udhcp: optionally support RFC3397 (by Gabriel L. Somlo
No binary (build failed)
—
(log yok)
| @@ -65,3 +65,11 @@ config FEATURE_UDHCP_DEBUG | |
| the background. | |
| See http://udhcp.busybox.net for further details. | |
| + | |
| + | config FEATURE_RFC3397 |
| + | bool "Support for RFC3397 domain search (experimental)" |
| + | default n |
| + | depends on APP_UDHCPD || APP_UDHCPC |
| + | help |
| + | If selected, both client and server will support passing of domain |
| + | search lists via option 119, specified in RFC3397. |
| @@ -6,13 +6,14 @@ | |
| # | |
| lib-y:= | |
| - | lib-$(CONFIG_APP_UDHCPC) += common.o options.o packet.o pidfile.o \ |
| - | signalpipe.o socket.o |
| - | lib-$(CONFIG_APP_UDHCPD) += common.o options.o packet.o pidfile.o \ |
| - | signalpipe.o socket.o |
| - | lib-$(CONFIG_APP_UDHCPC) += dhcpc.o clientpacket.o clientsocket.o \ |
| - | script.o |
| - | lib-$(CONFIG_APP_UDHCPD) += dhcpd.o arpping.o files.o leases.o \ |
| - | serverpacket.o static_leases.o |
| - | lib-$(CONFIG_APP_DUMPLEASES) += dumpleases.o |
| + | lib-$(CONFIG_APP_UDHCPC) += common.o options.o packet.o pidfile.o \ |
| + | signalpipe.o socket.o |
| + | lib-$(CONFIG_APP_UDHCPD) += common.o options.o packet.o pidfile.o \ |
| + | signalpipe.o socket.o |
| + | lib-$(CONFIG_APP_UDHCPC) += dhcpc.o clientpacket.o clientsocket.o \ |
| + | script.o |
| + | lib-$(CONFIG_APP_UDHCPD) += dhcpd.o arpping.o files.o leases.o \ |
| + | serverpacket.o static_leases.o |
| + | lib-$(CONFIG_APP_DUMPLEASES) += dumpleases.o |
| lib-$(CONFIG_APP_DHCPRELAY) += dhcprelay.o | |
| + | lib-$(CONFIG_FEATURE_RFC3397) += domain_codec.o |
| @@ -104,6 +104,12 @@ static void attach_option(struct option_set **opt_list, | |
| if (!existing) { | |
| DEBUG("Attaching option %s to list", option->name); | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | if ((option->flags & TYPE_MASK) == OPTION_STR1035) |
| + | /* reuse buffer and length for RFC1035-formatted string */ |
| + | buffer = dname_enc(NULL, 0, buffer, &length); |
| + | #endif |
| + | |
| /* make a new option */ | |
| new = xmalloc(sizeof(struct option_set)); | |
| new->data = xmalloc(length + 2); | |
| @@ -117,12 +123,22 @@ static void attach_option(struct option_set **opt_list, | |
| new->next = *curr; | |
| *curr = new; | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | if ((option->flags & TYPE_MASK) == OPTION_STR1035 && buffer != NULL) |
| + | free(buffer); |
| + | #endif |
| return; | |
| } | |
| /* add it to an existing option */ | |
| DEBUG("Attaching option %s to existing member of list", option->name); | |
| if (option->flags & OPTION_LIST) { | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | if ((option->flags & TYPE_MASK) == OPTION_STR1035) |
| + | /* reuse buffer and length for RFC1035-formatted string */ |
| + | buffer = dname_enc(existing->data + 2, |
| + | existing->data[OPT_LEN], buffer, &length); |
| + | #endif |
| if (existing->data[OPT_LEN] + length <= 255) { | |
| existing->data = xrealloc(existing->data, | |
| existing->data[OPT_LEN] + length + 3); | |
| @@ -137,6 +153,10 @@ static void attach_option(struct option_set **opt_list, | |
| memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length); | |
| existing->data[OPT_LEN] += length; | |
| } /* else, ignore the data, we could put this in a second option in the future */ | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | if ((option->flags & TYPE_MASK) == OPTION_STR1035 && buffer != NULL) |
| + | free(buffer); |
| + | #endif |
| } /* else, ignore the new data */ | |
| } | |
| @@ -183,6 +203,9 @@ static int read_opt(const char *const_line, void *arg) | |
| if (retval) retval = read_ip(val, buffer + 4); | |
| break; | |
| case OPTION_STRING: | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | case OPTION_STR1035: |
| + | #endif |
| length = strlen(val); | |
| if (length > 0) { | |
| if (length > 254) length = 254; | |
| @@ -11,7 +11,7 @@ | |
| /* supported options are easily added here */ | |
| const struct dhcp_option dhcp_options[] = { | |
| - | /* name[10] flags code */ |
| + | /* name[12] flags code */ |
| {"subnet", OPTION_IP | OPTION_REQ, 0x01}, | |
| {"timezone", OPTION_S32, 0x02}, | |
| {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, | |
| @@ -43,6 +43,9 @@ const struct dhcp_option dhcp_options[] = { | |
| {"tftp", OPTION_STRING, 0x42}, | |
| {"bootfile", OPTION_STRING, 0x43}, | |
| {"userclass", OPTION_STRING, 0x4D}, | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | {"search", OPTION_STR1035 | OPTION_LIST | OPTION_REQ, 0x77}, |
| + | #endif |
| /* MSIE's "Web Proxy Autodiscovery Protocol" support */ | |
| {"wpad", OPTION_STRING, 0xfc}, | |
| {"", 0x00, 0x00} | |
| @@ -54,6 +57,9 @@ const unsigned char option_lengths[] = { | |
| [OPTION_IP_PAIR] = 8, | |
| [OPTION_BOOLEAN] = 1, | |
| [OPTION_STRING] = 1, | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | [OPTION_STR1035] = 1, |
| + | #endif |
| [OPTION_U8] = 1, | |
| [OPTION_U16] = 2, | |
| [OPTION_S16] = 2, | |
| @@ -9,6 +9,9 @@ enum { | |
| OPTION_IP=1, | |
| OPTION_IP_PAIR, | |
| OPTION_STRING, | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | OPTION_STR1035, /* RFC1035 compressed domain name list */ |
| + | #endif |
| OPTION_BOOLEAN, | |
| OPTION_U8, | |
| OPTION_U16, | |
| @@ -33,5 +36,9 @@ uint8_t *get_option(struct dhcpMessage *packet, int code); | |
| int end_option(uint8_t *optionptr); | |
| int add_option_string(uint8_t *optionptr, uint8_t *string); | |
| int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data); | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | char *dname_dec(const uint8_t *cstr, int clen, const char *pre); |
| + | uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen); |
| + | #endif |
| #endif | |
| @@ -19,6 +19,9 @@ static const int max_option_length[] = { | |
| [OPTION_IP] = sizeof("255.255.255.255 "), | |
| [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, | |
| [OPTION_STRING] = 1, | |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | [OPTION_STR1035] = 1, |
| + | #endif |
| [OPTION_BOOLEAN] = sizeof("yes "), | |
| [OPTION_U8] = sizeof("255 "), | |
| [OPTION_U16] = sizeof("65535 "), | |
| @@ -53,21 +56,23 @@ static int mton(struct in_addr *mask) | |
| } | |
| - | /* Fill dest with the text of option 'option'. */ |
| - | static void fill_options(char *dest, uint8_t *option, |
| - | const struct dhcp_option *type_p) |
| + | /* Allocate and fill with the text of option 'option'. */ |
| + | static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p) |
| { | |
| - | int type, optlen; |
| + | int len, type, optlen; |
| uint16_t val_u16; | |
| int16_t val_s16; | |
| uint32_t val_u32; | |
| int32_t val_s32; | |
| - | int len = option[OPT_LEN - 2]; |
| - | |
| - | dest += sprintf(dest, "%s=", type_p->name); |
| + | char *dest, *ret; |
| + | len = option[OPT_LEN - 2]; |
| type = type_p->flags & TYPE_MASK; | |
| optlen = option_lengths[type]; | |
| + | |
| + | dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->name) + 2); |
| + | dest += sprintf(ret, "%s=", type_p->name); |
| + | |
| for (;;) { | |
| switch (type) { | |
| case OPTION_IP_PAIR: | |
| @@ -103,13 +108,21 @@ static void fill_options(char *dest, uint8_t *option, | |
| case OPTION_STRING: | |
| memcpy(dest, option, len); | |
| dest[len] = '\0'; | |
| - | return; /* Short circuit this case */ |
| + | return ret; /* Short circuit this case */ |
| + | #if ENABLE_FEATURE_RFC3397 |
| + | case OPTION_STR1035: |
| + | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ |
| + | dest = dname_dec(option, len, ret); |
| + | free(ret); |
| + | return dest; |
| + | #endif |
| } | |
| option += optlen; | |
| len -= optlen; | |
| if (len <= 0) break; | |
| dest += sprintf(dest, " "); | |
| } | |
| + | return ret; |
| } | |
| @@ -155,9 +168,7 @@ static char **fill_envp(struct dhcpMessage *packet) | |
| temp = get_option(packet, dhcp_options[i].code); | |
| if (!temp) | |
| continue; | |
| - | envp[j] = xmalloc(upper_length(temp[OPT_LEN - 2], |
| - | dhcp_options[i].flags & TYPE_MASK) + strlen(dhcp_options[i].name) + 2); |
| - | fill_options(envp[j++], temp, &dhcp_options[i]); |
| + | envp[j++] = alloc_fill_opts(temp, &dhcp_options[i]); |
| /* Fill in a subnet bits option for things like /24 */ | |
| if (dhcp_options[i].code == DHCP_SUBNET) { | |