diff options
author | shemminger <shemminger> | 2004-06-04 18:03:40 +0000 |
---|---|---|
committer | shemminger <shemminger> | 2004-06-04 18:03:40 +0000 |
commit | a7a262260da372c42850f7ce01a070275711c60d (patch) | |
tree | 80fc054fb772cdf309b90f0f0515a9e4e7387d61 | |
parent | 946695beaac41b6b50a5e641bbfd292f85e5a163 (diff) | |
download | android_external_brctl-a7a262260da372c42850f7ce01a070275711c60d.tar.gz android_external_brctl-a7a262260da372c42850f7ce01a070275711c60d.tar.bz2 android_external_brctl-a7a262260da372c42850f7ce01a070275711c60d.zip |
Get rid of all visible signs of port number and ifindex
from API, and display output.
Fix foreach_port for case when /sys is missing (but compiled for sysfs).
-rw-r--r-- | brctl/brctl_cmd.c | 22 | ||||
-rw-r--r-- | brctl/brctl_disp.c | 8 | ||||
-rw-r--r-- | libbridge/libbridge.h | 11 | ||||
-rw-r--r-- | libbridge/libbridge_devif.c | 172 | ||||
-rw-r--r-- | libbridge/libbridge_if.c | 50 | ||||
-rw-r--r-- | libbridge/libbridge_init.c | 64 |
6 files changed, 161 insertions, 166 deletions
diff --git a/brctl/brctl_cmd.c b/brctl/brctl_cmd.c index f9da974..9ab7166 100644 --- a/brctl/brctl_cmd.c +++ b/brctl/brctl_cmd.c @@ -82,16 +82,13 @@ static int br_cmd_delbr(char** argv) static int br_cmd_addif(char** argv) { int err; - int ifindex = if_nametoindex(argv[2]); - if (!ifindex) { - fprintf(stderr, "interface %s does not exist!\n", argv[2]); - return 1; - } - - switch (err = br_add_interface(argv[1], ifindex)) { + switch (err = br_add_interface(argv[1], argv[2])) { case 0: return 0; + case ENODEV: + fprintf(stderr, "interface %s does not exist!\n", argv[2]); + return 1; case EBUSY: fprintf(stderr, "device %s is already a member of a bridge; " @@ -115,16 +112,13 @@ static int br_cmd_addif(char** argv) static int br_cmd_delif(char** argv) { int err; - int ifindex = if_nametoindex(argv[2]); - if (!ifindex) { - fprintf(stderr, "interface %s does not exist!\n", argv[2]); - return 1; - } - - switch (err = br_del_interface(argv[1], ifindex)) { + switch (err = br_del_interface(argv[1], argv[2])) { case 0: return 0; + case ENODEV: + fprintf(stderr, "interface %s does not exist!\n", argv[2]); + return 1; case EINVAL: fprintf(stderr, "device %s is not a slave of %s\n", diff --git a/brctl/brctl_disp.c b/brctl/brctl_disp.c index a1f4aa3..acdc687 100644 --- a/brctl/brctl_disp.c +++ b/brctl/brctl_disp.c @@ -37,7 +37,7 @@ void br_show_timer(const struct timeval *tv) static int first; -static int dump_interface(const char *b, const char *p, int ind, void *arg) +static int dump_interface(const char *b, const char *p, void *arg) { if (first) @@ -62,12 +62,12 @@ void br_dump_interface_list(const char *br) printf("\n"); } -static int dump_port_info(const char *br, const char *p, int count, void *arg) +static int dump_port_info(const char *br, const char *p, void *arg) { struct port_info pinfo; - printf("%s (%i)", p, count); - if (br_get_port_info(br, p, count, &pinfo)) { + printf("%s", p); + if (br_get_port_info(br, p, &pinfo)) { printf("\tcan't get port info\n"); return 1; } diff --git a/libbridge/libbridge.h b/libbridge/libbridge.h index 1be50b0..a8ff2c2 100644 --- a/libbridge/libbridge.h +++ b/libbridge/libbridge.h @@ -82,19 +82,18 @@ extern void br_shutdown(void); extern int br_foreach_bridge(int (*iterator)(const char *brname, void *), void *arg); extern int br_foreach_port(const char *brname, - int (*iterator)(const char *brname, - const char *port, int ifindex, - void *), + int (*iterator)(const char *brname, const char *port, + void *arg ), void *arg); extern const char *br_get_state_name(int state); extern int br_get_bridge_info(const char *br, struct bridge_info *info); -extern int br_get_port_info(const char *brname, const char *port, int count, +extern int br_get_port_info(const char *brname, const char *port, struct port_info *info); extern int br_add_bridge(const char *brname); extern int br_del_bridge(const char *brname); -extern int br_add_interface(const char *br, int ifindex); -extern int br_del_interface(const char *br, int ifindex); +extern int br_add_interface(const char *br, const char *dev); +extern int br_del_interface(const char *br, const char *dev); extern int br_set_bridge_forward_delay(const char *br, struct timeval *tv); extern int br_set_bridge_hello_time(const char *br, struct timeval *tv); extern int br_set_bridge_max_age(const char *br, struct timeval *tv); diff --git a/libbridge/libbridge_devif.c b/libbridge/libbridge_devif.c index 018f9ce..0ca355d 100644 --- a/libbridge/libbridge_devif.c +++ b/libbridge/libbridge_devif.c @@ -70,16 +70,13 @@ static void fetch_id(struct sysfs_directory *sdir, const char *name, memset(id, 0, sizeof(id)); attr = sysfs_get_directory_attribute(sdir, (char *) name); - dprintf("fetch_id %s/%s = %s\n", sdir->path, name, - attr ? attr->value : "<null>\n"); - if (!attr) { - fprintf(stderr, "Can't find attribute %s/%s\n", sdir->path, name); + dprintf("Can't find attribute %s/%s\n", sdir->path, name); return; } if (strlen(attr->value) < 17) - fprintf(stderr, "Bad format for %s: '%s'\n", name, attr->value); + dprintf("Bad format for %s: '%s'\n", name, attr->value); else { const char *cp = attr->value; id->prio[0] = getoctet(cp); cp += 2; @@ -101,7 +98,7 @@ static void fetch_tv(struct sysfs_directory *sdir, const char *name, = sysfs_get_directory_attribute(sdir, (char *) name); if (!attr) { - fprintf(stderr, "Can't find attribute %s/%s\n", sdir->path, name); + dprintf("Can't find attribute %s/%s\n", sdir->path, name); memset(tv, 0, sizeof(tv)); return; } @@ -117,13 +114,51 @@ static int fetch_int(struct sysfs_directory *sdir, const char *name) int val = 0; if (!attr) - fprintf(stderr, "Can't find attribute %s/%s\n", sdir->path, name); + dprintf("Can't find attribute %s/%s\n", sdir->path, name); else val = strtol(attr->value, NULL, 0); return val; } #endif +/* + * Convert device name to an index in the list of ports in bridge. + * + * Old API does bridge operations as if ports were an array + * inside bridge structure. + */ +static int get_portno(const char *brname, const char *ifname) +{ + int i; + int ifindex = if_nametoindex(ifname); + int ifindices[MAX_PORTS]; + unsigned long args[4] = { BRCTL_GET_PORT_LIST, + (unsigned long)ifindices, MAX_PORTS, 0 }; + struct ifreq ifr; + + if (ifindex <= 0) + goto error; + + memset(ifindices, 0, sizeof(ifindices)); + strncpy(ifr.ifr_name, brname, IFNAMSIZ); + ifr.ifr_data = (char *) &args; + + if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) { + dprintf("get_portno: get ports of %s failed: %s\n", + brname, strerror(errno)); + goto error; + } + + for (i = 0; i < MAX_PORTS; i++) { + if (ifindices[i] == ifindex) + return i; + } + + dprintf("%s is not a in bridge %s\n", ifname, brname); + error: + return -1; +} + /* get information via ioctl */ static int old_get_bridge_info(const char *bridge, struct bridge_info *info) { @@ -207,22 +242,31 @@ int br_get_bridge_info(const char *bridge, struct bridge_info *info) #endif } -static int old_get_port_info(const char *brname, int index, +static int old_get_port_info(const char *brname, const char *port, struct port_info *info) { struct __port_info i; - struct ifreq ifr; - unsigned long args[4] = { BRCTL_GET_PORT_INFO, - (unsigned long) &i, index, 0 }; + int index; memset(info, 0, sizeof(*info)); - strncpy(ifr.ifr_name, brname, IFNAMSIZ); - ifr.ifr_data = (char *) &args; - if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) { - dprintf("old can't get port %s(%d) info %s\n", - brname, index, strerror(errno)); + index = get_portno(brname, port); + if (index < 0) return errno; + + else { + struct ifreq ifr; + unsigned long args[4] = { BRCTL_GET_PORT_INFO, + (unsigned long) &i, index, 0 }; + + strncpy(ifr.ifr_name, brname, IFNAMSIZ); + ifr.ifr_data = (char *) &args; + + if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) { + dprintf("old can't get port %s(%d) info %s\n", + brname, index, strerror(errno)); + return errno; + } } memcpy(&info->designated_root, &i.designated_root, 8); @@ -245,16 +289,17 @@ static int old_get_port_info(const char *brname, int index, /* * Get information about port on bridge. */ -int br_get_port_info(const char *brname, const char *port, int index, +int br_get_port_info(const char *brname, const char *port, struct port_info *info) { #ifndef HAVE_LIBSYSFS - return old_get_port_info(brname, index, info); + return old_get_port_info(brname, port, info); #else struct sysfs_directory *sdir = bridge_sysfs_directory(port, SYSFS_BRIDGE_PORT_ATTR); + if (!sdir) - return old_get_port_info(brname, index, info); + return old_get_port_info(brname, port, info); memset(info, 0, sizeof(*info)); fetch_id(sdir, "designated_root", &info->designated_root); @@ -278,47 +323,6 @@ int br_get_port_info(const char *brname, const char *port, int index, #endif } -int br_add_interface(const char *bridge, int ifindex) -{ - struct ifreq ifr; - int err; - - strncpy(ifr.ifr_name, bridge, IFNAMSIZ); -#ifdef SIOCBRADDIF - ifr.ifr_ifindex = ifindex; - err = ioctl(br_socket_fd, SIOCBRADDIF, &ifr); - if (err < 0) -#endif - { - unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 }; - - ifr.ifr_data = (char *) args; - err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); - } - - return err < 0 ? errno : 0; -} - -int br_del_interface(const char *bridge, int ifindex) -{ - struct ifreq ifr; - int err; - - strncpy(ifr.ifr_name, bridge, IFNAMSIZ); -#ifdef SIOCBRDELIF - ifr.ifr_ifindex = ifindex; - err = ioctl(br_socket_fd, SIOCBRDELIF, &ifr); - if (err < 0) -#endif - { - unsigned long args[4] = { BRCTL_DEL_IF, ifindex, 0, 0 }; - - ifr.ifr_data = (char *) args; - err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); - } - - return err < 0 ? errno : 0; -} static int br_set(const char *bridge, const char *name, unsigned long value, unsigned long oldcode) @@ -390,45 +394,6 @@ int br_set_bridge_priority(const char *br, int bridge_priority) BRCTL_SET_BRIDGE_PRIORITY); } -/* sigh.. if_nametoindex busted on older glibc and uclibc */ -static inline unsigned int ifnametoindex(const char* ifname) -{ - struct ifreq ifr; - - strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - - return (ioctl(br_socket_fd, SIOCGIFINDEX,&ifr) < 0) ? 0 : ifr.ifr_ifindex; -} - -static int nametoportindex(const char *brname, const char *ifname) -{ - int i; - int ifindex = ifnametoindex(ifname); - int ifindices[MAX_PORTS]; - unsigned long args[4] = { BRCTL_GET_PORT_LIST, - (unsigned long)ifindices, MAX_PORTS, 0 }; - struct ifreq ifr; - - if (ifindex <= 0) - goto error; - - memset(ifindices, 0, sizeof(ifindices)); - strncpy(ifr.ifr_name, brname, IFNAMSIZ); - ifr.ifr_data = (char *) &args; - - if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) - goto error; - - for (i = 0; i < MAX_PORTS; i++) { - if (ifindices[i] == ifindex) - return i; - } - - dprintf("%s is not a in bridge %s\n", ifname, brname); - error: - return -1; -} - static int port_set(const char *bridge, const char *ifname, const char *name, unsigned long value, unsigned long oldcode) @@ -454,7 +419,7 @@ static int port_set(const char *bridge, const char *ifname, sysfs_close_directory(sdir); } else #endif - if ( (index = nametoportindex(bridge, ifname)) < 0) + if ( (index = get_portno(bridge, ifname)) < 0) ret = index; else { @@ -527,9 +492,12 @@ int br_read_fdb(const char *bridge, struct fdb_entry *fdbs, retry: n = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); - sleep(0); - if (n < 0 && errno == EAGAIN && ++retries < 10) + + /* table can change during ioctl processing */ + if (n < 0 && errno == EAGAIN && ++retries < 10) { + sleep(0); goto retry; + } } for (i = 0; i < n; i++) diff --git a/libbridge/libbridge_if.c b/libbridge/libbridge_if.c index 5a31f0e..77d3f8a 100644 --- a/libbridge/libbridge_if.c +++ b/libbridge/libbridge_if.c @@ -65,3 +65,53 @@ int br_del_bridge(const char *brname) } return ret < 0 ? errno : 0; } + +int br_add_interface(const char *bridge, const char *dev) +{ + struct ifreq ifr; + int err; + int ifindex = if_nametoindex(dev); + + if (ifindex == 0) + return ENODEV; + + strncpy(ifr.ifr_name, bridge, IFNAMSIZ); +#ifdef SIOCBRADDIF + ifr.ifr_ifindex = ifindex; + err = ioctl(br_socket_fd, SIOCBRADDIF, &ifr); + if (err < 0) +#endif + { + unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 }; + + ifr.ifr_data = (char *) args; + err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); + } + + return err < 0 ? errno : 0; +} + +int br_del_interface(const char *bridge, const char *dev) +{ + struct ifreq ifr; + int err; + int ifindex = if_nametoindex(dev); + + if (ifindex == 0) + return ENODEV; + + strncpy(ifr.ifr_name, bridge, IFNAMSIZ); +#ifdef SIOCBRDELIF + ifr.ifr_ifindex = ifindex; + err = ioctl(br_socket_fd, SIOCBRDELIF, &ifr); + if (err < 0) +#endif + { + unsigned long args[4] = { BRCTL_DEL_IF, ifindex, 0, 0 }; + + ifr.ifr_data = (char *) args; + err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); + } + + return err < 0 ? errno : 0; +} diff --git a/libbridge/libbridge_init.c b/libbridge/libbridge_init.c index 3abcb18..b194705 100644 --- a/libbridge/libbridge_init.c +++ b/libbridge/libbridge_init.c @@ -82,7 +82,7 @@ static int new_foreach_bridge(int (*iterator)(const char *name, void *), devlist = sysfs_get_class_devices(br_class_net); if (!devlist) { - fprintf(stderr, "Can't read devices from sysfs\n"); + dprintf("Can't read devices from sysfs\n"); return -errno; } @@ -98,18 +98,6 @@ static int new_foreach_bridge(int (*iterator)(const char *name, void *), } #endif -/* once again, if_indextoname busted on older glibc and uclibc */ -static inline char * ifindextoname (unsigned int ifindex, char *ifname) -{ - struct ifreq ifr; - - ifr.ifr_ifindex = ifindex; - if ( ioctl(br_socket_fd, SIOCGIFNAME, &ifr) < 0) - return NULL; - - return strncpy(ifname, ifr.ifr_name, IFNAMSIZ); -} - /* * Old interface uses ioctl */ @@ -124,14 +112,14 @@ static int old_foreach_bridge(int (*iterator)(const char *, void *), num = ioctl(br_socket_fd, SIOCGIFBR, args); if (num < 0) { - fprintf(stderr, "Get bridge indices failed: %s\n", + dprintf("Get bridge indices failed: %s\n", strerror(errno)); return -errno; } for (i = 0; i < num; i++) { - if (!ifindextoname(ifindices[i], ifname)) { - fprintf(stderr, "get find name for ifindex %d\n", + if (!if_indextoname(ifindices[i], ifname)) { + dprintf("get find name for ifindex %d\n", ifindices[i]); return -errno; } @@ -167,11 +155,10 @@ int br_foreach_bridge(int (*iterator)(const char *, void *), /* * Only used if sysfs is not available. */ -static int old_foreach_port(const char *brname, - int (*iterator)(const char *br, - const char *port, int ind, - void *arg), - void *arg) +static int old_foreach_port(const char *brname, + int (*iterator)(const char *br, const char *port, + void *arg), + void *arg) { int i, err, count; struct ifreq ifr; @@ -186,7 +173,7 @@ static int old_foreach_port(const char *brname, err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); if (err < 0) { - fprintf(stderr, "list ports for bridge:'%s' failed: %s\n", + dprintf("list ports for bridge:'%s' failed: %s\n", brname, strerror(errno)); return -errno; } @@ -195,33 +182,29 @@ static int old_foreach_port(const char *brname, for (i = 0; i < MAX_PORTS; i++) { if (!ifindices[i]) continue; - if (!ifindextoname(ifindices[i], ifname)) { - fprintf(stderr, "can't find name for ifindex:%d\n", + + if (!if_indextoname(ifindices[i], ifname)) { + dprintf("can't find name for ifindex:%d\n", ifindices[i]); continue; } ++count; - if (iterator(brname, ifname, i, arg)) + if (iterator(brname, ifname, arg)) break; } return count; } - - /* * Iterate over all ports in bridge (using sysfs). */ int br_foreach_port(const char *brname, - int (*iterator)(const char *br, const char *port, - int ind, void *arg), + int (*iterator)(const char *br, const char *port, void *arg), void *arg) { -#ifndef HAVE_LIBSYSFS - return old_foreach_port(brname, iterator, arg); -#else +#ifdef HAVE_LIBSYSFS struct sysfs_class_device *dev; struct sysfs_directory *dir; struct sysfs_link *plink; @@ -231,7 +214,7 @@ int br_foreach_port(const char *brname, if (!br_class_net || !(dev = sysfs_get_class_device(br_class_net, (char *) brname))) - return -ENODEV; + goto old; snprintf(path, sizeof(path), "%s/%s", dev->path, SYSFS_BRIDGE_PORT_SUBDIR); @@ -242,26 +225,27 @@ int br_foreach_port(const char *brname, /* no /sys/class/net/ethX/brif subdirectory * either: old kernel, or not really a bridge */ - err = old_foreach_port(brname, iterator, arg); - goto out1; + goto old; } links = sysfs_get_dir_links(dir); if (!links) { err = -ENOSYS; - goto out2; + goto out; } err = 0; dlist_for_each_data(links, plink, struct sysfs_link) { ++err; - if (iterator(brname, plink->name, err, arg)) + if (iterator(brname, plink->name, arg)) break; - } - out2: + out: sysfs_close_directory(dir); - out1: return err; + + old: #endif + return old_foreach_port(brname, iterator, arg); + } |