Mercurial > hg > dhcpcd
changeset 2577:87aeca01a829 draft
Fix Prefix Exclude encoding/decoding.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Mon, 07 Jul 2014 09:21:35 +0000 |
| parents | c8af3fcd5905 |
| children | cc2c75cedfe4 |
| files | dhcp6.c |
| diffstat | 1 files changed, 36 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/dhcp6.c Sat Jul 05 19:47:22 2014 +0000 +++ b/dhcp6.c Mon Jul 07 09:21:35 2014 +0000 @@ -411,7 +411,7 @@ uint16_t *u16, n_options; struct if_options *ifo; const struct dhcp_opt *opt, *opt2; - uint8_t IA, *p; + uint8_t IA, *p, *pp; uint32_t u32; const struct ipv6_addr *ap; char hbuf[HOSTNAME_MAX_LEN + 1]; @@ -704,31 +704,28 @@ memcpy(p, &ap->prefix.s6_addr, sizeof(ap->prefix.s6_addr)); - /* RFC6603 Sectio 4.2 */ + /* RFC6603 Section 4.2 */ sla = dhcp6_findselfsla(ifp, ap->iaid); if (sla && dhcp6_delegateaddr(&addr, ifp, ap, sla) ==0) { - uint16_t el; - uint8_t *pp; - - el = ((sla->prefix_len - + n = ((sla->prefix_len - ap->prefix_len - 1) / NBBY) + 1; eo = D6_NEXT_OPTION(so); eo->code = htons(D6_OPTION_PD_EXCLUDE); - eo->len = el + 1; + eo->len = (uint16_t)n + 1; p = D6_OPTION_DATA(eo); *p++ = (uint8_t)sla->prefix_len; pp = addr.s6_addr; - pp += (ap->prefix_len - 1) / NBBY; + pp += ((ap->prefix_len - 1) / NBBY) + + (n - 1); u8 = ap->prefix_len % NBBY; - if (u8 % NBBY == 0) - pp++; - else { - *p = (uint8_t)(*pp++ << u8); - el--; - } - memcpy(p, pp, el); + if (u8) + n--; + while (n-- > 0) + *p++ = *pp--; + if (u8) + *p = (uint8_t)(*pp << u8); u32 = ntohs(so->len) + sizeof(*eo) + eo->len; so->len = htons(u32); @@ -1672,7 +1669,7 @@ char iabuf[INET6_ADDRSTRLEN]; const char *ia; int i; - uint8_t u8, len; + uint8_t u8, len, *pw; uint32_t u32, pltime, vltime; struct in6_addr prefix; size_t off; @@ -1748,7 +1745,19 @@ off = (size_t)(pe - p); ex = dhcp6_findoption(D6_OPTION_PD_EXCLUDE, p, off); +#if 0 + if (ex == NULL) { + struct dhcp6_option *w; + uint8_t *wp; + w = calloc(1, 128); + w->len = htons(2); + wp = D6_OPTION_DATA(w); + *wp++ = 64; + *wp++ = 0x78; + ex = w; + } +#endif if (ex) { off = ntohs(ex->len); if (off < 2) { @@ -1758,19 +1767,21 @@ } } if (ex) { - int bytelen, bitlen; - op = D6_COPTION_DATA(ex); a->prefix_exclude_len = *op++; memcpy(&a->prefix_exclude, &a->prefix, sizeof(a->prefix_exclude)); - bytelen = a->prefix_len / NBBY; - bitlen = a->prefix_len % NBBY; - if (bitlen != 0) - a->prefix_exclude.s6_addr[bytelen] |= - *op++ >> bitlen; - memcpy(a->prefix_exclude.s6_addr + bytelen + 1, - op, off - 2); + len = a->prefix_len / NBBY; + u8 = a->prefix_len % NBBY; + off--; + if (u8) + off--; + pw = a->prefix_exclude.s6_addr + + (a->prefix_exclude_len / NBBY) - 1; + while (off-- > 0) + *pw-- = *op++; + if (u8) + *pw |= *op >> u8; } else { a->prefix_exclude_len = 0; memset(&a->prefix_exclude, 0,
