Skip to content

Commit 58230c2

Browse files
committed
IPv6: Don't set IN6_IFF_TENTATIVE when the address exists
We can only work it out when we know the address, not beforehand.
1 parent fdeb8c7 commit 58230c2

File tree

1 file changed

+40
-51
lines changed

1 file changed

+40
-51
lines changed

src/ipv6.c

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989

9090
#ifdef IPV6_POLLADDRFLAG
9191
# warning kernel does not report IPv6 address flag changes
92-
# warning polling tentative address flags periodically
9392
#endif
9493

9594
/* Hackery at it's finest. */
@@ -661,8 +660,7 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
661660
struct interface *ifp;
662661
uint32_t pltime, vltime;
663662
int loglevel;
664-
struct ipv6_state *state;
665-
struct ipv6_addr *ia2;
663+
struct ipv6_addr *iaf;
666664

667665
#ifdef __sun
668666
/* If we re-add then address on Solaris then the prefix
@@ -678,8 +676,9 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
678676
/* Remember the interface of the address. */
679677
ifp = ia->iface;
680678

681-
if (!(ia->flags & IPV6_AF_DADCOMPLETED) &&
682-
ipv6_iffindaddr(ifp, &ia->addr, IN6_IFF_NOTUSEABLE))
679+
/* Find any existing address. */
680+
iaf = ipv6_iffindaddr(ifp, &ia->addr, 0);
681+
if (iaf != NULL && !(iaf->addr_flags & IN6_IFF_NOTUSEABLE))
683682
ia->flags |= IPV6_AF_DADCOMPLETED;
684683

685684
/* Adjust plftime and vltime based on acquired time */
@@ -785,18 +784,15 @@ ipv6_addaddr1(struct ipv6_addr *ia, const struct timespec *now)
785784
/* Take a copy of the address and add it to our state if
786785
* it does not exist.
787786
* This is important if route overflow loses the message. */
788-
state = IPV6_STATE(ifp);
789-
TAILQ_FOREACH(ia2, &state->addrs, next) {
790-
if (IN6_ARE_ADDR_EQUAL(&ia2->addr, &ia->addr))
791-
break;
792-
}
793-
if (ia2 == NULL) {
794-
if ((ia2 = malloc(sizeof(*ia2))) == NULL) {
787+
if (iaf == NULL) {
788+
struct ipv6_state *state = IPV6_STATE(ifp);
789+
790+
if ((iaf = malloc(sizeof(*iaf))) == NULL) {
795791
logerr(__func__);
796792
return 0; /* Well, we did add the address */
797793
}
798-
memcpy(ia2, ia, sizeof(*ia2));
799-
TAILQ_INSERT_TAIL(&state->addrs, ia2, next);
794+
memcpy(iaf, ia, sizeof(*iaf));
795+
TAILQ_INSERT_TAIL(&state->addrs, iaf, next);
800796
}
801797

802798
return 0;
@@ -1330,17 +1326,19 @@ ipv6_iffindaddr(struct interface *ifp, const struct in6_addr *addr,
13301326
struct ipv6_addr *ap;
13311327

13321328
state = IPV6_STATE(ifp);
1333-
if (state) {
1334-
TAILQ_FOREACH(ap, &state->addrs, next) {
1335-
if (addr == NULL) {
1336-
if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
1337-
(!revflags || !(ap->addr_flags & revflags)))
1338-
return ap;
1339-
} else {
1340-
if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr) &&
1341-
(!revflags || !(ap->addr_flags & revflags)))
1342-
return ap;
1343-
}
1329+
if (state == NULL)
1330+
return NULL;
1331+
1332+
TAILQ_FOREACH(ap, &state->addrs, next) {
1333+
if (addr == NULL) {
1334+
if (IN6_IS_ADDR_LINKLOCAL(&ap->addr) &&
1335+
(!revflags || !(ap->addr_flags & revflags)))
1336+
return ap;
1337+
} else if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr)) {
1338+
/* This is our address so we will return now */
1339+
if (!revflags || !(ap->addr_flags & revflags))
1340+
return ap;
1341+
return NULL;
13441342
}
13451343
}
13461344
return NULL;
@@ -1606,38 +1604,13 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
16061604
struct ipv6_addr *ia, *iaf;
16071605
char buf[INET6_ADDRSTRLEN];
16081606
const char *cbp;
1609-
bool tempaddr;
1610-
int addr_flags;
1611-
1612-
#ifdef IPV6_AF_TEMPORARY
1613-
tempaddr = flags & IPV6_AF_TEMPORARY;
1614-
#else
1615-
tempaddr = false;
1616-
#endif
1617-
1618-
/* If adding a new DHCP / RA derived address, check current flags
1619-
* from an existing address. */
1620-
if (tempaddr)
1621-
iaf = NULL;
1622-
else if (flags & IPV6_AF_AUTOCONF)
1623-
iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len);
1624-
else
1625-
iaf = ipv6_iffindaddr(ifp, addr, 0);
1626-
if (iaf != NULL) {
1627-
addr_flags = iaf->addr_flags;
1628-
flags |= IPV6_AF_ADDED;
1629-
} else
1630-
addr_flags = IN6_IFF_TENTATIVE;
16311607

16321608
ia = calloc(1, sizeof(*ia));
16331609
if (ia == NULL)
16341610
goto err;
16351611

16361612
ia->iface = ifp;
1637-
ia->addr_flags = addr_flags;
16381613
ia->flags = IPV6_AF_NEW | flags;
1639-
if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
1640-
ia->flags |= IPV6_AF_DADCOMPLETED;
16411614
ia->prefix_len = prefix_len;
16421615
ia->dhcp6_fd = -1;
16431616

@@ -1649,6 +1622,7 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
16491622
goto makepfx;
16501623
else if (ia->flags & IPV6_AF_AUTOCONF) {
16511624
ia->prefix = *addr;
1625+
iaf = ipv6nd_iffindprefix(ifp, addr, prefix_len);
16521626
if (iaf != NULL)
16531627
memcpy(&ia->addr, &iaf->addr, sizeof(ia->addr));
16541628
else {
@@ -1666,7 +1640,7 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
16661640
cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf));
16671641
goto paddr;
16681642
#else
1669-
return ia;
1643+
goto flags;
16701644
#endif
16711645
} else if (ia->flags & (IPV6_AF_REQUEST | IPV6_AF_PFXDELEGATION)) {
16721646
ia->prefix = *addr;
@@ -1686,6 +1660,21 @@ ipv6_newaddr(struct interface *ifp, const struct in6_addr *addr,
16861660
goto err;
16871661
snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", cbp, ia->prefix_len);
16881662

1663+
#ifndef __sun
1664+
flags:
1665+
#endif
1666+
/* If adding a new DHCP / RA derived address, check current flags
1667+
* from an existing address. */
1668+
iaf = ipv6_iffindaddr(ifp, &ia->addr, 0);
1669+
if (iaf != NULL) {
1670+
ia->addr_flags = iaf->addr_flags;
1671+
ia->flags |= IPV6_AF_ADDED;
1672+
} else
1673+
ia->addr_flags |= IN6_IFF_TENTATIVE;
1674+
1675+
if (!(ia->addr_flags & IN6_IFF_NOTUSEABLE))
1676+
ia->flags |= IPV6_AF_DADCOMPLETED;
1677+
16891678
return ia;
16901679

16911680
err:

0 commit comments

Comments
 (0)