aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-08-07 14:39:22 -0400
committerDavid S. Miller <davem@davemloft.net>2017-08-07 14:39:22 -0400
commit9bcb5a572fd6aed8fd1974ea24830f8a657cbfa2 (patch)
tree0eb95dbb9e503991b36468ccf4b00a010697f664
parent46d4b68f891bee5d83a32508bfbd9778be6b1b63 (diff)
parent5108ab4bf446fa9ad2c71f5fc1d839067b72636f (diff)
Merge branch 'net-l3mdev-Support-for-sockets-bound-to-enslaved-device'
David Ahern says: ==================== net: l3mdev: Support for sockets bound to enslaved device A missing piece to the VRF puzzle is the ability to bind sockets to devices enslaved to a VRF. This patch set adds the enslaved device index, sdif, to IPv4 and IPv6 socket lookups. The end result for users is the following scope options for services: 1. "global" services - sockets not bound to any device Allows 1 service to work across all network interfaces with connected sockets bound to the VRF the connection originates (Requires net.ipv4.tcp_l3mdev_accept=1 for TCP and net.ipv4.udp_l3mdev_accept=1 for UDP) 2. "VRF" local services - sockets bound to a VRF Sockets work across all network interfaces enslaved to a VRF but are limited to just the one VRF. 3. "device" services - sockets bound to a specific network interface Service works only through the one specific interface. v3 - convert __inet_lookup_established in dccp_v4_err; missed in v2 v2 - remove sk_lookup struct and add sdif as an argument to existing functions Changes since RFC: - no significant logic changes; mainly whitespace cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/igmp.h3
-rw-r--r--include/linux/ipv6.h10
-rw-r--r--include/net/inet6_hashtables.h22
-rw-r--r--include/net/inet_hashtables.h31
-rw-r--r--include/net/ip.h10
-rw-r--r--include/net/raw.h2
-rw-r--r--include/net/rawv6.h2
-rw-r--r--include/net/tcp.h20
-rw-r--r--include/net/udp.h4
-rw-r--r--net/dccp/ipv4.c4
-rw-r--r--net/dccp/ipv6.c4
-rw-r--r--net/ipv4/igmp.c6
-rw-r--r--net/ipv4/inet_hashtables.c27
-rw-r--r--net/ipv4/raw.c18
-rw-r--r--net/ipv4/raw_diag.c4
-rw-r--r--net/ipv4/tcp_ipv4.c13
-rw-r--r--net/ipv4/udp.c66
-rw-r--r--net/ipv4/udp_diag.c10
-rw-r--r--net/ipv6/inet6_hashtables.c28
-rw-r--r--net/ipv6/raw.c13
-rw-r--r--net/ipv6/tcp_ipv6.c13
-rw-r--r--net/ipv6/udp.c47
-rw-r--r--net/netfilter/xt_TPROXY.c6
23 files changed, 228 insertions, 135 deletions
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 97caf1821de8..f8231854b5d6 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -118,7 +118,8 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
118 struct ip_msfilter __user *optval, int __user *optlen); 118 struct ip_msfilter __user *optval, int __user *optlen);
119extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, 119extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
120 struct group_filter __user *optval, int __user *optlen); 120 struct group_filter __user *optval, int __user *optlen);
121extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif); 121extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt,
122 int dif, int sdif);
122extern void ip_mc_init_dev(struct in_device *); 123extern void ip_mc_init_dev(struct in_device *);
123extern void ip_mc_destroy_dev(struct in_device *); 124extern void ip_mc_destroy_dev(struct in_device *);
124extern void ip_mc_up(struct in_device *); 125extern void ip_mc_up(struct in_device *);
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 474d6bbc158c..ac2da4e11d5e 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -159,6 +159,16 @@ static inline bool inet6_is_jumbogram(const struct sk_buff *skb)
159} 159}
160 160
161/* can not be used in TCP layer after tcp_v6_fill_cb */ 161/* can not be used in TCP layer after tcp_v6_fill_cb */
162static inline int inet6_sdif(const struct sk_buff *skb)
163{
164#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
165 if (skb && ipv6_l3mdev_skb(IP6CB(skb)->flags))
166 return IP6CB(skb)->iif;
167#endif
168 return 0;
169}
170
171/* can not be used in TCP layer after tcp_v6_fill_cb */
162static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb) 172static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
163{ 173{
164#if defined(CONFIG_NET_L3_MASTER_DEV) 174#if defined(CONFIG_NET_L3_MASTER_DEV)
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index b87becacd9d3..6e91e38a31da 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -49,7 +49,8 @@ struct sock *__inet6_lookup_established(struct net *net,
49 const struct in6_addr *saddr, 49 const struct in6_addr *saddr,
50 const __be16 sport, 50 const __be16 sport,
51 const struct in6_addr *daddr, 51 const struct in6_addr *daddr,
52 const u16 hnum, const int dif); 52 const u16 hnum, const int dif,
53 const int sdif);
53 54
54struct sock *inet6_lookup_listener(struct net *net, 55struct sock *inet6_lookup_listener(struct net *net,
55 struct inet_hashinfo *hashinfo, 56 struct inet_hashinfo *hashinfo,
@@ -57,7 +58,8 @@ struct sock *inet6_lookup_listener(struct net *net,
57 const struct in6_addr *saddr, 58 const struct in6_addr *saddr,
58 const __be16 sport, 59 const __be16 sport,
59 const struct in6_addr *daddr, 60 const struct in6_addr *daddr,
60 const unsigned short hnum, const int dif); 61 const unsigned short hnum,
62 const int dif, const int sdif);
61 63
62static inline struct sock *__inet6_lookup(struct net *net, 64static inline struct sock *__inet6_lookup(struct net *net,
63 struct inet_hashinfo *hashinfo, 65 struct inet_hashinfo *hashinfo,
@@ -66,24 +68,25 @@ static inline struct sock *__inet6_lookup(struct net *net,
66 const __be16 sport, 68 const __be16 sport,
67 const struct in6_addr *daddr, 69 const struct in6_addr *daddr,
68 const u16 hnum, 70 const u16 hnum,
69 const int dif, 71 const int dif, const int sdif,
70 bool *refcounted) 72 bool *refcounted)
71{ 73{
72 struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr, 74 struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
73 sport, daddr, hnum, dif); 75 sport, daddr, hnum,
76 dif, sdif);
74 *refcounted = true; 77 *refcounted = true;
75 if (sk) 78 if (sk)
76 return sk; 79 return sk;
77 *refcounted = false; 80 *refcounted = false;
78 return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport, 81 return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
79 daddr, hnum, dif); 82 daddr, hnum, dif, sdif);
80} 83}
81 84
82static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, 85static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
83 struct sk_buff *skb, int doff, 86 struct sk_buff *skb, int doff,
84 const __be16 sport, 87 const __be16 sport,
85 const __be16 dport, 88 const __be16 dport,
86 int iif, 89 int iif, int sdif,
87 bool *refcounted) 90 bool *refcounted)
88{ 91{
89 struct sock *sk = skb_steal_sock(skb); 92 struct sock *sk = skb_steal_sock(skb);
@@ -95,7 +98,7 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
95 return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, 98 return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
96 doff, &ipv6_hdr(skb)->saddr, sport, 99 doff, &ipv6_hdr(skb)->saddr, sport,
97 &ipv6_hdr(skb)->daddr, ntohs(dport), 100 &ipv6_hdr(skb)->daddr, ntohs(dport),
98 iif, refcounted); 101 iif, sdif, refcounted);
99} 102}
100 103
101struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, 104struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
@@ -107,13 +110,14 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
107int inet6_hash(struct sock *sk); 110int inet6_hash(struct sock *sk);
108#endif /* IS_ENABLED(CONFIG_IPV6) */ 111#endif /* IS_ENABLED(CONFIG_IPV6) */
109 112
110#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \ 113#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \
111 (((__sk)->sk_portpair == (__ports)) && \ 114 (((__sk)->sk_portpair == (__ports)) && \
112 ((__sk)->sk_family == AF_INET6) && \ 115 ((__sk)->sk_family == AF_INET6) && \
113 ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \ 116 ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \
114 ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \ 117 ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \
115 (!(__sk)->sk_bound_dev_if || \ 118 (!(__sk)->sk_bound_dev_if || \
116 ((__sk)->sk_bound_dev_if == (__dif))) && \ 119 ((__sk)->sk_bound_dev_if == (__dif)) || \
120 ((__sk)->sk_bound_dev_if == (__sdif))) && \
117 net_eq(sock_net(__sk), (__net))) 121 net_eq(sock_net(__sk), (__net)))
118 122
119#endif /* _INET6_HASHTABLES_H */ 123#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 5026b1f08bb8..2dbbbff5e1e3 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -221,16 +221,16 @@ struct sock *__inet_lookup_listener(struct net *net,
221 const __be32 saddr, const __be16 sport, 221 const __be32 saddr, const __be16 sport,
222 const __be32 daddr, 222 const __be32 daddr,
223 const unsigned short hnum, 223 const unsigned short hnum,
224 const int dif); 224 const int dif, const int sdif);
225 225
226static inline struct sock *inet_lookup_listener(struct net *net, 226static inline struct sock *inet_lookup_listener(struct net *net,
227 struct inet_hashinfo *hashinfo, 227 struct inet_hashinfo *hashinfo,
228 struct sk_buff *skb, int doff, 228 struct sk_buff *skb, int doff,
229 __be32 saddr, __be16 sport, 229 __be32 saddr, __be16 sport,
230 __be32 daddr, __be16 dport, int dif) 230 __be32 daddr, __be16 dport, int dif, int sdif)
231{ 231{
232 return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport, 232 return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
233 daddr, ntohs(dport), dif); 233 daddr, ntohs(dport), dif, sdif);
234} 234}
235 235
236/* Socket demux engine toys. */ 236/* Socket demux engine toys. */
@@ -262,22 +262,24 @@ static inline struct sock *inet_lookup_listener(struct net *net,
262 (((__force __u64)(__be32)(__daddr)) << 32) | \ 262 (((__force __u64)(__be32)(__daddr)) << 32) | \
263 ((__force __u64)(__be32)(__saddr))) 263 ((__force __u64)(__be32)(__saddr)))
264#endif /* __BIG_ENDIAN */ 264#endif /* __BIG_ENDIAN */
265#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \ 265#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
266 (((__sk)->sk_portpair == (__ports)) && \ 266 (((__sk)->sk_portpair == (__ports)) && \
267 ((__sk)->sk_addrpair == (__cookie)) && \ 267 ((__sk)->sk_addrpair == (__cookie)) && \
268 (!(__sk)->sk_bound_dev_if || \ 268 (!(__sk)->sk_bound_dev_if || \
269 ((__sk)->sk_bound_dev_if == (__dif))) && \ 269 ((__sk)->sk_bound_dev_if == (__dif)) || \
270 ((__sk)->sk_bound_dev_if == (__sdif))) && \
270 net_eq(sock_net(__sk), (__net))) 271 net_eq(sock_net(__sk), (__net)))
271#else /* 32-bit arch */ 272#else /* 32-bit arch */
272#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ 273#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
273 const int __name __deprecated __attribute__((unused)) 274 const int __name __deprecated __attribute__((unused))
274 275
275#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \ 276#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
276 (((__sk)->sk_portpair == (__ports)) && \ 277 (((__sk)->sk_portpair == (__ports)) && \
277 ((__sk)->sk_daddr == (__saddr)) && \ 278 ((__sk)->sk_daddr == (__saddr)) && \
278 ((__sk)->sk_rcv_saddr == (__daddr)) && \ 279 ((__sk)->sk_rcv_saddr == (__daddr)) && \
279 (!(__sk)->sk_bound_dev_if || \ 280 (!(__sk)->sk_bound_dev_if || \
280 ((__sk)->sk_bound_dev_if == (__dif))) && \ 281 ((__sk)->sk_bound_dev_if == (__dif)) || \
282 ((__sk)->sk_bound_dev_if == (__sdif))) && \
281 net_eq(sock_net(__sk), (__net))) 283 net_eq(sock_net(__sk), (__net)))
282#endif /* 64-bit arch */ 284#endif /* 64-bit arch */
283 285
@@ -288,7 +290,7 @@ struct sock *__inet_lookup_established(struct net *net,
288 struct inet_hashinfo *hashinfo, 290 struct inet_hashinfo *hashinfo,
289 const __be32 saddr, const __be16 sport, 291 const __be32 saddr, const __be16 sport,
290 const __be32 daddr, const u16 hnum, 292 const __be32 daddr, const u16 hnum,
291 const int dif); 293 const int dif, const int sdif);
292 294
293static inline struct sock * 295static inline struct sock *
294 inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, 296 inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
@@ -297,7 +299,7 @@ static inline struct sock *
297 const int dif) 299 const int dif)
298{ 300{
299 return __inet_lookup_established(net, hashinfo, saddr, sport, daddr, 301 return __inet_lookup_established(net, hashinfo, saddr, sport, daddr,
300 ntohs(dport), dif); 302 ntohs(dport), dif, 0);
301} 303}
302 304
303static inline struct sock *__inet_lookup(struct net *net, 305static inline struct sock *__inet_lookup(struct net *net,
@@ -305,20 +307,20 @@ static inline struct sock *__inet_lookup(struct net *net,
305 struct sk_buff *skb, int doff, 307 struct sk_buff *skb, int doff,
306 const __be32 saddr, const __be16 sport, 308 const __be32 saddr, const __be16 sport,
307 const __be32 daddr, const __be16 dport, 309 const __be32 daddr, const __be16 dport,
308 const int dif, 310 const int dif, const int sdif,
309 bool *refcounted) 311 bool *refcounted)
310{ 312{
311 u16 hnum = ntohs(dport); 313 u16 hnum = ntohs(dport);
312 struct sock *sk; 314 struct sock *sk;
313 315
314 sk = __inet_lookup_established(net, hashinfo, saddr, sport, 316 sk = __inet_lookup_established(net, hashinfo, saddr, sport,
315 daddr, hnum, dif); 317 daddr, hnum, dif, sdif);
316 *refcounted = true; 318 *refcounted = true;
317 if (sk) 319 if (sk)
318 return sk; 320 return sk;
319 *refcounted = false; 321 *refcounted = false;
320 return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, 322 return __inet_lookup_listener(net, hashinfo, skb, doff, saddr,
321 sport, daddr, hnum, dif); 323 sport, daddr, hnum, dif, sdif);
322} 324}
323 325
324static inline struct sock *inet_lookup(struct net *net, 326static inline struct sock *inet_lookup(struct net *net,
@@ -332,7 +334,7 @@ static inline struct sock *inet_lookup(struct net *net,
332 bool refcounted; 334 bool refcounted;
333 335
334 sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, 336 sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
335 dport, dif, &refcounted); 337 dport, dif, 0, &refcounted);
336 338
337 if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt)) 339 if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
338 sk = NULL; 340 sk = NULL;
@@ -344,6 +346,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
344 int doff, 346 int doff,
345 const __be16 sport, 347 const __be16 sport,
346 const __be16 dport, 348 const __be16 dport,
349 const int sdif,
347 bool *refcounted) 350 bool *refcounted)
348{ 351{
349 struct sock *sk = skb_steal_sock(skb); 352 struct sock *sk = skb_steal_sock(skb);
@@ -355,7 +358,7 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
355 358
356 return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, 359 return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
357 doff, iph->saddr, sport, 360 doff, iph->saddr, sport,
358 iph->daddr, dport, inet_iif(skb), 361 iph->daddr, dport, inet_iif(skb), sdif,
359 refcounted); 362 refcounted);
360} 363}
361 364
diff --git a/include/net/ip.h b/include/net/ip.h
index 9e59dcf1787a..39db596eb89f 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -78,6 +78,16 @@ struct ipcm_cookie {
78#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) 78#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
79#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb)) 79#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
80 80
81/* return enslaved device index if relevant */
82static inline int inet_sdif(struct sk_buff *skb)
83{
84#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
85 if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
86 return IPCB(skb)->iif;
87#endif
88 return 0;
89}
90
81struct ip_ra_chain { 91struct ip_ra_chain {
82 struct ip_ra_chain __rcu *next; 92 struct ip_ra_chain __rcu *next;
83 struct sock *sk; 93 struct sock *sk;
diff --git a/include/net/raw.h b/include/net/raw.h
index 57c33dd22ec4..99d26d0c4a19 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -26,7 +26,7 @@ extern struct proto raw_prot;
26extern struct raw_hashinfo raw_v4_hashinfo; 26extern struct raw_hashinfo raw_v4_hashinfo;
27struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, 27struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
28 unsigned short num, __be32 raddr, 28 unsigned short num, __be32 raddr,
29 __be32 laddr, int dif); 29 __be32 laddr, int dif, int sdif);
30 30
31int raw_abort(struct sock *sk, int err); 31int raw_abort(struct sock *sk, int err);
32void raw_icmp_error(struct sk_buff *, int, u32); 32void raw_icmp_error(struct sk_buff *, int, u32);
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index cbe4e9de1894..4addc5c988e0 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -6,7 +6,7 @@
6extern struct raw_hashinfo raw_v6_hashinfo; 6extern struct raw_hashinfo raw_v6_hashinfo;
7struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, 7struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
8 unsigned short num, const struct in6_addr *loc_addr, 8 unsigned short num, const struct in6_addr *loc_addr,
9 const struct in6_addr *rmt_addr, int dif); 9 const struct in6_addr *rmt_addr, int dif, int sdif);
10 10
11int raw_abort(struct sock *sk, int err); 11int raw_abort(struct sock *sk, int err);
12 12
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 5173fecde495..999f3efe572b 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -827,6 +827,16 @@ static inline int tcp_v6_iif(const struct sk_buff *skb)
827 827
828 return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif; 828 return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
829} 829}
830
831/* TCP_SKB_CB reference means this can not be used from early demux */
832static inline int tcp_v6_sdif(const struct sk_buff *skb)
833{
834#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
835 if (skb && ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags))
836 return TCP_SKB_CB(skb)->header.h6.iif;
837#endif
838 return 0;
839}
830#endif 840#endif
831 841
832/* TCP_SKB_CB reference means this can not be used from early demux */ 842/* TCP_SKB_CB reference means this can not be used from early demux */
@@ -840,6 +850,16 @@ static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb)
840 return false; 850 return false;
841} 851}
842 852
853/* TCP_SKB_CB reference means this can not be used from early demux */
854static inline int tcp_v4_sdif(struct sk_buff *skb)
855{
856#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
857 if (skb && ipv4_l3mdev_skb(TCP_SKB_CB(skb)->header.h4.flags))
858 return TCP_SKB_CB(skb)->header.h4.iif;
859#endif
860 return 0;
861}
862
843/* Due to TSO, an SKB can be composed of multiple actual 863/* Due to TSO, an SKB can be composed of multiple actual
844 * packets. To keep these tracked properly, we use this. 864 * packets. To keep these tracked properly, we use this.
845 */ 865 */
diff --git a/include/net/udp.h b/include/net/udp.h
index cc8036987dcb..20dcdca4e85c 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -287,7 +287,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
287struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, 287struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
288 __be32 daddr, __be16 dport, int dif); 288 __be32 daddr, __be16 dport, int dif);
289struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, 289struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
290 __be32 daddr, __be16 dport, int dif, 290 __be32 daddr, __be16 dport, int dif, int sdif,
291 struct udp_table *tbl, struct sk_buff *skb); 291 struct udp_table *tbl, struct sk_buff *skb);
292struct sock *udp4_lib_lookup_skb(struct sk_buff *skb, 292struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
293 __be16 sport, __be16 dport); 293 __be16 sport, __be16 dport);
@@ -298,7 +298,7 @@ struct sock *udp6_lib_lookup(struct net *net,
298struct sock *__udp6_lib_lookup(struct net *net, 298struct sock *__udp6_lib_lookup(struct net *net,
299 const struct in6_addr *saddr, __be16 sport, 299 const struct in6_addr *saddr, __be16 sport,
300 const struct in6_addr *daddr, __be16 dport, 300 const struct in6_addr *daddr, __be16 dport,
301 int dif, struct udp_table *tbl, 301 int dif, int sdif, struct udp_table *tbl,
302 struct sk_buff *skb); 302 struct sk_buff *skb);
303struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, 303struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
304 __be16 sport, __be16 dport); 304 __be16 sport, __be16 dport);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 1b202f16531f..001c08696334 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -256,7 +256,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
256 sk = __inet_lookup_established(net, &dccp_hashinfo, 256 sk = __inet_lookup_established(net, &dccp_hashinfo,
257 iph->daddr, dh->dccph_dport, 257 iph->daddr, dh->dccph_dport,
258 iph->saddr, ntohs(dh->dccph_sport), 258 iph->saddr, ntohs(dh->dccph_sport),
259 inet_iif(skb)); 259 inet_iif(skb), 0);
260 if (!sk) { 260 if (!sk) {
261 __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); 261 __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
262 return; 262 return;
@@ -804,7 +804,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
804 804
805lookup: 805lookup:
806 sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh), 806 sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
807 dh->dccph_sport, dh->dccph_dport, &refcounted); 807 dh->dccph_sport, dh->dccph_dport, 0, &refcounted);
808 if (!sk) { 808 if (!sk) {
809 dccp_pr_debug("failed to look up flow ID in table and " 809 dccp_pr_debug("failed to look up flow ID in table and "
810 "get corresponding socket\n"); 810 "get corresponding socket\n");
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 1b58eac8aad3..47a7b59b355e 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -89,7 +89,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
89 sk = __inet6_lookup_established(net, &dccp_hashinfo, 89 sk = __inet6_lookup_established(net, &dccp_hashinfo,
90 &hdr->daddr, dh->dccph_dport, 90 &hdr->daddr, dh->dccph_dport,
91 &hdr->saddr, ntohs(dh->dccph_sport), 91 &hdr->saddr, ntohs(dh->dccph_sport),
92 inet6_iif(skb)); 92 inet6_iif(skb), 0);
93 93
94 if (!sk) { 94 if (!sk) {
95 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), 95 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
@@ -687,7 +687,7 @@ static int dccp_v6_rcv(struct sk_buff *skb)
687lookup: 687lookup:
688 sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh), 688 sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
689 dh->dccph_sport, dh->dccph_dport, 689 dh->dccph_sport, dh->dccph_dport,
690 inet6_iif(skb), &refcounted); 690 inet6_iif(skb), 0, &refcounted);
691 if (!sk) { 691 if (!sk) {
692 dccp_pr_debug("failed to look up flow ID in table and " 692 dccp_pr_debug("failed to look up flow ID in table and "
693 "get corresponding socket\n"); 693 "get corresponding socket\n");
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 28f14afd0dd3..5bc8570c2ec3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2549,7 +2549,8 @@ done:
2549/* 2549/*
2550 * check if a multicast source filter allows delivery for a given <src,dst,intf> 2550 * check if a multicast source filter allows delivery for a given <src,dst,intf>
2551 */ 2551 */
2552int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif) 2552int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr,
2553 int dif, int sdif)
2553{ 2554{
2554 struct inet_sock *inet = inet_sk(sk); 2555 struct inet_sock *inet = inet_sk(sk);
2555 struct ip_mc_socklist *pmc; 2556 struct ip_mc_socklist *pmc;
@@ -2564,7 +2565,8 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
2564 rcu_read_lock(); 2565 rcu_read_lock();
2565 for_each_pmc_rcu(inet, pmc) { 2566 for_each_pmc_rcu(inet, pmc) {
2566 if (pmc->multi.imr_multiaddr.s_addr == loc_addr && 2567 if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
2567 pmc->multi.imr_ifindex == dif) 2568 (pmc->multi.imr_ifindex == dif ||
2569 (sdif && pmc->multi.imr_ifindex == sdif)))
2568 break; 2570 break;
2569 } 2571 }
2570 ret = inet->mc_all; 2572 ret = inet->mc_all;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 2e3389d614d1..597bb4cfe805 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -170,7 +170,7 @@ EXPORT_SYMBOL_GPL(__inet_inherit_port);
170 170
171static inline int compute_score(struct sock *sk, struct net *net, 171static inline int compute_score(struct sock *sk, struct net *net,
172 const unsigned short hnum, const __be32 daddr, 172 const unsigned short hnum, const __be32 daddr,
173 const int dif, bool exact_dif) 173 const int dif, const int sdif, bool exact_dif)
174{ 174{
175 int score = -1; 175 int score = -1;
176 struct inet_sock *inet = inet_sk(sk); 176 struct inet_sock *inet = inet_sk(sk);
@@ -185,9 +185,13 @@ static inline int compute_score(struct sock *sk, struct net *net,
185 score += 4; 185 score += 4;
186 } 186 }
187 if (sk->sk_bound_dev_if || exact_dif) { 187 if (sk->sk_bound_dev_if || exact_dif) {
188 if (sk->sk_bound_dev_if != dif) 188 bool dev_match = (sk->sk_bound_dev_if == dif ||
189 sk->sk_bound_dev_if == sdif);
190
191 if (exact_dif && !dev_match)
189 return -1; 192 return -1;
190 score += 4; 193 if (sk->sk_bound_dev_if && dev_match)
194 score += 4;
191 } 195 }
192 if (sk->sk_incoming_cpu == raw_smp_processor_id()) 196 if (sk->sk_incoming_cpu == raw_smp_processor_id())
193 score++; 197 score++;
@@ -208,7 +212,7 @@ struct sock *__inet_lookup_listener(struct net *net,
208 struct sk_buff *skb, int doff, 212 struct sk_buff *skb, int doff,
209 const __be32 saddr, __be16 sport, 213 const __be32 saddr, __be16 sport,
210 const __be32 daddr, const unsigned short hnum, 214 const __be32 daddr, const unsigned short hnum,
211 const int dif) 215 const int dif, const int sdif)
212{ 216{
213 unsigned int hash = inet_lhashfn(net, hnum); 217 unsigned int hash = inet_lhashfn(net, hnum);
214 struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; 218 struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
@@ -218,7 +222,8 @@ struct sock *__inet_lookup_listener(struct net *net,
218 u32 phash = 0; 222 u32 phash = 0;
219 223
220 sk_for_each_rcu(sk, &ilb->head) { 224 sk_for_each_rcu(sk, &ilb->head) {
221 score = compute_score(sk, net, hnum, daddr, dif, exact_dif); 225 score = compute_score(sk, net, hnum, daddr,
226 dif, sdif, exact_dif);
222 if (score > hiscore) { 227 if (score > hiscore) {
223 reuseport = sk->sk_reuseport; 228 reuseport = sk->sk_reuseport;
224 if (reuseport) { 229 if (reuseport) {
@@ -268,7 +273,7 @@ struct sock *__inet_lookup_established(struct net *net,
268 struct inet_hashinfo *hashinfo, 273 struct inet_hashinfo *hashinfo,
269 const __be32 saddr, const __be16 sport, 274 const __be32 saddr, const __be16 sport,
270 const __be32 daddr, const u16 hnum, 275 const __be32 daddr, const u16 hnum,
271 const int dif) 276 const int dif, const int sdif)
272{ 277{
273 INET_ADDR_COOKIE(acookie, saddr, daddr); 278 INET_ADDR_COOKIE(acookie, saddr, daddr);
274 const __portpair ports = INET_COMBINED_PORTS(sport, hnum); 279 const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
@@ -286,11 +291,12 @@ begin:
286 if (sk->sk_hash != hash) 291 if (sk->sk_hash != hash)
287 continue; 292 continue;
288 if (likely(INET_MATCH(sk, net, acookie, 293 if (likely(INET_MATCH(sk, net, acookie,
289 saddr, daddr, ports, dif))) { 294 saddr, daddr, ports, dif, sdif))) {
290 if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) 295 if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
291 goto out; 296 goto out;
292 if (unlikely(!INET_MATCH(sk, net, acookie, 297 if (unlikely(!INET_MATCH(sk, net, acookie,
293 saddr, daddr, ports, dif))) { 298 saddr, daddr, ports,
299 dif, sdif))) {
294 sock_gen_put(sk); 300 sock_gen_put(sk);
295 goto begin; 301 goto begin;
296 } 302 }
@@ -321,9 +327,10 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
321 __be32 daddr = inet->inet_rcv_saddr; 327 __be32 daddr = inet->inet_rcv_saddr;
322 __be32 saddr = inet->inet_daddr; 328 __be32 saddr = inet->inet_daddr;
323 int dif = sk->sk_bound_dev_if; 329 int dif = sk->sk_bound_dev_if;
330 struct net *net = sock_net(sk);
331 int sdif = l3mdev_master_ifindex_by_index(net, dif);
324 INET_ADDR_COOKIE(acookie, saddr, daddr); 332 INET_ADDR_COOKIE(acookie, saddr, daddr);
325 const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport); 333 const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport);
326 struct net *net = sock_net(sk);
327 unsigned int hash = inet_ehashfn(net, daddr, lport, 334 unsigned int hash = inet_ehashfn(net, daddr, lport,
328 saddr, inet->inet_dport); 335 saddr, inet->inet_dport);
329 struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); 336 struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
@@ -339,7 +346,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
339 continue; 346 continue;
340 347
341 if (likely(INET_MATCH(sk2, net, acookie, 348 if (likely(INET_MATCH(sk2, net, acookie,
342 saddr, daddr, ports, dif))) { 349 saddr, daddr, ports, dif, sdif))) {
343 if (sk2->sk_state == TCP_TIME_WAIT) { 350 if (sk2->sk_state == TCP_TIME_WAIT) {
344 tw = inet_twsk(sk2); 351 tw = inet_twsk(sk2);
345 if (twsk_unique(sk, sk2, twp)) 352 if (twsk_unique(sk, sk2, twp))
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index b0bb5d0a30bd..33b70bfd1122 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -122,7 +122,8 @@ void raw_unhash_sk(struct sock *sk)
122EXPORT_SYMBOL_GPL(raw_unhash_sk); 122EXPORT_SYMBOL_GPL(raw_unhash_sk);
123 123
124struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, 124struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
125 unsigned short num, __be32 raddr, __be32 laddr, int dif) 125 unsigned short num, __be32 raddr, __be32 laddr,
126 int dif, int sdif)
126{ 127{
127 sk_for_each_from(sk) { 128 sk_for_each_from(sk) {
128 struct inet_sock *inet = inet_sk(sk); 129 struct inet_sock *inet = inet_sk(sk);
@@ -130,7 +131,8 @@ struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
130 if (net_eq(sock_net(sk), net) && inet->inet_num == num && 131 if (net_eq(sock_net(sk), net) && inet->inet_num == num &&
131 !(inet->inet_daddr && inet->inet_daddr != raddr) && 132 !(inet->inet_daddr && inet->inet_daddr != raddr) &&
132 !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && 133 !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
133 !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) 134 !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
135 sk->sk_bound_dev_if != sdif))
134 goto found; /* gotcha */ 136 goto found; /* gotcha */
135 } 137 }
136 sk = NULL; 138 sk = NULL;
@@ -171,6 +173,7 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
171 */ 173 */
172static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) 174static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
173{ 175{
176 int sdif = inet_sdif(skb);
174 struct sock *sk; 177 struct sock *sk;
175 struct hlist_head *head; 178 struct hlist_head *head;
176 int delivered = 0; 179 int delivered = 0;
@@ -184,13 +187,13 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
184 net = dev_net(skb->dev); 187 net = dev_net(skb->dev);
185 sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, 188 sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
186 iph->saddr, iph->daddr, 189 iph->saddr, iph->daddr,
187 skb->dev->ifindex); 190 skb->dev->ifindex, sdif);
188 191
189 while (sk) { 192 while (sk) {
190 delivered = 1; 193 delivered = 1;
191 if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) && 194 if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) &&
192 ip_mc_sf_allow(sk, iph->daddr, iph->saddr, 195 ip_mc_sf_allow(sk, iph->daddr, iph->saddr,
193 skb->dev->ifindex)) { 196 skb->dev->ifindex, sdif)) {
194 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 197 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
195 198
196 /* Not releasing hash table! */ 199 /* Not releasing hash table! */
@@ -199,7 +202,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
199 } 202 }
200 sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, 203 sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
201 iph->saddr, iph->daddr, 204 iph->saddr, iph->daddr,
202 skb->dev->ifindex); 205 skb->dev->ifindex, sdif);
203 } 206 }
204out: 207out:
205 read_unlock(&raw_v4_hashinfo.lock); 208 read_unlock(&raw_v4_hashinfo.lock);
@@ -297,12 +300,15 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
297 read_lock(&raw_v4_hashinfo.lock); 300 read_lock(&raw_v4_hashinfo.lock);
298 raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); 301 raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]);
299 if (raw_sk) { 302 if (raw_sk) {
303 int dif = skb->dev->ifindex;
304 int sdif = inet_sdif(skb);
305
300 iph = (const struct iphdr *)skb->data; 306 iph = (const struct iphdr *)skb->data;
301 net = dev_net(skb->dev); 307 net = dev_net(skb->dev);
302 308
303 while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, 309 while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol,
304 iph->daddr, iph->saddr, 310 iph->daddr, iph->saddr,
305 skb->dev->ifindex)) != NULL) { 311 dif, sdif)) != NULL) {
306 raw_err(raw_sk, skb, info); 312 raw_err(raw_sk, skb, info);
307 raw_sk = sk_next(raw_sk); 313 raw_sk = sk_next(raw_sk);
308 iph = (const struct iphdr *)skb->data; 314 iph = (const struct iphdr *)skb->data;
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
index e1a51ca68d23..c200065ef9a5 100644
--- a/net/ipv4/raw_diag.c
+++ b/net/ipv4/raw_diag.c
@@ -46,13 +46,13 @@ static struct sock *raw_lookup(struct net *net, struct sock *from,
46 sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol, 46 sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol,
47 r->id.idiag_dst[0], 47 r->id.idiag_dst[0],
48 r->id.idiag_src[0], 48 r->id.idiag_src[0],
49 r->id.idiag_if); 49 r->id.idiag_if, 0);
50#if IS_ENABLED(CONFIG_IPV6) 50#if IS_ENABLED(CONFIG_IPV6)
51 else 51 else
52 sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol, 52 sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol,
53 (const struct in6_addr *)r->id.idiag_src, 53 (const struct in6_addr *)r->id.idiag_src,
54 (const struct in6_addr *)r->id.idiag_dst, 54 (const struct in6_addr *)r->id.idiag_dst,
55 r->id.idiag_if); 55 r->id.idiag_if, 0);
56#endif 56#endif
57 return sk; 57 return sk;
58} 58}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5f708c85110e..c8784ab37852 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -383,7 +383,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
383 383
384 sk = __inet_lookup_established(net, &tcp_hashinfo, iph->daddr, 384 sk = __inet_lookup_established(net, &tcp_hashinfo, iph->daddr,
385 th->dest, iph->saddr, ntohs(th->source), 385 th->dest, iph->saddr, ntohs(th->source),
386 inet_iif(icmp_skb)); 386 inet_iif(icmp_skb), 0);
387 if (!sk) { 387 if (!sk) {
388 __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); 388 __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
389 return; 389 return;
@@ -659,7 +659,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
659 sk1 = __inet_lookup_listener(net, &tcp_hashinfo, NULL, 0, 659 sk1 = __inet_lookup_listener(net, &tcp_hashinfo, NULL, 0,
660 ip_hdr(skb)->saddr, 660 ip_hdr(skb)->saddr,
661 th->source, ip_hdr(skb)->daddr, 661 th->source, ip_hdr(skb)->daddr,
662 ntohs(th->source), inet_iif(skb)); 662 ntohs(th->source), inet_iif(skb),
663 tcp_v4_sdif(skb));
663 /* don't send rst if it can't find key */ 664 /* don't send rst if it can't find key */
664 if (!sk1) 665 if (!sk1)
665 goto out; 666 goto out;
@@ -1523,7 +1524,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
1523 sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo, 1524 sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
1524 iph->saddr, th->source, 1525 iph->saddr, th->source,
1525 iph->daddr, ntohs(th->dest), 1526 iph->daddr, ntohs(th->dest),
1526 skb->skb_iif); 1527 skb->skb_iif, inet_sdif(skb));
1527 if (sk) { 1528 if (sk) {
1528 skb->sk = sk; 1529 skb->sk = sk;
1529 skb->destructor = sock_edemux; 1530 skb->destructor = sock_edemux;
@@ -1588,6 +1589,7 @@ EXPORT_SYMBOL(tcp_filter);
1588int tcp_v4_rcv(struct sk_buff *skb) 1589int tcp_v4_rcv(struct sk_buff *skb)
1589{ 1590{
1590 struct net *net = dev_net(skb->dev); 1591 struct net *net = dev_net(skb->dev);
1592 int sdif = inet_sdif(skb);
1591 const struct iphdr *iph; 1593 const struct iphdr *iph;
1592 const struct tcphdr *th; 1594 const struct tcphdr *th;
1593 bool refcounted; 1595 bool refcounted;
@@ -1638,7 +1640,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
1638 1640
1639lookup: 1641lookup:
1640 sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source, 1642 sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source,
1641 th->dest, &refcounted); 1643 th->dest, sdif, &refcounted);
1642 if (!sk) 1644 if (!sk)
1643 goto no_tcp_socket; 1645 goto no_tcp_socket;
1644 1646
@@ -1766,7 +1768,8 @@ do_time_wait:
1766 __tcp_hdrlen(th), 1768 __tcp_hdrlen(th),
1767 iph->saddr, th->source, 1769 iph->saddr, th->source,
1768 iph->daddr, th->dest, 1770 iph->daddr, th->dest,
1769 inet_iif(skb)); 1771 inet_iif(skb),
1772 sdif);
1770 if (sk2) { 1773 if (sk2) {
1771 inet_twsk_deschedule_put(inet_twsk(sk)); 1774 inet_twsk_deschedule_put(inet_twsk(sk));
1772 sk = sk2; 1775 sk = sk2;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 38bca2c4897d..cac59d7420cd 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -380,8 +380,8 @@ int udp_v4_get_port(struct sock *sk, unsigned short snum)
380 380
381static int compute_score(struct sock *sk, struct net *net, 381static int compute_score(struct sock *sk, struct net *net,
382 __be32 saddr, __be16 sport, 382 __be32 saddr, __be16 sport,
383 __be32 daddr, unsigned short hnum, int dif, 383 __be32 daddr, unsigned short hnum,
384 bool exact_dif) 384 int dif, int sdif, bool exact_dif)
385{ 385{
386 int score; 386 int score;
387 struct inet_sock *inet; 387 struct inet_sock *inet;
@@ -413,10 +413,15 @@ static int compute_score(struct sock *sk, struct net *net,
413 } 413 }
414 414
415 if (sk->sk_bound_dev_if || exact_dif) { 415 if (sk->sk_bound_dev_if || exact_dif) {
416 if (sk->sk_bound_dev_if != dif) 416 bool dev_match = (sk->sk_bound_dev_if == dif ||
417 sk->sk_bound_dev_if == sdif);
418
419 if (exact_dif && !dev_match)
417 return -1; 420 return -1;
418 score += 4; 421 if (sk->sk_bound_dev_if && dev_match)
422 score += 4;
419 } 423 }
424
420 if (sk->sk_incoming_cpu == raw_smp_processor_id()) 425 if (sk->sk_incoming_cpu == raw_smp_processor_id())
421 score++; 426 score++;
422 return score; 427 return score;
@@ -436,10 +441,11 @@ static u32 udp_ehashfn(const struct net *net, const __be32 laddr,
436 441
437/* called with rcu_read_lock() */ 442/* called with rcu_read_lock() */
438static struct sock *udp4_lib_lookup2(struct net *net, 443static struct sock *udp4_lib_lookup2(struct net *net,
439 __be32 saddr, __be16 sport, 444 __be32 saddr, __be16 sport,
440 __be32 daddr, unsigned int hnum, int dif, bool exact_dif, 445 __be32 daddr, unsigned int hnum,
441 struct udp_hslot *hslot2, 446 int dif, int sdif, bool exact_dif,
442 struct sk_buff *skb) 447 struct udp_hslot *hslot2,
448 struct sk_buff *skb)
443{ 449{
444 struct sock *sk, *result; 450 struct sock *sk, *result;
445 int score, badness, matches = 0, reuseport = 0; 451 int score, badness, matches = 0, reuseport = 0;
@@ -449,7 +455,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
449 badness = 0; 455 badness = 0;
450 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { 456 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
451 score = compute_score(sk, net, saddr, sport, 457 score = compute_score(sk, net, saddr, sport,
452 daddr, hnum, dif, exact_dif); 458 daddr, hnum, dif, sdif, exact_dif);
453 if (score > badness) { 459 if (score > badness) {
454 reuseport = sk->sk_reuseport; 460 reuseport = sk->sk_reuseport;
455 if (reuseport) { 461 if (reuseport) {
@@ -477,8 +483,8 @@ static struct sock *udp4_lib_lookup2(struct net *net,
477 * harder than this. -DaveM 483 * harder than this. -DaveM
478 */ 484 */
479struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, 485struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
480 __be16 sport, __be32 daddr, __be16 dport, 486 __be16 sport, __be32 daddr, __be16 dport, int dif,
481 int dif, struct udp_table *udptable, struct sk_buff *skb) 487 int sdif, struct udp_table *udptable, struct sk_buff *skb)
482{ 488{
483 struct sock *sk, *result; 489 struct sock *sk, *result;
484 unsigned short hnum = ntohs(dport); 490 unsigned short hnum = ntohs(dport);
@@ -496,7 +502,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
496 goto begin; 502 goto begin;
497 503
498 result = udp4_lib_lookup2(net, saddr, sport, 504 result = udp4_lib_lookup2(net, saddr, sport,
499 daddr, hnum, dif, 505 daddr, hnum, dif, sdif,
500 exact_dif, hslot2, skb); 506 exact_dif, hslot2, skb);
501 if (!result) { 507 if (!result) {
502 unsigned int old_slot2 = slot2; 508 unsigned int old_slot2 = slot2;
@@ -511,7 +517,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
511 goto begin; 517 goto begin;
512 518
513 result = udp4_lib_lookup2(net, saddr, sport, 519 result = udp4_lib_lookup2(net, saddr, sport,
514 daddr, hnum, dif, 520 daddr, hnum, dif, sdif,
515 exact_dif, hslot2, skb); 521 exact_dif, hslot2, skb);
516 } 522 }
517 return result; 523 return result;
@@ -521,7 +527,7 @@ begin:
521 badness = 0; 527 badness = 0;
522 sk_for_each_rcu(sk, &hslot->head) { 528 sk_for_each_rcu(sk, &hslot->head) {
523 score = compute_score(sk, net, saddr, sport, 529 score = compute_score(sk, net, saddr, sport,
524 daddr, hnum, dif, exact_dif); 530 daddr, hnum, dif, sdif, exact_dif);
525 if (score > badness) { 531 if (score > badness) {
526 reuseport = sk->sk_reuseport; 532 reuseport = sk->sk_reuseport;
527 if (reuseport) { 533 if (reuseport) {
@@ -554,7 +560,7 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
554 560
555 return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport, 561 return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport,
556 iph->daddr, dport, inet_iif(skb), 562 iph->daddr, dport, inet_iif(skb),
557 udptable, skb); 563 inet_sdif(skb), udptable, skb);
558} 564}
559 565
560struct sock *udp4_lib_lookup_skb(struct sk_buff *skb, 566struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
@@ -576,7 +582,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
576 struct sock *sk; 582 struct sock *sk;
577 583
578 sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport, 584 sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport,
579 dif, &udp_table, NULL); 585 dif, 0, &udp_table, NULL);
580 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 586 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
581 sk = NULL; 587 sk = NULL;
582 return sk; 588 return sk;
@@ -587,7 +593,7 @@ EXPORT_SYMBOL_GPL(udp4_lib_lookup);
587static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk, 593static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
588 __be16 loc_port, __be32 loc_addr, 594 __be16 loc_port, __be32 loc_addr,
589 __be16 rmt_port, __be32 rmt_addr, 595 __be16 rmt_port, __be32 rmt_addr,
590 int dif, unsigned short hnum) 596 int dif, int sdif, unsigned short hnum)
591{ 597{
592 struct inet_sock *inet = inet_sk(sk); 598 struct inet_sock *inet = inet_sk(sk);
593 599
@@ -597,9 +603,10 @@ static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
597 (inet->inet_dport != rmt_port && inet->inet_dport) || 603 (inet->inet_dport != rmt_port && inet->inet_dport) ||
598 (inet->inet_rcv_saddr && inet->inet_rcv_saddr != loc_addr) || 604 (inet->inet_rcv_saddr && inet->inet_rcv_saddr != loc_addr) ||
599 ipv6_only_sock(sk) || 605 ipv6_only_sock(sk) ||
600 (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) 606 (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
607 sk->sk_bound_dev_if != sdif))
601 return false; 608 return false;
602 if (!ip_mc_sf_allow(sk, loc_addr, rmt_addr, dif)) 609 if (!ip_mc_sf_allow(sk, loc_addr, rmt_addr, dif, sdif))
603 return false; 610 return false;
604 return true; 611 return true;
605} 612}
@@ -628,8 +635,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
628 struct net *net = dev_net(skb->dev); 635 struct net *net = dev_net(skb->dev);
629 636
630 sk = __udp4_lib_lookup(net, iph->daddr, uh->dest, 637 sk = __udp4_lib_lookup(net, iph->daddr, uh->dest,
631 iph->saddr, uh->source, skb->dev->ifindex, udptable, 638 iph->saddr, uh->source, skb->dev->ifindex, 0,
632 NULL); 639 udptable, NULL);
633 if (!sk) { 640 if (!sk) {
634 __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); 641 __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
635 return; /* No socket for error */ 642 return; /* No socket for error */
@@ -1953,6 +1960,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
1953 unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); 1960 unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
1954 unsigned int offset = offsetof(typeof(*sk), sk_node); 1961 unsigned int offset = offsetof(typeof(*sk), sk_node);
1955 int dif = skb->dev->ifindex; 1962 int dif = skb->dev->ifindex;
1963 int sdif = inet_sdif(skb);
1956 struct hlist_node *node; 1964 struct hlist_node *node;
1957 struct sk_buff *nskb; 1965 struct sk_buff *nskb;
1958 1966
@@ -1967,7 +1975,7 @@ start_lookup:
1967 1975
1968 sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) { 1976 sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) {
1969 if (!__udp_is_mcast_sock(net, sk, uh->dest, daddr, 1977 if (!__udp_is_mcast_sock(net, sk, uh->dest, daddr,
1970 uh->source, saddr, dif, hnum)) 1978 uh->source, saddr, dif, sdif, hnum))
1971 continue; 1979 continue;
1972 1980
1973 if (!first) { 1981 if (!first) {
@@ -2157,7 +2165,7 @@ drop:
2157static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net, 2165static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net,
2158 __be16 loc_port, __be32 loc_addr, 2166 __be16 loc_port, __be32 loc_addr,
2159 __be16 rmt_port, __be32 rmt_addr, 2167 __be16 rmt_port, __be32 rmt_addr,
2160 int dif) 2168 int dif, int sdif)
2161{ 2169{
2162 struct sock *sk, *result; 2170 struct sock *sk, *result;
2163 unsigned short hnum = ntohs(loc_port); 2171 unsigned short hnum = ntohs(loc_port);
@@ -2171,7 +2179,7 @@ static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net,
2171 result = NULL; 2179 result = NULL;
2172 sk_for_each_rcu(sk, &hslot->head) { 2180 sk_for_each_rcu(sk, &hslot->head) {
2173 if (__udp_is_mcast_sock(net, sk, loc_port, loc_addr, 2181 if (__udp_is_mcast_sock(net, sk, loc_port, loc_addr,
2174 rmt_port, rmt_addr, dif, hnum)) { 2182 rmt_port, rmt_addr, dif, sdif, hnum)) {
2175 if (result) 2183 if (result)
2176 return NULL; 2184 return NULL;
2177 result = sk; 2185 result = sk;
@@ -2188,7 +2196,7 @@ static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net,
2188static struct sock *__udp4_lib_demux_lookup(struct net *net, 2196static struct sock *__udp4_lib_demux_lookup(struct net *net,
2189 __be16 loc_port, __be32 loc_addr, 2197 __be16 loc_port, __be32 loc_addr,
2190 __be16 rmt_port, __be32 rmt_addr, 2198 __be16 rmt_port, __be32 rmt_addr,
2191 int dif) 2199 int dif, int sdif)
2192{ 2200{
2193 unsigned short hnum = ntohs(loc_port); 2201 unsigned short hnum = ntohs(loc_port);
2194 unsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum); 2202 unsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum);
@@ -2200,7 +2208,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
2200 2208
2201 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { 2209 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
2202 if (INET_MATCH(sk, net, acookie, rmt_addr, 2210 if (INET_MATCH(sk, net, acookie, rmt_addr,
2203 loc_addr, ports, dif)) 2211 loc_addr, ports, dif, sdif))
2204 return sk; 2212 return sk;
2205 /* Only check first socket in chain */ 2213 /* Only check first socket in chain */
2206 break; 2214 break;
@@ -2216,6 +2224,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
2216 struct sock *sk = NULL; 2224 struct sock *sk = NULL;
2217 struct dst_entry *dst; 2225 struct dst_entry *dst;
2218 int dif = skb->dev->ifindex; 2226 int dif = skb->dev->ifindex;
2227 int sdif = inet_sdif(skb);
2219 int ours; 2228 int ours;
2220 2229
2221 /* validate the packet */ 2230 /* validate the packet */
@@ -2241,10 +2250,11 @@ void udp_v4_early_demux(struct sk_buff *skb)
2241 } 2250 }
2242 2251
2243 sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, 2252 sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
2244 uh->source, iph->saddr, dif); 2253 uh->source, iph->saddr,
2254 dif, sdif);
2245 } else if (skb->pkt_type == PACKET_HOST) { 2255 } else if (skb->pkt_type == PACKET_HOST) {
2246 sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, 2256 sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,
2247 uh->source, iph->saddr, dif); 2257 uh->source, iph->saddr, dif, sdif);
2248 } 2258 }
2249 2259
2250 if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt)) 2260 if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 4515836d2a3a..d0390d844ac8 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -45,7 +45,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
45 sk = __udp4_lib_lookup(net, 45 sk = __udp4_lib_lookup(net,
46 req->id.idiag_src[0], req->id.idiag_sport, 46 req->id.idiag_src[0], req->id.idiag_sport,
47 req->id.idiag_dst[0], req->id.idiag_dport, 47 req->id.idiag_dst[0], req->id.idiag_dport,
48 req->id.idiag_if, tbl, NULL); 48 req->id.idiag_if, 0, tbl, NULL);
49#if IS_ENABLED(CONFIG_IPV6) 49#if IS_ENABLED(CONFIG_IPV6)
50 else if (req->sdiag_family == AF_INET6) 50 else if (req->sdiag_family == AF_INET6)
51 sk = __udp6_lib_lookup(net, 51 sk = __udp6_lib_lookup(net,
@@ -53,7 +53,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
53 req->id.idiag_sport, 53 req->id.idiag_sport,
54 (struct in6_addr *)req->id.idiag_dst, 54 (struct in6_addr *)req->id.idiag_dst,
55 req->id.idiag_dport, 55 req->id.idiag_dport,
56 req->id.idiag_if, tbl, NULL); 56 req->id.idiag_if, 0, tbl, NULL);
57#endif 57#endif
58 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 58 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
59 sk = NULL; 59 sk = NULL;
@@ -182,7 +182,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
182 sk = __udp4_lib_lookup(net, 182 sk = __udp4_lib_lookup(net,
183 req->id.idiag_dst[0], req->id.idiag_dport, 183 req->id.idiag_dst[0], req->id.idiag_dport,
184 req->id.idiag_src[0], req->id.idiag_sport, 184 req->id.idiag_src[0], req->id.idiag_sport,
185 req->id.idiag_if, tbl, NULL); 185 req->id.idiag_if, 0, tbl, NULL);
186#if IS_ENABLED(CONFIG_IPV6) 186#if IS_ENABLED(CONFIG_IPV6)
187 else if (req->sdiag_family == AF_INET6) { 187 else if (req->sdiag_family == AF_INET6) {
188 if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) && 188 if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) &&
@@ -190,7 +190,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
190 sk = __udp4_lib_lookup(net, 190 sk = __udp4_lib_lookup(net,
191 req->id.idiag_dst[3], req->id.idiag_dport, 191 req->id.idiag_dst[3], req->id.idiag_dport,
192 req->id.idiag_src[3], req->id.idiag_sport, 192 req->id.idiag_src[3], req->id.idiag_sport,
193 req->id.idiag_if, tbl, NULL); 193 req->id.idiag_if, 0, tbl, NULL);
194 194
195 else 195 else
196 sk = __udp6_lib_lookup(net, 196 sk = __udp6_lib_lookup(net,
@@ -198,7 +198,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
198 req->id.idiag_dport, 198 req->id.idiag_dport,
199 (struct in6_addr *)req->id.idiag_src, 199 (struct in6_addr *)req->id.idiag_src,
200 req->id.idiag_sport, 200 req->id.idiag_sport,
201 req->id.idiag_if, tbl, NULL); 201 req->id.idiag_if, 0, tbl, NULL);
202 } 202 }
203#endif 203#endif
204 else { 204 else {
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index b13b8f93079d..b01858f5deb1 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -56,7 +56,7 @@ struct sock *__inet6_lookup_established(struct net *net,
56 const __be16 sport, 56 const __be16 sport,
57 const struct in6_addr *daddr, 57 const struct in6_addr *daddr,
58 const u16 hnum, 58 const u16 hnum,
59 const int dif) 59 const int dif, const int sdif)
60{ 60{
61 struct sock *sk; 61 struct sock *sk;
62 const struct hlist_nulls_node *node; 62 const struct hlist_nulls_node *node;
@@ -73,12 +73,12 @@ begin:
73 sk_nulls_for_each_rcu(sk, node, &head->chain) { 73 sk_nulls_for_each_rcu(sk, node, &head->chain) {
74 if (sk->sk_hash != hash) 74 if (sk->sk_hash != hash)
75 continue; 75 continue;
76 if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif)) 76 if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif, sdif))
77 continue; 77 continue;
78 if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) 78 if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
79 goto out; 79 goto out;
80 80
81 if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif))) { 81 if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif, sdif))) {
82 sock_gen_put(sk); 82 sock_gen_put(sk);
83 goto begin; 83 goto begin;
84 } 84 }
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__inet6_lookup_established);
96static inline int compute_score(struct sock *sk, struct net *net, 96static inline int compute_score(struct sock *sk, struct net *net,
97 const unsigned short hnum, 97 const unsigned short hnum,
98 const struct in6_addr *daddr, 98 const struct in6_addr *daddr,
99 const int dif, bool exact_dif) 99 const int dif, const int sdif, bool exact_dif)
100{ 100{
101 int score = -1; 101 int score = -1;
102 102
@@ -110,9 +110,13 @@ static inline int compute_score(struct sock *sk, struct net *net,
110 score++; 110 score++;
111 } 111 }
112 if (sk->sk_bound_dev_if || exact_dif) { 112 if (sk->sk_bound_dev_if || exact_dif) {
113 if (sk->sk_bound_dev_if != dif) 113 bool dev_match = (sk->sk_bound_dev_if == dif ||
114 sk->sk_bound_dev_if == sdif);
115
116 if (exact_dif && !dev_match)
114 return -1; 117 return -1;
115 score++; 118 if (sk->sk_bound_dev_if && dev_match)
119 score++;
116 } 120 }
117 if (sk->sk_incoming_cpu == raw_smp_processor_id()) 121 if (sk->sk_incoming_cpu == raw_smp_processor_id())
118 score++; 122 score++;
@@ -126,7 +130,7 @@ struct sock *inet6_lookup_listener(struct net *net,
126 struct sk_buff *skb, int doff, 130 struct sk_buff *skb, int doff,
127 const struct in6_addr *saddr, 131 const struct in6_addr *saddr,
128 const __be16 sport, const struct in6_addr *daddr, 132 const __be16 sport, const struct in6_addr *daddr,
129 const unsigned short hnum, const int dif) 133 const unsigned short hnum, const int dif, const int sdif)
130{ 134{
131 unsigned int hash = inet_lhashfn(net, hnum); 135 unsigned int hash = inet_lhashfn(net, hnum);
132 struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash]; 136 struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
@@ -136,7 +140,7 @@ struct sock *inet6_lookup_listener(struct net *net,
136 u32 phash = 0; 140 u32 phash = 0;
137 141
138 sk_for_each(sk, &ilb->head) { 142 sk_for_each(sk, &ilb->head) {
139 score = compute_score(sk, net, hnum, daddr, dif, exact_dif); 143 score = compute_score(sk, net, hnum, daddr, dif, sdif, exact_dif);
140 if (score > hiscore) { 144 if (score > hiscore) {
141 reuseport = sk->sk_reuseport; 145 reuseport = sk->sk_reuseport;
142 if (reuseport) { 146 if (reuseport) {
@@ -171,7 +175,7 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
171 bool refcounted; 175 bool refcounted;
172 176
173 sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, 177 sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
174 ntohs(dport), dif, &refcounted); 178 ntohs(dport), dif, 0, &refcounted);
175 if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt)) 179 if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
176 sk = NULL; 180 sk = NULL;
177 return sk; 181 return sk;
@@ -187,8 +191,9 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
187 const struct in6_addr *daddr = &sk->sk_v6_rcv_saddr; 191 const struct in6_addr *daddr = &sk->sk_v6_rcv_saddr;
188 const struct in6_addr *saddr = &sk->sk_v6_daddr; 192 const struct in6_addr *saddr = &sk->sk_v6_daddr;
189 const int dif = sk->sk_bound_dev_if; 193 const int dif = sk->sk_bound_dev_if;
190 const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport);
191 struct net *net = sock_net(sk); 194 struct net *net = sock_net(sk);
195 const int sdif = l3mdev_master_ifindex_by_index(net, dif);
196 const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport);
192 const unsigned int hash = inet6_ehashfn(net, daddr, lport, saddr, 197 const unsigned int hash = inet6_ehashfn(net, daddr, lport, saddr,
193 inet->inet_dport); 198 inet->inet_dport);
194 struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); 199 struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
@@ -203,7 +208,8 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
203 if (sk2->sk_hash != hash) 208 if (sk2->sk_hash != hash)
204 continue; 209 continue;
205 210
206 if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports, dif))) { 211 if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports,
212 dif, sdif))) {
207 if (sk2->sk_state == TCP_TIME_WAIT) { 213 if (sk2->sk_state == TCP_TIME_WAIT) {
208 tw = inet_twsk(sk2); 214 tw = inet_twsk(sk2);
209 if (twsk_unique(sk, sk2, twp)) 215 if (twsk_unique(sk, sk2, twp))
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 60be012fe708..e4462b0ff801 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(raw_v6_hashinfo);
72 72
73struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, 73struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
74 unsigned short num, const struct in6_addr *loc_addr, 74 unsigned short num, const struct in6_addr *loc_addr,
75 const struct in6_addr *rmt_addr, int dif) 75 const struct in6_addr *rmt_addr, int dif, int sdif)
76{ 76{
77 bool is_multicast = ipv6_addr_is_multicast(loc_addr); 77 bool is_multicast = ipv6_addr_is_multicast(loc_addr);
78 78
@@ -86,7 +86,9 @@ struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
86 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) 86 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
87 continue; 87 continue;
88 88
89 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) 89 if (sk->sk_bound_dev_if &&
90 sk->sk_bound_dev_if != dif &&
91 sk->sk_bound_dev_if != sdif)
90 continue; 92 continue;
91 93
92 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { 94 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
@@ -178,7 +180,8 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
178 goto out; 180 goto out;
179 181
180 net = dev_net(skb->dev); 182 net = dev_net(skb->dev);
181 sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb)); 183 sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr,
184 inet6_iif(skb), inet6_sdif(skb));
182 185
183 while (sk) { 186 while (sk) {
184 int filtered; 187 int filtered;
@@ -222,7 +225,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
222 } 225 }
223 } 226 }
224 sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, 227 sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr,
225 inet6_iif(skb)); 228 inet6_iif(skb), inet6_sdif(skb));
226 } 229 }
227out: 230out:
228 read_unlock(&raw_v6_hashinfo.lock); 231 read_unlock(&raw_v6_hashinfo.lock);
@@ -378,7 +381,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
378 net = dev_net(skb->dev); 381 net = dev_net(skb->dev);
379 382
380 while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, 383 while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
381 inet6_iif(skb)))) { 384 inet6_iif(skb), inet6_iif(skb)))) {
382 rawv6_err(sk, skb, NULL, type, code, 385 rawv6_err(sk, skb, NULL, type, code,
383 inner_offset, info); 386 inner_offset, info);
384 sk = sk_next(sk); 387 sk = sk_next(sk);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index ced5dcf37465..f776ec4ecf6d 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -350,7 +350,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
350 sk = __inet6_lookup_established(net, &tcp_hashinfo, 350 sk = __inet6_lookup_established(net, &tcp_hashinfo,
351 &hdr->daddr, th->dest, 351 &hdr->daddr, th->dest,
352 &hdr->saddr, ntohs(th->source), 352 &hdr->saddr, ntohs(th->source),
353 skb->dev->ifindex); 353 skb->dev->ifindex, inet6_sdif(skb));
354 354
355 if (!sk) { 355 if (!sk) {
356 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), 356 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
@@ -918,7 +918,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
918 &tcp_hashinfo, NULL, 0, 918 &tcp_hashinfo, NULL, 0,
919 &ipv6h->saddr, 919 &ipv6h->saddr,
920 th->source, &ipv6h->daddr, 920 th->source, &ipv6h->daddr,
921 ntohs(th->source), tcp_v6_iif(skb)); 921 ntohs(th->source), tcp_v6_iif(skb),
922 tcp_v6_sdif(skb));
922 if (!sk1) 923 if (!sk1)
923 goto out; 924 goto out;
924 925
@@ -1397,6 +1398,7 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,
1397 1398
1398static int tcp_v6_rcv(struct sk_buff *skb) 1399static int tcp_v6_rcv(struct sk_buff *skb)
1399{ 1400{
1401 int sdif = inet6_sdif(skb);
1400 const struct tcphdr *th; 1402 const struct tcphdr *th;
1401 const struct ipv6hdr *hdr; 1403 const struct ipv6hdr *hdr;
1402 bool refcounted; 1404 bool refcounted;
@@ -1430,7 +1432,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
1430 1432
1431lookup: 1433lookup:
1432 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), 1434 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
1433 th->source, th->dest, inet6_iif(skb), 1435 th->source, th->dest, inet6_iif(skb), sdif,
1434 &refcounted); 1436 &refcounted);
1435 if (!sk) 1437 if (!sk)
1436 goto no_tcp_socket; 1438 goto no_tcp_socket;
@@ -1563,7 +1565,8 @@ do_time_wait:
1563 skb, __tcp_hdrlen(th), 1565 skb, __tcp_hdrlen(th),
1564 &ipv6_hdr(skb)->saddr, th->source, 1566 &ipv6_hdr(skb)->saddr, th->source,
1565 &ipv6_hdr(skb)->daddr, 1567 &ipv6_hdr(skb)->daddr,
1566 ntohs(th->dest), tcp_v6_iif(skb)); 1568 ntohs(th->dest), tcp_v6_iif(skb),
1569 sdif);
1567 if (sk2) { 1570 if (sk2) {
1568 struct inet_timewait_sock *tw = inet_twsk(sk); 1571 struct inet_timewait_sock *tw = inet_twsk(sk);
1569 inet_twsk_deschedule_put(tw); 1572 inet_twsk_deschedule_put(tw);
@@ -1610,7 +1613,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
1610 sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo, 1613 sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
1611 &hdr->saddr, th->source, 1614 &hdr->saddr, th->source,
1612 &hdr->daddr, ntohs(th->dest), 1615 &hdr->daddr, ntohs(th->dest),
1613 inet6_iif(skb)); 1616 inet6_iif(skb), inet6_sdif(skb));
1614 if (sk) { 1617 if (sk) {
1615 skb->sk = sk; 1618 skb->sk = sk;
1616 skb->destructor = sock_edemux; 1619 skb->destructor = sock_edemux;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 578142b7ca3e..19afcaf4a22e 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -129,7 +129,7 @@ static void udp_v6_rehash(struct sock *sk)
129static int compute_score(struct sock *sk, struct net *net, 129static int compute_score(struct sock *sk, struct net *net,
130 const struct in6_addr *saddr, __be16 sport, 130 const struct in6_addr *saddr, __be16 sport,
131 const struct in6_addr *daddr, unsigned short hnum, 131 const struct in6_addr *daddr, unsigned short hnum,
132 int dif, bool exact_dif) 132 int dif, int sdif, bool exact_dif)
133{ 133{
134 int score; 134 int score;
135 struct inet_sock *inet; 135 struct inet_sock *inet;
@@ -161,9 +161,13 @@ static int compute_score(struct sock *sk, struct net *net,
161 } 161 }
162 162
163 if (sk->sk_bound_dev_if || exact_dif) { 163 if (sk->sk_bound_dev_if || exact_dif) {
164 if (sk->sk_bound_dev_if != dif) 164 bool dev_match = (sk->sk_bound_dev_if == dif ||
165 sk->sk_bound_dev_if == sdif);
166
167 if (exact_dif && !dev_match)
165 return -1; 168 return -1;
166 score++; 169 if (sk->sk_bound_dev_if && dev_match)
170 score++;
167 } 171 }
168 172
169 if (sk->sk_incoming_cpu == raw_smp_processor_id()) 173 if (sk->sk_incoming_cpu == raw_smp_processor_id())
@@ -175,9 +179,9 @@ static int compute_score(struct sock *sk, struct net *net,
175/* called with rcu_read_lock() */ 179/* called with rcu_read_lock() */
176static struct sock *udp6_lib_lookup2(struct net *net, 180static struct sock *udp6_lib_lookup2(struct net *net,
177 const struct in6_addr *saddr, __be16 sport, 181 const struct in6_addr *saddr, __be16 sport,
178 const struct in6_addr *daddr, unsigned int hnum, int dif, 182 const struct in6_addr *daddr, unsigned int hnum,
179 bool exact_dif, struct udp_hslot *hslot2, 183 int dif, int sdif, bool exact_dif,
180 struct sk_buff *skb) 184 struct udp_hslot *hslot2, struct sk_buff *skb)
181{ 185{
182 struct sock *sk, *result; 186 struct sock *sk, *result;
183 int score, badness, matches = 0, reuseport = 0; 187 int score, badness, matches = 0, reuseport = 0;
@@ -187,7 +191,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
187 badness = -1; 191 badness = -1;
188 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { 192 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
189 score = compute_score(sk, net, saddr, sport, 193 score = compute_score(sk, net, saddr, sport,
190 daddr, hnum, dif, exact_dif); 194 daddr, hnum, dif, sdif, exact_dif);
191 if (score > badness) { 195 if (score > badness) {
192 reuseport = sk->sk_reuseport; 196 reuseport = sk->sk_reuseport;
193 if (reuseport) { 197 if (reuseport) {
@@ -214,10 +218,10 @@ static struct sock *udp6_lib_lookup2(struct net *net,
214 218
215/* rcu_read_lock() must be held */ 219/* rcu_read_lock() must be held */
216struct sock *__udp6_lib_lookup(struct net *net, 220struct sock *__udp6_lib_lookup(struct net *net,
217 const struct in6_addr *saddr, __be16 sport, 221 const struct in6_addr *saddr, __be16 sport,
218 const struct in6_addr *daddr, __be16 dport, 222 const struct in6_addr *daddr, __be16 dport,
219 int dif, struct udp_table *udptable, 223 int dif, int sdif, struct udp_table *udptable,
220 struct sk_buff *skb) 224 struct sk_buff *skb)
221{ 225{
222 struct sock *sk, *result; 226 struct sock *sk, *result;
223 unsigned short hnum = ntohs(dport); 227 unsigned short hnum = ntohs(dport);
@@ -235,7 +239,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
235 goto begin; 239 goto begin;
236 240
237 result = udp6_lib_lookup2(net, saddr, sport, 241 result = udp6_lib_lookup2(net, saddr, sport,
238 daddr, hnum, dif, exact_dif, 242 daddr, hnum, dif, sdif, exact_dif,
239 hslot2, skb); 243 hslot2, skb);
240 if (!result) { 244 if (!result) {
241 unsigned int old_slot2 = slot2; 245 unsigned int old_slot2 = slot2;
@@ -250,7 +254,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
250 goto begin; 254 goto begin;
251 255
252 result = udp6_lib_lookup2(net, saddr, sport, 256 result = udp6_lib_lookup2(net, saddr, sport,
253 daddr, hnum, dif, 257 daddr, hnum, dif, sdif,
254 exact_dif, hslot2, 258 exact_dif, hslot2,
255 skb); 259 skb);
256 } 260 }
@@ -261,7 +265,7 @@ begin:
261 badness = -1; 265 badness = -1;
262 sk_for_each_rcu(sk, &hslot->head) { 266 sk_for_each_rcu(sk, &hslot->head) {
263 score = compute_score(sk, net, saddr, sport, daddr, hnum, dif, 267 score = compute_score(sk, net, saddr, sport, daddr, hnum, dif,
264 exact_dif); 268 sdif, exact_dif);
265 if (score > badness) { 269 if (score > badness) {
266 reuseport = sk->sk_reuseport; 270 reuseport = sk->sk_reuseport;
267 if (reuseport) { 271 if (reuseport) {
@@ -294,7 +298,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
294 298
295 return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport, 299 return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
296 &iph->daddr, dport, inet6_iif(skb), 300 &iph->daddr, dport, inet6_iif(skb),
297 udptable, skb); 301 inet6_sdif(skb), udptable, skb);
298} 302}
299 303
300struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, 304struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
@@ -304,7 +308,7 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
304 308
305 return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport, 309 return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
306 &iph->daddr, dport, inet6_iif(skb), 310 &iph->daddr, dport, inet6_iif(skb),
307 &udp_table, skb); 311 inet6_sdif(skb), &udp_table, skb);
308} 312}
309EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb); 313EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb);
310 314
@@ -320,7 +324,7 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
320 struct sock *sk; 324 struct sock *sk;
321 325
322 sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport, 326 sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport,
323 dif, &udp_table, NULL); 327 dif, 0, &udp_table, NULL);
324 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 328 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
325 sk = NULL; 329 sk = NULL;
326 return sk; 330 return sk;
@@ -501,7 +505,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
501 struct net *net = dev_net(skb->dev); 505 struct net *net = dev_net(skb->dev);
502 506
503 sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, 507 sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
504 inet6_iif(skb), udptable, skb); 508 inet6_iif(skb), 0, udptable, skb);
505 if (!sk) { 509 if (!sk) {
506 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), 510 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
507 ICMP6_MIB_INERRORS); 511 ICMP6_MIB_INERRORS);
@@ -893,7 +897,7 @@ discard:
893static struct sock *__udp6_lib_demux_lookup(struct net *net, 897static struct sock *__udp6_lib_demux_lookup(struct net *net,
894 __be16 loc_port, const struct in6_addr *loc_addr, 898 __be16 loc_port, const struct in6_addr *loc_addr,
895 __be16 rmt_port, const struct in6_addr *rmt_addr, 899 __be16 rmt_port, const struct in6_addr *rmt_addr,
896 int dif) 900 int dif, int sdif)
897{ 901{
898 unsigned short hnum = ntohs(loc_port); 902 unsigned short hnum = ntohs(loc_port);
899 unsigned int hash2 = udp6_portaddr_hash(net, loc_addr, hnum); 903 unsigned int hash2 = udp6_portaddr_hash(net, loc_addr, hnum);
@@ -904,7 +908,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
904 908
905 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { 909 udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
906 if (sk->sk_state == TCP_ESTABLISHED && 910 if (sk->sk_state == TCP_ESTABLISHED &&
907 INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif)) 911 INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif))
908 return sk; 912 return sk;
909 /* Only check first socket in chain */ 913 /* Only check first socket in chain */
910 break; 914 break;
@@ -919,6 +923,7 @@ static void udp_v6_early_demux(struct sk_buff *skb)
919 struct sock *sk; 923 struct sock *sk;
920 struct dst_entry *dst; 924 struct dst_entry *dst;
921 int dif = skb->dev->ifindex; 925 int dif = skb->dev->ifindex;
926 int sdif = inet6_sdif(skb);
922 927
923 if (!pskb_may_pull(skb, skb_transport_offset(skb) + 928 if (!pskb_may_pull(skb, skb_transport_offset(skb) +
924 sizeof(struct udphdr))) 929 sizeof(struct udphdr)))
@@ -930,7 +935,7 @@ static void udp_v6_early_demux(struct sk_buff *skb)
930 sk = __udp6_lib_demux_lookup(net, uh->dest, 935 sk = __udp6_lib_demux_lookup(net, uh->dest,
931 &ipv6_hdr(skb)->daddr, 936 &ipv6_hdr(skb)->daddr,
932 uh->source, &ipv6_hdr(skb)->saddr, 937 uh->source, &ipv6_hdr(skb)->saddr,
933 dif); 938 dif, sdif);
934 else 939 else
935 return; 940 return;
936 941
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index d767e35fff6b..ade4c10c28c6 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -125,7 +125,7 @@ nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp,
125 __tcp_hdrlen(tcph), 125 __tcp_hdrlen(tcph),
126 saddr, sport, 126 saddr, sport,
127 daddr, dport, 127 daddr, dport,
128 in->ifindex); 128 in->ifindex, 0);
129 129
130 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 130 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
131 sk = NULL; 131 sk = NULL;
@@ -195,7 +195,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
195 thoff + __tcp_hdrlen(tcph), 195 thoff + __tcp_hdrlen(tcph),
196 saddr, sport, 196 saddr, sport,
197 daddr, ntohs(dport), 197 daddr, ntohs(dport),
198 in->ifindex); 198 in->ifindex, 0);
199 199
200 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 200 if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
201 sk = NULL; 201 sk = NULL;
@@ -208,7 +208,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
208 case NFT_LOOKUP_ESTABLISHED: 208 case NFT_LOOKUP_ESTABLISHED:
209 sk = __inet6_lookup_established(net, &tcp_hashinfo, 209 sk = __inet6_lookup_established(net, &tcp_hashinfo,
210 saddr, sport, daddr, ntohs(dport), 210 saddr, sport, daddr, ntohs(dport),
211 in->ifindex); 211 in->ifindex, 0);
212 break; 212 break;
213 default: 213 default:
214 BUG(); 214 BUG();