diff options
| author | Roy Marples <roy@marples.name> | 2013-05-16 10:31:21 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2013-05-16 10:31:21 +0000 |
| commit | d8194bcd39a1dbb7230a5e7ea7af4c7f72899b42 (patch) | |
| tree | 62b9a003a4bc0fb8259f5865ade7a165ac3db49b /ipv6.c | |
| parent | e3e77f7290b771906f828a9a6df789142dcc8d8d (diff) | |
| download | dhcpcd-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.c | 23 |
1 files changed, 19 insertions, 4 deletions
@@ -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; } } |
