From 38bc630be6816eb5bd0a368437c97ee1aba3ee56 Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Wed, 17 Apr 2019 11:22:43 +0200 Subject: router: use ra_lifetime as lifetime for RA options (FS#2206) Use the RA lifetime as lifetime for the recursive DNS and DNS search options For the route options use as lifetime the smallest value of either the valid lifetime of the address associated with the route or the RA lifetime. This avoids routes having infinite lifetime being installed in downstream clients which can results into routes pointing to a removed router. Signed-off-by: Hans Dedecker --- src/router.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/router.c b/src/router.c index 93b75bf..a897d5b 100644 --- a/src/router.c +++ b/src/router.c @@ -319,7 +319,7 @@ static bool parse_routes(struct odhcpd_ipaddr *n, ssize_t len) } static int calc_adv_interval(struct interface *iface, uint32_t minvalid, - uint32_t *maxival) + uint32_t *maxival) { uint32_t minival = iface->ra_mininterval; int msecs; @@ -346,9 +346,9 @@ static int calc_adv_interval(struct interface *iface, uint32_t minvalid, return msecs; } -static uint16_t calc_ra_lifetime(struct interface *iface, uint32_t maxival) +static uint32_t calc_ra_lifetime(struct interface *iface, uint32_t maxival) { - uint16_t lifetime = 3*maxival; + uint32_t lifetime = 3*maxival; if (iface->ra_lifetime >= 0) { lifetime = iface->ra_lifetime; @@ -419,7 +419,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr struct sockaddr_in6 dest; size_t dns_sz = 0, search_sz = 0, pfxs_cnt = 0, routes_cnt = 0; ssize_t addr_cnt = 0; - uint32_t minvalid = UINT32_MAX, maxival; + uint32_t minvalid = UINT32_MAX, maxival, lifetime; int msecs, mtu = iface->ra_mtu, hlim = iface->ra_hoplimit; bool default_route = false; bool valid_prefix = false; @@ -569,6 +569,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr /* Calculate periodic transmit */ msecs = calc_adv_interval(iface, minvalid, &maxival); + lifetime = calc_ra_lifetime(iface, maxival); if (default_route) { if (!valid_prefix) { @@ -576,7 +577,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr "on %s thus we don't announce a default route!", iface->name); adv.h.nd_ra_router_lifetime = 0; } else - adv.h.nd_ra_router_lifetime = htons(calc_ra_lifetime(iface, maxival)); + adv.h.nd_ra_router_lifetime = htons(lifetime < UINT16_MAX ? lifetime : UINT16_MAX); } else adv.h.nd_ra_router_lifetime = 0; @@ -605,7 +606,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr memset(dns, 0, dns_sz); dns->type = ND_OPT_RECURSIVE_DNS; dns->len = 1 + (2 * dns_cnt); - dns->lifetime = htonl(maxival*10); + dns->lifetime = htonl(lifetime); memcpy(dns->addr, dns_addr, sizeof(struct in6_addr)*dns_cnt); } @@ -630,7 +631,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr memset(search, 0, search_sz); search->type = ND_OPT_DNS_SEARCH; search->len = search_len ? ((sizeof(*search) + search_padded) / 8) : 0; - search->lifetime = htonl(maxival*10); + search->lifetime = htonl(lifetime); if (search_len > 0) { memcpy(search->name, search_domain, search_len); @@ -646,6 +647,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr for (ssize_t i = 0; i < addr_cnt; ++i) { struct odhcpd_ipaddr *addr = &addrs[i]; struct nd_opt_route_info *tmp; + uint32_t valid; if (addr->dprefix > 64 || addr->dprefix == 0 || addr->valid <= (uint32_t)now) { syslog(LOG_INFO, "Address %s (dprefix %d, valid %u) not suitable as RA route on %s", @@ -689,7 +691,8 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr else if (iface->route_preference > 0) routes[routes_cnt].flags |= ND_RA_PREF_HIGH; - routes[routes_cnt].lifetime = htonl(TIME_LEFT(addr->valid, now)); + valid = TIME_LEFT(addr->valid, now); + routes[routes_cnt].lifetime = htonl(valid < lifetime ? valid : lifetime); routes[routes_cnt].addr[0] = addr->addr.in6.s6_addr32[0]; routes[routes_cnt].addr[1] = addr->addr.in6.s6_addr32[1]; routes[routes_cnt].addr[2] = 0; -- cgit v1.2.3