aboutsummaryrefslogtreecommitdiffstats
path: root/libbridge/libbridge_init.c
diff options
context:
space:
mode:
authorshemminger <shemminger>2004-04-01 22:01:19 +0000
committershemminger <shemminger>2004-04-01 22:01:19 +0000
commitd7d9d2f105ea6e8ccca2ac163582eb7a4e0bd2ae (patch)
tree8f805860becc061f69d11b27887bf21725425914 /libbridge/libbridge_init.c
parent294ee034008c7db57053ebdd4be11cc81c4e511b (diff)
downloadandroid_external_brctl-d7d9d2f105ea6e8ccca2ac163582eb7a4e0bd2ae.tar.gz
android_external_brctl-d7d9d2f105ea6e8ccca2ac163582eb7a4e0bd2ae.tar.bz2
android_external_brctl-d7d9d2f105ea6e8ccca2ac163582eb7a4e0bd2ae.zip
Fixes for 0.9.7
- error checking - handle upto 1000's of bridges - -V version - don't initialize bridge till have to.
Diffstat (limited to 'libbridge/libbridge_init.c')
-rw-r--r--libbridge/libbridge_init.c104
1 files changed, 65 insertions, 39 deletions
diff --git a/libbridge/libbridge_init.c b/libbridge/libbridge_init.c
index e7bb918..e027457 100644
--- a/libbridge/libbridge_init.c
+++ b/libbridge/libbridge_init.c
@@ -26,10 +26,14 @@
#include "libbridge.h"
#include "libbridge_private.h"
+#define MAX_BRIDGES 1024 /* arbitrary */
+#define MAX_PORTS 256 /* STP limitation */
+
int br_socket_fd;
struct bridge *bridge_list;
-static void __bridge_info_copy(struct bridge_info *info, struct __bridge_info *i)
+static void __bridge_info_copy(struct bridge_info *info,
+ const struct __bridge_info *i)
{
memcpy(&info->designated_root, &i->designated_root, 8);
memcpy(&info->bridge_id, &i->bridge_id, 8);
@@ -53,7 +57,8 @@ static void __bridge_info_copy(struct bridge_info *info, struct __bridge_info *i
__jiffies_to_tv(&info->gc_timer_value, i->gc_timer_value);
}
-static void __port_info_copy(struct port_info *info, struct __port_info *i)
+static void __port_info_copy(struct port_info *info,
+ const struct __port_info *i)
{
memcpy(&info->designated_root, &i->designated_root, 8);
memcpy(&info->designated_bridge, &i->designated_bridge, 8);
@@ -77,12 +82,16 @@ static int br_read_info(struct bridge *br)
struct __bridge_info i;
if (if_indextoname(br->ifindex, br->ifname) == NULL) {
- return ENODEV;
+ /* index was there, but now it is gone! */
+ return -1;
}
if (br_device_ioctl(br, BRCTL_GET_BRIDGE_INFO,
- (unsigned long)&i, 0, 0) < 0)
+ (unsigned long)&i, 0, 0) < 0) {
+ fprintf(stderr, "%s: can't get info %s\n",
+ br->ifname, strerror(errno));
return errno;
+ }
__bridge_info_copy(&br->info, &i);
return 0;
@@ -93,52 +102,58 @@ static 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)
+ (unsigned long)&i, p->index, 0) < 0) {
+ fprintf(stderr, "%s: can't get port %d info %s\n",
+ p->parent->ifname, p->index, strerror(errno));
return errno;
+ }
__port_info_copy(&p->info, &i);
return 0;
}
-void br_nuke_bridge(struct bridge *b)
+static void br_nuke_bridge(struct bridge *b)
{
- struct port *p;
+ struct port *p, *n;
- p = b->firstport;
- while (p != NULL) {
- struct port *pnext;
-
- pnext = p->next;
+ for (p = b->firstport; p; p = n) {
+ n = p->next;
free(p);
- p = pnext;
}
free(b);
}
-int br_make_port_list(struct bridge *br)
+static int br_make_port_list(struct bridge *br)
{
int err;
int i;
- int ifindices[256];
+ int ifindices[MAX_PORTS];
+ struct port *p, **top;
+ memset(ifindices, 0, sizeof(ifindices));
if (br_device_ioctl(br, BRCTL_GET_PORT_LIST, (unsigned long)ifindices,
- 0, 0) < 0)
+ MAX_PORTS, 0) < 0)
return errno;
- for (i=255;i>=0;i--) {
- struct port *p;
-
+ top = &br->firstport;
+ for (i = 0; i < MAX_PORTS; i++) {
if (!ifindices[i])
continue;
p = malloc(sizeof(struct port));
- p->index = i;
+ if (!p) {
+ err = -ENOMEM;
+ goto error_out;
+ }
+
+ p->next = NULL;
p->ifindex = ifindices[i];
p->parent = br;
- br->ports[i] = p;
- p->next = br->firstport;
- br->firstport = p;
+ p->index = i;
+ *top = p;
+ top = &p->next;
+
if ((err = br_read_port_info(p)) != 0)
goto error_out;
}
@@ -146,36 +161,46 @@ int br_make_port_list(struct bridge *br)
return 0;
error_out:
- while (++i < 256)
- free(br->ports[i]);
+ p = br->firstport;
+ while (p) {
+ struct port *n = p->next;
+ free(p);
+ p = n;
+ }
+ br->firstport = NULL;
return err;
}
-int br_make_bridge_list()
+static int br_make_bridge_list(void)
{
- int i;
- int ifindices[32];
- int num;
-
- num = br_ioctl(BRCTL_GET_BRIDGES, (unsigned long)ifindices, 32);
- if (num < 0)
+ int i, num;
+ int ifindices[MAX_BRIDGES];
+
+ num = br_get_br(BRCTL_GET_BRIDGES, (unsigned long)ifindices,
+ MAX_BRIDGES);
+ if (num < 0) {
+ fprintf(stderr, "Get bridge indices failed: %s\n",
+ strerror(errno));
return errno;
-
+ }
bridge_list = NULL;
- for (i=0;i<num;i++) {
+ for (i = 0;i < num; i++) {
struct bridge *br;
br = malloc(sizeof(struct bridge));
+ if (!br)
+ return -ENOMEM;
+
memset(br, 0, sizeof(struct bridge));
br->ifindex = ifindices[i];
br->firstport = NULL;
- if ( br_read_info(br) != 0 ||
- br_make_port_list(br) != 0) {
+ if ( br_read_info(br) || br_make_port_list(br)) {
/* ignore the problem could just be a race! */
free(br);
continue;
}
+
br->next = bridge_list;
bridge_list = br;
}
@@ -190,8 +215,10 @@ int br_init()
if ((br_socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return errno;
- if (br_get_version() != BRCTL_VERSION)
- return 12345;
+ if (br_get_version() != BRCTL_VERSION) {
+ fprintf(stderr, "bridge utilities not compatiable with kernel version\n");
+ exit(1);
+ }
if ((err = br_make_bridge_list()) != 0)
return err;
@@ -211,7 +238,6 @@ int br_refresh()
br_nuke_bridge(b);
b = bnext;
}
- bridge_list = NULL;
return br_make_bridge_list();
}