diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-07-28 16:54:06 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-07-28 19:30:56 +0200 |
commit | 6be71641ef3baa8658d031f3624f4481b493bdaf (patch) | |
tree | 4d2064ba61b1460bad4aa47a820e99ced14976b9 | |
parent | 3140c8b2ca48263da1a1f12b478031dc4b572db7 (diff) |
BSD: Use MSG_DONTROUTE for unicast packets on FreeBSD
BSD systems cannot use SO_DONTROUTE, because it does not work properly
with multicast packets (perhaps it tries to find iface based on multicast
group address). But we can use MSG_DONTROUTE sendmsg() flag for unicast
packets. Works on FreeBSD, is ignored on OpenBSD and is broken on NetBSD
(i guess due to integrated routing table and ARP table).
-rw-r--r-- | lib/ip.h | 3 | ||||
-rw-r--r-- | sysdep/bsd/sysio.h | 5 | ||||
-rw-r--r-- | sysdep/cf/README | 1 | ||||
-rw-r--r-- | sysdep/unix/io.c | 8 |
4 files changed, 16 insertions, 1 deletions
@@ -309,6 +309,9 @@ static inline int ip6_is_v4mapped(ip6_addr a) #define ipa_is_link_local(x) 0 #endif +static inline int ip4_is_unicast(ip4_addr a) +{ return _I(a) < 0xe0000000; } + static inline int ipa_classify_net(ip_addr a) { return ipa_zero2(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); } diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h index 9b10e6e8..545276a3 100644 --- a/sysdep/bsd/sysio.h +++ b/sysdep/bsd/sysio.h @@ -12,6 +12,11 @@ #include <sys/param.h> +#ifdef __FreeBSD__ +/* Should be defined in sysdep/cf/bsd.h, but it is flavor-specific */ +#define CONFIG_DONTROUTE_UNICAST +#endif + #ifdef __NetBSD__ #ifndef IP_RECVTTL diff --git a/sysdep/cf/README b/sysdep/cf/README index e62c3481..9a7a4afa 100644 --- a/sysdep/cf/README +++ b/sysdep/cf/README @@ -11,6 +11,7 @@ CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket s CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD) CONFIG_NO_IFACE_BIND Bind to iface is not available, use workarounds (def for *BSD) CONFIG_UNIX_DONTROUTE Use setsockopts DONTROUTE (undef for *BSD) +CONFIG_DONTROUTE_UNICAST Use MSG_DONTROUTE flag for unicast packets (def for FreeBSD) CONFIG_USE_HDRINCL Use IP_HDRINCL instead of control messages for source address on raw IP sockets. CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid() diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 53a37a50..786c6a56 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -1574,6 +1574,7 @@ sk_sendmsg(sock *s) struct iovec iov = {s->tbuf, s->tpos - s->tbuf}; byte cmsg_buf[CMSG_TX_SPACE]; sockaddr dst; + int flags = 0; sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport); @@ -1584,6 +1585,11 @@ sk_sendmsg(sock *s) .msg_iovlen = 1 }; +#ifdef CONFIG_DONTROUTE_UNICAST + if (ipa_is_ip4(s->daddr) && ip4_is_unicast(ipa_to_ip4(s->daddr))) + flags = MSG_DONTROUTE; +#endif + #ifdef CONFIG_USE_HDRINCL byte hdr[20]; struct iovec iov2[2] = { {hdr, 20}, iov }; @@ -1599,7 +1605,7 @@ sk_sendmsg(sock *s) if (s->flags & SKF_PKTINFO) sk_prepare_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf)); - return sendmsg(s->fd, &msg, 0); + return sendmsg(s->fd, &msg, flags); } static inline int |