]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
route: Rework rt structure so sockaddrs are pointers (#621)
authorRoy Marples <roy@marples.name>
Wed, 3 Jun 2026 10:27:09 +0000 (11:27 +0100)
committerGitHub <noreply@github.com>
Wed, 3 Jun 2026 10:27:09 +0000 (11:27 +0100)
For each sockaddr, put a sockaddr_storage in the rt and
reference it.
This removes the need of a union and the macro dance
around it.

13 files changed:
src/dhcp.c
src/dhcpcd.c
src/if-bsd.c
src/if-linux.c
src/if-options.c
src/if-sun.c
src/ipv4.c
src/ipv4ll.c
src/ipv6.c
src/route.c
src/route.h
src/sa.c
src/sa.h

index 2733e91c6a78676e562cd7ee4e089de55034141f..fe9c40cd59d0911df629f8c02a53a5ce21089cb5 100644 (file)
@@ -434,9 +434,9 @@ decode_rfc3442_rt(rb_tree_t *routes, struct interface *ifp, const uint8_t *data,
                if (netmask.s_addr == INADDR_BROADCAST)
                        rt->rt_flags = RTF_HOST;
 
-               sa_in_init(&rt->rt_dest, &dest);
-               sa_in_init(&rt->rt_netmask, &netmask);
-               sa_in_init(&rt->rt_gateway, &gateway);
+               sa_in_init(rt->rt_dest, &dest);
+               sa_in_init(rt->rt_netmask, &netmask);
+               sa_in_init(rt->rt_gateway, &gateway);
                if (rt_proto_add(routes, rt))
                        n = 1;
        }
@@ -614,9 +614,9 @@ get_option_routes(rb_tree_t *routes, struct interface *ifp,
                        if (netmask.s_addr == INADDR_BROADCAST)
                                rt->rt_flags = RTF_HOST;
 
-                       sa_in_init(&rt->rt_dest, &dest);
-                       sa_in_init(&rt->rt_netmask, &netmask);
-                       sa_in_init(&rt->rt_gateway, &gateway);
+                       sa_in_init(rt->rt_dest, &dest);
+                       sa_in_init(rt->rt_netmask, &netmask);
+                       sa_in_init(rt->rt_gateway, &gateway);
                        if (rt_proto_add(routes, rt))
                                n++;
                }
@@ -636,9 +636,9 @@ get_option_routes(rb_tree_t *routes, struct interface *ifp,
                                return -1;
                        memcpy(&gateway.s_addr, p, sizeof(gateway.s_addr));
                        p += 4;
-                       sa_in_init(&rt->rt_dest, &dest);
-                       sa_in_init(&rt->rt_netmask, &netmask);
-                       sa_in_init(&rt->rt_gateway, &gateway);
+                       sa_in_init(rt->rt_dest, &dest);
+                       sa_in_init(rt->rt_netmask, &netmask);
+                       sa_in_init(rt->rt_gateway, &gateway);
                        if (rt_proto_add(routes, rt))
                                n++;
                }
index f065c733613a8dff760d7f2afbd13a629aa12ca4..ab853a8fb38417c6bec587503c30afd0ecd95a66 100644 (file)
@@ -2201,7 +2201,7 @@ main(int argc, char **argv, char **envp)
        ctx.ifc = argc - optind;
        ctx.ifv = argv + optind;
 
-       rt_init(&ctx);
+       rt_init_routes(&ctx);
 
        ifo = read_config(&ctx, NULL, NULL, NULL);
        if (ifo == NULL) {
index 72d573b7cd145ded3bb2cdf0af212201e3b1bb8a..f017b5102d0deff11b857e4c69ad0bb6124db0e3 100644 (file)
@@ -751,15 +751,15 @@ if_route(unsigned char cmd, const struct rt *rt)
                rtm->rtm_flags |= RTF_PINNED;
 #endif
 
-       gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+       gateway_unspec = sa_is_unspecified(rt->rt_gateway);
 
        if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
-               bool netmask_bcast = sa_is_allones(&rt->rt_netmask);
+               bool netmask_bcast = sa_is_allones(rt->rt_netmask);
 
                rtm->rtm_flags |= RTF_UP;
                rtm->rtm_addrs |= RTA_GATEWAY;
                if (!(rtm->rtm_flags & RTF_REJECT) &&
-                   !sa_is_loopback(&rt->rt_gateway)) {
+                   !sa_is_loopback(rt->rt_gateway)) {
                        rtm->rtm_index = (unsigned short)rt->rt_ifp->index;
 /*
  * OpenBSD rejects this for on-link routes when there is no default route
@@ -770,10 +770,10 @@ if_route(unsigned char cmd, const struct rt *rt)
 #ifdef __OpenBSD__
 #warning kernel does not allow IPv6 address sharing
                        if (!gateway_unspec ||
-                           rt->rt_dest.sa_family != AF_INET6)
+                           rt->rt_dest->sa_family != AF_INET6)
 #endif
                                rtm->rtm_addrs |= RTA_IFP;
-                       if (!sa_is_unspecified(&rt->rt_ifa))
+                       if (!sa_is_unspecified(rt->rt_ifa))
                                rtm->rtm_addrs |= RTA_IFA;
                }
                if (netmask_bcast)
@@ -822,31 +822,32 @@ if_route(unsigned char cmd, const struct rt *rt)
 
        if_linkaddr(&sdl, rt->rt_ifp);
 
-       ADDSA(&rt->rt_dest);
+       ADDSA(rt->rt_dest);
 
        if (rtm->rtm_addrs & RTA_GATEWAY) {
                if (gateway_unspec)
                        ADDSA((struct sockaddr *)&sdl);
                else {
-                       union sa_ss gateway;
+                       struct sockaddr_storage gss;
+                       struct sockaddr *gsa = (struct sockaddr *)&gss;
 
-                       if_copysa(&gateway.sa, &rt->rt_gateway);
+                       if_copysa(gsa, rt->rt_gateway);
 #ifdef INET6
-                       if (gateway.sa.sa_family == AF_INET6)
-                               ipv6_setscope(&gateway.sin6, rt->rt_ifp->index);
+                       if (gss.ss_family == AF_INET6)
+                               ipv6_setscope((struct sockaddr_in6 *)&gss, rt->rt_ifp->index);
 #endif
-                       ADDSA(&gateway.sa);
+                       ADDSA(gsa);
                }
        }
 
        if (rtm->rtm_addrs & RTA_NETMASK)
-               ADDSA(&rt->rt_netmask);
+               ADDSA(rt->rt_netmask);
 
        if (rtm->rtm_addrs & RTA_IFP)
                ADDSA((struct sockaddr *)&sdl);
 
        if (rtm->rtm_addrs & RTA_IFA)
-               ADDSA(&rt->rt_ifa);
+               ADDSA(rt->rt_ifa);
 
 #undef ADDSA
 
@@ -903,13 +904,13 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
        if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm),
                rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
                return -1;
-       memset(rt, 0, sizeof(*rt));
 
+       rt_init(rt);
        rt->rt_flags = (unsigned int)rtm->rtm_flags;
-       if_copysa(&rt->rt_dest, rti_info[RTAX_DST]);
+       if_copysa(rt->rt_dest, rti_info[RTAX_DST]);
 
        if (rtm->rtm_addrs & RTA_NETMASK) {
-               if_copysa(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
+               if_copysa(rt->rt_netmask, rti_info[RTAX_NETMASK]);
                /*
                 * Netmask family and length are ignored by traditional
                 * userland tools such as route and netstat and are assumed
@@ -921,8 +922,8 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
                 *
                 * This is currently true for all BSD kernels.
                 */
-               rt->rt_netmask.sa_family = rt->rt_dest.sa_family;
-               rt->rt_netmask.sa_len = rt->rt_dest.sa_len;
+               rt->rt_netmask->sa_family = rt->rt_dest->sa_family;
+               rt->rt_netmask->sa_len = rt->rt_dest->sa_len;
        }
 
        /* dhcpcd likes an unspecified gateway to indicate via the link.
@@ -936,11 +937,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
                        if (sdl->sdl_alen != 0)
                                rt->rt_dflags |= RTDF_GATELINK;
                } else if (rtm->rtm_flags & RTF_GATEWAY)
-                       if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+                       if_copysa(rt->rt_gateway, rti_info[RTAX_GATEWAY]);
        }
 
        if (rtm->rtm_addrs & RTA_IFA)
-               if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]);
+               if_copysa(rt->rt_ifa, rti_info[RTAX_IFA]);
 
        rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
 
@@ -1018,7 +1019,7 @@ again:
                        logerr(__func__);
                        break;
                }
-               memcpy(rtn, &rt, sizeof(*rtn));
+               rt_copy(rtn, &rt);
                if (rb_tree_insert_node(kroutes, rtn) != rtn)
                        rt_free(rtn);
        }
@@ -1332,15 +1333,16 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
         * existance with a hardware address.
         * Ensure we don't call this for a newly incomplete state.
         */
-       if (rt.rt_dest.sa_family == AF_INET6 &&
+       if (rt.rt_dest->sa_family == AF_INET6 &&
            (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
            !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) {
                bool reachable;
+               struct sockaddr_in6 *dest = (struct sockaddr_in6 *)&rt.rt_ss_dest;
 
                reachable = (rtm->rtm_type == RTM_ADD ||
                                rtm->rtm_type == RTM_CHANGE) &&
                    rt.rt_dflags & RTDF_GATELINK;
-               ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
+               ipv6nd_neighbour(ctx, &dest->sin6_addr, reachable);
        }
 #endif
 
index 3f678d2954c74c14fba6629a3658075ad5e55c0b..5fa5505eafd9bff5251880f140f08c4329e68081 100644 (file)
@@ -689,7 +689,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
        if (rtm->rtm_table != RT_TABLE_MAIN)
                return -1;
 
-       memset(rt, 0, sizeof(*rt));
+       rt_init(rt);
        if (rtm->rtm_type == RTN_UNREACHABLE)
                rt->rt_flags |= RTF_REJECT;
 
@@ -699,11 +699,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
                sa = NULL;
                switch (rta->rta_type) {
                case RTA_DST:
-                       sa = &rt->rt_dest;
+                       sa = rt->rt_dest;
                        break;
                case RTA_SRC: {
-                       union sa_ss ssa;
-                       struct sockaddr *psa = (struct sockaddr *)&ssa;
+                       struct sockaddr_storage ss;     
+                       struct sockaddr *psa = (struct sockaddr *)&ss;
                        socklen_t salen;
 
                        psa->sa_family = rtm->rtm_family;
@@ -722,10 +722,10 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
                        break;
                }
                case RTA_GATEWAY:
-                       sa = &rt->rt_gateway;
+                       sa = rt->rt_gateway;
                        break;
                case RTA_PREFSRC:
-                       sa = &rt->rt_ifa;
+                       sa = rt->rt_ifa;
                        break;
                case RTA_OIF:
                        ifindex = *(unsigned int *)RTA_DATA(rta);
@@ -784,20 +784,18 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
 
                        sa->sa_family = rtm->rtm_family;
                        salen = sa_addrlen(sa);
-                       /* sa is a union where sockaddr_in6 is the biggest. */
-                       /* coverity[overrun-buffer-arg] */
                        memcpy((char *)sa + sa_addroffset(sa), RTA_DATA(rta),
                            MIN(salen, RTA_PAYLOAD(rta)));
                }
        }
 
        /* If no RTA_DST set the unspecified address for the family. */
-       if (rt->rt_dest.sa_family == AF_UNSPEC)
-               rt->rt_dest.sa_family = rtm->rtm_family;
+       if (rt->rt_dest->sa_family == AF_UNSPEC)
+               rt->rt_dest->sa_family = rtm->rtm_family;
 
-       rt->rt_netmask.sa_family = rtm->rtm_family;
-       sa_fromprefix(&rt->rt_netmask, rtm->rtm_dst_len);
-       if (sa_is_allones(&rt->rt_netmask))
+       rt->rt_netmask->sa_family = rtm->rtm_family;
+       sa_fromprefix(rt->rt_netmask, rtm->rtm_dst_len);
+       if (sa_is_allones(rt->rt_netmask))
                rt->rt_flags |= RTF_HOST;
 
 #if 0
@@ -1662,10 +1660,10 @@ if_route(unsigned char cmd, const struct rt *rt)
                break;
        }
        nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
-       nlm.rt.rtm_family = (unsigned char)rt->rt_dest.sa_family;
+       nlm.rt.rtm_family = (unsigned char)rt->rt_dest->sa_family;
        nlm.rt.rtm_table = RT_TABLE_MAIN;
 
-       gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+       gateway_unspec = sa_is_unspecified(rt->rt_gateway);
 
        if (cmd == RTM_DELETE) {
                nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
@@ -1702,22 +1700,18 @@ if_route(unsigned char cmd, const struct rt *rt)
        add_attr_l(&nlm.hdr, sizeof(nlm), (type),     \
            (const char *)(sa) + sa_addroffset((sa)), \
            (unsigned short)sa_addrlen((sa)));
-       nlm.rt.rtm_dst_len = (unsigned char)sa_toprefix(&rt->rt_netmask);
-       /* rt->rt_dest and rt->gateway are unions where sockaddr_in6
-        * is the biggest member. However, we access them as the
-        * generic sockaddr and coverity thinks this will overrun. */
-       /* coverity[overrun-buffer-arg] */
-       ADDSA(RTA_DST, &rt->rt_dest);
+       nlm.rt.rtm_dst_len = (unsigned char)sa_toprefix(rt->rt_netmask);
+       ADDSA(RTA_DST, rt->rt_dest);
        if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
                if (!gateway_unspec) {
                        /* coverity[overrun-buffer-arg] */
-                       ADDSA(RTA_GATEWAY, &rt->rt_gateway);
+                       ADDSA(RTA_GATEWAY, rt->rt_gateway);
                }
                /* Cannot add tentative source addresses.
                 * We don't know this here, so just skip INET6 ifa's.*/
-               if (!sa_is_unspecified(&rt->rt_ifa) &&
-                   rt->rt_ifa.sa_family != AF_INET6)
-                       ADDSA(RTA_PREFSRC, &rt->rt_ifa);
+               if (!sa_is_unspecified(rt->rt_ifa) &&
+                   rt->rt_ifa->sa_family != AF_INET6)
+                       ADDSA(RTA_PREFSRC, rt->rt_ifa);
                if (rt->rt_mtu) {
                        char metricsbuf[32];
                        struct rtattr *metrics = (void *)metricsbuf;
@@ -1754,7 +1748,7 @@ if_route(unsigned char cmd, const struct rt *rt)
 #endif
        }
 
-       if (!sa_is_loopback(&rt->rt_gateway))
+       if (!sa_is_loopback(rt->rt_gateway))
                add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->rt_ifp->index);
 
 #ifdef HAVE_ROUTE_LIFETIME
@@ -1785,7 +1779,7 @@ _if_initrt(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
                logerr(__func__);
                return 0;
        }
-       memcpy(rtn, &rt, sizeof(*rtn));
+       rt_copy(rtn, &rt);
        if (rb_tree_insert_node(kroutes, rtn) != rtn)
                rt_free(rtn);
        return 0;
index 54e048bf1016f70506a94f9cfd226cf368f36f94..cb4321d64b3c5a17462ba22ba0355092c53e9a1d 100644 (file)
@@ -1330,9 +1330,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                        *fp = ' ';
                        if ((rt = rt_new0(ctx)) == NULL)
                                return -1;
-                       sa_in_init(&rt->rt_dest, &addr);
-                       sa_in_init(&rt->rt_netmask, &addr2);
-                       sa_in_init(&rt->rt_gateway, &addr3);
+                       sa_in_init(rt->rt_dest, &addr);
+                       sa_in_init(rt->rt_netmask, &addr2);
+                       sa_in_init(rt->rt_gateway, &addr3);
                        if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
                                add_environ(&ifo->config, arg, 0);
 #else
@@ -1351,9 +1351,9 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                        if ((rt = rt_new0(ctx)) == NULL)
                                return -1;
                        addr2.s_addr = INADDR_ANY;
-                       sa_in_init(&rt->rt_dest, &addr2);
-                       sa_in_init(&rt->rt_netmask, &addr2);
-                       sa_in_init(&rt->rt_gateway, &addr);
+                       sa_in_init(rt->rt_dest, &addr2);
+                       sa_in_init(rt->rt_netmask, &addr2);
+                       sa_in_init(rt->rt_gateway, &addr);
                        if (rt_proto_add_ctx(&ifo->routes, rt, ctx))
                                add_environ(&ifo->config, arg, 0);
 #else
index 0a9747692da6f8427314c97a9a98e801889b6d58..37659bce979159bf1b465d7185d847e25d210404 100644 (file)
@@ -572,21 +572,21 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg, unsigned char cmd,
        rtm->rtm_flags = rt->rt_flags;
        rtm->rtm_addrs = RTA_DST | RTA_GATEWAY;
 
-       gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+       gateway_unspec = sa_is_unspecified(rt->rt_gateway);
 
        if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
-               bool netmask_bcast = sa_is_allones(&rt->rt_netmask);
+               bool netmask_bcast = sa_is_allones(rt->rt_netmask);
 
                rtm->rtm_flags |= RTF_UP;
                if (!(rtm->rtm_flags & RTF_REJECT) &&
-                   !sa_is_loopback(&rt->rt_gateway)) {
+                   !sa_is_loopback(rt->rt_gateway)) {
                        rtm->rtm_addrs |= RTA_IFP;
                        /* RTA_IFA is currently ignored by the kernel.
                         * RTA_SRC and RTF_SETSRC look like what we want,
                         * but they don't work with RTF_GATEWAY.
                         * We set RTA_IFA just in the hope that the
                         * kernel will one day support this. */
-                       if (!sa_is_unspecified(&rt->rt_ifa))
+                       if (!sa_is_unspecified(rt->rt_ifa))
                                rtm->rtm_addrs |= RTA_IFA;
                }
 
@@ -607,15 +607,15 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg, unsigned char cmd,
        if (!(rtm->rtm_flags & RTF_HOST))
                rtm->rtm_addrs |= RTA_NETMASK;
 
-       ADDSA(&rt->rt_dest);
+       ADDSA(rt->rt_dest);
 
        if (gateway_unspec)
-               ADDSA(&rt->rt_ifa);
+               ADDSA(rt->rt_ifa);
        else
-               ADDSA(&rt->rt_gateway);
+               ADDSA(rt->rt_gateway);
 
        if (rtm->rtm_addrs & RTA_NETMASK)
-               ADDSA(&rt->rt_netmask);
+               ADDSA(rt->rt_netmask);
 
        if (rtm->rtm_addrs & RTA_IFP) {
                struct sockaddr_dl sdl;
@@ -625,11 +625,11 @@ if_route0(struct dhcpcd_ctx *ctx, struct rtm *rtmsg, unsigned char cmd,
        }
 
        if (rtm->rtm_addrs & RTA_IFA)
-               ADDSA(&rt->rt_ifa);
+               ADDSA(rt->rt_ifa);
 
 #if 0
        if (rtm->rtm_addrs & RTA_SRC)
-               ADDSA(&rt->rt_ifa);
+               ADDSA(rt->rt_ifa);
 #endif
 
        rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm);
@@ -662,12 +662,12 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
                rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1)
                return -1;
 
-       memset(rt, 0, sizeof(*rt));
-
+       rt_init(rt);
        rt->rt_flags = (unsigned int)rtm->rtm_flags;
-       COPYSA(&rt->rt_dest, rti_info[RTAX_DST]);
+
+       COPYSA(rt->rt_dest, rti_info[RTAX_DST]);
        if (rtm->rtm_addrs & RTA_NETMASK)
-               COPYSA(&rt->rt_netmask, rti_info[RTAX_NETMASK]);
+               COPYSA(rt->rt_netmask, rti_info[RTAX_NETMASK]);
 
        /* dhcpcd likes an unspecified gateway to indicate via the link.
         * However we need to know if gateway was a link with an address. */
@@ -680,11 +680,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
                        if (sdl->sdl_alen != 0)
                                rt->rt_dflags |= RTDF_GATELINK;
                } else if (rtm->rtm_flags & RTF_GATEWAY)
