aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorNigel Hathaway <Nigel.Hathaway@ubiquisys.com>2011-04-26 02:38:29 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-04-26 02:38:29 +0200
commitc37d4c67e85782001953a8bae8a9c65ccdcb2f88 (patch)
tree341888f2fca67e16a7981bacc2dbe7f77abaff4e /networking
parentb83c9704128dd106071184e4b00335a3b8486857 (diff)
downloadbusybox-c37d4c67e85782001953a8bae8a9c65ccdcb2f88.tar.gz
dhcpc: export unrecognized options in "optNN=XXXXXXXXX" form
function old new delta udhcp_run_script 609 818 +209 Signed-off-by: Nigel Hathaway <Nigel.Hathaway@ubiquisys.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking')
-rw-r--r--networking/udhcp/dhcpc.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index ca82d37e6..510c3a1d0 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;
}