* 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
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));
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))
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) {
if (x) {
x->valid = new->valid;
x->preferred = new->preferred;
+ x->prefix_class = new->prefix_class;
} else {
odhcp6c_add_state(state, new, sizeof(*new));
}
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 {
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]) &&\
struct in6_addr target;
uint32_t valid;
uint32_t preferred;
+ uint32_t prefix_class;
};
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));
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();
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++] = ' ';