-                       COPYSA(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+                       COPYSA(rt->rt_gateway, rti_info[RTAX_GATEWAY]);
        }
 
        if (rtm->rtm_addrs & RTA_SRC)
-               COPYSA(&rt->rt_ifa, rti_info[RTAX_SRC]);
+               COPYSA(rt->rt_ifa, rti_info[RTAX_SRC]);
        rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
 
        if (rtm->rtm_index)
@@ -748,14 +748,14 @@ if_finishrt(struct dhcpcd_ctx *ctx, struct rt *rt)
         * of the owning address.
         * dhcpcd has a blank gateway here to indicate a
         * subnet route. */
-       if (!sa_is_unspecified(&rt->rt_dest) &&
-           !sa_is_unspecified(&rt->rt_gateway)) {
-               switch (rt->rt_gateway.sa_family) {
+       if (!sa_is_unspecified(rt->rt_dest) &&
+           !sa_is_unspecified(rt->rt_gateway)) {
+               switch (rt->rt_gateway->sa_family) {
 #ifdef INET
                case AF_INET: {
                        struct in_addr *in;
 
-                       in = &satosin(&rt->rt_gateway)->sin_addr;
+                       in = &satosin(rt->rt_gateway)->sin_addr;
                        if (ipv4_findaddr(ctx, in))
                                in->s_addr = INADDR_ANY;
                        break;
@@ -765,7 +765,7 @@ if_finishrt(struct dhcpcd_ctx *ctx, struct rt *rt)
                case AF_INET6: {
                        struct in6_addr *in6;
 
-                       in6 = &satosin6(&rt->rt_gateway)->sin6_addr;
+                       in6 = &satosin6(rt->rt_gateway)->sin6_addr;
                        if (ipv6_findaddr(ctx, in6, 0))
                                *in6 = in6addr_any;
                        break;
@@ -839,15 +839,16 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
         * existance with a hardware address.
         * Ensure we don't call this for a newly incomplete state.
         */
-       if (rt.rt_dest.sa_family == AF_INET6 &&
+       if (rt.rt_dest->sa_family == AF_INET6 &&
            (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
            !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) {
                bool reachable;
+               struct sockaddr_in6 *dest = (struct sockaddr_in6 *)rt.rt_dest;
 
                reachable = (rtm->rtm_type == RTM_ADD ||
                                rtm->rtm_type == RTM_CHANGE) &&
                    rt.rt_dflags & RTDF_GATELINK;
-               ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
+               ipv6nd_neighbour(ctx, &dest->sin6_addr, reachable);
        }
 #endif
 
@@ -1392,16 +1393,16 @@ if_walkrt(struct dhcpcd_ctx *ctx, rb_tree_t *routes, char *data, size_t len)
                        break;
                }
 
-               memset(&rt, 0, sizeof(rt));
+               rt_init(&rt);
                in.s_addr = re->ipRouteDest;
-               sa_in_init(&rt.rt_dest, &in);
+               sa_in_init(rt.rt_dest, &in);
                in.s_addr = re->ipRouteMask;
-               sa_in_init(&rt.rt_netmask, &in);
+               sa_in_init(rt.rt_netmask, &in);
                in.s_addr = re->ipRouteNextHop;
-               sa_in_init(&rt.rt_gateway, &in);
+               sa_in_init(rt.rt_gateway, &in);
                rt.rt_flags = re->ipRouteInfo.re_flags;
                in.s_addr = re->ipRouteInfo.re_src_addr;
-               sa_in_init(&rt.rt_ifa, &in);
+               sa_in_init(rt.rt_ifa, &in);
                rt.rt_mtu = re->ipRouteInfo.re_max_frag;
                if_octetstr(ifname, &re->ipRouteIfIndex, sizeof(ifname));
                rt.rt_ifp = if_find(ctx->ifaces, ifname);
@@ -1413,7 +1414,7 @@ if_walkrt(struct dhcpcd_ctx *ctx, rb_tree_t *routes, char *data, size_t len)
                        logerr(__func__);
                        break;
                }
-               memcpy(rtn, &rt, sizeof(*rtn));
+               rt_copy(rtn, &rt);
                if (rb_tree_insert_node(routes, rtn) != rtn)
                        rt_free(rtn);
        } while (++re < e);
@@ -1451,12 +1452,12 @@ if_walkrt6(struct dhcpcd_ctx *ctx, rb_tree_t *routes, char *data, size_t len)
                        break;
                }
 
-               memset(&rt, 0, sizeof(rt));
-               sa_in6_init(&rt.rt_dest, &re->ipv6RouteDest);
+               rt_init(&rt);
+               sa_in6_init(rt.rt_dest, &re->ipv6RouteDest);
                ipv6_mask(&in6, re->ipv6RoutePfxLength);
-               sa_in6_init(&rt.rt_netmask, &in6);
-               sa_in6_init(&rt.rt_gateway, &re->ipv6RouteNextHop);
-               sa_in6_init(&rt.rt_ifa, &re->ipv6RouteInfo.re_src_addr);
+               sa_in6_init(rt.rt_netmask, &in6);
+               sa_in6_init(rt.rt_gateway, &re->ipv6RouteNextHop);
+               sa_in6_init(rt.rt_ifa, &re->ipv6RouteInfo.re_src_addr);
                rt.rt_mtu = re->ipv6RouteInfo.re_max_frag;
                if_octetstr(ifname, &re->ipv6RouteIfIndex, sizeof(ifname));
                rt.rt_ifp = if_find(ctx->ifaces, ifname);
@@ -1468,7 +1469,7 @@ if_walkrt6(struct dhcpcd_ctx *ctx, rb_tree_t *routes, char *data, size_t len)
                        logerr(__func__);
                        break;
                }
-               memcpy(rtn, &rt, sizeof(*rtn));
+               rt_copy(rtn, &rt);
                if (rb_tree_insert_node(routes, rtn) != rtn)
                        rt_free(rtn);
        } while (++re < e);
index d77bfb462ecdcae35b3a7c6c676084ed3294de6f..6461d52a6389e387c530a5ba3e5059b50cdabddc 100644 (file)
@@ -308,12 +308,12 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp, bool *have_default)
                        return -1;
                rt->rt_dflags |= RTDF_IFA_ROUTE;
                in.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
-               sa_in_init(&rt->rt_dest, &in);
+               sa_in_init(rt->rt_dest, &in);
                in.s_addr = state->addr->mask.s_addr;
-               sa_in_init(&rt->rt_netmask, &in);
+               sa_in_init(rt->rt_netmask, &in);
                // in.s_addr = INADDR_ANY;
-               // sa_in_init(&rt->rt_gateway, &in);
-               rt->rt_gateway.sa_family = AF_UNSPEC;
+               // sa_in_init(rt->rt_gateway, &in);
+               rt->rt_gateway->sa_family = AF_UNSPEC;
                rt_proto_add(&nroutes, rt);
        }
 
