configure_interface1(struct interface *ifp)
{
struct if_options *ifo = ifp->options;
+ int ra_global, ra_iface;
/* Do any platform specific configuration */
if_conf(ifp);
/* We want to disable kernel interface RA as early as possible. */
if (ifo->options & DHCPCD_IPV6RS) {
- if (check_ipv6(NULL) != 1 || check_ipv6(ifp->name) != 1)
+ ra_global = check_ipv6(NULL, options & DHCPCD_IPV6RA_OWN);
+ ra_iface = check_ipv6(ifp->name,
+ ifp->options->options & DHCPCD_IPV6RA_OWN);
+ if (ra_global == -1 || ra_iface == -1)
ifo->options &= ~DHCPCD_IPV6RS;
+ else if (ra_iface == 0)
+ ifo->options |= DHCPCD_IPV6RA_OWN;
}
/* If we haven't specified a ClientID and our hardware address
struct rt6 *rt;
TAILQ_FOREACH(ifp, ifaces, next) {
+ if (!(ifp->options->options & DHCPCD_IPV6RA_OWN))
+ continue;
d6_state = D6_CSTATE(ifp);
if (d6_state && d6_state->state == dstate) {
TAILQ_FOREACH(addr, &d6_state->addrs, next) {
struct rt6head dnr, *nrs;
struct rt6 *rt, *rtn, *or;
uint8_t have_default;
-
- if (!(options & (DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT)))
- return;
+ unsigned long long o;
TAILQ_INIT(&dnr);
while ((rt = TAILQ_LAST(routes, rt6head))) {
TAILQ_REMOVE(routes, rt, next);
if (find_route6(nrs, rt) == NULL) {
+ o = rt->iface->options->options;
if (!have_default &&
- (options & DHCPCD_IPV6RA_OWN_DEFAULT) &&
- !(options & DHCPCD_IPV6RA_OWN) &&
+ (o & DHCPCD_IPV6RA_OWN_DEFAULT) &&
+ !(o & DHCPCD_IPV6RA_OWN) &&
RT_IS_DEFAULT(rt))
have_default = 1;
/* no need to add it back to our routing table
script_runreason(ifp, "TEST");
goto handle_flag;
}
- if (options & DHCPCD_IPV6RA_OWN)
+ if (ifp->options->options & DHCPCD_IPV6RA_OWN)
ipv6ns_probeaddrs(&rap->addrs);
ipv6_buildroutes();
}
int
-check_ipv6(const char *ifname)
+check_ipv6(const char *ifname, int own)
{
- static int ipv6_checked = 0;
- int r;
+ static int set_restore = 0, forward_warned = 0, global_ra = 0;
+ int ra, forward;
- /* BSD doesn't support these values per iface, so just return 1 */
+ /* BSD doesn't support these values per iface, so just return
+ * the global ra setting */
if (ifname)
- return 1;
-
- if (ipv6_checked)
- return 1;
- ipv6_checked = 1;
+ return global_ra;
- r = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
- if (r == -1)
+ ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
+ if (ra == -1)
/* The sysctl probably doesn't exist, but this isn't an
* error as such so just log it and continue */
syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
"IPV6CTL_ACCEPT_RTADV: %m");
- else if (r == 0)
- options |= DHCPCD_IPV6RA_OWN;
- else if (options & DHCPCD_IPV6RA_OWN) {
+ else if (ra != 0 && own) {
syslog(LOG_INFO, "disabling Kernel IPv6 RA support");
if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) {
syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
- return 0;
+ return ra;
+ }
+ if (!set_restore) {
+ set_restore = 1;
+ atexit(restore_kernel_ra);
}
- atexit(restore_kernel_ra);
+ ra = 0;
}
-
- r = get_inet6_sysctl(IPV6CTL_FORWARDING);
- if (r == -1)
- /* The sysctl probably doesn't exist, but this isn't an
- * error as such so just log it and continue */
- syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
- "IPV6CTL_FORWARDING: %m");
- else if (r != 0) {
- syslog(LOG_WARNING,
- "Kernel is configured as a router, not a host");
- return 0;
+ if (ifname == NULL)
+ global_ra = ra;
+
+ if (!forward_warned) {
+ forward = get_inet6_sysctl(IPV6CTL_FORWARDING);
+ if (forward == -1)
+ /* The sysctl probably doesn't exist, but this isn't an
+ * error as such so just log it and continue */
+ syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
+ "IPV6CTL_FORWARDING: %m");
+ else if (forward != 0) {
+ forward_warned = 1;
+ syslog(LOG_WARNING,
+ "Kernel is configured as a router, not a host");
+ }
}
/* Flush the kernel knowledge of advertised routers */
ipv6_ra_flush();
- return 1;
+ return ra;
}
int
}
int
-check_ipv6(const char *ifname)
+check_ipv6(const char *ifname, int own)
{
static int ipv6_checked = 0;
- int r, ex, i;
+ int ra, forward, ex, i;
char path[256], *p, **nrest;
if (ifname == NULL) {
ex = 0;
snprintf(path, sizeof(path), "%s/%s/accept_ra", prefix, ifname);
- r = check_proc_int(path);
- if (r == -1)
+ ra = check_proc_int(path);
+ if (ra == -1)
/* The sysctl probably doesn't exist, but this isn't an
* error as such so just log it and continue */
syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
"%s: %m", path);
- else if (r == 0)
- options |= DHCPCD_IPV6RA_OWN;
- else if (options & DHCPCD_IPV6RA_OWN) {
+ else if (ra != 0 && own) {
syslog(LOG_INFO, "%s: disabling Kernel IPv6 RA support",
ifname);
if (write_path(path, "0") == -1) {
syslog(LOG_ERR, "write_path: %s: %m", path);
- return 0;
+ return ra;
}
for (i = 0; i < nrestore; i++)
if (strcmp(restore[i], ifname) == 0)
}
forward:
- if (r != 2) {
+ if (ra != 2) {
snprintf(path, sizeof(path), "%s/%s/forwarding",
prefix, ifname);
- r = check_proc_int(path);
- if (r == -1) {
+ forward = check_proc_int(path);
+ if (forward == -1) {
/* The sysctl probably doesn't exist, but this isn't an
* error as such so just log it and continue */
syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
"%s: %m", path);
- } else if (r != 0) {
+ } else if (forward != 0) {
syslog(LOG_WARNING,
"%s: configured as a router, not a host", ifname);
return 0;
}
}
- return 1;
+ return ra;
}
int
char *hardware_platform(void);
#ifdef INET6
-int check_ipv6(const char *);
+int check_ipv6(const char *, int);
int ipv6_dadtransmits(const char *);
#else
#define check_ipv6(a) 0