]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Simplify BSD routing by having a common function to make the message
authorRoy Marples <roy@marples.name>
Thu, 28 Jul 2016 10:51:36 +0000 (10:51 +0000)
committerRoy Marples <roy@marples.name>
Thu, 28 Jul 2016 10:51:36 +0000 (10:51 +0000)
and the IP specific routines just generating the sockaddrs and flags.

if-bsd.c

index 0d37d927a7302bbf79bd6e453d681c15210478ef..f6fb036cecc4baa29f6b7b5a9c9e494dbf5f91b2 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -358,6 +358,93 @@ if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa)
        errno = ENOENT;
        return NULL;
 }
+
+static int
+if_rtmsg(unsigned char cmd, const struct interface *ifp,
+    int addrs, int flags,
+#ifdef RTP_CONNECTED
+    int priority,
+#endif
+    const struct sockaddr *dst, const struct sockaddr *mask,
+    const struct sockaddr *gate, const struct sockaddr *src,
+    uint32_t mtu)
+{
+       struct rtm
+       {
+               struct rt_msghdr hdr;
+               char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX];
+       } rtm;
+       char *bp = rtm.buffer;
+       size_t l;
+       struct sockaddr_dl sdl;
+
+       if ((cmd == RTM_ADD || cmd == RTM_DELETE || cmd == RTM_CHANGE) &&
+           ifp->ctx->options & DHCPCD_DAEMONISE &&
+           !(ifp->ctx->options & DHCPCD_DAEMONISED))
+               ifp->ctx->options |= DHCPCD_RTM_PPID;
+
+#define ADDSA(sa) do {                                                       \
+               l = RT_ROUNDUP(((sa)->sa_len));                               \
+               memcpy(bp, (sa), l);                                          \
+               bp += l;                                                      \
+       }  while (0 /* CONSTCOND */)
+
+       memset(&rtm, 0, sizeof(rtm));
+       rtm.hdr.rtm_version = RTM_VERSION;
+       rtm.hdr.rtm_type = cmd;
+#ifdef __OpenBSD__
+       rtm.hdr.rtm_pid = getpid();
+#endif
+       rtm.hdr.rtm_seq = ++ifp->ctx->seq;
+       rtm.hdr.rtm_flags = flags;
+       rtm.hdr.rtm_addrs = RTA_DST | addrs;
+#ifdef RTF_PINNED
+       if (cmd != RTM_ADD)
+               rtm.hdr.rtm_flags |= RTF_PINNED;
+#endif
+#ifdef RTP_CONNECTED
+       rtm.hdr.rtm_priority = priority;
+#endif
+
+       if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
+               rtm.hdr.rtm_flags |= RTF_UP;
+               rtm.hdr.rtm_addrs |= RTA_GATEWAY;
+               if (rtm.hdr.rtm_flags & (RTF_GATEWAY | RTF_REJECT))
+                       /* Going via lo0 so remove the interface flags. */
+                       rtm.hdr.rtm_addrs &= ~(RTA_IFP | RTA_IFA);
+               if (mtu != 0) {
+                       rtm.hdr.rtm_inits |= RTV_MTU;
+                       rtm.hdr.rtm_rmx.rmx_mtu = mtu;
+               }
+       }
+
+       ADDSA(dst);
+       if_linkaddr(&sdl, ifp);
+       if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
+               if (gate == NULL)
+                       ADDSA((struct sockaddr *)&sdl);
+               else
+                       ADDSA(gate);
+       }
+       if (rtm.hdr.rtm_addrs & RTA_NETMASK)
+               ADDSA(mask);
+
+       if (rtm.hdr.rtm_addrs & RTA_IFP) {
+               rtm.hdr.rtm_index = (unsigned short)ifp->index;
+               ADDSA((struct sockaddr *)&sdl);
+       }
+
+       if (rtm.hdr.rtm_addrs & RTA_IFA)
+               ADDSA(src);
+
+#undef ADDSA
+
+       rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
+       if (write(ifp->ctx->link_fd, &rtm, rtm.hdr.rtm_msglen) == -1)
+               return -1;
+       ifp->ctx->sseq = ifp->ctx->seq;
+       return 0;
+}
 #endif
 
 #ifdef INET