@@ -321,11 +321,11 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp, bool *have_default)
        if (RB_TREE_MIN(&ifp->options->routes)) {
                RB_TREE_FOREACH(r, &ifp->options->routes)
                {
-                       if (sa_is_unspecified(&r->rt_gateway))
+                       if (sa_is_unspecified(r->rt_gateway))
                                break;
                        if ((rt = rt_new0(ifp->ctx)) == NULL)
                                return -1;
-                       memcpy(rt, r, sizeof(*rt));
+                       rt_copy(rt, r);
                        rt_setif(rt, ifp);
                        rt->rt_dflags = RTDF_STATIC;
                        rt_proto_add(&nroutes, rt);
@@ -342,10 +342,10 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp, bool *have_default)
                if ((rt = rt_new(ifp)) == NULL)
                        return -1;
                in.s_addr = INADDR_ANY;
-               sa_in_init(&rt->rt_dest, &in);
-               sa_in_init(&rt->rt_netmask, &in);
-               sa_in_init(&rt->rt_gateway, &state->addr->brd);
-               sa_in_init(&rt->rt_ifa, &state->addr->addr);
+               sa_in_init(rt->rt_dest, &in);
+               sa_in_init(rt->rt_netmask, &in);
+               sa_in_init(rt->rt_gateway, &state->addr->brd);
+               sa_in_init(rt->rt_ifa, &state->addr->addr);
                rt_proto_add(&nroutes, rt);
        }
 
