[git commit] dhcpc: export unrecognized options in "optNN=XXXXXXXXX" form

Denys Vlasenko vda.linux at googlemail.com
Tue Apr 26 00:38:29 UTC 2011


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

function                                             old     new   delta
udhcp_run_script                                     609     818    +209

Signed-off-by: Nigel Hathaway <Nigel.Hathaway at ubiquisys.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/udhcp/dhcpc.c |   57 +++++++++++++++++++++++++++++++++++++--------
 1 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index ca82d37..510c3a1 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -300,6 +300,14 @@ static char **fill_envp(struct dhcp_packet *packet)
 	uint8_t *temp;
 	uint8_t overload = 0;
 
+#define BITMAP unsigned
+#define BBITS (sizeof(BITMAP) * 8)
+#define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1)))
+#define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS])
+	BITMAP found_opts[256 / BBITS];
+
+	memset(found_opts, 0, sizeof(found_opts));
+
 	/* We need 6 elements for:
 	 * "interface=IFACE"
 	 * "ip=N.N.N.N" from packet->yiaddr
@@ -311,18 +319,21 @@ static char **fill_envp(struct dhcp_packet *packet)
 	envc = 6;
 	/* +1 element for each option, +2 for subnet option: */
 	if (packet) {
-		for (i = 0; dhcp_optflags[i].code; i++) {
-			if (udhcp_get_option(packet, dhcp_optflags[i].code)) {
-				if (dhcp_optflags[i].code == DHCP_SUBNET)
+		/* note: do not search for "pad" (0) and "end" (255) options */
+		for (i = 1; i < 255; i++) {
+			temp = udhcp_get_option(packet, i);
+			if (temp) {
+				if (i == DHCP_OPTION_OVERLOAD)
+					overload = *temp;
+				else if (i == DHCP_SUBNET)
 					envc++; /* for mton */
 				envc++;
+				/*if (i != DHCP_MESSAGE_TYPE)*/
+				FOUND_OPTS(i) |= BMASK(i);
 			}
 		}
-		temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD);
-		if (temp)
-			overload = *temp;
 	}
-	curr = envp = xzalloc(sizeof(char *) * envc);
+	curr = envp = xzalloc(sizeof(envp[0]) * envc);
 
 	*curr = xasprintf("interface=%s", client_config.interface);
 	putenv(*curr++);
@@ -337,12 +348,16 @@ static char **fill_envp(struct dhcp_packet *packet)
 	opt_name = dhcp_option_strings;
 	i = 0;
 	while (*opt_name) {
-		temp = udhcp_get_option(packet, dhcp_optflags[i].code);
-		if (!temp)
+		uint8_t code = dhcp_optflags[i].code;
+		BITMAP *found_ptr = &FOUND_OPTS(code);
+		BITMAP found_mask = BMASK(code);
+		if (!(*found_ptr & found_mask))
 			goto next;
+		*found_ptr &= ~found_mask; /* leave only unknown options */
+		temp = udhcp_get_option(packet, code);
 		*curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);
 		putenv(*curr++);
-		if (dhcp_optflags[i].code == DHCP_SUBNET) {
+		if (code == DHCP_SUBNET) {
 			/* Subnet option: make things like "$ip/$mask" possible */
 			uint32_t subnet;
 			move_from_unaligned32(subnet, temp);
@@ -368,6 +383,28 @@ static char **fill_envp(struct dhcp_packet *packet)
 		*curr = xasprintf("sname=%."DHCP_PKT_SNAME_LEN_STR"s", packet->sname);
 		putenv(*curr++);
 	}
+	/* Handle unknown options */
+	for (i = 0; i < 256;) {
+		BITMAP bitmap = FOUND_OPTS(i);
+		if (!bitmap) {
+			i += BBITS;
+			continue;
+		}
+		if (bitmap & BMASK(i)) {
+			unsigned len, ofs;
+
+			temp = udhcp_get_option(packet, i);
+			/* udhcp_get_option returns ptr to data portion,
+			 * need to go back to get len
+			 */
+			len = temp[-OPT_DATA + OPT_LEN];
+			*curr = xmalloc(sizeof("optNNN=") + 1 + len*2);
+			ofs = sprintf(*curr, "opt%u=", i);
+			bin2hex(*curr + ofs, (void*) temp, len)[0] = '\0';
+			putenv(*curr++);
+		}
+		i++;
+	}
 	return envp;
 }
 
-- 
1.7.3.4



More information about the busybox-cvs mailing list