]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
If we receieve an RA without a public prefix but with the Managed flag set,
authorRoy Marples <roy@marples.name>
Sat, 4 Apr 2015 21:40:47 +0000 (21:40 +0000)
committerRoy Marples <roy@marples.name>
Sat, 4 Apr 2015 21:40:47 +0000 (21:40 +0000)
ignore the RA until we recieve a DHCPv6 lease with a public address at
which point it is applied.

dhcp6.c
dhcp6.h
ipv6nd.c
ipv6nd.h

diff --git a/dhcp6.c b/dhcp6.c
index b588be7816e70ec2249c0d683f629acc6e61a107..7b94caf7cf2851771e0add6076b5d06c9986c543 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -487,6 +487,22 @@ dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
        return sla->prefix_len;
 }
 
+int
+dhcp6_has_public_addr(const struct interface *ifp)
+{
+       const struct dhcp6_state *state = D6_CSTATE(ifp);
+       const struct ipv6_addr *ia;
+
+       if (state == NULL)
+               return 0;
+       TAILQ_FOREACH(ia, &state->addrs, next) {
+               if (ia->prefix_pltime &&
+                   (ia->addr.s6_addr[0] & 0xfe) != 0xc)
+                       return 1;
+       }
+       return 0;
+}
+
 static int
 dhcp6_makemessage(struct interface *ifp)
 {
@@ -3033,6 +3049,7 @@ recv:
                        eloop_timeout_add_sec(ifp->ctx->eloop,
                            (time_t)state->expire, dhcp6_startexpire, ifp);
 
+               ipv6nd_runignoredra(ifp);
                ipv6_addaddrs(&state->addrs);
                dhcp6_delegate_prefix(ifp);
 
diff --git a/dhcp6.h b/dhcp6.h
index aee627a64d7860fd93fbdfaf037f0a837f18daa4..41b2213c106f13f69f12bb026275322b21ec1b44 100644 (file)
--- a/dhcp6.h
+++ b/dhcp6.h
@@ -235,6 +235,7 @@ void dhcp6_printoptions(const struct dhcpcd_ctx *,
 struct ipv6_addr *dhcp6_findaddr(struct dhcpcd_ctx *, const struct in6_addr *,
     short);
 size_t dhcp6_find_delegates(struct interface *);
+int dhcp6_has_public_addr(const struct interface *);
 int dhcp6_start(struct interface *, enum DH6S);
 void dhcp6_reboot(struct interface *);
 ssize_t dhcp6_env(char **, const char *, const struct interface *,
index 7b803471503b692ea7326e10ee479c700d5b3997..5f33d9fc39d5afe79d40dbf89bd023823f8dd5d2 100644 (file)
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -1136,8 +1136,9 @@ extra_opt:
        if (new_rap)
                add_router(ifp->ctx->ipv6, rap);
        if (!ipv6nd_ra_has_public_addr(rap) &&
-           !(rap->flags & ND_RA_FLAG_MANAGED) &&
-           !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC))
+           !(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
+           (!(rap->flags & ND_RA_FLAG_MANAGED) ||
+           !dhcp6_has_public_addr(rap->iface)))
        {
                logger(rap->iface->ctx,
                    rap->no_public_warned ? LOG_DEBUG : LOG_WARNING,
@@ -1194,6 +1195,34 @@ nodhcp6:
        ipv6nd_expirera(ifp);
 }
 
+/* Run RA's we ignored becuase they had no public addresses
+ * This should only be called when DHCPv6 applies a public address */
+void
+ipv6nd_runignoredra(struct interface *ifp)
+{
+       struct ra *rap;
+
+       TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
+               if (rap->iface == ifp &&
+                   !rap->expired &&
+                   rap->no_public_warned)
+               {
+                       rap->no_public_warned = 0;
+                       logger(rap->iface->ctx, LOG_INFO,
+                           "%s: applying ignored RA from %s",
+                           rap->iface->name, rap->sfrom);
+                       if (ifp->ctx->options & DHCPCD_TEST) {
+                               script_runreason(ifp, "TEST");
+                               continue;
+                       }
+                       if (ipv6nd_scriptrun(rap))
+                               return;
+                       eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+                       eloop_timeout_delete(ifp->ctx->eloop, NULL, rap);
+               }
+       }
+}
+
 int
 ipv6nd_hasra(const struct interface *ifp)
 {
index e1e74570385057fb2cc3e0bafa5bfd3804697a9e..cb71d746845264d730e7dc79f3a79f0dc070536a 100644 (file)
--- a/ipv6nd.h
+++ b/ipv6nd.h
@@ -94,6 +94,7 @@ ssize_t ipv6nd_free(struct interface *);
 void ipv6nd_expirera(void *arg);
 int ipv6nd_hasra(const struct interface *);
 int ipv6nd_hasradhcp(const struct interface *);
+void ipv6nd_runignoredra(struct interface *);
 void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
     const char *, const struct in6_addr *, int);
 int ipv6nd_dadcompleted(const struct interface *);