From: Markus Stenberg Date: Mon, 24 Jun 2013 10:53:03 +0000 (+0300) Subject: Merge branch 'master' into hnet X-Git-Tag: debian/1.1+git20160131-1~133^2~3 X-Git-Url: https://git.decadent.org.uk/gitweb/?p=odhcp6c.git;a=commitdiff_plain;h=eb0b01e94374774609c31ab4508d8cfca8a400e1 Merge branch 'master' into hnet Conflicts: README src/dhcpv6.c src/odhcp6c.h --- eb0b01e94374774609c31ab4508d8cfca8a400e1 diff --cc README index 2a7ab63,16ac904..3f2087f --- a/README +++ b/README @@@ -53,12 -66,12 +66,12 @@@ Environment * SNTP_FQDN A space-separated list of SNTP server FQDNs * SIP_IP A space-separated list of SIP servers * SIP_DOMAIN A space-separated list of SIP domains - * OPTION_ Custom option received as base-16 + * OPTION_ Custom option received as base-16 * PREFIXES A space-separated list of prefixes currently assigned - Format: /,preferred,valid[,cls] - Format: /,preferred,valid[,excluded=/] ++ Format: /,preferred,valid[,excluded=/][,class=] * ADDRESSES A space-separated list of addresses currently assigned Format:
/,preferred,valid - * RA_ADDRESSES A space-separated list of addresses from RA-prefixes + * RA_ADDRESSES A space-separated list of addresses from RA-prefixes Format:
/,preferred,valid * RA_ROUTES A space-separated list of routes from the RA Format:
/,gateway,valid,metric diff --cc src/dhcpv6.c index 161f628,ed6b8f8..7f2aa1a --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@@ -131,12 -136,15 +136,17 @@@ int init_dhcpv6(const char *ifname, in } // Create ORO - uint16_t oro[] = {htons(DHCPV6_OPT_DNS_SERVERS), + uint16_t oro[] = { + htons(DHCPV6_OPT_SIP_SERVER_D), + htons(DHCPV6_OPT_SIP_SERVER_A), + htons(DHCPV6_OPT_DNS_SERVERS), htons(DHCPV6_OPT_DNS_DOMAIN), htons(DHCPV6_OPT_NTP_SERVER), + htons(DHCPV6_OPT_SIP_SERVER_A), - htons(DHCPV6_OPT_PREFIX_CLASS) - }; + htons(DHCPV6_OPT_AFTR_NAME), + htons(DHCPV6_OPT_PD_EXCLUDE), ++ htons(DHCPV6_OPT_PREFIX_CLASS), + }; odhcp6c_add_state(STATE_ORO, oro, sizeof(oro)); @@@ -748,16 -818,51 +820,57 @@@ static uint32_t dhcpv6_parse_ia(void *o 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)); - odhcp6c_update_entry(STATE_IA_PD, &entry); + // 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) + continue; + + uint8_t elen = sdata[0]; + if (elen > 64) + elen = 64; + + if (elen <= 32 || elen <= entry.length) { + ok = false; + continue; + } + + + uint8_t bytes = ((elen - entry.length - 1) / 8) + 1; + if (slen <= bytes) { + ok = false; + continue; + } + + uint32_t exclude = 0; + do { + exclude = exclude << 8 | sdata[bytes]; + } while (--bytes); + + exclude >>= 8 - ((elen - entry.length) % 8); + exclude <<= 64 - elen; + + // Abusing router & priority fields for exclusion + entry.router = entry.target; + entry.router.s6_addr32[1] |= htonl(exclude); + entry.priority = elen; + } + + if (ok) + odhcp6c_update_entry(STATE_IA_PD, &entry); + + entry.priority = 0; + memset(&entry.router, 0, sizeof(entry.router)); } else if (otype == DHCPV6_OPT_IA_ADDR) { struct dhcpv6_ia_addr *addr = (void*)&odata[-4]; if (olen + 4U < sizeof(*addr)) diff --cc src/odhcp6c.h index 1b46af0,2e7107c..d8a9bff --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@@ -51,9 -51,8 +51,10 @@@ enum dhcvp6_opt DHCPV6_OPT_NTP_SERVER = 56, DHCPV6_OPT_SIP_SERVER_D = 21, 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 { diff --cc src/ra.c index 580d4cd,4690d41..9a57985 --- a/src/ra.c +++ b/src/ra.c @@@ -173,9 -202,8 +202,8 @@@ 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(); while (true) { struct sockaddr_in6 from; diff --cc src/script.c index 7368080,bda9749..3cc7e2b --- a/src/script.c +++ b/src/script.c @@@ -152,8 -186,14 +186,17 @@@ static void entry_to_env(const char *na 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); + } ++ if (type == ENTRY_PREFIX && 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 + buf_len += snprintf(&buf[buf_len], 12, ",excluded="); + inet_ntop(AF_INET6, &e[i].router, &buf[buf_len], INET6_ADDRSTRLEN); + buf_len += strlen(&buf[buf_len]); + buf_len += snprintf(&buf[buf_len], 24, "/%u", e[i].priority); } } buf[buf_len++] = ' ';