X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=e8b6e9fa07dae4dda39e1fb60c033e7506ad24e8;hp=4c321ac0da44a7a78561426f0d1404a92a72dbdd;hb=e05553099c47b92420c21ff30b07709dfa40a84a;hpb=e63a2837acfaf54c97a9db466bf485e9f7024fe8;ds=sidebyside diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 4c321ac..e8b6e9f 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -83,7 +83,7 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable) syslog(LOG_ERR, "Calloc failed for border on interface %s", iface->ifname); return -1; } - + border->length = 64; list_add(&border->head, &iface->ia_assignments); } @@ -114,6 +114,8 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable) odhcpd_urandom(a->key, sizeof(a->key)); memcpy(a->clid_data, lease->duid, lease->duid_len); memcpy(a->mac, lease->mac.ether_addr_octet, sizeof(a->mac)); + /* Infinite valid */ + a->valid_until = 0; // Assign to all interfaces struct dhcpv6_assignment *c; @@ -234,7 +236,7 @@ void dhcpv6_write_statefile(void) if (iface->dhcpv6 == RELAYD_SERVER && iface->ia_assignments.next) { struct dhcpv6_assignment *c; list_for_each_entry(c, &iface->ia_assignments, head) { - if (c->clid_len == 0 || c->managed_size < 0) + if (!(c->flags & OAF_BOUND) || c->managed_size < 0) continue; char ipbuf[INET6_ADDRSTRLEN]; @@ -243,11 +245,12 @@ void dhcpv6_write_statefile(void) odhcpd_hexlify(duidbuf, c->clid_data, c->clid_len); // iface DUID iaid hostname lifetime assigned length [addrs...] - int l = snprintf(leasebuf, sizeof(leasebuf), "# %s %s %x %s %u %x %u ", + int l = snprintf(leasebuf, sizeof(leasebuf), "# %s %s %x %s %ld %x %u ", iface->ifname, duidbuf, ntohl(c->iaid), (c->hostname ? c->hostname : "-"), - (unsigned)(c->valid_until > now ? - (c->valid_until - now + wall_time) : 0), + (c->valid_until > now ? + (c->valid_until - now + wall_time) : + (INFINITE_VALID(c->valid_until) ? -1 : 0)), c->assigned, (unsigned)c->length); struct in6_addr addr; @@ -262,7 +265,7 @@ void dhcpv6_write_statefile(void) m = i; for (size_t i = 0; i < addrlen; ++i) { - if (addrs[i].prefix > 96 || c->valid_until <= now || + if (addrs[i].prefix > 96 || (!INFINITE_VALID(c->valid_until) && c->valid_until <= now) || (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && addrs[i].prefix == 64)) continue; @@ -279,9 +282,9 @@ void dhcpv6_write_statefile(void) fputs(ipbuf, fp); char b[256]; - if (dn_expand(iface->search, iface->search + iface->search_len, - iface->search, b, sizeof(b)) > 0) - fprintf(fp, "\t%s.%s", c->hostname, b); + if (dn_expand(iface->search, iface->search + iface->search_len, + iface->search, b, sizeof(b)) > 0) + fprintf(fp, "\t%s.%s", c->hostname, b); fprintf(fp, "\t%s\n", c->hostname); md5_hash(ipbuf, strlen(ipbuf), &md5); @@ -299,17 +302,21 @@ void dhcpv6_write_statefile(void) if (iface->dhcpv4 == RELAYD_SERVER && iface->dhcpv4_assignments.next) { struct dhcpv4_assignment *c; list_for_each_entry(c, &iface->dhcpv4_assignments, head) { + if (!(c->flags & OAF_BOUND)) + continue; + char ipbuf[INET6_ADDRSTRLEN]; char leasebuf[512]; char duidbuf[16]; odhcpd_hexlify(duidbuf, c->hwaddr, sizeof(c->hwaddr)); // iface DUID iaid hostname lifetime assigned length [addrs...] - int l = snprintf(leasebuf, sizeof(leasebuf), "# %s %s ipv4 %s %u %x 32 ", + int l = snprintf(leasebuf, sizeof(leasebuf), "# %s %s ipv4 %s %ld %x 32 ", iface->ifname, duidbuf, (c->hostname ? c->hostname : "-"), - (unsigned)(c->valid_until > now ? - (c->valid_until - now + wall_time) : 0), + (c->valid_until > now ? + (c->valid_until - now + wall_time) : + (INFINITE_VALID(c->valid_until) ? -1 : 0)), c->addr); struct in_addr addr = {htonl(c->addr)}; @@ -319,9 +326,9 @@ void dhcpv6_write_statefile(void) fputs(ipbuf, fp); char b[256]; - if (dn_expand(iface->search, iface->search + iface->search_len, - iface->search, b, sizeof(b)) > 0) - fprintf(fp, "\t%s.%s", c->hostname, b); + if (dn_expand(iface->search, iface->search + iface->search_len, + iface->search, b, sizeof(b)) > 0) + fprintf(fp, "\t%s.%s", c->hostname, b); fprintf(fp, "\t%s\n", c->hostname); md5_hash(ipbuf, strlen(ipbuf), &md5); @@ -592,7 +599,8 @@ void dhcpv6_ia_postupdate(struct interface *iface, time_t now) struct list_head reassign = LIST_HEAD_INIT(reassign); struct dhcpv6_assignment *c, *d; list_for_each_entry_safe(c, d, &iface->ia_assignments, head) { - if (c->clid_len == 0 || c->valid_until < now || c->managed_size) + if (c->clid_len == 0 || (!INFINITE_VALID(c->valid_until) && c->valid_until < now) || + c->managed_size) continue; if (c->length < 128 && c->assigned >= border->assigned && c != border) @@ -637,7 +645,7 @@ static void reconf_timer(struct uloop_timeout *event) struct dhcpv6_assignment *a, *n; list_for_each_entry_safe(a, n, &iface->ia_assignments, head) { - if (a->valid_until < now) { + if (!INFINITE_VALID(a->valid_until) && a->valid_until < now) { if ((a->length < 128 && a->clid_len > 0) || (a->length == 128 && a->clid_len == 0)) { list_del(&a->head); @@ -768,9 +776,12 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, } } - a->valid_until = valid + now; - out.t1 = htonl(pref * 5 / 10); - out.t2 = htonl(pref * 8 / 10); + if (!INFINITE_VALID(a->valid_until)) + /* UINT32_MAX is considered as infinite leasetime */ + a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; + + out.t1 = htonl((pref == UINT32_MAX) ? pref : pref * 5 / 10); + out.t2 = htonl((pref == UINT32_MAX) ? pref : pref * 8 / 10); if (!out.t1) out.t1 = htonl(1); @@ -1031,7 +1042,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (((c->clid_len == clid_len && !memcmp(c->clid_data, clid_data, clid_len)) || (c->clid_len >= clid_len && !c->clid_data[0] && !c->clid_data[1] && !memcmp(c->mac, mac, sizeof(mac)))) && - (c->iaid == ia->iaid || c->valid_until < now) && + (c->iaid == ia->iaid || INFINITE_VALID(c->valid_until) || now < c->valid_until) && ((is_pd && c->length <= 64) || (is_na && c->length == 128))) { a = c; @@ -1062,6 +1073,9 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, a->length = reqlen; a->peer = *addr; a->assigned = reqhint; + // Set valid time to current time indicating + // assignment is not having infinite lifetime + a->valid_until = now; if (first) memcpy(a->key, first->key, sizeof(a->key)); @@ -1114,7 +1128,10 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, // Was only a solicitation: mark binding for removal if (assigned && hdr->msg_type == DHCPV6_MSG_SOLICIT) { - a->valid_until = 0; + a->flags &= ~OAF_BOUND; + + if (!INFINITE_VALID(a->valid_until)) + a->valid_until = now; } else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) { if (hostname_len > 0) { a->hostname = realloc(a->hostname, hostname_len + 1); @@ -1124,6 +1141,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, } } a->accept_reconf = accept_reconf; + a->flags |= OAF_BOUND; apply_lease(iface, a, true); } else if (!assigned && a && a->managed_size == 0) { // Cleanup failed assignment free_dhcpv6_assignment(a); @@ -1138,14 +1156,23 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, } else if (hdr->msg_type == DHCPV6_MSG_RENEW || hdr->msg_type == DHCPV6_MSG_REBIND) { ia_response_len = append_reply(buf, buflen, status, ia, a, iface, false); - if (a) + if (a) { + a->flags |= OAF_BOUND; apply_lease(iface, a, true); + } } else if (hdr->msg_type == DHCPV6_MSG_RELEASE) { - a->valid_until = 0; + if (!INFINITE_VALID(a->valid_until)) + a->valid_until = now - 1; + + a->flags &= ~OAF_BOUND; apply_lease(iface, a, false); } else if (hdr->msg_type == DHCPV6_MSG_DECLINE && a->length == 128) { - a->clid_len = 0; - a->valid_until = now + 3600; // Block address for 1h + a->flags &= ~OAF_BOUND; + + if (!INFINITE_VALID(a->valid_until)) { + a->clid_len = 0; + a->valid_until = now + 3600; // Block address for 1h + } } } else if (hdr->msg_type == DHCPV6_MSG_CONFIRM && ia_addr_present) { // Send NOTONLINK for CONFIRM with addr present so that clients restart connection