summaryrefslogtreecommitdiff
path: root/net/ipv4/raw.c
diff options
context:
space:
mode:
authorDavid Ahern <dsa@cumulusnetworks.com>2016-11-03 09:25:00 -0700
committerDavid S. Miller <davem@davemloft.net>2016-11-07 13:14:34 -0500
commitcd2c0f454039ad303b54653c56ebc22ffd856200 (patch)
tree216cbe13e0e0bc29cd18c40203979e885153d4e2 /net/ipv4/raw.c
parent0ca6e000f5a8cb679c2da98bea14668126dc04d8 (diff)
net: Update raw socket bind to consider l3 domain
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>
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r--net/ipv4/raw.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 838ea5e33253..2300fae11b22 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -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)