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