summaryrefslogtreecommitdiffstats
path: root/ipv6rs.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2013-05-16 10:31:21 +0000
committerRoy Marples <roy@marples.name>2013-05-16 10:31:21 +0000
commitd8194bcd39a1dbb7230a5e7ea7af4c7f72899b42 (patch)
tree62b9a003a4bc0fb8259f5865ade7a165ac3db49b /ipv6rs.c
parente3e77f7290b771906f828a9a6df789142dcc8d8d (diff)
downloaddhcpcd-d8194bcd39a1dbb7230a5e7ea7af4c7f72899b42.tar.xz
Check address flags for tentative and duplicates bits for sanity.
Handle the actual trigger to callout dhcpcd-run-hooks in the DAD callback instead of on receipt of RTM_NEWADDR directly. This is more code, but it allows us to use our own DAD engine if we need to.
Diffstat (limited to 'ipv6rs.c')
-rw-r--r--ipv6rs.c83
1 files changed, 55 insertions, 28 deletions
diff --git a/ipv6rs.c b/ipv6rs.c
index b57592c5..1688ac91 100644
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -256,7 +256,7 @@ ipv6rs_sendprobe(void *arg)
cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));
- syslog(LOG_INFO, "%s: sending IPv6 Router Solicitation", ifp->name);
+ syslog(LOG_INFO, "%s: sending Router Solicitation", ifp->name);
if (sendmsg(sock, &sndhdr, 0) == -1) {
syslog(LOG_ERR, "%s: sendmsg: %m", ifp->name);
ipv6rs_drop(ifp);
@@ -394,23 +394,6 @@ add_router(struct ra *router)
}
static void
-ipv6rs_dadcallback(void *arg)
-{
- struct ipv6_addr *ap = arg;
-
- ipv6ns_cancelprobeaddr(ap);
- ap->dadcompleted = 1;
- if (ap->dad)
- /* No idea what how to try and make another address :( */
- syslog(LOG_WARNING, "%s: DAD detected %s",
- ap->iface->name, ap->saddr);
-#ifdef IPV6_SEND_DAD
- else
- ipv6_addaddr(ap);
-#endif
-}
-
-static void
ipv6rs_scriptrun(const struct ra *rap)
{
int hasdns;
@@ -419,8 +402,12 @@ ipv6rs_scriptrun(const struct ra *rap)
/* If all addresses have completed DAD run the script */
TAILQ_FOREACH(ap, &rap->addrs, next) {
- if (ap->dadcompleted == 0)
+ if (ap->dadcompleted == 0) {
+ syslog(LOG_DEBUG, "%s: waiting for Router Advertisement"
+ " DAD to complete",
+ rap->iface->name);
return;
+ }
}
/* If we don't require RDNSS then set hasdns = 1 so we fork */
@@ -453,6 +440,52 @@ ipv6rs_scriptrun(const struct ra *rap)
#endif
}
+static void
+ipv6rs_dadcallback(void *arg)
+{
+ struct ipv6_addr *ap = arg, *rapap;
+ struct interface *ifp;
+ struct ra *rap;
+ int wascompleted, found;
+
+ wascompleted = ap->dadcompleted;
+ ipv6ns_cancelprobeaddr(ap);
+ ap->dadcompleted = 1;
+ if (ap->dad)
+ /* No idea what how to try and make another address :( */
+ syslog(LOG_WARNING, "%s: DAD detected %s",
+ ap->iface->name, ap->saddr);
+#ifdef IPV6_SEND_DAD
+ else
+ ipv6_addaddr(ap);
+#endif
+
+ if (!wascompleted) {
+ ifp = ap->iface;
+
+ TAILQ_FOREACH(rap, &ipv6_routers, next) {
+ if (rap->iface != ifp)
+ continue;
+ wascompleted = 1;
+ TAILQ_FOREACH(rapap, &rap->addrs, next) {
+ if (!rapap->dadcompleted) {
+ wascompleted = 0;
+ break;
+ }
+ if (rapap == ap)
+ found = 1;
+ }
+
+ if (wascompleted && found && rap->lifetime) {
+ syslog(LOG_DEBUG,
+ "%s: Router Advertisement DAD completed",
+ rap->iface->name);
+ ipv6rs_scriptrun(rap);
+ }
+ }
+ }
+}
+
/* ARGSUSED */
static void
ipv6rs_handledata(__unused void *arg)
@@ -1081,21 +1114,15 @@ ipv6rs_findsameaddr(const struct ipv6_addr *ap)
}
void
-ipv6rs_handleifa(int cmd, const char *ifname, const struct in6_addr *addr)
+ipv6rs_handleifa(int cmd, const char *ifname,
+ const struct in6_addr *addr, int flags)
{
struct ra *rap;
- int found;
TAILQ_FOREACH(rap, &ipv6_routers, next) {
if (strcmp(rap->iface->name, ifname))
continue;
- found = ipv6_handleifa_addrs(cmd, &rap->addrs, addr);
- if (found && rap->lifetime) {
- syslog(LOG_DEBUG,
- "%s: IPv6 Router Advertisement DAD completed",
- rap->iface->name);
- ipv6rs_scriptrun(rap);
- }
+ ipv6_handleifa_addrs(cmd, &rap->addrs, addr, flags);
}
}