summaryrefslogtreecommitdiff
path: root/networking/udhcp/dhcpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r--networking/udhcp/dhcpc.c85
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...) */
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)