@@ -359,7 +359,7 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp, bool *have_default)
                        rt->rt_dflags |= RTDF_DHCP;
                if (state->added & STATE_FAKE)
                        rt->rt_dflags |= RTDF_FAKE;
-               sa_in_init(&rt->rt_ifa, &state->addr->addr);
+               sa_in_init(rt->rt_ifa, &state->addr->addr);
                if (rb_tree_insert_node(routes, rt) != rt) {
                        rt_free(rt);
                        continue;
@@ -393,26 +393,26 @@ inet_routerhostroute(rb_tree_t *routes, struct interface *ifp)
 
        RB_TREE_FOREACH(rt, routes)
        {
-               if (rt->rt_dest.sa_family != AF_INET)
+               if (rt->rt_dest->sa_family != AF_INET)
                        continue;
-               if (!sa_is_unspecified(&rt->rt_dest) ||
-                   sa_is_unspecified(&rt->rt_gateway))
+               if (!sa_is_unspecified(rt->rt_dest) ||
+                   sa_is_unspecified(rt->rt_gateway))
                        continue;
-               gateway = satosin(&rt->rt_gateway);
+               gateway = satosin(rt->rt_gateway);
                /* Scan for a route to match */
                RB_TREE_FOREACH(rth, routes)
                {
                        if (rth == rt)
                                break;
                        /* match host */
-                       if (sa_cmp(&rth->rt_dest, &rt->rt_gateway) == 0)
+                       if (sa_cmp(rth->rt_dest, rt->rt_gateway) == 0)
                                break;
                        /* match subnet */
                        /* XXX ADD TO RT_COMARE? XXX */
                        cp = (const char *)&gateway->sin_addr.s_addr;
-                       dest = satosin(&rth->rt_dest);
+                       dest = satosin(rth->rt_dest);
                        cp2 = (const char *)&dest->sin_addr.s_addr;
-                       netmask = satosin(&rth->rt_netmask);
+                       netmask = satosin(rth->rt_netmask);
                        cp3 = (const char *)&netmask->sin_addr.s_addr;
                        cplim = cp3 + sizeof(netmask->sin_addr.s_addr);
                        while (cp3 < cplim) {
@@ -436,7 +436,7 @@ inet_routerhostroute(rb_tree_t *routes, struct interface *ifp)
                                logwarnx("%s: forcing router %s through "
                                         "interface",
                                    ifp->name,
-                                   sa_addrtop(&rt->rt_gateway, buf,
+                                   sa_addrtop(rt->rt_gateway, buf,
                                        sizeof(buf)));
                        }
                        gateway->sin_addr.s_addr = INADDR_ANY;
@@ -449,22 +449,22 @@ inet_routerhostroute(rb_tree_t *routes, struct interface *ifp)
                        ifo->options |= DHCPCD_ROUTER_HOST_ROUTE_WARNED;
                        logwarnx("%s: router %s requires a host route",
                            ifp->name,
-                           sa_addrtop(&rt->rt_gateway, buf, sizeof(buf)));
+                           sa_addrtop(rt->rt_gateway, buf, sizeof(buf)));
                }
 
                if ((rth = rt_new(ifp)) == NULL)
                        return -1;
                rth->rt_flags |= RTF_HOST;
-               sa_in_init(&rth->rt_dest, &gateway->sin_addr);
+               sa_in_init(rth->rt_dest, &gateway->sin_addr);
                in.s_addr = INADDR_BROADCAST;
-               sa_in_init(&rth->rt_netmask, &in);
+               sa_in_init(rth->rt_netmask, &in);
                in.s_addr = INADDR_ANY;
-               sa_in_init(&rth->rt_gateway, &in);
+               sa_in_init(rth->rt_gateway, &in);
                rth->rt_mtu = dhcp_get_mtu(ifp);
                if (state->addr != NULL)
-                       sa_in_init(&rth->rt_ifa, &state->addr->addr);
+                       sa_in_init(rth->rt_ifa, &state->addr->addr);
                else
-                       rth->rt_ifa.sa_family = AF_UNSPEC;
+                       rth->rt_ifa->sa_family = AF_UNSPEC;
 
                /* We need to insert the host route just before the router. */
                while ((rtp = RB_TREE_MAX(routes)) != NULL) {
index eabe10b19dc6181f0878b8d3c3df5509c15668b6..8ee02264f6af34b6602899c763f59070e1a7019c 100644 (file)
@@ -102,12 +102,12 @@ ipv4ll_subnetroute(rb_tree_t *routes, struct interface *ifp)
                return -1;
 
        in.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
-       sa_in_init(&rt->rt_dest, &in);
+       sa_in_init(rt->rt_dest, &in);
        in.s_addr = state->addr->mask.s_addr;
-       sa_in_init(&rt->rt_netmask, &in);
+       sa_in_init(rt->rt_netmask, &in);
        in.s_addr = INADDR_ANY;
-       sa_in_init(&rt->rt_gateway, &in);
-       sa_in_init(&rt->rt_ifa, &state->addr->addr);
+       sa_in_init(rt->rt_gateway, &in);
+       sa_in_init(rt->rt_ifa, &state->addr->addr);
        rt->rt_dflags |= RTDF_IPV4LL;
        return rt_proto_add(routes, rt) ? 1 : 0;
 }
@@ -117,7 +117,7 @@ ipv4ll_defaultroute(rb_tree_t *routes, struct interface *ifp)
 {
        struct ipv4ll_state *state;
        struct rt *rt;
-       struct in_addr in;
+       struct in_addr in = { .s_addr = INADDR_ANY };
 
        assert(ifp != NULL);
        if ((state = IPV4LL_STATE(ifp)) == NULL || state->addr == NULL)
@@ -126,11 +126,10 @@ ipv4ll_defaultroute(rb_tree_t *routes, struct interface *ifp)
        if ((rt = rt_new(ifp)) == NULL)
                return -1;
 
-       in.s_addr = INADDR_ANY;
-       sa_in_init(&rt->rt_dest, &in);
-       sa_in_init(&rt->rt_netmask, &in);
-       sa_in_init(&rt->rt_gateway, &in);
-       sa_in_init(&rt->rt_ifa, &state->addr->addr);
+       sa_in_init(rt->rt_dest, &in);
+       sa_in_init(rt->rt_netmask, &in);
+       sa_in_init(rt->rt_gateway, &in);
+       sa_in_init(rt->rt_ifa, &state->addr->addr);
        rt->rt_dflags |= RTDF_IPV4LL;
 #ifdef HAVE_ROUTE_METRIC
        rt->rt_metric += RTMETRIC_IPV4LL;
@@ -510,7 +509,7 @@ ipv4ll_recvrt(__unused int cmd, const struct rt *rt)
        struct interface *ifp;
 
        /* Only interested in default route changes. */
-       if (sa_is_unspecified(&rt->rt_dest))
+       if (!sa_is_unspecified(rt->rt_dest))
                return 0;
 
        /* If any interface is running IPv4LL, rebuild our routing table. */
index 263fb6a08905b511114776d8ac84c76d4b7de988..1ff3fa69006a8951b3efff93f88e3161f9bbe67f 100644 (file)
@@ -2211,20 +2211,20 @@ inet6_makeprefix(struct interface *ifp, const struct ra *rap,
        if ((rt = inet6_makeroute(ifp, rap)) == NULL)
                return NULL;
 
-       sa_in6_init(&rt->rt_dest, &addr->prefix);
+       sa_in6_init(rt->rt_dest, &addr->prefix);
        ipv6_mask(&netmask, addr->prefix_len);
-       sa_in6_init(&rt->rt_netmask, &netmask);
+       sa_in6_init(rt->rt_netmask, &netmask);
        if (addr->flags & IPV6_AF_PFXDELEGATION) {
                rt->rt_flags |= RTF_REJECT;
                /* Linux does not like a gateway for a reject route. */
 #ifndef __linux__
-               sa_in6_init(&rt->rt_gateway, &in6addr_loopback);
+               sa_in6_init(rt->rt_gateway, &in6addr_loopback);
 #endif
        } else if (!(addr->flags & IPV6_AF_ONLINK))
-               sa_in6_init(&rt->rt_gateway, &rap->from);
+               sa_in6_init(rt->rt_gateway, &rap->from);
        else
-               rt->rt_gateway.sa_family = AF_UNSPEC;
-       sa_in6_init(&rt->rt_ifa, &addr->addr);
+               rt->rt_gateway->sa_family = AF_UNSPEC;
+       sa_in6_init(rt->rt_ifa, &addr->addr);
        return rt;
 }
 
@@ -2235,9 +2235,9 @@ inet6_makerouter(struct ra *rap)
 
        if ((rt = inet6_makeroute(rap->iface, rap)) == NULL)
                return NULL;
-       sa_in6_init(&rt->rt_dest, &in6addr_any);
-       sa_in6_init(&rt->rt_netmask, &in6addr_any);
-       sa_in6_init(&rt->rt_gateway, &rap->from);
+       sa_in6_init(rt->rt_dest, &in6addr_any);
+       sa_in6_init(rt->rt_netmask, &in6addr_any);
+       sa_in6_init(rt->rt_gateway, &rap->from);
        return rt;
 }
 
@@ -2293,9 +2293,9 @@ inet6_raroutes(rb_tree_t *routes, struct dhcpcd_ctx *ctx)
 
                        in6_addr_fromprefix(&netmask, rinfo->prefix_len);
 
-                       sa_in6_init(&rt->rt_dest, &rinfo->prefix);
-                       sa_in6_init(&rt->rt_netmask, &netmask);
-                       sa_in6_init(&rt->rt_gateway, &rap->from);
+                       sa_in6_init(rt->rt_dest, &rinfo->prefix);
+                       sa_in6_init(rt->rt_netmask, &netmask);
+                       sa_in6_init(rt->rt_gateway, &rap->from);
                        rt->rt_dflags |= RTDF_RA;
 #ifdef HAVE_ROUTE_PREF
                        rt->rt_pref = ipv6nd_rtpref(rinfo->flags);
index 804b1e25752917bf8d468c884b928d3faf4ef8f7..5a3957fc4d5d70d5b10b47b50c121b5cb864a9b5 100644 (file)
@@ -114,19 +114,21 @@ rt_cmp_netmask(const struct rt *rt1, const struct rt *rt2)
 {
        if (rt1->rt_flags & RTF_HOST && rt2->rt_flags & RTF_HOST)
                return 0;
-       return sa_cmp(&rt1->rt_netmask, &rt2->rt_netmask);
+       return sa_cmp(rt1->rt_netmask, rt2->rt_netmask);
 }
 
 int
 rt_cmp_dest(const struct rt *rt1, const struct rt *rt2)
 {
-       union sa_ss ma1 = { .sa.sa_family = AF_UNSPEC };
-       union sa_ss ma2 = { .sa.sa_family = AF_UNSPEC };
+       struct sockaddr_storage ss1 = { .ss_family = AF_UNSPEC };
+       struct sockaddr_storage ss2 = { .ss_family = AF_UNSPEC };
+       struct sockaddr *ma1 = (struct sockaddr *)&ss1;
+       struct sockaddr *ma2 = (struct sockaddr *)&ss2;
        int c;
 
-       rt_maskedaddr(&ma1.sa, &rt1->rt_dest, &rt1->rt_netmask);
-       rt_maskedaddr(&ma2.sa, &rt2->rt_dest, &rt2->rt_netmask);
-       c = sa_cmp(&ma1.sa, &ma2.sa);
+       rt_maskedaddr(ma1, rt1->rt_dest, rt1->rt_netmask);
+       rt_maskedaddr(ma2, rt2->rt_dest, rt2->rt_netmask);
+       c = sa_cmp(ma1, ma2);
        if (c != 0)
                return c;
 
@@ -243,7 +245,7 @@ static const rb_tree_ops_t rt_compare_free_ops = {
 #endif
 
 void
-rt_init(struct dhcpcd_ctx *ctx)
+rt_init_routes(struct dhcpcd_ctx *ctx)
 {
        rb_tree_init(&ctx->routes, &rt_compare_os_ops);
 #ifdef RT_FREE_ROUTE_TABLE
@@ -254,8 +256,8 @@ rt_init(struct dhcpcd_ctx *ctx)
 bool
 rt_is_default(const struct rt *rt)
 {
-       return sa_is_unspecified(&rt->rt_dest) &&
-           sa_is_unspecified(&rt->rt_netmask);
+       return sa_is_unspecified(rt->rt_dest) &&
+           sa_is_unspecified(rt->rt_netmask);
 }
 
 static void
@@ -269,10 +271,10 @@ rt_desc(int loglevel, const char *cmd, const struct rt *rt)
        assert(cmd != NULL);
        assert(rt != NULL);
 
-       sa_addrtop(&rt->rt_dest, dest, sizeof(dest));
-       prefix = sa_toprefix(&rt->rt_netmask);
-       sa_addrtop(&rt->rt_gateway, gateway, sizeof(gateway));
-       gateway_unspec = sa_is_unspecified(&rt->rt_gateway);
+       sa_addrtop(rt->rt_dest, dest, sizeof(dest));
+       prefix = sa_toprefix(rt->rt_netmask);
+       sa_addrtop(rt->rt_gateway, gateway, sizeof(gateway));
+       gateway_unspec = sa_is_unspecified(rt->rt_gateway);
        ifname = rt->rt_ifp == NULL ? "(null)" : rt->rt_ifp->name;
 
        if (rt->rt_flags & RTF_HOST) {
@@ -312,8 +314,8 @@ rt_headclear0(struct dhcpcd_ctx *ctx, rb_tree_t *rts, int af)
 
        RB_TREE_FOREACH_SAFE(rt, rts, rtn)
        {
-               if (af != AF_UNSPEC && rt->rt_dest.sa_family != af &&
-                   rt->rt_gateway.sa_family != af)
+               if (af != AF_UNSPEC && rt->rt_dest->sa_family != af &&
+                   rt->rt_gateway->sa_family != af)
                        continue;
                rb_tree_remove_node(rts, rt);
                rt_free(rt);
@@ -356,6 +358,29 @@ rt_dispose(struct dhcpcd_ctx *ctx)
 #endif
 }
 
+static void
+rt_setup_sa(struct rt *rt)
+{
+       rt->rt_dest = (struct sockaddr *)&rt->rt_ss_dest;
+       rt->rt_netmask = (struct sockaddr *)&rt->rt_ss_netmask;
+       rt->rt_gateway = (struct sockaddr *)&rt->rt_ss_gateway;
+       rt->rt_ifa = (struct sockaddr *)&rt->rt_ss_ifa;
+}
+
+void
+rt_init(struct rt *rt)
+{
+       memset(rt, 0, sizeof(*rt));
+       rt_setup_sa(rt);
+}
+
+void
+rt_copy(struct rt *dst, const struct rt *src)
+{
+       memcpy(dst, src, sizeof(*dst));
+       rt_setup_sa(dst);
+}
+
 struct rt *
 rt_new0(struct dhcpcd_ctx *ctx)
 {
@@ -375,7 +400,7 @@ rt_new0(struct dhcpcd_ctx *ctx)
                logerr(__func__);
                return NULL;
        }
-       memset(rt, 0, sizeof(*rt));
+       rt_init(rt);
        return rt;
 }
 
@@ -495,7 +520,7 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid)
        }
 
 #if defined(IPV4LL) && defined(HAVE_ROUTE_METRIC)
-       if (rt->rt_dest.sa_family == AF_INET)
+       if (rt->rt_dest->sa_family == AF_INET)
                ipv4ll_recvrt(cmd, rt);
 #endif
 }
@@ -571,8 +596,8 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
        if (((nrt->rt_ifp->active &&
                 !(nrt->rt_ifp->options->options & DHCPCD_GATEWAY)) ||
                (!nrt->rt_ifp->active && !(ctx->options & DHCPCD_GATEWAY))) &&
-           sa_is_unspecified(&nrt->rt_dest) &&
-           sa_is_unspecified(&nrt->rt_netmask))
+           sa_is_unspecified(nrt->rt_dest) &&
+           sa_is_unspecified(nrt->rt_netmask))
                return false;
 
        krt = rb_tree_find_node(kroutes, nrt);
@@ -582,9 +607,9 @@ rt_add(rb_tree_t *kroutes, struct rt *nrt, struct rt *ort)
 #ifdef HAVE_ROUTE_METRIC
            krt->rt_metric == nrt->rt_metric &&
 #endif
-           sa_cmp(&krt->rt_dest, &nrt->rt_dest) == 0 &&
+           sa_cmp(krt->rt_dest, nrt->rt_dest) == 0 &&
            rt_cmp_netmask(krt, nrt) == 0 &&
-           sa_cmp(&krt->rt_gateway, &nrt->rt_gateway) == 0 &&
+           sa_cmp(krt->rt_gateway, nrt->rt_gateway) == 0 &&
            (nrt->rt_ifp->flags & IFF_LOOPBACK || rt_cmp_mtu(krt, nrt) == 0)) {
 #ifdef HAVE_ROUTE_LIFETIME
                if (rt_cmp_lifetime(krt, nrt) == 0) {
@@ -702,7 +727,7 @@ rt_cmp(const struct rt *r1, const struct rt *r2)
 #ifdef HAVE_ROUTE_METRIC
            r1->rt_metric == r2->rt_metric &&
 #endif
-           sa_cmp(&r1->rt_gateway, &r2->rt_gateway) == 0)
+           sa_cmp(r1->rt_gateway, r2->rt_gateway) == 0)
                return 0;
        return 1;
 }
