diff options
-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) |