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 *		Implementation of the Transmission Control Protocol(TCP).
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci *		IPv4 specific functions
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *		code split from:
128c2ecf20Sopenharmony_ci *		linux/ipv4/tcp.c
138c2ecf20Sopenharmony_ci *		linux/ipv4/tcp_input.c
148c2ecf20Sopenharmony_ci *		linux/ipv4/tcp_output.c
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci *		See tcp.c for author information
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Changes:
218c2ecf20Sopenharmony_ci *		David S. Miller	:	New socket lookup architecture.
228c2ecf20Sopenharmony_ci *					This code is dedicated to John Dyson.
238c2ecf20Sopenharmony_ci *		David S. Miller :	Change semantics of established hash,
248c2ecf20Sopenharmony_ci *					half is devoted to TIME_WAIT sockets
258c2ecf20Sopenharmony_ci *					and the rest go in the other half.
268c2ecf20Sopenharmony_ci *		Andi Kleen :		Add support for syncookies and fixed
278c2ecf20Sopenharmony_ci *					some bugs: ip options weren't passed to
288c2ecf20Sopenharmony_ci *					the TCP layer, missed a check for an
298c2ecf20Sopenharmony_ci *					ACK bit.
308c2ecf20Sopenharmony_ci *		Andi Kleen :		Implemented fast path mtu discovery.
318c2ecf20Sopenharmony_ci *	     				Fixed many serious bugs in the
328c2ecf20Sopenharmony_ci *					request_sock handling and moved
338c2ecf20Sopenharmony_ci *					most of it into the af independent code.
348c2ecf20Sopenharmony_ci *					Added tail drop and some other bugfixes.
358c2ecf20Sopenharmony_ci *					Added new listen semantics.
368c2ecf20Sopenharmony_ci *		Mike McLagan	:	Routing by source
378c2ecf20Sopenharmony_ci *	Juan Jose Ciarlante:		ip_dynaddr bits
388c2ecf20Sopenharmony_ci *		Andi Kleen:		various fixes.
398c2ecf20Sopenharmony_ci *	Vitaly E. Lavrov	:	Transparent proxy revived after year
408c2ecf20Sopenharmony_ci *					coma.
418c2ecf20Sopenharmony_ci *	Andi Kleen		:	Fix new listen.
428c2ecf20Sopenharmony_ci *	Andi Kleen		:	Fix accept error reporting.
438c2ecf20Sopenharmony_ci *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
448c2ecf20Sopenharmony_ci *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
458c2ecf20Sopenharmony_ci *					a single port at the same time.
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "TCP: " fmt
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#include <linux/bottom_half.h>
518c2ecf20Sopenharmony_ci#include <linux/types.h>
528c2ecf20Sopenharmony_ci#include <linux/fcntl.h>
538c2ecf20Sopenharmony_ci#include <linux/module.h>
548c2ecf20Sopenharmony_ci#include <linux/random.h>
558c2ecf20Sopenharmony_ci#include <linux/cache.h>
568c2ecf20Sopenharmony_ci#include <linux/jhash.h>
578c2ecf20Sopenharmony_ci#include <linux/init.h>
588c2ecf20Sopenharmony_ci#include <linux/times.h>
598c2ecf20Sopenharmony_ci#include <linux/slab.h>
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#include <net/net_namespace.h>
628c2ecf20Sopenharmony_ci#include <net/icmp.h>
638c2ecf20Sopenharmony_ci#include <net/inet_hashtables.h>
648c2ecf20Sopenharmony_ci#include <net/tcp.h>
658c2ecf20Sopenharmony_ci#include <net/transp_v6.h>
668c2ecf20Sopenharmony_ci#include <net/ipv6.h>
678c2ecf20Sopenharmony_ci#include <net/inet_common.h>
688c2ecf20Sopenharmony_ci#include <net/timewait_sock.h>
698c2ecf20Sopenharmony_ci#include <net/xfrm.h>
708c2ecf20Sopenharmony_ci#include <net/secure_seq.h>
718c2ecf20Sopenharmony_ci#include <net/busy_poll.h>
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#include <linux/inet.h>
748c2ecf20Sopenharmony_ci#include <linux/ipv6.h>
758c2ecf20Sopenharmony_ci#include <linux/stddef.h>
768c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
778c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
788c2ecf20Sopenharmony_ci#include <linux/inetdevice.h>
798c2ecf20Sopenharmony_ci#include <linux/btf_ids.h>
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#include <crypto/hash.h>
828c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#include <trace/events/tcp.h>
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
878c2ecf20Sopenharmony_cistatic int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
888c2ecf20Sopenharmony_ci			       __be32 daddr, __be32 saddr, const struct tcphdr *th);
898c2ecf20Sopenharmony_ci#endif
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistruct inet_hashinfo tcp_hashinfo;
928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_hashinfo);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic DEFINE_PER_CPU(struct sock *, ipv4_tcp_sk);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic u32 tcp_v4_init_seq(const struct sk_buff *skb)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	return secure_tcp_seq(ip_hdr(skb)->daddr,
998c2ecf20Sopenharmony_ci			      ip_hdr(skb)->saddr,
1008c2ecf20Sopenharmony_ci			      tcp_hdr(skb)->dest,
1018c2ecf20Sopenharmony_ci			      tcp_hdr(skb)->source);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic u32 tcp_v4_init_ts_off(const struct net *net, const struct sk_buff *skb)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	return secure_tcp_ts_off(net, ip_hdr(skb)->daddr, ip_hdr(skb)->saddr);
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciint tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	int reuse = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_tw_reuse);
1128c2ecf20Sopenharmony_ci	const struct inet_timewait_sock *tw = inet_twsk(sktw);
1138c2ecf20Sopenharmony_ci	const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
1148c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	if (reuse == 2) {
1178c2ecf20Sopenharmony_ci		/* Still does not detect *everything* that goes through
1188c2ecf20Sopenharmony_ci		 * lo, since we require a loopback src or dst address
1198c2ecf20Sopenharmony_ci		 * or direct binding to 'lo' interface.
1208c2ecf20Sopenharmony_ci		 */
1218c2ecf20Sopenharmony_ci		bool loopback = false;
1228c2ecf20Sopenharmony_ci		if (tw->tw_bound_dev_if == LOOPBACK_IFINDEX)
1238c2ecf20Sopenharmony_ci			loopback = true;
1248c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
1258c2ecf20Sopenharmony_ci		if (tw->tw_family == AF_INET6) {
1268c2ecf20Sopenharmony_ci			if (ipv6_addr_loopback(&tw->tw_v6_daddr) ||
1278c2ecf20Sopenharmony_ci			    ipv6_addr_v4mapped_loopback(&tw->tw_v6_daddr) ||
1288c2ecf20Sopenharmony_ci			    ipv6_addr_loopback(&tw->tw_v6_rcv_saddr) ||
1298c2ecf20Sopenharmony_ci			    ipv6_addr_v4mapped_loopback(&tw->tw_v6_rcv_saddr))
1308c2ecf20Sopenharmony_ci				loopback = true;
1318c2ecf20Sopenharmony_ci		} else
1328c2ecf20Sopenharmony_ci#endif
1338c2ecf20Sopenharmony_ci		{
1348c2ecf20Sopenharmony_ci			if (ipv4_is_loopback(tw->tw_daddr) ||
1358c2ecf20Sopenharmony_ci			    ipv4_is_loopback(tw->tw_rcv_saddr))
1368c2ecf20Sopenharmony_ci				loopback = true;
1378c2ecf20Sopenharmony_ci		}
1388c2ecf20Sopenharmony_ci		if (!loopback)
1398c2ecf20Sopenharmony_ci			reuse = 0;
1408c2ecf20Sopenharmony_ci	}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/* With PAWS, it is safe from the viewpoint
1438c2ecf20Sopenharmony_ci	   of data integrity. Even without PAWS it is safe provided sequence
1448c2ecf20Sopenharmony_ci	   spaces do not overlap i.e. at data rates <= 80Mbit/sec.
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	   Actually, the idea is close to VJ's one, only timestamp cache is
1478c2ecf20Sopenharmony_ci	   held not per host, but per port pair and TW bucket is used as state
1488c2ecf20Sopenharmony_ci	   holder.
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	   If TW bucket has been already destroyed we fall back to VJ's scheme
1518c2ecf20Sopenharmony_ci	   and use initial timestamp retrieved from peer table.
1528c2ecf20Sopenharmony_ci	 */
1538c2ecf20Sopenharmony_ci	if (tcptw->tw_ts_recent_stamp &&
1548c2ecf20Sopenharmony_ci	    (!twp || (reuse && time_after32(ktime_get_seconds(),
1558c2ecf20Sopenharmony_ci					    tcptw->tw_ts_recent_stamp)))) {
1568c2ecf20Sopenharmony_ci		/* inet_twsk_hashdance() sets sk_refcnt after putting twsk
1578c2ecf20Sopenharmony_ci		 * and releasing the bucket lock.
1588c2ecf20Sopenharmony_ci		 */
1598c2ecf20Sopenharmony_ci		if (unlikely(!refcount_inc_not_zero(&sktw->sk_refcnt)))
1608c2ecf20Sopenharmony_ci			return 0;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci		/* In case of repair and re-using TIME-WAIT sockets we still
1638c2ecf20Sopenharmony_ci		 * want to be sure that it is safe as above but honor the
1648c2ecf20Sopenharmony_ci		 * sequence numbers and time stamps set as part of the repair
1658c2ecf20Sopenharmony_ci		 * process.
1668c2ecf20Sopenharmony_ci		 *
1678c2ecf20Sopenharmony_ci		 * Without this check re-using a TIME-WAIT socket with TCP
1688c2ecf20Sopenharmony_ci		 * repair would accumulate a -1 on the repair assigned
1698c2ecf20Sopenharmony_ci		 * sequence number. The first time it is reused the sequence
1708c2ecf20Sopenharmony_ci		 * is -1, the second time -2, etc. This fixes that issue
1718c2ecf20Sopenharmony_ci		 * without appearing to create any others.
1728c2ecf20Sopenharmony_ci		 */
1738c2ecf20Sopenharmony_ci		if (likely(!tp->repair)) {
1748c2ecf20Sopenharmony_ci			u32 seq = tcptw->tw_snd_nxt + 65535 + 2;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci			if (!seq)
1778c2ecf20Sopenharmony_ci				seq = 1;
1788c2ecf20Sopenharmony_ci			WRITE_ONCE(tp->write_seq, seq);
1798c2ecf20Sopenharmony_ci			tp->rx_opt.ts_recent	   = tcptw->tw_ts_recent;
1808c2ecf20Sopenharmony_ci			tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
1818c2ecf20Sopenharmony_ci		}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci		return 1;
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	return 0;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tcp_twsk_unique);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic int tcp_v4_pre_connect(struct sock *sk, struct sockaddr *uaddr,
1918c2ecf20Sopenharmony_ci			      int addr_len)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	/* This check is replicated from tcp_v4_connect() and intended to
1948c2ecf20Sopenharmony_ci	 * prevent BPF program called below from accessing bytes that are out
1958c2ecf20Sopenharmony_ci	 * of the bound specified by user in addr_len.
1968c2ecf20Sopenharmony_ci	 */
1978c2ecf20Sopenharmony_ci	if (addr_len < sizeof(struct sockaddr_in))
1988c2ecf20Sopenharmony_ci		return -EINVAL;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	sock_owned_by_me(sk);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	return BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/* This will initiate an outgoing connection. */
2068c2ecf20Sopenharmony_ciint tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
2098c2ecf20Sopenharmony_ci	struct inet_sock *inet = inet_sk(sk);
2108c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
2118c2ecf20Sopenharmony_ci	__be16 orig_sport, orig_dport;
2128c2ecf20Sopenharmony_ci	__be32 daddr, nexthop;
2138c2ecf20Sopenharmony_ci	struct flowi4 *fl4;
2148c2ecf20Sopenharmony_ci	struct rtable *rt;
2158c2ecf20Sopenharmony_ci	int err;
2168c2ecf20Sopenharmony_ci	struct ip_options_rcu *inet_opt;
2178c2ecf20Sopenharmony_ci	struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (addr_len < sizeof(struct sockaddr_in))
2208c2ecf20Sopenharmony_ci		return -EINVAL;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	if (usin->sin_family != AF_INET)
2238c2ecf20Sopenharmony_ci		return -EAFNOSUPPORT;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	nexthop = daddr = usin->sin_addr.s_addr;
2268c2ecf20Sopenharmony_ci	inet_opt = rcu_dereference_protected(inet->inet_opt,
2278c2ecf20Sopenharmony_ci					     lockdep_sock_is_held(sk));
2288c2ecf20Sopenharmony_ci	if (inet_opt && inet_opt->opt.srr) {
2298c2ecf20Sopenharmony_ci		if (!daddr)
2308c2ecf20Sopenharmony_ci			return -EINVAL;
2318c2ecf20Sopenharmony_ci		nexthop = inet_opt->opt.faddr;
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	orig_sport = inet->inet_sport;
2358c2ecf20Sopenharmony_ci	orig_dport = usin->sin_port;
2368c2ecf20Sopenharmony_ci	fl4 = &inet->cork.fl.u.ip4;
2378c2ecf20Sopenharmony_ci	rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
2388c2ecf20Sopenharmony_ci			      RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
2398c2ecf20Sopenharmony_ci			      IPPROTO_TCP,
2408c2ecf20Sopenharmony_ci			      orig_sport, orig_dport, sk);
2418c2ecf20Sopenharmony_ci	if (IS_ERR(rt)) {
2428c2ecf20Sopenharmony_ci		err = PTR_ERR(rt);
2438c2ecf20Sopenharmony_ci		if (err == -ENETUNREACH)
2448c2ecf20Sopenharmony_ci			IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
2458c2ecf20Sopenharmony_ci		return err;
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
2498c2ecf20Sopenharmony_ci		ip_rt_put(rt);
2508c2ecf20Sopenharmony_ci		return -ENETUNREACH;
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	if (!inet_opt || !inet_opt->opt.srr)
2548c2ecf20Sopenharmony_ci		daddr = fl4->daddr;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (!inet->inet_saddr)
2578c2ecf20Sopenharmony_ci		inet->inet_saddr = fl4->saddr;
2588c2ecf20Sopenharmony_ci	sk_rcv_saddr_set(sk, inet->inet_saddr);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) {
2618c2ecf20Sopenharmony_ci		/* Reset inherited state */
2628c2ecf20Sopenharmony_ci		tp->rx_opt.ts_recent	   = 0;
2638c2ecf20Sopenharmony_ci		tp->rx_opt.ts_recent_stamp = 0;
2648c2ecf20Sopenharmony_ci		if (likely(!tp->repair))
2658c2ecf20Sopenharmony_ci			WRITE_ONCE(tp->write_seq, 0);
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	inet->inet_dport = usin->sin_port;
2698c2ecf20Sopenharmony_ci	sk_daddr_set(sk, daddr);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	inet_csk(sk)->icsk_ext_hdr_len = 0;
2728c2ecf20Sopenharmony_ci	if (inet_opt)
2738c2ecf20Sopenharmony_ci		inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	/* Socket identity is still unknown (sport may be zero).
2788c2ecf20Sopenharmony_ci	 * However we set state to SYN-SENT and not releasing socket
2798c2ecf20Sopenharmony_ci	 * lock select source port, enter ourselves into the hash tables and
2808c2ecf20Sopenharmony_ci	 * complete initialization after this.
2818c2ecf20Sopenharmony_ci	 */
2828c2ecf20Sopenharmony_ci	tcp_set_state(sk, TCP_SYN_SENT);
2838c2ecf20Sopenharmony_ci	err = inet_hash_connect(tcp_death_row, sk);
2848c2ecf20Sopenharmony_ci	if (err)
2858c2ecf20Sopenharmony_ci		goto failure;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	sk_set_txhash(sk);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
2908c2ecf20Sopenharmony_ci			       inet->inet_sport, inet->inet_dport, sk);
2918c2ecf20Sopenharmony_ci	if (IS_ERR(rt)) {
2928c2ecf20Sopenharmony_ci		err = PTR_ERR(rt);
2938c2ecf20Sopenharmony_ci		rt = NULL;
2948c2ecf20Sopenharmony_ci		goto failure;
2958c2ecf20Sopenharmony_ci	}
2968c2ecf20Sopenharmony_ci	/* OK, now commit destination to socket.  */
2978c2ecf20Sopenharmony_ci	sk->sk_gso_type = SKB_GSO_TCPV4;
2988c2ecf20Sopenharmony_ci	sk_setup_caps(sk, &rt->dst);
2998c2ecf20Sopenharmony_ci	rt = NULL;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	if (likely(!tp->repair)) {
3028c2ecf20Sopenharmony_ci		if (!tp->write_seq)
3038c2ecf20Sopenharmony_ci			WRITE_ONCE(tp->write_seq,
3048c2ecf20Sopenharmony_ci				   secure_tcp_seq(inet->inet_saddr,
3058c2ecf20Sopenharmony_ci						  inet->inet_daddr,
3068c2ecf20Sopenharmony_ci						  inet->inet_sport,
3078c2ecf20Sopenharmony_ci						  usin->sin_port));
3088c2ecf20Sopenharmony_ci		tp->tsoffset = secure_tcp_ts_off(sock_net(sk),
3098c2ecf20Sopenharmony_ci						 inet->inet_saddr,
3108c2ecf20Sopenharmony_ci						 inet->inet_daddr);
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	inet->inet_id = prandom_u32();
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	if (tcp_fastopen_defer_connect(sk, &err))
3168c2ecf20Sopenharmony_ci		return err;
3178c2ecf20Sopenharmony_ci	if (err)
3188c2ecf20Sopenharmony_ci		goto failure;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	err = tcp_connect(sk);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (err)
3238c2ecf20Sopenharmony_ci		goto failure;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	return 0;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_cifailure:
3288c2ecf20Sopenharmony_ci	/*
3298c2ecf20Sopenharmony_ci	 * This unhashes the socket and releases the local port,
3308c2ecf20Sopenharmony_ci	 * if necessary.
3318c2ecf20Sopenharmony_ci	 */
3328c2ecf20Sopenharmony_ci	tcp_set_state(sk, TCP_CLOSE);
3338c2ecf20Sopenharmony_ci	if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
3348c2ecf20Sopenharmony_ci		inet_reset_saddr(sk);
3358c2ecf20Sopenharmony_ci	ip_rt_put(rt);
3368c2ecf20Sopenharmony_ci	sk->sk_route_caps = 0;
3378c2ecf20Sopenharmony_ci	inet->inet_dport = 0;
3388c2ecf20Sopenharmony_ci	return err;
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_connect);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci/*
3438c2ecf20Sopenharmony_ci * This routine reacts to ICMP_FRAG_NEEDED mtu indications as defined in RFC1191.
3448c2ecf20Sopenharmony_ci * It can be called through tcp_release_cb() if socket was owned by user
3458c2ecf20Sopenharmony_ci * at the time tcp_v4_err() was called to handle ICMP message.
3468c2ecf20Sopenharmony_ci */
3478c2ecf20Sopenharmony_civoid tcp_v4_mtu_reduced(struct sock *sk)
3488c2ecf20Sopenharmony_ci{
3498c2ecf20Sopenharmony_ci	struct inet_sock *inet = inet_sk(sk);
3508c2ecf20Sopenharmony_ci	struct dst_entry *dst;
3518c2ecf20Sopenharmony_ci	u32 mtu;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
3548c2ecf20Sopenharmony_ci		return;
3558c2ecf20Sopenharmony_ci	mtu = READ_ONCE(tcp_sk(sk)->mtu_info);
3568c2ecf20Sopenharmony_ci	dst = inet_csk_update_pmtu(sk, mtu);
3578c2ecf20Sopenharmony_ci	if (!dst)
3588c2ecf20Sopenharmony_ci		return;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	/* Something is about to be wrong... Remember soft error
3618c2ecf20Sopenharmony_ci	 * for the case, if this connection will not able to recover.
3628c2ecf20Sopenharmony_ci	 */
3638c2ecf20Sopenharmony_ci	if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
3648c2ecf20Sopenharmony_ci		sk->sk_err_soft = EMSGSIZE;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	mtu = dst_mtu(dst);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	if (inet->pmtudisc != IP_PMTUDISC_DONT &&
3698c2ecf20Sopenharmony_ci	    ip_sk_accept_pmtu(sk) &&
3708c2ecf20Sopenharmony_ci	    inet_csk(sk)->icsk_pmtu_cookie > mtu) {
3718c2ecf20Sopenharmony_ci		tcp_sync_mss(sk, mtu);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		/* Resend the TCP packet because it's
3748c2ecf20Sopenharmony_ci		 * clear that the old packet has been
3758c2ecf20Sopenharmony_ci		 * dropped. This is the new "fast" path mtu
3768c2ecf20Sopenharmony_ci		 * discovery.
3778c2ecf20Sopenharmony_ci		 */
3788c2ecf20Sopenharmony_ci		tcp_simple_retransmit(sk);
3798c2ecf20Sopenharmony_ci	} /* else let the usual retransmit timer handle it */
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_mtu_reduced);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_cistatic void do_redirect(struct sk_buff *skb, struct sock *sk)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	struct dst_entry *dst = __sk_dst_check(sk, 0);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	if (dst)
3888c2ecf20Sopenharmony_ci		dst->ops->redirect(dst, sk, skb);
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci/* handle ICMP messages on TCP_NEW_SYN_RECV request sockets */
3938c2ecf20Sopenharmony_civoid tcp_req_err(struct sock *sk, u32 seq, bool abort)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	struct request_sock *req = inet_reqsk(sk);
3968c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	/* ICMPs are not backlogged, hence we cannot get
3998c2ecf20Sopenharmony_ci	 * an established socket here.
4008c2ecf20Sopenharmony_ci	 */
4018c2ecf20Sopenharmony_ci	if (seq != tcp_rsk(req)->snt_isn) {
4028c2ecf20Sopenharmony_ci		__NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
4038c2ecf20Sopenharmony_ci	} else if (abort) {
4048c2ecf20Sopenharmony_ci		/*
4058c2ecf20Sopenharmony_ci		 * Still in SYN_RECV, just remove it silently.
4068c2ecf20Sopenharmony_ci		 * There is no good way to pass the error to the newly
4078c2ecf20Sopenharmony_ci		 * created socket, and POSIX does not want network
4088c2ecf20Sopenharmony_ci		 * errors returned from accept().
4098c2ecf20Sopenharmony_ci		 */
4108c2ecf20Sopenharmony_ci		inet_csk_reqsk_queue_drop(req->rsk_listener, req);
4118c2ecf20Sopenharmony_ci		tcp_listendrop(req->rsk_listener);
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci	reqsk_put(req);
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_req_err);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci/* TCP-LD (RFC 6069) logic */
4188c2ecf20Sopenharmony_civoid tcp_ld_RTO_revert(struct sock *sk, u32 seq)
4198c2ecf20Sopenharmony_ci{
4208c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk = inet_csk(sk);
4218c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
4228c2ecf20Sopenharmony_ci	struct sk_buff *skb;
4238c2ecf20Sopenharmony_ci	s32 remaining;
4248c2ecf20Sopenharmony_ci	u32 delta_us;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (sock_owned_by_user(sk))
4278c2ecf20Sopenharmony_ci		return;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	if (seq != tp->snd_una  || !icsk->icsk_retransmits ||
4308c2ecf20Sopenharmony_ci	    !icsk->icsk_backoff)
4318c2ecf20Sopenharmony_ci		return;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	skb = tcp_rtx_queue_head(sk);
4348c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(!skb))
4358c2ecf20Sopenharmony_ci		return;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	icsk->icsk_backoff--;
4388c2ecf20Sopenharmony_ci	icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) : TCP_TIMEOUT_INIT;
4398c2ecf20Sopenharmony_ci	icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	tcp_mstamp_refresh(tp);
4428c2ecf20Sopenharmony_ci	delta_us = (u32)(tp->tcp_mstamp - tcp_skb_timestamp_us(skb));
4438c2ecf20Sopenharmony_ci	remaining = icsk->icsk_rto - usecs_to_jiffies(delta_us);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	if (remaining > 0) {
4468c2ecf20Sopenharmony_ci		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
4478c2ecf20Sopenharmony_ci					  remaining, TCP_RTO_MAX);
4488c2ecf20Sopenharmony_ci	} else {
4498c2ecf20Sopenharmony_ci		/* RTO revert clocked out retransmission.
4508c2ecf20Sopenharmony_ci		 * Will retransmit now.
4518c2ecf20Sopenharmony_ci		 */
4528c2ecf20Sopenharmony_ci		tcp_retransmit_timer(sk);
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_ld_RTO_revert);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci/*
4588c2ecf20Sopenharmony_ci * This routine is called by the ICMP module when it gets some
4598c2ecf20Sopenharmony_ci * sort of error condition.  If err < 0 then the socket should
4608c2ecf20Sopenharmony_ci * be closed and the error returned to the user.  If err > 0
4618c2ecf20Sopenharmony_ci * it's just the icmp type << 8 | icmp code.  After adjustment
4628c2ecf20Sopenharmony_ci * header points to the first 8 bytes of the tcp header.  We need
4638c2ecf20Sopenharmony_ci * to find the appropriate port.
4648c2ecf20Sopenharmony_ci *
4658c2ecf20Sopenharmony_ci * The locking strategy used here is very "optimistic". When
4668c2ecf20Sopenharmony_ci * someone else accesses the socket the ICMP is just dropped
4678c2ecf20Sopenharmony_ci * and for some paths there is no check at all.
4688c2ecf20Sopenharmony_ci * A more general error queue to queue errors for later handling
4698c2ecf20Sopenharmony_ci * is probably better.
4708c2ecf20Sopenharmony_ci *
4718c2ecf20Sopenharmony_ci */
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ciint tcp_v4_err(struct sk_buff *skb, u32 info)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	const struct iphdr *iph = (const struct iphdr *)skb->data;
4768c2ecf20Sopenharmony_ci	struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
4778c2ecf20Sopenharmony_ci	struct tcp_sock *tp;
4788c2ecf20Sopenharmony_ci	struct inet_sock *inet;
4798c2ecf20Sopenharmony_ci	const int type = icmp_hdr(skb)->type;
4808c2ecf20Sopenharmony_ci	const int code = icmp_hdr(skb)->code;
4818c2ecf20Sopenharmony_ci	struct sock *sk;
4828c2ecf20Sopenharmony_ci	struct request_sock *fastopen;
4838c2ecf20Sopenharmony_ci	u32 seq, snd_una;
4848c2ecf20Sopenharmony_ci	int err;
4858c2ecf20Sopenharmony_ci	struct net *net = dev_net(skb->dev);
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	sk = __inet_lookup_established(net, &tcp_hashinfo, iph->daddr,
4888c2ecf20Sopenharmony_ci				       th->dest, iph->saddr, ntohs(th->source),
4898c2ecf20Sopenharmony_ci				       inet_iif(skb), 0);
4908c2ecf20Sopenharmony_ci	if (!sk) {
4918c2ecf20Sopenharmony_ci		__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
4928c2ecf20Sopenharmony_ci		return -ENOENT;
4938c2ecf20Sopenharmony_ci	}
4948c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_TIME_WAIT) {
4958c2ecf20Sopenharmony_ci		inet_twsk_put(inet_twsk(sk));
4968c2ecf20Sopenharmony_ci		return 0;
4978c2ecf20Sopenharmony_ci	}
4988c2ecf20Sopenharmony_ci	seq = ntohl(th->seq);
4998c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_NEW_SYN_RECV) {
5008c2ecf20Sopenharmony_ci		tcp_req_err(sk, seq, type == ICMP_PARAMETERPROB ||
5018c2ecf20Sopenharmony_ci				     type == ICMP_TIME_EXCEEDED ||
5028c2ecf20Sopenharmony_ci				     (type == ICMP_DEST_UNREACH &&
5038c2ecf20Sopenharmony_ci				      (code == ICMP_NET_UNREACH ||
5048c2ecf20Sopenharmony_ci				       code == ICMP_HOST_UNREACH)));
5058c2ecf20Sopenharmony_ci		return 0;
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	bh_lock_sock(sk);
5098c2ecf20Sopenharmony_ci	/* If too many ICMPs get dropped on busy
5108c2ecf20Sopenharmony_ci	 * servers this needs to be solved differently.
5118c2ecf20Sopenharmony_ci	 * We do take care of PMTU discovery (RFC1191) special case :
5128c2ecf20Sopenharmony_ci	 * we can receive locally generated ICMP messages while socket is held.
5138c2ecf20Sopenharmony_ci	 */
5148c2ecf20Sopenharmony_ci	if (sock_owned_by_user(sk)) {
5158c2ecf20Sopenharmony_ci		if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED))
5168c2ecf20Sopenharmony_ci			__NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
5178c2ecf20Sopenharmony_ci	}
5188c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_CLOSE)
5198c2ecf20Sopenharmony_ci		goto out;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
5228c2ecf20Sopenharmony_ci		__NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
5238c2ecf20Sopenharmony_ci		goto out;
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	tp = tcp_sk(sk);
5278c2ecf20Sopenharmony_ci	/* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */
5288c2ecf20Sopenharmony_ci	fastopen = rcu_dereference(tp->fastopen_rsk);
5298c2ecf20Sopenharmony_ci	snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una;
5308c2ecf20Sopenharmony_ci	if (sk->sk_state != TCP_LISTEN &&
5318c2ecf20Sopenharmony_ci	    !between(seq, snd_una, tp->snd_nxt)) {
5328c2ecf20Sopenharmony_ci		__NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
5338c2ecf20Sopenharmony_ci		goto out;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	switch (type) {
5378c2ecf20Sopenharmony_ci	case ICMP_REDIRECT:
5388c2ecf20Sopenharmony_ci		if (!sock_owned_by_user(sk))
5398c2ecf20Sopenharmony_ci			do_redirect(skb, sk);
5408c2ecf20Sopenharmony_ci		goto out;
5418c2ecf20Sopenharmony_ci	case ICMP_SOURCE_QUENCH:
5428c2ecf20Sopenharmony_ci		/* Just silently ignore these. */
5438c2ecf20Sopenharmony_ci		goto out;
5448c2ecf20Sopenharmony_ci	case ICMP_PARAMETERPROB:
5458c2ecf20Sopenharmony_ci		err = EPROTO;
5468c2ecf20Sopenharmony_ci		break;
5478c2ecf20Sopenharmony_ci	case ICMP_DEST_UNREACH:
5488c2ecf20Sopenharmony_ci		if (code > NR_ICMP_UNREACH)
5498c2ecf20Sopenharmony_ci			goto out;
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
5528c2ecf20Sopenharmony_ci			/* We are not interested in TCP_LISTEN and open_requests
5538c2ecf20Sopenharmony_ci			 * (SYN-ACKs send out by Linux are always <576bytes so
5548c2ecf20Sopenharmony_ci			 * they should go through unfragmented).
5558c2ecf20Sopenharmony_ci			 */
5568c2ecf20Sopenharmony_ci			if (sk->sk_state == TCP_LISTEN)
5578c2ecf20Sopenharmony_ci				goto out;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci			WRITE_ONCE(tp->mtu_info, info);
5608c2ecf20Sopenharmony_ci			if (!sock_owned_by_user(sk)) {
5618c2ecf20Sopenharmony_ci				tcp_v4_mtu_reduced(sk);
5628c2ecf20Sopenharmony_ci			} else {
5638c2ecf20Sopenharmony_ci				if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &sk->sk_tsq_flags))
5648c2ecf20Sopenharmony_ci					sock_hold(sk);
5658c2ecf20Sopenharmony_ci			}
5668c2ecf20Sopenharmony_ci			goto out;
5678c2ecf20Sopenharmony_ci		}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci		err = icmp_err_convert[code].errno;
5708c2ecf20Sopenharmony_ci		/* check if this ICMP message allows revert of backoff.
5718c2ecf20Sopenharmony_ci		 * (see RFC 6069)
5728c2ecf20Sopenharmony_ci		 */
5738c2ecf20Sopenharmony_ci		if (!fastopen &&
5748c2ecf20Sopenharmony_ci		    (code == ICMP_NET_UNREACH || code == ICMP_HOST_UNREACH))
5758c2ecf20Sopenharmony_ci			tcp_ld_RTO_revert(sk, seq);
5768c2ecf20Sopenharmony_ci		break;
5778c2ecf20Sopenharmony_ci	case ICMP_TIME_EXCEEDED:
5788c2ecf20Sopenharmony_ci		err = EHOSTUNREACH;
5798c2ecf20Sopenharmony_ci		break;
5808c2ecf20Sopenharmony_ci	default:
5818c2ecf20Sopenharmony_ci		goto out;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	switch (sk->sk_state) {
5858c2ecf20Sopenharmony_ci	case TCP_SYN_SENT:
5868c2ecf20Sopenharmony_ci	case TCP_SYN_RECV:
5878c2ecf20Sopenharmony_ci		/* Only in fast or simultaneous open. If a fast open socket is
5888c2ecf20Sopenharmony_ci		 * already accepted it is treated as a connected one below.
5898c2ecf20Sopenharmony_ci		 */
5908c2ecf20Sopenharmony_ci		if (fastopen && !fastopen->sk)
5918c2ecf20Sopenharmony_ci			break;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci		ip_icmp_error(sk, skb, err, th->dest, info, (u8 *)th);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci		if (!sock_owned_by_user(sk)) {
5968c2ecf20Sopenharmony_ci			sk->sk_err = err;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci			sk->sk_error_report(sk);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci			tcp_done(sk);
6018c2ecf20Sopenharmony_ci		} else {
6028c2ecf20Sopenharmony_ci			sk->sk_err_soft = err;
6038c2ecf20Sopenharmony_ci		}
6048c2ecf20Sopenharmony_ci		goto out;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	/* If we've already connected we will keep trying
6088c2ecf20Sopenharmony_ci	 * until we time out, or the user gives up.
6098c2ecf20Sopenharmony_ci	 *
6108c2ecf20Sopenharmony_ci	 * rfc1122 4.2.3.9 allows to consider as hard errors
6118c2ecf20Sopenharmony_ci	 * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
6128c2ecf20Sopenharmony_ci	 * but it is obsoleted by pmtu discovery).
6138c2ecf20Sopenharmony_ci	 *
6148c2ecf20Sopenharmony_ci	 * Note, that in modern internet, where routing is unreliable
6158c2ecf20Sopenharmony_ci	 * and in each dark corner broken firewalls sit, sending random
6168c2ecf20Sopenharmony_ci	 * errors ordered by their masters even this two messages finally lose
6178c2ecf20Sopenharmony_ci	 * their original sense (even Linux sends invalid PORT_UNREACHs)
6188c2ecf20Sopenharmony_ci	 *
6198c2ecf20Sopenharmony_ci	 * Now we are in compliance with RFCs.
6208c2ecf20Sopenharmony_ci	 *							--ANK (980905)
6218c2ecf20Sopenharmony_ci	 */
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	inet = inet_sk(sk);
6248c2ecf20Sopenharmony_ci	if (!sock_owned_by_user(sk) && inet->recverr) {
6258c2ecf20Sopenharmony_ci		sk->sk_err = err;
6268c2ecf20Sopenharmony_ci		sk->sk_error_report(sk);
6278c2ecf20Sopenharmony_ci	} else	{ /* Only an error on timeout */
6288c2ecf20Sopenharmony_ci		sk->sk_err_soft = err;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ciout:
6328c2ecf20Sopenharmony_ci	bh_unlock_sock(sk);
6338c2ecf20Sopenharmony_ci	sock_put(sk);
6348c2ecf20Sopenharmony_ci	return 0;
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_civoid __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	struct tcphdr *th = tcp_hdr(skb);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0);
6428c2ecf20Sopenharmony_ci	skb->csum_start = skb_transport_header(skb) - skb->head;
6438c2ecf20Sopenharmony_ci	skb->csum_offset = offsetof(struct tcphdr, check);
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci/* This routine computes an IPv4 TCP checksum. */
6478c2ecf20Sopenharmony_civoid tcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	const struct inet_sock *inet = inet_sk(sk);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	__tcp_v4_send_check(skb, inet->inet_saddr, inet->inet_daddr);
6528c2ecf20Sopenharmony_ci}
6538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_send_check);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci/*
6568c2ecf20Sopenharmony_ci *	This routine will send an RST to the other tcp.
6578c2ecf20Sopenharmony_ci *
6588c2ecf20Sopenharmony_ci *	Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
6598c2ecf20Sopenharmony_ci *		      for reset.
6608c2ecf20Sopenharmony_ci *	Answer: if a packet caused RST, it is not for a socket
6618c2ecf20Sopenharmony_ci *		existing in our system, if it is matched to a socket,
6628c2ecf20Sopenharmony_ci *		it is just duplicate segment or bug in other side's TCP.
6638c2ecf20Sopenharmony_ci *		So that we build reply only basing on parameters
6648c2ecf20Sopenharmony_ci *		arrived with segment.
6658c2ecf20Sopenharmony_ci *	Exception: precedence violation. We do not implement it in any case.
6668c2ecf20Sopenharmony_ci */
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
6698c2ecf20Sopenharmony_ci{
6708c2ecf20Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
6718c2ecf20Sopenharmony_ci	struct {
6728c2ecf20Sopenharmony_ci		struct tcphdr th;
6738c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
6748c2ecf20Sopenharmony_ci		__be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
6758c2ecf20Sopenharmony_ci#endif
6768c2ecf20Sopenharmony_ci	} rep;
6778c2ecf20Sopenharmony_ci	struct ip_reply_arg arg;
6788c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
6798c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key = NULL;
6808c2ecf20Sopenharmony_ci	const __u8 *hash_location = NULL;
6818c2ecf20Sopenharmony_ci	unsigned char newhash[16];
6828c2ecf20Sopenharmony_ci	int genhash;
6838c2ecf20Sopenharmony_ci	struct sock *sk1 = NULL;
6848c2ecf20Sopenharmony_ci#endif
6858c2ecf20Sopenharmony_ci	u64 transmit_time = 0;
6868c2ecf20Sopenharmony_ci	struct sock *ctl_sk;
6878c2ecf20Sopenharmony_ci	struct net *net;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	/* Never send a reset in response to a reset. */
6908c2ecf20Sopenharmony_ci	if (th->rst)
6918c2ecf20Sopenharmony_ci		return;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	/* If sk not NULL, it means we did a successful lookup and incoming
6948c2ecf20Sopenharmony_ci	 * route had to be correct. prequeue might have dropped our dst.
6958c2ecf20Sopenharmony_ci	 */
6968c2ecf20Sopenharmony_ci	if (!sk && skb_rtable(skb)->rt_type != RTN_LOCAL)
6978c2ecf20Sopenharmony_ci		return;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	/* Swap the send and the receive. */
7008c2ecf20Sopenharmony_ci	memset(&rep, 0, sizeof(rep));
7018c2ecf20Sopenharmony_ci	rep.th.dest   = th->source;
7028c2ecf20Sopenharmony_ci	rep.th.source = th->dest;
7038c2ecf20Sopenharmony_ci	rep.th.doff   = sizeof(struct tcphdr) / 4;
7048c2ecf20Sopenharmony_ci	rep.th.rst    = 1;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	if (th->ack) {
7078c2ecf20Sopenharmony_ci		rep.th.seq = th->ack_seq;
7088c2ecf20Sopenharmony_ci	} else {
7098c2ecf20Sopenharmony_ci		rep.th.ack = 1;
7108c2ecf20Sopenharmony_ci		rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
7118c2ecf20Sopenharmony_ci				       skb->len - (th->doff << 2));
7128c2ecf20Sopenharmony_ci	}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	memset(&arg, 0, sizeof(arg));
7158c2ecf20Sopenharmony_ci	arg.iov[0].iov_base = (unsigned char *)&rep;
7168c2ecf20Sopenharmony_ci	arg.iov[0].iov_len  = sizeof(rep.th);
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
7198c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
7208c2ecf20Sopenharmony_ci	rcu_read_lock();
7218c2ecf20Sopenharmony_ci	hash_location = tcp_parse_md5sig_option(th);
7228c2ecf20Sopenharmony_ci	if (sk && sk_fullsock(sk)) {
7238c2ecf20Sopenharmony_ci		const union tcp_md5_addr *addr;
7248c2ecf20Sopenharmony_ci		int l3index;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci		/* sdif set, means packet ingressed via a device
7278c2ecf20Sopenharmony_ci		 * in an L3 domain and inet_iif is set to it.
7288c2ecf20Sopenharmony_ci		 */
7298c2ecf20Sopenharmony_ci		l3index = tcp_v4_sdif(skb) ? inet_iif(skb) : 0;
7308c2ecf20Sopenharmony_ci		addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr;
7318c2ecf20Sopenharmony_ci		key = tcp_md5_do_lookup(sk, l3index, addr, AF_INET);
7328c2ecf20Sopenharmony_ci	} else if (hash_location) {
7338c2ecf20Sopenharmony_ci		const union tcp_md5_addr *addr;
7348c2ecf20Sopenharmony_ci		int sdif = tcp_v4_sdif(skb);
7358c2ecf20Sopenharmony_ci		int dif = inet_iif(skb);
7368c2ecf20Sopenharmony_ci		int l3index;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci		/*
7398c2ecf20Sopenharmony_ci		 * active side is lost. Try to find listening socket through
7408c2ecf20Sopenharmony_ci		 * source port, and then find md5 key through listening socket.
7418c2ecf20Sopenharmony_ci		 * we are not loose security here:
7428c2ecf20Sopenharmony_ci		 * Incoming packet is checked with md5 hash with finding key,
7438c2ecf20Sopenharmony_ci		 * no RST generated if md5 hash doesn't match.
7448c2ecf20Sopenharmony_ci		 */
7458c2ecf20Sopenharmony_ci		sk1 = __inet_lookup_listener(net, &tcp_hashinfo, NULL, 0,
7468c2ecf20Sopenharmony_ci					     ip_hdr(skb)->saddr,
7478c2ecf20Sopenharmony_ci					     th->source, ip_hdr(skb)->daddr,
7488c2ecf20Sopenharmony_ci					     ntohs(th->source), dif, sdif);
7498c2ecf20Sopenharmony_ci		/* don't send rst if it can't find key */
7508c2ecf20Sopenharmony_ci		if (!sk1)
7518c2ecf20Sopenharmony_ci			goto out;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci		/* sdif set, means packet ingressed via a device
7548c2ecf20Sopenharmony_ci		 * in an L3 domain and dif is set to it.
7558c2ecf20Sopenharmony_ci		 */
7568c2ecf20Sopenharmony_ci		l3index = sdif ? dif : 0;
7578c2ecf20Sopenharmony_ci		addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr;
7588c2ecf20Sopenharmony_ci		key = tcp_md5_do_lookup(sk1, l3index, addr, AF_INET);
7598c2ecf20Sopenharmony_ci		if (!key)
7608c2ecf20Sopenharmony_ci			goto out;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci		genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb);
7648c2ecf20Sopenharmony_ci		if (genhash || memcmp(hash_location, newhash, 16) != 0)
7658c2ecf20Sopenharmony_ci			goto out;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	if (key) {
7708c2ecf20Sopenharmony_ci		rep.opt[0] = htonl((TCPOPT_NOP << 24) |
7718c2ecf20Sopenharmony_ci				   (TCPOPT_NOP << 16) |
7728c2ecf20Sopenharmony_ci				   (TCPOPT_MD5SIG << 8) |
7738c2ecf20Sopenharmony_ci				   TCPOLEN_MD5SIG);
7748c2ecf20Sopenharmony_ci		/* Update length and the length the header thinks exists */
7758c2ecf20Sopenharmony_ci		arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
7768c2ecf20Sopenharmony_ci		rep.th.doff = arg.iov[0].iov_len / 4;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci		tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1],
7798c2ecf20Sopenharmony_ci				     key, ip_hdr(skb)->saddr,
7808c2ecf20Sopenharmony_ci				     ip_hdr(skb)->daddr, &rep.th);
7818c2ecf20Sopenharmony_ci	}
7828c2ecf20Sopenharmony_ci#endif
7838c2ecf20Sopenharmony_ci	arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
7848c2ecf20Sopenharmony_ci				      ip_hdr(skb)->saddr, /* XXX */
7858c2ecf20Sopenharmony_ci				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
7868c2ecf20Sopenharmony_ci	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
7878c2ecf20Sopenharmony_ci	arg.flags = (sk && inet_sk_transparent(sk)) ? IP_REPLY_ARG_NOSRCCHECK : 0;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	/* When socket is gone, all binding information is lost.
7908c2ecf20Sopenharmony_ci	 * routing might fail in this case. No choice here, if we choose to force
7918c2ecf20Sopenharmony_ci	 * input interface, we will misroute in case of asymmetric route.
7928c2ecf20Sopenharmony_ci	 */
7938c2ecf20Sopenharmony_ci	if (sk) {
7948c2ecf20Sopenharmony_ci		arg.bound_dev_if = sk->sk_bound_dev_if;
7958c2ecf20Sopenharmony_ci		if (sk_fullsock(sk))
7968c2ecf20Sopenharmony_ci			trace_tcp_send_reset(sk, skb);
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) !=
8008c2ecf20Sopenharmony_ci		     offsetof(struct inet_timewait_sock, tw_bound_dev_if));
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	arg.tos = ip_hdr(skb)->tos;
8038c2ecf20Sopenharmony_ci	arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
8048c2ecf20Sopenharmony_ci	local_bh_disable();
8058c2ecf20Sopenharmony_ci	ctl_sk = this_cpu_read(ipv4_tcp_sk);
8068c2ecf20Sopenharmony_ci	sock_net_set(ctl_sk, net);
8078c2ecf20Sopenharmony_ci	if (sk) {
8088c2ecf20Sopenharmony_ci		ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
8098c2ecf20Sopenharmony_ci				   inet_twsk(sk)->tw_mark : sk->sk_mark;
8108c2ecf20Sopenharmony_ci		ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
8118c2ecf20Sopenharmony_ci				   inet_twsk(sk)->tw_priority : sk->sk_priority;
8128c2ecf20Sopenharmony_ci		transmit_time = tcp_transmit_time(sk);
8138c2ecf20Sopenharmony_ci		xfrm_sk_clone_policy(ctl_sk, sk);
8148c2ecf20Sopenharmony_ci	} else {
8158c2ecf20Sopenharmony_ci		ctl_sk->sk_mark = 0;
8168c2ecf20Sopenharmony_ci		ctl_sk->sk_priority = 0;
8178c2ecf20Sopenharmony_ci	}
8188c2ecf20Sopenharmony_ci	ip_send_unicast_reply(ctl_sk,
8198c2ecf20Sopenharmony_ci			      skb, &TCP_SKB_CB(skb)->header.h4.opt,
8208c2ecf20Sopenharmony_ci			      ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
8218c2ecf20Sopenharmony_ci			      &arg, arg.iov[0].iov_len,
8228c2ecf20Sopenharmony_ci			      transmit_time);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	xfrm_sk_free_policy(ctl_sk);
8258c2ecf20Sopenharmony_ci	sock_net_set(ctl_sk, &init_net);
8268c2ecf20Sopenharmony_ci	__TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
8278c2ecf20Sopenharmony_ci	__TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
8288c2ecf20Sopenharmony_ci	local_bh_enable();
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
8318c2ecf20Sopenharmony_ciout:
8328c2ecf20Sopenharmony_ci	rcu_read_unlock();
8338c2ecf20Sopenharmony_ci#endif
8348c2ecf20Sopenharmony_ci}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
8378c2ecf20Sopenharmony_ci   outside socket context is ugly, certainly. What can I do?
8388c2ecf20Sopenharmony_ci */
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_cistatic void tcp_v4_send_ack(const struct sock *sk,
8418c2ecf20Sopenharmony_ci			    struct sk_buff *skb, u32 seq, u32 ack,
8428c2ecf20Sopenharmony_ci			    u32 win, u32 tsval, u32 tsecr, int oif,
8438c2ecf20Sopenharmony_ci			    struct tcp_md5sig_key *key,
8448c2ecf20Sopenharmony_ci			    int reply_flags, u8 tos)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
8478c2ecf20Sopenharmony_ci	struct {
8488c2ecf20Sopenharmony_ci		struct tcphdr th;
8498c2ecf20Sopenharmony_ci		__be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
8508c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
8518c2ecf20Sopenharmony_ci			   + (TCPOLEN_MD5SIG_ALIGNED >> 2)
8528c2ecf20Sopenharmony_ci#endif
8538c2ecf20Sopenharmony_ci			];
8548c2ecf20Sopenharmony_ci	} rep;
8558c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk);
8568c2ecf20Sopenharmony_ci	struct ip_reply_arg arg;
8578c2ecf20Sopenharmony_ci	struct sock *ctl_sk;
8588c2ecf20Sopenharmony_ci	u64 transmit_time;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	memset(&rep.th, 0, sizeof(struct tcphdr));
8618c2ecf20Sopenharmony_ci	memset(&arg, 0, sizeof(arg));
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	arg.iov[0].iov_base = (unsigned char *)&rep;
8648c2ecf20Sopenharmony_ci	arg.iov[0].iov_len  = sizeof(rep.th);
8658c2ecf20Sopenharmony_ci	if (tsecr) {
8668c2ecf20Sopenharmony_ci		rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
8678c2ecf20Sopenharmony_ci				   (TCPOPT_TIMESTAMP << 8) |
8688c2ecf20Sopenharmony_ci				   TCPOLEN_TIMESTAMP);
8698c2ecf20Sopenharmony_ci		rep.opt[1] = htonl(tsval);
8708c2ecf20Sopenharmony_ci		rep.opt[2] = htonl(tsecr);
8718c2ecf20Sopenharmony_ci		arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
8728c2ecf20Sopenharmony_ci	}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	/* Swap the send and the receive. */
8758c2ecf20Sopenharmony_ci	rep.th.dest    = th->source;
8768c2ecf20Sopenharmony_ci	rep.th.source  = th->dest;
8778c2ecf20Sopenharmony_ci	rep.th.doff    = arg.iov[0].iov_len / 4;
8788c2ecf20Sopenharmony_ci	rep.th.seq     = htonl(seq);
8798c2ecf20Sopenharmony_ci	rep.th.ack_seq = htonl(ack);
8808c2ecf20Sopenharmony_ci	rep.th.ack     = 1;
8818c2ecf20Sopenharmony_ci	rep.th.window  = htons(win);
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
8848c2ecf20Sopenharmony_ci	if (key) {
8858c2ecf20Sopenharmony_ci		int offset = (tsecr) ? 3 : 0;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci		rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
8888c2ecf20Sopenharmony_ci					  (TCPOPT_NOP << 16) |
8898c2ecf20Sopenharmony_ci					  (TCPOPT_MD5SIG << 8) |
8908c2ecf20Sopenharmony_ci					  TCPOLEN_MD5SIG);
8918c2ecf20Sopenharmony_ci		arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
8928c2ecf20Sopenharmony_ci		rep.th.doff = arg.iov[0].iov_len/4;
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci		tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[offset],
8958c2ecf20Sopenharmony_ci				    key, ip_hdr(skb)->saddr,
8968c2ecf20Sopenharmony_ci				    ip_hdr(skb)->daddr, &rep.th);
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci#endif
8998c2ecf20Sopenharmony_ci	arg.flags = reply_flags;
9008c2ecf20Sopenharmony_ci	arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
9018c2ecf20Sopenharmony_ci				      ip_hdr(skb)->saddr, /* XXX */
9028c2ecf20Sopenharmony_ci				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
9038c2ecf20Sopenharmony_ci	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
9048c2ecf20Sopenharmony_ci	if (oif)
9058c2ecf20Sopenharmony_ci		arg.bound_dev_if = oif;
9068c2ecf20Sopenharmony_ci	arg.tos = tos;
9078c2ecf20Sopenharmony_ci	arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
9088c2ecf20Sopenharmony_ci	local_bh_disable();
9098c2ecf20Sopenharmony_ci	ctl_sk = this_cpu_read(ipv4_tcp_sk);
9108c2ecf20Sopenharmony_ci	sock_net_set(ctl_sk, net);
9118c2ecf20Sopenharmony_ci	ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
9128c2ecf20Sopenharmony_ci			   inet_twsk(sk)->tw_mark : sk->sk_mark;
9138c2ecf20Sopenharmony_ci	ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
9148c2ecf20Sopenharmony_ci			   inet_twsk(sk)->tw_priority : sk->sk_priority;
9158c2ecf20Sopenharmony_ci	transmit_time = tcp_transmit_time(sk);
9168c2ecf20Sopenharmony_ci	ip_send_unicast_reply(ctl_sk,
9178c2ecf20Sopenharmony_ci			      skb, &TCP_SKB_CB(skb)->header.h4.opt,
9188c2ecf20Sopenharmony_ci			      ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
9198c2ecf20Sopenharmony_ci			      &arg, arg.iov[0].iov_len,
9208c2ecf20Sopenharmony_ci			      transmit_time);
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	sock_net_set(ctl_sk, &init_net);
9238c2ecf20Sopenharmony_ci	__TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
9248c2ecf20Sopenharmony_ci	local_bh_enable();
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	struct inet_timewait_sock *tw = inet_twsk(sk);
9308c2ecf20Sopenharmony_ci	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	tcp_v4_send_ack(sk, skb,
9338c2ecf20Sopenharmony_ci			tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
9348c2ecf20Sopenharmony_ci			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
9358c2ecf20Sopenharmony_ci			tcp_time_stamp_raw() + tcptw->tw_ts_offset,
9368c2ecf20Sopenharmony_ci			tcptw->tw_ts_recent,
9378c2ecf20Sopenharmony_ci			tw->tw_bound_dev_if,
9388c2ecf20Sopenharmony_ci			tcp_twsk_md5_key(tcptw),
9398c2ecf20Sopenharmony_ci			tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0,
9408c2ecf20Sopenharmony_ci			tw->tw_tos
9418c2ecf20Sopenharmony_ci			);
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci	inet_twsk_put(tw);
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cistatic void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
9478c2ecf20Sopenharmony_ci				  struct request_sock *req)
9488c2ecf20Sopenharmony_ci{
9498c2ecf20Sopenharmony_ci	const union tcp_md5_addr *addr;
9508c2ecf20Sopenharmony_ci	int l3index;
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
9538c2ecf20Sopenharmony_ci	 * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
9548c2ecf20Sopenharmony_ci	 */
9558c2ecf20Sopenharmony_ci	u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
9568c2ecf20Sopenharmony_ci					     tcp_sk(sk)->snd_nxt;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	/* RFC 7323 2.3
9598c2ecf20Sopenharmony_ci	 * The window field (SEG.WND) of every outgoing segment, with the
9608c2ecf20Sopenharmony_ci	 * exception of <SYN> segments, MUST be right-shifted by
9618c2ecf20Sopenharmony_ci	 * Rcv.Wind.Shift bits:
9628c2ecf20Sopenharmony_ci	 */
9638c2ecf20Sopenharmony_ci	addr = (union tcp_md5_addr *)&ip_hdr(skb)->saddr;
9648c2ecf20Sopenharmony_ci	l3index = tcp_v4_sdif(skb) ? inet_iif(skb) : 0;
9658c2ecf20Sopenharmony_ci	tcp_v4_send_ack(sk, skb, seq,
9668c2ecf20Sopenharmony_ci			tcp_rsk(req)->rcv_nxt,
9678c2ecf20Sopenharmony_ci			req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
9688c2ecf20Sopenharmony_ci			tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
9698c2ecf20Sopenharmony_ci			READ_ONCE(req->ts_recent),
9708c2ecf20Sopenharmony_ci			0,
9718c2ecf20Sopenharmony_ci			tcp_md5_do_lookup(sk, l3index, addr, AF_INET),
9728c2ecf20Sopenharmony_ci			inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
9738c2ecf20Sopenharmony_ci			ip_hdr(skb)->tos);
9748c2ecf20Sopenharmony_ci}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci/*
9778c2ecf20Sopenharmony_ci *	Send a SYN-ACK after having received a SYN.
9788c2ecf20Sopenharmony_ci *	This still operates on a request_sock only, not on a big
9798c2ecf20Sopenharmony_ci *	socket.
9808c2ecf20Sopenharmony_ci */
9818c2ecf20Sopenharmony_cistatic int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
9828c2ecf20Sopenharmony_ci			      struct flowi *fl,
9838c2ecf20Sopenharmony_ci			      struct request_sock *req,
9848c2ecf20Sopenharmony_ci			      struct tcp_fastopen_cookie *foc,
9858c2ecf20Sopenharmony_ci			      enum tcp_synack_type synack_type,
9868c2ecf20Sopenharmony_ci			      struct sk_buff *syn_skb)
9878c2ecf20Sopenharmony_ci{
9888c2ecf20Sopenharmony_ci	const struct inet_request_sock *ireq = inet_rsk(req);
9898c2ecf20Sopenharmony_ci	struct flowi4 fl4;
9908c2ecf20Sopenharmony_ci	int err = -1;
9918c2ecf20Sopenharmony_ci	struct sk_buff *skb;
9928c2ecf20Sopenharmony_ci	u8 tos;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	/* First, grab a route. */
9958c2ecf20Sopenharmony_ci	if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
9968c2ecf20Sopenharmony_ci		return -1;
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	skb = tcp_make_synack(sk, dst, req, foc, synack_type, syn_skb);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	if (skb) {
10018c2ecf20Sopenharmony_ci		__tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci		tos = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_reflect_tos) ?
10048c2ecf20Sopenharmony_ci				(tcp_rsk(req)->syn_tos & ~INET_ECN_MASK) |
10058c2ecf20Sopenharmony_ci				(inet_sk(sk)->tos & INET_ECN_MASK) :
10068c2ecf20Sopenharmony_ci				inet_sk(sk)->tos;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci		if (!INET_ECN_is_capable(tos) &&
10098c2ecf20Sopenharmony_ci		    tcp_bpf_ca_needs_ecn((struct sock *)req))
10108c2ecf20Sopenharmony_ci			tos |= INET_ECN_ECT_0;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci		rcu_read_lock();
10138c2ecf20Sopenharmony_ci		err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
10148c2ecf20Sopenharmony_ci					    ireq->ir_rmt_addr,
10158c2ecf20Sopenharmony_ci					    rcu_dereference(ireq->ireq_opt),
10168c2ecf20Sopenharmony_ci					    tos);
10178c2ecf20Sopenharmony_ci		rcu_read_unlock();
10188c2ecf20Sopenharmony_ci		err = net_xmit_eval(err);
10198c2ecf20Sopenharmony_ci	}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	return err;
10228c2ecf20Sopenharmony_ci}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci/*
10258c2ecf20Sopenharmony_ci *	IPv4 request_sock destructor.
10268c2ecf20Sopenharmony_ci */
10278c2ecf20Sopenharmony_cistatic void tcp_v4_reqsk_destructor(struct request_sock *req)
10288c2ecf20Sopenharmony_ci{
10298c2ecf20Sopenharmony_ci	kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1));
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
10338c2ecf20Sopenharmony_ci/*
10348c2ecf20Sopenharmony_ci * RFC2385 MD5 checksumming requires a mapping of
10358c2ecf20Sopenharmony_ci * IP address->MD5 Key.
10368c2ecf20Sopenharmony_ci * We need to maintain these in the sk structure.
10378c2ecf20Sopenharmony_ci */
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ciDEFINE_STATIC_KEY_FALSE(tcp_md5_needed);
10408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_md5_needed);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_cistatic bool better_md5_match(struct tcp_md5sig_key *old, struct tcp_md5sig_key *new)
10438c2ecf20Sopenharmony_ci{
10448c2ecf20Sopenharmony_ci	if (!old)
10458c2ecf20Sopenharmony_ci		return true;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	/* l3index always overrides non-l3index */
10488c2ecf20Sopenharmony_ci	if (old->l3index && new->l3index == 0)
10498c2ecf20Sopenharmony_ci		return false;
10508c2ecf20Sopenharmony_ci	if (old->l3index == 0 && new->l3index)
10518c2ecf20Sopenharmony_ci		return true;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	return old->prefixlen < new->prefixlen;
10548c2ecf20Sopenharmony_ci}
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci/* Find the Key structure for an address.  */
10578c2ecf20Sopenharmony_cistruct tcp_md5sig_key *__tcp_md5_do_lookup(const struct sock *sk, int l3index,
10588c2ecf20Sopenharmony_ci					   const union tcp_md5_addr *addr,
10598c2ecf20Sopenharmony_ci					   int family)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci	const struct tcp_sock *tp = tcp_sk(sk);
10628c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key;
10638c2ecf20Sopenharmony_ci	const struct tcp_md5sig_info *md5sig;
10648c2ecf20Sopenharmony_ci	__be32 mask;
10658c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *best_match = NULL;
10668c2ecf20Sopenharmony_ci	bool match;
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	/* caller either holds rcu_read_lock() or socket lock */
10698c2ecf20Sopenharmony_ci	md5sig = rcu_dereference_check(tp->md5sig_info,
10708c2ecf20Sopenharmony_ci				       lockdep_sock_is_held(sk));
10718c2ecf20Sopenharmony_ci	if (!md5sig)
10728c2ecf20Sopenharmony_ci		return NULL;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	hlist_for_each_entry_rcu(key, &md5sig->head, node,
10758c2ecf20Sopenharmony_ci				 lockdep_sock_is_held(sk)) {
10768c2ecf20Sopenharmony_ci		if (key->family != family)
10778c2ecf20Sopenharmony_ci			continue;
10788c2ecf20Sopenharmony_ci		if (key->l3index && key->l3index != l3index)
10798c2ecf20Sopenharmony_ci			continue;
10808c2ecf20Sopenharmony_ci		if (family == AF_INET) {
10818c2ecf20Sopenharmony_ci			mask = inet_make_mask(key->prefixlen);
10828c2ecf20Sopenharmony_ci			match = (key->addr.a4.s_addr & mask) ==
10838c2ecf20Sopenharmony_ci				(addr->a4.s_addr & mask);
10848c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
10858c2ecf20Sopenharmony_ci		} else if (family == AF_INET6) {
10868c2ecf20Sopenharmony_ci			match = ipv6_prefix_equal(&key->addr.a6, &addr->a6,
10878c2ecf20Sopenharmony_ci						  key->prefixlen);
10888c2ecf20Sopenharmony_ci#endif
10898c2ecf20Sopenharmony_ci		} else {
10908c2ecf20Sopenharmony_ci			match = false;
10918c2ecf20Sopenharmony_ci		}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci		if (match && better_md5_match(best_match, key))
10948c2ecf20Sopenharmony_ci			best_match = key;
10958c2ecf20Sopenharmony_ci	}
10968c2ecf20Sopenharmony_ci	return best_match;
10978c2ecf20Sopenharmony_ci}
10988c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__tcp_md5_do_lookup);
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_cistatic struct tcp_md5sig_key *tcp_md5_do_lookup_exact(const struct sock *sk,
11018c2ecf20Sopenharmony_ci						      const union tcp_md5_addr *addr,
11028c2ecf20Sopenharmony_ci						      int family, u8 prefixlen,
11038c2ecf20Sopenharmony_ci						      int l3index)
11048c2ecf20Sopenharmony_ci{
11058c2ecf20Sopenharmony_ci	const struct tcp_sock *tp = tcp_sk(sk);
11068c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key;
11078c2ecf20Sopenharmony_ci	unsigned int size = sizeof(struct in_addr);
11088c2ecf20Sopenharmony_ci	const struct tcp_md5sig_info *md5sig;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	/* caller either holds rcu_read_lock() or socket lock */
11118c2ecf20Sopenharmony_ci	md5sig = rcu_dereference_check(tp->md5sig_info,
11128c2ecf20Sopenharmony_ci				       lockdep_sock_is_held(sk));
11138c2ecf20Sopenharmony_ci	if (!md5sig)
11148c2ecf20Sopenharmony_ci		return NULL;
11158c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6)
11168c2ecf20Sopenharmony_ci	if (family == AF_INET6)
11178c2ecf20Sopenharmony_ci		size = sizeof(struct in6_addr);
11188c2ecf20Sopenharmony_ci#endif
11198c2ecf20Sopenharmony_ci	hlist_for_each_entry_rcu(key, &md5sig->head, node,
11208c2ecf20Sopenharmony_ci				 lockdep_sock_is_held(sk)) {
11218c2ecf20Sopenharmony_ci		if (key->family != family)
11228c2ecf20Sopenharmony_ci			continue;
11238c2ecf20Sopenharmony_ci		if (key->l3index != l3index)
11248c2ecf20Sopenharmony_ci			continue;
11258c2ecf20Sopenharmony_ci		if (!memcmp(&key->addr, addr, size) &&
11268c2ecf20Sopenharmony_ci		    key->prefixlen == prefixlen)
11278c2ecf20Sopenharmony_ci			return key;
11288c2ecf20Sopenharmony_ci	}
11298c2ecf20Sopenharmony_ci	return NULL;
11308c2ecf20Sopenharmony_ci}
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_cistruct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
11338c2ecf20Sopenharmony_ci					 const struct sock *addr_sk)
11348c2ecf20Sopenharmony_ci{
11358c2ecf20Sopenharmony_ci	const union tcp_md5_addr *addr;
11368c2ecf20Sopenharmony_ci	int l3index;
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	l3index = l3mdev_master_ifindex_by_index(sock_net(sk),
11398c2ecf20Sopenharmony_ci						 addr_sk->sk_bound_dev_if);
11408c2ecf20Sopenharmony_ci	addr = (const union tcp_md5_addr *)&addr_sk->sk_daddr;
11418c2ecf20Sopenharmony_ci	return tcp_md5_do_lookup(sk, l3index, addr, AF_INET);
11428c2ecf20Sopenharmony_ci}
11438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_md5_lookup);
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci/* This can be called on a newly created socket, from other files */
11468c2ecf20Sopenharmony_ciint tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
11478c2ecf20Sopenharmony_ci		   int family, u8 prefixlen, int l3index,
11488c2ecf20Sopenharmony_ci		   const u8 *newkey, u8 newkeylen, gfp_t gfp)
11498c2ecf20Sopenharmony_ci{
11508c2ecf20Sopenharmony_ci	/* Add Key to the list */
11518c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key;
11528c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
11538c2ecf20Sopenharmony_ci	struct tcp_md5sig_info *md5sig;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen, l3index);
11568c2ecf20Sopenharmony_ci	if (key) {
11578c2ecf20Sopenharmony_ci		/* Pre-existing entry - just update that one.
11588c2ecf20Sopenharmony_ci		 * Note that the key might be used concurrently.
11598c2ecf20Sopenharmony_ci		 * data_race() is telling kcsan that we do not care of
11608c2ecf20Sopenharmony_ci		 * key mismatches, since changing MD5 key on live flows
11618c2ecf20Sopenharmony_ci		 * can lead to packet drops.
11628c2ecf20Sopenharmony_ci		 */
11638c2ecf20Sopenharmony_ci		data_race(memcpy(key->key, newkey, newkeylen));
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci		/* Pairs with READ_ONCE() in tcp_md5_hash_key().
11668c2ecf20Sopenharmony_ci		 * Also note that a reader could catch new key->keylen value
11678c2ecf20Sopenharmony_ci		 * but old key->key[], this is the reason we use __GFP_ZERO
11688c2ecf20Sopenharmony_ci		 * at sock_kmalloc() time below these lines.
11698c2ecf20Sopenharmony_ci		 */
11708c2ecf20Sopenharmony_ci		WRITE_ONCE(key->keylen, newkeylen);
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci		return 0;
11738c2ecf20Sopenharmony_ci	}
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	md5sig = rcu_dereference_protected(tp->md5sig_info,
11768c2ecf20Sopenharmony_ci					   lockdep_sock_is_held(sk));
11778c2ecf20Sopenharmony_ci	if (!md5sig) {
11788c2ecf20Sopenharmony_ci		md5sig = kmalloc(sizeof(*md5sig), gfp);
11798c2ecf20Sopenharmony_ci		if (!md5sig)
11808c2ecf20Sopenharmony_ci			return -ENOMEM;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci		sk_nocaps_add(sk, NETIF_F_GSO_MASK);
11838c2ecf20Sopenharmony_ci		INIT_HLIST_HEAD(&md5sig->head);
11848c2ecf20Sopenharmony_ci		rcu_assign_pointer(tp->md5sig_info, md5sig);
11858c2ecf20Sopenharmony_ci	}
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	key = sock_kmalloc(sk, sizeof(*key), gfp | __GFP_ZERO);
11888c2ecf20Sopenharmony_ci	if (!key)
11898c2ecf20Sopenharmony_ci		return -ENOMEM;
11908c2ecf20Sopenharmony_ci	if (!tcp_alloc_md5sig_pool()) {
11918c2ecf20Sopenharmony_ci		sock_kfree_s(sk, key, sizeof(*key));
11928c2ecf20Sopenharmony_ci		return -ENOMEM;
11938c2ecf20Sopenharmony_ci	}
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	memcpy(key->key, newkey, newkeylen);
11968c2ecf20Sopenharmony_ci	key->keylen = newkeylen;
11978c2ecf20Sopenharmony_ci	key->family = family;
11988c2ecf20Sopenharmony_ci	key->prefixlen = prefixlen;
11998c2ecf20Sopenharmony_ci	key->l3index = l3index;
12008c2ecf20Sopenharmony_ci	memcpy(&key->addr, addr,
12018c2ecf20Sopenharmony_ci	       (family == AF_INET6) ? sizeof(struct in6_addr) :
12028c2ecf20Sopenharmony_ci				      sizeof(struct in_addr));
12038c2ecf20Sopenharmony_ci	hlist_add_head_rcu(&key->node, &md5sig->head);
12048c2ecf20Sopenharmony_ci	return 0;
12058c2ecf20Sopenharmony_ci}
12068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_md5_do_add);
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ciint tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family,
12098c2ecf20Sopenharmony_ci		   u8 prefixlen, int l3index)
12108c2ecf20Sopenharmony_ci{
12118c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen, l3index);
12148c2ecf20Sopenharmony_ci	if (!key)
12158c2ecf20Sopenharmony_ci		return -ENOENT;
12168c2ecf20Sopenharmony_ci	hlist_del_rcu(&key->node);
12178c2ecf20Sopenharmony_ci	atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
12188c2ecf20Sopenharmony_ci	kfree_rcu(key, rcu);
12198c2ecf20Sopenharmony_ci	return 0;
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_md5_do_del);
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_cistatic void tcp_clear_md5_list(struct sock *sk)
12248c2ecf20Sopenharmony_ci{
12258c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
12268c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key;
12278c2ecf20Sopenharmony_ci	struct hlist_node *n;
12288c2ecf20Sopenharmony_ci	struct tcp_md5sig_info *md5sig;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	md5sig = rcu_dereference_protected(tp->md5sig_info, 1);
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	hlist_for_each_entry_safe(key, n, &md5sig->head, node) {
12338c2ecf20Sopenharmony_ci		hlist_del_rcu(&key->node);
12348c2ecf20Sopenharmony_ci		atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
12358c2ecf20Sopenharmony_ci		kfree_rcu(key, rcu);
12368c2ecf20Sopenharmony_ci	}
12378c2ecf20Sopenharmony_ci}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_cistatic int tcp_v4_parse_md5_keys(struct sock *sk, int optname,
12408c2ecf20Sopenharmony_ci				 sockptr_t optval, int optlen)
12418c2ecf20Sopenharmony_ci{
12428c2ecf20Sopenharmony_ci	struct tcp_md5sig cmd;
12438c2ecf20Sopenharmony_ci	struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
12448c2ecf20Sopenharmony_ci	const union tcp_md5_addr *addr;
12458c2ecf20Sopenharmony_ci	u8 prefixlen = 32;
12468c2ecf20Sopenharmony_ci	int l3index = 0;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	if (optlen < sizeof(cmd))
12498c2ecf20Sopenharmony_ci		return -EINVAL;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	if (copy_from_sockptr(&cmd, optval, sizeof(cmd)))
12528c2ecf20Sopenharmony_ci		return -EFAULT;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci	if (sin->sin_family != AF_INET)
12558c2ecf20Sopenharmony_ci		return -EINVAL;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	if (optname == TCP_MD5SIG_EXT &&
12588c2ecf20Sopenharmony_ci	    cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) {
12598c2ecf20Sopenharmony_ci		prefixlen = cmd.tcpm_prefixlen;
12608c2ecf20Sopenharmony_ci		if (prefixlen > 32)
12618c2ecf20Sopenharmony_ci			return -EINVAL;
12628c2ecf20Sopenharmony_ci	}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	if (optname == TCP_MD5SIG_EXT &&
12658c2ecf20Sopenharmony_ci	    cmd.tcpm_flags & TCP_MD5SIG_FLAG_IFINDEX) {
12668c2ecf20Sopenharmony_ci		struct net_device *dev;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci		rcu_read_lock();
12698c2ecf20Sopenharmony_ci		dev = dev_get_by_index_rcu(sock_net(sk), cmd.tcpm_ifindex);
12708c2ecf20Sopenharmony_ci		if (dev && netif_is_l3_master(dev))
12718c2ecf20Sopenharmony_ci			l3index = dev->ifindex;
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci		rcu_read_unlock();
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci		/* ok to reference set/not set outside of rcu;
12768c2ecf20Sopenharmony_ci		 * right now device MUST be an L3 master
12778c2ecf20Sopenharmony_ci		 */
12788c2ecf20Sopenharmony_ci		if (!dev || !l3index)
12798c2ecf20Sopenharmony_ci			return -EINVAL;
12808c2ecf20Sopenharmony_ci	}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	addr = (union tcp_md5_addr *)&sin->sin_addr.s_addr;
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci	if (!cmd.tcpm_keylen)
12858c2ecf20Sopenharmony_ci		return tcp_md5_do_del(sk, addr, AF_INET, prefixlen, l3index);
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
12888c2ecf20Sopenharmony_ci		return -EINVAL;
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	return tcp_md5_do_add(sk, addr, AF_INET, prefixlen, l3index,
12918c2ecf20Sopenharmony_ci			      cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
12928c2ecf20Sopenharmony_ci}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_cistatic int tcp_v4_md5_hash_headers(struct tcp_md5sig_pool *hp,
12958c2ecf20Sopenharmony_ci				   __be32 daddr, __be32 saddr,
12968c2ecf20Sopenharmony_ci				   const struct tcphdr *th, int nbytes)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	struct tcp4_pseudohdr *bp;
12998c2ecf20Sopenharmony_ci	struct scatterlist sg;
13008c2ecf20Sopenharmony_ci	struct tcphdr *_th;
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	bp = hp->scratch;
13038c2ecf20Sopenharmony_ci	bp->saddr = saddr;
13048c2ecf20Sopenharmony_ci	bp->daddr = daddr;
13058c2ecf20Sopenharmony_ci	bp->pad = 0;
13068c2ecf20Sopenharmony_ci	bp->protocol = IPPROTO_TCP;
13078c2ecf20Sopenharmony_ci	bp->len = cpu_to_be16(nbytes);
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci	_th = (struct tcphdr *)(bp + 1);
13108c2ecf20Sopenharmony_ci	memcpy(_th, th, sizeof(*th));
13118c2ecf20Sopenharmony_ci	_th->check = 0;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	sg_init_one(&sg, bp, sizeof(*bp) + sizeof(*th));
13148c2ecf20Sopenharmony_ci	ahash_request_set_crypt(hp->md5_req, &sg, NULL,
13158c2ecf20Sopenharmony_ci				sizeof(*bp) + sizeof(*th));
13168c2ecf20Sopenharmony_ci	return crypto_ahash_update(hp->md5_req);
13178c2ecf20Sopenharmony_ci}
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_cistatic int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
13208c2ecf20Sopenharmony_ci			       __be32 daddr, __be32 saddr, const struct tcphdr *th)
13218c2ecf20Sopenharmony_ci{
13228c2ecf20Sopenharmony_ci	struct tcp_md5sig_pool *hp;
13238c2ecf20Sopenharmony_ci	struct ahash_request *req;
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci	hp = tcp_get_md5sig_pool();
13268c2ecf20Sopenharmony_ci	if (!hp)
13278c2ecf20Sopenharmony_ci		goto clear_hash_noput;
13288c2ecf20Sopenharmony_ci	req = hp->md5_req;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	if (crypto_ahash_init(req))
13318c2ecf20Sopenharmony_ci		goto clear_hash;
13328c2ecf20Sopenharmony_ci	if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, th->doff << 2))
13338c2ecf20Sopenharmony_ci		goto clear_hash;
13348c2ecf20Sopenharmony_ci	if (tcp_md5_hash_key(hp, key))
13358c2ecf20Sopenharmony_ci		goto clear_hash;
13368c2ecf20Sopenharmony_ci	ahash_request_set_crypt(req, NULL, md5_hash, 0);
13378c2ecf20Sopenharmony_ci	if (crypto_ahash_final(req))
13388c2ecf20Sopenharmony_ci		goto clear_hash;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	tcp_put_md5sig_pool();
13418c2ecf20Sopenharmony_ci	return 0;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ciclear_hash:
13448c2ecf20Sopenharmony_ci	tcp_put_md5sig_pool();
13458c2ecf20Sopenharmony_ciclear_hash_noput:
13468c2ecf20Sopenharmony_ci	memset(md5_hash, 0, 16);
13478c2ecf20Sopenharmony_ci	return 1;
13488c2ecf20Sopenharmony_ci}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ciint tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
13518c2ecf20Sopenharmony_ci			const struct sock *sk,
13528c2ecf20Sopenharmony_ci			const struct sk_buff *skb)
13538c2ecf20Sopenharmony_ci{
13548c2ecf20Sopenharmony_ci	struct tcp_md5sig_pool *hp;
13558c2ecf20Sopenharmony_ci	struct ahash_request *req;
13568c2ecf20Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
13578c2ecf20Sopenharmony_ci	__be32 saddr, daddr;
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	if (sk) { /* valid for establish/request sockets */
13608c2ecf20Sopenharmony_ci		saddr = sk->sk_rcv_saddr;
13618c2ecf20Sopenharmony_ci		daddr = sk->sk_daddr;
13628c2ecf20Sopenharmony_ci	} else {
13638c2ecf20Sopenharmony_ci		const struct iphdr *iph = ip_hdr(skb);
13648c2ecf20Sopenharmony_ci		saddr = iph->saddr;
13658c2ecf20Sopenharmony_ci		daddr = iph->daddr;
13668c2ecf20Sopenharmony_ci	}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	hp = tcp_get_md5sig_pool();
13698c2ecf20Sopenharmony_ci	if (!hp)
13708c2ecf20Sopenharmony_ci		goto clear_hash_noput;
13718c2ecf20Sopenharmony_ci	req = hp->md5_req;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (crypto_ahash_init(req))
13748c2ecf20Sopenharmony_ci		goto clear_hash;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, skb->len))
13778c2ecf20Sopenharmony_ci		goto clear_hash;
13788c2ecf20Sopenharmony_ci	if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
13798c2ecf20Sopenharmony_ci		goto clear_hash;
13808c2ecf20Sopenharmony_ci	if (tcp_md5_hash_key(hp, key))
13818c2ecf20Sopenharmony_ci		goto clear_hash;
13828c2ecf20Sopenharmony_ci	ahash_request_set_crypt(req, NULL, md5_hash, 0);
13838c2ecf20Sopenharmony_ci	if (crypto_ahash_final(req))
13848c2ecf20Sopenharmony_ci		goto clear_hash;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	tcp_put_md5sig_pool();
13878c2ecf20Sopenharmony_ci	return 0;
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ciclear_hash:
13908c2ecf20Sopenharmony_ci	tcp_put_md5sig_pool();
13918c2ecf20Sopenharmony_ciclear_hash_noput:
13928c2ecf20Sopenharmony_ci	memset(md5_hash, 0, 16);
13938c2ecf20Sopenharmony_ci	return 1;
13948c2ecf20Sopenharmony_ci}
13958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_md5_hash_skb);
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci#endif
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci/* Called with rcu_read_lock() */
14008c2ecf20Sopenharmony_cistatic bool tcp_v4_inbound_md5_hash(const struct sock *sk,
14018c2ecf20Sopenharmony_ci				    const struct sk_buff *skb,
14028c2ecf20Sopenharmony_ci				    int dif, int sdif)
14038c2ecf20Sopenharmony_ci{
14048c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
14058c2ecf20Sopenharmony_ci	/*
14068c2ecf20Sopenharmony_ci	 * This gets called for each TCP segment that arrives
14078c2ecf20Sopenharmony_ci	 * so we want to be efficient.
14088c2ecf20Sopenharmony_ci	 * We have 3 drop cases:
14098c2ecf20Sopenharmony_ci	 * o No MD5 hash and one expected.
14108c2ecf20Sopenharmony_ci	 * o MD5 hash and we're not expecting one.
14118c2ecf20Sopenharmony_ci	 * o MD5 hash and its wrong.
14128c2ecf20Sopenharmony_ci	 */
14138c2ecf20Sopenharmony_ci	const __u8 *hash_location = NULL;
14148c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *hash_expected;
14158c2ecf20Sopenharmony_ci	const struct iphdr *iph = ip_hdr(skb);
14168c2ecf20Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
14178c2ecf20Sopenharmony_ci	const union tcp_md5_addr *addr;
14188c2ecf20Sopenharmony_ci	unsigned char newhash[16];
14198c2ecf20Sopenharmony_ci	int genhash, l3index;
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	/* sdif set, means packet ingressed via a device
14228c2ecf20Sopenharmony_ci	 * in an L3 domain and dif is set to the l3mdev
14238c2ecf20Sopenharmony_ci	 */
14248c2ecf20Sopenharmony_ci	l3index = sdif ? dif : 0;
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	addr = (union tcp_md5_addr *)&iph->saddr;
14278c2ecf20Sopenharmony_ci	hash_expected = tcp_md5_do_lookup(sk, l3index, addr, AF_INET);
14288c2ecf20Sopenharmony_ci	hash_location = tcp_parse_md5sig_option(th);
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	/* We've parsed the options - do we have a hash? */
14318c2ecf20Sopenharmony_ci	if (!hash_expected && !hash_location)
14328c2ecf20Sopenharmony_ci		return false;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	if (hash_expected && !hash_location) {
14358c2ecf20Sopenharmony_ci		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
14368c2ecf20Sopenharmony_ci		return true;
14378c2ecf20Sopenharmony_ci	}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	if (!hash_expected && hash_location) {
14408c2ecf20Sopenharmony_ci		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
14418c2ecf20Sopenharmony_ci		return true;
14428c2ecf20Sopenharmony_ci	}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	/* Okay, so this is hash_expected and hash_location -
14458c2ecf20Sopenharmony_ci	 * so we need to calculate the checksum.
14468c2ecf20Sopenharmony_ci	 */
14478c2ecf20Sopenharmony_ci	genhash = tcp_v4_md5_hash_skb(newhash,
14488c2ecf20Sopenharmony_ci				      hash_expected,
14498c2ecf20Sopenharmony_ci				      NULL, skb);
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
14528c2ecf20Sopenharmony_ci		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
14538c2ecf20Sopenharmony_ci		net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s L3 index %d\n",
14548c2ecf20Sopenharmony_ci				     &iph->saddr, ntohs(th->source),
14558c2ecf20Sopenharmony_ci				     &iph->daddr, ntohs(th->dest),
14568c2ecf20Sopenharmony_ci				     genhash ? " tcp_v4_calc_md5_hash failed"
14578c2ecf20Sopenharmony_ci				     : "", l3index);
14588c2ecf20Sopenharmony_ci		return true;
14598c2ecf20Sopenharmony_ci	}
14608c2ecf20Sopenharmony_ci	return false;
14618c2ecf20Sopenharmony_ci#endif
14628c2ecf20Sopenharmony_ci	return false;
14638c2ecf20Sopenharmony_ci}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_cistatic void tcp_v4_init_req(struct request_sock *req,
14668c2ecf20Sopenharmony_ci			    const struct sock *sk_listener,
14678c2ecf20Sopenharmony_ci			    struct sk_buff *skb)
14688c2ecf20Sopenharmony_ci{
14698c2ecf20Sopenharmony_ci	struct inet_request_sock *ireq = inet_rsk(req);
14708c2ecf20Sopenharmony_ci	struct net *net = sock_net(sk_listener);
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
14738c2ecf20Sopenharmony_ci	sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
14748c2ecf20Sopenharmony_ci	RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(net, skb));
14758c2ecf20Sopenharmony_ci}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_cistatic struct dst_entry *tcp_v4_route_req(const struct sock *sk,
14788c2ecf20Sopenharmony_ci					  struct flowi *fl,
14798c2ecf20Sopenharmony_ci					  const struct request_sock *req)
14808c2ecf20Sopenharmony_ci{
14818c2ecf20Sopenharmony_ci	return inet_csk_route_req(sk, &fl->u.ip4, req);
14828c2ecf20Sopenharmony_ci}
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_cistruct request_sock_ops tcp_request_sock_ops __read_mostly = {
14858c2ecf20Sopenharmony_ci	.family		=	PF_INET,
14868c2ecf20Sopenharmony_ci	.obj_size	=	sizeof(struct tcp_request_sock),
14878c2ecf20Sopenharmony_ci	.rtx_syn_ack	=	tcp_rtx_synack,
14888c2ecf20Sopenharmony_ci	.send_ack	=	tcp_v4_reqsk_send_ack,
14898c2ecf20Sopenharmony_ci	.destructor	=	tcp_v4_reqsk_destructor,
14908c2ecf20Sopenharmony_ci	.send_reset	=	tcp_v4_send_reset,
14918c2ecf20Sopenharmony_ci	.syn_ack_timeout =	tcp_syn_ack_timeout,
14928c2ecf20Sopenharmony_ci};
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ciconst struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
14958c2ecf20Sopenharmony_ci	.mss_clamp	=	TCP_MSS_DEFAULT,
14968c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
14978c2ecf20Sopenharmony_ci	.req_md5_lookup	=	tcp_v4_md5_lookup,
14988c2ecf20Sopenharmony_ci	.calc_md5_hash	=	tcp_v4_md5_hash_skb,
14998c2ecf20Sopenharmony_ci#endif
15008c2ecf20Sopenharmony_ci	.init_req	=	tcp_v4_init_req,
15018c2ecf20Sopenharmony_ci#ifdef CONFIG_SYN_COOKIES
15028c2ecf20Sopenharmony_ci	.cookie_init_seq =	cookie_v4_init_sequence,
15038c2ecf20Sopenharmony_ci#endif
15048c2ecf20Sopenharmony_ci	.route_req	=	tcp_v4_route_req,
15058c2ecf20Sopenharmony_ci	.init_seq	=	tcp_v4_init_seq,
15068c2ecf20Sopenharmony_ci	.init_ts_off	=	tcp_v4_init_ts_off,
15078c2ecf20Sopenharmony_ci	.send_synack	=	tcp_v4_send_synack,
15088c2ecf20Sopenharmony_ci};
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ciint tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
15118c2ecf20Sopenharmony_ci{
15128c2ecf20Sopenharmony_ci	/* Never answer to SYNs send to broadcast or multicast */
15138c2ecf20Sopenharmony_ci	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
15148c2ecf20Sopenharmony_ci		goto drop;
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	return tcp_conn_request(&tcp_request_sock_ops,
15178c2ecf20Sopenharmony_ci				&tcp_request_sock_ipv4_ops, sk, skb);
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_cidrop:
15208c2ecf20Sopenharmony_ci	tcp_listendrop(sk);
15218c2ecf20Sopenharmony_ci	return 0;
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_conn_request);
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci/*
15278c2ecf20Sopenharmony_ci * The three way handshake has completed - we got a valid synack -
15288c2ecf20Sopenharmony_ci * now create the new socket.
15298c2ecf20Sopenharmony_ci */
15308c2ecf20Sopenharmony_cistruct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
15318c2ecf20Sopenharmony_ci				  struct request_sock *req,
15328c2ecf20Sopenharmony_ci				  struct dst_entry *dst,
15338c2ecf20Sopenharmony_ci				  struct request_sock *req_unhash,
15348c2ecf20Sopenharmony_ci				  bool *own_req)
15358c2ecf20Sopenharmony_ci{
15368c2ecf20Sopenharmony_ci	struct inet_request_sock *ireq;
15378c2ecf20Sopenharmony_ci	bool found_dup_sk = false;
15388c2ecf20Sopenharmony_ci	struct inet_sock *newinet;
15398c2ecf20Sopenharmony_ci	struct tcp_sock *newtp;
15408c2ecf20Sopenharmony_ci	struct sock *newsk;
15418c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
15428c2ecf20Sopenharmony_ci	const union tcp_md5_addr *addr;
15438c2ecf20Sopenharmony_ci	struct tcp_md5sig_key *key;
15448c2ecf20Sopenharmony_ci	int l3index;
15458c2ecf20Sopenharmony_ci#endif
15468c2ecf20Sopenharmony_ci	struct ip_options_rcu *inet_opt;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	if (sk_acceptq_is_full(sk))
15498c2ecf20Sopenharmony_ci		goto exit_overflow;
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	newsk = tcp_create_openreq_child(sk, req, skb);
15528c2ecf20Sopenharmony_ci	if (!newsk)
15538c2ecf20Sopenharmony_ci		goto exit_nonewsk;
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	newsk->sk_gso_type = SKB_GSO_TCPV4;
15568c2ecf20Sopenharmony_ci	inet_sk_rx_dst_set(newsk, skb);
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci	newtp		      = tcp_sk(newsk);
15598c2ecf20Sopenharmony_ci	newinet		      = inet_sk(newsk);
15608c2ecf20Sopenharmony_ci	ireq		      = inet_rsk(req);
15618c2ecf20Sopenharmony_ci	sk_daddr_set(newsk, ireq->ir_rmt_addr);
15628c2ecf20Sopenharmony_ci	sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
15638c2ecf20Sopenharmony_ci	newsk->sk_bound_dev_if = ireq->ir_iif;
15648c2ecf20Sopenharmony_ci	newinet->inet_saddr   = ireq->ir_loc_addr;
15658c2ecf20Sopenharmony_ci	inet_opt	      = rcu_dereference(ireq->ireq_opt);
15668c2ecf20Sopenharmony_ci	RCU_INIT_POINTER(newinet->inet_opt, inet_opt);
15678c2ecf20Sopenharmony_ci	newinet->mc_index     = inet_iif(skb);
15688c2ecf20Sopenharmony_ci	newinet->mc_ttl	      = ip_hdr(skb)->ttl;
15698c2ecf20Sopenharmony_ci	newinet->rcv_tos      = ip_hdr(skb)->tos;
15708c2ecf20Sopenharmony_ci	inet_csk(newsk)->icsk_ext_hdr_len = 0;
15718c2ecf20Sopenharmony_ci	if (inet_opt)
15728c2ecf20Sopenharmony_ci		inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
15738c2ecf20Sopenharmony_ci	newinet->inet_id = prandom_u32();
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	/* Set ToS of the new socket based upon the value of incoming SYN.
15768c2ecf20Sopenharmony_ci	 * ECT bits are set later in tcp_init_transfer().
15778c2ecf20Sopenharmony_ci	 */
15788c2ecf20Sopenharmony_ci	if (READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_reflect_tos))
15798c2ecf20Sopenharmony_ci		newinet->tos = tcp_rsk(req)->syn_tos & ~INET_ECN_MASK;
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	if (!dst) {
15828c2ecf20Sopenharmony_ci		dst = inet_csk_route_child_sock(sk, newsk, req);
15838c2ecf20Sopenharmony_ci		if (!dst)
15848c2ecf20Sopenharmony_ci			goto put_and_exit;
15858c2ecf20Sopenharmony_ci	} else {
15868c2ecf20Sopenharmony_ci		/* syncookie case : see end of cookie_v4_check() */
15878c2ecf20Sopenharmony_ci	}
15888c2ecf20Sopenharmony_ci	sk_setup_caps(newsk, dst);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	tcp_ca_openreq_child(newsk, dst);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	tcp_sync_mss(newsk, dst_mtu(dst));
15938c2ecf20Sopenharmony_ci	newtp->advmss = tcp_mss_clamp(tcp_sk(sk), dst_metric_advmss(dst));
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	tcp_initialize_rcv_mss(newsk);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
15988c2ecf20Sopenharmony_ci	l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif);
15998c2ecf20Sopenharmony_ci	/* Copy over the MD5 key from the original socket */
16008c2ecf20Sopenharmony_ci	addr = (union tcp_md5_addr *)&newinet->inet_daddr;
16018c2ecf20Sopenharmony_ci	key = tcp_md5_do_lookup(sk, l3index, addr, AF_INET);
16028c2ecf20Sopenharmony_ci	if (key) {
16038c2ecf20Sopenharmony_ci		/*
16048c2ecf20Sopenharmony_ci		 * We're using one, so create a matching key
16058c2ecf20Sopenharmony_ci		 * on the newsk structure. If we fail to get
16068c2ecf20Sopenharmony_ci		 * memory, then we end up not copying the key
16078c2ecf20Sopenharmony_ci		 * across. Shucks.
16088c2ecf20Sopenharmony_ci		 */
16098c2ecf20Sopenharmony_ci		tcp_md5_do_add(newsk, addr, AF_INET, 32, l3index,
16108c2ecf20Sopenharmony_ci			       key->key, key->keylen, GFP_ATOMIC);
16118c2ecf20Sopenharmony_ci		sk_nocaps_add(newsk, NETIF_F_GSO_MASK);
16128c2ecf20Sopenharmony_ci	}
16138c2ecf20Sopenharmony_ci#endif
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci	if (__inet_inherit_port(sk, newsk) < 0)
16168c2ecf20Sopenharmony_ci		goto put_and_exit;
16178c2ecf20Sopenharmony_ci	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash),
16188c2ecf20Sopenharmony_ci				       &found_dup_sk);
16198c2ecf20Sopenharmony_ci	if (likely(*own_req)) {
16208c2ecf20Sopenharmony_ci		tcp_move_syn(newtp, req);
16218c2ecf20Sopenharmony_ci		ireq->ireq_opt = NULL;
16228c2ecf20Sopenharmony_ci	} else {
16238c2ecf20Sopenharmony_ci		newinet->inet_opt = NULL;
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci		if (!req_unhash && found_dup_sk) {
16268c2ecf20Sopenharmony_ci			/* This code path should only be executed in the
16278c2ecf20Sopenharmony_ci			 * syncookie case only
16288c2ecf20Sopenharmony_ci			 */
16298c2ecf20Sopenharmony_ci			bh_unlock_sock(newsk);
16308c2ecf20Sopenharmony_ci			sock_put(newsk);
16318c2ecf20Sopenharmony_ci			newsk = NULL;
16328c2ecf20Sopenharmony_ci		}
16338c2ecf20Sopenharmony_ci	}
16348c2ecf20Sopenharmony_ci	return newsk;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ciexit_overflow:
16378c2ecf20Sopenharmony_ci	NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
16388c2ecf20Sopenharmony_ciexit_nonewsk:
16398c2ecf20Sopenharmony_ci	dst_release(dst);
16408c2ecf20Sopenharmony_ciexit:
16418c2ecf20Sopenharmony_ci	tcp_listendrop(sk);
16428c2ecf20Sopenharmony_ci	return NULL;
16438c2ecf20Sopenharmony_ciput_and_exit:
16448c2ecf20Sopenharmony_ci	newinet->inet_opt = NULL;
16458c2ecf20Sopenharmony_ci	inet_csk_prepare_forced_close(newsk);
16468c2ecf20Sopenharmony_ci	tcp_done(newsk);
16478c2ecf20Sopenharmony_ci	goto exit;
16488c2ecf20Sopenharmony_ci}
16498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_syn_recv_sock);
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_cistatic struct sock *tcp_v4_cookie_check(struct sock *sk, struct sk_buff *skb)
16528c2ecf20Sopenharmony_ci{
16538c2ecf20Sopenharmony_ci#ifdef CONFIG_SYN_COOKIES
16548c2ecf20Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	if (!th->syn)
16578c2ecf20Sopenharmony_ci		sk = cookie_v4_check(sk, skb);
16588c2ecf20Sopenharmony_ci#endif
16598c2ecf20Sopenharmony_ci	return sk;
16608c2ecf20Sopenharmony_ci}
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ciu16 tcp_v4_get_syncookie(struct sock *sk, struct iphdr *iph,
16638c2ecf20Sopenharmony_ci			 struct tcphdr *th, u32 *cookie)
16648c2ecf20Sopenharmony_ci{
16658c2ecf20Sopenharmony_ci	u16 mss = 0;
16668c2ecf20Sopenharmony_ci#ifdef CONFIG_SYN_COOKIES
16678c2ecf20Sopenharmony_ci	mss = tcp_get_syncookie_mss(&tcp_request_sock_ops,
16688c2ecf20Sopenharmony_ci				    &tcp_request_sock_ipv4_ops, sk, th);
16698c2ecf20Sopenharmony_ci	if (mss) {
16708c2ecf20Sopenharmony_ci		*cookie = __cookie_v4_init_sequence(iph, th, &mss);
16718c2ecf20Sopenharmony_ci		tcp_synq_overflow(sk);
16728c2ecf20Sopenharmony_ci	}
16738c2ecf20Sopenharmony_ci#endif
16748c2ecf20Sopenharmony_ci	return mss;
16758c2ecf20Sopenharmony_ci}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci/* The socket must have it's spinlock held when we get
16788c2ecf20Sopenharmony_ci * here, unless it is a TCP_LISTEN socket.
16798c2ecf20Sopenharmony_ci *
16808c2ecf20Sopenharmony_ci * We have a potential double-lock case here, so even when
16818c2ecf20Sopenharmony_ci * doing backlog processing we use the BH locking scheme.
16828c2ecf20Sopenharmony_ci * This is because we cannot sleep with the original spinlock
16838c2ecf20Sopenharmony_ci * held.
16848c2ecf20Sopenharmony_ci */
16858c2ecf20Sopenharmony_ciint tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
16868c2ecf20Sopenharmony_ci{
16878c2ecf20Sopenharmony_ci	struct sock *rsk;
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
16908c2ecf20Sopenharmony_ci		struct dst_entry *dst;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci		dst = rcu_dereference_protected(sk->sk_rx_dst,
16938c2ecf20Sopenharmony_ci						lockdep_sock_is_held(sk));
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci		sock_rps_save_rxhash(sk, skb);
16968c2ecf20Sopenharmony_ci		sk_mark_napi_id(sk, skb);
16978c2ecf20Sopenharmony_ci		if (dst) {
16988c2ecf20Sopenharmony_ci			if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
16998c2ecf20Sopenharmony_ci			    !dst->ops->check(dst, 0)) {
17008c2ecf20Sopenharmony_ci				RCU_INIT_POINTER(sk->sk_rx_dst, NULL);
17018c2ecf20Sopenharmony_ci				dst_release(dst);
17028c2ecf20Sopenharmony_ci			}
17038c2ecf20Sopenharmony_ci		}
17048c2ecf20Sopenharmony_ci		tcp_rcv_established(sk, skb);
17058c2ecf20Sopenharmony_ci		return 0;
17068c2ecf20Sopenharmony_ci	}
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	if (tcp_checksum_complete(skb))
17098c2ecf20Sopenharmony_ci		goto csum_err;
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_LISTEN) {
17128c2ecf20Sopenharmony_ci		struct sock *nsk = tcp_v4_cookie_check(sk, skb);
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci		if (!nsk)
17158c2ecf20Sopenharmony_ci			goto discard;
17168c2ecf20Sopenharmony_ci		if (nsk != sk) {
17178c2ecf20Sopenharmony_ci			if (tcp_child_process(sk, nsk, skb)) {
17188c2ecf20Sopenharmony_ci				rsk = nsk;
17198c2ecf20Sopenharmony_ci				goto reset;
17208c2ecf20Sopenharmony_ci			}
17218c2ecf20Sopenharmony_ci			return 0;
17228c2ecf20Sopenharmony_ci		}
17238c2ecf20Sopenharmony_ci	} else
17248c2ecf20Sopenharmony_ci		sock_rps_save_rxhash(sk, skb);
17258c2ecf20Sopenharmony_ci
17268c2ecf20Sopenharmony_ci	if (tcp_rcv_state_process(sk, skb)) {
17278c2ecf20Sopenharmony_ci		rsk = sk;
17288c2ecf20Sopenharmony_ci		goto reset;
17298c2ecf20Sopenharmony_ci	}
17308c2ecf20Sopenharmony_ci	return 0;
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_cireset:
17338c2ecf20Sopenharmony_ci	tcp_v4_send_reset(rsk, skb);
17348c2ecf20Sopenharmony_cidiscard:
17358c2ecf20Sopenharmony_ci	kfree_skb(skb);
17368c2ecf20Sopenharmony_ci	/* Be careful here. If this function gets more complicated and
17378c2ecf20Sopenharmony_ci	 * gcc suffers from register pressure on the x86, sk (in %ebx)
17388c2ecf20Sopenharmony_ci	 * might be destroyed here. This current version compiles correctly,
17398c2ecf20Sopenharmony_ci	 * but you have been warned.
17408c2ecf20Sopenharmony_ci	 */
17418c2ecf20Sopenharmony_ci	return 0;
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_cicsum_err:
17448c2ecf20Sopenharmony_ci	TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
17458c2ecf20Sopenharmony_ci	TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
17468c2ecf20Sopenharmony_ci	goto discard;
17478c2ecf20Sopenharmony_ci}
17488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_do_rcv);
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ciint tcp_v4_early_demux(struct sk_buff *skb)
17518c2ecf20Sopenharmony_ci{
17528c2ecf20Sopenharmony_ci	const struct iphdr *iph;
17538c2ecf20Sopenharmony_ci	const struct tcphdr *th;
17548c2ecf20Sopenharmony_ci	struct sock *sk;
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	if (skb->pkt_type != PACKET_HOST)
17578c2ecf20Sopenharmony_ci		return 0;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
17608c2ecf20Sopenharmony_ci		return 0;
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	iph = ip_hdr(skb);
17638c2ecf20Sopenharmony_ci	th = tcp_hdr(skb);
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	if (th->doff < sizeof(struct tcphdr) / 4)
17668c2ecf20Sopenharmony_ci		return 0;
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
17698c2ecf20Sopenharmony_ci				       iph->saddr, th->source,
17708c2ecf20Sopenharmony_ci				       iph->daddr, ntohs(th->dest),
17718c2ecf20Sopenharmony_ci				       skb->skb_iif, inet_sdif(skb));
17728c2ecf20Sopenharmony_ci	if (sk) {
17738c2ecf20Sopenharmony_ci		skb->sk = sk;
17748c2ecf20Sopenharmony_ci		skb->destructor = sock_edemux;
17758c2ecf20Sopenharmony_ci		if (sk_fullsock(sk)) {
17768c2ecf20Sopenharmony_ci			struct dst_entry *dst = rcu_dereference(sk->sk_rx_dst);
17778c2ecf20Sopenharmony_ci
17788c2ecf20Sopenharmony_ci			if (dst)
17798c2ecf20Sopenharmony_ci				dst = dst_check(dst, 0);
17808c2ecf20Sopenharmony_ci			if (dst &&
17818c2ecf20Sopenharmony_ci			    inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
17828c2ecf20Sopenharmony_ci				skb_dst_set_noref(skb, dst);
17838c2ecf20Sopenharmony_ci		}
17848c2ecf20Sopenharmony_ci	}
17858c2ecf20Sopenharmony_ci	return 0;
17868c2ecf20Sopenharmony_ci}
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_cibool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
17898c2ecf20Sopenharmony_ci{
17908c2ecf20Sopenharmony_ci	u32 limit, tail_gso_size, tail_gso_segs;
17918c2ecf20Sopenharmony_ci	struct skb_shared_info *shinfo;
17928c2ecf20Sopenharmony_ci	const struct tcphdr *th;
17938c2ecf20Sopenharmony_ci	struct tcphdr *thtail;
17948c2ecf20Sopenharmony_ci	struct sk_buff *tail;
17958c2ecf20Sopenharmony_ci	unsigned int hdrlen;
17968c2ecf20Sopenharmony_ci	bool fragstolen;
17978c2ecf20Sopenharmony_ci	u32 gso_segs;
17988c2ecf20Sopenharmony_ci	u32 gso_size;
17998c2ecf20Sopenharmony_ci	int delta;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	/* In case all data was pulled from skb frags (in __pskb_pull_tail()),
18028c2ecf20Sopenharmony_ci	 * we can fix skb->truesize to its real value to avoid future drops.
18038c2ecf20Sopenharmony_ci	 * This is valid because skb is not yet charged to the socket.
18048c2ecf20Sopenharmony_ci	 * It has been noticed pure SACK packets were sometimes dropped
18058c2ecf20Sopenharmony_ci	 * (if cooked by drivers without copybreak feature).
18068c2ecf20Sopenharmony_ci	 */
18078c2ecf20Sopenharmony_ci	skb_condense(skb);
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	skb_dst_drop(skb);
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci	if (unlikely(tcp_checksum_complete(skb))) {
18128c2ecf20Sopenharmony_ci		bh_unlock_sock(sk);
18138c2ecf20Sopenharmony_ci		__TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
18148c2ecf20Sopenharmony_ci		__TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
18158c2ecf20Sopenharmony_ci		return true;
18168c2ecf20Sopenharmony_ci	}
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ci	/* Attempt coalescing to last skb in backlog, even if we are
18198c2ecf20Sopenharmony_ci	 * above the limits.
18208c2ecf20Sopenharmony_ci	 * This is okay because skb capacity is limited to MAX_SKB_FRAGS.
18218c2ecf20Sopenharmony_ci	 */
18228c2ecf20Sopenharmony_ci	th = (const struct tcphdr *)skb->data;
18238c2ecf20Sopenharmony_ci	hdrlen = th->doff * 4;
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	tail = sk->sk_backlog.tail;
18268c2ecf20Sopenharmony_ci	if (!tail)
18278c2ecf20Sopenharmony_ci		goto no_coalesce;
18288c2ecf20Sopenharmony_ci	thtail = (struct tcphdr *)tail->data;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	if (TCP_SKB_CB(tail)->end_seq != TCP_SKB_CB(skb)->seq ||
18318c2ecf20Sopenharmony_ci	    TCP_SKB_CB(tail)->ip_dsfield != TCP_SKB_CB(skb)->ip_dsfield ||
18328c2ecf20Sopenharmony_ci	    ((TCP_SKB_CB(tail)->tcp_flags |
18338c2ecf20Sopenharmony_ci	      TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_SYN | TCPHDR_RST | TCPHDR_URG)) ||
18348c2ecf20Sopenharmony_ci	    !((TCP_SKB_CB(tail)->tcp_flags &
18358c2ecf20Sopenharmony_ci	      TCP_SKB_CB(skb)->tcp_flags) & TCPHDR_ACK) ||
18368c2ecf20Sopenharmony_ci	    ((TCP_SKB_CB(tail)->tcp_flags ^
18378c2ecf20Sopenharmony_ci	      TCP_SKB_CB(skb)->tcp_flags) & (TCPHDR_ECE | TCPHDR_CWR)) ||
18388c2ecf20Sopenharmony_ci#ifdef CONFIG_TLS_DEVICE
18398c2ecf20Sopenharmony_ci	    tail->decrypted != skb->decrypted ||
18408c2ecf20Sopenharmony_ci#endif
18418c2ecf20Sopenharmony_ci	    !mptcp_skb_can_collapse(tail, skb) ||
18428c2ecf20Sopenharmony_ci	    thtail->doff != th->doff ||
18438c2ecf20Sopenharmony_ci	    memcmp(thtail + 1, th + 1, hdrlen - sizeof(*th)))
18448c2ecf20Sopenharmony_ci		goto no_coalesce;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci	__skb_pull(skb, hdrlen);
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ci	shinfo = skb_shinfo(skb);
18498c2ecf20Sopenharmony_ci	gso_size = shinfo->gso_size ?: skb->len;
18508c2ecf20Sopenharmony_ci	gso_segs = shinfo->gso_segs ?: 1;
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci	shinfo = skb_shinfo(tail);
18538c2ecf20Sopenharmony_ci	tail_gso_size = shinfo->gso_size ?: (tail->len - hdrlen);
18548c2ecf20Sopenharmony_ci	tail_gso_segs = shinfo->gso_segs ?: 1;
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci	if (skb_try_coalesce(tail, skb, &fragstolen, &delta)) {
18578c2ecf20Sopenharmony_ci		TCP_SKB_CB(tail)->end_seq = TCP_SKB_CB(skb)->end_seq;
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci		if (likely(!before(TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(tail)->ack_seq))) {
18608c2ecf20Sopenharmony_ci			TCP_SKB_CB(tail)->ack_seq = TCP_SKB_CB(skb)->ack_seq;
18618c2ecf20Sopenharmony_ci			thtail->window = th->window;
18628c2ecf20Sopenharmony_ci		}
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci		/* We have to update both TCP_SKB_CB(tail)->tcp_flags and
18658c2ecf20Sopenharmony_ci		 * thtail->fin, so that the fast path in tcp_rcv_established()
18668c2ecf20Sopenharmony_ci		 * is not entered if we append a packet with a FIN.
18678c2ecf20Sopenharmony_ci		 * SYN, RST, URG are not present.
18688c2ecf20Sopenharmony_ci		 * ACK is set on both packets.
18698c2ecf20Sopenharmony_ci		 * PSH : we do not really care in TCP stack,
18708c2ecf20Sopenharmony_ci		 *       at least for 'GRO' packets.
18718c2ecf20Sopenharmony_ci		 */
18728c2ecf20Sopenharmony_ci		thtail->fin |= th->fin;
18738c2ecf20Sopenharmony_ci		TCP_SKB_CB(tail)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci		if (TCP_SKB_CB(skb)->has_rxtstamp) {
18768c2ecf20Sopenharmony_ci			TCP_SKB_CB(tail)->has_rxtstamp = true;
18778c2ecf20Sopenharmony_ci			tail->tstamp = skb->tstamp;
18788c2ecf20Sopenharmony_ci			skb_hwtstamps(tail)->hwtstamp = skb_hwtstamps(skb)->hwtstamp;
18798c2ecf20Sopenharmony_ci		}
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci		/* Not as strict as GRO. We only need to carry mss max value */
18828c2ecf20Sopenharmony_ci		shinfo->gso_size = max(gso_size, tail_gso_size);
18838c2ecf20Sopenharmony_ci		shinfo->gso_segs = min_t(u32, gso_segs + tail_gso_segs, 0xFFFF);
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci		sk->sk_backlog.len += delta;
18868c2ecf20Sopenharmony_ci		__NET_INC_STATS(sock_net(sk),
18878c2ecf20Sopenharmony_ci				LINUX_MIB_TCPBACKLOGCOALESCE);
18888c2ecf20Sopenharmony_ci		kfree_skb_partial(skb, fragstolen);
18898c2ecf20Sopenharmony_ci		return false;
18908c2ecf20Sopenharmony_ci	}
18918c2ecf20Sopenharmony_ci	__skb_push(skb, hdrlen);
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_cino_coalesce:
18948c2ecf20Sopenharmony_ci	limit = (u32)READ_ONCE(sk->sk_rcvbuf) + (u32)(READ_ONCE(sk->sk_sndbuf) >> 1);
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_ci	/* Only socket owner can try to collapse/prune rx queues
18978c2ecf20Sopenharmony_ci	 * to reduce memory overhead, so add a little headroom here.
18988c2ecf20Sopenharmony_ci	 * Few sockets backlog are possibly concurrently non empty.
18998c2ecf20Sopenharmony_ci	 */
19008c2ecf20Sopenharmony_ci	limit += 64 * 1024;
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	if (unlikely(sk_add_backlog(sk, skb, limit))) {
19038c2ecf20Sopenharmony_ci		bh_unlock_sock(sk);
19048c2ecf20Sopenharmony_ci		__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPBACKLOGDROP);
19058c2ecf20Sopenharmony_ci		return true;
19068c2ecf20Sopenharmony_ci	}
19078c2ecf20Sopenharmony_ci	return false;
19088c2ecf20Sopenharmony_ci}
19098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_add_backlog);
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ciint tcp_filter(struct sock *sk, struct sk_buff *skb)
19128c2ecf20Sopenharmony_ci{
19138c2ecf20Sopenharmony_ci	struct tcphdr *th = (struct tcphdr *)skb->data;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	return sk_filter_trim_cap(sk, skb, th->doff * 4);
19168c2ecf20Sopenharmony_ci}
19178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_filter);
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_cistatic void tcp_v4_restore_cb(struct sk_buff *skb)
19208c2ecf20Sopenharmony_ci{
19218c2ecf20Sopenharmony_ci	memmove(IPCB(skb), &TCP_SKB_CB(skb)->header.h4,
19228c2ecf20Sopenharmony_ci		sizeof(struct inet_skb_parm));
19238c2ecf20Sopenharmony_ci}
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_cistatic void tcp_v4_fill_cb(struct sk_buff *skb, const struct iphdr *iph,
19268c2ecf20Sopenharmony_ci			   const struct tcphdr *th)
19278c2ecf20Sopenharmony_ci{
19288c2ecf20Sopenharmony_ci	/* This is tricky : We move IPCB at its correct location into TCP_SKB_CB()
19298c2ecf20Sopenharmony_ci	 * barrier() makes sure compiler wont play fool^Waliasing games.
19308c2ecf20Sopenharmony_ci	 */
19318c2ecf20Sopenharmony_ci	memmove(&TCP_SKB_CB(skb)->header.h4, IPCB(skb),
19328c2ecf20Sopenharmony_ci		sizeof(struct inet_skb_parm));
19338c2ecf20Sopenharmony_ci	barrier();
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->seq = ntohl(th->seq);
19368c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
19378c2ecf20Sopenharmony_ci				    skb->len - th->doff * 4);
19388c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
19398c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
19408c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->tcp_tw_isn = 0;
19418c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
19428c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->sacked	 = 0;
19438c2ecf20Sopenharmony_ci	TCP_SKB_CB(skb)->has_rxtstamp =
19448c2ecf20Sopenharmony_ci			skb->tstamp || skb_hwtstamps(skb)->hwtstamp;
19458c2ecf20Sopenharmony_ci}
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci/*
19488c2ecf20Sopenharmony_ci *	From tcp_input.c
19498c2ecf20Sopenharmony_ci */
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ciint tcp_v4_rcv(struct sk_buff *skb)
19528c2ecf20Sopenharmony_ci{
19538c2ecf20Sopenharmony_ci	struct net *net = dev_net(skb->dev);
19548c2ecf20Sopenharmony_ci	struct sk_buff *skb_to_free;
19558c2ecf20Sopenharmony_ci	int sdif = inet_sdif(skb);
19568c2ecf20Sopenharmony_ci	int dif = inet_iif(skb);
19578c2ecf20Sopenharmony_ci	const struct iphdr *iph;
19588c2ecf20Sopenharmony_ci	const struct tcphdr *th;
19598c2ecf20Sopenharmony_ci	bool refcounted;
19608c2ecf20Sopenharmony_ci	struct sock *sk;
19618c2ecf20Sopenharmony_ci	int ret;
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_ci	if (skb->pkt_type != PACKET_HOST)
19648c2ecf20Sopenharmony_ci		goto discard_it;
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci	/* Count it even if it's bad */
19678c2ecf20Sopenharmony_ci	__TCP_INC_STATS(net, TCP_MIB_INSEGS);
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_ci	if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
19708c2ecf20Sopenharmony_ci		goto discard_it;
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci	th = (const struct tcphdr *)skb->data;
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci	if (unlikely(th->doff < sizeof(struct tcphdr) / 4))
19758c2ecf20Sopenharmony_ci		goto bad_packet;
19768c2ecf20Sopenharmony_ci	if (!pskb_may_pull(skb, th->doff * 4))
19778c2ecf20Sopenharmony_ci		goto discard_it;
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci	/* An explanation is required here, I think.
19808c2ecf20Sopenharmony_ci	 * Packet length and doff are validated by header prediction,
19818c2ecf20Sopenharmony_ci	 * provided case of th->doff==0 is eliminated.
19828c2ecf20Sopenharmony_ci	 * So, we defer the checks. */
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	if (skb_checksum_init(skb, IPPROTO_TCP, inet_compute_pseudo))
19858c2ecf20Sopenharmony_ci		goto csum_error;
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci	th = (const struct tcphdr *)skb->data;
19888c2ecf20Sopenharmony_ci	iph = ip_hdr(skb);
19898c2ecf20Sopenharmony_cilookup:
19908c2ecf20Sopenharmony_ci	sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source,
19918c2ecf20Sopenharmony_ci			       th->dest, sdif, &refcounted);
19928c2ecf20Sopenharmony_ci	if (!sk)
19938c2ecf20Sopenharmony_ci		goto no_tcp_socket;
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ciprocess:
19968c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_TIME_WAIT)
19978c2ecf20Sopenharmony_ci		goto do_time_wait;
19988c2ecf20Sopenharmony_ci
19998c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_NEW_SYN_RECV) {
20008c2ecf20Sopenharmony_ci		struct request_sock *req = inet_reqsk(sk);
20018c2ecf20Sopenharmony_ci		bool req_stolen = false;
20028c2ecf20Sopenharmony_ci		struct sock *nsk;
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci		sk = req->rsk_listener;
20058c2ecf20Sopenharmony_ci		if (unlikely(!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb) ||
20068c2ecf20Sopenharmony_ci			     tcp_v4_inbound_md5_hash(sk, skb, dif, sdif))) {
20078c2ecf20Sopenharmony_ci			sk_drops_add(sk, skb);
20088c2ecf20Sopenharmony_ci			reqsk_put(req);
20098c2ecf20Sopenharmony_ci			goto discard_it;
20108c2ecf20Sopenharmony_ci		}
20118c2ecf20Sopenharmony_ci		if (tcp_checksum_complete(skb)) {
20128c2ecf20Sopenharmony_ci			reqsk_put(req);
20138c2ecf20Sopenharmony_ci			goto csum_error;
20148c2ecf20Sopenharmony_ci		}
20158c2ecf20Sopenharmony_ci		if (unlikely(sk->sk_state != TCP_LISTEN)) {
20168c2ecf20Sopenharmony_ci			inet_csk_reqsk_queue_drop_and_put(sk, req);
20178c2ecf20Sopenharmony_ci			goto lookup;
20188c2ecf20Sopenharmony_ci		}
20198c2ecf20Sopenharmony_ci		/* We own a reference on the listener, increase it again
20208c2ecf20Sopenharmony_ci		 * as we might lose it too soon.
20218c2ecf20Sopenharmony_ci		 */
20228c2ecf20Sopenharmony_ci		sock_hold(sk);
20238c2ecf20Sopenharmony_ci		refcounted = true;
20248c2ecf20Sopenharmony_ci		nsk = NULL;
20258c2ecf20Sopenharmony_ci		if (!tcp_filter(sk, skb)) {
20268c2ecf20Sopenharmony_ci			th = (const struct tcphdr *)skb->data;
20278c2ecf20Sopenharmony_ci			iph = ip_hdr(skb);
20288c2ecf20Sopenharmony_ci			tcp_v4_fill_cb(skb, iph, th);
20298c2ecf20Sopenharmony_ci			nsk = tcp_check_req(sk, skb, req, false, &req_stolen);
20308c2ecf20Sopenharmony_ci		}
20318c2ecf20Sopenharmony_ci		if (!nsk) {
20328c2ecf20Sopenharmony_ci			reqsk_put(req);
20338c2ecf20Sopenharmony_ci			if (req_stolen) {
20348c2ecf20Sopenharmony_ci				/* Another cpu got exclusive access to req
20358c2ecf20Sopenharmony_ci				 * and created a full blown socket.
20368c2ecf20Sopenharmony_ci				 * Try to feed this packet to this socket
20378c2ecf20Sopenharmony_ci				 * instead of discarding it.
20388c2ecf20Sopenharmony_ci				 */
20398c2ecf20Sopenharmony_ci				tcp_v4_restore_cb(skb);
20408c2ecf20Sopenharmony_ci				sock_put(sk);
20418c2ecf20Sopenharmony_ci				goto lookup;
20428c2ecf20Sopenharmony_ci			}
20438c2ecf20Sopenharmony_ci			goto discard_and_relse;
20448c2ecf20Sopenharmony_ci		}
20458c2ecf20Sopenharmony_ci		nf_reset_ct(skb);
20468c2ecf20Sopenharmony_ci		if (nsk == sk) {
20478c2ecf20Sopenharmony_ci			reqsk_put(req);
20488c2ecf20Sopenharmony_ci			tcp_v4_restore_cb(skb);
20498c2ecf20Sopenharmony_ci		} else if (tcp_child_process(sk, nsk, skb)) {
20508c2ecf20Sopenharmony_ci			tcp_v4_send_reset(nsk, skb);
20518c2ecf20Sopenharmony_ci			goto discard_and_relse;
20528c2ecf20Sopenharmony_ci		} else {
20538c2ecf20Sopenharmony_ci			sock_put(sk);
20548c2ecf20Sopenharmony_ci			return 0;
20558c2ecf20Sopenharmony_ci		}
20568c2ecf20Sopenharmony_ci	}
20578c2ecf20Sopenharmony_ci	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
20588c2ecf20Sopenharmony_ci		__NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
20598c2ecf20Sopenharmony_ci		goto discard_and_relse;
20608c2ecf20Sopenharmony_ci	}
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
20638c2ecf20Sopenharmony_ci		goto discard_and_relse;
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	if (tcp_v4_inbound_md5_hash(sk, skb, dif, sdif))
20668c2ecf20Sopenharmony_ci		goto discard_and_relse;
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_ci	nf_reset_ct(skb);
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	if (tcp_filter(sk, skb))
20718c2ecf20Sopenharmony_ci		goto discard_and_relse;
20728c2ecf20Sopenharmony_ci	th = (const struct tcphdr *)skb->data;
20738c2ecf20Sopenharmony_ci	iph = ip_hdr(skb);
20748c2ecf20Sopenharmony_ci	tcp_v4_fill_cb(skb, iph, th);
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci	skb->dev = NULL;
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_LISTEN) {
20798c2ecf20Sopenharmony_ci		ret = tcp_v4_do_rcv(sk, skb);
20808c2ecf20Sopenharmony_ci		goto put_and_return;
20818c2ecf20Sopenharmony_ci	}
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci	sk_incoming_cpu_update(sk);
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	bh_lock_sock_nested(sk);
20868c2ecf20Sopenharmony_ci	tcp_segs_in(tcp_sk(sk), skb);
20878c2ecf20Sopenharmony_ci	ret = 0;
20888c2ecf20Sopenharmony_ci	if (!sock_owned_by_user(sk)) {
20898c2ecf20Sopenharmony_ci		skb_to_free = sk->sk_rx_skb_cache;
20908c2ecf20Sopenharmony_ci		sk->sk_rx_skb_cache = NULL;
20918c2ecf20Sopenharmony_ci		ret = tcp_v4_do_rcv(sk, skb);
20928c2ecf20Sopenharmony_ci	} else {
20938c2ecf20Sopenharmony_ci		if (tcp_add_backlog(sk, skb))
20948c2ecf20Sopenharmony_ci			goto discard_and_relse;
20958c2ecf20Sopenharmony_ci		skb_to_free = NULL;
20968c2ecf20Sopenharmony_ci	}
20978c2ecf20Sopenharmony_ci	bh_unlock_sock(sk);
20988c2ecf20Sopenharmony_ci	if (skb_to_free)
20998c2ecf20Sopenharmony_ci		__kfree_skb(skb_to_free);
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ciput_and_return:
21028c2ecf20Sopenharmony_ci	if (refcounted)
21038c2ecf20Sopenharmony_ci		sock_put(sk);
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci	return ret;
21068c2ecf20Sopenharmony_ci
21078c2ecf20Sopenharmony_cino_tcp_socket:
21088c2ecf20Sopenharmony_ci	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
21098c2ecf20Sopenharmony_ci		goto discard_it;
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci	tcp_v4_fill_cb(skb, iph, th);
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	if (tcp_checksum_complete(skb)) {
21148c2ecf20Sopenharmony_cicsum_error:
21158c2ecf20Sopenharmony_ci		__TCP_INC_STATS(net, TCP_MIB_CSUMERRORS);
21168c2ecf20Sopenharmony_cibad_packet:
21178c2ecf20Sopenharmony_ci		__TCP_INC_STATS(net, TCP_MIB_INERRS);
21188c2ecf20Sopenharmony_ci	} else {
21198c2ecf20Sopenharmony_ci		tcp_v4_send_reset(NULL, skb);
21208c2ecf20Sopenharmony_ci	}
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_cidiscard_it:
21238c2ecf20Sopenharmony_ci	/* Discard frame. */
21248c2ecf20Sopenharmony_ci	kfree_skb(skb);
21258c2ecf20Sopenharmony_ci	return 0;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_cidiscard_and_relse:
21288c2ecf20Sopenharmony_ci	sk_drops_add(sk, skb);
21298c2ecf20Sopenharmony_ci	if (refcounted)
21308c2ecf20Sopenharmony_ci		sock_put(sk);
21318c2ecf20Sopenharmony_ci	goto discard_it;
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_cido_time_wait:
21348c2ecf20Sopenharmony_ci	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
21358c2ecf20Sopenharmony_ci		inet_twsk_put(inet_twsk(sk));
21368c2ecf20Sopenharmony_ci		goto discard_it;
21378c2ecf20Sopenharmony_ci	}
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	tcp_v4_fill_cb(skb, iph, th);
21408c2ecf20Sopenharmony_ci
21418c2ecf20Sopenharmony_ci	if (tcp_checksum_complete(skb)) {
21428c2ecf20Sopenharmony_ci		inet_twsk_put(inet_twsk(sk));
21438c2ecf20Sopenharmony_ci		goto csum_error;
21448c2ecf20Sopenharmony_ci	}
21458c2ecf20Sopenharmony_ci	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
21468c2ecf20Sopenharmony_ci	case TCP_TW_SYN: {
21478c2ecf20Sopenharmony_ci		struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
21488c2ecf20Sopenharmony_ci							&tcp_hashinfo, skb,
21498c2ecf20Sopenharmony_ci							__tcp_hdrlen(th),
21508c2ecf20Sopenharmony_ci							iph->saddr, th->source,
21518c2ecf20Sopenharmony_ci							iph->daddr, th->dest,
21528c2ecf20Sopenharmony_ci							inet_iif(skb),
21538c2ecf20Sopenharmony_ci							sdif);
21548c2ecf20Sopenharmony_ci		if (sk2) {
21558c2ecf20Sopenharmony_ci			inet_twsk_deschedule_put(inet_twsk(sk));
21568c2ecf20Sopenharmony_ci			sk = sk2;
21578c2ecf20Sopenharmony_ci			tcp_v4_restore_cb(skb);
21588c2ecf20Sopenharmony_ci			refcounted = false;
21598c2ecf20Sopenharmony_ci			goto process;
21608c2ecf20Sopenharmony_ci		}
21618c2ecf20Sopenharmony_ci	}
21628c2ecf20Sopenharmony_ci		/* to ACK */
21638c2ecf20Sopenharmony_ci		fallthrough;
21648c2ecf20Sopenharmony_ci	case TCP_TW_ACK:
21658c2ecf20Sopenharmony_ci		tcp_v4_timewait_ack(sk, skb);
21668c2ecf20Sopenharmony_ci		break;
21678c2ecf20Sopenharmony_ci	case TCP_TW_RST:
21688c2ecf20Sopenharmony_ci		tcp_v4_send_reset(sk, skb);
21698c2ecf20Sopenharmony_ci		inet_twsk_deschedule_put(inet_twsk(sk));
21708c2ecf20Sopenharmony_ci		goto discard_it;
21718c2ecf20Sopenharmony_ci	case TCP_TW_SUCCESS:;
21728c2ecf20Sopenharmony_ci	}
21738c2ecf20Sopenharmony_ci	goto discard_it;
21748c2ecf20Sopenharmony_ci}
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_cistatic struct timewait_sock_ops tcp_timewait_sock_ops = {
21778c2ecf20Sopenharmony_ci	.twsk_obj_size	= sizeof(struct tcp_timewait_sock),
21788c2ecf20Sopenharmony_ci	.twsk_unique	= tcp_twsk_unique,
21798c2ecf20Sopenharmony_ci	.twsk_destructor= tcp_twsk_destructor,
21808c2ecf20Sopenharmony_ci};
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_civoid inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
21838c2ecf20Sopenharmony_ci{
21848c2ecf20Sopenharmony_ci	struct dst_entry *dst = skb_dst(skb);
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci	if (dst && dst_hold_safe(dst)) {
21878c2ecf20Sopenharmony_ci		rcu_assign_pointer(sk->sk_rx_dst, dst);
21888c2ecf20Sopenharmony_ci		inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
21898c2ecf20Sopenharmony_ci	}
21908c2ecf20Sopenharmony_ci}
21918c2ecf20Sopenharmony_ciEXPORT_SYMBOL(inet_sk_rx_dst_set);
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ciconst struct inet_connection_sock_af_ops ipv4_specific = {
21948c2ecf20Sopenharmony_ci	.queue_xmit	   = ip_queue_xmit,
21958c2ecf20Sopenharmony_ci	.send_check	   = tcp_v4_send_check,
21968c2ecf20Sopenharmony_ci	.rebuild_header	   = inet_sk_rebuild_header,
21978c2ecf20Sopenharmony_ci	.sk_rx_dst_set	   = inet_sk_rx_dst_set,
21988c2ecf20Sopenharmony_ci	.conn_request	   = tcp_v4_conn_request,
21998c2ecf20Sopenharmony_ci	.syn_recv_sock	   = tcp_v4_syn_recv_sock,
22008c2ecf20Sopenharmony_ci	.net_header_len	   = sizeof(struct iphdr),
22018c2ecf20Sopenharmony_ci	.setsockopt	   = ip_setsockopt,
22028c2ecf20Sopenharmony_ci	.getsockopt	   = ip_getsockopt,
22038c2ecf20Sopenharmony_ci	.addr2sockaddr	   = inet_csk_addr2sockaddr,
22048c2ecf20Sopenharmony_ci	.sockaddr_len	   = sizeof(struct sockaddr_in),
22058c2ecf20Sopenharmony_ci	.mtu_reduced	   = tcp_v4_mtu_reduced,
22068c2ecf20Sopenharmony_ci};
22078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ipv4_specific);
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
22108c2ecf20Sopenharmony_cistatic const struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
22118c2ecf20Sopenharmony_ci	.md5_lookup		= tcp_v4_md5_lookup,
22128c2ecf20Sopenharmony_ci	.calc_md5_hash		= tcp_v4_md5_hash_skb,
22138c2ecf20Sopenharmony_ci	.md5_parse		= tcp_v4_parse_md5_keys,
22148c2ecf20Sopenharmony_ci};
22158c2ecf20Sopenharmony_ci#endif
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_ci/* NOTE: A lot of things set to zero explicitly by call to
22188c2ecf20Sopenharmony_ci *       sk_alloc() so need not be done here.
22198c2ecf20Sopenharmony_ci */
22208c2ecf20Sopenharmony_cistatic int tcp_v4_init_sock(struct sock *sk)
22218c2ecf20Sopenharmony_ci{
22228c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk = inet_csk(sk);
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_ci	tcp_init_sock(sk);
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci	icsk->icsk_af_ops = &ipv4_specific;
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
22298c2ecf20Sopenharmony_ci	tcp_sk(sk)->af_specific = &tcp_sock_ipv4_specific;
22308c2ecf20Sopenharmony_ci#endif
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci	return 0;
22338c2ecf20Sopenharmony_ci}
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_civoid tcp_v4_destroy_sock(struct sock *sk)
22368c2ecf20Sopenharmony_ci{
22378c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	trace_tcp_destroy_sock(sk);
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	tcp_clear_xmit_timers(sk);
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	tcp_cleanup_congestion_control(sk);
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci	tcp_cleanup_ulp(sk);
22468c2ecf20Sopenharmony_ci
22478c2ecf20Sopenharmony_ci	/* Cleanup up the write buffer. */
22488c2ecf20Sopenharmony_ci	tcp_write_queue_purge(sk);
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci	/* Check if we want to disable active TFO */
22518c2ecf20Sopenharmony_ci	tcp_fastopen_active_disable_ofo_check(sk);
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	/* Cleans up our, hopefully empty, out_of_order_queue. */
22548c2ecf20Sopenharmony_ci	skb_rbtree_purge(&tp->out_of_order_queue);
22558c2ecf20Sopenharmony_ci
22568c2ecf20Sopenharmony_ci#ifdef CONFIG_TCP_MD5SIG
22578c2ecf20Sopenharmony_ci	/* Clean up the MD5 key list, if any */
22588c2ecf20Sopenharmony_ci	if (tp->md5sig_info) {
22598c2ecf20Sopenharmony_ci		tcp_clear_md5_list(sk);
22608c2ecf20Sopenharmony_ci		kfree_rcu(rcu_dereference_protected(tp->md5sig_info, 1), rcu);
22618c2ecf20Sopenharmony_ci		tp->md5sig_info = NULL;
22628c2ecf20Sopenharmony_ci	}
22638c2ecf20Sopenharmony_ci#endif
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci	/* Clean up a referenced TCP bind bucket. */
22668c2ecf20Sopenharmony_ci	if (inet_csk(sk)->icsk_bind_hash)
22678c2ecf20Sopenharmony_ci		inet_put_port(sk);
22688c2ecf20Sopenharmony_ci
22698c2ecf20Sopenharmony_ci	BUG_ON(rcu_access_pointer(tp->fastopen_rsk));
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	/* If socket is aborted during connect operation */
22728c2ecf20Sopenharmony_ci	tcp_free_fastopen_req(tp);
22738c2ecf20Sopenharmony_ci	tcp_fastopen_destroy_cipher(sk);
22748c2ecf20Sopenharmony_ci	tcp_saved_syn_free(tp);
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci	sk_sockets_allocated_dec(sk);
22778c2ecf20Sopenharmony_ci}
22788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_v4_destroy_sock);
22798c2ecf20Sopenharmony_ci
22808c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
22818c2ecf20Sopenharmony_ci/* Proc filesystem TCP sock list dumping. */
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci/*
22848c2ecf20Sopenharmony_ci * Get next listener socket follow cur.  If cur is NULL, get first socket
22858c2ecf20Sopenharmony_ci * starting from bucket given in st->bucket; when st->bucket is zero the
22868c2ecf20Sopenharmony_ci * very first socket in the hash table is returned.
22878c2ecf20Sopenharmony_ci */
22888c2ecf20Sopenharmony_cistatic void *listening_get_next(struct seq_file *seq, void *cur)
22898c2ecf20Sopenharmony_ci{
22908c2ecf20Sopenharmony_ci	struct tcp_seq_afinfo *afinfo;
22918c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
22928c2ecf20Sopenharmony_ci	struct net *net = seq_file_net(seq);
22938c2ecf20Sopenharmony_ci	struct inet_listen_hashbucket *ilb;
22948c2ecf20Sopenharmony_ci	struct hlist_nulls_node *node;
22958c2ecf20Sopenharmony_ci	struct sock *sk = cur;
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_ci	if (st->bpf_seq_afinfo)
22988c2ecf20Sopenharmony_ci		afinfo = st->bpf_seq_afinfo;
22998c2ecf20Sopenharmony_ci	else
23008c2ecf20Sopenharmony_ci		afinfo = PDE_DATA(file_inode(seq->file));
23018c2ecf20Sopenharmony_ci
23028c2ecf20Sopenharmony_ci	if (!sk) {
23038c2ecf20Sopenharmony_ciget_head:
23048c2ecf20Sopenharmony_ci		ilb = &tcp_hashinfo.listening_hash[st->bucket];
23058c2ecf20Sopenharmony_ci		spin_lock(&ilb->lock);
23068c2ecf20Sopenharmony_ci		sk = sk_nulls_head(&ilb->nulls_head);
23078c2ecf20Sopenharmony_ci		st->offset = 0;
23088c2ecf20Sopenharmony_ci		goto get_sk;
23098c2ecf20Sopenharmony_ci	}
23108c2ecf20Sopenharmony_ci	ilb = &tcp_hashinfo.listening_hash[st->bucket];
23118c2ecf20Sopenharmony_ci	++st->num;
23128c2ecf20Sopenharmony_ci	++st->offset;
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	sk = sk_nulls_next(sk);
23158c2ecf20Sopenharmony_ciget_sk:
23168c2ecf20Sopenharmony_ci	sk_nulls_for_each_from(sk, node) {
23178c2ecf20Sopenharmony_ci		if (!net_eq(sock_net(sk), net))
23188c2ecf20Sopenharmony_ci			continue;
23198c2ecf20Sopenharmony_ci		if (afinfo->family == AF_UNSPEC ||
23208c2ecf20Sopenharmony_ci		    sk->sk_family == afinfo->family)
23218c2ecf20Sopenharmony_ci			return sk;
23228c2ecf20Sopenharmony_ci	}
23238c2ecf20Sopenharmony_ci	spin_unlock(&ilb->lock);
23248c2ecf20Sopenharmony_ci	st->offset = 0;
23258c2ecf20Sopenharmony_ci	if (++st->bucket < INET_LHTABLE_SIZE)
23268c2ecf20Sopenharmony_ci		goto get_head;
23278c2ecf20Sopenharmony_ci	return NULL;
23288c2ecf20Sopenharmony_ci}
23298c2ecf20Sopenharmony_ci
23308c2ecf20Sopenharmony_cistatic void *listening_get_idx(struct seq_file *seq, loff_t *pos)
23318c2ecf20Sopenharmony_ci{
23328c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
23338c2ecf20Sopenharmony_ci	void *rc;
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci	st->bucket = 0;
23368c2ecf20Sopenharmony_ci	st->offset = 0;
23378c2ecf20Sopenharmony_ci	rc = listening_get_next(seq, NULL);
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	while (rc && *pos) {
23408c2ecf20Sopenharmony_ci		rc = listening_get_next(seq, rc);
23418c2ecf20Sopenharmony_ci		--*pos;
23428c2ecf20Sopenharmony_ci	}
23438c2ecf20Sopenharmony_ci	return rc;
23448c2ecf20Sopenharmony_ci}
23458c2ecf20Sopenharmony_ci
23468c2ecf20Sopenharmony_cistatic inline bool empty_bucket(const struct tcp_iter_state *st)
23478c2ecf20Sopenharmony_ci{
23488c2ecf20Sopenharmony_ci	return hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].chain);
23498c2ecf20Sopenharmony_ci}
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci/*
23528c2ecf20Sopenharmony_ci * Get first established socket starting from bucket given in st->bucket.
23538c2ecf20Sopenharmony_ci * If st->bucket is zero, the very first socket in the hash is returned.
23548c2ecf20Sopenharmony_ci */
23558c2ecf20Sopenharmony_cistatic void *established_get_first(struct seq_file *seq)
23568c2ecf20Sopenharmony_ci{
23578c2ecf20Sopenharmony_ci	struct tcp_seq_afinfo *afinfo;
23588c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
23598c2ecf20Sopenharmony_ci	struct net *net = seq_file_net(seq);
23608c2ecf20Sopenharmony_ci	void *rc = NULL;
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_ci	if (st->bpf_seq_afinfo)
23638c2ecf20Sopenharmony_ci		afinfo = st->bpf_seq_afinfo;
23648c2ecf20Sopenharmony_ci	else
23658c2ecf20Sopenharmony_ci		afinfo = PDE_DATA(file_inode(seq->file));
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci	st->offset = 0;
23688c2ecf20Sopenharmony_ci	for (; st->bucket <= tcp_hashinfo.ehash_mask; ++st->bucket) {
23698c2ecf20Sopenharmony_ci		struct sock *sk;
23708c2ecf20Sopenharmony_ci		struct hlist_nulls_node *node;
23718c2ecf20Sopenharmony_ci		spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
23728c2ecf20Sopenharmony_ci
23738c2ecf20Sopenharmony_ci		/* Lockless fast path for the common case of empty buckets */
23748c2ecf20Sopenharmony_ci		if (empty_bucket(st))
23758c2ecf20Sopenharmony_ci			continue;
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ci		spin_lock_bh(lock);
23788c2ecf20Sopenharmony_ci		sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
23798c2ecf20Sopenharmony_ci			if ((afinfo->family != AF_UNSPEC &&
23808c2ecf20Sopenharmony_ci			     sk->sk_family != afinfo->family) ||
23818c2ecf20Sopenharmony_ci			    !net_eq(sock_net(sk), net)) {
23828c2ecf20Sopenharmony_ci				continue;
23838c2ecf20Sopenharmony_ci			}
23848c2ecf20Sopenharmony_ci			rc = sk;
23858c2ecf20Sopenharmony_ci			goto out;
23868c2ecf20Sopenharmony_ci		}
23878c2ecf20Sopenharmony_ci		spin_unlock_bh(lock);
23888c2ecf20Sopenharmony_ci	}
23898c2ecf20Sopenharmony_ciout:
23908c2ecf20Sopenharmony_ci	return rc;
23918c2ecf20Sopenharmony_ci}
23928c2ecf20Sopenharmony_ci
23938c2ecf20Sopenharmony_cistatic void *established_get_next(struct seq_file *seq, void *cur)
23948c2ecf20Sopenharmony_ci{
23958c2ecf20Sopenharmony_ci	struct tcp_seq_afinfo *afinfo;
23968c2ecf20Sopenharmony_ci	struct sock *sk = cur;
23978c2ecf20Sopenharmony_ci	struct hlist_nulls_node *node;
23988c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
23998c2ecf20Sopenharmony_ci	struct net *net = seq_file_net(seq);
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci	if (st->bpf_seq_afinfo)
24028c2ecf20Sopenharmony_ci		afinfo = st->bpf_seq_afinfo;
24038c2ecf20Sopenharmony_ci	else
24048c2ecf20Sopenharmony_ci		afinfo = PDE_DATA(file_inode(seq->file));
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	++st->num;
24078c2ecf20Sopenharmony_ci	++st->offset;
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci	sk = sk_nulls_next(sk);
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci	sk_nulls_for_each_from(sk, node) {
24128c2ecf20Sopenharmony_ci		if ((afinfo->family == AF_UNSPEC ||
24138c2ecf20Sopenharmony_ci		     sk->sk_family == afinfo->family) &&
24148c2ecf20Sopenharmony_ci		    net_eq(sock_net(sk), net))
24158c2ecf20Sopenharmony_ci			return sk;
24168c2ecf20Sopenharmony_ci	}
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci	spin_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
24198c2ecf20Sopenharmony_ci	++st->bucket;
24208c2ecf20Sopenharmony_ci	return established_get_first(seq);
24218c2ecf20Sopenharmony_ci}
24228c2ecf20Sopenharmony_ci
24238c2ecf20Sopenharmony_cistatic void *established_get_idx(struct seq_file *seq, loff_t pos)
24248c2ecf20Sopenharmony_ci{
24258c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
24268c2ecf20Sopenharmony_ci	void *rc;
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci	st->bucket = 0;
24298c2ecf20Sopenharmony_ci	rc = established_get_first(seq);
24308c2ecf20Sopenharmony_ci
24318c2ecf20Sopenharmony_ci	while (rc && pos) {
24328c2ecf20Sopenharmony_ci		rc = established_get_next(seq, rc);
24338c2ecf20Sopenharmony_ci		--pos;
24348c2ecf20Sopenharmony_ci	}
24358c2ecf20Sopenharmony_ci	return rc;
24368c2ecf20Sopenharmony_ci}
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_cistatic void *tcp_get_idx(struct seq_file *seq, loff_t pos)
24398c2ecf20Sopenharmony_ci{
24408c2ecf20Sopenharmony_ci	void *rc;
24418c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci	st->state = TCP_SEQ_STATE_LISTENING;
24448c2ecf20Sopenharmony_ci	rc	  = listening_get_idx(seq, &pos);
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_ci	if (!rc) {
24478c2ecf20Sopenharmony_ci		st->state = TCP_SEQ_STATE_ESTABLISHED;
24488c2ecf20Sopenharmony_ci		rc	  = established_get_idx(seq, pos);
24498c2ecf20Sopenharmony_ci	}
24508c2ecf20Sopenharmony_ci
24518c2ecf20Sopenharmony_ci	return rc;
24528c2ecf20Sopenharmony_ci}
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_cistatic void *tcp_seek_last_pos(struct seq_file *seq)
24558c2ecf20Sopenharmony_ci{
24568c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
24578c2ecf20Sopenharmony_ci	int bucket = st->bucket;
24588c2ecf20Sopenharmony_ci	int offset = st->offset;
24598c2ecf20Sopenharmony_ci	int orig_num = st->num;
24608c2ecf20Sopenharmony_ci	void *rc = NULL;
24618c2ecf20Sopenharmony_ci
24628c2ecf20Sopenharmony_ci	switch (st->state) {
24638c2ecf20Sopenharmony_ci	case TCP_SEQ_STATE_LISTENING:
24648c2ecf20Sopenharmony_ci		if (st->bucket >= INET_LHTABLE_SIZE)
24658c2ecf20Sopenharmony_ci			break;
24668c2ecf20Sopenharmony_ci		st->state = TCP_SEQ_STATE_LISTENING;
24678c2ecf20Sopenharmony_ci		rc = listening_get_next(seq, NULL);
24688c2ecf20Sopenharmony_ci		while (offset-- && rc && bucket == st->bucket)
24698c2ecf20Sopenharmony_ci			rc = listening_get_next(seq, rc);
24708c2ecf20Sopenharmony_ci		if (rc)
24718c2ecf20Sopenharmony_ci			break;
24728c2ecf20Sopenharmony_ci		st->bucket = 0;
24738c2ecf20Sopenharmony_ci		st->state = TCP_SEQ_STATE_ESTABLISHED;
24748c2ecf20Sopenharmony_ci		fallthrough;
24758c2ecf20Sopenharmony_ci	case TCP_SEQ_STATE_ESTABLISHED:
24768c2ecf20Sopenharmony_ci		if (st->bucket > tcp_hashinfo.ehash_mask)
24778c2ecf20Sopenharmony_ci			break;
24788c2ecf20Sopenharmony_ci		rc = established_get_first(seq);
24798c2ecf20Sopenharmony_ci		while (offset-- && rc && bucket == st->bucket)
24808c2ecf20Sopenharmony_ci			rc = established_get_next(seq, rc);
24818c2ecf20Sopenharmony_ci	}
24828c2ecf20Sopenharmony_ci
24838c2ecf20Sopenharmony_ci	st->num = orig_num;
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_ci	return rc;
24868c2ecf20Sopenharmony_ci}
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_civoid *tcp_seq_start(struct seq_file *seq, loff_t *pos)
24898c2ecf20Sopenharmony_ci{
24908c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
24918c2ecf20Sopenharmony_ci	void *rc;
24928c2ecf20Sopenharmony_ci
24938c2ecf20Sopenharmony_ci	if (*pos && *pos == st->last_pos) {
24948c2ecf20Sopenharmony_ci		rc = tcp_seek_last_pos(seq);
24958c2ecf20Sopenharmony_ci		if (rc)
24968c2ecf20Sopenharmony_ci			goto out;
24978c2ecf20Sopenharmony_ci	}
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci	st->state = TCP_SEQ_STATE_LISTENING;
25008c2ecf20Sopenharmony_ci	st->num = 0;
25018c2ecf20Sopenharmony_ci	st->bucket = 0;
25028c2ecf20Sopenharmony_ci	st->offset = 0;
25038c2ecf20Sopenharmony_ci	rc = *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ciout:
25068c2ecf20Sopenharmony_ci	st->last_pos = *pos;
25078c2ecf20Sopenharmony_ci	return rc;
25088c2ecf20Sopenharmony_ci}
25098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_seq_start);
25108c2ecf20Sopenharmony_ci
25118c2ecf20Sopenharmony_civoid *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
25128c2ecf20Sopenharmony_ci{
25138c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
25148c2ecf20Sopenharmony_ci	void *rc = NULL;
25158c2ecf20Sopenharmony_ci
25168c2ecf20Sopenharmony_ci	if (v == SEQ_START_TOKEN) {
25178c2ecf20Sopenharmony_ci		rc = tcp_get_idx(seq, 0);
25188c2ecf20Sopenharmony_ci		goto out;
25198c2ecf20Sopenharmony_ci	}
25208c2ecf20Sopenharmony_ci
25218c2ecf20Sopenharmony_ci	switch (st->state) {
25228c2ecf20Sopenharmony_ci	case TCP_SEQ_STATE_LISTENING:
25238c2ecf20Sopenharmony_ci		rc = listening_get_next(seq, v);
25248c2ecf20Sopenharmony_ci		if (!rc) {
25258c2ecf20Sopenharmony_ci			st->state = TCP_SEQ_STATE_ESTABLISHED;
25268c2ecf20Sopenharmony_ci			st->bucket = 0;
25278c2ecf20Sopenharmony_ci			st->offset = 0;
25288c2ecf20Sopenharmony_ci			rc	  = established_get_first(seq);
25298c2ecf20Sopenharmony_ci		}
25308c2ecf20Sopenharmony_ci		break;
25318c2ecf20Sopenharmony_ci	case TCP_SEQ_STATE_ESTABLISHED:
25328c2ecf20Sopenharmony_ci		rc = established_get_next(seq, v);
25338c2ecf20Sopenharmony_ci		break;
25348c2ecf20Sopenharmony_ci	}
25358c2ecf20Sopenharmony_ciout:
25368c2ecf20Sopenharmony_ci	++*pos;
25378c2ecf20Sopenharmony_ci	st->last_pos = *pos;
25388c2ecf20Sopenharmony_ci	return rc;
25398c2ecf20Sopenharmony_ci}
25408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_seq_next);
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_civoid tcp_seq_stop(struct seq_file *seq, void *v)
25438c2ecf20Sopenharmony_ci{
25448c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = seq->private;
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_ci	switch (st->state) {
25478c2ecf20Sopenharmony_ci	case TCP_SEQ_STATE_LISTENING:
25488c2ecf20Sopenharmony_ci		if (v != SEQ_START_TOKEN)
25498c2ecf20Sopenharmony_ci			spin_unlock(&tcp_hashinfo.listening_hash[st->bucket].lock);
25508c2ecf20Sopenharmony_ci		break;
25518c2ecf20Sopenharmony_ci	case TCP_SEQ_STATE_ESTABLISHED:
25528c2ecf20Sopenharmony_ci		if (v)
25538c2ecf20Sopenharmony_ci			spin_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
25548c2ecf20Sopenharmony_ci		break;
25558c2ecf20Sopenharmony_ci	}
25568c2ecf20Sopenharmony_ci}
25578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_seq_stop);
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_cistatic void get_openreq4(const struct request_sock *req,
25608c2ecf20Sopenharmony_ci			 struct seq_file *f, int i)
25618c2ecf20Sopenharmony_ci{
25628c2ecf20Sopenharmony_ci	const struct inet_request_sock *ireq = inet_rsk(req);
25638c2ecf20Sopenharmony_ci	long delta = req->rsk_timer.expires - jiffies;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
25668c2ecf20Sopenharmony_ci		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d %pK",
25678c2ecf20Sopenharmony_ci		i,
25688c2ecf20Sopenharmony_ci		ireq->ir_loc_addr,
25698c2ecf20Sopenharmony_ci		ireq->ir_num,
25708c2ecf20Sopenharmony_ci		ireq->ir_rmt_addr,
25718c2ecf20Sopenharmony_ci		ntohs(ireq->ir_rmt_port),
25728c2ecf20Sopenharmony_ci		TCP_SYN_RECV,
25738c2ecf20Sopenharmony_ci		0, 0, /* could print option size, but that is af dependent. */
25748c2ecf20Sopenharmony_ci		1,    /* timers active (only the expire timer) */
25758c2ecf20Sopenharmony_ci		jiffies_delta_to_clock_t(delta),
25768c2ecf20Sopenharmony_ci		req->num_timeout,
25778c2ecf20Sopenharmony_ci		from_kuid_munged(seq_user_ns(f),
25788c2ecf20Sopenharmony_ci				 sock_i_uid(req->rsk_listener)),
25798c2ecf20Sopenharmony_ci		0,  /* non standard timer */
25808c2ecf20Sopenharmony_ci		0, /* open_requests have no inode */
25818c2ecf20Sopenharmony_ci		0,
25828c2ecf20Sopenharmony_ci		req);
25838c2ecf20Sopenharmony_ci}
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_cistatic void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
25868c2ecf20Sopenharmony_ci{
25878c2ecf20Sopenharmony_ci	int timer_active;
25888c2ecf20Sopenharmony_ci	unsigned long timer_expires;
25898c2ecf20Sopenharmony_ci	const struct tcp_sock *tp = tcp_sk(sk);
25908c2ecf20Sopenharmony_ci	const struct inet_connection_sock *icsk = inet_csk(sk);
25918c2ecf20Sopenharmony_ci	const struct inet_sock *inet = inet_sk(sk);
25928c2ecf20Sopenharmony_ci	const struct fastopen_queue *fastopenq = &icsk->icsk_accept_queue.fastopenq;
25938c2ecf20Sopenharmony_ci	__be32 dest = inet->inet_daddr;
25948c2ecf20Sopenharmony_ci	__be32 src = inet->inet_rcv_saddr;
25958c2ecf20Sopenharmony_ci	__u16 destp = ntohs(inet->inet_dport);
25968c2ecf20Sopenharmony_ci	__u16 srcp = ntohs(inet->inet_sport);
25978c2ecf20Sopenharmony_ci	int rx_queue;
25988c2ecf20Sopenharmony_ci	int state;
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_ci	if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
26018c2ecf20Sopenharmony_ci	    icsk->icsk_pending == ICSK_TIME_REO_TIMEOUT ||
26028c2ecf20Sopenharmony_ci	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
26038c2ecf20Sopenharmony_ci		timer_active	= 1;
26048c2ecf20Sopenharmony_ci		timer_expires	= icsk->icsk_timeout;
26058c2ecf20Sopenharmony_ci	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
26068c2ecf20Sopenharmony_ci		timer_active	= 4;
26078c2ecf20Sopenharmony_ci		timer_expires	= icsk->icsk_timeout;
26088c2ecf20Sopenharmony_ci	} else if (timer_pending(&sk->sk_timer)) {
26098c2ecf20Sopenharmony_ci		timer_active	= 2;
26108c2ecf20Sopenharmony_ci		timer_expires	= sk->sk_timer.expires;
26118c2ecf20Sopenharmony_ci	} else {
26128c2ecf20Sopenharmony_ci		timer_active	= 0;
26138c2ecf20Sopenharmony_ci		timer_expires = jiffies;
26148c2ecf20Sopenharmony_ci	}
26158c2ecf20Sopenharmony_ci
26168c2ecf20Sopenharmony_ci	state = inet_sk_state_load(sk);
26178c2ecf20Sopenharmony_ci	if (state == TCP_LISTEN)
26188c2ecf20Sopenharmony_ci		rx_queue = READ_ONCE(sk->sk_ack_backlog);
26198c2ecf20Sopenharmony_ci	else
26208c2ecf20Sopenharmony_ci		/* Because we don't lock the socket,
26218c2ecf20Sopenharmony_ci		 * we might find a transient negative value.
26228c2ecf20Sopenharmony_ci		 */
26238c2ecf20Sopenharmony_ci		rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) -
26248c2ecf20Sopenharmony_ci				      READ_ONCE(tp->copied_seq), 0);
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ci	seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
26278c2ecf20Sopenharmony_ci			"%08X %5u %8d %lu %d %pK %lu %lu %u %u %d",
26288c2ecf20Sopenharmony_ci		i, src, srcp, dest, destp, state,
26298c2ecf20Sopenharmony_ci		READ_ONCE(tp->write_seq) - tp->snd_una,
26308c2ecf20Sopenharmony_ci		rx_queue,
26318c2ecf20Sopenharmony_ci		timer_active,
26328c2ecf20Sopenharmony_ci		jiffies_delta_to_clock_t(timer_expires - jiffies),
26338c2ecf20Sopenharmony_ci		icsk->icsk_retransmits,
26348c2ecf20Sopenharmony_ci		from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)),
26358c2ecf20Sopenharmony_ci		icsk->icsk_probes_out,
26368c2ecf20Sopenharmony_ci		sock_i_ino(sk),
26378c2ecf20Sopenharmony_ci		refcount_read(&sk->sk_refcnt), sk,
26388c2ecf20Sopenharmony_ci		jiffies_to_clock_t(icsk->icsk_rto),
26398c2ecf20Sopenharmony_ci		jiffies_to_clock_t(icsk->icsk_ack.ato),
26408c2ecf20Sopenharmony_ci		(icsk->icsk_ack.quick << 1) | inet_csk_in_pingpong_mode(sk),
26418c2ecf20Sopenharmony_ci		tp->snd_cwnd,
26428c2ecf20Sopenharmony_ci		state == TCP_LISTEN ?
26438c2ecf20Sopenharmony_ci		    fastopenq->max_qlen :
26448c2ecf20Sopenharmony_ci		    (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh));
26458c2ecf20Sopenharmony_ci}
26468c2ecf20Sopenharmony_ci
26478c2ecf20Sopenharmony_cistatic void get_timewait4_sock(const struct inet_timewait_sock *tw,
26488c2ecf20Sopenharmony_ci			       struct seq_file *f, int i)
26498c2ecf20Sopenharmony_ci{
26508c2ecf20Sopenharmony_ci	long delta = tw->tw_timer.expires - jiffies;
26518c2ecf20Sopenharmony_ci	__be32 dest, src;
26528c2ecf20Sopenharmony_ci	__u16 destp, srcp;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci	dest  = tw->tw_daddr;
26558c2ecf20Sopenharmony_ci	src   = tw->tw_rcv_saddr;
26568c2ecf20Sopenharmony_ci	destp = ntohs(tw->tw_dport);
26578c2ecf20Sopenharmony_ci	srcp  = ntohs(tw->tw_sport);
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
26608c2ecf20Sopenharmony_ci		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
26618c2ecf20Sopenharmony_ci		i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
26628c2ecf20Sopenharmony_ci		3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
26638c2ecf20Sopenharmony_ci		refcount_read(&tw->tw_refcnt), tw);
26648c2ecf20Sopenharmony_ci}
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_ci#define TMPSZ 150
26678c2ecf20Sopenharmony_ci
26688c2ecf20Sopenharmony_cistatic int tcp4_seq_show(struct seq_file *seq, void *v)
26698c2ecf20Sopenharmony_ci{
26708c2ecf20Sopenharmony_ci	struct tcp_iter_state *st;
26718c2ecf20Sopenharmony_ci	struct sock *sk = v;
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	seq_setwidth(seq, TMPSZ - 1);
26748c2ecf20Sopenharmony_ci	if (v == SEQ_START_TOKEN) {
26758c2ecf20Sopenharmony_ci		seq_puts(seq, "  sl  local_address rem_address   st tx_queue "
26768c2ecf20Sopenharmony_ci			   "rx_queue tr tm->when retrnsmt   uid  timeout "
26778c2ecf20Sopenharmony_ci			   "inode");
26788c2ecf20Sopenharmony_ci		goto out;
26798c2ecf20Sopenharmony_ci	}
26808c2ecf20Sopenharmony_ci	st = seq->private;
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_TIME_WAIT)
26838c2ecf20Sopenharmony_ci		get_timewait4_sock(v, seq, st->num);
26848c2ecf20Sopenharmony_ci	else if (sk->sk_state == TCP_NEW_SYN_RECV)
26858c2ecf20Sopenharmony_ci		get_openreq4(v, seq, st->num);
26868c2ecf20Sopenharmony_ci	else
26878c2ecf20Sopenharmony_ci		get_tcp4_sock(v, seq, st->num);
26888c2ecf20Sopenharmony_ciout:
26898c2ecf20Sopenharmony_ci	seq_pad(seq, '\n');
26908c2ecf20Sopenharmony_ci	return 0;
26918c2ecf20Sopenharmony_ci}
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_ci#ifdef CONFIG_BPF_SYSCALL
26948c2ecf20Sopenharmony_cistruct bpf_iter__tcp {
26958c2ecf20Sopenharmony_ci	__bpf_md_ptr(struct bpf_iter_meta *, meta);
26968c2ecf20Sopenharmony_ci	__bpf_md_ptr(struct sock_common *, sk_common);
26978c2ecf20Sopenharmony_ci	uid_t uid __aligned(8);
26988c2ecf20Sopenharmony_ci};
26998c2ecf20Sopenharmony_ci
27008c2ecf20Sopenharmony_cistatic int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
27018c2ecf20Sopenharmony_ci			     struct sock_common *sk_common, uid_t uid)
27028c2ecf20Sopenharmony_ci{
27038c2ecf20Sopenharmony_ci	struct bpf_iter__tcp ctx;
27048c2ecf20Sopenharmony_ci
27058c2ecf20Sopenharmony_ci	meta->seq_num--;  /* skip SEQ_START_TOKEN */
27068c2ecf20Sopenharmony_ci	ctx.meta = meta;
27078c2ecf20Sopenharmony_ci	ctx.sk_common = sk_common;
27088c2ecf20Sopenharmony_ci	ctx.uid = uid;
27098c2ecf20Sopenharmony_ci	return bpf_iter_run_prog(prog, &ctx);
27108c2ecf20Sopenharmony_ci}
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_cistatic int bpf_iter_tcp_seq_show(struct seq_file *seq, void *v)
27138c2ecf20Sopenharmony_ci{
27148c2ecf20Sopenharmony_ci	struct bpf_iter_meta meta;
27158c2ecf20Sopenharmony_ci	struct bpf_prog *prog;
27168c2ecf20Sopenharmony_ci	struct sock *sk = v;
27178c2ecf20Sopenharmony_ci	uid_t uid;
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci	if (v == SEQ_START_TOKEN)
27208c2ecf20Sopenharmony_ci		return 0;
27218c2ecf20Sopenharmony_ci
27228c2ecf20Sopenharmony_ci	if (sk->sk_state == TCP_TIME_WAIT) {
27238c2ecf20Sopenharmony_ci		uid = 0;
27248c2ecf20Sopenharmony_ci	} else if (sk->sk_state == TCP_NEW_SYN_RECV) {
27258c2ecf20Sopenharmony_ci		const struct request_sock *req = v;
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_ci		uid = from_kuid_munged(seq_user_ns(seq),
27288c2ecf20Sopenharmony_ci				       sock_i_uid(req->rsk_listener));
27298c2ecf20Sopenharmony_ci	} else {
27308c2ecf20Sopenharmony_ci		uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk));
27318c2ecf20Sopenharmony_ci	}
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	meta.seq = seq;
27348c2ecf20Sopenharmony_ci	prog = bpf_iter_get_info(&meta, false);
27358c2ecf20Sopenharmony_ci	return tcp_prog_seq_show(prog, &meta, v, uid);
27368c2ecf20Sopenharmony_ci}
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_cistatic void bpf_iter_tcp_seq_stop(struct seq_file *seq, void *v)
27398c2ecf20Sopenharmony_ci{
27408c2ecf20Sopenharmony_ci	struct bpf_iter_meta meta;
27418c2ecf20Sopenharmony_ci	struct bpf_prog *prog;
27428c2ecf20Sopenharmony_ci
27438c2ecf20Sopenharmony_ci	if (!v) {
27448c2ecf20Sopenharmony_ci		meta.seq = seq;
27458c2ecf20Sopenharmony_ci		prog = bpf_iter_get_info(&meta, true);
27468c2ecf20Sopenharmony_ci		if (prog)
27478c2ecf20Sopenharmony_ci			(void)tcp_prog_seq_show(prog, &meta, v, 0);
27488c2ecf20Sopenharmony_ci	}
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci	tcp_seq_stop(seq, v);
27518c2ecf20Sopenharmony_ci}
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_cistatic const struct seq_operations bpf_iter_tcp_seq_ops = {
27548c2ecf20Sopenharmony_ci	.show		= bpf_iter_tcp_seq_show,
27558c2ecf20Sopenharmony_ci	.start		= tcp_seq_start,
27568c2ecf20Sopenharmony_ci	.next		= tcp_seq_next,
27578c2ecf20Sopenharmony_ci	.stop		= bpf_iter_tcp_seq_stop,
27588c2ecf20Sopenharmony_ci};
27598c2ecf20Sopenharmony_ci#endif
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_cistatic const struct seq_operations tcp4_seq_ops = {
27628c2ecf20Sopenharmony_ci	.show		= tcp4_seq_show,
27638c2ecf20Sopenharmony_ci	.start		= tcp_seq_start,
27648c2ecf20Sopenharmony_ci	.next		= tcp_seq_next,
27658c2ecf20Sopenharmony_ci	.stop		= tcp_seq_stop,
27668c2ecf20Sopenharmony_ci};
27678c2ecf20Sopenharmony_ci
27688c2ecf20Sopenharmony_cistatic struct tcp_seq_afinfo tcp4_seq_afinfo = {
27698c2ecf20Sopenharmony_ci	.family		= AF_INET,
27708c2ecf20Sopenharmony_ci};
27718c2ecf20Sopenharmony_ci
27728c2ecf20Sopenharmony_cistatic int __net_init tcp4_proc_init_net(struct net *net)
27738c2ecf20Sopenharmony_ci{
27748c2ecf20Sopenharmony_ci	if (!proc_create_net_data("tcp", 0444, net->proc_net, &tcp4_seq_ops,
27758c2ecf20Sopenharmony_ci			sizeof(struct tcp_iter_state), &tcp4_seq_afinfo))
27768c2ecf20Sopenharmony_ci		return -ENOMEM;
27778c2ecf20Sopenharmony_ci	return 0;
27788c2ecf20Sopenharmony_ci}
27798c2ecf20Sopenharmony_ci
27808c2ecf20Sopenharmony_cistatic void __net_exit tcp4_proc_exit_net(struct net *net)
27818c2ecf20Sopenharmony_ci{
27828c2ecf20Sopenharmony_ci	remove_proc_entry("tcp", net->proc_net);
27838c2ecf20Sopenharmony_ci}
27848c2ecf20Sopenharmony_ci
27858c2ecf20Sopenharmony_cistatic struct pernet_operations tcp4_net_ops = {
27868c2ecf20Sopenharmony_ci	.init = tcp4_proc_init_net,
27878c2ecf20Sopenharmony_ci	.exit = tcp4_proc_exit_net,
27888c2ecf20Sopenharmony_ci};
27898c2ecf20Sopenharmony_ci
27908c2ecf20Sopenharmony_ciint __init tcp4_proc_init(void)
27918c2ecf20Sopenharmony_ci{
27928c2ecf20Sopenharmony_ci	return register_pernet_subsys(&tcp4_net_ops);
27938c2ecf20Sopenharmony_ci}
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_civoid tcp4_proc_exit(void)
27968c2ecf20Sopenharmony_ci{
27978c2ecf20Sopenharmony_ci	unregister_pernet_subsys(&tcp4_net_ops);
27988c2ecf20Sopenharmony_ci}
27998c2ecf20Sopenharmony_ci#endif /* CONFIG_PROC_FS */
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_cistruct proto tcp_prot = {
28028c2ecf20Sopenharmony_ci	.name			= "TCP",
28038c2ecf20Sopenharmony_ci	.owner			= THIS_MODULE,
28048c2ecf20Sopenharmony_ci	.close			= tcp_close,
28058c2ecf20Sopenharmony_ci	.pre_connect		= tcp_v4_pre_connect,
28068c2ecf20Sopenharmony_ci	.connect		= tcp_v4_connect,
28078c2ecf20Sopenharmony_ci	.disconnect		= tcp_disconnect,
28088c2ecf20Sopenharmony_ci	.accept			= inet_csk_accept,
28098c2ecf20Sopenharmony_ci	.ioctl			= tcp_ioctl,
28108c2ecf20Sopenharmony_ci	.init			= tcp_v4_init_sock,
28118c2ecf20Sopenharmony_ci	.destroy		= tcp_v4_destroy_sock,
28128c2ecf20Sopenharmony_ci	.shutdown		= tcp_shutdown,
28138c2ecf20Sopenharmony_ci	.setsockopt		= tcp_setsockopt,
28148c2ecf20Sopenharmony_ci	.getsockopt		= tcp_getsockopt,
28158c2ecf20Sopenharmony_ci	.bpf_bypass_getsockopt	= tcp_bpf_bypass_getsockopt,
28168c2ecf20Sopenharmony_ci	.keepalive		= tcp_set_keepalive,
28178c2ecf20Sopenharmony_ci	.recvmsg		= tcp_recvmsg,
28188c2ecf20Sopenharmony_ci	.sendmsg		= tcp_sendmsg,
28198c2ecf20Sopenharmony_ci	.sendpage		= tcp_sendpage,
28208c2ecf20Sopenharmony_ci	.backlog_rcv		= tcp_v4_do_rcv,
28218c2ecf20Sopenharmony_ci	.release_cb		= tcp_release_cb,
28228c2ecf20Sopenharmony_ci	.hash			= inet_hash,
28238c2ecf20Sopenharmony_ci	.unhash			= inet_unhash,
28248c2ecf20Sopenharmony_ci	.get_port		= inet_csk_get_port,
28258c2ecf20Sopenharmony_ci	.enter_memory_pressure	= tcp_enter_memory_pressure,
28268c2ecf20Sopenharmony_ci	.leave_memory_pressure	= tcp_leave_memory_pressure,
28278c2ecf20Sopenharmony_ci	.stream_memory_free	= tcp_stream_memory_free,
28288c2ecf20Sopenharmony_ci	.sockets_allocated	= &tcp_sockets_allocated,
28298c2ecf20Sopenharmony_ci	.orphan_count		= &tcp_orphan_count,
28308c2ecf20Sopenharmony_ci	.memory_allocated	= &tcp_memory_allocated,
28318c2ecf20Sopenharmony_ci	.memory_pressure	= &tcp_memory_pressure,
28328c2ecf20Sopenharmony_ci	.sysctl_mem		= sysctl_tcp_mem,
28338c2ecf20Sopenharmony_ci	.sysctl_wmem_offset	= offsetof(struct net, ipv4.sysctl_tcp_wmem),
28348c2ecf20Sopenharmony_ci	.sysctl_rmem_offset	= offsetof(struct net, ipv4.sysctl_tcp_rmem),
28358c2ecf20Sopenharmony_ci	.max_header		= MAX_TCP_HEADER,
28368c2ecf20Sopenharmony_ci	.obj_size		= sizeof(struct tcp_sock),
28378c2ecf20Sopenharmony_ci	.slab_flags		= SLAB_TYPESAFE_BY_RCU,
28388c2ecf20Sopenharmony_ci	.twsk_prot		= &tcp_timewait_sock_ops,
28398c2ecf20Sopenharmony_ci	.rsk_prot		= &tcp_request_sock_ops,
28408c2ecf20Sopenharmony_ci	.h.hashinfo		= &tcp_hashinfo,
28418c2ecf20Sopenharmony_ci	.no_autobind		= true,
28428c2ecf20Sopenharmony_ci	.diag_destroy		= tcp_abort,
28438c2ecf20Sopenharmony_ci};
28448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tcp_prot);
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_cistatic void __net_exit tcp_sk_exit(struct net *net)
28478c2ecf20Sopenharmony_ci{
28488c2ecf20Sopenharmony_ci	if (net->ipv4.tcp_congestion_control)
28498c2ecf20Sopenharmony_ci		bpf_module_put(net->ipv4.tcp_congestion_control,
28508c2ecf20Sopenharmony_ci			       net->ipv4.tcp_congestion_control->owner);
28518c2ecf20Sopenharmony_ci}
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_cistatic int __net_init tcp_sk_init(struct net *net)
28548c2ecf20Sopenharmony_ci{
28558c2ecf20Sopenharmony_ci	int cnt;
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_ecn = 2;
28588c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_ecn_fallback = 1;
28598c2ecf20Sopenharmony_ci
28608c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS;
28618c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS;
28628c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD;
28638c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL;
28648c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_mtu_probe_floor = TCP_MIN_SND_MSS;
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
28678c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
28688c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
28718c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES;
28728c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_syncookies = 1;
28738c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH;
28748c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_retries1 = TCP_RETR1;
28758c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_retries2 = TCP_RETR2;
28768c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_orphan_retries = 0;
28778c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
28788c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX;
28798c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_tw_reuse = 2;
28808c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_no_ssthresh_metrics_save = 1;
28818c2ecf20Sopenharmony_ci
28828c2ecf20Sopenharmony_ci	cnt = tcp_hashinfo.ehash_mask + 1;
28838c2ecf20Sopenharmony_ci	net->ipv4.tcp_death_row.sysctl_max_tw_buckets = cnt / 2;
28848c2ecf20Sopenharmony_ci	net->ipv4.tcp_death_row.hashinfo = &tcp_hashinfo;
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_ci	net->ipv4.sysctl_max_syn_backlog = max(128, cnt / 128);
28878c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_sack = 1;
28888c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_window_scaling = 1;
28898c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_timestamps = 1;
28908c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_early_retrans = 3;
28918c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_recovery = TCP_RACK_LOSS_DETECTION;
28928c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_slow_start_after_idle = 1; /* By default, RFC2861 behavior.  */
28938c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_retrans_collapse = 1;
28948c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_max_reordering = 300;
28958c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_dsack = 1;
28968c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_app_win = 31;
28978c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_adv_win_scale = 1;
28988c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_frto = 2;
28998c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_moderate_rcvbuf = 1;
29008c2ecf20Sopenharmony_ci	/* This limits the percentage of the congestion window which we
29018c2ecf20Sopenharmony_ci	 * will allow a single TSO frame to consume.  Building TSO frames
29028c2ecf20Sopenharmony_ci	 * which are too large can cause TCP streams to be bursty.
29038c2ecf20Sopenharmony_ci	 */
29048c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_tso_win_divisor = 3;
29058c2ecf20Sopenharmony_ci	/* Default TSQ limit of 16 TSO segments */
29068c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_limit_output_bytes = 16 * 65536;
29078c2ecf20Sopenharmony_ci	/* rfc5961 challenge ack rate limiting */
29088c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_challenge_ack_limit = 1000;
29098c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_min_tso_segs = 2;
29108c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_min_rtt_wlen = 300;
29118c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_autocorking = 1;
29128c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_invalid_ratelimit = HZ/2;
29138c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_pacing_ss_ratio = 200;
29148c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_pacing_ca_ratio = 120;
29158c2ecf20Sopenharmony_ci	if (net != &init_net) {
29168c2ecf20Sopenharmony_ci		memcpy(net->ipv4.sysctl_tcp_rmem,
29178c2ecf20Sopenharmony_ci		       init_net.ipv4.sysctl_tcp_rmem,
29188c2ecf20Sopenharmony_ci		       sizeof(init_net.ipv4.sysctl_tcp_rmem));
29198c2ecf20Sopenharmony_ci		memcpy(net->ipv4.sysctl_tcp_wmem,
29208c2ecf20Sopenharmony_ci		       init_net.ipv4.sysctl_tcp_wmem,
29218c2ecf20Sopenharmony_ci		       sizeof(init_net.ipv4.sysctl_tcp_wmem));
29228c2ecf20Sopenharmony_ci	}
29238c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_comp_sack_delay_ns = NSEC_PER_MSEC;
29248c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_comp_sack_slack_ns = 100 * NSEC_PER_USEC;
29258c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_comp_sack_nr = 44;
29268c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_fastopen = TFO_CLIENT_ENABLE;
29278c2ecf20Sopenharmony_ci	spin_lock_init(&net->ipv4.tcp_fastopen_ctx_lock);
29288c2ecf20Sopenharmony_ci	net->ipv4.sysctl_tcp_fastopen_blackhole_timeout = 0;
29298c2ecf20Sopenharmony_ci	atomic_set(&net->ipv4.tfo_active_disable_times, 0);
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	/* Reno is always built in */
29328c2ecf20Sopenharmony_ci	if (!net_eq(net, &init_net) &&
29338c2ecf20Sopenharmony_ci	    bpf_try_module_get(init_net.ipv4.tcp_congestion_control,
29348c2ecf20Sopenharmony_ci			       init_net.ipv4.tcp_congestion_control->owner))
29358c2ecf20Sopenharmony_ci		net->ipv4.tcp_congestion_control = init_net.ipv4.tcp_congestion_control;
29368c2ecf20Sopenharmony_ci	else
29378c2ecf20Sopenharmony_ci		net->ipv4.tcp_congestion_control = &tcp_reno;
29388c2ecf20Sopenharmony_ci
29398c2ecf20Sopenharmony_ci	return 0;
29408c2ecf20Sopenharmony_ci}
29418c2ecf20Sopenharmony_ci
29428c2ecf20Sopenharmony_cistatic void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)
29438c2ecf20Sopenharmony_ci{
29448c2ecf20Sopenharmony_ci	struct net *net;
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci	inet_twsk_purge(&tcp_hashinfo, AF_INET);
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_ci	list_for_each_entry(net, net_exit_list, exit_list)
29498c2ecf20Sopenharmony_ci		tcp_fastopen_ctx_destroy(net);
29508c2ecf20Sopenharmony_ci}
29518c2ecf20Sopenharmony_ci
29528c2ecf20Sopenharmony_cistatic struct pernet_operations __net_initdata tcp_sk_ops = {
29538c2ecf20Sopenharmony_ci       .init	   = tcp_sk_init,
29548c2ecf20Sopenharmony_ci       .exit	   = tcp_sk_exit,
29558c2ecf20Sopenharmony_ci       .exit_batch = tcp_sk_exit_batch,
29568c2ecf20Sopenharmony_ci};
29578c2ecf20Sopenharmony_ci
29588c2ecf20Sopenharmony_ci#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
29598c2ecf20Sopenharmony_ciDEFINE_BPF_ITER_FUNC(tcp, struct bpf_iter_meta *meta,
29608c2ecf20Sopenharmony_ci		     struct sock_common *sk_common, uid_t uid)
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_cistatic int bpf_iter_init_tcp(void *priv_data, struct bpf_iter_aux_info *aux)
29638c2ecf20Sopenharmony_ci{
29648c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = priv_data;
29658c2ecf20Sopenharmony_ci	struct tcp_seq_afinfo *afinfo;
29668c2ecf20Sopenharmony_ci	int ret;
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_ci	afinfo = kmalloc(sizeof(*afinfo), GFP_USER | __GFP_NOWARN);
29698c2ecf20Sopenharmony_ci	if (!afinfo)
29708c2ecf20Sopenharmony_ci		return -ENOMEM;
29718c2ecf20Sopenharmony_ci
29728c2ecf20Sopenharmony_ci	afinfo->family = AF_UNSPEC;
29738c2ecf20Sopenharmony_ci	st->bpf_seq_afinfo = afinfo;
29748c2ecf20Sopenharmony_ci	ret = bpf_iter_init_seq_net(priv_data, aux);
29758c2ecf20Sopenharmony_ci	if (ret)
29768c2ecf20Sopenharmony_ci		kfree(afinfo);
29778c2ecf20Sopenharmony_ci	return ret;
29788c2ecf20Sopenharmony_ci}
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_cistatic void bpf_iter_fini_tcp(void *priv_data)
29818c2ecf20Sopenharmony_ci{
29828c2ecf20Sopenharmony_ci	struct tcp_iter_state *st = priv_data;
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci	kfree(st->bpf_seq_afinfo);
29858c2ecf20Sopenharmony_ci	bpf_iter_fini_seq_net(priv_data);
29868c2ecf20Sopenharmony_ci}
29878c2ecf20Sopenharmony_ci
29888c2ecf20Sopenharmony_cistatic const struct bpf_iter_seq_info tcp_seq_info = {
29898c2ecf20Sopenharmony_ci	.seq_ops		= &bpf_iter_tcp_seq_ops,
29908c2ecf20Sopenharmony_ci	.init_seq_private	= bpf_iter_init_tcp,
29918c2ecf20Sopenharmony_ci	.fini_seq_private	= bpf_iter_fini_tcp,
29928c2ecf20Sopenharmony_ci	.seq_priv_size		= sizeof(struct tcp_iter_state),
29938c2ecf20Sopenharmony_ci};
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_cistatic struct bpf_iter_reg tcp_reg_info = {
29968c2ecf20Sopenharmony_ci	.target			= "tcp",
29978c2ecf20Sopenharmony_ci	.ctx_arg_info_size	= 1,
29988c2ecf20Sopenharmony_ci	.ctx_arg_info		= {
29998c2ecf20Sopenharmony_ci		{ offsetof(struct bpf_iter__tcp, sk_common),
30008c2ecf20Sopenharmony_ci		  PTR_TO_BTF_ID_OR_NULL },
30018c2ecf20Sopenharmony_ci	},
30028c2ecf20Sopenharmony_ci	.seq_info		= &tcp_seq_info,
30038c2ecf20Sopenharmony_ci};
30048c2ecf20Sopenharmony_ci
30058c2ecf20Sopenharmony_cistatic void __init bpf_iter_register(void)
30068c2ecf20Sopenharmony_ci{
30078c2ecf20Sopenharmony_ci	tcp_reg_info.ctx_arg_info[0].btf_id = btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON];
30088c2ecf20Sopenharmony_ci	if (bpf_iter_reg_target(&tcp_reg_info))
30098c2ecf20Sopenharmony_ci		pr_warn("Warning: could not register bpf iterator tcp\n");
30108c2ecf20Sopenharmony_ci}
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_ci#endif
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_civoid __init tcp_v4_init(void)
30158c2ecf20Sopenharmony_ci{
30168c2ecf20Sopenharmony_ci	int cpu, res;
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci	for_each_possible_cpu(cpu) {
30198c2ecf20Sopenharmony_ci		struct sock *sk;
30208c2ecf20Sopenharmony_ci
30218c2ecf20Sopenharmony_ci		res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
30228c2ecf20Sopenharmony_ci					   IPPROTO_TCP, &init_net);
30238c2ecf20Sopenharmony_ci		if (res)
30248c2ecf20Sopenharmony_ci			panic("Failed to create the TCP control socket.\n");
30258c2ecf20Sopenharmony_ci		sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
30268c2ecf20Sopenharmony_ci
30278c2ecf20Sopenharmony_ci		/* Please enforce IP_DF and IPID==0 for RST and
30288c2ecf20Sopenharmony_ci		 * ACK sent in SYN-RECV and TIME-WAIT state.
30298c2ecf20Sopenharmony_ci		 */
30308c2ecf20Sopenharmony_ci		inet_sk(sk)->pmtudisc = IP_PMTUDISC_DO;
30318c2ecf20Sopenharmony_ci
30328c2ecf20Sopenharmony_ci		per_cpu(ipv4_tcp_sk, cpu) = sk;
30338c2ecf20Sopenharmony_ci	}
30348c2ecf20Sopenharmony_ci	if (register_pernet_subsys(&tcp_sk_ops))
30358c2ecf20Sopenharmony_ci		panic("Failed to create the TCP control socket.\n");
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
30388c2ecf20Sopenharmony_ci	bpf_iter_register();
30398c2ecf20Sopenharmony_ci#endif
30408c2ecf20Sopenharmony_ci}
3041