@@ -720,8 +745,8 @@ rt_doroute(rb_tree_t *kroutes, struct rt *rt)
                if (rt->rt_dflags & RTDF_FAKE)
                        return true;
                if (or->rt_dflags & RTDF_FAKE || rt_cmp(rt, or) != 0 ||
-                   (rt->rt_ifa.sa_family != AF_UNSPEC &&
-                       sa_cmp(&or->rt_ifa, &rt->rt_ifa) != 0) ||
+                   (rt->rt_ifa->sa_family != AF_UNSPEC &&
+                       sa_cmp(or->rt_ifa, rt->rt_ifa) != 0) ||
 #ifdef HAVE_ROUTE_LIFETIME
                    rt_cmp_lifetime(rt, or) != 0 ||
 #endif
@@ -791,13 +816,13 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
                        continue;
 #ifdef BSD
                if (rt_is_default(rt) &&
-                   if_missfilter(rt->rt_ifp, &rt->rt_gateway) == -1)
+                   if_missfilter(rt->rt_ifp, rt->rt_gateway) == -1)
                        logerr("if_missfilter");
 #endif
-               if ((rt->rt_dest.sa_family != af &&
-                       rt->rt_dest.sa_family != AF_UNSPEC) ||
-                   (rt->rt_gateway.sa_family != af &&
-                       rt->rt_gateway.sa_family != AF_UNSPEC))
+               if ((rt->rt_dest->sa_family != af &&
+                       rt->rt_dest->sa_family != AF_UNSPEC) ||
+                   (rt->rt_gateway->sa_family != af &&
+                       rt->rt_gateway->sa_family != AF_UNSPEC))
                        continue;
                /* Is this route already in our table? */
                if (rb_tree_find_node(&added, rt) != NULL)
