]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
IO: Support nonlocal bind in socket interface
authorAlexander Zubkov <green@qrator.net>
Sat, 8 Jan 2022 17:31:56 +0000 (18:31 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sat, 8 Jan 2022 18:02:31 +0000 (19:02 +0100)
Add option to socket interface for nonlocal binding, i.e. binding to an
IP address that is not present on interfaces. This behaviour is enabled
when SKF_FREEBIND socket flag is set. For Linux systems, it is
implemented by IP_FREEBIND socket flag.

Minor changes done by commiter.

lib/socket.h
sysdep/bsd/sysio.h
sysdep/linux/sysio.h
sysdep/unix/io.c

index 96fedeebbb26bdca11f6b44caac70cd38d32ad95..0b6ac5898d6d0db42bf393b8d06fb7e8f2fbc39b 100644 (file)
@@ -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 */
index c757960a141149c6615a00c0cca97aea0c6f2607..f1887fb406b32fae44239274af325e45f5830c44 100644 (file)
@@ -271,3 +271,9 @@ sk_set_priority(sock *s, int prio UNUSED)
 {
   ERR_MSG("Socket priority not supported");
 }
+
+static inline int
+sk_set_freebind(sock *s)
+{
+  ERR_MSG("Freebind is not supported");
+}
index e21ff48743833308d3046fe48c470cff45499b25..f13eda7c08ad2b1f5b6847bd744d6656e478f4fb 100644 (file)
 #define IPV6_MINHOPCOUNT 73
 #endif
 
+#ifndef IPV6_FREEBIND
+#define IPV6_FREEBIND 78
+#endif
+
 #ifndef TCP_MD5SIG_EXT
 #define TCP_MD5SIG_EXT 32
 #endif
@@ -266,3 +270,18 @@ sk_set_priority(sock *s, int prio)
   return 0;
 }
 
+static inline int
+sk_set_freebind(sock *s)
+{
+  int y = 1;
+
+  if (sk_is_ipv4(s))
+    if (setsockopt(s->fd, SOL_IP, IP_FREEBIND, &y, sizeof(y)) < 0)
+      ERR("IP_FREEBIND");
+
+  if (sk_is_ipv6(s))
+    if (setsockopt(s->fd, SOL_IPV6, IPV6_FREEBIND, &y, sizeof(y)) < 0)
+      ERR("IPV6_FREEBIND");
+
+  return 0;
+}
index 3d67d0a7a8f07e6baf45d14470af3c5d897a05de..4fd774534f1f488ea600d4643cd1bd98d927e47f 100644 (file)
@@ -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");