summaryrefslogtreecommitdiffstats
path: root/ipv6nd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2014-05-08 23:35:30 +0000
committerRoy Marples <roy@marples.name>2014-05-08 23:35:30 +0000
commit72c37f5f56ea5ca3c46bfc4c646be7ed1f1ef95c (patch)
tree7c24322fd2da8887461b151fd181377121f37247 /ipv6nd.c
parenta3ee6b2392dee5ed1fb5860a6166333a06ad2673 (diff)
downloaddhcpcd-72c37f5f56ea5ca3c46bfc4c646be7ed1f1ef95c.tar.xz
Support RTM_GETNEIGH on Linux as well as the polling for NUD changes on BSD.
Fixes [bb6153d18b].
Diffstat (limited to 'ipv6nd.c')
-rw-r--r--ipv6nd.c76
1 files changed, 55 insertions, 21 deletions
diff --git a/ipv6nd.c b/ipv6nd.c
index 07df8ab6..da3817b6 100644
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -317,39 +317,69 @@ ipv6nd_sendrsprobe(void *arg)
}
static void
+ipv6nd_reachable(struct ra *rap, int flags)
+{
+
+ if (flags & IPV6ND_REACHABLE) {
+ if (rap->lifetime && rap->expired) {
+ syslog(LOG_INFO, "%s: %s is reachable again",
+ rap->iface->name, rap->sfrom);
+ rap->expired = 0;
+ ipv6_buildroutes(rap->iface->ctx);
+ /* XXX Not really an RA */
+ script_runreason(rap->iface, "ROUTERADVERT");
+ }
+ } else {
+ /* Any error means it's really gone from the kernel
+ * neighbour database */
+ if (rap->lifetime && !rap->expired) {
+ syslog(LOG_WARNING,
+ "%s: %s is unreachable, expiring it",
+ rap->iface->name, rap->sfrom);
+ rap->expired = 1;
+ ipv6_buildroutes(rap->iface->ctx);
+ /* XXX Not really an RA */
+ script_runreason(rap->iface, "ROUTERADVERT");
+ }
+ }
+}
+
+#ifdef HAVE_RTM_GETNEIGH
+void
+ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags)
+{
+ struct ra *rap;
+
+ TAILQ_FOREACH(rap, ctx->ipv6->ra_routers, next) {
+ if (IN6_ARE_ADDR_EQUAL(&rap->from, addr)) {
+ ipv6nd_reachable(rap, flags);
+ break;
+ }
+ }
+}
+
+#else
+
+static void
ipv6nd_checkreachablerouters(void *arg)
{
struct dhcpcd_ctx *ctx = arg;
struct ra *rap;
+ int flags;
TAILQ_FOREACH(rap, ctx->ipv6->ra_routers, next) {
- if (if_nd6reachable(rap->iface->name, &rap->from) == 1) {
- if (rap->lifetime && rap->expired) {
- syslog(LOG_INFO, "%s: %s is reachable again",
- rap->iface->name, rap->sfrom);
- rap->expired = 0;
- ipv6_buildroutes(ctx);
- /* XXX Not really an RA */
- script_runreason(rap->iface, "ROUTERADVERT");
- }
- } else {
- /* Any error means it's really gone from the kernel
- * neighbour database */
- if (rap->lifetime && !rap->expired) {
- syslog(LOG_WARNING,
- "%s: %s is unreachable, expiring it",
- rap->iface->name, rap->sfrom);
- rap->expired = 1;
- ipv6_buildroutes(ctx);
- /* XXX Not really an RA */
- script_runreason(rap->iface, "ROUTERADVERT");
- }
+ flags = if_nd6reachable(rap->iface->name, &rap->from);
+ if (flags == -1) {
+ /* An error occured, so it's unreachable */
+ flags = 0;
}
+ ipv6nd_reachable(rap, flags);
}
eloop_timeout_add_sec(ctx->eloop, ND6REACHABLE_TIMER,
ipv6nd_checkreachablerouters, ctx);
}
+#endif
static void
ipv6nd_free_opts(struct ra *rap)
@@ -390,9 +420,11 @@ void ipv6nd_freedrop_ra(struct ra *rap, int drop)
eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap);
if (!drop)
TAILQ_REMOVE(rap->iface->ctx->ipv6->ra_routers, rap, next);
+#ifndef HAVE_RTM_GETNEIGH
if (TAILQ_FIRST(rap->iface->ctx->ipv6->ra_routers) == NULL)
eloop_timeout_delete(rap->iface->ctx->eloop,
ipv6nd_checkreachablerouters, rap->iface->ctx);
+#endif
ipv6_freedrop_addrs(&rap->addrs, drop, NULL);
ipv6nd_free_opts(rap);
free(rap->data);
@@ -983,8 +1015,10 @@ handle_flag:
/* Expire should be called last as the rap object could be destroyed */
ipv6nd_expirera(ifp);
+#ifndef HAVE_RTM_GETNEIGH
/* Start our reachability tests now */
ipv6nd_checkreachablerouters(ifp->ctx);
+#endif
}
int