]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Remove hardcoded IPv6 address flags and use a bitmask instead.
authorRoy Marples <roy@marples.name>
Fri, 31 May 2013 13:01:54 +0000 (13:01 +0000)
committerRoy Marples <roy@marples.name>
Fri, 31 May 2013 13:01:54 +0000 (13:01 +0000)
Only add delegated addresses once for each delegation.
When the kernel expires them we will see this via RTM_DELADDR and
remove the address from our list and thus the route.

dhcp6.c
ipv6.c
ipv6.h
ipv6ns.c
ipv6rs.c

diff --git a/dhcp6.c b/dhcp6.c
index 1e19c3662421a0ac654d4ae734f5f3bb34f64c3b..7fb4f47a9a38d0759273b55d91f2832904004d39 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -610,7 +610,7 @@ dhcp6_freedrop_addrs(struct interface *ifp, int drop)
                /* Only drop the address if no other RAs have assigned it.
                 * This is safe because the RA is removed from the list
                 * before we are called. */
-               if (drop && ap->onlink &&
+               if (drop && ap->flags & IPV6_AF_ONLINK &&
                    !dhcp6_addrexists(ap) &&
                    !ipv6rs_addrexists(ap))
                {
@@ -1088,10 +1088,10 @@ dhcp6_dadcallback(void *arg)
        struct dhcp6_state *state;
        int wascompleted;
 
-       wascompleted = ap->dadcompleted;
+       wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
        ipv6ns_cancelprobeaddr(ap);
-       ap->dadcompleted = 1;
-       if (ap->dad)
+       ap->flags |= IPV6_AF_DADCOMPLETED;
+       if (ap->flags & IPV6_AF_DUPLICATED)
                /* XXX FIXME
                 * We should decline the address */
                syslog(LOG_WARNING, "%s: DAD detected %s",
@@ -1108,7 +1108,7 @@ dhcp6_dadcallback(void *arg)
                    state->state == DH6S_DELEGATED)
                {
                        TAILQ_FOREACH(ap, &state->addrs, next) {
-                               if (!ap->dadcompleted) {
+                               if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
                                        wascompleted = 1;
                                        break;
                                }
@@ -1163,8 +1163,7 @@ dhcp6_findna(struct interface *ifp, const uint8_t *iaid,
                                break;
                        }
                        a->iface = ifp;
-                       a->new = 1;
-                       a->onlink = 1; /* XXX: suprised no DHCP opt for this */
+                       a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
                        a->dadcallback = dhcp6_dadcallback;
                        memcpy(a->iaid, iaid, sizeof(a->iaid));
                        memcpy(&a->addr.s6_addr, &in6.s6_addr,
@@ -1196,8 +1195,8 @@ dhcp6_findna(struct interface *ifp, const uint8_t *iaid,
                    iabuf, sizeof(iabuf));
                snprintf(a->saddr, sizeof(a->saddr),
                    "%s/%d", ia, a->prefix_len);
-               if (a->stale)
-                       a->stale = 0;
+               if (a->flags & IPV6_AF_STALE)
+                       a->flags &= ~IPV6_AF_STALE;
                else
                        TAILQ_INSERT_TAIL(&state->addrs, a, next);
                i++;
@@ -1239,8 +1238,7 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid,
                        break;
                }
                a->iface = ifp;
-               a->new = 1;
-               a->onlink = 0;
+               a->flags = IPV6_AF_NEW;
                a->dadcallback = dhcp6_dadcallback;
                memcpy(a->iaid, iaid, sizeof(a->iaid));
                p = D6_COPTION_DATA(o);
@@ -1340,7 +1338,7 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l,
                        }
                } else {
                        TAILQ_FOREACH(ap, &state->addrs, next) {
-                               ap->stale = 1;
+                               ap->flags |= IPV6_AF_STALE;
                        }
                        if (dhcp6_findna(ifp, iaid, p, ol) == 0) {
                                syslog(LOG_ERR,
@@ -1349,7 +1347,7 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l,
                                return -1;
                        }
                        TAILQ_FOREACH_SAFE(ap, &state->addrs, next, nap) {
-                               if (ap->stale) {
+                               if (ap->flags & IPV6_AF_STALE) {
                                        TAILQ_REMOVE(&state->addrs, ap, next);
                                        if (ap->dadcallback)
                                                eloop_q_timeout_delete(0, NULL,
@@ -1526,8 +1524,7 @@ dhcp6_delegate_addr(struct interface *ifp, const struct ipv6_addr *prefix,
                return NULL;
        }
        a->iface = ifp;
-       a->new = 1;
-       a->onlink = 1;
+       a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK;
        a->dadcallback = dhcp6_dadcallback;
        a->delegating_iface = ifs;
        memcpy(&a->iaid, &prefix->iaid, sizeof(a->iaid));
@@ -1830,7 +1827,7 @@ replyok:
 recv:
        stale = 1;
        TAILQ_FOREACH(ap, &state->addrs, next) {
-               if (ap->new) {
+               if (ap->flags & IPV6_AF_NEW) {
                        stale = 0;
                        break;
                }
@@ -1918,7 +1915,9 @@ recv:
                len = 1;
                /* If all addresses have completed DAD run the script */
                TAILQ_FOREACH(ap, &state->addrs, next) {
-                       if (ap->onlink && ap->dadcompleted == 0) {
+                       if (ap->flags & IPV6_AF_ONLINK &&
+                           (ap->flags & IPV6_AF_DADCOMPLETED) == 0)
+                       {
                                len = 0;
                                break;
                        }
diff --git a/ipv6.c b/ipv6.c
index c7a515b638a6fc7bcd4d1cebd1912228248748f1..13ae7c1baf7f8cbafb41aeeba2b7eed6a41b9fb8 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -235,14 +235,16 @@ int
 ipv6_addaddr(struct ipv6_addr *ap)
 {
 
-       syslog(ap->new ? LOG_INFO : LOG_DEBUG,
+       syslog(ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
            "%s: adding address %s", ap->iface->name, ap->saddr);
        if (add_address6(ap->iface, ap) == -1) {
                syslog(LOG_ERR, "add_address6 %m");
                return -1;
        }
-       ap->new = 0;
-       ap->added = 1;
+       ap->flags &= ~IPV6_AF_NEW;
+       ap->flags |= IPV6_AF_ADDED;
+       if (ap->delegating_iface)
+               ap->flags |= IPV6_AF_DELEGATED;
        if (ipv6_removesubnet(ap->iface, ap) == -1)
                syslog(LOG_ERR,"ipv6_removesubnet %m");
        syslog(LOG_DEBUG,
@@ -260,7 +262,8 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs)
        i = 0;
        TAILQ_FOREACH(ap, addrs, next) {
                if (ap->prefix_vltime == 0 ||
-                   IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
+                   IN6_IS_ADDR_UNSPECIFIED(&ap->addr) ||
+                   ap->flags & IPV6_AF_DELEGATED)
                        continue;
                if (ipv6_addaddr(ap) == 0)
                        i++;
@@ -441,7 +444,7 @@ ipv6_handleifa_addrs(int cmd,
        found = 0;
        TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
                if (!IN6_ARE_ADDR_EQUAL(addr, &ap->addr)) {
-                       if (ap->dadcompleted == 0)
+                       if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0)
                                alldadcompleted = 0;
                        continue;
                }
@@ -456,15 +459,15 @@ ipv6_handleifa_addrs(int cmd,
                        /* Safety - ignore tentative announcements */
                        if (flags & IN6_IFF_TENTATIVE)
                                break;
-                       if (!ap->dadcompleted) {
+                       if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
                                found++;
-                               if (flags & IN6_IFF_DUPLICATED && ap->dad == 0)
-                                       ap->dad = 1;
+                               if (flags & IN6_IFF_DUPLICATED)
+                                       ap->flags |= IPV6_AF_DUPLICATED;
                                if (ap->dadcallback)
                                        ap->dadcallback(ap);
                                /* We need to set this here in-case the
                                 * dadcallback function checks it */
-                               ap->dadcompleted = 1;
+                               ap->flags |= IPV6_AF_DADCOMPLETED;
                        }
                        break;
                }
@@ -654,7 +657,7 @@ ipv6_buildroutes1(struct rt6head *dnr, int expired)
                        continue;
                if (rap->iface->options->options & DHCPCD_IPV6RA_OWN) {
                        TAILQ_FOREACH(addr, &rap->addrs, next) {
-                               if (!addr->onlink)
+                               if ((addr->flags & IPV6_AF_ONLINK) == 0)
                                        continue;
                                rt = make_prefix(rap->iface, rap, addr);
                                if (rt)
@@ -701,7 +704,7 @@ ipv6_buildroutes(void)
                     d6_state->state == DH6S_DELEGATED))
                {
                        TAILQ_FOREACH(addr, &d6_state->addrs, next) {
-                               if (!addr->onlink ||
+                               if ((addr->flags & IPV6_AF_ONLINK) == 0 ||
                                    IN6_IS_ADDR_UNSPECIFIED(&addr->addr))
                                        continue;
                                rt = make_prefix(ifp, NULL, addr);
diff --git a/ipv6.h b/ipv6.h
index 38b9a989f0e16b200726e3d2fe6d0ae7ef4b0580..74af1e36fe4c66ccb8e571dbeade3944d6c99d60 100644 (file)
--- a/ipv6.h
+++ b/ipv6.h
@@ -76,24 +76,27 @@ struct ipv6_addr {
        uint32_t prefix_vltime;
        uint32_t prefix_pltime;
        struct in6_addr addr;
-       uint8_t onlink;
-       uint8_t new;
-       uint8_t stale;
+       short flags;
        char saddr[INET6_ADDRSTRLEN];
-       uint8_t added;
-       uint8_t autoconf;
        uint8_t iaid[4];
        struct interface *delegating_iface;
 
        void (*dadcallback)(void *);
-       uint8_t dad;
-       uint8_t dadcompleted;
        uint8_t *ns;
        size_t nslen;
        int nsprobes;
 };
 TAILQ_HEAD(ipv6_addrhead, ipv6_addr);
 
+#define IPV6_AF_ONLINK         0x0001
+#define        IPV6_AF_NEW             0x0002
+#define IPV6_AF_STALE          0x0004
+#define IPV6_AF_ADDED          0x0008
+#define IPV6_AF_AUTOCONF       0x0010
+#define IPV6_AF_DUPLICATED     0x0020
+#define IPV6_AF_DADCOMPLETED   0x0040
+#define IPV6_AF_DELEGATED      0x0080
+
 struct rt6 {
        TAILQ_ENTRY(rt6) next;
        struct in6_addr dest;
index 00748819bde12b1a5bd93a336e4a161bbf238b2e..7e9d4b01b9ef234aedb15c8fd0943f11675c476b 100644 (file)
--- a/ipv6ns.c
+++ b/ipv6ns.c
@@ -261,7 +261,8 @@ ipv6ns_probeaddr(void *arg)
 #endif
 
        if (ap->dadcallback &&
-           (ap->new == 0 || ap->nsprobes >= ap->iface->options->dadtransmits))
+           ((ap->flags & IPV6_AF_NEW) == 0 ||
+           ap->nsprobes >= ap->iface->options->dadtransmits))
        {
 #ifdef IPV6_SEND_DAD
                ap->dadcallback(ap);
@@ -274,7 +275,7 @@ ipv6ns_probeaddr(void *arg)
        if (ipv6ns_open() == -1)
                return;
 
-       ap->dadcompleted = 0;
+       ap->flags &= ~IPV6_AF_DADCOMPLETED;
 
 #ifdef IPV6_SEND_DAD
        if (!ap->ns) {
@@ -386,10 +387,11 @@ ipv6ns_probeaddrs(struct ipv6_addrhead *addrs)
        i = 0;
        TAILQ_FOREACH(ap, addrs, next) {
                if (ap->prefix_vltime == 0 ||
-                   IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
+                   IN6_IS_ADDR_UNSPECIFIED(&ap->addr) ||
+                   ap->flags & IPV6_AF_DELEGATED)
                        continue;
                ipv6ns_probeaddr(ap);
-               if (ap->new)
+               if (ap->flags & IPV6_AF_NEW)
                        i++;
        }
 
index 6c4758629171dcd014f62a37163ef5b4eaefdc15..a31cd3615e1d061c076e8d3b4878e71f1af13010 100644 (file)
--- a/ipv6rs.c
+++ b/ipv6rs.c
@@ -318,7 +318,7 @@ ipv6rs_freedrop_addrs(struct ra *rap, int drop)
                /* Only drop the address if no other RAs have assigned it.
                 * This is safe because the RA is removed from the list
                 * before we are called. */
-               if (drop && ap->added &&
+               if (drop && ap->flags & IPV6_AF_ADDED &&
                    !IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
                    !ipv6rs_addrexists(ap) && !dhcp6_addrexists(ap))
                {
@@ -414,7 +414,7 @@ ipv6rs_scriptrun(const struct ra *rap)
 
        /* If all addresses have completed DAD run the script */
        TAILQ_FOREACH(ap, &rap->addrs, next) {
-               if (ap->dadcompleted == 0) {
+               if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
                        syslog(LOG_DEBUG,
                            "%s: waiting for Router Advertisement"
                            " DAD to complete",
@@ -461,10 +461,10 @@ ipv6rs_dadcallback(void *arg)
        struct ra *rap;
        int wascompleted, found;
 
-       wascompleted = ap->dadcompleted;
+       wascompleted = (ap->flags & IPV6_AF_DADCOMPLETED);
        ipv6ns_cancelprobeaddr(ap);
-       ap->dadcompleted = 1;
-       if (ap->dad)
+       ap->flags |= IPV6_AF_DADCOMPLETED;
+       if (ap->flags & IPV6_AF_DUPLICATED)
                /* No idea what how to try and make another address :( */
                syslog(LOG_WARNING, "%s: DAD detected %s",
                    ap->iface->name, ap->saddr);
@@ -481,7 +481,7 @@ ipv6rs_dadcallback(void *arg)
                                continue;
                        wascompleted = 1;
                        TAILQ_FOREACH(rapap, &rap->addrs, next) {
-                               if (!rapap->dadcompleted) {
+                               if ((rapap->flags & IPV6_AF_DADCOMPLETED) == 0){
                                        wascompleted = 0;
                                        break;
                                }
@@ -741,9 +741,7 @@ ipv6rs_handledata(__unused void *arg)
                                        break;
                                }
                                ap->iface = rap->iface;
-                               ap->new = 1;
-                               ap->onlink = 0;
-                               ap->autoconf = 1;
+                               ap->flags = IPV6_AF_NEW | IPV6_AF_AUTOCONF;
                                ap->prefix_len = pi->nd_opt_pi_prefix_len;
                                memcpy(ap->prefix.s6_addr,
                                   pi->nd_opt_pi_prefix.s6_addr,
@@ -774,19 +772,19 @@ ipv6rs_handledata(__unused void *arg)
                            ntohl(pi->nd_opt_pi_valid_time) ||
                            ap->prefix_pltime !=
                            ntohl(pi->nd_opt_pi_preferred_time) ||
-                           ap->dad)
+                           ap->flags & IPV6_AF_DUPLICATED)
                        {
-                               ap->new = 1;
+                               ap->flags |= IPV6_AF_NEW;
                        }
                        if (pi->nd_opt_pi_flags_reserved &
                            ND_OPT_PI_FLAG_ONLINK)
-                               ap->onlink = 1;
+                               ap->flags |= IPV6_AF_ONLINK;
                        ap->prefix_vltime =
                            ntohl(pi->nd_opt_pi_valid_time);
                        ap->prefix_pltime =
                            ntohl(pi->nd_opt_pi_preferred_time);
                        ap->nsprobes = 0;
-                       ap->dad = 0;
+                       ap->flags &= ~IPV6_AF_DUPLICATED;
                        if (opt) {
                                l = strlen(opt);
                                tmp = realloc(opt,