[git commit] networking/interface.c: code shrink

Denys Vlasenko vda.linux at googlemail.com
Mon Mar 5 15:56:16 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=8a5299fcfd54ae3b895b66249d6d105e956192cb
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 <vda.linux at googlemail.com>
---
 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 <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,10 +1027,12 @@ 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');
 
 	/* If needed, display the interface statistics. */
@@ -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 */
-}


More information about the busybox-cvs mailing list