commit 3ed4532cf7b652adb14336ca4a611a49cfe3b262
Author: Alexander Zubkov <green@qrator.net>
Date:   Tue Dec 28 18:16:33 2021 +0100

    IO: Support nonlocal bind in socket interface
    
    Add option to socket interface for nonlocal binding, i.e. binding an IP
    address, that is not present on the interfaces. This behaviour is
    enabled when SKF_FREEBIND socket flag is set.
    It is now implemented for Linux system only with IP_FREEBIND socket flag.

diff --git a/lib/socket.h b/lib/socket.h
index 96fedeeb..0b6ac589 100644
--- a/lib/socket.h
+++ b/lib/socket.h
@@ -123,6 +123,7 @@ extern int sk_priority_control;		/* Suggested priority for control traffic, shou
 #define SKF_TTL_RX	0x08	/* Report TTL / Hop Limit for RX packets */
 #define SKF_BIND	0x10	/* Bind datagram socket to given source address */
 #define SKF_HIGH_PORT	0x20	/* Choose port from high range if possible */
+#define SKF_FREEBIND	0x40	/* Allow socket to bind to a nonlocal address */
 
 #define SKF_THREAD	0x100	/* Socked used in thread, Do not add to main loop */
 #define SKF_TRUNCATED	0x200	/* Received packet was truncated, set by IO layer */
diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h
index c757960a..2ae03aae 100644
--- a/sysdep/bsd/sysio.h
+++ b/sysdep/bsd/sysio.h
@@ -271,3 +271,11 @@ sk_set_priority(sock *s, int prio UNUSED)
 {
   ERR_MSG("Socket priority not supported");
 }
+
+static inline int
+sk_set_freebind(sock *s)
+{
+  ERR("IP free bind is not implemented");
+
+  return 0;
+}
diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h
index e21ff487..a55b5c2a 100644
--- a/sysdep/linux/sysio.h
+++ b/sysdep/linux/sysio.h
@@ -266,3 +266,16 @@ sk_set_priority(sock *s, int prio)
   return 0;
 }
 
+static inline int
+sk_set_freebind(sock *s)
+{
+#ifdef IP_FREEBIND
+  int y = 1;
+  if (setsockopt(s->fd, SOL_IP, IP_FREEBIND, &y, sizeof(y)) < 0)
+    ERR("IP_FREEBIND");
+#else
+  ERR("IP_FREEBIND is not supported");
+#endif
+
+  return 0;
+}
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 3d67d0a7..4fd77453 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -1436,6 +1436,10 @@ sk_open(sock *s)
 	if (sk_set_high_port(s) < 0)
 	  log(L_WARN "Socket error: %s%#m", s->err);
 
+    if (s->flags & SKF_FREEBIND)
+      if (sk_set_freebind(s) < 0)
+        log(L_WARN "Socket error: %s%#m", s->err);
+
     sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port);
     if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
       ERR2("bind");
