From: Markus Stenberg <markus.stenberg@iki.fi>
Date: Tue, 26 Mar 2013 13:12:50 +0000 (+0200)
Subject: First hnet-based version.
X-Git-Tag: debian/1.1+git20160131-1~133^2~7
X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=4ad21618ad863b5f590ed00f2c7677605a98e39f;p=odhcp6c.git

First hnet-based version.
---

diff --git a/README b/README
index 5555a83..2a7ab63 100644
--- a/README
+++ b/README
@@ -55,7 +55,7 @@ Environment:
 * SIP_DOMAIN		A space-separated list of SIP domains
 * OPTION_<num>	Custom option received as base-16
 * PREFIXES		A space-separated list of prefixes currently assigned
-				Format: <prefix>/<length>,preferred,valid
+				Format: <prefix>/<length>,preferred,valid[,cls]
 * ADDRESSES		A space-separated list of addresses currently assigned
 				Format: <address>/<length>,preferred,valid
 * RA_ADDRESSES	A space-separated list of addresses from RA-prefixes
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index e991958..013e215 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -135,7 +135,8 @@ int init_dhcpv6(const char *ifname, int request_pd)
 			htons(DHCPV6_OPT_DNS_DOMAIN),
 			htons(DHCPV6_OPT_NTP_SERVER),
 			htons(DHCPV6_OPT_SIP_SERVER_A),
-			htons(DHCPV6_OPT_SIP_SERVER_D)};
+                          htons(DHCPV6_OPT_PREFIX_CLASS)
+                         };
 	odhcp6c_add_state(STATE_ORO, oro, sizeof(oro));
 
 
@@ -725,11 +726,11 @@ static uint32_t dhcpv6_parse_ia(void *opt, void *end)
 	uint16_t otype, olen;
 	uint8_t *odata;
 
-	struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT,
-			0, 0, IN6ADDR_ANY_INIT, 0, 0};
-
 	// Update address IA
 	dhcpv6_for_each_option(opt, end, otype, olen, odata) {
+          struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT,
+                                        0, 0, IN6ADDR_ANY_INIT, 0, 0, 0};
+
 		if (otype == DHCPV6_OPT_IA_PREFIX) {
 			struct dhcpv6_ia_prefix *prefix = (void*)&odata[-4];
 			if (olen + 4U < sizeof(*prefix))
@@ -743,6 +744,14 @@ static uint32_t dhcpv6_parse_ia(void *opt, void *end)
 
 			entry.length = prefix->prefix;
 			entry.target = prefix->addr;
+			uint16_t stype, slen;
+			uint8_t *sdata;
+
+                        // Find prefix class, if any
+			dhcpv6_for_each_option(odata, odata + olen,
+                                               stype, slen, sdata)
+                          if (stype == DHCPV6_OPT_PREFIX_CLASS && slen == 2) 
+                            entry.prefix_class = ntohs(*((uint16_t*)sdata));
 
 			odhcp6c_update_entry(STATE_IA_PD, &entry);
 		} else if (otype == DHCPV6_OPT_IA_ADDR) {
diff --git a/src/odhcp6c.c b/src/odhcp6c.c
index 6451312..64d363f 100644
--- a/src/odhcp6c.c
+++ b/src/odhcp6c.c
@@ -427,6 +427,7 @@ void odhcp6c_update_entry_safe(enum odhcp6c_state state, struct odhcp6c_entry *n
 		if (x) {
 			x->valid = new->valid;
 			x->preferred = new->preferred;
+                        x->prefix_class = new->prefix_class;
 		} else {
 			odhcp6c_add_state(state, new, sizeof(*new));
 		}
diff --git a/src/odhcp6c.h b/src/odhcp6c.h
index eae9b7a..1b46af0 100644
--- a/src/odhcp6c.h
+++ b/src/odhcp6c.h
@@ -51,6 +51,9 @@ enum dhcvp6_opt {
 	DHCPV6_OPT_NTP_SERVER = 56,
 	DHCPV6_OPT_SIP_SERVER_D = 21,
 	DHCPV6_OPT_SIP_SERVER_A = 22,
+
+        /* draft-bhandari-dhc-class-based-prefix */
+	DHCPV6_OPT_PREFIX_CLASS = 200, /* NOT STANDARDIZED! */
 };
 
 enum dhcpv6_opt_npt {
@@ -131,7 +134,6 @@ struct dhcpv6_duid {
 	uint8_t data[128];
 } _packed;
 
-
 #define dhcpv6_for_each_option(start, end, otype, olen, odata)\
 	for (uint8_t *_o = (uint8_t*)(start); _o + 4 <= (uint8_t*)(end) &&\
 		((otype) = _o[0] << 8 | _o[1]) && ((odata) = (void*)&_o[4]) &&\
@@ -197,6 +199,7 @@ struct odhcp6c_entry {
 	struct in6_addr target;
 	uint32_t valid;
 	uint32_t preferred;
+        uint32_t prefix_class;
 };
 
 
diff --git a/src/ra.c b/src/ra.c
index 4ed5371..580d4cd 100644
--- a/src/ra.c
+++ b/src/ra.c
@@ -123,7 +123,7 @@ static void update_proc(const char *sect, const char *opt, uint32_t value)
 
 static bool ra_deduplicate(const struct in6_addr *any, uint8_t length)
 {
-	struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, length, 0, *any, 0, 0};
+  struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, length, 0, *any, 0, 0, 0};
 	struct odhcp6c_entry *x = odhcp6c_find_entry(STATE_RA_PREFIX, &entry);
 	if (x && IN6_ARE_ADDR_EQUAL(&x->target, any)) {
 		odhcp6c_random(&x->target.s6_addr32[2], 2 * sizeof(uint32_t));
@@ -173,7 +173,7 @@ bool ra_process(void)
 	bool found = false;
 	uint8_t buf[1500];
 	struct nd_router_advert *adv = (struct nd_router_advert*)buf;
-	struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0, IN6ADDR_ANY_INIT, 0, 0};
+	struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0, IN6ADDR_ANY_INIT, 0, 0, 0};
 	const struct in6_addr any = IN6ADDR_ANY_INIT;
 	odhcp6c_expire();
 
diff --git a/src/script.c b/src/script.c
index 205c581..7368080 100644
--- a/src/script.c
+++ b/src/script.c
@@ -152,6 +152,8 @@ static void entry_to_env(const char *name, const void *data, size_t len, bool ho
 				buf_len += snprintf(&buf[buf_len], 12, ",%u", e[i].priority);
 			} else {
 				buf_len += snprintf(&buf[buf_len], 24, ",%u,%u", e[i].preferred, e[i].valid);
+                                if (e[i].prefix_class)
+                                  buf_len += snprintf(&buf[buf_len], 12, ",%u", e[i].prefix_class);
 			}
 		}
 		buf[buf_len++] = ' ';