summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/socket.h1
-rw-r--r--sysdep/bsd/sysio.h6
-rw-r--r--sysdep/linux/sysio.h19
-rw-r--r--sysdep/unix/io.c4
4 files changed, 30 insertions, 0 deletions
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..f1887fb4 100644
--- a/sysdep/bsd/sysio.h
+++ b/sysdep/bsd/sysio.h
@@ -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");
+}
diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h
index e21ff487..f13eda7c 100644
--- a/sysdep/linux/sysio.h
+++ b/sysdep/linux/sysio.h
@@ -10,6 +10,10 @@
#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;
+}
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");