| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
|---|
| 3 | 4 | * operating system. INET is implemented using the BSD Socket |
|---|
| 4 | 5 | * interface as the means of communication with the user level. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Authors: Lotsa people, from code originally in tcp |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or |
|---|
| 9 | | - * modify it under the terms of the GNU General Public License |
|---|
| 10 | | - * as published by the Free Software Foundation; either version |
|---|
| 11 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | |
|---|
| 14 | 10 | #ifndef _INET_HASHTABLES_H |
|---|
| .. | .. |
|---|
| 79 | 75 | |
|---|
| 80 | 76 | struct inet_bind_bucket { |
|---|
| 81 | 77 | possible_net_t ib_net; |
|---|
| 78 | + int l3mdev; |
|---|
| 82 | 79 | unsigned short port; |
|---|
| 83 | 80 | signed char fastreuse; |
|---|
| 84 | 81 | signed char fastreuseport; |
|---|
| .. | .. |
|---|
| 188 | 185 | |
|---|
| 189 | 186 | int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo); |
|---|
| 190 | 187 | |
|---|
| 188 | +static inline void inet_hashinfo2_free_mod(struct inet_hashinfo *h) |
|---|
| 189 | +{ |
|---|
| 190 | + kfree(h->lhash2); |
|---|
| 191 | + h->lhash2 = NULL; |
|---|
| 192 | +} |
|---|
| 193 | + |
|---|
| 191 | 194 | static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) |
|---|
| 192 | 195 | { |
|---|
| 193 | 196 | kvfree(hashinfo->ehash_locks); |
|---|
| .. | .. |
|---|
| 197 | 200 | struct inet_bind_bucket * |
|---|
| 198 | 201 | inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net, |
|---|
| 199 | 202 | struct inet_bind_hashbucket *head, |
|---|
| 200 | | - const unsigned short snum); |
|---|
| 203 | + const unsigned short snum, int l3mdev); |
|---|
| 201 | 204 | void inet_bind_bucket_destroy(struct kmem_cache *cachep, |
|---|
| 202 | 205 | struct inet_bind_bucket *tb); |
|---|
| 203 | 206 | |
|---|
| .. | .. |
|---|
| 231 | 234 | unsigned long numentries, int scale, |
|---|
| 232 | 235 | unsigned long low_limit, |
|---|
| 233 | 236 | unsigned long high_limit); |
|---|
| 237 | +int inet_hashinfo2_init_mod(struct inet_hashinfo *h); |
|---|
| 234 | 238 | |
|---|
| 235 | | -bool inet_ehash_insert(struct sock *sk, struct sock *osk); |
|---|
| 236 | | -bool inet_ehash_nolisten(struct sock *sk, struct sock *osk); |
|---|
| 239 | +bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk); |
|---|
| 240 | +bool inet_ehash_nolisten(struct sock *sk, struct sock *osk, |
|---|
| 241 | + bool *found_dup_sk); |
|---|
| 237 | 242 | int __inet_hash(struct sock *sk, struct sock *osk); |
|---|
| 238 | 243 | int inet_hash(struct sock *sk); |
|---|
| 239 | 244 | void inet_unhash(struct sock *sk); |
|---|
| .. | .. |
|---|
| 273 | 278 | ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport))) |
|---|
| 274 | 279 | #endif |
|---|
| 275 | 280 | |
|---|
| 276 | | -#if (BITS_PER_LONG == 64) |
|---|
| 277 | 281 | #ifdef __BIG_ENDIAN |
|---|
| 278 | 282 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ |
|---|
| 279 | 283 | const __addrpair __name = (__force __addrpair) ( \ |
|---|
| .. | .. |
|---|
| 285 | 289 | (((__force __u64)(__be32)(__daddr)) << 32) | \ |
|---|
| 286 | 290 | ((__force __u64)(__be32)(__saddr))) |
|---|
| 287 | 291 | #endif /* __BIG_ENDIAN */ |
|---|
| 288 | | -#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \ |
|---|
| 289 | | - (((__sk)->sk_portpair == (__ports)) && \ |
|---|
| 290 | | - ((__sk)->sk_addrpair == (__cookie)) && \ |
|---|
| 291 | | - (!(__sk)->sk_bound_dev_if || \ |
|---|
| 292 | | - ((__sk)->sk_bound_dev_if == (__dif)) || \ |
|---|
| 293 | | - ((__sk)->sk_bound_dev_if == (__sdif))) && \ |
|---|
| 294 | | - net_eq(sock_net(__sk), (__net))) |
|---|
| 295 | | -#else /* 32-bit arch */ |
|---|
| 296 | | -#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ |
|---|
| 297 | | - const int __name __deprecated __attribute__((unused)) |
|---|
| 298 | 292 | |
|---|
| 299 | | -#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \ |
|---|
| 300 | | - (((__sk)->sk_portpair == (__ports)) && \ |
|---|
| 301 | | - ((__sk)->sk_daddr == (__saddr)) && \ |
|---|
| 302 | | - ((__sk)->sk_rcv_saddr == (__daddr)) && \ |
|---|
| 303 | | - (!(__sk)->sk_bound_dev_if || \ |
|---|
| 304 | | - ((__sk)->sk_bound_dev_if == (__dif)) || \ |
|---|
| 305 | | - ((__sk)->sk_bound_dev_if == (__sdif))) && \ |
|---|
| 306 | | - net_eq(sock_net(__sk), (__net))) |
|---|
| 307 | | -#endif /* 64-bit arch */ |
|---|
| 293 | +static inline bool INET_MATCH(struct net *net, const struct sock *sk, |
|---|
| 294 | + const __addrpair cookie, const __portpair ports, |
|---|
| 295 | + int dif, int sdif) |
|---|
| 296 | +{ |
|---|
| 297 | + if (!net_eq(sock_net(sk), net) || |
|---|
| 298 | + sk->sk_portpair != ports || |
|---|
| 299 | + sk->sk_addrpair != cookie) |
|---|
| 300 | + return false; |
|---|
| 301 | + |
|---|
| 302 | + /* READ_ONCE() paired with WRITE_ONCE() in sock_bindtoindex_locked() */ |
|---|
| 303 | + return inet_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif, |
|---|
| 304 | + sdif); |
|---|
| 305 | +} |
|---|
| 308 | 306 | |
|---|
| 309 | 307 | /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need |
|---|
| 310 | 308 | * not check it for lookups anymore, thanks Alexey. -DaveM |
|---|
| .. | .. |
|---|
| 372 | 370 | const int sdif, |
|---|
| 373 | 371 | bool *refcounted) |
|---|
| 374 | 372 | { |
|---|
| 375 | | - struct sock *sk = skb_steal_sock(skb); |
|---|
| 373 | + struct sock *sk = skb_steal_sock(skb, refcounted); |
|---|
| 376 | 374 | const struct iphdr *iph = ip_hdr(skb); |
|---|
| 377 | 375 | |
|---|
| 378 | | - *refcounted = true; |
|---|
| 379 | 376 | if (sk) |
|---|
| 380 | 377 | return sk; |
|---|
| 381 | 378 | |
|---|
| .. | .. |
|---|
| 406 | 403 | } |
|---|
| 407 | 404 | |
|---|
| 408 | 405 | int __inet_hash_connect(struct inet_timewait_death_row *death_row, |
|---|
| 409 | | - struct sock *sk, u32 port_offset, |
|---|
| 406 | + struct sock *sk, u64 port_offset, |
|---|
| 410 | 407 | int (*check_established)(struct inet_timewait_death_row *, |
|---|
| 411 | 408 | struct sock *, __u16, |
|---|
| 412 | 409 | struct inet_timewait_sock **)); |
|---|