From: Roy Marples Date: Mon, 3 Nov 2014 11:58:10 +0000 (+0000) Subject: If the IPv6 LL address is duplicated and using SLAAC private addressing, X-Git-Tag: v6.6.1~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=90bd98e37daab71d177993810474790599e0495a;p=thirdparty%2Fdhcpcd.git 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. --- diff --git a/ipv6.c b/ipv6.c index dc39124f..08a0972d 100644 --- a/ipv6.c +++ b/ipv6.c @@ -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);