|
@@ -25,6 +25,7 @@
|
|
|
#include <net/inet_hashtables.h>
|
|
|
#include <net/secure_seq.h>
|
|
|
#include <net/ip.h>
|
|
|
+#include <net/tcp.h>
|
|
|
#include <net/sock_reuseport.h>
|
|
|
|
|
|
static u32 inet_ehashfn(const struct net *net, const __be32 laddr,
|
|
@@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(__inet_inherit_port);
|
|
|
|
|
|
static inline int compute_score(struct sock *sk, struct net *net,
|
|
|
const unsigned short hnum, const __be32 daddr,
|
|
|
- const int dif)
|
|
|
+ const int dif, bool exact_dif)
|
|
|
{
|
|
|
int score = -1;
|
|
|
struct inet_sock *inet = inet_sk(sk);
|
|
@@ -186,7 +187,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
|
|
|
return -1;
|
|
|
score += 4;
|
|
|
}
|
|
|
- if (sk->sk_bound_dev_if) {
|
|
|
+ if (sk->sk_bound_dev_if || exact_dif) {
|
|
|
if (sk->sk_bound_dev_if != dif)
|
|
|
return -1;
|
|
|
score += 4;
|
|
@@ -215,11 +216,12 @@ struct sock *__inet_lookup_listener(struct net *net,
|
|
|
unsigned int hash = inet_lhashfn(net, hnum);
|
|
|
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
|
|
|
int score, hiscore = 0, matches = 0, reuseport = 0;
|
|
|
+ bool exact_dif = inet_exact_dif_match(net, skb);
|
|
|
struct sock *sk, *result = NULL;
|
|
|
u32 phash = 0;
|
|
|
|
|
|
sk_for_each_rcu(sk, &ilb->head) {
|
|
|
- score = compute_score(sk, net, hnum, daddr, dif);
|
|
|
+ score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
|
|
|
if (score > hiscore) {
|
|
|
reuseport = sk->sk_reuseport;
|
|
|
if (reuseport) {
|