udhcpc: support option 0x79 (static routes) (part of bug 341)
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>
diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c
index 76d6e37..ddb8944 100644
--- a/networking/udhcp/options.c
+++ b/networking/udhcp/options.c
@@ -48,6 +48,7 @@
#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 @@
#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 @@
[OPTION_S16] = 2,
[OPTION_U32] = 4,
[OPTION_S32] = 4,
+ /* Just like OPTION_STRING, we use minimum length here */
+ [OPTION_STATIC_ROUTES] = 5,
};
diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h
index 9e62431..aeed369 100644
--- a/networking/udhcp/options.h
+++ b/networking/udhcp/options.h
@@ -20,6 +20,7 @@
OPTION_S16,
OPTION_U32,
OPTION_S32,
+ OPTION_STATIC_ROUTES,
};
/* Client requests this option by default */
@@ -68,6 +69,7 @@
#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
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c
index 94dabf4..f315008 100644
--- a/networking/udhcp/script.c
+++ b/networking/udhcp/script.c
@@ -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 @@
/* 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 @@
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=") */