diff options
Diffstat (limited to 'libbridge/libbridge_init.c')
-rw-r--r-- | libbridge/libbridge_init.c | 139 |
1 files changed, 116 insertions, 23 deletions
diff --git a/libbridge/libbridge_init.c b/libbridge/libbridge_init.c index eb5399c..d401250 100644 --- a/libbridge/libbridge_init.c +++ b/libbridge/libbridge_init.c @@ -32,6 +32,79 @@ int br_socket_fd; struct bridge *bridge_list; +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); + 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->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); +} + + +int br_get_bridge_info(const struct bridge *br, struct bridge_info *info) +{ + struct __bridge_info i; + + if (br_device_ioctl(br, BRCTL_GET_BRIDGE_INFO, + (unsigned long )&i, 0, 0) < 0) { + return errno; + } + + __bridge_info_copy(info, &i); + return 0; +} + +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); + 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_get_port_info(const struct port *p, struct port_info *info) +{ + struct __port_info i; + + if (br_device_ioctl(p->parent, BRCTL_GET_PORT_INFO, + (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(info, &i); + + return 0; +} + static void br_nuke_bridge(struct bridge *b) { struct port *p, *n; @@ -46,26 +119,31 @@ static void br_nuke_bridge(struct bridge *b) static int br_make_port_list(struct bridge *br) { - int err; - int i; - int ifindices[MAX_PORTS]; + int i, cnt; struct port *p, **top; + int *ifindices; + + ifindices = calloc(MAX_PORTS, sizeof(int)); + if (!ifindices) + return -ENOMEM; - memset(ifindices, 0, sizeof(ifindices)); - if (br_device_ioctl(br, BRCTL_GET_PORT_LIST, (unsigned long)ifindices, - MAX_PORTS, 0) < 0) + cnt = br_device_ioctl(br, BRCTL_GET_PORT_LIST, + (unsigned long)ifindices, + MAX_PORTS, 0); + if (cnt < 0) return errno; + if (cnt == 0) + cnt = 256; /* old 2.4 compatiablity */ + top = &br->firstport; - for (i = 0; i < MAX_PORTS; i++) { + for (i = 0; i < cnt; i++) { if (!ifindices[i]) continue; p = malloc(sizeof(struct port)); - if (!p) { - err = -ENOMEM; - goto error_out; - } + if (!p) + goto nomem; p->next = NULL; p->ifindex = ifindices[i]; @@ -75,9 +153,10 @@ static int br_make_port_list(struct bridge *br) top = &p->next; } + free(ifindices); return 0; - error_out: + nomem: p = br->firstport; while (p) { struct port *n = p->next; @@ -85,14 +164,31 @@ static int br_make_port_list(struct bridge *br) p = n; } br->firstport = NULL; + free(ifindices); + + return -ENOMEM; +} + +static struct bridge *new_bridge(int ifindex, const char *name) +{ + struct bridge *br; - return err; + br = malloc(sizeof(struct bridge)); + if (br) { + memset(br, 0, sizeof(struct bridge)); + br->ifindex = ifindex; + strncpy(br->ifname, name, IFNAMSIZ); + br->firstport = NULL; + } + return br; } static int br_make_bridge_list(void) { + struct bridge *br; int i, num; int ifindices[MAX_BRIDGES]; + char ifname[IFNAMSIZ]; num = br_get_br(BRCTL_GET_BRIDGES, (unsigned long)ifindices, MAX_BRIDGES); @@ -101,19 +197,16 @@ static int br_make_bridge_list(void) strerror(errno)); return errno; } - bridge_list = NULL; - for (i = 0;i < num; i++) { - struct bridge *br; - br = malloc(sizeof(struct bridge)); - if (!br) - return -ENOMEM; + bridge_list = NULL; + for (i = 0; i < num; i++) { + if (!if_indextoname(ifindices[i], ifname)) + continue; + br = new_bridge(ifindices[i], ifname); + if (!br) /* ignore the problem could just be a race! */ + continue; - memset(br, 0, sizeof(struct bridge)); - br->ifindex = ifindices[i]; - br->firstport = NULL; if ( br_make_port_list(br)) { - /* ignore the problem could just be a race! */ free(br); continue; } |