]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Make ipv6_newaddr() more flexable so it's the sole source of
authorRoy Marples <roy@marples.name>
Tue, 13 Jun 2017 19:47:49 +0000 (20:47 +0100)
committerRoy Marples <roy@marples.name>
Tue, 13 Jun 2017 19:47:49 +0000 (20:47 +0100)
creating ipv6_addr structures.

src/dhcp6.c
src/ipv6.c
src/ipv6.h
src/ipv6nd.c

index 8c712d991510d4dc798139bf94786444f1e5afd1..2db1f97ca84c783c249b9273e664a92bbf74acdd 100644 (file)
@@ -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)
index bd385694b07df4a498c684352e727cd37a83f564..b37610aeef281c7bb1e889f834d95408bfca3119 100644 (file)
@@ -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;
 }
index bd0f900f8fa9f2c029ae172f4d133cf626a80ba8..1855cc2b7ef749d38402b5255db42b6fb734609b 100644 (file)
@@ -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)
index 5c9384fe0c4dfc893561d46b3811a91834811d3a..0884c9abe76149ca5edbf9145a1796b6585248c6 100644 (file)
@@ -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);