diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-03 17:34:52 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-03 17:34:52 +0200 |
| commit | 243ddcbc76d19847d9e8022dc2f6659078f5cc20 (patch) | |
| tree | badf9d7e92a70b2a2d60d47d35cad5418d91cdd1 | |
| parent | ccd1efc3c1d5b0187e20c1566654df92fa6be5c9 (diff) | |
| download | busybox-w32-243ddcbc76d19847d9e8022dc2f6659078f5cc20.tar.gz busybox-w32-243ddcbc76d19847d9e8022dc2f6659078f5cc20.tar.bz2 busybox-w32-243ddcbc76d19847d9e8022dc2f6659078f5cc20.zip | |
udhcpd: support decoding of option 120 "SIP servers". Closes bug 737
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/udhcp/Config.in | 3 | ||||
| -rw-r--r-- | networking/udhcp/common.c | 35 | ||||
| -rw-r--r-- | networking/udhcp/common.h | 4 | ||||
| -rw-r--r-- | networking/udhcp/dhcpc.c | 85 |
4 files changed, 83 insertions, 44 deletions
diff --git a/networking/udhcp/Config.in b/networking/udhcp/Config.in index fd2a61cc0..34adf35fe 100644 --- a/networking/udhcp/Config.in +++ b/networking/udhcp/Config.in | |||
| @@ -92,7 +92,8 @@ config FEATURE_UDHCP_RFC3397 | |||
| 92 | depends on UDHCPD || UDHCPC | 92 | depends on UDHCPD || UDHCPC |
| 93 | help | 93 | help |
| 94 | If selected, both client and server will support passing of domain | 94 | If selected, both client and server will support passing of domain |
| 95 | search lists via option 119, specified in RFC3397. | 95 | search lists via option 119, specified in RFC 3397, |
| 96 | and SIP servers option 120, specified in RFC 3361. | ||
| 96 | 97 | ||
| 97 | config UDHCPC_DEFAULT_SCRIPT | 98 | config UDHCPC_DEFAULT_SCRIPT |
| 98 | string "Absolute path to config script" | 99 | string "Absolute path to config script" |
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index adbcd77ac..77d7fd5d4 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
| @@ -50,7 +50,8 @@ const struct dhcp_option dhcp_options[] = { | |||
| 50 | //TODO: not a string, but a set of LASCII strings: | 50 | //TODO: not a string, but a set of LASCII strings: |
| 51 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ | 51 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ |
| 52 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 52 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 53 | { OPTION_STR1035 | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ | 53 | { OPTION_DNS_STRING | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ |
| 54 | { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ | ||
| 54 | #endif | 55 | #endif |
| 55 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ | 56 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ |
| 56 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | 57 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ |
| @@ -106,22 +107,32 @@ const char dhcp_option_strings[] ALIGN1 = | |||
| 106 | // "userclass" "\0" /* DHCP_USER_CLASS */ | 107 | // "userclass" "\0" /* DHCP_USER_CLASS */ |
| 107 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 108 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 108 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ | 109 | "search" "\0" /* DHCP_DOMAIN_SEARCH */ |
| 110 | // doesn't work in udhcpd.conf since OPTION_SIP_SERVERS | ||
| 111 | // is not handled yet by "string->option" conversion code: | ||
| 112 | "sipservers" "\0" /* DHCP_SIP_SERVERS */ | ||
| 109 | #endif | 113 | #endif |
| 110 | // "staticroutes" is only used to set udhcpc environment, it doesn't work | 114 | // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES |
| 111 | // in udhcpd.conf since OPTION_STATIC_ROUTES is not handled yet | 115 | // is not handled yet by "string->option" conversion code: |
| 112 | // by "string->option" conversion code: | 116 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ |
| 113 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | 117 | "wpad" "\0" /* DHCP_WPAD */ |
| 114 | "wpad" "\0" /* DHCP_WPAD */ | ||
| 115 | ; | 118 | ; |
| 116 | 119 | ||
| 117 | /* Lengths of the different option types */ | 120 | /* Lengths of the option types in binary form. |
| 121 | * Used by: | ||
| 122 | * udhcp_str2optset: to determine how many bytes to allocate. | ||
| 123 | * xmalloc_optname_optval: to estimate string length | ||
| 124 | * from binary option length: (option[LEN] / dhcp_option_lengths[opt_type]) | ||
| 125 | * is the number of elements, multiply in by one element's string width | ||
| 126 | * (len_of_option_as_string[opt_type]) and you know how wide string you need. | ||
| 127 | */ | ||
| 118 | const uint8_t dhcp_option_lengths[] ALIGN1 = { | 128 | const uint8_t dhcp_option_lengths[] ALIGN1 = { |
| 119 | [OPTION_IP] = 4, | 129 | [OPTION_IP] = 4, |
| 120 | [OPTION_IP_PAIR] = 8, | 130 | [OPTION_IP_PAIR] = 8, |
| 121 | // [OPTION_BOOLEAN] = 1, | 131 | // [OPTION_BOOLEAN] = 1, |
| 122 | [OPTION_STRING] = 1, | 132 | [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */ |
| 123 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 133 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 124 | [OPTION_STR1035] = 1, | 134 | [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */ |
| 135 | [OPTION_SIP_SERVERS] = 1, | ||
| 125 | #endif | 136 | #endif |
| 126 | [OPTION_U8] = 1, | 137 | [OPTION_U8] = 1, |
| 127 | [OPTION_U16] = 2, | 138 | [OPTION_U16] = 2, |
| @@ -332,7 +343,7 @@ static NOINLINE void attach_option( | |||
| 332 | if (!existing) { | 343 | if (!existing) { |
| 333 | log2("Attaching option %02x to list", option->code); | 344 | log2("Attaching option %02x to list", option->code); |
| 334 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 345 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 335 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { | 346 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
| 336 | /* reuse buffer and length for RFC1035-formatted string */ | 347 | /* reuse buffer and length for RFC1035-formatted string */ |
| 337 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); | 348 | allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length); |
| 338 | } | 349 | } |
| @@ -360,7 +371,7 @@ static NOINLINE void attach_option( | |||
| 360 | log1("Attaching option %02x to existing member of list", option->code); | 371 | log1("Attaching option %02x to existing member of list", option->code); |
| 361 | old_len = existing->data[OPT_LEN]; | 372 | old_len = existing->data[OPT_LEN]; |
| 362 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 373 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 363 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_STR1035) { | 374 | if ((option->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
| 364 | /* reuse buffer and length for RFC1035-formatted string */ | 375 | /* reuse buffer and length for RFC1035-formatted string */ |
| 365 | allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); | 376 | allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length); |
| 366 | } | 377 | } |
| @@ -426,7 +437,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |||
| 426 | break; | 437 | break; |
| 427 | case OPTION_STRING: | 438 | case OPTION_STRING: |
| 428 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 439 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 429 | case OPTION_STR1035: | 440 | case OPTION_DNS_STRING: |
| 430 | #endif | 441 | #endif |
| 431 | length = strnlen(val, 254); | 442 | length = strnlen(val, 254); |
| 432 | if (length > 0) { | 443 | if (length > 0) { |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 1c5afa6f9..28e34718a 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
| @@ -71,7 +71,8 @@ enum { | |||
| 71 | OPTION_IP_PAIR, | 71 | OPTION_IP_PAIR, |
| 72 | OPTION_STRING, | 72 | OPTION_STRING, |
| 73 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 73 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 74 | OPTION_STR1035, /* RFC1035 compressed domain name list */ | 74 | OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ |
| 75 | OPTION_SIP_SERVERS, | ||
| 75 | #endif | 76 | #endif |
| 76 | // OPTION_BOOLEAN, | 77 | // OPTION_BOOLEAN, |
| 77 | OPTION_U8, | 78 | OPTION_U8, |
| @@ -130,6 +131,7 @@ enum { | |||
| 130 | //#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ | 131 | //#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ |
| 131 | #define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ | 132 | #define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ |
| 132 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ | 133 | //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ |
| 134 | //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ | ||
| 133 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ | 135 | //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ |
| 134 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ | 136 | //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ |
| 135 | #define DHCP_END 0xff | 137 | #define DHCP_END 0xff |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index c36d4180b..53e10d00e 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
| @@ -42,19 +42,24 @@ | |||
| 42 | 42 | ||
| 43 | /* get a rough idea of how long an option will be (rounding up...) */ | 43 | /* get a rough idea of how long an option will be (rounding up...) */ |
| 44 | static const uint8_t len_of_option_as_string[] = { | 44 | static const uint8_t len_of_option_as_string[] = { |
| 45 | [OPTION_IP] = sizeof("255.255.255.255 "), | 45 | [OPTION_IP ] = sizeof("255.255.255.255 "), |
| 46 | [OPTION_IP_PAIR] = sizeof("255.255.255.255 ") * 2, | 46 | [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, |
| 47 | [OPTION_STATIC_ROUTES]= sizeof("255.255.255.255/32 255.255.255.255 "), | 47 | [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), |
| 48 | [OPTION_STRING] = 1, | 48 | [OPTION_STRING ] = 1, |
| 49 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 49 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 50 | [OPTION_STR1035] = 1, | 50 | [OPTION_DNS_STRING ] = 1, /* unused */ |
| 51 | /* Hmmm, this severely overestimates size if SIP_SERVERS option | ||
| 52 | * is in domain name form: N-byte option in binary form | ||
| 53 | * mallocs ~16*N bytes. But it is freed almost at once. | ||
| 54 | */ | ||
| 55 | [OPTION_SIP_SERVERS ] = sizeof("255.255.255.255 "), | ||
| 51 | #endif | 56 | #endif |
| 52 | // [OPTION_BOOLEAN] = sizeof("yes "), | 57 | // [OPTION_BOOLEAN ] = sizeof("yes "), |
| 53 | [OPTION_U8] = sizeof("255 "), | 58 | [OPTION_U8 ] = sizeof("255 "), |
| 54 | [OPTION_U16] = sizeof("65535 "), | 59 | [OPTION_U16 ] = sizeof("65535 "), |
| 55 | // [OPTION_S16] = sizeof("-32768 "), | 60 | // [OPTION_S16 ] = sizeof("-32768 "), |
| 56 | [OPTION_U32] = sizeof("4294967295 "), | 61 | [OPTION_U32 ] = sizeof("4294967295 "), |
| 57 | [OPTION_S32] = sizeof("-2147483684 "), | 62 | [OPTION_S32 ] = sizeof("-2147483684 "), |
| 58 | }; | 63 | }; |
| 59 | 64 | ||
| 60 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ | 65 | /* note: ip is a pointer to an IP in network order, possibly misaliged */ |
| @@ -80,16 +85,13 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
| 80 | { | 85 | { |
| 81 | unsigned upper_length; | 86 | unsigned upper_length; |
| 82 | int len, type, optlen; | 87 | int len, type, optlen; |
| 83 | uint16_t val_u16; | ||
| 84 | uint32_t val_u32; | ||
| 85 | int32_t val_s32; | ||
| 86 | char *dest, *ret; | 88 | char *dest, *ret; |
| 87 | 89 | ||
| 88 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ | 90 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ |
| 89 | len = option[OPT_LEN - OPT_DATA]; | 91 | len = option[OPT_LEN - OPT_DATA]; |
| 90 | type = type_p->flags & OPTION_TYPE_MASK; | 92 | type = type_p->flags & OPTION_TYPE_MASK; |
| 91 | optlen = dhcp_option_lengths[type]; | 93 | optlen = dhcp_option_lengths[type]; |
| 92 | upper_length = len_of_option_as_string[type] * (len / optlen); | 94 | upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); |
| 93 | 95 | ||
| 94 | dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); | 96 | dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); |
| 95 | dest += sprintf(ret, "%s=", opt_name); | 97 | dest += sprintf(ret, "%s=", opt_name); |
| @@ -113,24 +115,20 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
| 113 | case OPTION_U8: | 115 | case OPTION_U8: |
| 114 | dest += sprintf(dest, "%u", *option); | 116 | dest += sprintf(dest, "%u", *option); |
| 115 | break; | 117 | break; |
| 116 | case OPTION_U16: | 118 | // case OPTION_S16: |
| 119 | case OPTION_U16: { | ||
| 120 | uint16_t val_u16; | ||
| 117 | move_from_unaligned16(val_u16, option); | 121 | move_from_unaligned16(val_u16, option); |
| 118 | dest += sprintf(dest, "%u", ntohs(val_u16)); | 122 | dest += sprintf(dest, "%u", ntohs(val_u16)); |
| 119 | break; | 123 | break; |
| 120 | // case OPTION_S16: { | 124 | } |
| 121 | // int16_t val_s16; | ||
| 122 | // move_from_unaligned16(val_s16, option); | ||
| 123 | // dest += sprintf(dest, "%d", ntohs(val_s16)); | ||
| 124 | // break; | ||
| 125 | // } | ||
| 126 | case OPTION_U32: | ||
| 127 | move_from_unaligned32(val_u32, option); | ||
| 128 | dest += sprintf(dest, "%lu", (unsigned long) ntohl(val_u32)); | ||
| 129 | break; | ||
| 130 | case OPTION_S32: | 125 | case OPTION_S32: |
| 131 | move_from_unaligned32(val_s32, option); | 126 | case OPTION_U32: { |
| 132 | dest += sprintf(dest, "%ld", (long) ntohl(val_s32)); | 127 | uint32_t val_u32; |
| 128 | move_from_unaligned32(val_u32, option); | ||
| 129 | dest += sprintf(dest, type == OPTION_U32 ? "%lu" : "%ld", (unsigned long) ntohl(val_u32)); | ||
| 133 | break; | 130 | break; |
| 131 | } | ||
| 134 | case OPTION_STRING: | 132 | case OPTION_STRING: |
| 135 | memcpy(dest, option, len); | 133 | memcpy(dest, option, len); |
| 136 | dest[len] = '\0'; | 134 | dest[len] = '\0'; |
| @@ -180,7 +178,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
| 180 | return ret; | 178 | return ret; |
| 181 | } | 179 | } |
| 182 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 180 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
| 183 | case OPTION_STR1035: | 181 | case OPTION_DNS_STRING: |
| 184 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ | 182 | /* unpack option into dest; use ret for prefix (i.e., "optname=") */ |
| 185 | dest = dname_dec(option, len, ret); | 183 | dest = dname_dec(option, len, ret); |
| 186 | if (dest) { | 184 | if (dest) { |
| @@ -189,8 +187,35 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
| 189 | } | 187 | } |
| 190 | /* error. return "optname=" string */ | 188 | /* error. return "optname=" string */ |
| 191 | return ret; | 189 | return ret; |
| 190 | case OPTION_SIP_SERVERS: | ||
| 191 | /* Option binary format: | ||
| 192 | * type: byte | ||
| 193 | * type=0: domain names, dns-compressed | ||
| 194 | * type=1: IP addrs | ||
| 195 | */ | ||
| 196 | option++; | ||
| 197 | len--; | ||
| 198 | if (option[-1] == 0) { | ||
| 199 | dest = dname_dec(option, len, ret); | ||
| 200 | if (dest) { | ||
| 201 | free(ret); | ||
| 202 | return dest; | ||
| 203 | } | ||
| 204 | } else | ||
| 205 | if (option[-1] == 1) { | ||
| 206 | const char *pfx = ""; | ||
| 207 | while (1) { | ||
| 208 | len -= 4; | ||
| 209 | if (len < 0) | ||
| 210 | break; | ||
| 211 | dest += sprint_nip(dest, pfx, option); | ||
| 212 | pfx = " "; | ||
| 213 | option += 4; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | return ret; | ||
| 192 | #endif | 217 | #endif |
| 193 | } | 218 | } /* switch */ |
| 194 | option += optlen; | 219 | option += optlen; |
| 195 | len -= optlen; | 220 | len -= optlen; |
| 196 | if (len <= 0) | 221 | if (len <= 0) |
