diff options
| author | Roy Marples <roy@marples.name> | 2014-11-03 11:58:10 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2014-11-03 11:58:10 +0000 |
| commit | 90bd98e37daab71d177993810474790599e0495a (patch) | |
| tree | f33c471118713cebfa832239c07332fbab100f43 /ipv6.c | |
| parent | 7a1ae5f5e0cb48b7b21631701f2c67e5441b3962 (diff) | |
| download | dhcpcd-90bd98e37daab71d177993810474790599e0495a.tar.xz | |
If the IPv6 LL address is duplicated and using SLAAC private addressing,
increament the DAD counter and get a new address.
Otherwise return a suitable error.
Diffstat (limited to 'ipv6.c')
| -rw-r--r-- | ipv6.c | 26 |
1 files changed, 25 insertions, 1 deletions
@@ -982,7 +982,7 @@ static int ipv6_addlinklocal(struct interface *ifp) { struct ipv6_state *state; - struct ipv6_addr *ap; + struct ipv6_addr *ap, *ap2; int dadcounter; if (ipv6_linklocal(ifp)) @@ -1020,6 +1020,7 @@ ipv6_addlinklocal(struct interface *ifp) if (ifp->options->options & DHCPCD_SLAACPRIVATE) { dadcounter = 0; +nextslaacprivate: if (ipv6_makestableprivate(&ap->addr, &ap->prefix, ap->prefix_len, ifp, &dadcounter) == -1) { @@ -1054,6 +1055,29 @@ ipv6_addlinklocal(struct interface *ifp) EUI64_TO_IFID(&ap->addr); } + /* Do we already have this address? */ + TAILQ_FOREACH(ap2, &state->addrs, next) { + if (IN6_ARE_ADDR_EQUAL(&ap->addr, &ap2->addr)) { + if (ap2->addr_flags & IN6_IFF_DUPLICATED) { + if (ifp->options->options & + DHCPCD_SLAACPRIVATE) + { + dadcounter++; + goto nextslaacprivate; + } + free(ap); + errno = EADDRNOTAVAIL; + return -1; + } + + syslog(LOG_WARNING, "%s: waiting for %s to complete", + ap2->iface->name, ap2->saddr); + free(ap); + errno = EEXIST; + return 0; + } + } + inet_ntop(AF_INET6, &ap->addr, ap->saddr, sizeof(ap->saddr)); TAILQ_INSERT_TAIL(&state->addrs, ap, next); ipv6_addaddr(ap); |
