From: Roy Marples Date: Tue, 31 Mar 2020 21:33:25 +0000 (+0100) Subject: ND: If a secondary router adds the same prefix, use it's address X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=67d90035be1ec5286de30b9e50094cae9223b83f;p=thirdparty%2Fdhcpcd.git ND: If a secondary router adds the same prefix, use it's address With slaac private, it will generate a new address which would be wrong. --- diff --git a/src/ipv6.c b/src/ipv6.c index 000db984..51b4c9b7 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -1509,17 +1509,26 @@ struct ipv6_addr * ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr, uint8_t prefix_len, unsigned int flags) { - struct ipv6_addr *ia; + struct ipv6_addr *ia, *iaf; char buf[INET6_ADDRSTRLEN]; const char *cbp; bool tempaddr; int addr_flags; +#ifdef IPV6_AF_TEMPORARY + tempaddr = flags & IPV6_AF_TEMPORARY; +#else + tempaddr = false; +#endif + /* If adding a new DHCP / RA derived address, check current flags * from an existing address. */ - ia = ipv6_iffindaddr(ifp, addr, 0); - if (ia != NULL) { - addr_flags = ia->addr_flags; + if (flags & IPV6_AF_AUTOCONF) + iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len); + else + iaf = ipv6_iffindaddr(ifp, addr, 0); + if (iaf != NULL) { + addr_flags = iaf->addr_flags; flags |= IPV6_AF_ADDED; } else addr_flags = IN6_IFF_TENTATIVE; @@ -1540,21 +1549,19 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr, TAILQ_INIT(&ia->pd_pfxs); #endif -#ifdef IPV6_AF_TEMPORARY - tempaddr = ia->flags & IPV6_AF_TEMPORARY; -#else - tempaddr = false; -#endif - if (prefix_len == 128) goto makepfx; else if (ia->flags & IPV6_AF_AUTOCONF && !tempaddr) { ia->prefix = *addr; - ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp, - &ia->prefix, - ia->prefix_len); - if (ia->dadcounter == -1) - goto err; + if (iaf != NULL) + memcpy(&ia->addr, &iaf->addr, sizeof(ia->addr)); + else { + ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp, + &ia->prefix, + ia->prefix_len); + if (ia->dadcounter == -1) + goto err; + } } else if (ia->flags & IPV6_AF_RAPFX) { ia->prefix = *addr; #ifdef __sun diff --git a/src/ipv6nd.c b/src/ipv6nd.c index ca5f4335..81a80550 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -746,6 +746,40 @@ ipv6nd_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr, return NULL; } +static struct ipv6_addr * +ipv6nd_rapfindprefix(struct ra *rap, + const struct in6_addr *pfx, uint8_t pfxlen) +{ + struct ipv6_addr *ia; + + TAILQ_FOREACH(ia, &rap->addrs, next) { + if (ia->prefix_vltime == 0) + continue; + if (ia->prefix_len == pfxlen && + IN6_ARE_ADDR_EQUAL(&ia->prefix, pfx)) + break; + } + return ia; +} + +struct ipv6_addr * +ipv6nd_iffindprefix(struct interface *ifp, + const struct in6_addr *pfx, uint8_t pfxlen) +{ + struct ra *rap; + struct ipv6_addr *ia; + + ia = NULL; + TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) { + if (rap->iface != ifp) + continue; + ia = ipv6nd_rapfindprefix(rap, pfx, pfxlen); + if (ia != NULL) + break; + } + return ia; +} + static void ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra) { @@ -1229,10 +1263,8 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, logmessage(loglevel, "%s: pltime > vltime", ifp->name); continue; } - TAILQ_FOREACH(ia, &rap->addrs, next) - if (ia->prefix_len == pi.nd_opt_pi_prefix_len && - IN6_ARE_ADDR_EQUAL(&ia->prefix, &pi_prefix)) - break; + ia = ipv6nd_rapfindprefix(rap, + &pi_prefix, pi.nd_opt_pi_prefix_len); if (ia == NULL) { unsigned int flags; diff --git a/src/ipv6nd.h b/src/ipv6nd.h index 0c85239d..bb14d7b3 100644 --- a/src/ipv6nd.h +++ b/src/ipv6nd.h @@ -112,6 +112,8 @@ const struct ipv6_addr *ipv6nd_iffindaddr(const struct interface *ifp, const struct in6_addr *addr, unsigned int flags); struct ipv6_addr *ipv6nd_findaddr(struct dhcpcd_ctx *, const struct in6_addr *, unsigned int); +struct ipv6_addr *ipv6nd_iffindprefix(struct interface *, + const struct in6_addr *, uint8_t); ssize_t ipv6nd_free(struct interface *); void ipv6nd_expirera(void *arg); bool ipv6nd_hasralifetime(const struct interface *, bool);