udhcpc: support option 0x79 (static routes) (part of bug 341)
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 3 Jul 2009 16:14:03 +0000 (18:14 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 3 Jul 2009 16:14:03 +0000 (18:14 +0200)
function                                             old     new   delta
xmalloc_optname_optval                                 -     583    +583
dhcp_option_strings                                  258     266      +8
dhcp_options                                          70      72      +2
len_of_option_as_string                               11      12      +1
dhcp_option_lengths                                   11      12      +1
udhcp_run_script                                    1187     669    -518
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/1 up/down: 595/-518)           Total: 77 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/udhcp/options.c
networking/udhcp/options.h
networking/udhcp/script.c

index 76d6e373703e91bc33a4229ea716dc5889bea6bb..ddb894432c6bff0066187e01eed2a8657a6e5ddc 100644 (file)
@@ -48,6 +48,7 @@ const struct dhcp_option dhcp_options[] = {
 #if ENABLE_FEATURE_UDHCP_RFC3397
        { OPTION_STR1035 | OPTION_LIST            , 0x77 }, /* search             */
 #endif
+       { OPTION_STATIC_ROUTES                    , 0x79 }, /* DHCP_STATIC_ROUTES */
        /* MSIE's "Web Proxy Autodiscovery Protocol" support */
        { OPTION_STRING                           , 0xfc }, /* wpad               */
 
@@ -97,6 +98,7 @@ const char dhcp_option_strings[] ALIGN1 =
 #if ENABLE_FEATURE_UDHCP_RFC3397
        "search" "\0"
 #endif
+       "staticroutes" "\0" /* DHCP_STATIC_ROUTES  */
        /* MSIE's "Web Proxy Autodiscovery Protocol" support */
        "wpad" "\0"
        ;
@@ -116,6 +118,8 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = {
        [OPTION_S16] =     2,
        [OPTION_U32] =     4,
        [OPTION_S32] =     4,
+       /* Just like OPTION_STRING, we use minimum length here */
+       [OPTION_STATIC_ROUTES] = 5,
 };
 
 
index 9e624318f6b6e23dc79a62a8c5746cefb934609b..aeed3690737e31bcb29b5cf170ab0d8640820366 100644 (file)
@@ -20,6 +20,7 @@ enum {
        OPTION_S16,
        OPTION_U32,
        OPTION_S32,
+       OPTION_STATIC_ROUTES,
 };
 
 /* Client requests this option by default */
@@ -68,6 +69,7 @@ enum {
 #define DHCP_VENDOR             0x3c
 #define DHCP_CLIENT_ID          0x3d
 #define DHCP_FQDN               0x51
+#define DHCP_STATIC_ROUTES      0x79
 #define DHCP_END                0xFF
 /* Offsets in option byte sequence */
 #define OPT_CODE                0
index 94dabf4d17058a6637d473041a773b5ffd5badf1..f315008a33f51bad533ffa258f4fd444572f8648 100644 (file)
@@ -17,6 +17,7 @@
 static const uint8_t len_of_option_as_string[] = {
        [OPTION_IP] =           sizeof("255.255.255.255 "),
        [OPTION_IP_PAIR] =      sizeof("255.255.255.255 ") * 2,
+       [OPTION_STATIC_ROUTES]= sizeof("255.255.255.255/32 255.255.255.255 "),
        [OPTION_STRING] =       1,
 #if ENABLE_FEATURE_UDHCP_RFC3397
        [OPTION_STR1035] =      1,
@@ -51,7 +52,7 @@ static int mton(uint32_t mask)
 
 
 /* Create "opt_name=opt_value" string */
-static char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name)
+static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *type_p, const char *opt_name)
 {
        unsigned upper_length;
        int len, type, optlen;
@@ -106,6 +107,50 @@ static char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_option *t
                        memcpy(dest, option, len);
                        dest[len] = '\0';
                        return ret;      /* Short circuit this case */
+               case OPTION_STATIC_ROUTES: {
+                       /* Option binary format:
+                        * mask [one byte, 0..32]
+                        * ip [big endian, 0..4 bytes depending on mask]
+                        * router [big endian, 4 bytes]
+                        * may be repeated
+                        *
+                        * We convert it to a string "IP/MASK ROUTER IP2/MASK2 ROUTER2"
+                        */
+                       const char *pfx = "";
+
+                       while (len >= 1 + 4) { /* mask + 0-byte ip + router */
+                               uint32_t nip;
+                               uint8_t *p;
+                               unsigned mask;
+                               int bytes;
+
+                               mask = *option++;
+                               if (mask > 32)
+                                       break;
+                               len--;
+
+                               nip = 0;
+                               p = (void*) &nip;
+                               bytes = (mask + 7) / 8; /* 0 -> 0, 1..8 -> 1, 9..16 -> 2 etc */
+                               while (--bytes >= 0) {
+                                       *p++ = *option++;
+                                       len--;
+                               }
+                               if (len < 4)
+                                       break;
+
+                               /* print ip/mask */
+                               dest += sprint_nip(dest, pfx, (void*) &nip);
+                               pfx = " ";
+                               dest += sprintf(dest, "/%u ", mask);
+                               /* print router */
+                               dest += sprint_nip(dest, "", option);
+                               option += 4;
+                               len -= 4;
+                       }
+
+                       return ret;
+               }
 #if ENABLE_FEATURE_UDHCP_RFC3397
                case OPTION_STR1035:
                        /* unpack option into dest; use ret for prefix (i.e., "optname=") */