@@ -821,10 +846,10 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
        /* Remove old routes we used to manage. */
        RB_TREE_FOREACH_REVERSE_SAFE(rt, &ctx->routes, rtn)
        {
-               if ((rt->rt_dest.sa_family != af &&
-                       rt->rt_dest.sa_family != AF_UNSPEC) ||
-                   (rt->rt_gateway.sa_family != af &&
-                       rt->rt_gateway.sa_family != AF_UNSPEC))
+               if ((rt->rt_dest->sa_family != af &&
+                       rt->rt_dest->sa_family != AF_UNSPEC) ||
+                   (rt->rt_gateway->sa_family != af &&
+                       rt->rt_gateway->sa_family != AF_UNSPEC))
                        continue;
                rb_tree_remove_node(&ctx->routes, rt);
                if (rb_tree_find_node(&added, rt) == NULL) {
index bfe1d8ee54d90f0673778967995e5a2c3671d77a..62bfa511fe459dbae7cec67bcdf3f80a893835f0 100644 (file)
 #endif
 
 struct rt {
-       union sa_ss rt_ss_dest;
-#define rt_dest rt_ss_dest.sa
-       union sa_ss rt_ss_netmask;
-#define rt_netmask rt_ss_netmask.sa
-       union sa_ss rt_ss_gateway;
-#define rt_gateway rt_ss_gateway.sa
+       struct sockaddr *rt_dest;
+       struct sockaddr *rt_netmask;
+       struct sockaddr *rt_gateway;
        struct interface *rt_ifp;
-       union sa_ss rt_ss_ifa;
-#define rt_ifa rt_ss_ifa.sa
+       struct sockaddr *rt_ifa;
+
+       /* Storage for the above sockaddrs */
+       struct sockaddr_storage rt_ss_dest;
+       struct sockaddr_storage rt_ss_netmask;
+       struct sockaddr_storage rt_ss_gateway;
+       struct sockaddr_storage rt_ss_ifa;
+
        unsigned int rt_flags;
        unsigned int rt_mtu;
+
 #ifdef HAVE_ROUTE_METRIC
        unsigned int rt_metric;
 #endif
@@ -108,6 +112,7 @@ struct rt {
 #define RTMETRIC_WIRELESS 2000U
 #define RTMETRIC_IPV4LL          1000000U
 #define RTMETRIC_ROAM    2000000U
+
 #ifdef HAVE_ROUTE_PREF
        int rt_pref;
 #endif
@@ -116,6 +121,7 @@ struct rt {
 #define RTPREF_LOW     (-1)
 #define RTPREF_RESERVED (-2)
 #define RTPREF_INVALID (-3) /* internal */
+
        unsigned int rt_dflags;
 #define RTDF_IFA_ROUTE 0x01 /* Address generated route */
 #define RTDF_FAKE      0x02 /* Maybe us on lease reboot */
@@ -124,8 +130,10 @@ struct rt {
 #define RTDF_DHCP      0x10 /* DHCP route */
 #define RTDF_STATIC    0x20 /* Configured in dhcpcd */
 #define RTDF_GATELINK  0x40 /* Gateway is on link */
+
        size_t rt_order;
        rb_node_t rt_tree;
+
 #ifdef HAVE_ROUTE_LIFETIME
        struct timespec rt_aquired; /* timestamp of aquisition */
        uint32_t rt_lifetime;       /* current lifetime of route */
@@ -136,7 +144,7 @@ struct rt {
 extern const rb_tree_ops_t rt_compare_list_ops;
 extern const rb_tree_ops_t rt_compare_proto_ops;
 
-void rt_init(struct dhcpcd_ctx *);
+void rt_init_routes(struct dhcpcd_ctx *);
 void rt_dispose(struct dhcpcd_ctx *);
 void rt_free(struct rt *);
 void rt_freeif(struct interface *);
@@ -144,6 +152,8 @@ bool rt_is_default(const struct rt *);
 void rt_headclear0(struct dhcpcd_ctx *, rb_tree_t *, int);
 void rt_headclear(rb_tree_t *, int);
 void rt_headfreeif(rb_tree_t *);
+void rt_init(struct rt *);
+void rt_copy(struct rt *, const struct rt *);
 struct rt *rt_new0(struct dhcpcd_ctx *);
 void rt_setif(struct rt *, struct interface *);
 struct rt *rt_new(struct interface *);
index b2554099e1feaca146a7fcd74f50575ccf6bc740..b91ff79e3e5490ea344c57510a5847eea71f9998 100644 (file)
--- a/src/sa.c
+++ b/src/sa.c
@@ -281,11 +281,12 @@ sa_toprefix(const struct sockaddr *sa)
 #ifndef NDEBUG
        /* Ensure the calculation is correct */
        if (!sa_inprefix) {
-               union sa_ss ss = { .sa = { .sa_family = sa->sa_family } };
+               struct sockaddr_storage ss = { .ss_family = sa->sa_family };
+               struct sockaddr *ss_sa = (struct sockaddr *)&ss;
 
                sa_inprefix = true;
-               sa_fromprefix(&ss.sa, prefix);
-               assert(sa_cmp(sa, &ss.sa) == 0);
+               sa_fromprefix(ss_sa, prefix);
+               assert(sa_cmp(sa, ss_sa) == 0);
                sa_inprefix = false;
        }
 #endif
index e40d68fe1907229f6b6b035fcea0cf12e8567e62..9903125025b3858107e46e1cbb888dcab75098df 100644 (file)
--- a/src/sa.h
+++ b/src/sa.h
 
 #include <netinet/in.h>
 
-union sa_ss {
-       struct sockaddr sa;
-       struct sockaddr_in sin;
-       struct sockaddr_in6 sin6;
-//     struct sockaddr_storage ss; /* avoids memory overrun */
-};
-
 #ifdef BSD
 #define HAVE_SA_LEN
 #endif