X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=a7146a767960cde012f1962a5e014f64e6a4c272;hp=852af97914a4067fe792948a7c6f2b838fc23364;hb=4c89614ccf5d72ee0c0824e5050a8814748a32c3;hpb=d7732c6050cd091dac5e88b9b625e4cdb61acc69 diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 852af97..a7146a7 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,10 @@ 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)); + /* Static assignment */ + a->flags |= OAF_STATIC; + /* Infinite valid */ + a->valid_until = 0; // Assign to all interfaces struct dhcpv6_assignment *c; @@ -234,7 +238,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,12 +247,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) : - (INFINITE_VALID(c->valid_until) ? INT32_MAX: 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; @@ -280,9 +284,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); @@ -300,18 +304,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) : - (INFINITE_VALID(c->valid_until) ? INT32_MAX: 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)}; @@ -321,9 +328,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); @@ -771,8 +778,10 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, } } - /* UINT32_MAX is considered as infinite leasetime */ - a->valid_until = (valid == UINT32_MAX) ? 0 : valid + now; + 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); @@ -1035,7 +1044,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 || (!INFINITE_VALID(c->valid_until) && 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; @@ -1066,6 +1075,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)); @@ -1118,7 +1130,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 = now; + a->flags &= ~OAF_BOUND; + + if (!(a->flags & OAF_STATIC)) + 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); @@ -1128,6 +1143,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); @@ -1142,14 +1158,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 = now - 1; + if (!(a->flags & OAF_STATIC)) + 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 (!(a->flags & OAF_STATIC)) { + 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