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 * Generic INET6 transport hashtables 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Authors: Lotsa people, from code originally in tcp, generalised here 108c2ecf20Sopenharmony_ci * by Arnaldo Carvalho de Melo <acme@mandriva.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/random.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <net/addrconf.h> 178c2ecf20Sopenharmony_ci#include <net/inet_connection_sock.h> 188c2ecf20Sopenharmony_ci#include <net/inet_hashtables.h> 198c2ecf20Sopenharmony_ci#include <net/inet6_hashtables.h> 208c2ecf20Sopenharmony_ci#include <net/secure_seq.h> 218c2ecf20Sopenharmony_ci#include <net/ip.h> 228c2ecf20Sopenharmony_ci#include <net/sock_reuseport.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciextern struct inet_hashinfo tcp_hashinfo; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciu32 inet6_ehashfn(const struct net *net, 278c2ecf20Sopenharmony_ci const struct in6_addr *laddr, const u16 lport, 288c2ecf20Sopenharmony_ci const struct in6_addr *faddr, const __be16 fport) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci static u32 inet6_ehash_secret __read_mostly; 318c2ecf20Sopenharmony_ci static u32 ipv6_hash_secret __read_mostly; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci u32 lhash, fhash; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci net_get_random_once(&inet6_ehash_secret, sizeof(inet6_ehash_secret)); 368c2ecf20Sopenharmony_ci net_get_random_once(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci lhash = (__force u32)laddr->s6_addr32[3]; 398c2ecf20Sopenharmony_ci fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci return __inet6_ehashfn(lhash, lport, fhash, fport, 428c2ecf20Sopenharmony_ci inet6_ehash_secret + net_hash_mix(net)); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so 478c2ecf20Sopenharmony_ci * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * The sockhash lock must be held as a reader here. 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_cistruct sock *__inet6_lookup_established(struct net *net, 528c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 538c2ecf20Sopenharmony_ci const struct in6_addr *saddr, 548c2ecf20Sopenharmony_ci const __be16 sport, 558c2ecf20Sopenharmony_ci const struct in6_addr *daddr, 568c2ecf20Sopenharmony_ci const u16 hnum, 578c2ecf20Sopenharmony_ci const int dif, const int sdif) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci struct sock *sk; 608c2ecf20Sopenharmony_ci const struct hlist_nulls_node *node; 618c2ecf20Sopenharmony_ci const __portpair ports = INET_COMBINED_PORTS(sport, hnum); 628c2ecf20Sopenharmony_ci /* Optimize here for direct hit, only listening connections can 638c2ecf20Sopenharmony_ci * have wildcards anyways. 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_ci unsigned int hash = inet6_ehashfn(net, daddr, hnum, saddr, sport); 668c2ecf20Sopenharmony_ci unsigned int slot = hash & hashinfo->ehash_mask; 678c2ecf20Sopenharmony_ci struct inet_ehash_bucket *head = &hashinfo->ehash[slot]; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cibegin: 718c2ecf20Sopenharmony_ci sk_nulls_for_each_rcu(sk, node, &head->chain) { 728c2ecf20Sopenharmony_ci if (sk->sk_hash != hash) 738c2ecf20Sopenharmony_ci continue; 748c2ecf20Sopenharmony_ci if (!inet6_match(net, sk, saddr, daddr, ports, dif, sdif)) 758c2ecf20Sopenharmony_ci continue; 768c2ecf20Sopenharmony_ci if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt))) 778c2ecf20Sopenharmony_ci goto out; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (unlikely(!inet6_match(net, sk, saddr, daddr, ports, dif, sdif))) { 808c2ecf20Sopenharmony_ci sock_gen_put(sk); 818c2ecf20Sopenharmony_ci goto begin; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci goto found; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci if (get_nulls_value(node) != slot) 868c2ecf20Sopenharmony_ci goto begin; 878c2ecf20Sopenharmony_ciout: 888c2ecf20Sopenharmony_ci sk = NULL; 898c2ecf20Sopenharmony_cifound: 908c2ecf20Sopenharmony_ci return sk; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__inet6_lookup_established); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic inline int compute_score(struct sock *sk, struct net *net, 958c2ecf20Sopenharmony_ci const unsigned short hnum, 968c2ecf20Sopenharmony_ci const struct in6_addr *daddr, 978c2ecf20Sopenharmony_ci const int dif, const int sdif) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci int score = -1; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (net_eq(sock_net(sk), net) && inet_sk(sk)->inet_num == hnum && 1028c2ecf20Sopenharmony_ci sk->sk_family == PF_INET6) { 1038c2ecf20Sopenharmony_ci if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr)) 1048c2ecf20Sopenharmony_ci return -1; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) 1078c2ecf20Sopenharmony_ci return -1; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci score = sk->sk_bound_dev_if ? 2 : 1; 1108c2ecf20Sopenharmony_ci if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) 1118c2ecf20Sopenharmony_ci score++; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci return score; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic inline struct sock *lookup_reuseport(struct net *net, struct sock *sk, 1178c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 1188c2ecf20Sopenharmony_ci const struct in6_addr *saddr, 1198c2ecf20Sopenharmony_ci __be16 sport, 1208c2ecf20Sopenharmony_ci const struct in6_addr *daddr, 1218c2ecf20Sopenharmony_ci unsigned short hnum) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct sock *reuse_sk = NULL; 1248c2ecf20Sopenharmony_ci u32 phash; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (sk->sk_reuseport) { 1278c2ecf20Sopenharmony_ci phash = inet6_ehashfn(net, daddr, hnum, saddr, sport); 1288c2ecf20Sopenharmony_ci reuse_sk = reuseport_select_sock(sk, phash, skb, doff); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci return reuse_sk; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci/* called with rcu_read_lock() */ 1348c2ecf20Sopenharmony_cistatic struct sock *inet6_lhash2_lookup(struct net *net, 1358c2ecf20Sopenharmony_ci struct inet_listen_hashbucket *ilb2, 1368c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 1378c2ecf20Sopenharmony_ci const struct in6_addr *saddr, 1388c2ecf20Sopenharmony_ci const __be16 sport, const struct in6_addr *daddr, 1398c2ecf20Sopenharmony_ci const unsigned short hnum, const int dif, const int sdif) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct inet_connection_sock *icsk; 1428c2ecf20Sopenharmony_ci struct sock *sk, *result = NULL; 1438c2ecf20Sopenharmony_ci int score, hiscore = 0; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci inet_lhash2_for_each_icsk_rcu(icsk, &ilb2->head) { 1468c2ecf20Sopenharmony_ci sk = (struct sock *)icsk; 1478c2ecf20Sopenharmony_ci score = compute_score(sk, net, hnum, daddr, dif, sdif); 1488c2ecf20Sopenharmony_ci if (score > hiscore) { 1498c2ecf20Sopenharmony_ci result = lookup_reuseport(net, sk, skb, doff, 1508c2ecf20Sopenharmony_ci saddr, sport, daddr, hnum); 1518c2ecf20Sopenharmony_ci if (result) 1528c2ecf20Sopenharmony_ci return result; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci result = sk; 1558c2ecf20Sopenharmony_ci hiscore = score; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return result; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic inline struct sock *inet6_lookup_run_bpf(struct net *net, 1638c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 1648c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 1658c2ecf20Sopenharmony_ci const struct in6_addr *saddr, 1668c2ecf20Sopenharmony_ci const __be16 sport, 1678c2ecf20Sopenharmony_ci const struct in6_addr *daddr, 1688c2ecf20Sopenharmony_ci const u16 hnum) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci struct sock *sk, *reuse_sk; 1718c2ecf20Sopenharmony_ci bool no_reuseport; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (hashinfo != &tcp_hashinfo) 1748c2ecf20Sopenharmony_ci return NULL; /* only TCP is supported */ 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_TCP, 1778c2ecf20Sopenharmony_ci saddr, sport, daddr, hnum, &sk); 1788c2ecf20Sopenharmony_ci if (no_reuseport || IS_ERR_OR_NULL(sk)) 1798c2ecf20Sopenharmony_ci return sk; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci reuse_sk = lookup_reuseport(net, sk, skb, doff, saddr, sport, daddr, hnum); 1828c2ecf20Sopenharmony_ci if (reuse_sk) 1838c2ecf20Sopenharmony_ci sk = reuse_sk; 1848c2ecf20Sopenharmony_ci return sk; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistruct sock *inet6_lookup_listener(struct net *net, 1888c2ecf20Sopenharmony_ci struct inet_hashinfo *hashinfo, 1898c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 1908c2ecf20Sopenharmony_ci const struct in6_addr *saddr, 1918c2ecf20Sopenharmony_ci const __be16 sport, const struct in6_addr *daddr, 1928c2ecf20Sopenharmony_ci const unsigned short hnum, const int dif, const int sdif) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci struct inet_listen_hashbucket *ilb2; 1958c2ecf20Sopenharmony_ci struct sock *result = NULL; 1968c2ecf20Sopenharmony_ci unsigned int hash2; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* Lookup redirect from BPF */ 1998c2ecf20Sopenharmony_ci if (static_branch_unlikely(&bpf_sk_lookup_enabled)) { 2008c2ecf20Sopenharmony_ci result = inet6_lookup_run_bpf(net, hashinfo, skb, doff, 2018c2ecf20Sopenharmony_ci saddr, sport, daddr, hnum); 2028c2ecf20Sopenharmony_ci if (result) 2038c2ecf20Sopenharmony_ci goto done; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci hash2 = ipv6_portaddr_hash(net, daddr, hnum); 2078c2ecf20Sopenharmony_ci ilb2 = inet_lhash2_bucket(hashinfo, hash2); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci result = inet6_lhash2_lookup(net, ilb2, skb, doff, 2108c2ecf20Sopenharmony_ci saddr, sport, daddr, hnum, 2118c2ecf20Sopenharmony_ci dif, sdif); 2128c2ecf20Sopenharmony_ci if (result) 2138c2ecf20Sopenharmony_ci goto done; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* Lookup lhash2 with in6addr_any */ 2168c2ecf20Sopenharmony_ci hash2 = ipv6_portaddr_hash(net, &in6addr_any, hnum); 2178c2ecf20Sopenharmony_ci ilb2 = inet_lhash2_bucket(hashinfo, hash2); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci result = inet6_lhash2_lookup(net, ilb2, skb, doff, 2208c2ecf20Sopenharmony_ci saddr, sport, &in6addr_any, hnum, 2218c2ecf20Sopenharmony_ci dif, sdif); 2228c2ecf20Sopenharmony_cidone: 2238c2ecf20Sopenharmony_ci if (IS_ERR(result)) 2248c2ecf20Sopenharmony_ci return NULL; 2258c2ecf20Sopenharmony_ci return result; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(inet6_lookup_listener); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistruct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, 2308c2ecf20Sopenharmony_ci struct sk_buff *skb, int doff, 2318c2ecf20Sopenharmony_ci const struct in6_addr *saddr, const __be16 sport, 2328c2ecf20Sopenharmony_ci const struct in6_addr *daddr, const __be16 dport, 2338c2ecf20Sopenharmony_ci const int dif) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct sock *sk; 2368c2ecf20Sopenharmony_ci bool refcounted; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, 2398c2ecf20Sopenharmony_ci ntohs(dport), dif, 0, &refcounted); 2408c2ecf20Sopenharmony_ci if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt)) 2418c2ecf20Sopenharmony_ci sk = NULL; 2428c2ecf20Sopenharmony_ci return sk; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(inet6_lookup); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic int __inet6_check_established(struct inet_timewait_death_row *death_row, 2478c2ecf20Sopenharmony_ci struct sock *sk, const __u16 lport, 2488c2ecf20Sopenharmony_ci struct inet_timewait_sock **twp) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci struct inet_hashinfo *hinfo = death_row->hashinfo; 2518c2ecf20Sopenharmony_ci struct inet_sock *inet = inet_sk(sk); 2528c2ecf20Sopenharmony_ci const struct in6_addr *daddr = &sk->sk_v6_rcv_saddr; 2538c2ecf20Sopenharmony_ci const struct in6_addr *saddr = &sk->sk_v6_daddr; 2548c2ecf20Sopenharmony_ci const int dif = sk->sk_bound_dev_if; 2558c2ecf20Sopenharmony_ci struct net *net = sock_net(sk); 2568c2ecf20Sopenharmony_ci const int sdif = l3mdev_master_ifindex_by_index(net, dif); 2578c2ecf20Sopenharmony_ci const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport); 2588c2ecf20Sopenharmony_ci const unsigned int hash = inet6_ehashfn(net, daddr, lport, saddr, 2598c2ecf20Sopenharmony_ci inet->inet_dport); 2608c2ecf20Sopenharmony_ci struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); 2618c2ecf20Sopenharmony_ci spinlock_t *lock = inet_ehash_lockp(hinfo, hash); 2628c2ecf20Sopenharmony_ci struct sock *sk2; 2638c2ecf20Sopenharmony_ci const struct hlist_nulls_node *node; 2648c2ecf20Sopenharmony_ci struct inet_timewait_sock *tw = NULL; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci spin_lock(lock); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci sk_nulls_for_each(sk2, node, &head->chain) { 2698c2ecf20Sopenharmony_ci if (sk2->sk_hash != hash) 2708c2ecf20Sopenharmony_ci continue; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (likely(inet6_match(net, sk2, saddr, daddr, ports, 2738c2ecf20Sopenharmony_ci dif, sdif))) { 2748c2ecf20Sopenharmony_ci if (sk2->sk_state == TCP_TIME_WAIT) { 2758c2ecf20Sopenharmony_ci tw = inet_twsk(sk2); 2768c2ecf20Sopenharmony_ci if (twsk_unique(sk, sk2, twp)) 2778c2ecf20Sopenharmony_ci break; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci goto not_unique; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* Must record num and sport now. Otherwise we will see 2848c2ecf20Sopenharmony_ci * in hash table socket with a funny identity. 2858c2ecf20Sopenharmony_ci */ 2868c2ecf20Sopenharmony_ci inet->inet_num = lport; 2878c2ecf20Sopenharmony_ci inet->inet_sport = htons(lport); 2888c2ecf20Sopenharmony_ci sk->sk_hash = hash; 2898c2ecf20Sopenharmony_ci WARN_ON(!sk_unhashed(sk)); 2908c2ecf20Sopenharmony_ci __sk_nulls_add_node_rcu(sk, &head->chain); 2918c2ecf20Sopenharmony_ci if (tw) { 2928c2ecf20Sopenharmony_ci sk_nulls_del_node_init_rcu((struct sock *)tw); 2938c2ecf20Sopenharmony_ci __NET_INC_STATS(net, LINUX_MIB_TIMEWAITRECYCLED); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci spin_unlock(lock); 2968c2ecf20Sopenharmony_ci sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (twp) { 2998c2ecf20Sopenharmony_ci *twp = tw; 3008c2ecf20Sopenharmony_ci } else if (tw) { 3018c2ecf20Sopenharmony_ci /* Silly. Should hash-dance instead... */ 3028c2ecf20Sopenharmony_ci inet_twsk_deschedule_put(tw); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cinot_unique: 3078c2ecf20Sopenharmony_ci spin_unlock(lock); 3088c2ecf20Sopenharmony_ci return -EADDRNOTAVAIL; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic u64 inet6_sk_port_offset(const struct sock *sk) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci const struct inet_sock *inet = inet_sk(sk); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return secure_ipv6_port_ephemeral(sk->sk_v6_rcv_saddr.s6_addr32, 3168c2ecf20Sopenharmony_ci sk->sk_v6_daddr.s6_addr32, 3178c2ecf20Sopenharmony_ci inet->inet_dport); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ciint inet6_hash_connect(struct inet_timewait_death_row *death_row, 3218c2ecf20Sopenharmony_ci struct sock *sk) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci u64 port_offset = 0; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (!inet_sk(sk)->inet_num) 3268c2ecf20Sopenharmony_ci port_offset = inet6_sk_port_offset(sk); 3278c2ecf20Sopenharmony_ci return __inet_hash_connect(death_row, sk, port_offset, 3288c2ecf20Sopenharmony_ci __inet6_check_established); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(inet6_hash_connect); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ciint inet6_hash(struct sock *sk) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci int err = 0; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (sk->sk_state != TCP_CLOSE) 3378c2ecf20Sopenharmony_ci err = __inet_hash(sk, NULL); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return err; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(inet6_hash); 342