summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHans Dedecker <dedeckeh@gmail.com>2018-06-26 12:17:11 +0200
committerHans Dedecker <dedeckeh@gmail.com>2018-06-26 14:20:53 +0200
commit81a281e83d71c778ad1dab72721d07f0a129521d (patch)
treef289678edabcc55e31d6185a04de39f46dc03050
parenta2ffc5986cd35bea983b81b28b8a656e3b81fdf1 (diff)
dhcpv6-ia: fix border assignment size setting
The border assignment size is not updated by address list change events if the interface is not configured as DHCPv6 server; therefore set the border assignment size when an interface is enabled and configured as a DHCPv6 server in order to keep the assignment size in sync with the available prefix sizes Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
-rw-r--r--src/dhcpv6-ia.c51
1 files changed, 34 insertions, 17 deletions
diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c
index fa652ab..4ee6dd2 100644
--- a/src/dhcpv6-ia.c
+++ b/src/dhcpv6-ia.c
@@ -41,6 +41,7 @@
static void dhcpv6_netevent_cb(unsigned long event, struct netevent_handler_info *info);
static void free_dhcpv6_assignment(struct dhcpv6_assignment *c);
+static void set_border_assignment_size(struct interface *iface, struct dhcpv6_assignment *b);
static void handle_addrlist_change(struct netevent_handler_info *info);
static void start_reconf(struct dhcpv6_assignment *a);
static void stop_reconf(struct dhcpv6_assignment *a);
@@ -72,11 +73,15 @@ int dhcpv6_setup_ia_interface(struct interface *iface, bool enable)
}
if (enable && iface->dhcpv6 == MODE_SERVER) {
+ struct dhcpv6_assignment *border;
+ struct lease *lease;
+
if (!iface->ia_assignments.next)
INIT_LIST_HEAD(&iface->ia_assignments);
if (list_empty(&iface->ia_assignments)) {
- struct dhcpv6_assignment *border = calloc(1, sizeof(*border));
+ border = calloc(1, sizeof(*border));
+
if (!border) {
syslog(LOG_ERR, "Calloc failed for border on interface %s", iface->ifname);
return -1;
@@ -84,10 +89,12 @@ int dhcpv6_setup_ia_interface(struct interface *iface, bool enable)
border->length = 64;
list_add(&border->head, &iface->ia_assignments);
- }
+ } else
+ border = list_last_entry(&iface->ia_assignments, struct dhcpv6_assignment, head);
+
+ set_border_assignment_size(iface, border);
/* Parse static entries */
- struct lease *lease;
list_for_each_entry(lease, &leases, head) {
/* Construct entry */
size_t duid_len = lease->duid_len ? lease->duid_len : 14;
@@ -489,6 +496,25 @@ static void apply_lease(struct interface *iface, struct dhcpv6_assignment *a, bo
__apply_lease(iface, a, addrs, addrlen, add);
}
+/* Set border assignment size based on the IPv6 address prefixes */
+static void set_border_assignment_size(struct interface *iface, struct dhcpv6_assignment *b)
+{
+ time_t now = odhcpd_time();
+ int minprefix = -1;
+
+ for (size_t i = 0; i < iface->addr6_len; ++i) {
+ if (iface->addr6[i].preferred > (uint32_t)now &&
+ iface->addr6[i].prefix < 64 &&
+ iface->addr6[i].prefix > minprefix)
+ minprefix = iface->addr6[i].prefix;
+ }
+
+ if (minprefix > 32 && minprefix <= 64)
+ b->assigned = 1U << (64 - minprefix);
+ else
+ b->assigned = 0;
+}
+
/* More data was received from TCP connection */
static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
{
@@ -695,28 +721,18 @@ static void handle_addrlist_change(struct netevent_handler_info *info)
struct interface *iface = info->iface;
struct dhcpv6_assignment *c, *d, *border = list_last_entry(
&iface->ia_assignments, struct dhcpv6_assignment, head);
+ struct list_head reassign = LIST_HEAD_INIT(reassign);
time_t now = odhcpd_time();
- int minprefix = -1;
- list_for_each_entry(c, &iface->ia_assignments, head)
+ list_for_each_entry(c, &iface->ia_assignments, head) {
if (c != border && iface->ra_managed == RA_MANAGED_NO_MFLAG
&& (c->flags & OAF_BOUND))
__apply_lease(iface, c, info->addrs_old.addrs,
info->addrs_old.len, false);
-
- for (size_t i = 0; i < iface->addr6_len; ++i) {
- if (iface->addr6[i].preferred > (uint32_t)now &&
- iface->addr6[i].prefix < 64 &&
- iface->addr6[i].prefix > minprefix)
- minprefix = iface->addr6[i].prefix;
}
- if (minprefix > 32 && minprefix <= 64)
- border->assigned = 1U << (64 - minprefix);
- else
- border->assigned = 0;
+ set_border_assignment_size(iface, border);
- struct list_head reassign = LIST_HEAD_INIT(reassign);
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)
@@ -728,10 +744,11 @@ static void handle_addrlist_change(struct netevent_handler_info *info)
apply_lease(iface, c, true);
if (c->accept_reconf && c->reconf_cnt == 0) {
+ struct dhcpv6_assignment *a;
+
start_reconf(c);
/* Leave all other assignments of that client alone */
- struct dhcpv6_assignment *a;
list_for_each_entry(a, &iface->ia_assignments, head)
if (a != c && a->clid_len == c->clid_len &&
!memcmp(a->clid_data, c->clid_data, a->clid_len))