router: unify RA router and DNS lifetime
[project/odhcpd.git] / src / dhcpv6-ia.c
index 74e3441..6ea49b0 100644 (file)
@@ -60,7 +60,6 @@ void free_dhcpv6_assignment(struct dhcpv6_assignment *c)
 
        free(c->managed);
        free(c->hostname);
-       free(c->classes);
        free(c);
 }
 
@@ -75,7 +74,7 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable)
                }
        }
 
-       if (iface->dhcpv6 == RELAYD_SERVER) {
+       if (enable && iface->dhcpv6 == RELAYD_SERVER) {
                if (!iface->ia_assignments.next)
                        INIT_LIST_HEAD(&iface->ia_assignments);
 
@@ -133,7 +132,6 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable)
                                        a->hostname = strdup(lease->hostname);
                                }
                        } else {
-                               free(a->classes);
                                free(a->hostname);
                                free(a);
                        }
@@ -365,7 +363,7 @@ static void apply_lease(struct interface *iface, struct dhcpv6_assignment *a, bo
                struct in6_addr prefix = addrs[i].addr;
                prefix.s6_addr32[1] |= htonl(a->assigned);
                odhcpd_setup_route(&prefix, (a->managed_size) ? addrs[i].prefix : a->length,
-                               iface, &a->peer.sin6_addr, add);
+                               iface, &a->peer.sin6_addr, 1024, add);
        }
 }
 
@@ -583,7 +581,8 @@ static void update(struct interface *iface)
        int minprefix = -1;
 
        for (int i = 0; i < len; ++i) {
-               if (addr[i].preferred > 0 && addr[i].prefix > minprefix)
+               if (addr[i].preferred > 0 && addr[i].prefix < 64 &&
+                               addr[i].prefix > minprefix)
                        minprefix = addr[i].prefix;
 
                addr[i].addr.s6_addr32[3] = 0;
@@ -596,7 +595,10 @@ static void update(struct interface *iface)
        }
 
        struct dhcpv6_assignment *border = list_last_entry(&iface->ia_assignments, struct dhcpv6_assignment, head);
-       border->assigned = 1 << (64 - minprefix);
+       if (minprefix > 32 && minprefix <= 64)
+               border->assigned = 1U << (64 - minprefix);
+       else
+               border->assigned = 0;
 
        bool change = len != (int)iface->ia_addr_len;
        for (int i = 0; !change && i < len; ++i)
@@ -728,13 +730,19 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status,
                                        m = i;
 
                        for (size_t i = 0; i < addrlen; ++i) {
-                               uint32_t prefix_pref = addrs[i].preferred - now;
-                               uint32_t prefix_valid = addrs[i].valid - now;
+                               uint32_t prefix_pref = addrs[i].preferred;
+                               uint32_t prefix_valid = addrs[i].valid;
 
                                if (addrs[i].prefix > 96 ||
                                                addrs[i].preferred <= (uint32_t)now)
                                        continue;
 
+                               if (prefix_pref != UINT32_MAX)
+                                       prefix_pref -= now;
+
+                               if (prefix_valid != UINT32_MAX)
+                                       prefix_valid -= now;
+
                                if (a->length < 128) {
                                        struct dhcpv6_ia_prefix p = {
                                                .type = htons(DHCPV6_OPT_IA_PREFIX),
@@ -749,7 +757,8 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status,
                                        size_t entrlen = sizeof(p) - 4;
 
                                        if (datalen + entrlen + 4 > buflen ||
-                                                       (a->assigned == 0 && a->managed_size == 0))
+                                                       (a->assigned == 0 && a->managed_size == 0) ||
+                                                       (!a->managed_size && a->length <= addrs[i].prefix))
                                                continue;
 
                                        memcpy(buf + datalen, &p, sizeof(p));