dhcpv6-ia: create assignment for unknown IA in rebind messages
[project/odhcpd.git] / src / router.c
index 4ab06b6..feae5c7 100644 (file)
@@ -120,6 +120,7 @@ int setup_router_interface(struct interface *iface, bool enable)
                } else if (iface->ra == RELAYD_SERVER && !iface->master) {
                        iface->timer_rs.cb = trigger_router_advert;
                        uloop_timeout_set(&iface->timer_rs, 1000);
+                       ndp_rqs_addr6_dump();
                }
 
                if (iface->ra == RELAYD_RELAY || (iface->ra == RELAYD_SERVER && !iface->master))
@@ -233,7 +234,8 @@ static int calc_adv_interval(struct interface *iface, uint32_t minvalid,
                minival = (*maxival >= 9 ? *maxival/3 : *maxival);
 
        odhcpd_urandom(&msecs, sizeof(msecs));
-       msecs = (labs(msecs) % ((*maxival - minival)*1000)) + minival*1000;
+       msecs = (labs(msecs) % ((*maxival != minival) ? (*maxival - minival)*1000 : 500)) +
+                       minival*1000;
 
        return msecs;
 }
@@ -317,10 +319,12 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
        struct in6_addr dns_pref, *dns_addr = &dns_pref;
        size_t dns_cnt = 1;
 
-       odhcpd_get_linklocal_interface_address(iface->ifindex, &dns_pref);
+       odhcpd_get_interface_dns_addr(iface, &dns_pref);
 
        for (ssize_t i = 0; i < ipcnt; ++i) {
                struct odhcpd_ipaddr *addr = &addrs[i];
+               uint32_t preferred = 0;
+               uint32_t valid = 0;
 
                if (addr->prefix > 96 || addr->valid <= (uint32_t)now) {
                        char namebuf[INET6_ADDRSTRLEN];
@@ -346,9 +350,20 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
                        p = &adv.prefix[cnt++];
                }
 
-               if (addr->preferred > (uint32_t)now &&
-                               minvalid > TIME_LEFT(addr->valid, now))
-                       minvalid = TIME_LEFT(addr->valid, now);
+               if (addr->preferred > (uint32_t)now) {
+                       preferred = TIME_LEFT(addr->preferred, now);
+
+                       if (iface->ra_useleasetime &&
+                                       preferred > iface->dhcpv4_leasetime)
+                               preferred = iface->dhcpv4_leasetime;
+               }
+
+               valid = TIME_LEFT(addr->valid, now);
+               if (iface->ra_useleasetime && valid > iface->dhcpv4_leasetime)
+                       valid = iface->dhcpv4_leasetime;
+
+               if (minvalid > valid)
+                       minvalid = valid;
 
                if (!IN6_IS_ADDR_ULA(&addr->addr) || iface->default_router)
                        valid_prefix = true;
@@ -365,11 +380,8 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
                        p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
                if (iface->ra_advrouter)
                        p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
-               p->nd_opt_pi_valid_time = htonl(TIME_LEFT(addr->valid, now));
-               if (addr->preferred > (uint32_t)now)
-                       p->nd_opt_pi_preferred_time = htonl(TIME_LEFT(addr->preferred, now));
-               else if (addr->valid - now < 7200)
-                       p->nd_opt_pi_valid_time = 0;
+               p->nd_opt_pi_preferred_time = htonl(preferred);
+               p->nd_opt_pi_valid_time = htonl(valid);
        }
 
        // Calculate periodic transmit
@@ -605,7 +617,7 @@ static void forward_router_advertisement(uint8_t *data, size_t len)
                        size_t rewrite_cnt = iface->dns_cnt;
 
                        if (rewrite_cnt == 0) {
-                               if (odhcpd_get_linklocal_interface_address(iface->ifindex, &addr))
+                               if (odhcpd_get_interface_dns_addr(iface, &addr))
                                        continue; // Unable to comply
 
                                rewrite = &addr;