aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/common.c55
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[] = {
{ 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;
}