X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=597bc74981e6f2d2293ff4b1918c933dac5a4870;hp=c5f8783ca9fd543be2d5a2c1ca179e996d158bf4;hb=44ca70ae6f0fb649cef47d9160ec1ee13e7844f1;hpb=73850ae66e29b6cebf73a787a639f8400c6c94ab diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index c5f8783..597bc74 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -92,14 +92,18 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable) struct lease *lease; list_for_each_entry(lease, &leases, head) { // Construct entry - struct dhcpv6_assignment *a = calloc(1, sizeof(*a) + lease->duid_len); + size_t duid_len = lease->duid_len ? lease->duid_len : 14; + struct dhcpv6_assignment *a = calloc(1, sizeof(*a) + duid_len); if (!a) { syslog(LOG_ERR, "Calloc failed for static lease assignment on interface %s", iface->ifname); return -1; } - a->clid_len = lease->duid_len; + if (lease->dhcpv4_leasetime > 0) + a->leasetime = lease->dhcpv4_leasetime; + + a->clid_len = duid_len; a->length = 128; if (lease->hostid) { a->assigned = lease->hostid; @@ -108,7 +112,7 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable) a->assigned = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10); } odhcpd_urandom(a->key, sizeof(a->key)); - memcpy(a->clid_data, lease->duid, a->clid_len); + memcpy(a->clid_data, lease->duid, lease->duid_len); memcpy(a->mac, lease->mac.ether_addr_octet, sizeof(a->mac)); // Assign to all interfaces @@ -258,7 +262,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; @@ -572,7 +576,7 @@ void dhcpv6_ia_postupdate(struct interface *iface, time_t now) int minprefix = -1; for (size_t i = 0; i < iface->ia_addr_len; ++i) { - if (iface->ia_addr[i].preferred > now && + if (iface->ia_addr[i].preferred > (uint32_t)now && iface->ia_addr[i].prefix < 64 && iface->ia_addr[i].prefix > minprefix) minprefix = iface->ia_addr[i].prefix; @@ -588,7 +592,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) @@ -633,7 +638,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); @@ -674,7 +679,12 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, datalen += sizeof(stat); } else { if (a) { - uint32_t leasetime = iface->dhcpv4_leasetime; + uint32_t leasetime; + if (a->leasetime > 0) { + leasetime = a->leasetime; + } else { + leasetime = iface->dhcpv4_leasetime; + } if (leasetime == 0) leasetime = 3600; else if (leasetime < 60) @@ -739,7 +749,7 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, size_t entrlen = sizeof(n) - 4; if (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && - addrs[i].prefix == 64) + addrs[i].prefix <= 64) continue; if (datalen + entrlen + 4 > buflen || a->assigned == 0) @@ -759,9 +769,10 @@ 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); + /* 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); @@ -1022,7 +1033,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) && c->valid_until < now)) && ((is_pd && c->length <= 64) || (is_na && c->length == 128))) { a = c; @@ -1105,7 +1116,7 @@ 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->valid_until = now; } else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) { if (hostname_len > 0) { a->hostname = realloc(a->hostname, hostname_len + 1); @@ -1132,7 +1143,7 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (a) apply_lease(iface, a, true); } else if (hdr->msg_type == DHCPV6_MSG_RELEASE) { - a->valid_until = 0; + a->valid_until = now - 1; apply_lease(iface, a, false); } else if (hdr->msg_type == DHCPV6_MSG_DECLINE && a->length == 128) { a->clid_len = 0;