From 5066473d411d6a474af3393d1b62a58ee3313861 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Tue, 27 Feb 2007 21:15:08 +0000 Subject: [PATCH] udhcp: optionally support RFC3397 (by Gabriel L. Somlo ) --- networking/udhcp/Config.in | 8 ++++++++ networking/udhcp/Kbuild | 19 ++++++++++--------- networking/udhcp/files.c | 23 +++++++++++++++++++++++ networking/udhcp/options.c | 8 +++++++- networking/udhcp/options.h | 7 +++++++ networking/udhcp/script.c | 33 ++++++++++++++++++++++----------- 6 files changed, 77 insertions(+), 21 deletions(-) diff --git a/networking/udhcp/Config.in b/networking/udhcp/Config.in index f633473..9dd02c4 100644 --- a/networking/udhcp/Config.in +++ b/networking/udhcp/Config.in @@ -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. diff --git a/networking/udhcp/Kbuild b/networking/udhcp/Kbuild index dc2c01f..57d2511 100644 --- a/networking/udhcp/Kbuild +++ b/networking/udhcp/Kbuild @@ -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 diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c index e35f50a..ab6f4a3 100644 --- a/networking/udhcp/files.c +++ b/networking/udhcp/files.c @@ -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; diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c index bda6efc..a58adb9 100644 --- a/networking/udhcp/options.c +++ b/networking/udhcp/options.c @@ -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, diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h index 588504e..11f013f 100644 --- a/networking/udhcp/options.h +++ b/networking/udhcp/options.h @@ -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 diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c index d2b0bb0..dc8ff7a 100644 --- a/networking/udhcp/script.c +++ b/networking/udhcp/script.c @@ -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) { -- 2.7.4