@@ -623,68 +710,55 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
 int
 if_route(unsigned char cmd, const struct rt *rt)
 {
-       union sockunion {
-               struct sockaddr sa;
-               struct sockaddr_in sin;
-               struct sockaddr_dl sdl;
-       } su;
-       struct rtm
-       {
-               struct rt_msghdr hdr;
-               char buffer[sizeof(su) * RTAX_MAX];
-       } rtm;
-       char *bp = rtm.buffer;
-       size_t l;
-
-       if ((cmd == RTM_ADD || cmd == RTM_DELETE || cmd == RTM_CHANGE) &&
-           rt->iface->ctx->options & DHCPCD_DAEMONISE &&
-           !(rt->iface->ctx->options & DHCPCD_DAEMONISED))
-               rt->iface->ctx->options |= DHCPCD_RTM_PPID;
-
-#define ADDSU {                                                                      \
-               l = RT_ROUNDUP(su.sa.sa_len);                                 \
-               memcpy(bp, &su, l);                                           \
-               bp += l;                                                      \
-       }
-#define ADDADDR(addr) {                                                              \
-               memset(&su, 0, sizeof(su));                                   \
-               su.sin.sin_family = AF_INET;                                  \
-               su.sin.sin_len = sizeof(su.sin);                              \
-               (&su.sin)->sin_addr = *(addr);                                \
-               ADDSU;                                                        \
-       }
-
-       memset(&rtm, 0, sizeof(rtm));
-       rtm.hdr.rtm_version = RTM_VERSION;
-       rtm.hdr.rtm_type = cmd;
-       rtm.hdr.rtm_addrs = RTA_DST;
-       rtm.hdr.rtm_flags = RTF_UP;
-       rtm.hdr.rtm_pid = getpid();
-       rtm.hdr.rtm_seq = ++rt->iface->ctx->seq;
-#ifdef RTF_PINNED
-       if (cmd != RTM_ADD)
-               rtm.hdr.rtm_flags |= RTF_PINNED;
+       struct sockaddr_in dst = {
+               .sin_family = AF_INET,
+               .sin_len = sizeof(dst),
+               .sin_addr = rt->dest
+       };
+       struct sockaddr_in mask = {
+               .sin_family = AF_INET,
+               .sin_len = sizeof(mask),
+               .sin_addr = rt->mask
+       };
+       struct sockaddr_in gate = {
+               .sin_family = AF_INET,
+               .sin_len = sizeof(gate),
+               .sin_addr = rt->gate
+       };
+       struct sockaddr_in src = {
+               .sin_family = AF_INET,
+               .sin_len = sizeof(src),
+               .sin_addr = rt->src
+       };
+       struct sockaddr_in *g;
+       int addrs, flags;
+#ifdef RTP_CONNECTED
+       int priority = 0;
 #endif
 
+       addrs = 0;
+       flags = 0;
+
        if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
-               rtm.hdr.rtm_addrs |= RTA_GATEWAY | RTA_IFP;
-               if (rt->src.s_addr != htonl(INADDR_ANY))
-                       rtm.hdr.rtm_addrs |= RTA_IFA;
-               /* Subnet routes are clonning or connected if supported.
+               addrs |= RTA_GATEWAY | RTA_IFP;
+               /* Subnet routes are cloning or connected if supported.
                 * All other routes are static. */
-               if (rt->gate.s_addr == htonl(INADDR_ANY)) {
+               if (rt->gate.s_addr == ntohl(INADDR_ANY)) {
 #ifdef RTF_CLONING
-                       rtm.hdr.rtm_flags |= RTF_CLONING;
+                       flags |= RTF_CLONING;
 #endif
 #ifdef RTF_CONNECTED
-                       rtm.hdr.rtm_flags |= RTF_CONNECTED;
+                       flags |= RTF_CONNECTED;
 #endif
 #ifdef RTP_CONNECTED
-                       rtm.hdr.rtm_priority = RTP_CONNECTED;
+                       priority = RTP_CONNECTED;
 #endif
                } else
-                       rtm.hdr.rtm_flags |= RTF_STATIC;
+                       flags |= RTF_STATIC;
+               if (rt->src.s_addr != ntohl(INADDR_ANY))
+                       addrs |= RTA_IFA;
        }
+
        if (rt->mask.s_addr == htonl(INADDR_BROADCAST) &&
            rt->gate.s_addr == htonl(INADDR_ANY))
        {
@@ -695,74 +769,45 @@ if_route(unsigned char cmd, const struct rt *rt)
                 * It might be more correct to use RTF_HOST instead of
                 * RTF_CLONING, and that does work, but some OS generate
                 * an arp warning diagnostic which we don't want to do. */
-               rtm.hdr.rtm_flags |= RTF_CLONING;
-               rtm.hdr.rtm_addrs |= RTA_NETMASK;
+               flags |= RTF_CLONING;
+               addrs |= RTA_NETMASK;
 #else
-               rtm.hdr.rtm_flags |= RTF_HOST;
+               flags |= RTF_HOST;
 #endif
        } else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
            rt->mask.s_addr == htonl(INADDR_BROADCAST))
        {
-               rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
+               flags |= RTF_HOST | RTF_GATEWAY;
                /* Going via lo0 so remove the interface flags */
-               if (cmd == RTM_ADD)
-                       rtm.hdr.rtm_addrs &= ~(RTA_IFA | RTA_IFP);
+               addrs &= ~(RTA_IFA | RTA_IFP);
        } else {
-               rtm.hdr.rtm_addrs |= RTA_NETMASK;
-               if (rtm.hdr.rtm_flags & RTF_STATIC)
-                       rtm.hdr.rtm_flags |= RTF_GATEWAY;
+               addrs |= RTA_NETMASK;
+               if (flags & RTF_STATIC)
+                       flags |= RTF_GATEWAY;
                if (rt->mask.s_addr == htonl(INADDR_BROADCAST))
-                       rtm.hdr.rtm_flags |= RTF_HOST;
+                       flags |= RTF_HOST;
        }
