From: Roy Marples Date: Thu, 28 Jul 2016 10:51:36 +0000 (+0000) Subject: Simplify BSD routing by having a common function to make the message X-Git-Tag: v6.11.2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3bcd5ea44a1e20a1e4fc843bafad890274f4291;p=thirdparty%2Fdhcpcd.git Simplify BSD routing by having a common function to make the message and the IP specific routines just generating the sockaddrs and flags. --- diff --git a/if-bsd.c b/if-bsd.c index 0d37d927..f6fb036c 100644 --- 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