summaryrefslogtreecommitdiffstats
path: root/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2015-09-12 20:21:02 +0000
committerRoy Marples <roy@marples.name>2015-09-12 20:21:02 +0000
commit1c37d02e330f1788b499563ab7b680ddedd9129d (patch)
tree6c5bf202fb8dec00a67237186f492a489eec0731 /ipv6.c
parentf5e909a57f2b73cb7bffab2177d0aead3a72841e (diff)
downloaddhcpcd-1c37d02e330f1788b499563ab7b680ddedd9129d.tar.xz
If we can toggle the automatic creation of the lladdr by the kernel then
we can remove the lladdr at carrier down and only add it at carrier up. This allows us to ensure the lladdr undergoes DaD and we can randomise it per SSID if we need to.
Diffstat (limited to 'ipv6.c')
-rw-r--r--ipv6.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/ipv6.c b/ipv6.c
index 2172f1cb..5b63cdf5 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -102,6 +102,16 @@
# endif
#endif
+#if defined(HAVE_IFLA_AF_SPEC) || defined(ND6_IFF_AUTO_LINKLOCAL)
+/* If we're using a private SLAAC address on wireless,
+ * don't add it until we have associated as we randomise
+ * it based on the SSID. */
+#define CAN_ADD_LLADDR(ifp) \
+ (!((ifp)->options->options & DHCPCD_SLAACPRIVATE) || \
+ (ifp)->carrier != LINK_DOWN)
+#else
+#define CAN_ADD_LLADDR(ifp) (1)
+#endif
#ifdef IPV6_MANAGETEMPADDR
static void ipv6_regentempifid(void *);
@@ -882,10 +892,12 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
(DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
(DHCPCD_EXITING | DHCPCD_PERSISTENT))
{
- if (drop == 2)
- TAILQ_REMOVE(addrs, ap, next);
/* Don't drop link-local addresses. */
- if (!IN6_IS_ADDR_LINKLOCAL(&ap->addr)) {
+ if (!(IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
+ CAN_ADD_LLADDR(ap->iface)))
+ {
+ if (drop == 2)
+ TAILQ_REMOVE(addrs, ap, next);
/* Find the same address somewhere else */
apf = ipv6_findaddr(ap->iface->ctx, &ap->addr,
0);
@@ -900,9 +912,9 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
&now);
ipv6_addaddr(apf, &now);
}
+ if (drop == 2)
+ ipv6_freeaddr(ap);
}
- if (drop == 2)
- ipv6_freeaddr(ap);
}
if (drop != 2)
ipv6_freeaddr(ap);
@@ -945,11 +957,13 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
struct ll_callback *cb;
#if 0
- char buf[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &addr->s6_addr,
- buf, INET6_ADDRSTRLEN);
- logger(ctx, LOG_DEBUG, "%s: cmd %d addr %s flags %d",
- ifname, cmd, buf, flags);
+ char dbuf[INET6_ADDRSTRLEN];
+ const char *dbp;
+
+ dbp = inet_ntop(AF_INET6, &addr->s6_addr,
+ dbuf, INET6_ADDRSTRLEN);
+ logger(ctx, LOG_INFO, "%s: cmd %d addr %s flags %d",
+ ifname, cmd, dbp, flags);
#endif
if (ifs == NULL)
@@ -1277,7 +1291,9 @@ ipv6_start(struct interface *ifp)
} else
ap = NULL;
- if (ap == NULL && ipv6_addlinklocal(ifp) == -1)
+ if (ap == NULL &&
+ CAN_ADD_LLADDR(ifp) &&
+ ipv6_addlinklocal(ifp) == -1)
return -1;
/* Load existing routes */
@@ -1299,7 +1315,7 @@ ipv6_freedrop(struct interface *ifp, int drop)
ipv6_freedrop_addrs(&state->addrs, drop ? 2 : 0, NULL);
- /* Becuase we need to cache the addresses we don't control,
+ /* Because we need to cache the addresses we don't control,
* we only free the state on when NOT dropping addresses. */
if (drop == 0) {
while ((cb = TAILQ_FIRST(&state->ll_callbacks))) {