net: Update raw socket bind to consider l3 domain
authorDavid Ahern <dsa@cumulusnetworks.com>
Thu, 3 Nov 2016 16:25:00 +0000 (09:25 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Nov 2016 18:14:34 +0000 (13:14 -0500)
Binding a raw socket to a local address fails if the socket is bound
to an L3 domain:

    $ vrf-test  -s -l 10.100.1.2 -R -I red
    error binding socket: 99: Cannot assign requested address

Update raw_bind to look consider if sk_bound_dev_if is bound to an L3
domain and use inet_addr_type_table to lookup the address.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/raw.c

index 838ea5e3325320e408059f16e7f7f63affed3083..2300fae11b22ea2beab67cdc4fbc6fe1b36222f5 100644 (file)
@@ -695,12 +695,20 @@ 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;
+       u32 tb_id = RT_TABLE_LOCAL;
        int ret = -EINVAL;
        int chk_addr_ret;
 
        if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
                goto out;
-       chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+
+       if (sk->sk_bound_dev_if)
+               tb_id = l3mdev_fib_table_by_index(sock_net(sk),
+                                                sk->sk_bound_dev_if) ? : tb_id;
+
+       chk_addr_ret = inet_addr_type_table(sock_net(sk), addr->sin_addr.s_addr,
+                                           tb_id);
+
        ret = -EADDRNOTAVAIL;
        if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
            chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)