From: Roy Marples Date: Wed, 27 Jul 2016 04:59:32 +0000 (+0000) Subject: Fix aliasing on Solaris. X-Git-Tag: v6.11.2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7458e7e97472ac5588d83d51427f58ab400fdc3f;p=thirdparty%2Fdhcpcd.git Fix aliasing on Solaris. --- diff --git a/ipv4.c b/ipv4.c index 6e9ce04e..a2c5e9e4 100644 --- a/ipv4.c +++ b/ipv4.c @@ -947,8 +947,6 @@ find_lun: else snprintf(alias, sizeof(alias), "%s:%u", ia->iface->name, lun); TAILQ_FOREACH(iap, &state->addrs, next) { - if (iap->iface != ia->iface) - continue; if (iap->addr.s_addr == INADDR_ANY) { /* No address assigned? Lets use it. */ strlcpy(ia->alias, iap->alias, sizeof(ia->alias)); @@ -959,6 +957,7 @@ find_lun: if (strcmp(iap->alias, alias) == 0) break; } + if (iap != NULL) { if (lun == UINT_MAX) { errno = ERANGE; @@ -967,6 +966,7 @@ find_lun: lun++; goto find_lun; } + strlcpy(ia->alias, alias, sizeof(ia->alias)); return 0; } diff --git a/ipv6.c b/ipv6.c index 30be5b2d..1561497b 100644 --- a/ipv6.c +++ b/ipv6.c @@ -747,6 +747,27 @@ ipv6_addaddr1(struct ipv6_addr *ap, const struct timespec *now) } #endif +#ifdef __sun + /* Solaris does not announce new addresses which need DaD + * so we need to take a copy and add it to our list. + * Otherwise aliasing gets confused if we add another + * address during DaD. */ + + state = IPV6_STATE(ap->iface); + TAILQ_FOREACH(nap, &state->addrs, next) { + if (IN6_ARE_ADDR_EQUAL(&nap->addr, &ap->addr)) + break; + } + if (nap == NULL) { + if ((nap = malloc(sizeof(*nap))) == NULL) { + syslog(LOG_ERR, "%s: malloc: %m", __func__); + return 0; /* Well, we did add the address */ + } + memcpy(nap, ap, sizeof(*nap)); + TAILQ_INSERT_TAIL(&state->addrs, nap, next); + } +#endif + return 0; } @@ -760,16 +781,28 @@ ipv6_aliasaddr(struct ipv6_addr *ia, struct ipv6_addr **repl) unsigned int unit; char alias[IF_NAMESIZE]; - unit = 0; + if (ia->alias[0] != '\0') + return 0; + state = IPV6_STATE(ia->iface); + + /* First find an existng address. + * This can happen when dhcpcd restarts as ND and DHCPv6 + * maintain their own lists of addresses. */ + TAILQ_FOREACH(iap, &state->addrs, next) { + if (IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr)) { + strlcpy(ia->alias, iap->alias, sizeof(ia->alias)); + return 0; + } + } + + unit = 0; find_unit: if (unit == 0) strlcpy(alias, ia->iface->name, sizeof(alias)); else snprintf(alias, sizeof(alias), "%s:%u", ia->iface->name, unit); TAILQ_FOREACH(iap, &state->addrs, next) { - if (iap->iface != ia->iface) - continue; if (IN6_IS_ADDR_UNSPECIFIED(&iap->addr)) { /* No address assigned? Lets use it. */ strlcpy(ia->alias, iap->alias, sizeof(ia->alias)); @@ -780,6 +813,7 @@ find_unit: if (strcmp(iap->alias, alias) == 0) break; } + if (iap != NULL) { if (unit == UINT_MAX) { errno = ERANGE; @@ -788,6 +822,7 @@ find_unit: unit++; goto find_unit; } + strlcpy(ia->alias, alias, sizeof(ia->alias)); return 0; }