From: Roy Marples Date: Tue, 13 Jun 2017 19:47:49 +0000 (+0100) Subject: Make ipv6_newaddr() more flexable so it's the sole source of X-Git-Tag: v7.0.0-rc2~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=61564d343be63e1d35f34c5ac906d23c3cea792a;p=thirdparty%2Fdhcpcd.git Make ipv6_newaddr() more flexable so it's the sole source of creating ipv6_addr structures. --- diff --git a/src/dhcp6.c b/src/dhcp6.c index 8c712d99..2db1f97c 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -1387,8 +1387,6 @@ dhcp6_addrequestedaddrs(struct interface *ifp) size_t i; struct if_ia *ia; struct ipv6_addr *a; - char iabuf[INET6_ADDRSTRLEN]; - const char *iap; state = D6_STATE(ifp); /* Add any requested prefixes / addresses */ @@ -1397,26 +1395,7 @@ dhcp6_addrequestedaddrs(struct interface *ifp) if (!((ia->ia_type == D6_OPTION_IA_PD && ia->prefix_len) || !IN6_IS_ADDR_UNSPECIFIED(&ia->addr))) continue; - a = calloc(1, sizeof(*a)); - if (a == NULL) { - logerr(__func__); - return; - } - a->flags = IPV6_AF_REQUEST; - a->iface = ifp; - a->dadcallback = dhcp6_dadcallback; - memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid)); - a->ia_type = ia->ia_type; - //a->prefix_pltime = 0; - //a->prefix_vltime = 0; - - if (ia->ia_type == D6_OPTION_IA_PD) { - memcpy(&a->prefix, &ia->addr, sizeof(a->addr)); - a->prefix_len = ia->prefix_len; - iap = inet_ntop(AF_INET6, &a->prefix, - iabuf, sizeof(iabuf)); - } else { - memcpy(&a->addr, &ia->addr, sizeof(a->addr)); + a = ipv6_newaddr(ifp, &ia->addr, /* * RFC 5942 Section 5 * We cannot assume any prefix length, nor tie the @@ -1424,13 +1403,13 @@ dhcp6_addrequestedaddrs(struct interface *ifp) * before the address. * As such we just give it a 128 prefix. */ - a->prefix_len = 128; - ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len); - iap = inet_ntop(AF_INET6, &a->addr, - iabuf, sizeof(iabuf)); - } - snprintf(a->saddr, sizeof(a->saddr), - "%s/%d", iap, a->prefix_len); + ia->ia_type == D6_OPTION_IA_PD ? ia->prefix_len : 128, + IPV6_AF_REQUEST); + if (a == NULL) + continue; + a->dadcallback = dhcp6_dadcallback; + memcpy(&a->iaid, &ia->iaid, sizeof(a->iaid)); + a->ia_type = ia->ia_type; TAILQ_INSERT_TAIL(&state->addrs, a, next); } } @@ -1810,8 +1789,6 @@ dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid, uint8_t *o, *nd; uint16_t ol; struct ipv6_addr *a; - char iabuf[INET6_ADDRSTRLEN]; - const char *ias; int i; struct dhcp6_ia_addr ia; @@ -1843,19 +1820,6 @@ dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid, break; } if (a == NULL) { - a = calloc(1, sizeof(*a)); - if (a == NULL) { - logerr(__func__); - break; - } - a->iface = ifp; - a->flags = IPV6_AF_NEW | IPV6_AF_ONLINK; - a->dadcallback = dhcp6_dadcallback; - a->ia_type = ot; - memcpy(a->iaid, iaid, sizeof(a->iaid)); - a->addr = ia.addr; - a->created = *acquired; - /* * RFC 5942 Section 5 * We cannot assume any prefix length, nor tie the @@ -1863,12 +1827,11 @@ dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid, * before the address. * As such we just give it a 128 prefix. */ - a->prefix_len = 128; - ipv6_makeprefix(&a->prefix, &a->addr, a->prefix_len); - ias = inet_ntop(AF_INET6, &a->addr, - iabuf, sizeof(iabuf)); - snprintf(a->saddr, sizeof(a->saddr), - "%s/%d", ias, a->prefix_len); + a = ipv6_newaddr(ifp, &ia.addr, 128, IPV6_AF_ONLINK); + a->dadcallback = dhcp6_dadcallback; + a->ia_type = ot; + memcpy(a->iaid, iaid, sizeof(a->iaid)); + a->created = *acquired; TAILQ_INSERT_TAIL(&state->addrs, a, next); } else { @@ -1899,8 +1862,6 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, struct dhcp6_state *state; uint8_t *o, *nd; struct ipv6_addr *a; - char iabuf[INET6_ADDRSTRLEN]; - const char *ia; int i; uint8_t nb, *pw; uint16_t ol; @@ -1943,24 +1904,14 @@ dhcp6_findpd(struct interface *ifp, const uint8_t *iaid, } if (a == NULL) { - a = calloc(1, sizeof(*a)); - if (a == NULL) { - logerr(__func__); + a = ipv6_newaddr(ifp, &pdp_prefix, pdp.prefix_len, + IPV6_AF_DELEGATEDPFX); + if (a == NULL) break; - } - a->iface = ifp; - a->flags = IPV6_AF_NEW | IPV6_AF_DELEGATEDPFX; a->created = *acquired; a->dadcallback = dhcp6_dadcallback; a->ia_type = D6_OPTION_IA_PD; memcpy(a->iaid, iaid, sizeof(a->iaid)); - /* pdp.prefix is not aligned so use copy. */ - a->prefix = pdp_prefix; - a->prefix_len = pdp.prefix_len; - ia = inet_ntop(AF_INET6, &a->prefix, - iabuf, sizeof(iabuf)); - snprintf(a->saddr, sizeof(a->saddr), - "%s/%d", ia, a->prefix_len); TAILQ_INIT(&a->pd_pfxs); TAILQ_INSERT_TAIL(&state->addrs, a, next); } else { @@ -2452,8 +2403,6 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix, struct dhcp6_state *state; struct in6_addr addr, daddr; struct ipv6_addr *ia; - char sabuf[INET6_ADDRSTRLEN]; - const char *sa; int pfxlen, dadcounter; uint64_t vl; @@ -2501,17 +2450,12 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix, break; } if (ia == NULL) { - ia = calloc(1, sizeof(*ia)); - if (ia == NULL) { - logerr(__func__); + ia = ipv6_newaddr(ifp, &daddr, (uint8_t)pfxlen, IPV6_AF_ONLINK); + if (ia == NULL) return NULL; - } - ia->iface = ifp; - ia->flags = IPV6_AF_NEW | IPV6_AF_ONLINK; ia->dadcallback = dhcp6_dadcallback; memcpy(&ia->iaid, &prefix->iaid, sizeof(ia->iaid)); ia->created = prefix->acquired; - ia->addr = daddr; TAILQ_INSERT_TAIL(&state->addrs, ia, next); TAILQ_INSERT_TAIL(&prefix->pd_pfxs, ia, pd_next); @@ -2523,9 +2467,6 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix, ia->prefix_pltime = prefix->prefix_pltime; ia->prefix_vltime = prefix->prefix_vltime; - sa = inet_ntop(AF_INET6, &ia->addr, sabuf, sizeof(sabuf)); - snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", sa, ia->prefix_len); - /* If the prefix length hasn't changed, * don't install a reject route. */ if (prefix->prefix_len == pfxlen) diff --git a/src/ipv6.c b/src/ipv6.c index bd385694..b37610ae 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -379,7 +379,7 @@ ipv6_makeaddr(struct in6_addr *addr, struct interface *ifp, return 0; } -int +static int ipv6_makeprefix(struct in6_addr *prefix, const struct in6_addr *addr, int len) { int bytes, bits; @@ -1286,21 +1286,18 @@ ipv6_addlinklocalcallback(struct interface *ifp, static struct ipv6_addr * ipv6_newlinklocal(struct interface *ifp) { - struct ipv6_addr *ap; + struct ipv6_addr *ia; + struct in6_addr in6; - ap = calloc(1, sizeof(*ap)); - if (ap != NULL) { - ap->iface = ifp; - ap->prefix.s6_addr32[0] = htonl(0xfe800000); - ap->prefix.s6_addr32[1] = 0; - ap->prefix_len = 64; - ap->dadcounter = 0; - ap->prefix_pltime = ND6_INFINITE_LIFETIME; - ap->prefix_vltime = ND6_INFINITE_LIFETIME; - ap->flags = IPV6_AF_NEW; - ap->addr_flags = IN6_IFF_TENTATIVE; - } - return ap; + in6.s6_addr32[0] = htonl(0xfe800000); + in6.s6_addr32[1] = 0; + ia = ipv6_newaddr(ifp, &in6, 64, 0); + if (ia != NULL) { + ia->prefix_pltime = ND6_INFINITE_LIFETIME; + ia->prefix_vltime = ND6_INFINITE_LIFETIME; + ia->addr_flags = IN6_IFF_TENTATIVE; + } + return ia; } static const uint8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1445,31 +1442,56 @@ ipv6_tryaddlinklocal(struct interface *ifp) return ipv6_addlinklocal(ifp); } -static struct ipv6_addr * -ipv6_newaddr(struct interface *ifp, struct in6_addr *addr, uint8_t prefix_len) +struct ipv6_addr * +ipv6_newaddr(struct interface *ifp, struct in6_addr *addr, uint8_t prefix_len, + short flags) { struct ipv6_addr *ia; char buf[INET6_ADDRSTRLEN]; const char *cbp; - if ((ia = calloc(1, sizeof(*ia))) == NULL) - return NULL; + ia = calloc(1, sizeof(*ia)); + if (ia == NULL) + goto err; + ia->iface = ifp; - ia->flags = IPV6_AF_NEW; + ia->flags = IPV6_AF_NEW | flags; ia->addr_flags = IN6_IFF_TENTATIVE; - ia->addr = *addr; ia->prefix_len = prefix_len; - if (ipv6_makeprefix(&ia->prefix, &ia->addr, ia->prefix_len) == -1) { - free(ia); - return NULL; + + if (ia->flags & IPV6_AF_AUTOCONF) { + ia->prefix = *addr; + ia->dadcounter = ipv6_makeaddr(&ia->addr, ifp, + &ia->prefix, + ia->prefix_len); + if (ia->dadcounter == -1) + goto err; + } else if (ia->flags & IPV6_AF_RAPFX) { + ia->prefix = *addr; + return ia; + } else if (ia->flags & IPV6_AF_REQUEST && prefix_len != 128) { + ia->prefix = *addr; + cbp = inet_ntop(AF_INET6, &ia->prefix, buf, sizeof(buf)); + goto paddr; + } else { + ia->addr = *addr; + if (ipv6_makeprefix(&ia->prefix, + &ia->addr, ia->prefix_len) == -1) + goto err; } + cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf)); - if (cbp) - snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", - cbp, ia->prefix_len); - else - ia->saddr[0] = '\0'; +paddr: + if (cbp == NULL) + goto err; + snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", cbp, ia->prefix_len); + return ia; + +err: + logerr(__func__); + free(ia); + return NULL; } static void @@ -1569,7 +1591,7 @@ ipv6_startstatic(struct interface *ifp) struct ipv6_state *state; ia = ipv6_newaddr(ifp, &ifp->options->req_addr6, - ifp->options->req_prefix_len); + ifp->options->req_prefix_len, 0); if (ia == NULL) return -1; state = IPV6_STATE(ifp); @@ -1865,8 +1887,6 @@ ipv6_createtempaddr(struct ipv6_addr *ia0, const struct timespec *now) const struct ipv6_addr *ap; struct ipv6_addr *ia; uint32_t i, trylimit; - char buf[INET6_ADDRSTRLEN]; - const char *cbp; trylimit = TEMP_IDGEN_RETRIES; state = IPV6_STATE(ia0->iface); @@ -1913,17 +1933,11 @@ again: } } - if ((ia = calloc(1, sizeof(*ia))) == NULL) - return NULL; - - ia->iface = ia0->iface; - ia->addr = addr; + ia = ipv6_newaddr(ia0->iface, &addr, ia0->prefix_len, + IPV6_AF_AUTOCONF | IPV6_AF_TEMPORARY); /* Must be made tentative, for our DaD to work */ ia->addr_flags = IN6_IFF_TENTATIVE; ia->dadcallback = ipv6_tempdadcallback; - ia->flags = IPV6_AF_NEW | IPV6_AF_AUTOCONF | IPV6_AF_TEMPORARY; - ia->prefix = ia0->prefix; - ia->prefix_len = ia0->prefix_len; ia->created = ia->acquired = now ? *now : ia0->acquired; /* Ensure desync is still valid */ @@ -1943,11 +1957,6 @@ again: return NULL; } - cbp = inet_ntop(AF_INET6, &ia->addr, buf, sizeof(buf)); - if (cbp) - snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d", - cbp, ia->prefix_len); else ia->saddr[0] = '\0'; - TAILQ_INSERT_TAIL(&state->addrs, ia, next); return ia; } diff --git a/src/ipv6.h b/src/ipv6.h index bd0f900f..1855cc2b 100644 --- a/src/ipv6.h +++ b/src/ipv6.h @@ -165,6 +165,7 @@ struct ipv6_addr { char saddr[INET6_ADDRSTRLEN]; uint8_t iaid[4]; uint16_t ia_type; + int fd; #ifndef SMALL struct ipv6_addr *delegating_prefix; @@ -199,8 +200,9 @@ struct ipv6_addr { #define IPV6_AF_REQUEST 0x0400 #define IPV6_AF_STATIC 0x0800 #define IPV6_AF_DELEGATEDLOG 0x1000 +#define IPV6_AF_RAPFX 0x2000 #ifdef IPV6_MANAGETEMPADDR -#define IPV6_AF_TEMPORARY 0X2000 +#define IPV6_AF_TEMPORARY 0X4000 #endif struct ll_callback { @@ -236,7 +238,6 @@ int ipv6_makestableprivate(struct in6_addr *addr, const struct interface *ifp, int *dad_counter); int ipv6_makeaddr(struct in6_addr *, struct interface *, const struct in6_addr *, int); -int ipv6_makeprefix(struct in6_addr *, const struct in6_addr *, int); int ipv6_mask(struct in6_addr *, int); uint8_t ipv6_prefixlen(const struct in6_addr *); int ipv6_userprefix( const struct in6_addr *, short prefix_len, @@ -260,6 +261,8 @@ struct ipv6_addr *ipv6_findmaskaddr(struct dhcpcd_ctx *, const struct in6_addr *); #define ipv6_linklocal(ifp) ipv6_iffindaddr((ifp), NULL, IN6_IFF_NOTUSEABLE) int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *); +struct ipv6_addr *ipv6_newaddr(struct interface *, struct in6_addr *, uint8_t, + short); void ipv6_freeaddr(struct ipv6_addr *); void ipv6_freedrop(struct interface *, int); #define ipv6_free(ifp) ipv6_freedrop((ifp), 0) diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 5c9384fe..0884c9ab 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -733,8 +733,6 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nd_opt_mtu mtu; struct nd_opt_rdnss rdnss; uint8_t *p; - char buf[INET6_ADDRSTRLEN]; - const char *cbp; struct ra *rap; struct in6_addr pi_prefix; struct ipv6_addr *ap; @@ -943,48 +941,26 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, struct interface *ifp, IN6_ARE_ADDR_EQUAL(&ap->prefix, &pi_prefix)) break; if (ap == NULL) { + short flags; + if (!(pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && !(pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK)) continue; - ap = calloc(1, sizeof(*ap)); - if (ap == NULL) { - logerr(__func__); - break; - } - ap->iface = rap->iface; - ap->flags = IPV6_AF_NEW; - ap->prefix_len = pi.nd_opt_pi_prefix_len; - ap->prefix = pi_prefix; + + flags = IPV6_AF_RAPFX; if (pi.nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO && - ap->iface->options->options & + rap->iface->options->options & DHCPCD_IPV6RA_AUTOCONF) - { - ap->flags |= IPV6_AF_AUTOCONF; - ap->dadcounter = - ipv6_makeaddr(&ap->addr, ifp, - &ap->prefix, - pi.nd_opt_pi_prefix_len); - if (ap->dadcounter == -1) { - free(ap); - break; - } - cbp = inet_ntop(AF_INET6, - &ap->addr, - buf, sizeof(buf)); - if (cbp) - snprintf(ap->saddr, - sizeof(ap->saddr), - "%s/%d", - cbp, ap->prefix_len); - else - ap->saddr[0] = '\0'; - } else { - memset(&ap->addr, 0, sizeof(ap->addr)); - ap->saddr[0] = '\0'; - } + flags |= IPV6_AF_AUTOCONF; + + ap = ipv6_newaddr(rap->iface, + &pi_prefix, pi.nd_opt_pi_prefix_len, flags); + if (ap == NULL) + break; + ap->prefix = pi_prefix; ap->dadcallback = ipv6nd_dadcallback; ap->created = ap->acquired = rap->acquired; TAILQ_INSERT_TAIL(&rap->addrs, ap, next);