Lets set IP_FREEBIND on IPv6 sockets as well, this works since Linux 3.3
and doesn't require CAP_NET_ADMIN privileges (IPV6_TRANSPARENT does).
This allows unprivileged users to bind to non-local IPv6 addresses, which
can be useful when setting up the listening sockets or when connecting
to backend servers with a specific, non-local source IPv6 address (at that
point we usually dropped root privileges already).
---
Before this patch an unprivileged bind fails:
setsockopt(5, SOL_IPV6, 0x4b /* IPV6_TRANSPARENT */, [1], 4) = -1 EPERM
(Operation not permitted)
bind(5, {sa_family=AF_INET6, sin6_port=htons(1080), inet_pton(AF_INET6,
"2005::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1
EADDRNOTAVAIL (Cannot assign requested address)
After the patch:
setsockopt(5, SOL_IPV6, 0x4b /* IPV6_TRANSPARENT */, [1], 4) = -1 EPERM
(Operation not permitted)
setsockopt(5, SOL_IP, IP_FREEBIND, [1], 4) = 0
bind(5, {sa_family=AF_INET6, sin6_port=htons(1080), inet_pton(AF_INET6,
"2005::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
---
src/proto_tcp.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 11f6331..2b12ef8 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -160,6 +160,9 @@ int tcp_bind_socket(int fd, int flags, struct
sockaddr_storage *local, struct so
#if defined(IPV6_TRANSPARENT)
|| (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT,
&one, sizeof(one)) == 0)
#endif
+#if defined(IP_FREEBIND)
+ || (setsockopt(fd, SOL_IP, IP_FREEBIND, &one,
sizeof(one)) == 0)
+#endif
#if defined(IPV6_BINDANY)
|| (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY,
&one, sizeof(one)) == 0)
#endif
@@ -787,6 +790,9 @@ int tcp_bind_listener(struct listener *listener, char
*errmsg, int errlen)
#if defined(IPV6_TRANSPARENT)
&& (setsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT,
&one, sizeof(one)) == -1)
#endif
+#if defined(IP_FREEBIND)
+ && (setsockopt(fd, SOL_IP, IP_FREEBIND, &one,
sizeof(one)) == -1)
+#endif
#if defined(IPV6_BINDANY)
&& (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY,
&one, sizeof(one)) == -1)
#endif
--
1.7.9.5