[git commit] ifconfig: do not accept "ifconfig eth0 up 1.2.3.4/17" (ip with mask). Closes 5786

Denys Vlasenko vda.linux at googlemail.com
Sun Jan 20 17:10:12 UTC 2013


commit: http://git.busybox.net/busybox/commit/?id=31dc8603eedc0140c798c9af3404a35ea190af2c
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
ifconfig_main                                       1221    1237     +16

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/ifconfig.c |  167 +++++++++++++++++++++++-------------------------
 networking/route.c    |    2 +-
 2 files changed, 81 insertions(+), 88 deletions(-)

diff --git a/networking/ifconfig.c b/networking/ifconfig.c
index 320df30..782374b 100644
--- a/networking/ifconfig.c
+++ b/networking/ifconfig.c
@@ -174,10 +174,6 @@ struct in6_ifreq {
 #define ARG_ADD_DEL      (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
 
 
-/*
- * Set up the tables.  Warning!  They must have corresponding order!
- */
-
 struct arg1opt {
 	const char *name;
 	unsigned short selector;
@@ -198,6 +194,10 @@ struct options {
 
 #define ifreq_offsetof(x)  offsetof(struct ifreq, x)
 
+/*
+ * Set up the tables.  Warning!  They must have corresponding order!
+ */
+
 static const struct arg1opt Arg1Opt[] = {
 	{ "SIFMETRIC",  SIOCSIFMETRIC,  ifreq_offsetof(ifr_metric) },
 	{ "SIFMTU",     SIOCSIFMTU,     ifreq_offsetof(ifr_mtu) },
@@ -220,11 +220,11 @@ static const struct arg1opt Arg1Opt[] = {
 	{ "SIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.base_addr) },
 	{ "SIFMAP",     SIOCSIFMAP,     ifreq_offsetof(ifr_map.irq) },
 #endif
-	/* Last entry if for unmatched (possibly hostname) arg. */
 #if ENABLE_FEATURE_IPV6
 	{ "SIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
 	{ "DIFADDR",    SIOCDIFADDR,    ifreq_offsetof(ifr_addr) }, /* IPv6 version ignores the offset */
 #endif
+	/* Last entry is for unmatched (assumed to be hostname/address) arg. */
 	{ "SIFADDR",    SIOCSIFADDR,    ifreq_offsetof(ifr_addr) },
 };
 
@@ -265,16 +265,49 @@ static const struct options OptArray[] = {
 	{ NULL,          0,             ARG_HOSTNAME,    (IFF_UP | IFF_RUNNING) }
 };
 
-/*
- * A couple of prototypes.
- */
 #if ENABLE_FEATURE_IFCONFIG_HW
-static int in_ether(const char *bufp, struct sockaddr *sap);
+/* Input an Ethernet address and convert to binary. */
+static int in_ether(const char *bufp, struct sockaddr *sap)
+{
+	char *ptr;
+	int i, j;
+	unsigned char val;
+	unsigned char c;
+
+	sap->sa_family = ARPHRD_ETHER;
+	ptr = (char *) sap->sa_data;
+
+	i = 0;
+	do {
+		j = val = 0;
+
+		/* We might get a semicolon here - not required. */
+		if (i && (*bufp == ':')) {
+			bufp++;
+		}
+
+		do {
+			c = *bufp;
+			if (((unsigned char)(c - '0')) <= 9) {
+				c -= '0';
+			} else if ((unsigned char)((c|0x20) - 'a') <= 5) {
+				c = (unsigned char)((c|0x20) - 'a') + 10;
+			} else if (j && (c == ':' || c == 0)) {
+				break;
+			} else {
+				return -1;
+			}
+			++bufp;
+			val <<= 4;
+			val += c;
+		} while (++j < 2);
+		*ptr++ = val;
+	} while (++i < ETH_ALEN);
+
+	return *bufp; /* Error if we don't end at end of string. */
+}
 #endif
 
-/*
- * Our main function.
- */
 int ifconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 {
@@ -330,7 +363,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 	strncpy_IFNAMSIZ(ifr.ifr_name, *argv);
 
 	/* Process the remaining arguments. */
-	while (*++argv != (char *) NULL) {
+	while (*++argv != NULL) {
 		p = *argv;
 		mask = N_MASK;
 		if (*p == '-') {	/* If the arg starts with '-'... */
@@ -356,9 +389,9 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
  FOUND_ARG:
 		if (mask & ARG_MASK) {
 			mask = op->arg_flags;
-			a1op = Arg1Opt + (op - OptArray);
 			if (mask & A_NETMASK & did_flags)
 				bb_show_usage();
+			a1op = Arg1Opt + (op - OptArray);
 			if (*++argv == NULL) {
 				if (mask & A_ARG_REQ)
 					bb_show_usage();
@@ -371,19 +404,9 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 #if ENABLE_FEATURE_IFCONFIG_HW
 					if (mask & A_CAST_RESOLVE) {
 #endif
-#if ENABLE_FEATURE_IPV6
-						char *prefix;
-						int prefix_len = 0;
-#endif
-						/*safe_strncpy(host, *argv, (sizeof host));*/
 						host = *argv;
-#if ENABLE_FEATURE_IPV6
-						prefix = strchr(host, '/');
-						if (prefix) {
-							prefix_len = xatou_range(prefix + 1, 0, 128);
-							*prefix = '\0';
-						}
-#endif
+						if (strcmp(host, "inet") == 0)
+							continue; /* compat stuff */
 						sai.sin_family = AF_INET;
 						sai.sin_port = 0;
 						if (strcmp(host, "default") == 0) {
@@ -391,7 +414,8 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 							sai.sin_addr.s_addr = INADDR_ANY;
 						}
 #if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
-						else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST)
+						else if ((host[0] == '+' && !host[1])
+						 && (mask & A_BROADCAST)
 						 && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)
 						) {
 							/* + is special, meaning broadcast is derived. */
@@ -400,23 +424,36 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 #endif
 						else {
 							len_and_sockaddr *lsa;
-							if (strcmp(host, "inet") == 0)
-								continue; /* compat stuff */
+#if ENABLE_FEATURE_IPV6
+							char *prefix;
+							int prefix_len = 0;
+							prefix = strchr(host, '/');
+							if (prefix) {
+								prefix_len = xatou_range(prefix + 1, 0, 128);
+								*prefix = '\0';
+							}
+ resolve:
+#endif
 							lsa = xhost2sockaddr(host, 0);
 #if ENABLE_FEATURE_IPV6
+							if (lsa->u.sa.sa_family != AF_INET6 && prefix) {
+/* TODO: we do not support "ifconfig eth0 up 1.2.3.4/17".
+ * For now, just make it fail instead of silently ignoring "/17" part:
+ */
+								*prefix = '/';
+								goto resolve;
+							}
 							if (lsa->u.sa.sa_family == AF_INET6) {
 								int sockfd6;
 								struct in6_ifreq ifr6;
 
-								memcpy((char *) &ifr6.ifr6_addr,
-										(char *) &(lsa->u.sin6.sin6_addr),
-										sizeof(struct in6_addr));
-
-								/* Create a channel to the NET kernel. */
 								sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
-								xioctl(sockfd6, SIOGIFINDEX, &ifr);
+								xioctl(sockfd6, SIOCGIFINDEX, &ifr);
 								ifr6.ifr6_ifindex = ifr.ifr_ifindex;
 								ifr6.ifr6_prefixlen = prefix_len;
+								memcpy(&ifr6.ifr6_addr,
+										&lsa->u.sin6.sin6_addr,
+										sizeof(struct in6_addr));
 								ioctl_or_perror_and_die(sockfd6, a1op->selector, &ifr6, "SIOC%s", a1op->name);
 								if (ENABLE_FEATURE_CLEAN_UP)
 									free(lsa);
@@ -437,18 +474,17 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 #if ENABLE_FEATURE_IFCONFIG_HW
 					} else {	/* A_CAST_HOST_COPY_IN_ETHER */
 						/* This is the "hw" arg case. */
-						smalluint hw_class= index_in_substrings("ether\0"
+						smalluint hw_class = index_in_substrings("ether\0"
 								IF_FEATURE_HWIB("infiniband\0"), *argv) + 1;
 						if (!hw_class || !*++argv)
 							bb_show_usage();
-						/*safe_strncpy(host, *argv, sizeof(host));*/
 						host = *argv;
 						if (hw_class == 1 ? in_ether(host, &sa) : in_ib(host, &sa))
 							bb_error_msg_and_die("invalid hw-addr %s", host);
 						p = (char *) &sa;
 					}
 #endif
-					memcpy( (((char *)&ifr) + a1op->ifr_offset),
+					memcpy( ((char *)&ifr) + a1op->ifr_offset,
 						p, sizeof(struct sockaddr));
 				} else {
 					/* FIXME: error check?? */
@@ -458,17 +494,17 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 					if (mask & A_MAP_TYPE) {
 						xioctl(sockfd, SIOCGIFMAP, &ifr);
 						if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR)
-							*((unsigned char *) p) = i;
+							*(unsigned char *) p = i;
 						else if (mask & A_MAP_USHORT)
-							*((unsigned short *) p) = i;
+							*(unsigned short *) p = i;
 						else
-							*((unsigned long *) p) = i;
+							*(unsigned long *) p = i;
 					} else
 #endif
 					if (mask & A_CAST_CHAR_PTR)
-						*((caddr_t *) p) = (caddr_t) i;
+						*(caddr_t *) p = (caddr_t) i;
 					else	/* A_CAST_INT */
-						*((int *) p) = i;
+						*(int *) p = i;
 				}
 
 				ioctl_or_perror_and_die(sockfd, a1op->selector, &ifr, "SIOC%s", a1op->name);
@@ -494,7 +530,7 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 			if (!(mask & A_SET_AFTER))
 				continue;
 			mask = N_SET;
-		}
+		} /* if (mask & ARG_MASK) */
 
 		xioctl(sockfd, SIOCGIFFLAGS, &ifr);
 		selector = op->selector;
@@ -509,46 +545,3 @@ int ifconfig_main(int argc UNUSED_PARAM, char **argv)
 		close(sockfd);
 	return 0;
 }
-
-#if ENABLE_FEATURE_IFCONFIG_HW
-/* Input an Ethernet address and convert to binary. */
-static int in_ether(const char *bufp, struct sockaddr *sap)
-{
-	char *ptr;
-	int i, j;
-	unsigned char val;
-	unsigned char c;
-
-	sap->sa_family = ARPHRD_ETHER;
-	ptr = (char *) sap->sa_data;
-
-	i = 0;
-	do {
-		j = val = 0;
-
-		/* We might get a semicolon here - not required. */
-		if (i && (*bufp == ':')) {
-			bufp++;
-		}
-
-		do {
-			c = *bufp;
-			if (((unsigned char)(c - '0')) <= 9) {
-				c -= '0';
-			} else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
-				c = (c|0x20) - ('a'-10);
-			} else if (j && (c == ':' || c == 0)) {
-				break;
-			} else {
-				return -1;
-			}
-			++bufp;
-			val <<= 4;
-			val += c;
-		} while (++j < 2);
-		*ptr++ = val;
-	} while (++i < ETH_ALEN);
-
-	return *bufp; /* Error if we don't end at end of string. */
-}
-#endif
diff --git a/networking/route.c b/networking/route.c
index f662031..4235ea7 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -435,7 +435,7 @@ static NOINLINE void INET6_setroute(int action, char **args)
 		struct ifreq ifr;
 		memset(&ifr, 0, sizeof(ifr));
 		strncpy_IFNAMSIZ(ifr.ifr_name, devname);
-		xioctl(skfd, SIOGIFINDEX, &ifr);
+		xioctl(skfd, SIOCGIFINDEX, &ifr);
 		rt.rtmsg_ifindex = ifr.ifr_ifindex;
 	}
 


More information about the busybox-cvs mailing list