aboutsummaryrefslogtreecommitdiffstats
path: root/libbridge/libbridge_init.c
diff options
context:
space:
mode:
authorbuytenh <buytenh>2001-06-22 19:59:02 +0000
committerbuytenh <buytenh>2001-06-22 19:59:02 +0000
commit38837a8e19540690c80f5a3b0971e0e1495a4a3e (patch)
treec1136c0d3a50a9887a866c403c416e3f6efb1a07 /libbridge/libbridge_init.c
downloadandroid_external_brctl-38837a8e19540690c80f5a3b0971e0e1495a4a3e.tar.gz
android_external_brctl-38837a8e19540690c80f5a3b0971e0e1495a4a3e.tar.bz2
android_external_brctl-38837a8e19540690c80f5a3b0971e0e1495a4a3e.zip
Initial revision
Diffstat (limited to 'libbridge/libbridge_init.c')
-rw-r--r--libbridge/libbridge_init.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/libbridge/libbridge_init.c b/libbridge/libbridge_init.c
new file mode 100644
index 0000000..114a099
--- /dev/null
+++ b/libbridge/libbridge_init.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2000 Lennert Buytenhek
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include "libbridge.h"
+#include "libbridge_private.h"
+
+int br_socket_fd;
+struct bridge *bridge_list;
+
+static void __bridge_info_copy(struct bridge_info *info, struct __bridge_info *i)
+{
+ memcpy(&info->designated_root, &i->designated_root, 8);
+ memcpy(&info->bridge_id, &i->bridge_id, 8);
+ info->root_path_cost = i->root_path_cost;
+ info->topology_change = i->topology_change;
+ info->topology_change_detected = i->topology_change_detected;
+ info->root_port = i->root_port;
+ info->stp_enabled = i->stp_enabled;
+ __jiffies_to_tv(&info->max_age, i->max_age);
+ __jiffies_to_tv(&info->hello_time, i->hello_time);
+ __jiffies_to_tv(&info->forward_delay, i->forward_delay);
+ __jiffies_to_tv(&info->bridge_max_age, i->bridge_max_age);
+ __jiffies_to_tv(&info->bridge_hello_time, i->bridge_hello_time);
+ __jiffies_to_tv(&info->bridge_forward_delay, i->bridge_forward_delay);
+ __jiffies_to_tv(&info->ageing_time, i->ageing_time);
+ __jiffies_to_tv(&info->gc_interval, i->gc_interval);
+ __jiffies_to_tv(&info->hello_timer_value, i->hello_timer_value);
+ __jiffies_to_tv(&info->tcn_timer_value, i->tcn_timer_value);
+ __jiffies_to_tv(&info->topology_change_timer_value,
+ i->topology_change_timer_value);
+ __jiffies_to_tv(&info->gc_timer_value, i->gc_timer_value);
+}
+
+static void __port_info_copy(struct port_info *info, struct __port_info *i)
+{
+ memcpy(&info->designated_root, &i->designated_root, 8);
+ memcpy(&info->designated_bridge, &i->designated_bridge, 8);
+ info->port_id = i->port_id;
+ info->designated_port = i->designated_port;
+ info->path_cost = i->path_cost;
+ info->designated_cost = i->designated_cost;
+ info->state = i->state;
+ info->top_change_ack = i->top_change_ack;
+ info->config_pending = i->config_pending;
+ __jiffies_to_tv(&info->message_age_timer_value,
+ i->message_age_timer_value);
+ __jiffies_to_tv(&info->forward_delay_timer_value,
+ i->forward_delay_timer_value);
+ __jiffies_to_tv(&info->hold_timer_value,
+ i->hold_timer_value);
+}
+
+int br_read_info(struct bridge *br)
+{
+ struct __bridge_info i;
+
+ if (if_indextoname(br->ifindex, br->ifname) == NULL)
+ return 1;
+
+ if (br_device_ioctl(br, BRCTL_GET_BRIDGE_INFO,
+ (unsigned long)&i, 0, 0) < 0)
+ return 1;
+
+ __bridge_info_copy(&br->info, &i);
+ return 0;
+}
+
+int br_read_port_info(struct port *p)
+{
+ struct __port_info i;
+
+ if (br_device_ioctl(p->parent, BRCTL_GET_PORT_INFO,
+ (unsigned long)&i, p->index, 0) < 0)
+ return errno;
+
+ __port_info_copy(&p->info, &i);
+ return 0;
+}
+
+void br_nuke_bridge(struct bridge *b)
+{
+ struct port *p;
+
+ p = b->firstport;
+ while (p != NULL) {
+ struct port *pnext;
+
+ pnext = p->next;
+ free(p);
+ p = pnext;
+ }
+
+ free(b);
+}
+
+int br_make_port_list(struct bridge *br)
+{
+ int err;
+ int i;
+ int ifindices[256];
+
+ if (br_device_ioctl(br, BRCTL_GET_PORT_LIST, (unsigned long)ifindices,
+ 0, 0) < 0)
+ return errno;
+
+ for (i=255;i>=0;i--) {
+ struct port *p;
+
+ if (!ifindices[i])
+ continue;
+
+ p = malloc(sizeof(struct port));
+ p->index = i;
+ p->ifindex = ifindices[i];
+ p->parent = br;
+ br->ports[i] = p;
+ p->next = br->firstport;
+ br->firstport = p;
+ if ((err = br_read_port_info(p)) != 0)
+ goto error_out;
+ }
+
+ return 0;
+
+ error_out:
+ while (++i < 256)
+ free(br->ports[i]);
+
+ return err;
+}
+
+int br_make_bridge_list()
+{
+ int err;
+ int i;
+ int ifindices[32];
+ int num;
+
+ num = br_ioctl(BRCTL_GET_BRIDGES, (unsigned long)ifindices, 32);
+ if (num < 0)
+ return errno;
+
+ bridge_list = NULL;
+ for (i=0;i<num;i++) {
+ struct bridge *br;
+
+ br = malloc(sizeof(struct bridge));
+ memset(br, 0, sizeof(struct bridge));
+ br->ifindex = ifindices[i];
+ br->firstport = NULL;
+ br->next = bridge_list;
+ bridge_list = br;
+ if ((err = br_read_info(br)) != 0)
+ goto error_out;
+ if ((err = br_make_port_list(br)) != 0)
+ goto error_out;
+ }
+
+ return 0;
+
+ error_out:
+ while (bridge_list != NULL) {
+ struct bridge *nxt;
+
+ nxt = bridge_list->next;
+ br_nuke_bridge(bridge_list);
+ bridge_list = nxt;
+ }
+
+ return err;
+}
+
+int br_init()
+{
+ int err;
+
+ if ((br_socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return errno;
+
+ if (br_get_version() != BRCTL_VERSION)
+ return 12345;
+
+ if ((err = br_make_bridge_list()) != 0)
+ return err;
+
+ return 0;
+}
+
+int br_refresh()
+{
+ struct bridge *b;
+
+ b = bridge_list;
+ while (b != NULL) {
+ struct bridge *bnext;
+
+ bnext = b->next;
+ br_nuke_bridge(b);
+ b = bnext;
+ }
+
+ return br_make_bridge_list();
+}