Commit 6be71641 authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

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).
parent 3140c8b2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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); }

+5 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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()
+7 −1
Original line number Diff line number Diff line
@@ -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