diff options
Diffstat (limited to 'libbb/interface.c')
-rw-r--r-- | libbb/interface.c | 283 |
1 files changed, 154 insertions, 129 deletions
diff --git a/libbb/interface.c b/libbb/interface.c index 47358fe..394ba5f 100644 --- a/libbb/interface.c +++ b/libbb/interface.c @@ -15,7 +15,7 @@ * that either displays or sets the characteristics of * one or more of the system's networking interfaces. * - * Version: $Id: interface.c,v 1.18 2003/07/28 06:35:32 andersen Exp $ + * Version: $Id: interface.c,v 1.19 2003/08/02 00:04:18 mjn3 Exp $ * * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * and others. Copyright 1993 MicroWalt Corporation @@ -87,8 +87,6 @@ #define new(p) ((p) = xcalloc(1,sizeof(*(p)))) #define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch)) -static int procnetdev_vsn = 1; - #ifdef HAVE_HWSLIP #include <net/if_slip.h> #endif @@ -1021,71 +1019,76 @@ static char *get_name(char *name, char *p) return p; } -static int get_dev_fields(char *bp, struct interface *ife) +/* If scanf supports size qualifiers for %n conversions, then we can + * use a modified fmt that simply stores the position in the fields + * having no associated fields in the proc string. Of course, we need + * to zero them again when we're done. But that is smaller than the + * old approach of multiple scanf occurrences with large numbers of + * args. */ + +/* static const char *ss_fmt[] = { */ +/* "%Ln%Lu%lu%lu%lu%lu%ln%ln%Ln%Lu%lu%lu%lu%lu%lu", */ +/* "%Lu%Lu%lu%lu%lu%lu%ln%ln%Lu%Lu%lu%lu%lu%lu%lu", */ +/* "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu" */ +/* }; */ + + /* Lie about the size of the int pointed to for %n. */ +#if INT_MAX == LONG_MAX +static const char *ss_fmt[] = { + "%n%Lu%u%u%u%u%n%n%n%Lu%u%u%u%u%u", + "%Lu%Lu%u%u%u%u%n%n%Lu%Lu%u%u%u%u%u", + "%Lu%Lu%u%u%u%u%u%u%Lu%Lu%u%u%u%u%u%u" +}; +#else +static const char *ss_fmt[] = { + "%n%Lu%lu%lu%lu%lu%n%n%n%Lu%lu%lu%lu%lu%lu", + "%Lu%Lu%lu%lu%lu%lu%n%n%Lu%Lu%lu%lu%lu%lu%lu", + "%Lu%Lu%lu%lu%lu%lu%lu%lu%Lu%Lu%lu%lu%lu%lu%lu%lu" +}; + +#endif + +static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) { - switch (procnetdev_vsn) { - case 3: - sscanf(bp, - "%Lu %Lu %lu %lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu %lu", - &ife->stats.rx_bytes, - &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, - &ife->stats.rx_multicast, - &ife->stats.tx_bytes, - &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); - break; - case 2: - sscanf(bp, "%Lu %Lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu", - &ife->stats.rx_bytes, - &ife->stats.rx_packets, - &ife->stats.rx_errors, - &ife->stats.rx_dropped, - &ife->stats.rx_fifo_errors, - &ife->stats.rx_frame_errors, - &ife->stats.tx_bytes, - &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.rx_multicast = 0; - break; - case 1: - sscanf(bp, "%Lu %lu %lu %lu %lu %Lu %lu %lu %lu %lu %lu", - &ife->stats.rx_packets, - &ife->stats.rx_errors, - &ife->stats.rx_dropped, - &ife->stats.rx_fifo_errors, - &ife->stats.rx_frame_errors, - &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.rx_bytes = 0; - ife->stats.tx_bytes = 0; + 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_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.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 */ + ); + + if (procnetdev_vsn <= 1) { + if (procnetdev_vsn == 0) { + ife->stats.rx_bytes = 0; + ife->stats.tx_bytes = 0; + } ife->stats.rx_multicast = 0; - break; + ife->stats.rx_compressed = 0; + ife->stats.tx_compressed = 0; } - return 0; } static inline int procnetdev_version(char *buf) { if (strstr(buf, "compressed")) - return 3; - if (strstr(buf, "bytes")) return 2; - return 1; + if (strstr(buf, "bytes")) + return 1; + return 0; } static int if_readlist_proc(char *target) @@ -1094,7 +1097,7 @@ static int if_readlist_proc(char *target) FILE *fh; char buf[512]; struct interface *ife; - int err; + int err, procnetdev_vsn; if (proc_read) return 0; @@ -1109,28 +1112,7 @@ static int if_readlist_proc(char *target) fgets(buf, sizeof buf, fh); /* eat line */ fgets(buf, sizeof buf, fh); -#if 0 /* pretty, but can't cope with missing fields */ - fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh, "face", "", /* parsed separately */ - "bytes", "%lu", - "packets", "%lu", - "errs", "%lu", - "drop", "%lu", - "fifo", "%lu", - "frame", "%lu", - "compressed", "%lu", - "multicast", "%lu", - "bytes", "%lu", - "packets", "%lu", - "errs", "%lu", - "drop", "%lu", - "fifo", "%lu", - "colls", "%lu", - "carrier", "%lu", "compressed", "%lu", NULL); - if (!fmt) - return -1; -#else procnetdev_vsn = procnetdev_version(buf); -#endif err = 0; while (fgets(buf, sizeof buf, fh)) { @@ -1138,7 +1120,7 @@ static int if_readlist_proc(char *target) s = get_name(name, buf); ife = add_interface(name); - get_dev_fields(s, ife); + get_dev_fields(s, ife, procnetdev_vsn); ife->statistics_valid = 1; if (target && !strcmp(target, name)) break; @@ -1148,9 +1130,6 @@ static int if_readlist_proc(char *target) err = -1; proc_read = 0; } -#if 0 - free(fmt); -#endif fclose(fh); return err; } @@ -1670,7 +1649,8 @@ static void hwinit() #endif /* KEEP_UNUSED */ #ifdef IFF_PORTSEL -static const char *if_port_text[][4] = { +#if 0 +static const char * const if_port_text[][4] = { /* Keep in step with <linux/netdevice.h> */ {"unknown", NULL, NULL, NULL}, {"10base2", "bnc", "coax", NULL}, @@ -1681,6 +1661,19 @@ static const char *if_port_text[][4] = { {"100baseFX", NULL, NULL, NULL}, {NULL, NULL, NULL, NULL}, }; +#else +static const char * const if_port_text[] = { + /* Keep in step with <linux/netdevice.h> */ + "unknown", + "10base2", + "10baseT", + "AUI", + "100baseT", + "100baseTX", + "100baseFX", + NULL +}; +#endif #endif /* Check our hardware type table for this type. */ @@ -1714,29 +1707,83 @@ static int hw_null_address(struct hwtype *hw, void *ap) return 1; } -static const char TRext[] = "\0\0k\0M"; +#warning devel code +static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti"; static void print_bytes_scaled(unsigned long long ull, const char *end) { unsigned long long int_part; - unsigned long frac_part; const char *ext; + unsigned int frac_part; int i; frac_part = 0; ext = TRext; int_part = ull; - for (i = 0; i < 2; i++) { + i = 4; + do { +#if 0 + /* This does correct rounding and is a little larger. But it + * uses KiB as the smallest displayed unit. */ + if ((int_part < (1024*1024 - 51)) || !--i) { + i = 0; + int_part += 51; /* 1024*.05 = 51.2 */ + frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024; + } + int_part /= 1024; + ext += 3; /* KiB, MiB, GiB, TiB */ +#else if (int_part >= 1024) { - frac_part = ((int_part % 1024) * 10) / 1024; + frac_part = ((((unsigned int) int_part) & (1024-1)) * 10) / 1024; int_part /= 1024; - ext += 2; /* Kb, Mb */ + ext += 3; /* KiB, MiB, GiB, TiB */ } - } + --i; +#endif + } while (i); - printf("X bytes:%Lu (%Lu.%lu %siB)%s", ull, int_part, frac_part, ext, end); + printf("X bytes:%Lu (%Lu.%u %sB)%s", ull, int_part, frac_part, ext, end); } +static const char * const ife_print_flags_strs[] = { + "UP ", + "BROADCAST ", + "DEBUG ", + "LOOPBACK ", + "POINTOPOINT ", + "NOTRAILERS ", + "RUNNING ", + "NOARP ", + "PROMISC ", + "ALLMULTI ", + "SLAVE ", + "MASTER ", + "MULTICAST ", +#ifdef HAVE_DYNAMIC + "DYNAMIC " +#endif +}; + +static const unsigned short ife_print_flags_mask[] = { + IFF_UP, + IFF_BROADCAST, + IFF_DEBUG, + IFF_LOOPBACK, + IFF_POINTOPOINT, + IFF_NOTRAILERS, + IFF_RUNNING, + IFF_NOARP, + IFF_PROMISC, + IFF_ALLMULTI, + IFF_SLAVE, + IFF_MASTER, + IFF_MULTICAST, +#ifdef HAVE_DYNAMIC + IFF_DYNAMIC +#endif + 0 +}; + static void ife_print(struct interface *ptr) { struct aftype *ap; @@ -1782,7 +1829,7 @@ static void ife_print(struct interface *ptr) printf(_("HWaddr %s "), hw->print(ptr->hwaddr)); #ifdef IFF_PORTSEL if (ptr->flags & IFF_PORTSEL) { - printf(_("Media:%s"), if_port_text[ptr->map.port][0]); + printf(_("Media:%s"), if_port_text[ptr->map.port] /* [0] */); if (ptr->flags & IFF_AUTOMEDIA) printf(_("(auto)")); } @@ -1907,38 +1954,18 @@ static void ife_print(struct interface *ptr) printf(" "); /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */ - if (ptr->flags == 0) + + if (ptr->flags == 0) { printf(_("[NO FLAGS] ")); - if (ptr->flags & IFF_UP) - printf(_("UP ")); - if (ptr->flags & IFF_BROADCAST) - printf(_("BROADCAST ")); - if (ptr->flags & IFF_DEBUG) - printf(_("DEBUG ")); - if (ptr->flags & IFF_LOOPBACK) - printf(_("LOOPBACK ")); - if (ptr->flags & IFF_POINTOPOINT) - printf(_("POINTOPOINT ")); - if (ptr->flags & IFF_NOTRAILERS) - printf(_("NOTRAILERS ")); - if (ptr->flags & IFF_RUNNING) - printf(_("RUNNING ")); - if (ptr->flags & IFF_NOARP) - printf(_("NOARP ")); - if (ptr->flags & IFF_PROMISC) - printf(_("PROMISC ")); - if (ptr->flags & IFF_ALLMULTI) - printf(_("ALLMULTI ")); - if (ptr->flags & IFF_SLAVE) - printf(_("SLAVE ")); - if (ptr->flags & IFF_MASTER) - printf(_("MASTER ")); - if (ptr->flags & IFF_MULTICAST) - printf(_("MULTICAST ")); -#ifdef HAVE_DYNAMIC - if (ptr->flags & IFF_DYNAMIC) - printf(_("DYNAMIC ")); -#endif + } else { + int i = 0; + do { + if (ptr->flags & ife_print_flags_mask[i]) { + printf(_(ife_print_flags_strs[i])); + } + } while (ife_print_flags_mask[++i]); + } + /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ printf(_(" MTU:%d Metric:%d"), ptr->mtu, ptr->metric ? ptr->metric : 1); #ifdef SIOCSKEEPALIVE @@ -1956,8 +1983,7 @@ static void ife_print(struct interface *ptr) */ printf(" "); - printf(_ - ("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"), + printf(_("RX packets:%Lu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"), ptr->stats.rx_packets, ptr->stats.rx_errors, ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors, ptr->stats.rx_frame_errors); @@ -1965,8 +1991,7 @@ static void ife_print(struct interface *ptr) printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed); printf(" "); - printf(_ - ("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"), + printf(_("TX packets:%Lu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"), ptr->stats.tx_packets, ptr->stats.tx_errors, ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors, ptr->stats.tx_carrier_errors); |