]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BSD: Use MSG_DONTROUTE for unicast packets on FreeBSD
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Sat, 28 Jul 2018 14:54:06 +0000 (16:54 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sat, 28 Jul 2018 17:30:56 +0000 (19:30 +0200)
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).

lib/ip.h
sysdep/bsd/sysio.h
sysdep/cf/README
sysdep/unix/io.c

index 298b72a7eea8d1ad52e4cb9144b37fb48dc6930b..d876a70764a626762e944a9f5a98b215951fa783 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -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); }
 
index 9b10e6e82563bbf82f43d4263ed3f4324a1a33b2..545276a37c3ab3060baf606c3e7f83cc1b11d4bd 100644 (file)
 #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
index e62c348194ddce07ffef25fc3114cb26ae7a667b..9a7a4afafe0fc9b8a928c010d76458d72c6b96c9 100644 (file)
@@ -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()
index 53a37a501b284ca774710f1c2d0c1e0e8eb5cf32..786c6a56c38aae7ae9347d8ae094c7024f851fb5 100644 (file)
@@ -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