net: Require exact match for TCP socket lookups if dif is l3mdev
authorDavid Ahern <dsa@cumulusnetworks.com>
Mon, 17 Oct 2016 03:02:52 +0000 (20:02 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Oct 2016 14:17:05 +0000 (10:17 -0400)
commita04a480d4392ea6efd117be2de564117b2a009c0
treea8a8b400fb1a06174a1b9a9838a3b72343fd8b84
parentfb5c6cfaec126d9a96b9dd471d4711bf4c737a6f
net: Require exact match for TCP socket lookups if dif is l3mdev

Currently, socket lookups for l3mdev (vrf) use cases can match a socket
that is bound to a port but not a device (ie., a global socket). If the
sysctl tcp_l3mdev_accept is not set this leads to ack packets going out
based on the main table even though the packet came in from an L3 domain.
The end result is that the connection does not establish creating
confusion for users since the service is running and a socket shows in
ss output. Fix by requiring an exact dif to sk_bound_dev_if match if the
skb came through an interface enslaved to an l3mdev device and the
tcp_l3mdev_accept is not set.

skb's through an l3mdev interface are marked by setting a flag in
inet{6}_skb_parm. The IPv6 variant is already set; this patch adds the
flag for IPv4. Using an skb flag avoids a device lookup on the dif. The
flag is set in the VRF driver using the IP{6}CB macros. For IPv4, the
inet_skb_parm struct is moved in the cb per commit 971f10eca186, so the
match function in the TCP stack needs to use TCP_SKB_CB. For IPv6, the
move is done after the socket lookup, so IP6CB is used.

The flags field in inet_skb_parm struct needs to be increased to add
another flag. There is currently a 1-byte hole following the flags,
so it can be expanded to u16 without increasing the size of the struct.

Fixes: 193125dbd8eb ("net: Introduce VRF device driver")
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vrf.c
include/linux/ipv6.h
include/net/ip.h
include/net/tcp.h
net/ipv4/inet_hashtables.c
net/ipv6/inet6_hashtables.c