-       if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
-           !(rtm.hdr.rtm_flags & RTF_GATEWAY))
-               rtm.hdr.rtm_addrs |= RTA_IFP;
 
-       ADDADDR(&rt->dest);
-       if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
-               if ((rtm.hdr.rtm_flags & RTF_HOST &&
-                   rt->gate.s_addr == htonl(INADDR_ANY)) ||
+       if ((flags & RTF_HOST && rt->gate.s_addr == htonl(INADDR_ANY)) ||
 #ifdef RTF_CLONING
-                   rtm.hdr.rtm_flags & RTF_CLONING ||
+          flags & RTF_CLONING ||
 #endif
 #ifdef RTF_CONNECTED
-                   rtm.hdr.rtm_flags & RTF_CONNECTED ||
+           flags & RTF_CONNECTED ||
 #endif
-                   !(rtm.hdr.rtm_flags & RTF_STATIC))
-               {
-                       if_linkaddr(&su.sdl, rt->iface);
-                       ADDSU;
-               } else
-                       ADDADDR(&rt->gate);
-       }
-
-       if (rtm.hdr.rtm_addrs & RTA_NETMASK)
-               ADDADDR(&rt->mask);
-
-       if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
-               rtm.hdr.rtm_index = (unsigned short)rt->iface->index;
-               if (rtm.hdr.rtm_addrs & RTA_IFP) {
-                       if_linkaddr(&su.sdl, rt->iface);
-                       ADDSU;
-               }
-
-               if (rtm.hdr.rtm_addrs & RTA_IFA)
-                       ADDADDR(&rt->src);
-
-               if (rt->mtu) {
-                       rtm.hdr.rtm_inits |= RTV_MTU;
-                       rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
-               }
-       }
-
-#undef ADDADDR
-#undef ADDSU
-
-       rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
-       if (write(rt->iface->ctx->link_fd, &rtm, rtm.hdr.rtm_msglen) == -1)
-               return -1;
-       rt->iface->ctx->sseq = rt->iface->ctx->seq;
-       return 0;
+#ifdef RTP_CONNECTED
+           priority != 0 ||
+#endif
+           !(flags & RTF_STATIC))
+               g = NULL;
+       else
+               g = &gate;
+       return if_rtmsg(cmd, rt->iface, addrs, flags,
+#ifdef RTP_CONNECTED
+           priority,
+#endif
+           (struct sockaddr *)&dst, (struct sockaddr *)&mask,
+           (struct sockaddr *)g, (struct sockaddr *)&src, rt->mtu);
 }
 
 int
@@ -1013,114 +1058,63 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, const struct rt_msghdr *rtm)
 int
 if_route6(unsigned char cmd, const struct rt6 *rt)
 {
-       union sockunion {
-               struct sockaddr sa;
-               struct sockaddr_in6 sin;
-               struct sockaddr_dl sdl;
-       } su;
-       struct rtm
-       {
-               struct rt_msghdr hdr;
-               char buffer[sizeof(su) * RTAX_MAX];
-       } rtm;
-       char *bp = rtm.buffer;
-       size_t l;
-
-       if ((cmd == RTM_ADD || cmd == RTM_DELETE || cmd == RTM_CHANGE) &&
-           rt->iface->ctx->options & DHCPCD_DAEMONISE &&
-           !(rt->iface->ctx->options & DHCPCD_DAEMONISED))
-               rt->iface->ctx->options |= DHCPCD_RTM_PPID;
-
-#define ADDSU {                                                                      \
-               l = RT_ROUNDUP(su.sa.sa_len);                                 \
-               memcpy(bp, &su, l);                                           \
-               bp += l;                                                      \
-       }
-#define ADDADDRS(addr, scope) {                                                      \
-               memset(&su, 0, sizeof(su));                                   \
-               su.sin.sin6_family = AF_INET6;                                \
-               su.sin.sin6_len = sizeof(su.sin);                             \
-               (&su.sin)->sin6_addr = *addr;                                 \
-               if (scope)                                                    \
-                       ifa_scope(&su.sin, scope);                            \
-               ADDSU;                                                        \
-       }
-#define ADDADDR(addr) ADDADDRS(addr, 0)
+       struct sockaddr_in6 dst = {
+               .sin6_family = AF_INET6,
+               .sin6_len = sizeof(dst),
+               .sin6_addr = rt->dest
+       };
+       struct sockaddr_in6 mask = {
+               .sin6_family = AF_INET6,
+               .sin6_len = sizeof(mask),
+               .sin6_addr = rt->mask
+       };
+       struct sockaddr_in6 gate = {
+               .sin6_family = AF_INET6,
+               .sin6_len = sizeof(gate),
+               .sin6_addr = rt->gate
+       };
+       struct sockaddr_in6 src = {
+               .sin6_family = AF_INET6,
+               .sin6_len = sizeof(src),
+               .sin6_addr = rt->src
+       };
+       struct sockaddr_in6 *g;
+       int addrs, flags;
+#ifdef RTP_CONNECTED
+       int priority = 0;
+#endif
 
