networking/interface.c: code shrink
No binary (build failed)
—
(log yok)
| @@ -318,20 +318,27 @@ struct interface { | |
| char name[IFNAMSIZ]; /* interface name */ | |
| short type; /* if type */ | |
| short flags; /* various flags */ | |
| + | int tx_queue_len; /* transmit queue length */ |
| + | |
| + | /* these should be contiguous, zeroed in one go in if_fetch(): */ |
| + | #define FIRST_TO_ZERO metric |
| int metric; /* routing metric */ | |
| int mtu; /* MTU value */ | |
| - | int tx_queue_len; /* transmit queue length */ |
| struct ifmap map; /* hardware setup */ | |
| struct sockaddr addr; /* IP address */ | |
| struct sockaddr dstaddr; /* P-P IP address */ | |
| struct sockaddr broadaddr; /* IP broadcast address */ | |
| struct sockaddr netmask; /* IP network mask */ | |
| - | int has_ip; |
| char hwaddr[32]; /* HW address */ | |
| - | int statistics_valid; |
| + | #define LAST_TO_ZERO hwaddr |
| + | |
| + | smallint has_ip; |
| + | smallint statistics_valid; |
| struct user_net_device_stats stats; /* statistics */ | |
| + | #if 0 /* UNUSED */ |
| int keepalive; /* keepalive value for SLIP */ | |
| int outfill; /* outfill value for SLIP */ | |
| + | #endif |
| }; | |
| @@ -342,7 +349,7 @@ static struct interface *int_list, *int_last; | |
| #if 0 | |
| /* like strcmp(), but knows about numbers */ | |
| - | except that the freshly added calls to xatoul() brf on ethernet aliases with |
| + | except that the freshly added calls to xatoul() barf on ethernet aliases with |
| uClibc with e.g.: ife->name='lo' name='eth0:1' | |
| static int nstrcmp(const char *a, const char *b) | |
| { | |
| @@ -394,32 +401,31 @@ static struct interface *add_interface(char *name) | |
| return new; | |
| } | |
| - | static char *get_name(char *name, char *p) |
| + | static char *get_name(char name[IFNAMSIZ], char *p) |
| { | |
| - | /* Extract <name> from nul-terminated p where p matches |
| - | * <name>: after leading whitespace. |
| - | * If match is not made, set name empty and return unchanged p |
| + | /* Extract NAME from nul-terminated p of the form "<whitespace>NAME:" |
| + | * If match is not made, set NAME to "" and return unchanged p. |
| */ | |
| char *nameend; | |
| - | char *namestart = skip_whitespace(p); |
| + | char *namestart; |
| - | nameend = namestart; |
| - | while (*nameend && *nameend != ':' && !isspace(*nameend)) |
| - | nameend++; |
| - | if (*nameend == ':') { |
| - | if ((nameend - namestart) < IFNAMSIZ) { |
| + | nameend = namestart = skip_whitespace(p); |
| + | |
| + | for (;;) { |
| + | if ((nameend - namestart) >= IFNAMSIZ) |
| + | break; /* interface name too large - return "" */ |
| + | if (*nameend == ':') { |
| memcpy(name, namestart, nameend - namestart); | |
| name[nameend - namestart] = '\0'; | |
| - | p = nameend; |
| - | } else { |
| - | /* Interface name too large */ |
| - | name[0] = '\0'; |
| + | return nameend + 1; |
| } | |
| - | } else { |
| - | /* trailing ':' not found - return empty */ |
| - | name[0] = '\0'; |
| + | nameend++; |
| + | /* isspace, NUL, any control char? */ |
| + | if ((unsigned char)*nameend <= (unsigned char)' ') |
| + | break; /* trailing ':' not found - return "" */ |
| } | |
| - | return p + 1; |
| + | name[0] = '\0'; |
| + | return p; |
| } | |
| /* If scanf supports size qualifiers for %n conversions, then we can | |
| @@ -435,7 +441,10 @@ static char *get_name(char *name, char *p) | |
| /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ | |
| /* }; */ | |
| - | /* Lie about the size of the int pointed to for %n. */ |
| + | /* We use %n for unavailable data in older versions of /proc/net/dev formats. |
| + | * This results in bogus stores to ife->FOO members corresponding to |
| + | * %n specifiers (even the size of integers may not match). |
| + | */ |
| #if INT_MAX == LONG_MAX | |
| static const char *const ss_fmt[] = { | |
| "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", | |
| @@ -448,7 +457,6 @@ static const char *const ss_fmt[] = { | |
| "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", | |
| "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" | |
| }; | |
| - | |
| #endif | |
| static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | |
| @@ -456,22 +464,22 @@ static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | |
| memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); | |
| sscanf(bp, ss_fmt[procnetdev_vsn], | |
| - | &ife->stats.rx_bytes, /* missing for 0 */ |
| + | &ife->stats.rx_bytes, /* missing for v0 */ |
| &ife->stats.rx_packets, | |
| &ife->stats.rx_errors, | |
| &ife->stats.rx_dropped, | |
| &ife->stats.rx_fifo_errors, | |
| &ife->stats.rx_frame_errors, | |
| - | &ife->stats.rx_compressed, /* missing for <= 1 */ |
| - | &ife->stats.rx_multicast, /* missing for <= 1 */ |
| - | &ife->stats.tx_bytes, /* missing for 0 */ |
| + | &ife->stats.rx_compressed, /* missing for v0, v1 */ |
| + | &ife->stats.rx_multicast, /* missing for v0, v1 */ |
| + | &ife->stats.tx_bytes, /* missing for v0 */ |
| &ife->stats.tx_packets, | |
| &ife->stats.tx_errors, | |
| &ife->stats.tx_dropped, | |
| &ife->stats.tx_fifo_errors, | |
| &ife->stats.collisions, | |
| &ife->stats.tx_carrier_errors, | |
| - | &ife->stats.tx_compressed /* missing for <= 1 */ |
| + | &ife->stats.tx_compressed /* missing for v0, v1 */ |
| ); | |
| if (procnetdev_vsn <= 1) { | |
| @@ -499,24 +507,21 @@ static int if_readconf(void) | |
| int numreqs = 30; | |
| struct ifconf ifc; | |
| struct ifreq *ifr; | |
| - | int n, err = -1; |
| + | int n, err; |
| int skfd; | |
| ifc.ifc_buf = NULL; | |
| /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets | |
| (as of 2.1.128) */ | |
| - | skfd = socket(AF_INET, SOCK_DGRAM, 0); |
| - | if (skfd < 0) { |
| - | bb_perror_msg("error: no inet socket available"); |
| - | return -1; |
| - | } |
| + | skfd = xsocket(AF_INET, SOCK_DGRAM, 0); |
| for (;;) { | |
| ifc.ifc_len = sizeof(struct ifreq) * numreqs; | |
| ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); | |
| - | if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) { |
| + | err = ioctl_or_warn(skfd, SIOCGIFCONF, &ifc); |
| + | if (err < 0) { |
| goto out; | |
| } | |
| if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { | |
| @@ -565,7 +570,7 @@ static int if_readlist_proc(char *target) | |
| err = 0; | |
| while (fgets(buf, sizeof buf, fh)) { | |
| - | char *s, name[128]; |
| + | char *s, name[IFNAMSIZ]; |
| s = get_name(name, buf); | |
| ife = add_interface(name); | |
| @@ -574,11 +579,15 @@ static int if_readlist_proc(char *target) | |
| if (target && strcmp(target, name) == 0) | |
| break; | |
| } | |
| + | |
| + | #if 0 /* we trust kernel to not be buggy, /proc/net/dev reads never fail */ |
| if (ferror(fh)) { | |
| bb_perror_msg(_PATH_PROCNET_DEV); | |
| err = -1; | |
| proc_read = 0; | |
| } | |
| + | #endif |
| + | |
| fclose(fh); | |
| return err; | |
| } | |
| @@ -608,24 +617,29 @@ static int if_fetch(struct interface *ife) | |
| } | |
| ife->flags = ifr.ifr_flags; | |
| + | /* set up default values if ioctl's would fail */ |
| + | ife->tx_queue_len = -1; /* unknown value */ |
| + | memset(&ife->FIRST_TO_ZERO, 0, |
| + | offsetof(struct interface, LAST_TO_ZERO) |
| + | - offsetof(struct interface, FIRST_TO_ZERO) |
| + | + sizeof(ife->LAST_TO_ZERO) |
| + | ); |
| + | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | memset(ife->hwaddr, 0, 32); |
| if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) | |
| memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); | |
| + | //er.... why this _isnt_ inside if()? |
| ife->type = ifr.ifr_hwaddr.sa_family; | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | ife->metric = 0; |
| if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) | |
| ife->metric = ifr.ifr_metric; | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | ife->mtu = 0; |
| if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) | |
| ife->mtu = ifr.ifr_mtu; | |
| - | memset(&ife->map, 0, sizeof(struct ifmap)); |
| #ifdef SIOCGIFMAP | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) | |
| @@ -634,31 +648,24 @@ static int if_fetch(struct interface *ife) | |
| #ifdef HAVE_TXQUEUELEN | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | ife->tx_queue_len = -1; /* unknown value */ |
| if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) | |
| ife->tx_queue_len = ifr.ifr_qlen; | |
| - | #else |
| - | ife->tx_queue_len = -1; /* unknown value */ |
| #endif | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| ifr.ifr_addr.sa_family = AF_INET; | |
| - | memset(&ife->addr, 0, sizeof(struct sockaddr)); |
| if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { | |
| ife->has_ip = 1; | |
| ife->addr = ifr.ifr_addr; | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); |
| if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) | |
| ife->dstaddr = ifr.ifr_dstaddr; | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); |
| if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) | |
| ife->broadaddr = ifr.ifr_broadaddr; | |
| strncpy_IFNAMSIZ(ifr.ifr_name, ifname); | |
| - | memset(&ife->netmask, 0, sizeof(struct sockaddr)); |
| if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) | |
| ife->netmask = ifr.ifr_netmask; | |
| } | |
| @@ -1020,9 +1027,11 @@ static void ife_print(struct interface *ptr) | |
| /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ | |
| printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); | |
| + | #if 0 |
| #ifdef SIOCSKEEPALIVE | |
| if (ptr->outfill || ptr->keepalive) | |
| printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); | |
| + | #endif |
| #endif | |
| bb_putchar('\n'); | |
| @@ -1105,8 +1114,11 @@ static int for_all_interfaces(int (*doit) (struct interface *, void *), | |
| { | |
| struct interface *ife; | |
| - | if (!int_list && (if_readlist() < 0)) |
| - | return -1; |
| + | if (!int_list) { |
| + | int err = if_readlist(); |
| + | if (err < 0) |
| + | return err; |
| + | } |
| for (ife = int_list; ife; ife = ife->next) { | |
| int err = doit(ife, cookie); | |
| if (err) | |
| @@ -1124,8 +1136,11 @@ static int if_print(char *ifname) | |
| if (!ifname) { | |
| /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ | |
| - | if (!int_list && (if_readlist() < 0)) |
| - | return -1; |
| + | if (!int_list) { |
| + | int err = if_readlist(); |
| + | if (err < 0) |
| + | return err; |
| + | } |
| for (ife = int_list; ife; ife = ife->next) { | |
| int err = do_if_print(ife); /*, &interface_opt_a);*/ | |
| if (err) | |
| @@ -1140,6 +1155,15 @@ static int if_print(char *ifname) | |
| return res; | |
| } | |
| + | int FAST_FUNC display_interfaces(char *ifname) |
| + | { |
| + | int status; |
| + | |
| + | status = if_print(ifname); |
| + | |
| + | return (status < 0); /* status < 0 == 1 -- error */ |
| + | } |
| + | |
| #if ENABLE_FEATURE_HWIB | |
| /* Input an Infiniband address and convert to binary. */ | |
| int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) | |
| @@ -1153,12 +1177,3 @@ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) | |
| return 0; | |
| } | |
| #endif | |
| - | |
| - | int FAST_FUNC display_interfaces(char *ifname) |
| - | { |
| - | int status; |
| - | |
| - | status = if_print(ifname); |
| - | |
| - | return (status < 0); /* status < 0 == 1 -- error */ |
| - | } |