udhcp: finish support of classless static routes (now the correct patch!)

Signed-off-by: Michael McTernan <Michael.McTernan.2001@cs.bris.ac.uk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Michael McTernan 2011-12-16 17:10:09 +01:00 committed by Denys Vlasenko
parent 7b57ff4436
commit ee0f444f11

View File

@ -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;
}