dhcpcd: Update to Version 5.5.6

Change-Id: I98c378688be723a2a602ec17c26bc13f2fd83cc8
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/dhcp.c b/dhcp.c
index 1169993..c22e767 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -1,6 +1,6 @@
 /* 
  * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2010 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,7 @@
 #define RFC3361	(1 << 10)
 #define RFC3397	(1 << 11)
 #define RFC3442 (1 << 12)
+#define RFC5969 (1 << 13)
 
 #define IPV4R	IPV4 | REQUEST
 
@@ -163,6 +164,8 @@
 	{ 114,	STRING,		"default_url" },
 	{ 118,	IPV4,		"subnet_selection" },
 	{ 119,	STRING | RFC3397,	"domain_search" },
+	{ 120,	STRING | RFC3361,	"sip_server" },
+	{ 212,  RFC5969,	"sixrd" },
 	{ 0, 0, NULL }
 };
 
@@ -270,18 +273,17 @@
 			*type = opt->type;
 
 		if (opt->type == 0 ||
-		    opt->type & STRING ||
-		    opt->type & RFC3442)
+		    opt->type & (STRING | RFC3442 | RFC5969))
 			return 0;
 
 		sz = 0;
-		if (opt->type & UINT32 || opt->type & IPV4)
+		if (opt->type & (UINT32 | IPV4))
 			sz = sizeof(uint32_t);
 		if (opt->type & UINT16)
 			sz = sizeof(uint16_t);
 		if (opt->type & UINT8)
 			sz = sizeof(uint8_t);
-		if (opt->type & IPV4 || opt->type & ARRAY)
+		if (opt->type & (IPV4 | ARRAY))
 			return dl % sz;
 		return (dl == sz ? 0 : -1);
 	}
@@ -428,7 +430,7 @@
  * separated string. Returns length of string (including
  * terminating zero) or zero on error. out may be NULL
  * to just determine output length. */
-static ssize_t
+ssize_t
 decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p)
 {
 	const uint8_t *r, *q = p;
@@ -624,11 +626,11 @@
 		addr.s_addr = INADDR_BROADCAST;
 		l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1;
 		sip = p = xmalloc(l);
-		while (l != 0) {
+		while (dl != 0) {
 			memcpy(&addr.s_addr, data, sizeof(addr.s_addr));
 			data += sizeof(addr.s_addr);
 			p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr));
-			l -= sizeof(addr.s_addr);
+			dl -= sizeof(addr.s_addr);
 		}
 		*--p = '\0';
 		break;
@@ -640,6 +642,74 @@
 	return sip;
 }
 
+/* Decode an RFC5969 6rd order option into a space
+ * separated string. Returns length of string (including
+ * terminating zero) or zero on error. */
+static ssize_t
+decode_rfc5969(char *out, ssize_t len, int pl, const uint8_t *p)
+{
+	uint8_t ipv4masklen, ipv6prefixlen;
+	uint8_t ipv6prefix[16];
+	uint8_t br[4];
+	int i;
+	ssize_t b, bytes = 0;
+
+	if (pl < 22) {
+		errno = EINVAL;
+		return 0;
+	}
+	
+	ipv4masklen = *p++;
+	pl--;
+	ipv6prefixlen = *p++;
+	pl--;
+	
+	for (i = 0; i < 16; i++) {
+		ipv6prefix[i] = *p++;
+		pl--;
+	}
+	if (out) {
+		b= snprintf(out, len,
+		    "%d %d "
+		    "%02x%02x:%02x%02x:"
+		    "%02x%02x:%02x%02x:"
+		    "%02x%02x:%02x%02x:"
+		    "%02x%02x:%02x%02x",
+		    ipv4masklen, ipv6prefixlen,
+		    ipv6prefix[0], ipv6prefix[1], ipv6prefix[2], ipv6prefix[3],
+		    ipv6prefix[4], ipv6prefix[5], ipv6prefix[6], ipv6prefix[7],
+		    ipv6prefix[8], ipv6prefix[9], ipv6prefix[10],ipv6prefix[11],
+		    ipv6prefix[12],ipv6prefix[13],ipv6prefix[14], ipv6prefix[15]
+		);
+		    
+		len -= b;
+		out += b;
+		bytes += b;
+	} else {
+		bytes += 16 * 2 + 8 + 2 + 1 + 2;
+	}
+
+	while (pl >= 4) {
+		br[0] = *p++;
+		br[1] = *p++;
+		br[2] = *p++;
+		br[3] = *p++;
+		pl -= 4;
+		
+		if (out) {
+			b= snprintf(out, len, " %d.%d.%d.%d",
+			    br[0], br[1], br[2], br[3]);
+			len -= b;
+			out += b;
+			bytes += b;
+		} else {
+			bytes += (4 * 4);
+		}
+	}
+	
+	return bytes;
+}
+
 char *
 get_option_string(const struct dhcp_message *dhcp, uint8_t option)
 {
@@ -706,7 +776,7 @@
  * Otherwise we add static routes and then routers. */
 struct rt *
 get_option_routes(const struct dhcp_message *dhcp,
-    const char *ifname, int *opts)
+    const char *ifname, unsigned long long *opts)
 {
 	const uint8_t *p;
 	const uint8_t *e;
@@ -721,11 +791,13 @@
 		p = get_option(dhcp, DHO_MSCSR, &len, NULL);
 	if (p) {
 		routes = decode_rfc3442_rt(len, p);
-		if (routes && !(*opts & DHCPCD_CSR_WARNED)) {
-			syslog(LOG_DEBUG,
-			    "%s: using Classless Static Routes (RFC3442)",
-			    ifname);
-			*opts |= DHCPCD_CSR_WARNED;
+		if (routes) {
+			if (!(*opts & DHCPCD_CSR_WARNED)) {
+				syslog(LOG_DEBUG,
+				    "%s: using Classless Static Routes",
+				    ifname);
+				*opts |= DHCPCD_CSR_WARNED;
+			}
 			return routes;
 		}
 	}
@@ -1154,7 +1226,9 @@
 		case '\'': /* FALLTHROUGH */
 		case '$':  /* FALLTHROUGH */
 		case '`':  /* FALLTHROUGH */
- 		case '\\':
+ 		case '\\': /* FALLTHROUGH */
+		case '|':  /* FALLTHROUGH */
+		case '&':
 			if (s) {
 				if (len < 3) {
 					errno = ENOBUFS;
@@ -1204,9 +1278,21 @@
 		return l;
 	}
 
+	if (type & RFC3361) {
+		if ((tmp = decode_rfc3361(dl, data)) == NULL)
+			return -1;
+		l = strlen(tmp);
+		l = print_string(s, len, l - 1, (uint8_t *)tmp);
+		free(tmp);
+		return l;
+	}
+
 	if (type & RFC3442)
 		return decode_rfc3442(s, len, dl, data);
 
+	if (type & RFC5969)
+		return decode_rfc5969(s, len, dl, data);
+
 	if (type & STRING) {
 		/* Some DHCP servers return NULL strings */
 		if (*data == '\0')
@@ -1284,16 +1370,6 @@
 	return bytes;
 }
 
-static void
-setvar(char ***e, const char *prefix, const char *var, const char *value)
-{
-	size_t len = strlen(prefix) + strlen(var) + strlen(value) + 4;
-
-	**e = xmalloc(len);
-	snprintf(**e, len, "%s_%s=%s", prefix, var, value);
-	(*e)++;
-}
-
 ssize_t
 configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
     const struct if_options *ifo)