Add support to inet raw sockets for binding to nonlocal addresses
through the IP_FREEBIND and IP_TRANSPARENT socket options, as well as
the ipv4.ip_nonlocal_bind kernel parameter.

Signed-off-by: Riccardo Paolo Bestetti <p...@bestov.io>
---
 net/ipv4/raw.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 50a73178d63a..734c0332b54b 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -717,6 +717,7 @@ static int raw_bind(struct sock *sk, struct sockaddr 
*uaddr, int addr_len)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+       struct net *net = sock_net(sk);
        u32 tb_id = RT_TABLE_LOCAL;
        int ret = -EINVAL;
        int chk_addr_ret;
@@ -732,7 +733,8 @@ static int raw_bind(struct sock *sk, struct sockaddr 
*uaddr, int addr_len)
                                            tb_id);
 
        ret = -EADDRNOTAVAIL;
-       if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
+       if (!inet_can_nonlocal_bind(net, inet) &&
+           addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
            chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
                goto out;
        inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
-- 
2.31.0

Reply via email to