summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--src/dhcpv6.c27
-rw-r--r--src/odhcp6c.c1
-rw-r--r--src/odhcp6c.h3
-rw-r--r--src/ra.c2
-rw-r--r--src/script.c3
6 files changed, 31 insertions, 7 deletions
diff --git a/README b/README
index cccb3ea..32b6893 100644
--- a/README
+++ b/README
@@ -67,7 +67,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[,excluded=<excluded-prefix>/<length>]
+ Format: <prefix>/<length>,preferred,valid[,excluded=<excluded-prefix>/<length>][,class=<prefix class #>]
* 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 3f5bc83..fe4cc0b 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -142,8 +142,10 @@ int init_dhcpv6(const char *ifname, int request_pd)
htons(DHCPV6_OPT_DNS_SERVERS),
htons(DHCPV6_OPT_DNS_DOMAIN),
htons(DHCPV6_OPT_NTP_SERVER),
+ htons(DHCPV6_OPT_SIP_SERVER_A),
htons(DHCPV6_OPT_AFTR_NAME),
htons(DHCPV6_OPT_PD_EXCLUDE),
+ htons(DHCPV6_OPT_PREFIX_CLASS),
};
odhcp6c_add_state(STATE_ORO, oro, sizeof(oro));
@@ -827,11 +829,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))
@@ -845,11 +847,17 @@ 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(&prefix[1], odata + olen,
+ stype, slen, sdata)
+ if (stype == DHCPV6_OPT_PREFIX_CLASS && slen == 2)
+ entry.prefix_class = ntohs(*((uint16_t*)sdata));
// Parse PD-exclude
bool ok = true;
- uint16_t stype, slen;
- uint8_t *sdata;
dhcpv6_for_each_option(odata + sizeof(*prefix) - 4U,
odata + olen, stype, slen, sdata) {
if (stype != DHCPV6_OPT_PD_EXCLUDE || slen < 2)
@@ -904,6 +912,15 @@ static uint32_t dhcpv6_parse_ia(void *opt, void *end)
entry.length = 128;
entry.target = addr->addr;
+ uint16_t stype, slen;
+ uint8_t *sdata;
+
+ // Find prefix class, if any
+ dhcpv6_for_each_option(&addr[1], 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_NA, &entry);
}
diff --git a/src/odhcp6c.c b/src/odhcp6c.c
index 38b8e82..b2c6b98 100644
--- a/src/odhcp6c.c
+++ b/src/odhcp6c.c
@@ -459,6 +459,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 ac0932f..e0f6f62 100644
--- a/src/odhcp6c.h
+++ b/src/odhcp6c.h
@@ -53,6 +53,8 @@ enum dhcvp6_opt {
DHCPV6_OPT_SIP_SERVER_A = 22,
DHCPV6_OPT_AFTR_NAME = 64,
DHCPV6_OPT_PD_EXCLUDE = 67,
+ /* draft-bhandari-dhc-class-based-prefix */
+ DHCPV6_OPT_PREFIX_CLASS = 200, /* NOT STANDARDIZED! */
};
enum dhcpv6_opt_npt {
@@ -215,6 +217,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 4c1302c..9c1ed74 100644
--- a/src/ra.c
+++ b/src/ra.c
@@ -133,7 +133,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;
while (true) {
diff --git a/src/script.c b/src/script.c
index bda9749..74aea64 100644
--- a/src/script.c
+++ b/src/script.c
@@ -187,6 +187,9 @@ static void entry_to_env(const char *name, const void *data, size_t len, enum en
} else {
buf_len += snprintf(&buf[buf_len], 24, ",%u,%u", e[i].preferred, e[i].valid);
}
+ if ((type == ENTRY_PREFIX || type == ENTRY_ADDRESS) && e[i].prefix_class) {
+ buf_len += snprintf(&buf[buf_len], 12, ",class=%u", e[i].prefix_class);
+ }
if (type == ENTRY_PREFIX && e[i].priority) {
// priority and router are abused for prefix exclusion