X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=7e8e53520036ebab024101705838877c958a04df;hp=c97a0797dc93a1968f0b36548a81f315896d3ef9;hb=33858d341fa7eff6e7245a2486fc42aee64c81ff;hpb=7103b67707aac1a44b64211b45eca9c5c54bef2d diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index c97a079..7e8e535 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -219,7 +219,7 @@ void dhcpv6_write_statefile(void) return; lockf(fd, F_LOCK, 0); - ftruncate(fd, 0); + if (ftruncate(fd, 0) < 0) {} FILE *fp = fdopen(fd, "w"); if (!fp) { @@ -254,11 +254,18 @@ void dhcpv6_write_statefile(void) struct in6_addr addr; struct odhcpd_ipaddr *addrs = (c->managed) ? c->managed : iface->ia_addr; size_t addrlen = (c->managed) ? (size_t)c->managed_size : iface->ia_addr_len; + size_t m = 0; + + for (size_t i = 0; i < addrlen; ++i) + if (addrs[i].preferred > addrs[m].preferred || + (addrs[i].preferred == addrs[m].preferred && + memcmp(&addrs[i].addr, &addrs[m].addr, 16) > 0)) + m = i; for (size_t i = 0; i < addrlen; ++i) { - if (addrs[i].prefix > 96) - continue; - if (c->valid_until <= now) + if (addrs[i].prefix > 96 || c->valid_until <= now || + (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && + addrs[i].prefix == 64)) continue; addr = addrs[i].addr; @@ -589,7 +596,10 @@ static void update(struct interface *iface) } struct dhcpv6_assignment *border = list_last_entry(&iface->ia_assignments, struct dhcpv6_assignment, head); - border->assigned = 1 << (64 - minprefix); + if (minprefix > 32 && minprefix <= 64) + border->assigned = 1U << (64 - minprefix); + else + border->assigned = 0; bool change = len != (int)iface->ia_addr_len; for (int i = 0; !change && i < len; ++i) @@ -712,20 +722,28 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->ia_addr; size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->ia_addr_len; - size_t mostpref = 0; + size_t m = 0; for (size_t i = 0; i < addrlen; ++i) - if (addrs[i].preferred > addrs[mostpref].preferred) - mostpref = i; + if (addrs[i].preferred > addrs[m].preferred || + (addrs[i].preferred == addrs[m].preferred && + memcmp(&addrs[i].addr, &addrs[m].addr, 16) > 0)) + m = i; for (size_t i = 0; i < addrlen; ++i) { - uint32_t prefix_pref = addrs[i].preferred - now; - uint32_t prefix_valid = addrs[i].valid - now; + uint32_t prefix_pref = addrs[i].preferred; + uint32_t prefix_valid = addrs[i].valid; if (addrs[i].prefix > 96 || addrs[i].preferred <= (uint32_t)now) continue; + if (prefix_pref != UINT32_MAX) + prefix_pref -= now; + + if (prefix_valid != UINT32_MAX) + prefix_valid -= now; + if (a->length < 128) { struct dhcpv6_ia_prefix p = { .type = htons(DHCPV6_OPT_IA_PREFIX), @@ -756,7 +774,8 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, n.addr.s6_addr32[3] = htonl(a->assigned); size_t entrlen = sizeof(n) - 4; - if (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != mostpref) + if (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && + addrs[i].prefix == 64) continue; if (datalen + entrlen + 4 > buflen || a->assigned == 0)