From: Roy Marples Date: Sat, 9 Nov 2019 22:03:19 +0000 (+0000) Subject: INET6: Apply hoplimit, reachable and retrans timer values from RA. X-Git-Tag: v8.1.2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12f623711e56841ff2785e5bcab3f29f6f504fc8;p=thirdparty%2Fdhcpcd.git INET6: Apply hoplimit, reachable and retrans timer values from RA. Only tested thus far on NetBSD. While here, fix prior to not lose the first sorted route. --- diff --git a/src/if-bsd.c b/src/if-bsd.c index d2e910ef..eb7673a2 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -1484,6 +1484,22 @@ inet6_sysctl(int code, int val, int action) } #endif +int +if_applyra(const struct ra *rap) +{ + struct in6_ndireq ndi = { .ndi.chlim = 0 }; + struct priv *priv = rap->iface->ctx->priv; + + strncpy(ndi.ifname, rap->iface->name, sizeof(ndi.ifname)); + if (ioctl(priv->pf_inet6_fd, SIOCGIFINFO_IN6, &ndi) == -1) + return -1; + + ndi.ndi.chlim = rap->hoplimit; + ndi.ndi.retrans = rap->retrans; + ndi.ndi.basereachable = rap->reachable; + return ioctl(priv->pf_inet6_fd, SIOCSIFINFO_IN6, &ndi); +} + #ifdef IPV6_MANAGETEMPADDR #ifndef IPV6CTL_TEMPVLTIME #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) diff --git a/src/if-linux.c b/src/if-linux.c index f7f280bd..68121300 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -229,7 +229,7 @@ check_proc_hex(const char *path, unsigned int *value) } static ssize_t -if_writepathstr(const char *path, const char *val) +if_writepathuint(const char *path, unsigned int val) { FILE *fp; ssize_t r; @@ -237,7 +237,7 @@ if_writepathstr(const char *path, const char *val) fp = fopen(path, "w"); if (fp == NULL) return -1; - r = fprintf(fp, "%s\n", val); + r = fprintf(fp, "%u\n", val); fclose(fp); return r; } @@ -261,7 +261,7 @@ if_init(struct interface *ifp) return errno == ENOENT ? 0 : -1; if (n == 1) return 0; - return if_writepathstr(path, "1") == -1 ? -1 : 0; + return if_writepathuint(path, 1) == -1 ? -1 : 0; } int @@ -1875,7 +1875,7 @@ if_setup_inet6(const struct interface *ifp) snprintf(path, sizeof(path), "%s/%s/autoconf", prefix, ifp->name); ra = check_proc_int(path); if (ra != 1 && ra != -1) { - if (if_writepathstr(path, "0") == -1) + if (if_writepathuint(path, 0) == -1) logerr("%s: %s", __func__, path); } @@ -1888,11 +1888,29 @@ if_setup_inet6(const struct interface *ifp) * error as such so just log it and continue */ logfunc("%s", path); } else if (ra != 0) { - if (if_writepathstr(path, "0") == -1) + if (if_writepathuint(path, 0) == -1) logerr("%s: %s", __func__, path); } } +int +if_applyra(const struct ra *rap) +{ + int error = 0; + + snprintf(path, sizeof(path), "%s/%s/hop_limit", prefix, ifp->name); + if (if_writepathuint(path, rap->hoplimit) == -1) + error = -1; + snprintf(path, sizeof(path), "%s/%s/retrans_time", prefix, ifp->name); + if (if_writepathuint(path, rap->retrans) == -1) + error = -1; + snprintf(path, sizeof(path), "%s/%s/base_reachable_time", prefix, + ifp->name); + if (if_writepathuint(path, rap->reachable) == -1) + error = -1; + return error; +} + #ifdef IPV6_MANAGETEMPADDR int ip6_use_tempaddr(const char *ifname) diff --git a/src/if-sun.c b/src/if-sun.c index 39e217c2..6f6f5915 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -1711,6 +1711,20 @@ if_getlifetime6(struct ipv6_addr *addr) return -1; } +int +if_applyra(const struct ra *rap) +{ + struct lifreq lifr = { + .lifr_ifinfo.lir_maxhops = rap->hoplimit, + .lifr_ifinfo.lir_reachtime = rap->reachable, + .lifr_ifinfo.lir_reachretrans = rap->retrans, + }; + + strlcpy(lifr.lifr_ifname, rap->iface->name, sizeof(lifr.lifr_ifname)); + if (ioctl(rap->iface->ctx->pf_inet_fd, SIOCSLIFLNKINFO, &lifr) == -1) + return -1; +} + void if_setup_inet6(__unused const struct interface *ifp) { diff --git a/src/if.h b/src/if.h index ecfdb102..cc62cc94 100644 --- a/src/if.h +++ b/src/if.h @@ -65,6 +65,7 @@ #include "dhcpcd.h" #include "ipv4.h" #include "ipv6.h" +#include "ipv6nd.h" #include "route.h" #define EUI64_ADDR_LEN 8 @@ -206,6 +207,7 @@ int ip6_temp_valid_lifetime(const char *ifname); #endif int ip6_forwarding(const char *ifname); +int if_applyra(const struct ra *); int if_address6(unsigned char, const struct ipv6_addr *); int if_addrflags6(const struct interface *, const struct in6_addr *, const char *); diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 783ceaed..3cf69713 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -581,9 +581,6 @@ ipv6nd_sortrouters(struct dhcpcd_ctx *ctx) struct ra_head sorted_routers = TAILQ_HEAD_INITIALIZER(sorted_routers); struct ra *ra1, *ra2; - /* Pop the first router off */ - ra1 = TAILQ_FIRST(ctx->ra_routers); - TAILQ_REMOVE(ctx->ra_routers, ra1, next); while ((ra1 = TAILQ_FIRST(ctx->ra_routers)) != NULL) { TAILQ_REMOVE(ctx->ra_routers, ra1, next); TAILQ_FOREACH(ra2, &sorted_routers, next) { @@ -610,6 +607,25 @@ ipv6nd_sortrouters(struct dhcpcd_ctx *ctx) TAILQ_CONCAT(ctx->ra_routers, &sorted_routers, next); } +static void +ipv6nd_applyra(struct dhcpcd_ctx *ctx, struct interface *ifp) +{ + struct ra *rap; + struct rs_state *state = RS_STATE(ifp); + + TAILQ_FOREACH(rap, ctx->ra_routers, next) { + if (rap->iface == ifp) + break; + } + + if (rap == NULL) + return; + + state->retrans = rap->retrans; + if (if_applyra(rap) == -1) + logerr(__func__); +} + /* * Neighbour reachability. * @@ -645,6 +661,7 @@ ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable) /* See if we can install a reachable default router. */ ipv6nd_sortrouters(ctx); + ipv6nd_applyra(ctx, rap->iface); rt_build(ctx, AF_INET6); /* If we have no reachable default routers, try and solicit one. */ @@ -1082,16 +1099,20 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, if (!new_rap && rap->lifetime == 0 && old_lifetime != 0) logwarnx("%s: %s: no longer a default router", ifp->name, rap->sfrom); - if (nd_ra->nd_ra_reachable) { + if (nd_ra->nd_ra_curhoplimit != 0) + rap->hoplimit = nd_ra->nd_ra_curhoplimit; + else + rap->hoplimit = IPV6_DEFHLIM; + if (nd_ra->nd_ra_reachable != 0) { rap->reachable = ntohl(nd_ra->nd_ra_reachable); if (rap->reachable > MAX_REACHABLE_TIME) rap->reachable = 0; - } - if (nd_ra->nd_ra_retransmit) { - struct rs_state *state = RS_STATE(ifp); - - state->retrans = rap->retrans = ntohl(nd_ra->nd_ra_retransmit); - } + } else + rap->reachable = REACHABLE_TIME; + if (nd_ra->nd_ra_retransmit != 0) + rap->retrans = ntohl(nd_ra->nd_ra_retransmit); + else + rap->retrans = RETRANS_TIMER; rap->expired = false; rap->hasdns = false; rap->isreachable = true; @@ -1311,6 +1332,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, script_runreason(ifp, "TEST"); goto handle_flag; } + ipv6nd_applyra(ifp->ctx, ifp); ipv6_addaddrs(&rap->addrs); #ifdef IPV6_MANAGETEMPADDR ipv6_addtempaddrs(ifp, &rap->acquired); diff --git a/src/ipv6nd.h b/src/ipv6nd.h index 16c4dc79..1097a88a 100644 --- a/src/ipv6nd.h +++ b/src/ipv6nd.h @@ -50,6 +50,7 @@ struct ra { uint32_t reachable; uint32_t retrans; uint32_t mtu; + uint8_t hoplimit; struct ipv6_addrhead addrs; bool hasdns; bool expired;