(addrs)[(i)].prefix > 64)
static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info *info);
+static void apply_lease(struct dhcp_assignment *a, bool add);
static void set_border_assignment_size(struct interface *iface, struct dhcp_assignment *b);
static void handle_addrlist_change(struct netevent_handler_info *info);
static void start_reconf(struct dhcp_assignment *a);
border = alloc_assignment(0);
if (!border) {
- syslog(LOG_ERR, "Failed to alloc border on %s", iface->name);
+ syslog(LOG_WARNING, "Failed to alloc border on %s", iface->name);
return -1;
}
close(a->managed_sock.fd.fd);
}
+ if ((a->flags & OAF_BOUND) && (a->flags & OAF_DHCPV6_PD))
+ apply_lease(a, false);
+
if (a->reconf_cnt)
stop_reconf(a);
inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf) - 1);
- if (ctxt->c->length == 128 && ctxt->c->hostname &&
+ if ((ctxt->c->flags & OAF_DHCPV6_NA) && ctxt->c->hostname &&
!(ctxt->c->flags & OAF_BROKEN_HOSTNAME)) {
fputs(ipbuf, ctxt->fp);
}
}
-static void __apply_lease(struct interface *iface, struct dhcp_assignment *a,
+static void __apply_lease(struct dhcp_assignment *a,
struct odhcpd_ipaddr *addrs, ssize_t addr_len, bool add)
{
- if (a->length > 64)
+ if (a->flags & OAF_DHCPV6_NA)
return;
for (ssize_t i = 0; i < addr_len; ++i) {
prefix.s6_addr32[1] |= htonl(a->assigned);
prefix.s6_addr32[2] = prefix.s6_addr32[3] = 0;
netlink_setup_route(&prefix, (a->managed_size) ? addrs[i].prefix : a->length,
- iface->ifindex, &a->peer.sin6_addr, 1024, add);
+ a->iface->ifindex, &a->peer.sin6_addr, 1024, add);
}
}
-static void apply_lease(struct interface *iface, struct dhcp_assignment *a, bool add)
+static void apply_lease(struct dhcp_assignment *a, bool add)
{
+ struct interface *iface = a->iface;
struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->addr6;
ssize_t addrlen = (a->managed) ? a->managed_size : (ssize_t)iface->addr6_len;
- __apply_lease(iface, a, addrs, addrlen, add);
+ __apply_lease(a, addrs, addrlen, add);
}
/* Set border assignment size based on the IPv6 address prefixes */
uint32_t current = 1, asize = (1 << (64 - assign->length)) - 1;
if (assign->assigned) {
list_for_each_entry(c, &iface->ia_assignments, head) {
- if (c->length == 128 || c->length == 0)
+ if (c->flags & OAF_DHCPV6_NA)
continue;
if (assign->assigned >= current && assign->assigned + asize < c->assigned) {
list_add_tail(&assign->head, &c->head);
if (assign->flags & OAF_BOUND)
- apply_lease(iface, assign, true);
+ apply_lease(assign, true);
return true;
}
/* Fallback to a variable assignment */
current = 1;
list_for_each_entry(c, &iface->ia_assignments, head) {
- if (c->length == 128 || c->length == 0)
+ if (c->flags & OAF_DHCPV6_NA)
continue;
current = (current + asize) & (~asize);
list_add_tail(&assign->head, &c->head);
if (assign->flags & OAF_BOUND)
- apply_lease(iface, assign, true);
+ apply_lease(assign, true);
return true;
}
/* Preconfigured assignment by static lease */
if (a->assigned) {
list_for_each_entry(c, &iface->ia_assignments, head) {
- if (c->length == 0)
- continue;
-
- if (c->assigned > a->assigned || c->length != 128) {
+ if (c->assigned > a->assigned || !(c->flags & OAF_DHCPV6_NA)) {
list_add_tail(&a->head, &c->head);
return true;
} else if (c->assigned == a->assigned)
continue;
list_for_each_entry(c, &iface->ia_assignments, head) {
- if (c->length == 0)
- continue;
-
- if (c->assigned > try || c->length != 128) {
+ if (c->assigned > try || !(c->flags & OAF_DHCPV6_NA)) {
a->assigned = try;
list_add_tail(&a->head, &c->head);
return true;
time_t now = odhcpd_time();
list_for_each_entry(c, &iface->ia_assignments, head) {
- if (c != border && !(iface->ra_flags & ND_RA_FLAG_MANAGED)
+ if ((c->flags & OAF_DHCPV6_PD) && !(iface->ra_flags & ND_RA_FLAG_MANAGED)
&& (c->flags & OAF_BOUND))
- __apply_lease(iface, c, info->addrs_old.addrs,
+ __apply_lease(c, info->addrs_old.addrs,
info->addrs_old.len, false);
}
set_border_assignment_size(iface, border);
list_for_each_entry_safe(c, d, &iface->ia_assignments, head) {
- if (c->clid_len == 0 || (!INFINITE_VALID(c->valid_until) && c->valid_until < now) ||
- c->managed_size)
+ if (c->clid_len == 0 ||
+ !(c->flags & OAF_DHCPV6_PD) ||
+ (!INFINITE_VALID(c->valid_until) && c->valid_until < now) ||
+ c->managed_size)
continue;
- if (c->length < 128 && (c->assigned == 0 || c->assigned >= border->assigned) && c != border)
+ if (c->assigned == 0 || c->assigned >= border->assigned)
list_move(&c->head, &reassign);
- else if (c != border && (c->flags & OAF_BOUND))
- apply_lease(iface, c, true);
+ else if (c->flags & OAF_BOUND)
+ apply_lease(c, true);
if (c->accept_reconf && c->reconf_cnt == 0) {
struct dhcp_assignment *a;
if (a->leasetime)
leasetime = a->leasetime;
else
- leasetime = iface->dhcpv4_leasetime;
+ leasetime = iface->dhcp_leasetime;
uint32_t pref = leasetime;
uint32_t valid = leasetime;
if (prefix_pref != UINT32_MAX)
prefix_pref -= now;
+ if (prefix_pref > leasetime)
+ prefix_pref = leasetime;
+
if (prefix_valid != UINT32_MAX)
prefix_valid -= now;
- if (a->length < 128) {
+ if (prefix_valid > leasetime)
+ prefix_valid = leasetime;
+
+ if (a->flags & OAF_DHCPV6_PD) {
struct dhcpv6_ia_prefix o_ia_p = {
.type = htons(DHCPV6_OPT_IA_PREFIX),
.len = htons(sizeof(o_ia_p) - 4),
memcpy(buf + ia_len, &o_ia_p, sizeof(o_ia_p));
ia_len += sizeof(o_ia_p);
- } else {
+ }
+
+ if (a->flags & OAF_DHCPV6_NA) {
struct dhcpv6_ia_addr o_ia_a = {
.type = htons(DHCPV6_OPT_IA_ADDR),
.len = htons(sizeof(o_ia_a) - 4),
dhcpv6_ia_enum_addrs(iface, a, now, dhcpv6_log_ia_addr, &ctxt);
}
- syslog(LOG_NOTICE, "DHCPV6 %s %s from %s on %s: %s %s", type, (is_pd) ? "IA_PD" : "IA_NA",
- duidbuf, iface->name, status, leasebuf);
+ syslog(LOG_INFO, "DHCPV6 %s %s from %s on %s: %s %s", type, (is_pd) ? "IA_PD" : "IA_NA",
+ duidbuf, iface->name, status, leasebuf);
}
static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcp_assignment *a,
list_for_each_entry(c, &iface->ia_assignments, head) {
if ((c->clid_len == clid_len && !memcmp(c->clid_data, clid_data, clid_len)) &&
c->iaid == ia->iaid && (INFINITE_VALID(c->valid_until) || now < c->valid_until) &&
- ((is_pd && c->length <= 64) || (is_na && c->length == 128))) {
+ ((is_pd && (c->flags & OAF_DHCPV6_PD)) || (is_na && (c->flags & OAF_DHCPV6_NA)))) {
a = c;
/* Reset state */
if (a->flags & OAF_BOUND)
- apply_lease(iface, a, false);
+ apply_lease(a, false);
stop_reconf(a);
break;
a->valid_until = l ? 0 : now;
a->dhcp_free_cb = dhcpv6_ia_free_assignment;
a->iface = iface;
- a->flags = OAF_DHCPV6;
+ a->flags = (is_pd ? OAF_DHCPV6_PD : OAF_DHCPV6_NA);
if (first)
memcpy(a->key, first->key, sizeof(a->key));
a->accept_reconf = accept_reconf;
a->flags &= ~OAF_TENTATIVE;
a->flags |= OAF_BOUND;
- apply_lease(iface, a, true);
+ apply_lease(a, true);
} else if (!assigned && a && a->managed_size == 0) {
/* Cleanup failed assignment */
free_assignment(a);
ia_response_len = build_ia(buf, buflen, status, ia, a, iface, false);
if (a) {
a->flags |= OAF_BOUND;
- apply_lease(iface, a, true);
+ apply_lease(a, true);
}
} else if (hdr->msg_type == DHCPV6_MSG_RELEASE) {
- if (!(a->flags & OAF_STATIC))
- a->valid_until = now - 1;
-
- if (a->flags & OAF_BOUND) {
- apply_lease(iface, a, false);
+ if (a->flags & OAF_STATIC) {
+ apply_lease(a, false);
a->flags &= ~OAF_BOUND;
}
- } else if (hdr->msg_type == DHCPV6_MSG_DECLINE && a->length == 128) {
+ else
+ a->valid_until = now - 1;
+
+ } else if ((a->flags & OAF_DHCPV6_NA) && hdr->msg_type == DHCPV6_MSG_DECLINE) {
a->flags &= ~OAF_BOUND;
if (!(a->flags & OAF_STATIC)) {