{ 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_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */
{ 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[],
// 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 */
"vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */
#endif
+ "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */
"ip6rd" "\0" /* DHCP_6RD */
"msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */
"wpad" "\0" /* DHCP_WPAD */
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;
}
char *buffer,
int length)
{
- struct option_set *existing, *new, **curr;
- char *allocated = NULL;
+ struct option_set *existing;
+ char *allocated;
- existing = udhcp_find_option(*opt_list, optflag->code);
- if (!existing) {
- log2("Attaching option %02x to list", optflag->code);
- allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
+ allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
#if ENABLE_FEATURE_UDHCP_RFC3397
- if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
- /* reuse buffer and length for RFC1035-formatted string */
- allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length);
- }
+ if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
+ /* reuse buffer and length for RFC1035-formatted string */
+ allocated = buffer = (char *)dname_enc(NULL, 0, buffer, &length);
+ }
#endif
+
+ existing = udhcp_find_option(*opt_list, optflag->code);
+ if (!existing) {
+ struct option_set *new, **curr;
+
/* make a new option */
+ log2("Attaching option %02x to list", optflag->code);
new = xmalloc(sizeof(*new));
new->data = xmalloc(length + OPT_DATA);
new->data[OPT_CODE] = optflag->code;
/* add it to an existing option */
log2("Attaching option %02x to existing member of list", optflag->code);
- allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
old_len = existing->data[OPT_LEN];
-#if ENABLE_FEATURE_UDHCP_RFC3397
- if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
- /* reuse buffer and length for RFC1035-formatted string */
- allocated = buffer = (char *)dname_enc(existing->data + OPT_DATA, old_len, buffer, &length);
- }
-#endif
if (old_len + length < 255) {
/* actually 255 is ok too, but adding a space can overlow it */
existing->data[OPT_DATA + old_len] = ' ';
old_len++;
}
- memcpy(existing->data + OPT_DATA + old_len, buffer, length);
+ memcpy(existing->data + OPT_DATA + old_len, (allocated ? allocated : buffer), length);
existing->data[OPT_LEN] = old_len + length;
} /* else, ignore the data, we could put this in a second option in the future */
} /* else, ignore the new data */
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;
// 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() */
}
if (retval)
attach_option(opt_list, optflag, opt, length);
- } while (retval && optflag->flags & OPTION_LIST);
+ } while (retval && (optflag->flags & OPTION_LIST));
return retval;
}