udhcp: finish support of classless static routes (now the correct patch!)
authorMichael McTernan <Michael.McTernan.2001@cs.bris.ac.uk>
Fri, 16 Dec 2011 16:10:09 +0000 (17:10 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 16 Dec 2011 16:10:09 +0000 (17:10 +0100)
Signed-off-by: Michael McTernan <Michael.McTernan.2001@cs.bris.ac.uk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/udhcp/common.c

index cf6b1ca91d9a5f3a1ff9c1ae3fe4be8b63918e6f..ae0e0d30637092d94d4dd5db8161ed0b1093f08c 100644 (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;
 }