From: Roy Marples Date: Fri, 31 May 2013 13:01:54 +0000 (+0000) Subject: Remove hardcoded IPv6 address flags and use a bitmask instead. X-Git-Tag: v5.99.7~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=46b8a6b7ae56617a728eb7fe1f7531beda794fe2;p=thirdparty%2Fdhcpcd.git Remove hardcoded IPv6 address flags and use a bitmask instead. 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. --- diff --git a/dhcp6.c b/dhcp6.c index 1e19c366..7fb4f47a 100644 --- 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 c7a515b6..13ae7c1b 100644 --- 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 38b9a989..74af1e36 100644 --- 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; diff --git a/ipv6ns.c b/ipv6ns.c index 00748819..7e9d4b01 100644 --- 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++; } diff --git a/ipv6rs.c b/ipv6rs.c index 6c475862..a31cd361 100644 --- 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,