summaryrefslogtreecommitdiffstats
path: root/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2013-05-16 10:31:21 +0000
committerRoy Marples <roy@marples.name>2013-05-16 10:31:21 +0000
commitd8194bcd39a1dbb7230a5e7ea7af4c7f72899b42 (patch)
tree62b9a003a4bc0fb8259f5865ade7a165ac3db49b /ipv6.c
parente3e77f7290b771906f828a9a6df789142dcc8d8d (diff)
downloaddhcpcd-d8194bcd39a1dbb7230a5e7ea7af4c7f72899b42.tar.xz
Check address flags for tentative and duplicates bits for sanity.
Handle the actual trigger to callout dhcpcd-run-hooks in the DAD callback instead of on receipt of RTM_NEWADDR directly. This is more code, but it allows us to use our own DAD engine if we need to.
Diffstat (limited to 'ipv6.c')
-rw-r--r--ipv6.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/ipv6.c b/ipv6.c
index 5e201b19..4a6a57e2 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -34,6 +34,11 @@
#ifdef __linux__
# include <asm/types.h> /* for systems with broken headers */
# include <linux/rtnetlink.h>
+ /* Match Linux defines to BSD */
+# define IN6_IFF_TENTATIVE IFA_F_TENTATIVE | IFA_F_OPTIMISTIC
+# define IN6_IFF_DUPLICATED IFA_F_DADFAILED
+#else
+# include <netinet6/in6_var.h>
#endif
#include <errno.h>
@@ -292,16 +297,17 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs)
}
void
-ipv6_handleifa(int cmd, const char *ifname, const struct in6_addr *addr)
+ipv6_handleifa(int cmd, const char *ifname,
+ const struct in6_addr *addr, int flags)
{
- ipv6rs_handleifa(cmd, ifname, addr);
- dhcp6_handleifa(cmd, ifname, addr);
+ ipv6rs_handleifa(cmd, ifname, addr, flags);
+ dhcp6_handleifa(cmd, ifname, addr, flags);
}
int
ipv6_handleifa_addrs(int cmd,
- struct ipv6_addrhead *addrs, const struct in6_addr *addr)
+ struct ipv6_addrhead *addrs, const struct in6_addr *addr, int flags)
{
struct ipv6_addr *ap, *apn;
uint8_t found, alldadcompleted;
@@ -324,8 +330,17 @@ ipv6_handleifa_addrs(int cmd,
free(ap);
break;
case RTM_NEWADDR:
+ /* Safety - ignore tentative announcements */
+ if (flags & IN6_IFF_TENTATIVE)
+ break;
if (!ap->dadcompleted) {
found++;
+ if (flags & IN6_IFF_DUPLICATED && ap->dad == 0)
+ ap->dad = 1;
+ if (ap->dadcallback)
+ ap->dadcallback(ap);
+ /* We need to set this here in-case the
+ * dadcallback function checks it */
ap->dadcompleted = 1;
}
}