diff options
Diffstat (limited to 'networking/udhcp/common.c')
-rw-r--r-- | networking/udhcp/common.c | 88 |
1 files changed, 65 insertions, 23 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 2e6113627..ae0e0d306 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -29,9 +29,9 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
29 | // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ | 29 | // { OPTION_IP | OPTION_LIST , 0x07 }, /* DHCP_LOG_SERVER */ |
30 | // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ | 30 | // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ |
31 | { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ | 31 | { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ |
32 | { OPTION_STRING | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ | 32 | { OPTION_STRING_HOST | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ |
33 | { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ | 33 | { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ |
34 | { OPTION_STRING | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ | 34 | { OPTION_STRING_HOST | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ |
35 | { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ | 35 | { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ |
36 | { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ | 36 | { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ |
37 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ | 37 | { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ |
@@ -41,7 +41,7 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
41 | //server would let us know anyway? | 41 | //server would let us know anyway? |
42 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ | 42 | { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ |
43 | { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ | 43 | { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ |
44 | { OPTION_STRING , 0x28 }, /* DHCP_NIS_DOMAIN */ | 44 | { OPTION_STRING_HOST , 0x28 }, /* DHCP_NIS_DOMAIN */ |
45 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ | 45 | { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ |
46 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ | 46 | { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ |
47 | { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ | 47 | { OPTION_IP | OPTION_LIST , 0x2c }, /* DHCP_WINS_SERVER */ |
@@ -49,7 +49,7 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
49 | { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ | 49 | { OPTION_IP , 0x36 }, /* DHCP_SERVER_ID */ |
50 | { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ | 50 | { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ |
51 | //TODO: must be combined with 'sname' and 'file' handling: | 51 | //TODO: must be combined with 'sname' and 'file' handling: |
52 | { OPTION_STRING , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ | 52 | { OPTION_STRING_HOST , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ |
53 | { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ | 53 | { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ |
54 | //TODO: not a string, but a set of LASCII strings: | 54 | //TODO: not a string, but a set of LASCII strings: |
55 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ | 55 | // { OPTION_STRING , 0x4D }, /* DHCP_USER_CLASS */ |
@@ -57,13 +57,13 @@ const struct dhcp_optflag dhcp_optflags[] = { | |||
57 | { OPTION_DNS_STRING | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ | 57 | { OPTION_DNS_STRING | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ |
58 | { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ | 58 | { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ |
59 | #endif | 59 | #endif |
60 | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ | 60 | { OPTION_STATIC_ROUTES | OPTION_LIST , 0x79 }, /* DHCP_STATIC_ROUTES */ |
61 | #if ENABLE_FEATURE_UDHCP_8021Q | 61 | #if ENABLE_FEATURE_UDHCP_8021Q |
62 | { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */ | 62 | { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */ |
63 | { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ | 63 | { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ |
64 | #endif | 64 | #endif |
65 | { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ | 65 | { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ |
66 | { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ | 66 | { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ |
67 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | 67 | { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ |
68 | 68 | ||
69 | /* Options below have no match in dhcp_option_strings[], | 69 | /* Options below have no match in dhcp_option_strings[], |
@@ -123,8 +123,6 @@ const char dhcp_option_strings[] ALIGN1 = | |||
123 | // is not handled yet by "string->option" conversion code: | 123 | // is not handled yet by "string->option" conversion code: |
124 | "sipsrv" "\0" /* DHCP_SIP_SERVERS */ | 124 | "sipsrv" "\0" /* DHCP_SIP_SERVERS */ |
125 | #endif | 125 | #endif |
126 | // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES | ||
127 | // is not handled yet by "string->option" conversion code: | ||
128 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | 126 | "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ |
129 | #if ENABLE_FEATURE_UDHCP_8021Q | 127 | #if ENABLE_FEATURE_UDHCP_8021Q |
130 | "vlanid" "\0" /* DHCP_VLAN_ID */ | 128 | "vlanid" "\0" /* DHCP_VLAN_ID */ |
@@ -148,6 +146,7 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = { | |||
148 | [OPTION_IP_PAIR] = 8, | 146 | [OPTION_IP_PAIR] = 8, |
149 | // [OPTION_BOOLEAN] = 1, | 147 | // [OPTION_BOOLEAN] = 1, |
150 | [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */ | 148 | [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */ |
149 | [OPTION_STRING_HOST] = 1, /* ignored by udhcp_str2optset */ | ||
151 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 150 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
152 | [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */ | 151 | [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */ |
153 | [OPTION_SIP_SERVERS] = 1, | 152 | [OPTION_SIP_SERVERS] = 1, |
@@ -337,7 +336,8 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | |||
337 | lsa = host_and_af2sockaddr(str, 0, AF_INET); | 336 | lsa = host_and_af2sockaddr(str, 0, AF_INET); |
338 | if (!lsa) | 337 | if (!lsa) |
339 | return 0; | 338 | return 0; |
340 | *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr; | 339 | /* arg maybe unaligned */ |
340 | move_to_unaligned32((uint32_t*)arg, lsa->u.sin.sin_addr.s_addr); | ||
341 | free(lsa); | 341 | free(lsa); |
342 | return 1; | 342 | return 1; |
343 | } | 343 | } |
@@ -417,7 +417,9 @@ static NOINLINE void attach_option( | |||
417 | /* actually 255 is ok too, but adding a space can overlow it */ | 417 | /* actually 255 is ok too, but adding a space can overlow it */ |
418 | 418 | ||
419 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); | 419 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); |
420 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING) { | 420 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING |
421 | || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST | ||
422 | ) { | ||
421 | /* add space separator between STRING options in a list */ | 423 | /* add space separator between STRING options in a list */ |
422 | existing->data[OPT_DATA + old_len] = ' '; | 424 | existing->data[OPT_DATA + old_len] = ' '; |
423 | old_len++; | 425 | old_len++; |
@@ -434,13 +436,14 @@ static NOINLINE void attach_option( | |||
434 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | 436 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) |
435 | { | 437 | { |
436 | struct option_set **opt_list = arg; | 438 | struct option_set **opt_list = arg; |
437 | char *opt, *val, *endptr; | 439 | char *opt, *val; |
438 | char *str; | 440 | char *str; |
439 | const struct dhcp_optflag *optflag; | 441 | const struct dhcp_optflag *optflag; |
440 | struct dhcp_optflag bin_optflag; | 442 | struct dhcp_optflag bin_optflag; |
441 | unsigned optcode; | 443 | unsigned optcode; |
442 | int retval, length; | 444 | int retval, length; |
443 | char buffer[8] ALIGNED(4); | 445 | /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */ |
446 | char buffer[9] ALIGNED(4); | ||
444 | uint16_t *result_u16 = (uint16_t *) buffer; | 447 | uint16_t *result_u16 = (uint16_t *) buffer; |
445 | uint32_t *result_u32 = (uint32_t *) buffer; | 448 | uint32_t *result_u32 = (uint32_t *) buffer; |
446 | 449 | ||
@@ -481,6 +484,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |||
481 | retval = udhcp_str2nip(val, buffer + 4); | 484 | retval = udhcp_str2nip(val, buffer + 4); |
482 | break; | 485 | break; |
483 | case OPTION_STRING: | 486 | case OPTION_STRING: |
487 | case OPTION_STRING_HOST: | ||
484 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 488 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
485 | case OPTION_DNS_STRING: | 489 | case OPTION_DNS_STRING: |
486 | #endif | 490 | #endif |
@@ -497,34 +501,53 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |||
497 | // break; | 501 | // break; |
498 | // } | 502 | // } |
499 | case OPTION_U8: | 503 | case OPTION_U8: |
500 | buffer[0] = strtoul(val, &endptr, 0); | 504 | buffer[0] = bb_strtou32(val, NULL, 0); |
501 | retval = (endptr[0] == '\0'); | 505 | retval = (errno == 0); |
502 | break; | 506 | break; |
503 | /* htonX are macros in older libc's, using temp var | 507 | /* htonX are macros in older libc's, using temp var |
504 | * in code below for safety */ | 508 | * in code below for safety */ |
505 | /* TODO: use bb_strtoX? */ | 509 | /* TODO: use bb_strtoX? */ |
506 | case OPTION_U16: { | 510 | case OPTION_U16: { |
507 | unsigned long tmp = strtoul(val, &endptr, 0); | 511 | uint32_t tmp = bb_strtou32(val, NULL, 0); |
508 | *result_u16 = htons(tmp); | 512 | *result_u16 = htons(tmp); |
509 | retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/); | 513 | retval = (errno == 0 /*&& tmp < 0x10000*/); |
510 | break; | 514 | break; |
511 | } | 515 | } |
512 | // case OPTION_S16: { | 516 | // case OPTION_S16: { |
513 | // long tmp = strtol(val, &endptr, 0); | 517 | // long tmp = bb_strtoi32(val, NULL, 0); |
514 | // *result_u16 = htons(tmp); | 518 | // *result_u16 = htons(tmp); |
515 | // retval = (endptr[0] == '\0'); | 519 | // retval = (errno == 0); |
516 | // break; | 520 | // break; |
517 | // } | 521 | // } |
518 | case OPTION_U32: { | 522 | case OPTION_U32: { |
519 | unsigned long tmp = strtoul(val, &endptr, 0); | 523 | uint32_t tmp = bb_strtou32(val, NULL, 0); |
520 | *result_u32 = htonl(tmp); | 524 | *result_u32 = htonl(tmp); |
521 | retval = (endptr[0] == '\0'); | 525 | retval = (errno == 0); |
522 | break; | 526 | break; |
523 | } | 527 | } |
524 | case OPTION_S32: { | 528 | case OPTION_S32: { |
525 | long tmp = strtol(val, &endptr, 0); | 529 | int32_t tmp = bb_strtoi32(val, NULL, 0); |
526 | *result_u32 = htonl(tmp); | 530 | *result_u32 = htonl(tmp); |
527 | retval = (endptr[0] == '\0'); | 531 | retval = (errno == 0); |
532 | break; | ||
533 | } | ||
534 | case OPTION_STATIC_ROUTES: { | ||
535 | /* Input: "a.b.c.d/m" */ | ||
536 | /* Output: mask(1 byte),pfx(0-4 bytes),gw(4 bytes) */ | ||
537 | unsigned mask; | ||
538 | char *slash = strchr(val, '/'); | ||
539 | if (slash) { | ||
540 | *slash = '\0'; | ||
541 | retval = udhcp_str2nip(val, buffer + 1); | ||
542 | buffer[0] = mask = bb_strtou(slash + 1, NULL, 10); | ||
543 | val = strtok(NULL, ", \t/-"); | ||
544 | if (!val || mask > 32 || errno) | ||
545 | retval = 0; | ||
546 | if (retval) { | ||
547 | length = ((mask + 7) >> 3) + 5; | ||
548 | retval = udhcp_str2nip(val, buffer + (length - 4)); | ||
549 | } | ||
550 | } | ||
528 | break; | 551 | break; |
529 | } | 552 | } |
530 | case OPTION_BIN: /* handled in attach_option() */ | 553 | case OPTION_BIN: /* handled in attach_option() */ |
@@ -535,7 +558,26 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |||
535 | } | 558 | } |
536 | if (retval) | 559 | if (retval) |
537 | attach_option(opt_list, optflag, opt, length); | 560 | attach_option(opt_list, optflag, opt, length); |
538 | } while (retval && optflag->flags & OPTION_LIST); | 561 | } while (retval && (optflag->flags & OPTION_LIST)); |
539 | 562 | ||
540 | return retval; | 563 | return retval; |
541 | } | 564 | } |
565 | |||
566 | /* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ | ||
567 | int FAST_FUNC sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) | ||
568 | { | ||
569 | char hexstrbuf[16 * 2]; | ||
570 | bin2hex(hexstrbuf, (void*)ip, 16); | ||
571 | return sprintf(dest, /* "%s" */ | ||
572 | "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s", | ||
573 | /* pre, */ | ||
574 | hexstrbuf + 0 * 4, | ||
575 | hexstrbuf + 1 * 4, | ||
576 | hexstrbuf + 2 * 4, | ||
577 | hexstrbuf + 3 * 4, | ||
578 | hexstrbuf + 4 * 4, | ||
579 | hexstrbuf + 5 * 4, | ||
580 | hexstrbuf + 6 * 4, | ||
581 | hexstrbuf + 7 * 4 | ||
582 | ); | ||
583 | } | ||