aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h4
-rw-r--r--networking/udhcp/common.c3
-rw-r--r--networking/udhcp/common.h1
-rw-r--r--networking/udhcp/dhcpc.c80
4 files changed, 84 insertions, 4 deletions
diff --git a/include/libbb.h b/include/libbb.h
index f79b69365..f0f54ef82 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -814,9 +814,9 @@ void smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_F
814const char *make_human_readable_str(unsigned long long size, 814const char *make_human_readable_str(unsigned long long size,
815 unsigned long block_size, unsigned long display_unit) FAST_FUNC; 815 unsigned long block_size, unsigned long display_unit) FAST_FUNC;
816/* Put a string of hex bytes ("1b2e66fe"...), return advanced pointer */ 816/* Put a string of hex bytes ("1b2e66fe"...), return advanced pointer */
817char *bin2hex(char *buf, const char *cp, int count) FAST_FUNC; 817char *bin2hex(char *dst, const char *src, int count) FAST_FUNC;
818/* Reverse */ 818/* Reverse */
819char* hex2bin(char *dst, const char *str, int count) FAST_FUNC; 819char* hex2bin(char *dst, const char *src, int count) FAST_FUNC;
820 820
821/* Generate a UUID */ 821/* Generate a UUID */
822void generate_uuid(uint8_t *buf) FAST_FUNC; 822void generate_uuid(uint8_t *buf) FAST_FUNC;
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 70e34614c..ba41905cc 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -59,6 +59,7 @@ const struct dhcp_optflag dhcp_optflags[] = {
59 { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */ 59 { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */
60 { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ 60 { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */
61#endif 61#endif
62 { OPTION_6RD , 0xd4 }, /* DHCP_6RD */
62 { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ 63 { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */
63 { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ 64 { OPTION_STRING , 0xfc }, /* DHCP_WPAD */
64 65
@@ -126,6 +127,7 @@ const char dhcp_option_strings[] ALIGN1 =
126 "vlanid" "\0" /* DHCP_VLAN_ID */ 127 "vlanid" "\0" /* DHCP_VLAN_ID */
127 "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ 128 "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */
128#endif 129#endif
130 "ip6rd" "\0" /* DHCP_6RD */
129 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ 131 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
130 "wpad" "\0" /* DHCP_WPAD */ 132 "wpad" "\0" /* DHCP_WPAD */
131 ; 133 ;
@@ -154,6 +156,7 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = {
154 [OPTION_S32] = 4, 156 [OPTION_S32] = 4,
155 /* Just like OPTION_STRING, we use minimum length here */ 157 /* Just like OPTION_STRING, we use minimum length here */
156 [OPTION_STATIC_ROUTES] = 5, 158 [OPTION_STATIC_ROUTES] = 5,
159 [OPTION_6RD] = 22, /* ignored by udhcp_str2optset */
157}; 160};
158 161
159 162
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 786266810..da0bd38d1 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -88,6 +88,7 @@ enum {
88 OPTION_S32, 88 OPTION_S32,
89 OPTION_BIN, 89 OPTION_BIN,
90 OPTION_STATIC_ROUTES, 90 OPTION_STATIC_ROUTES,
91 OPTION_6RD,
91#if ENABLE_FEATURE_UDHCP_RFC3397 92#if ENABLE_FEATURE_UDHCP_RFC3397
92 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ 93 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */
93 OPTION_SIP_SERVERS, 94 OPTION_SIP_SERVERS,
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index ddfe3ccc0..311d4867a 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -100,6 +100,7 @@ static const uint8_t len_of_option_as_string[] = {
100 [OPTION_IP ] = sizeof("255.255.255.255 "), 100 [OPTION_IP ] = sizeof("255.255.255.255 "),
101 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 101 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2,
102 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 102 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "),
103 [OPTION_6RD ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "),
103 [OPTION_STRING ] = 1, 104 [OPTION_STRING ] = 1,
104#if ENABLE_FEATURE_UDHCP_RFC3397 105#if ENABLE_FEATURE_UDHCP_RFC3397
105 [OPTION_DNS_STRING ] = 1, /* unused */ 106 [OPTION_DNS_STRING ] = 1, /* unused */
@@ -123,6 +124,24 @@ static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
123 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); 124 return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
124} 125}
125 126
127static int sprint_nip6(char *dest, const char *pre, const uint8_t *ip)
128{
129 char hexstrbuf[16 * 2];
130 bin2hex(hexstrbuf, (void*)ip, 16);
131 return sprintf(dest, "%s"
132 "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
133 pre,
134 hexstrbuf + 0 * 4,
135 hexstrbuf + 1 * 4,
136 hexstrbuf + 2 * 4,
137 hexstrbuf + 3 * 4,
138 hexstrbuf + 4 * 4,
139 hexstrbuf + 5 * 4,
140 hexstrbuf + 6 * 4,
141 hexstrbuf + 7 * 4
142 );
143}
144
126/* really simple implementation, just count the bits */ 145/* really simple implementation, just count the bits */
127static int mton(uint32_t mask) 146static int mton(uint32_t mask)
128{ 147{
@@ -147,7 +166,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
147 166
148 type = optflag->flags & OPTION_TYPE_MASK; 167 type = optflag->flags & OPTION_TYPE_MASK;
149 optlen = dhcp_option_lengths[type]; 168 optlen = dhcp_option_lengths[type];
150 upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); 169 upper_length = len_of_option_as_string[type]
170 * ((unsigned)(len + optlen - 1) / (unsigned)optlen);
151 171
152 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); 172 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2);
153 dest += sprintf(ret, "%s=", opt_name); 173 dest += sprintf(ret, "%s=", opt_name);
@@ -232,6 +252,62 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
232 252
233 return ret; 253 return ret;
234 } 254 }
255 case OPTION_6RD: {
256 /* Option binary format (see RFC 5969):
257 * 0 1 2 3
258 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
259 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260 * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen |
261 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
262 * | |
263 * | 6rdPrefix |
264 * | (16 octets) |
265 * | |
266 * | |
267 * | |
268 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269 * | 6rdBRIPv4Address(es) |
270 * . .
271 * . .
272 * . .
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 *
275 * We convert it to a string
276 * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..."
277 */
278
279 /* Sanity check: ensure that our length is at least 22 bytes, that
280 * IPv4MaskLen <= 32,
281 * 6rdPrefixLen <= 128,
282 * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128
283 * (2nd condition need no check - it follows from 1st and 3rd).
284 * If any of these requirements is not fulfilled, return with empty
285 * value.
286 */
287 if (len >= 22
288 && option[0] <= 32
289 && (option[1] + 32 - option[0]) <= 128
290 ) {
291 /* IPv4MaskLen */
292 dest += sprintf(dest, "%u ", *option++);
293 /* 6rdPrefixLen */
294 dest += sprintf(dest, "%u ", *option++);
295 /* 6rdPrefix */
296 dest += sprint_nip6(dest, "", option);
297 option += 16;
298 len -= 1 + 1 + 16;
299 /* 6rdBRIPv4Address(es) */
300 while (1) {
301 dest += sprint_nip(dest, " ", option);
302 option += 4;
303 len -= 4;
304 if (len < 0)
305 break;
306 }
307 }
308
309 return ret;
310 }
235#if ENABLE_FEATURE_UDHCP_RFC3397 311#if ENABLE_FEATURE_UDHCP_RFC3397
236 case OPTION_DNS_STRING: 312 case OPTION_DNS_STRING:
237 /* unpack option into dest; use ret for prefix (i.e., "optname=") */ 313 /* unpack option into dest; use ret for prefix (i.e., "optname=") */
@@ -394,7 +470,7 @@ static char **fill_envp(struct dhcp_packet *packet)
394 len = temp[-OPT_DATA + OPT_LEN]; 470 len = temp[-OPT_DATA + OPT_LEN];
395 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); 471 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2);
396 ofs = sprintf(*curr, "opt%u=", i); 472 ofs = sprintf(*curr, "opt%u=", i);
397 bin2hex(*curr + ofs, (void*) temp, len)[0] = '\0'; 473 *bin2hex(*curr + ofs, (void*) temp, len) = '\0';
398 putenv(*curr++); 474 putenv(*curr++);
399 } 475 }
400 i++; 476 i++;