aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/Config.in3
-rw-r--r--networking/udhcp/common.c35
-rw-r--r--networking/udhcp/common.h4
-rw-r--r--networking/udhcp/dhcpc.c85
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
97config UDHCPC_DEFAULT_SCRIPT 98config 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 */
118const uint8_t dhcp_option_lengths[] ALIGN1 = { 128const 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...) */
44static const uint8_t len_of_option_as_string[] = { 44static 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)