X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Frouter.c;h=89b1c520ab13d4a104e00a65d10dd7c1cf79771d;hp=f942d8f851639c039faff54cf985ef0a80ba8fbc;hb=053ca41a841aa4a1b1ce86ce6ee9f4304cba7027;hpb=e23972527f93a3d2a5412400384519ff550708b7 diff --git a/src/router.c b/src/router.c index f942d8f..89b1c52 100644 --- a/src/router.c +++ b/src/router.c @@ -37,6 +37,7 @@ static void sigusr1_refresh(int signal); static struct odhcpd_event router_event = {{.fd = -1}, handle_icmpv6}; static FILE *fp_route = NULL; +#define RA_IOV_LEN 6 int init_router(void) @@ -205,7 +206,6 @@ static bool parse_routes(struct odhcpd_ipaddr *n, ssize_t len) return found_default; } - // Router Advert server mode static uint64_t send_router_advert(struct interface *iface, const struct in6_addr *from) { @@ -244,7 +244,8 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add // If not currently shutting down struct odhcpd_ipaddr addrs[RELAYD_MAX_PREFIXES]; ssize_t ipcnt = 0; - uint64_t maxpreferred = 0; + uint64_t minvalid = UINT64_MAX; + uint64_t maxvalid = 0; // If not shutdown if (iface->timer_rs.cb) { @@ -253,12 +254,10 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add // Check default route if (parse_routes(addrs, ipcnt) || iface->default_router > 1) - adv.h.nd_ra_router_lifetime = - htons(3 * MaxRtrAdvInterval); + adv.h.nd_ra_router_lifetime = 1; } // Construct Prefix Information options - bool have_public = false; size_t cnt = 0; struct in6_addr dns_pref = IN6ADDR_ANY_INIT, *dns_addr = &dns_pref; @@ -270,8 +269,8 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add if (addr->prefix > 96) continue; // Address not suitable - if (addr->preferred > MaxPreferredTime) - addr->preferred = MaxPreferredTime; + if (addr->preferred > MaxValidTime) + addr->preferred = MaxValidTime; if (addr->valid > MaxValidTime) addr->valid = MaxValidTime; @@ -291,13 +290,16 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add p = &adv.prefix[cnt++]; } - if ((addr->addr.s6_addr[0] & 0xfe) != 0xfc && addr->preferred > 0) { - have_public = true; + if (addr->preferred > 0) { + if (minvalid > 1000ULL * addr->valid) + minvalid = 1000ULL * addr->valid; - if (maxpreferred < 1000 * addr->preferred) - maxpreferred = 1000 * addr->preferred; + if (maxvalid < 1000ULL * addr->valid && (iface->default_router || + (addr->addr.s6_addr[0] & 0xfe) != 0xfc)) + maxvalid = 1000ULL * addr->valid; } + odhcpd_bmemcpy(&p->nd_opt_pi_prefix, &addr->addr, (iface->ra_advrouter) ? 128 : addr->prefix); p->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; @@ -319,7 +321,7 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add } } - if (!have_public && !iface->default_router && adv.h.nd_ra_router_lifetime) { + if (!maxvalid && !iface->default_router && adv.h.nd_ra_router_lifetime) { syslog(LOG_WARNING, "A default route is present but there is no public prefix " "on %s thus we don't announce a default route!", iface->ifname); adv.h.nd_ra_router_lifetime = 0; @@ -329,7 +331,7 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add if (iface->dns_cnt > 0) { dns_addr = iface->dns; dns_cnt = iface->dns_cnt; - dns_time = 2 * MaxRtrAdvInterval; + dns_time = 0; } if (!dns_addr || IN6_IS_ADDR_UNSPECIFIED(dns_addr)) @@ -374,7 +376,6 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add search->len = search_len ? ((sizeof(*search) + search_padded) / 8) : 0; search->pad = 0; search->pad2 = 0; - search->lifetime = htonl(2 * MaxRtrAdvInterval);; memcpy(search->name, search_domain, search_len); memset(&search->name[search_len], 0, search_padded - search_len); @@ -420,20 +421,28 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add // Calculate periodic transmit int msecs = 0; - uint32_t maxival = MaxRtrAdvInterval * 1000; - uint32_t minival = MinRtrAdvInterval * 1000; + uint32_t maxival = iface->ra_maxinterval * 1000; + uint32_t minival; + + if (maxival < 4000 || maxival > MaxRtrAdvInterval * 1000) + maxival = MaxRtrAdvInterval * 1000; + + if (maxival > minvalid / 3) { + maxival = minvalid / 3; - if (maxpreferred > 0 && maxival > maxpreferred / 2) { - maxival = maxpreferred / 2; if (maxival < 4000) maxival = 4000; - - if (maxival >= 9000) - minival = maxival / 3; - else - minival = (maxival * 3) / 4; } + minival = (maxival * 3) / 4; + if (adv.h.nd_ra_router_lifetime) + adv.h.nd_ra_router_lifetime = htons(maxvalid / 1000); + + search->lifetime = htonl(maxvalid / 1000); + + if (!dns.lifetime) + dns.lifetime = search->lifetime; + odhcpd_urandom(&msecs, sizeof(msecs)); msecs = (labs(msecs) % (maxival - minival)) + minival; @@ -443,7 +452,8 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add .data = {0, 0, maxival >> 24, maxival >> 16, maxival >> 8, maxival} }; - struct iovec iov[] = {{&adv, (uint8_t*)&adv.prefix[cnt] - (uint8_t*)&adv}, + struct iovec iov[RA_IOV_LEN] = { + {&adv, (uint8_t*)&adv.prefix[cnt] - (uint8_t*)&adv}, {&routes, routes_cnt * sizeof(*routes)}, {&dns, (dns_cnt) ? sizeof(dns) : 0}, {dns_addr, dns_cnt * sizeof(*dns_addr)},