From 8a5299fcfd54ae3b895b66249d6d105e956192cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Mar 2018 16:56:16 +0100 Subject: [PATCH] networking/interface.c: code shrink function old new delta ife_print 1293 1296 +3 display_interfaces 145 146 +1 if_readconf 162 141 -21 if_readlist_proc 631 560 -71 do_if_fetch 753 643 -110 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/3 up/down: 4/-202) Total: -198 bytes Signed-off-by: Denys Vlasenko --- networking/interface.c | 137 +++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 61 deletions(-) diff --git a/networking/interface.c b/networking/interface.c index 89427f2f4..0bbef9879 100644 --- a/networking/interface.c +++ b/networking/interface.c @@ -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 from nul-terminated p where p matches - * : after leading whitespace. - * If match is not made, set name empty and return unchanged p + /* Extract NAME from nul-terminated p of the form "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 */ -}