From ee0f444f11504e47fc0f3ab6bc2bf95defb6e6ae Mon Sep 17 00:00:00 2001 From: Michael McTernan Date: Fri, 16 Dec 2011 17:10:09 +0100 Subject: [PATCH] udhcp: finish support of classless static routes (now the correct patch!) Signed-off-by: Michael McTernan Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 55 ++++++++++++++++++++++++++------------- 1 file 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; } -- 2.25.1