diff options
-rw-r--r-- | networking/udhcp/common.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index cf6b1ca91..ae0e0d306 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -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 */ |
@@ -338,7 +336,8 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | |||
338 | lsa = host_and_af2sockaddr(str, 0, AF_INET); | 336 | lsa = host_and_af2sockaddr(str, 0, AF_INET); |
339 | if (!lsa) | 337 | if (!lsa) |
340 | return 0; | 338 | return 0; |
341 | *(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); | ||
342 | free(lsa); | 341 | free(lsa); |
343 | return 1; | 342 | return 1; |
344 | } | 343 | } |
@@ -437,13 +436,14 @@ static NOINLINE void attach_option( | |||
437 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | 436 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) |
438 | { | 437 | { |
439 | struct option_set **opt_list = arg; | 438 | struct option_set **opt_list = arg; |
440 | char *opt, *val, *endptr; | 439 | char *opt, *val; |
441 | char *str; | 440 | char *str; |
442 | const struct dhcp_optflag *optflag; | 441 | const struct dhcp_optflag *optflag; |
443 | struct dhcp_optflag bin_optflag; | 442 | struct dhcp_optflag bin_optflag; |
444 | unsigned optcode; | 443 | unsigned optcode; |
445 | int retval, length; | 444 | int retval, length; |
446 | char buffer[8] ALIGNED(4); | 445 | /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */ |
446 | char buffer[9] ALIGNED(4); | ||
447 | uint16_t *result_u16 = (uint16_t *) buffer; | 447 | uint16_t *result_u16 = (uint16_t *) buffer; |
448 | uint32_t *result_u32 = (uint32_t *) buffer; | 448 | uint32_t *result_u32 = (uint32_t *) buffer; |
449 | 449 | ||
@@ -501,34 +501,53 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |||
501 | // break; | 501 | // break; |
502 | // } | 502 | // } |
503 | case OPTION_U8: | 503 | case OPTION_U8: |
504 | buffer[0] = strtoul(val, &endptr, 0); | 504 | buffer[0] = bb_strtou32(val, NULL, 0); |
505 | retval = (endptr[0] == '\0'); | 505 | retval = (errno == 0); |
506 | break; | 506 | break; |
507 | /* htonX are macros in older libc's, using temp var | 507 | /* htonX are macros in older libc's, using temp var |
508 | * in code below for safety */ | 508 | * in code below for safety */ |
509 | /* TODO: use bb_strtoX? */ | 509 | /* TODO: use bb_strtoX? */ |
510 | case OPTION_U16: { | 510 | case OPTION_U16: { |
511 | unsigned long tmp = strtoul(val, &endptr, 0); | 511 | uint32_t tmp = bb_strtou32(val, NULL, 0); |
512 | *result_u16 = htons(tmp); | 512 | *result_u16 = htons(tmp); |
513 | retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/); | 513 | retval = (errno == 0 /*&& tmp < 0x10000*/); |
514 | break; | 514 | break; |
515 | } | 515 | } |
516 | // case OPTION_S16: { | 516 | // case OPTION_S16: { |
517 | // long tmp = strtol(val, &endptr, 0); | 517 | // long tmp = bb_strtoi32(val, NULL, 0); |
518 | // *result_u16 = htons(tmp); | 518 | // *result_u16 = htons(tmp); |
519 | // retval = (endptr[0] == '\0'); | 519 | // retval = (errno == 0); |
520 | // break; | 520 | // break; |
521 | // } | 521 | // } |
522 | case OPTION_U32: { | 522 | case OPTION_U32: { |
523 | unsigned long tmp = strtoul(val, &endptr, 0); | 523 | uint32_t tmp = bb_strtou32(val, NULL, 0); |
524 | *result_u32 = htonl(tmp); | 524 | *result_u32 = htonl(tmp); |
525 | retval = (endptr[0] == '\0'); | 525 | retval = (errno == 0); |
526 | break; | 526 | break; |
527 | } | 527 | } |
528 | case OPTION_S32: { | 528 | case OPTION_S32: { |
529 | long tmp = strtol(val, &endptr, 0); | 529 | int32_t tmp = bb_strtoi32(val, NULL, 0); |
530 | *result_u32 = htonl(tmp); | 530 | *result_u32 = htonl(tmp); |
531 | 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 | } | ||
532 | break; | 551 | break; |
533 | } | 552 | } |
534 | case OPTION_BIN: /* handled in attach_option() */ | 553 | case OPTION_BIN: /* handled in attach_option() */ |
@@ -539,7 +558,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |||
539 | } | 558 | } |
540 | if (retval) | 559 | if (retval) |
541 | attach_option(opt_list, optflag, opt, length); | 560 | attach_option(opt_list, optflag, opt, length); |
542 | } while (retval && optflag->flags & OPTION_LIST); | 561 | } while (retval && (optflag->flags & OPTION_LIST)); |
543 | 562 | ||
544 | return retval; | 563 | return retval; |
545 | } | 564 | } |