udhcp: finish support of classless static routes (now the correct patch!)
No binary (build failed)
—
(log yok)
| @@ -57,13 +57,13 @@ const struct dhcp_optflag dhcp_optflags[] = { | |
| { OPTION_DNS_STRING | OPTION_LIST , 0x77 }, /* DHCP_DOMAIN_SEARCH */ | |
| { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ | |
| #endif | |
| - | { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ |
| + | { OPTION_STATIC_ROUTES | OPTION_LIST , 0x79 }, /* DHCP_STATIC_ROUTES */ |
| #if ENABLE_FEATURE_UDHCP_8021Q | |
| { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */ | |
| { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ | |
| #endif | |
| { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ | |
| - | { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ |
| + | { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ |
| { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ | |
| /* Options below have no match in dhcp_option_strings[], | |
| @@ -123,8 +123,6 @@ const char dhcp_option_strings[] ALIGN1 = | |
| // is not handled yet by "string->option" conversion code: | |
| "sipsrv" "\0" /* DHCP_SIP_SERVERS */ | |
| #endif | |
| - | // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES |
| - | // is not handled yet by "string->option" conversion code: |
| "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ | |
| #if ENABLE_FEATURE_UDHCP_8021Q | |
| "vlanid" "\0" /* DHCP_VLAN_ID */ | |
| @@ -338,7 +336,8 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | |
| lsa = host_and_af2sockaddr(str, 0, AF_INET); | |
| if (!lsa) | |
| return 0; | |
| - | *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr; |
| + | /* arg maybe unaligned */ |
| + | move_to_unaligned32((uint32_t*)arg, lsa->u.sin.sin_addr.s_addr); |
| free(lsa); | |
| return 1; | |
| } | |
| @@ -437,13 +436,14 @@ static NOINLINE void attach_option( | |
| int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |
| { | |
| struct option_set **opt_list = arg; | |
| - | char *opt, *val, *endptr; |
| + | char *opt, *val; |
| char *str; | |
| const struct dhcp_optflag *optflag; | |
| struct dhcp_optflag bin_optflag; | |
| unsigned optcode; | |
| int retval, length; | |
| - | char buffer[8] ALIGNED(4); |
| + | /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */ |
| + | char buffer[9] ALIGNED(4); |
| uint16_t *result_u16 = (uint16_t *) buffer; | |
| uint32_t *result_u32 = (uint32_t *) buffer; | |
| @@ -501,34 +501,53 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |
| // break; | |
| // } | |
| case OPTION_U8: | |
| - | buffer[0] = strtoul(val, &endptr, 0); |
| - | retval = (endptr[0] == '\0'); |
| + | buffer[0] = bb_strtou32(val, NULL, 0); |
| + | retval = (errno == 0); |
| break; | |
| /* htonX are macros in older libc's, using temp var | |
| * in code below for safety */ | |
| /* TODO: use bb_strtoX? */ | |
| case OPTION_U16: { | |
| - | unsigned long tmp = strtoul(val, &endptr, 0); |
| + | uint32_t tmp = bb_strtou32(val, NULL, 0); |
| *result_u16 = htons(tmp); | |
| - | retval = (endptr[0] == '\0' /*&& tmp < 0x10000*/); |
| + | retval = (errno == 0 /*&& tmp < 0x10000*/); |
| break; | |
| } | |
| // case OPTION_S16: { | |
| - | // long tmp = strtol(val, &endptr, 0); |
| + | // long tmp = bb_strtoi32(val, NULL, 0); |
| // *result_u16 = htons(tmp); | |
| - | // retval = (endptr[0] == '\0'); |
| + | // retval = (errno == 0); |
| // break; | |
| // } | |
| case OPTION_U32: { | |
| - | unsigned long tmp = strtoul(val, &endptr, 0); |
| + | uint32_t tmp = bb_strtou32(val, NULL, 0); |
| *result_u32 = htonl(tmp); | |
| - | retval = (endptr[0] == '\0'); |
| + | retval = (errno == 0); |
| break; | |
| } | |
| case OPTION_S32: { | |
| - | long tmp = strtol(val, &endptr, 0); |
| + | int32_t tmp = bb_strtoi32(val, NULL, 0); |
| *result_u32 = htonl(tmp); | |
| - | retval = (endptr[0] == '\0'); |
| + | retval = (errno == 0); |
| + | break; |
| + | } |
| + | case OPTION_STATIC_ROUTES: { |
| + | /* Input: "a.b.c.d/m" */ |
| + | /* Output: mask(1 byte),pfx(0-4 bytes),gw(4 bytes) */ |
| + | unsigned mask; |
| + | char *slash = strchr(val, '/'); |
| + | if (slash) { |
| + | *slash = '\0'; |
| + | retval = udhcp_str2nip(val, buffer + 1); |
| + | buffer[0] = mask = bb_strtou(slash + 1, NULL, 10); |
| + | val = strtok(NULL, ", \t/-"); |
| + | if (!val || mask > 32 || errno) |
| + | retval = 0; |
| + | if (retval) { |
| + | length = ((mask + 7) >> 3) + 5; |
| + | retval = udhcp_str2nip(val, buffer + (length - 4)); |
| + | } |
| + | } |
| break; | |
| } | |
| case OPTION_BIN: /* handled in attach_option() */ | |
| @@ -539,7 +558,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | |
| } | |
| if (retval) | |
| attach_option(opt_list, optflag, opt, length); | |
| - | } while (retval && optflag->flags & OPTION_LIST); |
| + | } while (retval && (optflag->flags & OPTION_LIST)); |
| return retval; | |
| } | |