-       memset(&rtm, 0, sizeof(rtm));
-       rtm.hdr.rtm_version = RTM_VERSION;
-       rtm.hdr.rtm_type = cmd;
-       rtm.hdr.rtm_flags = RTF_UP | (int)rt->flags;
-       rtm.hdr.rtm_pid = getpid();
-       rtm.hdr.rtm_seq = ++rt->iface->ctx->seq;
+       addrs = RTA_NETMASK;
+       flags = 0;
 #ifdef RTF_PINNED
-       if (rtm.hdr.rtm_type != RTM_ADD)
-               rtm.hdr.rtm_flags |= RTF_PINNED;
+       if (cmd != RTM_ADD)
+               flags |= RTF_PINNED;
 #endif
-       rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
-       /* None interface subnet routes are static. */
+
        if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
 #ifdef RTF_CLONING
-               rtm.hdr.rtm_flags |= RTF_CLONING;
+               flags |= RTF_CLONING;
 #endif
 #ifdef RTF_CONNECTED
-               rtm.hdr.rtm_flags |= RTF_CONNECTED;
+               flags |= RTF_CONNECTED;
 #endif
 #ifdef RTP_CONNECTED
-               rtm.hdr.rtm_priority = RTP_CONNECTED;
+               priority = RTP_CONNECTED;
 #endif
        } else
-               rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC;
-
-       if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
-               rtm.hdr.rtm_addrs |= RTA_GATEWAY;
-               if (!(rtm.hdr.rtm_flags & RTF_REJECT))
-                       rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
-       }
-
-       ADDADDR(&rt->dest);
-       if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
-               if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
-                       if_linkaddr(&su.sdl, rt->iface);
-                       ADDSU;
-               } else {
-                       ADDADDRS(&rt->gate, rt->iface->index);
-               }
-       }
-
-       if (rtm.hdr.rtm_addrs & RTA_NETMASK)
-               ADDADDR(&rt->mask);
+               flags |= RTF_GATEWAY | RTF_STATIC;
 
-       if (cmd == RTM_ADD || cmd == RTM_CHANGE) {
-               rtm.hdr.rtm_index = (unsigned short)rt->iface->index;
-               if (rtm.hdr.rtm_addrs & RTA_IFP) {
-                       if_linkaddr(&su.sdl, rt->iface);
-                       ADDSU;
-               }
-
-               if (rtm.hdr.rtm_addrs & RTA_IFA) {
-                       const struct ipv6_addr *lla;
-
-                       lla = ipv6_linklocal(UNCONST(rt->iface));
-                       if (lla == NULL) /* unlikely */
-                                       return -1;
-                       ADDADDRS(&lla->addr, rt->iface->index);
-               }
-
-               if (rt->mtu) {
-                       rtm.hdr.rtm_inits |= RTV_MTU;
-                       rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
-               }
-       }
-
-#undef ADDADDR
-#undef ADDSU
+       if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate))
+               g = NULL;
+       else
+               g = &gate;
 
-       rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
-       if (write(rt->iface->ctx->link_fd, &rtm, rtm.hdr.rtm_msglen) == -1)
-               return -1;
-       rt->iface->ctx->sseq = rt->iface->ctx->seq;
-       return 0;
+       return if_rtmsg(cmd, rt->iface, addrs, flags,
+#ifdef RTP_CONNECTED
+           priority,
+#endif
+           (struct sockaddr *)&dst, (struct sockaddr *)&mask,
+           (struct sockaddr *)g, (struct sockaddr *)&src, rt->mtu);
 }
 
 int