18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 48c2ecf20Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 58c2ecf20Sopenharmony_ci * interface as the means of communication with the user level. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Authors: Lotsa people, from code originally in tcp 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef _INET_HASHTABLES_H 118c2ecf20Sopenharmony_ci#define _INET_HASHTABLES_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 158c2ecf20Sopenharmony_ci#include <linux/ip.h> 168c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 178c2ecf20Sopenharmony_ci#include <linux/list.h> 188c2ecf20Sopenharmony_ci#include <linux/slab.h> 198c2ecf20Sopenharmony_ci#include <linux/socket.h> 208c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 218c2ecf20Sopenharmony_ci#include <linux/types.h> 228c2ecf20Sopenharmony_ci#include <linux/wait.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <net/inet_connection_sock.h> 258c2ecf20Sopenharmony_ci#include <net/inet_sock.h> 268c2ecf20Sopenharmony_ci#include <net/sock.h> 278c2ecf20Sopenharmony_ci#include <net/route.h> 288c2ecf20Sopenharmony_ci#include <net/tcp_states.h> 298c2ecf20Sopenharmony_ci#include <net/netns/hash.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <linux/refcount.h> 328c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* This is for all connections with a full identity, no wildcards. 358c2ecf20Sopenharmony_ci * The 'e' prefix stands for Establish, but we really put all sockets 368c2ecf20Sopenharmony_ci * but LISTEN ones. 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_cistruct inet_ehash_bucket { 398c2ecf20Sopenharmony_ci struct hlist_nulls_head chain; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* There are a few simple rules, which allow for local port reuse by 438c2ecf20Sopenharmony_ci * an application. In essence: 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * 1) Sockets bound to different interfaces may share a local port. 468c2ecf20Sopenharmony_ci * Failing that, goto test 2. 478c2ecf20Sopenharmony_ci * 2) If all sockets have sk->sk_reuse set, and none of them are in 488c2ecf20Sopenharmony_ci * TCP_LISTEN state, the port may be shared. 498c2ecf20Sopenharmony_ci * Failing that, goto test 3. 508c2ecf20Sopenharmony_ci * 3) If all sockets are bound to a specific inet_sk(sk)->rcv_saddr local 518c2ecf20Sopenharmony_ci * address, and none of them are the same, the port may be 528c2ecf20Sopenharmony_ci * shared. 538c2ecf20Sopenharmony_ci * Failing this, the port cannot be shared. 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * The interesting point, is test #2. This is what an FTP server does 568c2ecf20Sopenharmony_ci * all day. To optimize this case we use a specific flag bit defined 578c2ecf20Sopenharmony_ci * below. As we add sockets to a bind bucket list, we perform a 588c2ecf20Sopenharmony_ci * check of: (newsk->sk_reuse && (newsk->sk_state != TCP_LISTEN)) 598c2ecf20Sopenharmony_ci * As long as all sockets added to a bind bucket pass this test, 608c2ecf20Sopenharmony_ci * the flag bit will be set. 618c2ecf20Sopenharmony_ci * The resulting situation is that tcp_v[46]_verify_bind() can just check 628c2ecf20Sopenharmony_ci * for this flag bit, if it is set and the socket trying to bind has 638c2ecf20Sopenharmony_ci * sk->sk_reuse set, we don't even have to walk the owners list at all, 648c2ecf20Sopenharmony_ci * we return that it is ok to bind this socket to the requested local port. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * Sounds like a lot of work, but it is worth it. In a more naive 678c2ecf20Sopenharmony_ci * implementation (ie. current FreeBSD etc.) the entire list of ports 688c2ecf20Sopenharmony_ci * must be walked for each data port opened by an ftp server. Needless 698c2ecf20Sopenharmony_ci * to say, this does not scale at all. With a couple thousand FTP 708c2ecf20Sopenharmony_ci * users logged onto your box, isn't it nice to know that new data 718c2ecf20Sopenharmony_ci * ports are created in O(1) time? I thought so. ;-) -DaveM 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci#define FASTREUSEPORT_ANY 1 748c2ecf20Sopenharmony_ci#define FASTREUSEPORT_STRICT 2 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct inet_bind_bucket { 778c2ecf20Sopenharmony_ci possible_net_t ib_net; 788c2ecf20Sopenharmony_ci int l3mdev; 798c2ecf20Sopenharmony_ci unsigned short port; 808c2ecf20Sopenharmony_ci signed char fastreuse; 818c2ecf20Sopenharmony_ci signed char fastreuseport; 828c2ecf20Sopenharmony_ci kuid_t fastuid; 838c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 848c2ecf20Sopenharmony_ci struct in6_addr fast_v6_rcv_saddr; 858c2ecf20Sopenharmony_ci#endif 868c2ecf20Sopenharmony_ci __be32 fast_rcv_saddr; 878c2ecf20Sopenharmony_ci unsigned short fast_sk_family; 888c2ecf20Sopenharmony_ci bool fast_ipv6_only; 898c2ecf20Sopenharmony_ci struct hlist_node node; 908c2ecf20Sopenharmony_ci struct hlist_head owners; 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic inline struct net *ib_net(struct inet_bind_bucket *ib) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci return read_pnet(&ib->ib_net); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define inet_bind_bucket_for_each(tb, head) \ 998c2ecf20Sopenharmony_ci hlist_for_each_entry(tb, head, node) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistruct inet_bind_hashbucket { 1028c2ecf20Sopenharmony_ci spinlock_t lock; 1038c2ecf20Sopenharmony_ci struct hlist_head chain; 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* Sockets can be hashed in established or listening table. 1078c2ecf20Sopenharmony_ci * We must use different 'nulls' end-of-chain value for all hash buckets : 1088c2ecf20Sopenharmony_ci * A socket might transition from ESTABLISH to LISTEN state without 1098c2ecf20Sopenharmony_ci * RCU grace period. A lookup in ehash table needs to handle this case. 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_ci#define LISTENING_NULLS_BASE (1U << 29) 1128c2ecf20Sopenharmony_cistruct inet_listen_hashbucket { 1138c2ecf20Sopenharmony_ci spinlock_t lock; 1148c2ecf20Sopenharmony_ci unsigned int count; 1158c2ecf20Sopenharmony_ci union { 1168c2ecf20Sopenharmony_ci struct hlist_head head; 1178c2ecf20Sopenharmony_ci struct hlist_nulls_head nulls_head; 1188c2ecf20Sopenharmony_ci }; 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* This is for listening sockets, thus all sockets which possess wildcards. */ 1228c2ecf20Sopenharmony_ci#define INET_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */ 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct inet_hashinfo { 1258c2ecf20Sopenharmony_ci /* This is for sockets with full identity only. Sockets here will 1268c2ecf20Sopenharmony_ci * always be without wildcards and will have the following invariant: 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_ci struct inet_ehash_bucket *ehash; 1328c2ecf20Sopenharmony_ci spinlock_t *ehash_locks; 1338c2ecf20Sopenharmony_ci unsigned int ehash_mask; 1348c2ecf20Sopenharmony_ci unsigned int ehash_locks_mask; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* Ok, let's try this, I give up, we do need a local binding 1378c2ecf20Sopenharmony_ci * TCP hash as well as the others for fast bind/connect. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci struct kmem_cache *bind_bucket_cachep; 1408c2ecf20Sopenharmony_ci struct inet_bind_hashbucket *bhash; 1418c2ecf20Sopenharmony_ci unsigned int bhash_size; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* The 2nd listener table hashed by local port and address */ 1448c2ecf20Sopenharmony_ci unsigned int lhash2_mask; 1458c2ecf20Sopenharmony_ci struct inet_listen_hashbucket *lhash2; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* All the above members are written once at bootup and 1488c2ecf20Sopenharmony_ci * never written again _or_ are predominantly read-access. 1498c2ecf20Sopenharmony_ci * 1508c2ecf20Sopenharmony_ci * Now align to a new cache line as all the following members 1518c2ecf20Sopenharmony_ci * might be often dirty. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ci /* All sockets in TCP_LISTEN state will be in listening_hash. 1548c2ecf20Sopenharmony_ci * This is the only table where wildcard'd TCP sockets can 1558c2ecf20Sopenharmony_ci * exist. listening_hash is only hashed by local port number. 1568c2ecf20Sopenharmony_ci * If lhash2 is initialized, the same socket will also be hashed 1578c2ecf20Sopenharmony_ci * to lhash2 by port and address. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci struct inet_listen_hashbucket listening_hash[INET_LHTABLE_SIZE] 1608c2ecf20Sopenharmony_ci ____cacheline_aligned_in_smp; 1618c2ecf20Sopenharmony_ci}; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci#define inet_lhash2_for_each_icsk_rcu(__icsk, list) \ 1648c2ecf20Sopenharmony_ci hlist_for_each_entry_rcu(__icsk, list, icsk_listen_portaddr_node) 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic inline struct inet_listen_hashbucket * 1678c2ecf20Sopenharmony_ciinet_lhash2_bucket(struct inet_hashinfo *h, u32 hash) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci return &h->lhash2[hash & h->lhash2_mask]; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic inline struct inet_ehash_bucket *inet_ehash_bucket( 1738c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 1748c2ecf20Sopenharmony_ci unsigned int hash) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci return &hashinfo->ehash[hash & hashinfo->ehash_mask]; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic inline spinlock_t *inet_ehash_lockp( 1808c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 1818c2ecf20Sopenharmony_ci unsigned int hash) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci return &hashinfo->ehash_locks[hash & hashinfo->ehash_locks_mask]; 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ciint inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic inline void inet_hashinfo2_free_mod(struct inet_hashinfo *h) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci kfree(h->lhash2); 1918c2ecf20Sopenharmony_ci h->lhash2 = NULL; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci kvfree(hashinfo->ehash_locks); 1978c2ecf20Sopenharmony_ci hashinfo->ehash_locks = NULL; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistruct inet_bind_bucket * 2018c2ecf20Sopenharmony_ciinet_bind_bucket_create(struct kmem_cache *cachep, struct net *net, 2028c2ecf20Sopenharmony_ci struct inet_bind_hashbucket *head, 2038c2ecf20Sopenharmony_ci const unsigned short snum, int l3mdev); 2048c2ecf20Sopenharmony_civoid inet_bind_bucket_destroy(struct kmem_cache *cachep, 2058c2ecf20Sopenharmony_ci struct inet_bind_bucket *tb); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic inline u32 inet_bhashfn(const struct net *net, const __u16 lport, 2088c2ecf20Sopenharmony_ci const u32 bhash_size) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci return (lport + net_hash_mix(net)) & (bhash_size - 1); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_civoid inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb, 2148c2ecf20Sopenharmony_ci const unsigned short snum); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/* These can have wildcards, don't try too hard. */ 2178c2ecf20Sopenharmony_cistatic inline u32 inet_lhashfn(const struct net *net, const unsigned short num) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci return (num + net_hash_mix(net)) & (INET_LHTABLE_SIZE - 1); 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic inline int inet_sk_listen_hashfn(const struct sock *sk) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci return inet_lhashfn(sock_net(sk), inet_sk(sk)->inet_num); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci/* Caller must disable local BH processing. */ 2288c2ecf20Sopenharmony_ciint __inet_inherit_port(const struct sock *sk, struct sock *child); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_civoid inet_put_port(struct sock *sk); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_civoid inet_hashinfo_init(struct inet_hashinfo *h); 2338c2ecf20Sopenharmony_civoid inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, 2348c2ecf20Sopenharmony_ci unsigned long numentries, int scale, 2358c2ecf20Sopenharmony_ci unsigned long low_limit, 2368c2ecf20Sopenharmony_ci unsigned long high_limit); 2378c2ecf20Sopenharmony_ciint inet_hashinfo2_init_mod(struct inet_hashinfo *h); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cibool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk); 2408c2ecf20Sopenharmony_cibool inet_ehash_nolisten(struct sock *sk, struct sock *osk, 2418c2ecf20Sopenharmony_ci bool *found_dup_sk); 2428c2ecf20Sopenharmony_ciint __inet_hash(struct sock *sk, struct sock *osk); 2438c2ecf20Sopenharmony_ciint inet_hash(struct sock *sk); 2448c2ecf20Sopenharmony_civoid inet_unhash(struct sock *sk); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistruct sock *__inet_lookup_listener(struct net *net, 2478c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 2488c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 2498c2ecf20Sopenharmony_ci const __be32 saddr, const __be16 sport, 2508c2ecf20Sopenharmony_ci const __be32 daddr, 2518c2ecf20Sopenharmony_ci const unsigned short hnum, 2528c2ecf20Sopenharmony_ci const int dif, const int sdif); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic inline struct sock *inet_lookup_listener(struct net *net, 2558c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 2568c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 2578c2ecf20Sopenharmony_ci __be32 saddr, __be16 sport, 2588c2ecf20Sopenharmony_ci __be32 daddr, __be16 dport, int dif, int sdif) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport, 2618c2ecf20Sopenharmony_ci daddr, ntohs(dport), dif, sdif); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/* Socket demux engine toys. */ 2658c2ecf20Sopenharmony_ci/* What happens here is ugly; there's a pair of adjacent fields in 2668c2ecf20Sopenharmony_ci struct inet_sock; __be16 dport followed by __u16 num. We want to 2678c2ecf20Sopenharmony_ci search by pair, so we combine the keys into a single 32bit value 2688c2ecf20Sopenharmony_ci and compare with 32bit value read from &...->dport. Let's at least 2698c2ecf20Sopenharmony_ci make sure that it's not mixed with anything else... 2708c2ecf20Sopenharmony_ci On 64bit targets we combine comparisons with pair of adjacent __be32 2718c2ecf20Sopenharmony_ci fields in the same way. 2728c2ecf20Sopenharmony_ci*/ 2738c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 2748c2ecf20Sopenharmony_ci#define INET_COMBINED_PORTS(__sport, __dport) \ 2758c2ecf20Sopenharmony_ci ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport))) 2768c2ecf20Sopenharmony_ci#else /* __LITTLE_ENDIAN */ 2778c2ecf20Sopenharmony_ci#define INET_COMBINED_PORTS(__sport, __dport) \ 2788c2ecf20Sopenharmony_ci ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport))) 2798c2ecf20Sopenharmony_ci#endif 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 2828c2ecf20Sopenharmony_ci#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ 2838c2ecf20Sopenharmony_ci const __addrpair __name = (__force __addrpair) ( \ 2848c2ecf20Sopenharmony_ci (((__force __u64)(__be32)(__saddr)) << 32) | \ 2858c2ecf20Sopenharmony_ci ((__force __u64)(__be32)(__daddr))) 2868c2ecf20Sopenharmony_ci#else /* __LITTLE_ENDIAN */ 2878c2ecf20Sopenharmony_ci#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ 2888c2ecf20Sopenharmony_ci const __addrpair __name = (__force __addrpair) ( \ 2898c2ecf20Sopenharmony_ci (((__force __u64)(__be32)(__daddr)) << 32) | \ 2908c2ecf20Sopenharmony_ci ((__force __u64)(__be32)(__saddr))) 2918c2ecf20Sopenharmony_ci#endif /* __BIG_ENDIAN */ 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic inline bool INET_MATCH(struct net *net, const struct sock *sk, 2948c2ecf20Sopenharmony_ci const __addrpair cookie, const __portpair ports, 2958c2ecf20Sopenharmony_ci int dif, int sdif) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci if (!net_eq(sock_net(sk), net) || 2988c2ecf20Sopenharmony_ci sk->sk_portpair != ports || 2998c2ecf20Sopenharmony_ci sk->sk_addrpair != cookie) 3008c2ecf20Sopenharmony_ci return false; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* READ_ONCE() paired with WRITE_ONCE() in sock_bindtoindex_locked() */ 3038c2ecf20Sopenharmony_ci return inet_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), dif, 3048c2ecf20Sopenharmony_ci sdif); 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci/* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so we need 3088c2ecf20Sopenharmony_ci * not check it for lookups anymore, thanks Alexey. -DaveM 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_cistruct sock *__inet_lookup_established(struct net *net, 3118c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 3128c2ecf20Sopenharmony_ci const __be32 saddr, const __be16 sport, 3138c2ecf20Sopenharmony_ci const __be32 daddr, const u16 hnum, 3148c2ecf20Sopenharmony_ci const int dif, const int sdif); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic inline struct sock * 3178c2ecf20Sopenharmony_ci inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo, 3188c2ecf20Sopenharmony_ci const __be32 saddr, const __be16 sport, 3198c2ecf20Sopenharmony_ci const __be32 daddr, const __be16 dport, 3208c2ecf20Sopenharmony_ci const int dif) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci return __inet_lookup_established(net, hashinfo, saddr, sport, daddr, 3238c2ecf20Sopenharmony_ci ntohs(dport), dif, 0); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic inline struct sock *__inet_lookup(struct net *net, 3278c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 3288c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 3298c2ecf20Sopenharmony_ci const __be32 saddr, const __be16 sport, 3308c2ecf20Sopenharmony_ci const __be32 daddr, const __be16 dport, 3318c2ecf20Sopenharmony_ci const int dif, const int sdif, 3328c2ecf20Sopenharmony_ci bool *refcounted) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci u16 hnum = ntohs(dport); 3358c2ecf20Sopenharmony_ci struct sock *sk; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci sk = __inet_lookup_established(net, hashinfo, saddr, sport, 3388c2ecf20Sopenharmony_ci daddr, hnum, dif, sdif); 3398c2ecf20Sopenharmony_ci *refcounted = true; 3408c2ecf20Sopenharmony_ci if (sk) 3418c2ecf20Sopenharmony_ci return sk; 3428c2ecf20Sopenharmony_ci *refcounted = false; 3438c2ecf20Sopenharmony_ci return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, 3448c2ecf20Sopenharmony_ci sport, daddr, hnum, dif, sdif); 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic inline struct sock *inet_lookup(struct net *net, 3488c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 3498c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 3508c2ecf20Sopenharmony_ci const __be32 saddr, const __be16 sport, 3518c2ecf20Sopenharmony_ci const __be32 daddr, const __be16 dport, 3528c2ecf20Sopenharmony_ci const int dif) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci struct sock *sk; 3558c2ecf20Sopenharmony_ci bool refcounted; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, 3588c2ecf20Sopenharmony_ci dport, dif, 0, &refcounted); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt)) 3618c2ecf20Sopenharmony_ci sk = NULL; 3628c2ecf20Sopenharmony_ci return sk; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, 3668c2ecf20Sopenharmony_ci struct sk_buff *skb, 3678c2ecf20Sopenharmony_ci int doff, 3688c2ecf20Sopenharmony_ci const __be16 sport, 3698c2ecf20Sopenharmony_ci const __be16 dport, 3708c2ecf20Sopenharmony_ci const int sdif, 3718c2ecf20Sopenharmony_ci bool *refcounted) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci struct sock *sk = skb_steal_sock(skb, refcounted); 3748c2ecf20Sopenharmony_ci const struct iphdr *iph = ip_hdr(skb); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci if (sk) 3778c2ecf20Sopenharmony_ci return sk; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, 3808c2ecf20Sopenharmony_ci doff, iph->saddr, sport, 3818c2ecf20Sopenharmony_ci iph->daddr, dport, inet_iif(skb), sdif, 3828c2ecf20Sopenharmony_ci refcounted); 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ciu32 inet6_ehashfn(const struct net *net, 3868c2ecf20Sopenharmony_ci const struct in6_addr *laddr, const u16 lport, 3878c2ecf20Sopenharmony_ci const struct in6_addr *faddr, const __be16 fport); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic inline void sk_daddr_set(struct sock *sk, __be32 addr) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci sk->sk_daddr = addr; /* alias of inet_daddr */ 3928c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 3938c2ecf20Sopenharmony_ci ipv6_addr_set_v4mapped(addr, &sk->sk_v6_daddr); 3948c2ecf20Sopenharmony_ci#endif 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic inline void sk_rcv_saddr_set(struct sock *sk, __be32 addr) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci sk->sk_rcv_saddr = addr; /* alias of inet_rcv_saddr */ 4008c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 4018c2ecf20Sopenharmony_ci ipv6_addr_set_v4mapped(addr, &sk->sk_v6_rcv_saddr); 4028c2ecf20Sopenharmony_ci#endif 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ciint __inet_hash_connect(struct inet_timewait_death_row *death_row, 4068c2ecf20Sopenharmony_ci struct sock *sk, u64 port_offset, 4078c2ecf20Sopenharmony_ci int (*check_established)(struct inet_timewait_death_row *, 4088c2ecf20Sopenharmony_ci struct sock *, __u16, 4098c2ecf20Sopenharmony_ci struct inet_timewait_sock **)); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ciint inet_hash_connect(struct inet_timewait_death_row *death_row, 4128c2ecf20Sopenharmony_ci struct sock *sk); 4138c2ecf20Sopenharmony_ci#endif /* _INET_HASHTABLES_H */ 414