Only tested thus far on NetBSD.
While here, fix prior to not lose the first sorted route.
}
#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)
}
static ssize_t
-if_writepathstr(const char *path, const char *val)
+if_writepathuint(const char *path, unsigned int val)
{
FILE *fp;
ssize_t r;
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;
}
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
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);
}
* 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)
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)
{
#include "dhcpcd.h"
#include "ipv4.h"
#include "ipv6.h"
+#include "ipv6nd.h"
#include "route.h"
#define EUI64_ADDR_LEN 8
#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 *);
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) {
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.
*
/* 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. */
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;
script_runreason(ifp, "TEST");
goto handle_flag;
}
+ ipv6nd_applyra(ifp->ctx, ifp);
ipv6_addaddrs(&rap->addrs);
#ifdef IPV6_MANAGETEMPADDR
ipv6_addtempaddrs(ifp, &rap->acquired);
uint32_t reachable;
uint32_t retrans;
uint32_t mtu;
+ uint8_t hoplimit;
struct ipv6_addrhead addrs;
bool hasdns;
bool expired;