diff options
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r-- | networking/udhcp/dhcpc.c | 85 |
1 files changed, 55 insertions, 30 deletions
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) |