diff options
-rw-r--r-- | include/libbb.h | 4 | ||||
-rw-r--r-- | networking/udhcp/common.c | 3 | ||||
-rw-r--r-- | networking/udhcp/common.h | 1 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 80 |
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 | |||
814 | const char *make_human_readable_str(unsigned long long size, | 814 | const 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 */ |
817 | char *bin2hex(char *buf, const char *cp, int count) FAST_FUNC; | 817 | char *bin2hex(char *dst, const char *src, int count) FAST_FUNC; |
818 | /* Reverse */ | 818 | /* Reverse */ |
819 | char* hex2bin(char *dst, const char *str, int count) FAST_FUNC; | 819 | char* hex2bin(char *dst, const char *src, int count) FAST_FUNC; |
820 | 820 | ||
821 | /* Generate a UUID */ | 821 | /* Generate a UUID */ |
822 | void generate_uuid(uint8_t *buf) FAST_FUNC; | 822 | void 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 | ||
127 | static 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 */ |
127 | static int mton(uint32_t mask) | 146 | static 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++; |