162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Multipath TCP
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2017 - 2019, Intel Corporation.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define pr_fmt(fmt) "MPTCP: " fmt
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <crypto/sha2.h>
1162306a36Sopenharmony_ci#include <net/tcp.h>
1262306a36Sopenharmony_ci#include <net/mptcp.h>
1362306a36Sopenharmony_ci#include "protocol.h"
1462306a36Sopenharmony_ci#include "mib.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <trace/events/mptcp.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic bool mptcp_cap_flag_sha256(u8 flags)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic void mptcp_parse_option(const struct sk_buff *skb,
2462306a36Sopenharmony_ci			       const unsigned char *ptr, int opsize,
2562306a36Sopenharmony_ci			       struct mptcp_options_received *mp_opt)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	u8 subtype = *ptr >> 4;
2862306a36Sopenharmony_ci	int expected_opsize;
2962306a36Sopenharmony_ci	u16 subopt;
3062306a36Sopenharmony_ci	u8 version;
3162306a36Sopenharmony_ci	u8 flags;
3262306a36Sopenharmony_ci	u8 i;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	switch (subtype) {
3562306a36Sopenharmony_ci	case MPTCPOPT_MP_CAPABLE:
3662306a36Sopenharmony_ci		/* strict size checking */
3762306a36Sopenharmony_ci		if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
3862306a36Sopenharmony_ci			if (skb->len > tcp_hdr(skb)->doff << 2)
3962306a36Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_ACK_DATA;
4062306a36Sopenharmony_ci			else
4162306a36Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_ACK;
4262306a36Sopenharmony_ci			subopt = OPTION_MPTCP_MPC_ACK;
4362306a36Sopenharmony_ci		} else {
4462306a36Sopenharmony_ci			if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_ACK) {
4562306a36Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_SYNACK;
4662306a36Sopenharmony_ci				subopt = OPTION_MPTCP_MPC_SYNACK;
4762306a36Sopenharmony_ci			} else {
4862306a36Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_SYN;
4962306a36Sopenharmony_ci				subopt = OPTION_MPTCP_MPC_SYN;
5062306a36Sopenharmony_ci			}
5162306a36Sopenharmony_ci		}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		/* Cfr RFC 8684 Section 3.3.0:
5462306a36Sopenharmony_ci		 * If a checksum is present but its use had
5562306a36Sopenharmony_ci		 * not been negotiated in the MP_CAPABLE handshake, the receiver MUST
5662306a36Sopenharmony_ci		 * close the subflow with a RST, as it is not behaving as negotiated.
5762306a36Sopenharmony_ci		 * If a checksum is not present when its use has been negotiated, the
5862306a36Sopenharmony_ci		 * receiver MUST close the subflow with a RST, as it is considered
5962306a36Sopenharmony_ci		 * broken
6062306a36Sopenharmony_ci		 * We parse even option with mismatching csum presence, so that
6162306a36Sopenharmony_ci		 * later in subflow_data_ready we can trigger the reset.
6262306a36Sopenharmony_ci		 */
6362306a36Sopenharmony_ci		if (opsize != expected_opsize &&
6462306a36Sopenharmony_ci		    (expected_opsize != TCPOLEN_MPTCP_MPC_ACK_DATA ||
6562306a36Sopenharmony_ci		     opsize != TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM))
6662306a36Sopenharmony_ci			break;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		/* try to be gentle vs future versions on the initial syn */
6962306a36Sopenharmony_ci		version = *ptr++ & MPTCP_VERSION_MASK;
7062306a36Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_MPC_SYN) {
7162306a36Sopenharmony_ci			if (version != MPTCP_SUPPORTED_VERSION)
7262306a36Sopenharmony_ci				break;
7362306a36Sopenharmony_ci		} else if (version < MPTCP_SUPPORTED_VERSION) {
7462306a36Sopenharmony_ci			break;
7562306a36Sopenharmony_ci		}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci		flags = *ptr++;
7862306a36Sopenharmony_ci		if (!mptcp_cap_flag_sha256(flags) ||
7962306a36Sopenharmony_ci		    (flags & MPTCP_CAP_EXTENSIBILITY))
8062306a36Sopenharmony_ci			break;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci		/* RFC 6824, Section 3.1:
8362306a36Sopenharmony_ci		 * "For the Checksum Required bit (labeled "A"), if either
8462306a36Sopenharmony_ci		 * host requires the use of checksums, checksums MUST be used.
8562306a36Sopenharmony_ci		 * In other words, the only way for checksums not to be used
8662306a36Sopenharmony_ci		 * is if both hosts in their SYNs set A=0."
8762306a36Sopenharmony_ci		 */
8862306a36Sopenharmony_ci		if (flags & MPTCP_CAP_CHECKSUM_REQD)
8962306a36Sopenharmony_ci			mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		mp_opt->deny_join_id0 = !!(flags & MPTCP_CAP_DENY_JOIN_ID0);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci		mp_opt->suboptions |= subopt;
9462306a36Sopenharmony_ci		if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK) {
9562306a36Sopenharmony_ci			mp_opt->sndr_key = get_unaligned_be64(ptr);
9662306a36Sopenharmony_ci			ptr += 8;
9762306a36Sopenharmony_ci		}
9862306a36Sopenharmony_ci		if (opsize >= TCPOLEN_MPTCP_MPC_ACK) {
9962306a36Sopenharmony_ci			mp_opt->rcvr_key = get_unaligned_be64(ptr);
10062306a36Sopenharmony_ci			ptr += 8;
10162306a36Sopenharmony_ci		}
10262306a36Sopenharmony_ci		if (opsize >= TCPOLEN_MPTCP_MPC_ACK_DATA) {
10362306a36Sopenharmony_ci			/* Section 3.1.:
10462306a36Sopenharmony_ci			 * "the data parameters in a MP_CAPABLE are semantically
10562306a36Sopenharmony_ci			 * equivalent to those in a DSS option and can be used
10662306a36Sopenharmony_ci			 * interchangeably."
10762306a36Sopenharmony_ci			 */
10862306a36Sopenharmony_ci			mp_opt->suboptions |= OPTION_MPTCP_DSS;
10962306a36Sopenharmony_ci			mp_opt->use_map = 1;
11062306a36Sopenharmony_ci			mp_opt->mpc_map = 1;
11162306a36Sopenharmony_ci			mp_opt->use_ack = 0;
11262306a36Sopenharmony_ci			mp_opt->data_len = get_unaligned_be16(ptr);
11362306a36Sopenharmony_ci			ptr += 2;
11462306a36Sopenharmony_ci		}
11562306a36Sopenharmony_ci		if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM) {
11662306a36Sopenharmony_ci			mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
11762306a36Sopenharmony_ci			mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
11862306a36Sopenharmony_ci			ptr += 2;
11962306a36Sopenharmony_ci		}
12062306a36Sopenharmony_ci		pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d csum=%u",
12162306a36Sopenharmony_ci			 version, flags, opsize, mp_opt->sndr_key,
12262306a36Sopenharmony_ci			 mp_opt->rcvr_key, mp_opt->data_len, mp_opt->csum);
12362306a36Sopenharmony_ci		break;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	case MPTCPOPT_MP_JOIN:
12662306a36Sopenharmony_ci		if (opsize == TCPOLEN_MPTCP_MPJ_SYN) {
12762306a36Sopenharmony_ci			mp_opt->suboptions |= OPTION_MPTCP_MPJ_SYN;
12862306a36Sopenharmony_ci			mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
12962306a36Sopenharmony_ci			mp_opt->join_id = *ptr++;
13062306a36Sopenharmony_ci			mp_opt->token = get_unaligned_be32(ptr);
13162306a36Sopenharmony_ci			ptr += 4;
13262306a36Sopenharmony_ci			mp_opt->nonce = get_unaligned_be32(ptr);
13362306a36Sopenharmony_ci			ptr += 4;
13462306a36Sopenharmony_ci			pr_debug("MP_JOIN bkup=%u, id=%u, token=%u, nonce=%u",
13562306a36Sopenharmony_ci				 mp_opt->backup, mp_opt->join_id,
13662306a36Sopenharmony_ci				 mp_opt->token, mp_opt->nonce);
13762306a36Sopenharmony_ci		} else if (opsize == TCPOLEN_MPTCP_MPJ_SYNACK) {
13862306a36Sopenharmony_ci			mp_opt->suboptions |= OPTION_MPTCP_MPJ_SYNACK;
13962306a36Sopenharmony_ci			mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
14062306a36Sopenharmony_ci			mp_opt->join_id = *ptr++;
14162306a36Sopenharmony_ci			mp_opt->thmac = get_unaligned_be64(ptr);
14262306a36Sopenharmony_ci			ptr += 8;
14362306a36Sopenharmony_ci			mp_opt->nonce = get_unaligned_be32(ptr);
14462306a36Sopenharmony_ci			ptr += 4;
14562306a36Sopenharmony_ci			pr_debug("MP_JOIN bkup=%u, id=%u, thmac=%llu, nonce=%u",
14662306a36Sopenharmony_ci				 mp_opt->backup, mp_opt->join_id,
14762306a36Sopenharmony_ci				 mp_opt->thmac, mp_opt->nonce);
14862306a36Sopenharmony_ci		} else if (opsize == TCPOLEN_MPTCP_MPJ_ACK) {
14962306a36Sopenharmony_ci			mp_opt->suboptions |= OPTION_MPTCP_MPJ_ACK;
15062306a36Sopenharmony_ci			ptr += 2;
15162306a36Sopenharmony_ci			memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN);
15262306a36Sopenharmony_ci			pr_debug("MP_JOIN hmac");
15362306a36Sopenharmony_ci		}
15462306a36Sopenharmony_ci		break;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	case MPTCPOPT_DSS:
15762306a36Sopenharmony_ci		pr_debug("DSS");
15862306a36Sopenharmony_ci		ptr++;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci		/* we must clear 'mpc_map' be able to detect MP_CAPABLE
16162306a36Sopenharmony_ci		 * map vs DSS map in mptcp_incoming_options(), and reconstruct
16262306a36Sopenharmony_ci		 * map info accordingly
16362306a36Sopenharmony_ci		 */
16462306a36Sopenharmony_ci		mp_opt->mpc_map = 0;
16562306a36Sopenharmony_ci		flags = (*ptr++) & MPTCP_DSS_FLAG_MASK;
16662306a36Sopenharmony_ci		mp_opt->data_fin = (flags & MPTCP_DSS_DATA_FIN) != 0;
16762306a36Sopenharmony_ci		mp_opt->dsn64 = (flags & MPTCP_DSS_DSN64) != 0;
16862306a36Sopenharmony_ci		mp_opt->use_map = (flags & MPTCP_DSS_HAS_MAP) != 0;
16962306a36Sopenharmony_ci		mp_opt->ack64 = (flags & MPTCP_DSS_ACK64) != 0;
17062306a36Sopenharmony_ci		mp_opt->use_ack = (flags & MPTCP_DSS_HAS_ACK);
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		pr_debug("data_fin=%d dsn64=%d use_map=%d ack64=%d use_ack=%d",
17362306a36Sopenharmony_ci			 mp_opt->data_fin, mp_opt->dsn64,
17462306a36Sopenharmony_ci			 mp_opt->use_map, mp_opt->ack64,
17562306a36Sopenharmony_ci			 mp_opt->use_ack);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci		expected_opsize = TCPOLEN_MPTCP_DSS_BASE;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci		if (mp_opt->use_ack) {
18062306a36Sopenharmony_ci			if (mp_opt->ack64)
18162306a36Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_ACK64;
18262306a36Sopenharmony_ci			else
18362306a36Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_ACK32;
18462306a36Sopenharmony_ci		}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		if (mp_opt->use_map) {
18762306a36Sopenharmony_ci			if (mp_opt->dsn64)
18862306a36Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_MAP64;
18962306a36Sopenharmony_ci			else
19062306a36Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_MAP32;
19162306a36Sopenharmony_ci		}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci		/* Always parse any csum presence combination, we will enforce
19462306a36Sopenharmony_ci		 * RFC 8684 Section 3.3.0 checks later in subflow_data_ready
19562306a36Sopenharmony_ci		 */
19662306a36Sopenharmony_ci		if (opsize != expected_opsize &&
19762306a36Sopenharmony_ci		    opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM)
19862306a36Sopenharmony_ci			break;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_DSS;
20162306a36Sopenharmony_ci		if (mp_opt->use_ack) {
20262306a36Sopenharmony_ci			if (mp_opt->ack64) {
20362306a36Sopenharmony_ci				mp_opt->data_ack = get_unaligned_be64(ptr);
20462306a36Sopenharmony_ci				ptr += 8;
20562306a36Sopenharmony_ci			} else {
20662306a36Sopenharmony_ci				mp_opt->data_ack = get_unaligned_be32(ptr);
20762306a36Sopenharmony_ci				ptr += 4;
20862306a36Sopenharmony_ci			}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci			pr_debug("data_ack=%llu", mp_opt->data_ack);
21162306a36Sopenharmony_ci		}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci		if (mp_opt->use_map) {
21462306a36Sopenharmony_ci			if (mp_opt->dsn64) {
21562306a36Sopenharmony_ci				mp_opt->data_seq = get_unaligned_be64(ptr);
21662306a36Sopenharmony_ci				ptr += 8;
21762306a36Sopenharmony_ci			} else {
21862306a36Sopenharmony_ci				mp_opt->data_seq = get_unaligned_be32(ptr);
21962306a36Sopenharmony_ci				ptr += 4;
22062306a36Sopenharmony_ci			}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci			mp_opt->subflow_seq = get_unaligned_be32(ptr);
22362306a36Sopenharmony_ci			ptr += 4;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci			mp_opt->data_len = get_unaligned_be16(ptr);
22662306a36Sopenharmony_ci			ptr += 2;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci			if (opsize == expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) {
22962306a36Sopenharmony_ci				mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
23062306a36Sopenharmony_ci				mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
23162306a36Sopenharmony_ci				ptr += 2;
23262306a36Sopenharmony_ci			}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci			pr_debug("data_seq=%llu subflow_seq=%u data_len=%u csum=%d:%u",
23562306a36Sopenharmony_ci				 mp_opt->data_seq, mp_opt->subflow_seq,
23662306a36Sopenharmony_ci				 mp_opt->data_len, !!(mp_opt->suboptions & OPTION_MPTCP_CSUMREQD),
23762306a36Sopenharmony_ci				 mp_opt->csum);
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		break;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	case MPTCPOPT_ADD_ADDR:
24362306a36Sopenharmony_ci		mp_opt->echo = (*ptr++) & MPTCP_ADDR_ECHO;
24462306a36Sopenharmony_ci		if (!mp_opt->echo) {
24562306a36Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR ||
24662306a36Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR_PORT)
24762306a36Sopenharmony_ci				mp_opt->addr.family = AF_INET;
24862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
24962306a36Sopenharmony_ci			else if (opsize == TCPOLEN_MPTCP_ADD_ADDR6 ||
25062306a36Sopenharmony_ci				 opsize == TCPOLEN_MPTCP_ADD_ADDR6_PORT)
25162306a36Sopenharmony_ci				mp_opt->addr.family = AF_INET6;
25262306a36Sopenharmony_ci#endif
25362306a36Sopenharmony_ci			else
25462306a36Sopenharmony_ci				break;
25562306a36Sopenharmony_ci		} else {
25662306a36Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE ||
25762306a36Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT)
25862306a36Sopenharmony_ci				mp_opt->addr.family = AF_INET;
25962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
26062306a36Sopenharmony_ci			else if (opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE ||
26162306a36Sopenharmony_ci				 opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT)
26262306a36Sopenharmony_ci				mp_opt->addr.family = AF_INET6;
26362306a36Sopenharmony_ci#endif
26462306a36Sopenharmony_ci			else
26562306a36Sopenharmony_ci				break;
26662306a36Sopenharmony_ci		}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_ADD_ADDR;
26962306a36Sopenharmony_ci		mp_opt->addr.id = *ptr++;
27062306a36Sopenharmony_ci		mp_opt->addr.port = 0;
27162306a36Sopenharmony_ci		mp_opt->ahmac = 0;
27262306a36Sopenharmony_ci		if (mp_opt->addr.family == AF_INET) {
27362306a36Sopenharmony_ci			memcpy((u8 *)&mp_opt->addr.addr.s_addr, (u8 *)ptr, 4);
27462306a36Sopenharmony_ci			ptr += 4;
27562306a36Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR_PORT ||
27662306a36Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT) {
27762306a36Sopenharmony_ci				mp_opt->addr.port = htons(get_unaligned_be16(ptr));
27862306a36Sopenharmony_ci				ptr += 2;
27962306a36Sopenharmony_ci			}
28062306a36Sopenharmony_ci		}
28162306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
28262306a36Sopenharmony_ci		else {
28362306a36Sopenharmony_ci			memcpy(mp_opt->addr.addr6.s6_addr, (u8 *)ptr, 16);
28462306a36Sopenharmony_ci			ptr += 16;
28562306a36Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR6_PORT ||
28662306a36Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT) {
28762306a36Sopenharmony_ci				mp_opt->addr.port = htons(get_unaligned_be16(ptr));
28862306a36Sopenharmony_ci				ptr += 2;
28962306a36Sopenharmony_ci			}
29062306a36Sopenharmony_ci		}
29162306a36Sopenharmony_ci#endif
29262306a36Sopenharmony_ci		if (!mp_opt->echo) {
29362306a36Sopenharmony_ci			mp_opt->ahmac = get_unaligned_be64(ptr);
29462306a36Sopenharmony_ci			ptr += 8;
29562306a36Sopenharmony_ci		}
29662306a36Sopenharmony_ci		pr_debug("ADD_ADDR%s: id=%d, ahmac=%llu, echo=%d, port=%d",
29762306a36Sopenharmony_ci			 (mp_opt->addr.family == AF_INET6) ? "6" : "",
29862306a36Sopenharmony_ci			 mp_opt->addr.id, mp_opt->ahmac, mp_opt->echo, ntohs(mp_opt->addr.port));
29962306a36Sopenharmony_ci		break;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	case MPTCPOPT_RM_ADDR:
30262306a36Sopenharmony_ci		if (opsize < TCPOLEN_MPTCP_RM_ADDR_BASE + 1 ||
30362306a36Sopenharmony_ci		    opsize > TCPOLEN_MPTCP_RM_ADDR_BASE + MPTCP_RM_IDS_MAX)
30462306a36Sopenharmony_ci			break;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci		ptr++;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_RM_ADDR;
30962306a36Sopenharmony_ci		mp_opt->rm_list.nr = opsize - TCPOLEN_MPTCP_RM_ADDR_BASE;
31062306a36Sopenharmony_ci		for (i = 0; i < mp_opt->rm_list.nr; i++)
31162306a36Sopenharmony_ci			mp_opt->rm_list.ids[i] = *ptr++;
31262306a36Sopenharmony_ci		pr_debug("RM_ADDR: rm_list_nr=%d", mp_opt->rm_list.nr);
31362306a36Sopenharmony_ci		break;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	case MPTCPOPT_MP_PRIO:
31662306a36Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_PRIO)
31762306a36Sopenharmony_ci			break;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_PRIO;
32062306a36Sopenharmony_ci		mp_opt->backup = *ptr++ & MPTCP_PRIO_BKUP;
32162306a36Sopenharmony_ci		pr_debug("MP_PRIO: prio=%d", mp_opt->backup);
32262306a36Sopenharmony_ci		break;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	case MPTCPOPT_MP_FASTCLOSE:
32562306a36Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_FASTCLOSE)
32662306a36Sopenharmony_ci			break;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		ptr += 2;
32962306a36Sopenharmony_ci		mp_opt->rcvr_key = get_unaligned_be64(ptr);
33062306a36Sopenharmony_ci		ptr += 8;
33162306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_FASTCLOSE;
33262306a36Sopenharmony_ci		pr_debug("MP_FASTCLOSE: recv_key=%llu", mp_opt->rcvr_key);
33362306a36Sopenharmony_ci		break;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	case MPTCPOPT_RST:
33662306a36Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_RST)
33762306a36Sopenharmony_ci			break;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci		if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST))
34062306a36Sopenharmony_ci			break;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_RST;
34362306a36Sopenharmony_ci		flags = *ptr++;
34462306a36Sopenharmony_ci		mp_opt->reset_transient = flags & MPTCP_RST_TRANSIENT;
34562306a36Sopenharmony_ci		mp_opt->reset_reason = *ptr;
34662306a36Sopenharmony_ci		pr_debug("MP_RST: transient=%u reason=%u",
34762306a36Sopenharmony_ci			 mp_opt->reset_transient, mp_opt->reset_reason);
34862306a36Sopenharmony_ci		break;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	case MPTCPOPT_MP_FAIL:
35162306a36Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_FAIL)
35262306a36Sopenharmony_ci			break;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		ptr += 2;
35562306a36Sopenharmony_ci		mp_opt->suboptions |= OPTION_MPTCP_FAIL;
35662306a36Sopenharmony_ci		mp_opt->fail_seq = get_unaligned_be64(ptr);
35762306a36Sopenharmony_ci		pr_debug("MP_FAIL: data_seq=%llu", mp_opt->fail_seq);
35862306a36Sopenharmony_ci		break;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	default:
36162306a36Sopenharmony_ci		break;
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_civoid mptcp_get_options(const struct sk_buff *skb,
36662306a36Sopenharmony_ci		       struct mptcp_options_received *mp_opt)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
36962306a36Sopenharmony_ci	const unsigned char *ptr;
37062306a36Sopenharmony_ci	int length;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	/* initialize option status */
37362306a36Sopenharmony_ci	mp_opt->suboptions = 0;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	length = (th->doff * 4) - sizeof(struct tcphdr);
37662306a36Sopenharmony_ci	ptr = (const unsigned char *)(th + 1);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	while (length > 0) {
37962306a36Sopenharmony_ci		int opcode = *ptr++;
38062306a36Sopenharmony_ci		int opsize;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci		switch (opcode) {
38362306a36Sopenharmony_ci		case TCPOPT_EOL:
38462306a36Sopenharmony_ci			return;
38562306a36Sopenharmony_ci		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
38662306a36Sopenharmony_ci			length--;
38762306a36Sopenharmony_ci			continue;
38862306a36Sopenharmony_ci		default:
38962306a36Sopenharmony_ci			if (length < 2)
39062306a36Sopenharmony_ci				return;
39162306a36Sopenharmony_ci			opsize = *ptr++;
39262306a36Sopenharmony_ci			if (opsize < 2) /* "silly options" */
39362306a36Sopenharmony_ci				return;
39462306a36Sopenharmony_ci			if (opsize > length)
39562306a36Sopenharmony_ci				return;	/* don't parse partial options */
39662306a36Sopenharmony_ci			if (opcode == TCPOPT_MPTCP)
39762306a36Sopenharmony_ci				mptcp_parse_option(skb, ptr, opsize, mp_opt);
39862306a36Sopenharmony_ci			ptr += opsize - 2;
39962306a36Sopenharmony_ci			length -= opsize;
40062306a36Sopenharmony_ci		}
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cibool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
40562306a36Sopenharmony_ci		       unsigned int *size, struct mptcp_out_options *opts)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	/* we will use snd_isn to detect first pkt [re]transmission
41062306a36Sopenharmony_ci	 * in mptcp_established_options_mp()
41162306a36Sopenharmony_ci	 */
41262306a36Sopenharmony_ci	subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
41362306a36Sopenharmony_ci	if (subflow->request_mptcp) {
41462306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPC_SYN;
41562306a36Sopenharmony_ci		opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk));
41662306a36Sopenharmony_ci		opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk));
41762306a36Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPC_SYN;
41862306a36Sopenharmony_ci		return true;
41962306a36Sopenharmony_ci	} else if (subflow->request_join) {
42062306a36Sopenharmony_ci		pr_debug("remote_token=%u, nonce=%u", subflow->remote_token,
42162306a36Sopenharmony_ci			 subflow->local_nonce);
42262306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPJ_SYN;
42362306a36Sopenharmony_ci		opts->join_id = subflow->local_id;
42462306a36Sopenharmony_ci		opts->token = subflow->remote_token;
42562306a36Sopenharmony_ci		opts->nonce = subflow->local_nonce;
42662306a36Sopenharmony_ci		opts->backup = subflow->request_bkup;
42762306a36Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPJ_SYN;
42862306a36Sopenharmony_ci		return true;
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci	return false;
43162306a36Sopenharmony_ci}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_cistatic void clear_3rdack_retransmission(struct sock *sk)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	struct inet_connection_sock *icsk = inet_csk(sk);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	sk_stop_timer(sk, &icsk->icsk_delack_timer);
43862306a36Sopenharmony_ci	icsk->icsk_ack.timeout = 0;
43962306a36Sopenharmony_ci	icsk->icsk_ack.ato = 0;
44062306a36Sopenharmony_ci	icsk->icsk_ack.pending &= ~(ICSK_ACK_SCHED | ICSK_ACK_TIMER);
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
44462306a36Sopenharmony_ci					 bool snd_data_fin_enable,
44562306a36Sopenharmony_ci					 unsigned int *size,
44662306a36Sopenharmony_ci					 struct mptcp_out_options *opts)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
44962306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
45062306a36Sopenharmony_ci	struct mptcp_ext *mpext;
45162306a36Sopenharmony_ci	unsigned int data_len;
45262306a36Sopenharmony_ci	u8 len;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	/* When skb is not available, we better over-estimate the emitted
45562306a36Sopenharmony_ci	 * options len. A full DSS option (28 bytes) is longer than
45662306a36Sopenharmony_ci	 * TCPOLEN_MPTCP_MPC_ACK_DATA(22) or TCPOLEN_MPTCP_MPJ_ACK(24), so
45762306a36Sopenharmony_ci	 * tell the caller to defer the estimate to
45862306a36Sopenharmony_ci	 * mptcp_established_options_dss(), which will reserve enough space.
45962306a36Sopenharmony_ci	 */
46062306a36Sopenharmony_ci	if (!skb)
46162306a36Sopenharmony_ci		return false;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	/* MPC/MPJ needed only on 3rd ack packet, DATA_FIN and TCP shutdown take precedence */
46462306a36Sopenharmony_ci	if (subflow->fully_established || snd_data_fin_enable ||
46562306a36Sopenharmony_ci	    subflow->snd_isn != TCP_SKB_CB(skb)->seq ||
46662306a36Sopenharmony_ci	    sk->sk_state != TCP_ESTABLISHED)
46762306a36Sopenharmony_ci		return false;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	if (subflow->mp_capable) {
47062306a36Sopenharmony_ci		mpext = mptcp_get_ext(skb);
47162306a36Sopenharmony_ci		data_len = mpext ? mpext->data_len : 0;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci		/* we will check ops->data_len in mptcp_write_options() to
47462306a36Sopenharmony_ci		 * discriminate between TCPOLEN_MPTCP_MPC_ACK_DATA and
47562306a36Sopenharmony_ci		 * TCPOLEN_MPTCP_MPC_ACK
47662306a36Sopenharmony_ci		 */
47762306a36Sopenharmony_ci		opts->data_len = data_len;
47862306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPC_ACK;
47962306a36Sopenharmony_ci		opts->sndr_key = subflow->local_key;
48062306a36Sopenharmony_ci		opts->rcvr_key = subflow->remote_key;
48162306a36Sopenharmony_ci		opts->csum_reqd = READ_ONCE(msk->csum_enabled);
48262306a36Sopenharmony_ci		opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk));
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci		/* Section 3.1.
48562306a36Sopenharmony_ci		 * The MP_CAPABLE option is carried on the SYN, SYN/ACK, and ACK
48662306a36Sopenharmony_ci		 * packets that start the first subflow of an MPTCP connection,
48762306a36Sopenharmony_ci		 * as well as the first packet that carries data
48862306a36Sopenharmony_ci		 */
48962306a36Sopenharmony_ci		if (data_len > 0) {
49062306a36Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_ACK_DATA;
49162306a36Sopenharmony_ci			if (opts->csum_reqd) {
49262306a36Sopenharmony_ci				/* we need to propagate more info to csum the pseudo hdr */
49362306a36Sopenharmony_ci				opts->data_seq = mpext->data_seq;
49462306a36Sopenharmony_ci				opts->subflow_seq = mpext->subflow_seq;
49562306a36Sopenharmony_ci				opts->csum = mpext->csum;
49662306a36Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_CHECKSUM;
49762306a36Sopenharmony_ci			}
49862306a36Sopenharmony_ci			*size = ALIGN(len, 4);
49962306a36Sopenharmony_ci		} else {
50062306a36Sopenharmony_ci			*size = TCPOLEN_MPTCP_MPC_ACK;
50162306a36Sopenharmony_ci		}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci		pr_debug("subflow=%p, local_key=%llu, remote_key=%llu map_len=%d",
50462306a36Sopenharmony_ci			 subflow, subflow->local_key, subflow->remote_key,
50562306a36Sopenharmony_ci			 data_len);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci		return true;
50862306a36Sopenharmony_ci	} else if (subflow->mp_join) {
50962306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPJ_ACK;
51062306a36Sopenharmony_ci		memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN);
51162306a36Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPJ_ACK;
51262306a36Sopenharmony_ci		pr_debug("subflow=%p", subflow);
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci		/* we can use the full delegate action helper only from BH context
51562306a36Sopenharmony_ci		 * If we are in process context - sk is flushing the backlog at
51662306a36Sopenharmony_ci		 * socket lock release time - just set the appropriate flag, will
51762306a36Sopenharmony_ci		 * be handled by the release callback
51862306a36Sopenharmony_ci		 */
51962306a36Sopenharmony_ci		if (sock_owned_by_user(sk))
52062306a36Sopenharmony_ci			set_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status);
52162306a36Sopenharmony_ci		else
52262306a36Sopenharmony_ci			mptcp_subflow_delegate(subflow, MPTCP_DELEGATE_ACK);
52362306a36Sopenharmony_ci		return true;
52462306a36Sopenharmony_ci	}
52562306a36Sopenharmony_ci	return false;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
52962306a36Sopenharmony_ci				 struct sk_buff *skb, struct mptcp_ext *ext)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	/* The write_seq value has already been incremented, so the actual
53262306a36Sopenharmony_ci	 * sequence number for the DATA_FIN is one less.
53362306a36Sopenharmony_ci	 */
53462306a36Sopenharmony_ci	u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq) - 1;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (!ext->use_map || !skb->len) {
53762306a36Sopenharmony_ci		/* RFC6824 requires a DSS mapping with specific values
53862306a36Sopenharmony_ci		 * if DATA_FIN is set but no data payload is mapped
53962306a36Sopenharmony_ci		 */
54062306a36Sopenharmony_ci		ext->data_fin = 1;
54162306a36Sopenharmony_ci		ext->use_map = 1;
54262306a36Sopenharmony_ci		ext->dsn64 = 1;
54362306a36Sopenharmony_ci		ext->data_seq = data_fin_tx_seq;
54462306a36Sopenharmony_ci		ext->subflow_seq = 0;
54562306a36Sopenharmony_ci		ext->data_len = 1;
54662306a36Sopenharmony_ci	} else if (ext->data_seq + ext->data_len == data_fin_tx_seq) {
54762306a36Sopenharmony_ci		/* If there's an existing DSS mapping and it is the
54862306a36Sopenharmony_ci		 * final mapping, DATA_FIN consumes 1 additional byte of
54962306a36Sopenharmony_ci		 * mapping space.
55062306a36Sopenharmony_ci		 */
55162306a36Sopenharmony_ci		ext->data_fin = 1;
55262306a36Sopenharmony_ci		ext->data_len++;
55362306a36Sopenharmony_ci	}
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
55762306a36Sopenharmony_ci					  bool snd_data_fin_enable,
55862306a36Sopenharmony_ci					  unsigned int *size,
55962306a36Sopenharmony_ci					  struct mptcp_out_options *opts)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
56262306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
56362306a36Sopenharmony_ci	unsigned int dss_size = 0;
56462306a36Sopenharmony_ci	struct mptcp_ext *mpext;
56562306a36Sopenharmony_ci	unsigned int ack_size;
56662306a36Sopenharmony_ci	bool ret = false;
56762306a36Sopenharmony_ci	u64 ack_seq;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	opts->csum_reqd = READ_ONCE(msk->csum_enabled);
57062306a36Sopenharmony_ci	mpext = skb ? mptcp_get_ext(skb) : NULL;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
57362306a36Sopenharmony_ci		unsigned int map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci		if (mpext) {
57662306a36Sopenharmony_ci			if (opts->csum_reqd)
57762306a36Sopenharmony_ci				map_size += TCPOLEN_MPTCP_DSS_CHECKSUM;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci			opts->ext_copy = *mpext;
58062306a36Sopenharmony_ci		}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci		dss_size = map_size;
58362306a36Sopenharmony_ci		if (skb && snd_data_fin_enable)
58462306a36Sopenharmony_ci			mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
58562306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_DSS;
58662306a36Sopenharmony_ci		ret = true;
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	/* passive sockets msk will set the 'can_ack' after accept(), even
59062306a36Sopenharmony_ci	 * if the first subflow may have the already the remote key handy
59162306a36Sopenharmony_ci	 */
59262306a36Sopenharmony_ci	opts->ext_copy.use_ack = 0;
59362306a36Sopenharmony_ci	if (!READ_ONCE(msk->can_ack)) {
59462306a36Sopenharmony_ci		*size = ALIGN(dss_size, 4);
59562306a36Sopenharmony_ci		return ret;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	ack_seq = READ_ONCE(msk->ack_seq);
59962306a36Sopenharmony_ci	if (READ_ONCE(msk->use_64bit_ack)) {
60062306a36Sopenharmony_ci		ack_size = TCPOLEN_MPTCP_DSS_ACK64;
60162306a36Sopenharmony_ci		opts->ext_copy.data_ack = ack_seq;
60262306a36Sopenharmony_ci		opts->ext_copy.ack64 = 1;
60362306a36Sopenharmony_ci	} else {
60462306a36Sopenharmony_ci		ack_size = TCPOLEN_MPTCP_DSS_ACK32;
60562306a36Sopenharmony_ci		opts->ext_copy.data_ack32 = (uint32_t)ack_seq;
60662306a36Sopenharmony_ci		opts->ext_copy.ack64 = 0;
60762306a36Sopenharmony_ci	}
60862306a36Sopenharmony_ci	opts->ext_copy.use_ack = 1;
60962306a36Sopenharmony_ci	opts->suboptions = OPTION_MPTCP_DSS;
61062306a36Sopenharmony_ci	WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk));
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	/* Add kind/length/subtype/flag overhead if mapping is not populated */
61362306a36Sopenharmony_ci	if (dss_size == 0)
61462306a36Sopenharmony_ci		ack_size += TCPOLEN_MPTCP_DSS_BASE;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	dss_size += ack_size;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	*size = ALIGN(dss_size, 4);
61962306a36Sopenharmony_ci	return true;
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic u64 add_addr_generate_hmac(u64 key1, u64 key2,
62362306a36Sopenharmony_ci				  struct mptcp_addr_info *addr)
62462306a36Sopenharmony_ci{
62562306a36Sopenharmony_ci	u16 port = ntohs(addr->port);
62662306a36Sopenharmony_ci	u8 hmac[SHA256_DIGEST_SIZE];
62762306a36Sopenharmony_ci	u8 msg[19];
62862306a36Sopenharmony_ci	int i = 0;
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	msg[i++] = addr->id;
63162306a36Sopenharmony_ci	if (addr->family == AF_INET) {
63262306a36Sopenharmony_ci		memcpy(&msg[i], &addr->addr.s_addr, 4);
63362306a36Sopenharmony_ci		i += 4;
63462306a36Sopenharmony_ci	}
63562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
63662306a36Sopenharmony_ci	else if (addr->family == AF_INET6) {
63762306a36Sopenharmony_ci		memcpy(&msg[i], &addr->addr6.s6_addr, 16);
63862306a36Sopenharmony_ci		i += 16;
63962306a36Sopenharmony_ci	}
64062306a36Sopenharmony_ci#endif
64162306a36Sopenharmony_ci	msg[i++] = port >> 8;
64262306a36Sopenharmony_ci	msg[i++] = port & 0xFF;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	mptcp_crypto_hmac_sha(key1, key2, msg, i, hmac);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
64762306a36Sopenharmony_ci}
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_cistatic bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *skb,
65062306a36Sopenharmony_ci					       unsigned int *size,
65162306a36Sopenharmony_ci					       unsigned int remaining,
65262306a36Sopenharmony_ci					       struct mptcp_out_options *opts)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
65562306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
65662306a36Sopenharmony_ci	bool drop_other_suboptions = false;
65762306a36Sopenharmony_ci	unsigned int opt_size = *size;
65862306a36Sopenharmony_ci	bool echo;
65962306a36Sopenharmony_ci	int len;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	/* add addr will strip the existing options, be sure to avoid breaking
66262306a36Sopenharmony_ci	 * MPC/MPJ handshakes
66362306a36Sopenharmony_ci	 */
66462306a36Sopenharmony_ci	if (!mptcp_pm_should_add_signal(msk) ||
66562306a36Sopenharmony_ci	    (opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) ||
66662306a36Sopenharmony_ci	    !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, &opts->addr,
66762306a36Sopenharmony_ci		    &echo, &drop_other_suboptions))
66862306a36Sopenharmony_ci		return false;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	if (drop_other_suboptions)
67162306a36Sopenharmony_ci		remaining += opt_size;
67262306a36Sopenharmony_ci	len = mptcp_add_addr_len(opts->addr.family, echo, !!opts->addr.port);
67362306a36Sopenharmony_ci	if (remaining < len)
67462306a36Sopenharmony_ci		return false;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	*size = len;
67762306a36Sopenharmony_ci	if (drop_other_suboptions) {
67862306a36Sopenharmony_ci		pr_debug("drop other suboptions");
67962306a36Sopenharmony_ci		opts->suboptions = 0;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci		/* note that e.g. DSS could have written into the memory
68262306a36Sopenharmony_ci		 * aliased by ahmac, we must reset the field here
68362306a36Sopenharmony_ci		 * to avoid appending the hmac even for ADD_ADDR echo
68462306a36Sopenharmony_ci		 * options
68562306a36Sopenharmony_ci		 */
68662306a36Sopenharmony_ci		opts->ahmac = 0;
68762306a36Sopenharmony_ci		*size -= opt_size;
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
69062306a36Sopenharmony_ci	if (!echo) {
69162306a36Sopenharmony_ci		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDRTX);
69262306a36Sopenharmony_ci		opts->ahmac = add_addr_generate_hmac(msk->local_key,
69362306a36Sopenharmony_ci						     msk->remote_key,
69462306a36Sopenharmony_ci						     &opts->addr);
69562306a36Sopenharmony_ci	} else {
69662306a36Sopenharmony_ci		MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADDTX);
69762306a36Sopenharmony_ci	}
69862306a36Sopenharmony_ci	pr_debug("addr_id=%d, ahmac=%llu, echo=%d, port=%d",
69962306a36Sopenharmony_ci		 opts->addr.id, opts->ahmac, echo, ntohs(opts->addr.port));
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	return true;
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_cistatic bool mptcp_established_options_rm_addr(struct sock *sk,
70562306a36Sopenharmony_ci					      unsigned int *size,
70662306a36Sopenharmony_ci					      unsigned int remaining,
70762306a36Sopenharmony_ci					      struct mptcp_out_options *opts)
70862306a36Sopenharmony_ci{
70962306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
71062306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
71162306a36Sopenharmony_ci	struct mptcp_rm_list rm_list;
71262306a36Sopenharmony_ci	int i, len;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	if (!mptcp_pm_should_rm_signal(msk) ||
71562306a36Sopenharmony_ci	    !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_list)))
71662306a36Sopenharmony_ci		return false;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	len = mptcp_rm_addr_len(&rm_list);
71962306a36Sopenharmony_ci	if (len < 0)
72062306a36Sopenharmony_ci		return false;
72162306a36Sopenharmony_ci	if (remaining < len)
72262306a36Sopenharmony_ci		return false;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	*size = len;
72562306a36Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_RM_ADDR;
72662306a36Sopenharmony_ci	opts->rm_list = rm_list;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	for (i = 0; i < opts->rm_list.nr; i++)
72962306a36Sopenharmony_ci		pr_debug("rm_list_ids[%d]=%d", i, opts->rm_list.ids[i]);
73062306a36Sopenharmony_ci	MPTCP_ADD_STATS(sock_net(sk), MPTCP_MIB_RMADDRTX, opts->rm_list.nr);
73162306a36Sopenharmony_ci	return true;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cistatic bool mptcp_established_options_mp_prio(struct sock *sk,
73562306a36Sopenharmony_ci					      unsigned int *size,
73662306a36Sopenharmony_ci					      unsigned int remaining,
73762306a36Sopenharmony_ci					      struct mptcp_out_options *opts)
73862306a36Sopenharmony_ci{
73962306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	/* can't send MP_PRIO with MPC, as they share the same option space:
74262306a36Sopenharmony_ci	 * 'backup'. Also it makes no sense at all
74362306a36Sopenharmony_ci	 */
74462306a36Sopenharmony_ci	if (!subflow->send_mp_prio || (opts->suboptions & OPTIONS_MPTCP_MPC))
74562306a36Sopenharmony_ci		return false;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	/* account for the trailing 'nop' option */
74862306a36Sopenharmony_ci	if (remaining < TCPOLEN_MPTCP_PRIO_ALIGN)
74962306a36Sopenharmony_ci		return false;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	*size = TCPOLEN_MPTCP_PRIO_ALIGN;
75262306a36Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_PRIO;
75362306a36Sopenharmony_ci	opts->backup = subflow->request_bkup;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	pr_debug("prio=%d", opts->backup);
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	return true;
75862306a36Sopenharmony_ci}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_cistatic noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb,
76162306a36Sopenharmony_ci						   unsigned int *size,
76262306a36Sopenharmony_ci						   unsigned int remaining,
76362306a36Sopenharmony_ci						   struct mptcp_out_options *opts)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	if (remaining < TCPOLEN_MPTCP_RST)
76862306a36Sopenharmony_ci		return false;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	*size = TCPOLEN_MPTCP_RST;
77162306a36Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_RST;
77262306a36Sopenharmony_ci	opts->reset_transient = subflow->reset_transient;
77362306a36Sopenharmony_ci	opts->reset_reason = subflow->reset_reason;
77462306a36Sopenharmony_ci	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX);
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	return true;
77762306a36Sopenharmony_ci}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_cistatic bool mptcp_established_options_fastclose(struct sock *sk,
78062306a36Sopenharmony_ci						unsigned int *size,
78162306a36Sopenharmony_ci						unsigned int remaining,
78262306a36Sopenharmony_ci						struct mptcp_out_options *opts)
78362306a36Sopenharmony_ci{
78462306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
78562306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	if (likely(!subflow->send_fastclose))
78862306a36Sopenharmony_ci		return false;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	if (remaining < TCPOLEN_MPTCP_FASTCLOSE)
79162306a36Sopenharmony_ci		return false;
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	*size = TCPOLEN_MPTCP_FASTCLOSE;
79462306a36Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_FASTCLOSE;
79562306a36Sopenharmony_ci	opts->rcvr_key = msk->remote_key;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	pr_debug("FASTCLOSE key=%llu", opts->rcvr_key);
79862306a36Sopenharmony_ci	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX);
79962306a36Sopenharmony_ci	return true;
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_cistatic bool mptcp_established_options_mp_fail(struct sock *sk,
80362306a36Sopenharmony_ci					      unsigned int *size,
80462306a36Sopenharmony_ci					      unsigned int remaining,
80562306a36Sopenharmony_ci					      struct mptcp_out_options *opts)
80662306a36Sopenharmony_ci{
80762306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	if (likely(!subflow->send_mp_fail))
81062306a36Sopenharmony_ci		return false;
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	if (remaining < TCPOLEN_MPTCP_FAIL)
81362306a36Sopenharmony_ci		return false;
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	*size = TCPOLEN_MPTCP_FAIL;
81662306a36Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_FAIL;
81762306a36Sopenharmony_ci	opts->fail_seq = subflow->map_seq;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq);
82062306a36Sopenharmony_ci	MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILTX);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	return true;
82362306a36Sopenharmony_ci}
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_cibool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
82662306a36Sopenharmony_ci			       unsigned int *size, unsigned int remaining,
82762306a36Sopenharmony_ci			       struct mptcp_out_options *opts)
82862306a36Sopenharmony_ci{
82962306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
83062306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
83162306a36Sopenharmony_ci	unsigned int opt_size = 0;
83262306a36Sopenharmony_ci	bool snd_data_fin;
83362306a36Sopenharmony_ci	bool ret = false;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	opts->suboptions = 0;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	if (unlikely(__mptcp_check_fallback(msk) && !mptcp_check_infinite_map(skb)))
83862306a36Sopenharmony_ci		return false;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) {
84162306a36Sopenharmony_ci		if (mptcp_established_options_fastclose(sk, &opt_size, remaining, opts) ||
84262306a36Sopenharmony_ci		    mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) {
84362306a36Sopenharmony_ci			*size += opt_size;
84462306a36Sopenharmony_ci			remaining -= opt_size;
84562306a36Sopenharmony_ci		}
84662306a36Sopenharmony_ci		/* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */
84762306a36Sopenharmony_ci		if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) {
84862306a36Sopenharmony_ci			*size += opt_size;
84962306a36Sopenharmony_ci			remaining -= opt_size;
85062306a36Sopenharmony_ci		}
85162306a36Sopenharmony_ci		return true;
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	snd_data_fin = mptcp_data_fin_enabled(msk);
85562306a36Sopenharmony_ci	if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, opts))
85662306a36Sopenharmony_ci		ret = true;
85762306a36Sopenharmony_ci	else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, opts)) {
85862306a36Sopenharmony_ci		unsigned int mp_fail_size;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci		ret = true;
86162306a36Sopenharmony_ci		if (mptcp_established_options_mp_fail(sk, &mp_fail_size,
86262306a36Sopenharmony_ci						      remaining - opt_size, opts)) {
86362306a36Sopenharmony_ci			*size += opt_size + mp_fail_size;
86462306a36Sopenharmony_ci			remaining -= opt_size - mp_fail_size;
86562306a36Sopenharmony_ci			return true;
86662306a36Sopenharmony_ci		}
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	/* we reserved enough space for the above options, and exceeding the
87062306a36Sopenharmony_ci	 * TCP option space would be fatal
87162306a36Sopenharmony_ci	 */
87262306a36Sopenharmony_ci	if (WARN_ON_ONCE(opt_size > remaining))
87362306a36Sopenharmony_ci		return false;
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	*size += opt_size;
87662306a36Sopenharmony_ci	remaining -= opt_size;
87762306a36Sopenharmony_ci	if (mptcp_established_options_add_addr(sk, skb, &opt_size, remaining, opts)) {
87862306a36Sopenharmony_ci		*size += opt_size;
87962306a36Sopenharmony_ci		remaining -= opt_size;
88062306a36Sopenharmony_ci		ret = true;
88162306a36Sopenharmony_ci	} else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
88262306a36Sopenharmony_ci		*size += opt_size;
88362306a36Sopenharmony_ci		remaining -= opt_size;
88462306a36Sopenharmony_ci		ret = true;
88562306a36Sopenharmony_ci	}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	if (mptcp_established_options_mp_prio(sk, &opt_size, remaining, opts)) {
88862306a36Sopenharmony_ci		*size += opt_size;
88962306a36Sopenharmony_ci		remaining -= opt_size;
89062306a36Sopenharmony_ci		ret = true;
89162306a36Sopenharmony_ci	}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	return ret;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cibool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
89762306a36Sopenharmony_ci			  struct mptcp_out_options *opts)
89862306a36Sopenharmony_ci{
89962306a36Sopenharmony_ci	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	if (subflow_req->mp_capable) {
90262306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPC_SYNACK;
90362306a36Sopenharmony_ci		opts->sndr_key = subflow_req->local_key;
90462306a36Sopenharmony_ci		opts->csum_reqd = subflow_req->csum_reqd;
90562306a36Sopenharmony_ci		opts->allow_join_id0 = subflow_req->allow_join_id0;
90662306a36Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPC_SYNACK;
90762306a36Sopenharmony_ci		pr_debug("subflow_req=%p, local_key=%llu",
90862306a36Sopenharmony_ci			 subflow_req, subflow_req->local_key);
90962306a36Sopenharmony_ci		return true;
91062306a36Sopenharmony_ci	} else if (subflow_req->mp_join) {
91162306a36Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPJ_SYNACK;
91262306a36Sopenharmony_ci		opts->backup = subflow_req->backup;
91362306a36Sopenharmony_ci		opts->join_id = subflow_req->local_id;
91462306a36Sopenharmony_ci		opts->thmac = subflow_req->thmac;
91562306a36Sopenharmony_ci		opts->nonce = subflow_req->local_nonce;
91662306a36Sopenharmony_ci		pr_debug("req=%p, bkup=%u, id=%u, thmac=%llu, nonce=%u",
91762306a36Sopenharmony_ci			 subflow_req, opts->backup, opts->join_id,
91862306a36Sopenharmony_ci			 opts->thmac, opts->nonce);
91962306a36Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPJ_SYNACK;
92062306a36Sopenharmony_ci		return true;
92162306a36Sopenharmony_ci	}
92262306a36Sopenharmony_ci	return false;
92362306a36Sopenharmony_ci}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_cistatic bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
92662306a36Sopenharmony_ci				    struct mptcp_subflow_context *subflow,
92762306a36Sopenharmony_ci				    struct sk_buff *skb,
92862306a36Sopenharmony_ci				    struct mptcp_options_received *mp_opt)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	/* here we can process OoO, in-window pkts, only in-sequence 4th ack
93162306a36Sopenharmony_ci	 * will make the subflow fully established
93262306a36Sopenharmony_ci	 */
93362306a36Sopenharmony_ci	if (likely(subflow->fully_established)) {
93462306a36Sopenharmony_ci		/* on passive sockets, check for 3rd ack retransmission
93562306a36Sopenharmony_ci		 * note that msk is always set by subflow_syn_recv_sock()
93662306a36Sopenharmony_ci		 * for mp_join subflows
93762306a36Sopenharmony_ci		 */
93862306a36Sopenharmony_ci		if (TCP_SKB_CB(skb)->seq == subflow->ssn_offset + 1 &&
93962306a36Sopenharmony_ci		    TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq &&
94062306a36Sopenharmony_ci		    subflow->mp_join && (mp_opt->suboptions & OPTIONS_MPTCP_MPJ) &&
94162306a36Sopenharmony_ci		    !subflow->request_join)
94262306a36Sopenharmony_ci			tcp_send_ack(ssk);
94362306a36Sopenharmony_ci		goto check_notify;
94462306a36Sopenharmony_ci	}
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	/* we must process OoO packets before the first subflow is fully
94762306a36Sopenharmony_ci	 * established. OoO packets are instead a protocol violation
94862306a36Sopenharmony_ci	 * for MP_JOIN subflows as the peer must not send any data
94962306a36Sopenharmony_ci	 * before receiving the forth ack - cfr. RFC 8684 section 3.2.
95062306a36Sopenharmony_ci	 */
95162306a36Sopenharmony_ci	if (TCP_SKB_CB(skb)->seq != subflow->ssn_offset + 1) {
95262306a36Sopenharmony_ci		if (subflow->mp_join)
95362306a36Sopenharmony_ci			goto reset;
95462306a36Sopenharmony_ci		if (subflow->is_mptfo && mp_opt->suboptions & OPTION_MPTCP_MPC_ACK)
95562306a36Sopenharmony_ci			goto set_fully_established;
95662306a36Sopenharmony_ci		return subflow->mp_capable;
95762306a36Sopenharmony_ci	}
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	if (subflow->remote_key_valid &&
96062306a36Sopenharmony_ci	    (((mp_opt->suboptions & OPTION_MPTCP_DSS) && mp_opt->use_ack) ||
96162306a36Sopenharmony_ci	     ((mp_opt->suboptions & OPTION_MPTCP_ADD_ADDR) && !mp_opt->echo))) {
96262306a36Sopenharmony_ci		/* subflows are fully established as soon as we get any
96362306a36Sopenharmony_ci		 * additional ack, including ADD_ADDR.
96462306a36Sopenharmony_ci		 */
96562306a36Sopenharmony_ci		goto set_fully_established;
96662306a36Sopenharmony_ci	}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	/* If the first established packet does not contain MP_CAPABLE + data
96962306a36Sopenharmony_ci	 * then fallback to TCP. Fallback scenarios requires a reset for
97062306a36Sopenharmony_ci	 * MP_JOIN subflows.
97162306a36Sopenharmony_ci	 */
97262306a36Sopenharmony_ci	if (!(mp_opt->suboptions & OPTIONS_MPTCP_MPC)) {
97362306a36Sopenharmony_ci		if (subflow->mp_join)
97462306a36Sopenharmony_ci			goto reset;
97562306a36Sopenharmony_ci		subflow->mp_capable = 0;
97662306a36Sopenharmony_ci		pr_fallback(msk);
97762306a36Sopenharmony_ci		mptcp_do_fallback(ssk);
97862306a36Sopenharmony_ci		return false;
97962306a36Sopenharmony_ci	}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	if (mp_opt->deny_join_id0)
98262306a36Sopenharmony_ci		WRITE_ONCE(msk->pm.remote_deny_join_id0, true);
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	if (unlikely(!READ_ONCE(msk->pm.server_side)))
98562306a36Sopenharmony_ci		pr_warn_once("bogus mpc option on established client sk");
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ciset_fully_established:
98862306a36Sopenharmony_ci	mptcp_data_lock((struct sock *)msk);
98962306a36Sopenharmony_ci	__mptcp_subflow_fully_established(msk, subflow, mp_opt);
99062306a36Sopenharmony_ci	mptcp_data_unlock((struct sock *)msk);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_cicheck_notify:
99362306a36Sopenharmony_ci	/* if the subflow is not already linked into the conn_list, we can't
99462306a36Sopenharmony_ci	 * notify the PM: this subflow is still on the listener queue
99562306a36Sopenharmony_ci	 * and the PM possibly acquiring the subflow lock could race with
99662306a36Sopenharmony_ci	 * the listener close
99762306a36Sopenharmony_ci	 */
99862306a36Sopenharmony_ci	if (likely(subflow->pm_notified) || list_empty(&subflow->node))
99962306a36Sopenharmony_ci		return true;
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	subflow->pm_notified = 1;
100262306a36Sopenharmony_ci	if (subflow->mp_join) {
100362306a36Sopenharmony_ci		clear_3rdack_retransmission(ssk);
100462306a36Sopenharmony_ci		mptcp_pm_subflow_established(msk);
100562306a36Sopenharmony_ci	} else {
100662306a36Sopenharmony_ci		mptcp_pm_fully_established(msk, ssk);
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci	return true;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_cireset:
101162306a36Sopenharmony_ci	mptcp_subflow_reset(ssk);
101262306a36Sopenharmony_ci	return false;
101362306a36Sopenharmony_ci}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ciu64 __mptcp_expand_seq(u64 old_seq, u64 cur_seq)
101662306a36Sopenharmony_ci{
101762306a36Sopenharmony_ci	u32 old_seq32, cur_seq32;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	old_seq32 = (u32)old_seq;
102062306a36Sopenharmony_ci	cur_seq32 = (u32)cur_seq;
102162306a36Sopenharmony_ci	cur_seq = (old_seq & GENMASK_ULL(63, 32)) + cur_seq32;
102262306a36Sopenharmony_ci	if (unlikely(cur_seq32 < old_seq32 && before(old_seq32, cur_seq32)))
102362306a36Sopenharmony_ci		return cur_seq + (1LL << 32);
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	/* reverse wrap could happen, too */
102662306a36Sopenharmony_ci	if (unlikely(cur_seq32 > old_seq32 && after(old_seq32, cur_seq32)))
102762306a36Sopenharmony_ci		return cur_seq - (1LL << 32);
102862306a36Sopenharmony_ci	return cur_seq;
102962306a36Sopenharmony_ci}
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_cistatic void __mptcp_snd_una_update(struct mptcp_sock *msk, u64 new_snd_una)
103262306a36Sopenharmony_ci{
103362306a36Sopenharmony_ci	msk->bytes_acked += new_snd_una - msk->snd_una;
103462306a36Sopenharmony_ci	msk->snd_una = new_snd_una;
103562306a36Sopenharmony_ci}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_cistatic void ack_update_msk(struct mptcp_sock *msk,
103862306a36Sopenharmony_ci			   struct sock *ssk,
103962306a36Sopenharmony_ci			   struct mptcp_options_received *mp_opt)
104062306a36Sopenharmony_ci{
104162306a36Sopenharmony_ci	u64 new_wnd_end, new_snd_una, snd_nxt = READ_ONCE(msk->snd_nxt);
104262306a36Sopenharmony_ci	struct sock *sk = (struct sock *)msk;
104362306a36Sopenharmony_ci	u64 old_snd_una;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	mptcp_data_lock(sk);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	/* avoid ack expansion on update conflict, to reduce the risk of
104862306a36Sopenharmony_ci	 * wrongly expanding to a future ack sequence number, which is way
104962306a36Sopenharmony_ci	 * more dangerous than missing an ack
105062306a36Sopenharmony_ci	 */
105162306a36Sopenharmony_ci	old_snd_una = msk->snd_una;
105262306a36Sopenharmony_ci	new_snd_una = mptcp_expand_seq(old_snd_una, mp_opt->data_ack, mp_opt->ack64);
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	/* ACK for data not even sent yet? Ignore.*/
105562306a36Sopenharmony_ci	if (unlikely(after64(new_snd_una, snd_nxt)))
105662306a36Sopenharmony_ci		new_snd_una = old_snd_una;
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	new_wnd_end = new_snd_una + tcp_sk(ssk)->snd_wnd;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	if (after64(new_wnd_end, msk->wnd_end))
106162306a36Sopenharmony_ci		msk->wnd_end = new_wnd_end;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	/* this assumes mptcp_incoming_options() is invoked after tcp_ack() */
106462306a36Sopenharmony_ci	if (after64(msk->wnd_end, READ_ONCE(msk->snd_nxt)))
106562306a36Sopenharmony_ci		__mptcp_check_push(sk, ssk);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	if (after64(new_snd_una, old_snd_una)) {
106862306a36Sopenharmony_ci		__mptcp_snd_una_update(msk, new_snd_una);
106962306a36Sopenharmony_ci		__mptcp_data_acked(sk);
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci	mptcp_data_unlock(sk);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	trace_ack_update_msk(mp_opt->data_ack,
107462306a36Sopenharmony_ci			     old_snd_una, new_snd_una,
107562306a36Sopenharmony_ci			     new_wnd_end, msk->wnd_end);
107662306a36Sopenharmony_ci}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_cibool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit)
107962306a36Sopenharmony_ci{
108062306a36Sopenharmony_ci	/* Skip if DATA_FIN was already received.
108162306a36Sopenharmony_ci	 * If updating simultaneously with the recvmsg loop, values
108262306a36Sopenharmony_ci	 * should match. If they mismatch, the peer is misbehaving and
108362306a36Sopenharmony_ci	 * we will prefer the most recent information.
108462306a36Sopenharmony_ci	 */
108562306a36Sopenharmony_ci	if (READ_ONCE(msk->rcv_data_fin))
108662306a36Sopenharmony_ci		return false;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	WRITE_ONCE(msk->rcv_data_fin_seq,
108962306a36Sopenharmony_ci		   mptcp_expand_seq(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
109062306a36Sopenharmony_ci	WRITE_ONCE(msk->rcv_data_fin, 1);
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	return true;
109362306a36Sopenharmony_ci}
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_cistatic bool add_addr_hmac_valid(struct mptcp_sock *msk,
109662306a36Sopenharmony_ci				struct mptcp_options_received *mp_opt)
109762306a36Sopenharmony_ci{
109862306a36Sopenharmony_ci	u64 hmac = 0;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	if (mp_opt->echo)
110162306a36Sopenharmony_ci		return true;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	hmac = add_addr_generate_hmac(msk->remote_key,
110462306a36Sopenharmony_ci				      msk->local_key,
110562306a36Sopenharmony_ci				      &mp_opt->addr);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	pr_debug("msk=%p, ahmac=%llu, mp_opt->ahmac=%llu\n",
110862306a36Sopenharmony_ci		 msk, hmac, mp_opt->ahmac);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	return hmac == mp_opt->ahmac;
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci/* Return false if a subflow has been reset, else return true */
111462306a36Sopenharmony_cibool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
111562306a36Sopenharmony_ci{
111662306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
111762306a36Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
111862306a36Sopenharmony_ci	struct mptcp_options_received mp_opt;
111962306a36Sopenharmony_ci	struct mptcp_ext *mpext;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	if (__mptcp_check_fallback(msk)) {
112262306a36Sopenharmony_ci		/* Keep it simple and unconditionally trigger send data cleanup and
112362306a36Sopenharmony_ci		 * pending queue spooling. We will need to acquire the data lock
112462306a36Sopenharmony_ci		 * for more accurate checks, and once the lock is acquired, such
112562306a36Sopenharmony_ci		 * helpers are cheap.
112662306a36Sopenharmony_ci		 */
112762306a36Sopenharmony_ci		mptcp_data_lock(subflow->conn);
112862306a36Sopenharmony_ci		if (sk_stream_memory_free(sk))
112962306a36Sopenharmony_ci			__mptcp_check_push(subflow->conn, sk);
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci		/* on fallback we just need to ignore the msk-level snd_una, as
113262306a36Sopenharmony_ci		 * this is really plain TCP
113362306a36Sopenharmony_ci		 */
113462306a36Sopenharmony_ci		__mptcp_snd_una_update(msk, READ_ONCE(msk->snd_nxt));
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci		__mptcp_data_acked(subflow->conn);
113762306a36Sopenharmony_ci		mptcp_data_unlock(subflow->conn);
113862306a36Sopenharmony_ci		return true;
113962306a36Sopenharmony_ci	}
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	mptcp_get_options(skb, &mp_opt);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	/* The subflow can be in close state only if check_fully_established()
114462306a36Sopenharmony_ci	 * just sent a reset. If so, tell the caller to ignore the current packet.
114562306a36Sopenharmony_ci	 */
114662306a36Sopenharmony_ci	if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
114762306a36Sopenharmony_ci		return sk->sk_state != TCP_CLOSE;
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	if (unlikely(mp_opt.suboptions != OPTION_MPTCP_DSS)) {
115062306a36Sopenharmony_ci		if ((mp_opt.suboptions & OPTION_MPTCP_FASTCLOSE) &&
115162306a36Sopenharmony_ci		    msk->local_key == mp_opt.rcvr_key) {
115262306a36Sopenharmony_ci			WRITE_ONCE(msk->rcv_fastclose, true);
115362306a36Sopenharmony_ci			mptcp_schedule_work((struct sock *)msk);
115462306a36Sopenharmony_ci			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSERX);
115562306a36Sopenharmony_ci		}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci		if ((mp_opt.suboptions & OPTION_MPTCP_ADD_ADDR) &&
115862306a36Sopenharmony_ci		    add_addr_hmac_valid(msk, &mp_opt)) {
115962306a36Sopenharmony_ci			if (!mp_opt.echo) {
116062306a36Sopenharmony_ci				mptcp_pm_add_addr_received(sk, &mp_opt.addr);
116162306a36Sopenharmony_ci				MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
116262306a36Sopenharmony_ci			} else {
116362306a36Sopenharmony_ci				mptcp_pm_add_addr_echoed(msk, &mp_opt.addr);
116462306a36Sopenharmony_ci				mptcp_pm_del_add_timer(msk, &mp_opt.addr, true);
116562306a36Sopenharmony_ci				MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
116662306a36Sopenharmony_ci			}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci			if (mp_opt.addr.port)
116962306a36Sopenharmony_ci				MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_PORTADD);
117062306a36Sopenharmony_ci		}
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci		if (mp_opt.suboptions & OPTION_MPTCP_RM_ADDR)
117362306a36Sopenharmony_ci			mptcp_pm_rm_addr_received(msk, &mp_opt.rm_list);
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci		if (mp_opt.suboptions & OPTION_MPTCP_PRIO) {
117662306a36Sopenharmony_ci			mptcp_pm_mp_prio_received(sk, mp_opt.backup);
117762306a36Sopenharmony_ci			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPPRIORX);
117862306a36Sopenharmony_ci		}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci		if (mp_opt.suboptions & OPTION_MPTCP_FAIL) {
118162306a36Sopenharmony_ci			mptcp_pm_mp_fail_received(sk, mp_opt.fail_seq);
118262306a36Sopenharmony_ci			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFAILRX);
118362306a36Sopenharmony_ci		}
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci		if (mp_opt.suboptions & OPTION_MPTCP_RST) {
118662306a36Sopenharmony_ci			subflow->reset_seen = 1;
118762306a36Sopenharmony_ci			subflow->reset_reason = mp_opt.reset_reason;
118862306a36Sopenharmony_ci			subflow->reset_transient = mp_opt.reset_transient;
118962306a36Sopenharmony_ci			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTRX);
119062306a36Sopenharmony_ci		}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci		if (!(mp_opt.suboptions & OPTION_MPTCP_DSS))
119362306a36Sopenharmony_ci			return true;
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	/* we can't wait for recvmsg() to update the ack_seq, otherwise
119762306a36Sopenharmony_ci	 * monodirectional flows will stuck
119862306a36Sopenharmony_ci	 */
119962306a36Sopenharmony_ci	if (mp_opt.use_ack)
120062306a36Sopenharmony_ci		ack_update_msk(msk, sk, &mp_opt);
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	/* Zero-data-length packets are dropped by the caller and not
120362306a36Sopenharmony_ci	 * propagated to the MPTCP layer, so the skb extension does not
120462306a36Sopenharmony_ci	 * need to be allocated or populated. DATA_FIN information, if
120562306a36Sopenharmony_ci	 * present, needs to be updated here before the skb is freed.
120662306a36Sopenharmony_ci	 */
120762306a36Sopenharmony_ci	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
120862306a36Sopenharmony_ci		if (mp_opt.data_fin && mp_opt.data_len == 1 &&
120962306a36Sopenharmony_ci		    mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64))
121062306a36Sopenharmony_ci			mptcp_schedule_work((struct sock *)msk);
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci		return true;
121362306a36Sopenharmony_ci	}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
121662306a36Sopenharmony_ci	if (!mpext)
121762306a36Sopenharmony_ci		return true;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	memset(mpext, 0, sizeof(*mpext));
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	if (likely(mp_opt.use_map)) {
122262306a36Sopenharmony_ci		if (mp_opt.mpc_map) {
122362306a36Sopenharmony_ci			/* this is an MP_CAPABLE carrying MPTCP data
122462306a36Sopenharmony_ci			 * we know this map the first chunk of data
122562306a36Sopenharmony_ci			 */
122662306a36Sopenharmony_ci			mptcp_crypto_key_sha(subflow->remote_key, NULL,
122762306a36Sopenharmony_ci					     &mpext->data_seq);
122862306a36Sopenharmony_ci			mpext->data_seq++;
122962306a36Sopenharmony_ci			mpext->subflow_seq = 1;
123062306a36Sopenharmony_ci			mpext->dsn64 = 1;
123162306a36Sopenharmony_ci			mpext->mpc_map = 1;
123262306a36Sopenharmony_ci			mpext->data_fin = 0;
123362306a36Sopenharmony_ci		} else {
123462306a36Sopenharmony_ci			mpext->data_seq = mp_opt.data_seq;
123562306a36Sopenharmony_ci			mpext->subflow_seq = mp_opt.subflow_seq;
123662306a36Sopenharmony_ci			mpext->dsn64 = mp_opt.dsn64;
123762306a36Sopenharmony_ci			mpext->data_fin = mp_opt.data_fin;
123862306a36Sopenharmony_ci		}
123962306a36Sopenharmony_ci		mpext->data_len = mp_opt.data_len;
124062306a36Sopenharmony_ci		mpext->use_map = 1;
124162306a36Sopenharmony_ci		mpext->csum_reqd = !!(mp_opt.suboptions & OPTION_MPTCP_CSUMREQD);
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci		if (mpext->csum_reqd)
124462306a36Sopenharmony_ci			mpext->csum = mp_opt.csum;
124562306a36Sopenharmony_ci	}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	return true;
124862306a36Sopenharmony_ci}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_cistatic void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th)
125162306a36Sopenharmony_ci{
125262306a36Sopenharmony_ci	const struct sock *ssk = (const struct sock *)tp;
125362306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow;
125462306a36Sopenharmony_ci	u64 ack_seq, rcv_wnd_old, rcv_wnd_new;
125562306a36Sopenharmony_ci	struct mptcp_sock *msk;
125662306a36Sopenharmony_ci	u32 new_win;
125762306a36Sopenharmony_ci	u64 win;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	subflow = mptcp_subflow_ctx(ssk);
126062306a36Sopenharmony_ci	msk = mptcp_sk(subflow->conn);
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	ack_seq = READ_ONCE(msk->ack_seq);
126362306a36Sopenharmony_ci	rcv_wnd_new = ack_seq + tp->rcv_wnd;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	rcv_wnd_old = atomic64_read(&msk->rcv_wnd_sent);
126662306a36Sopenharmony_ci	if (after64(rcv_wnd_new, rcv_wnd_old)) {
126762306a36Sopenharmony_ci		u64 rcv_wnd;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci		for (;;) {
127062306a36Sopenharmony_ci			rcv_wnd = atomic64_cmpxchg(&msk->rcv_wnd_sent, rcv_wnd_old, rcv_wnd_new);
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci			if (rcv_wnd == rcv_wnd_old)
127362306a36Sopenharmony_ci				break;
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci			rcv_wnd_old = rcv_wnd;
127662306a36Sopenharmony_ci			if (before64(rcv_wnd_new, rcv_wnd_old)) {
127762306a36Sopenharmony_ci				MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDCONFLICTUPDATE);
127862306a36Sopenharmony_ci				goto raise_win;
127962306a36Sopenharmony_ci			}
128062306a36Sopenharmony_ci			MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDCONFLICT);
128162306a36Sopenharmony_ci		}
128262306a36Sopenharmony_ci		return;
128362306a36Sopenharmony_ci	}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	if (rcv_wnd_new != rcv_wnd_old) {
128662306a36Sopenharmony_ciraise_win:
128762306a36Sopenharmony_ci		win = rcv_wnd_old - ack_seq;
128862306a36Sopenharmony_ci		tp->rcv_wnd = min_t(u64, win, U32_MAX);
128962306a36Sopenharmony_ci		new_win = tp->rcv_wnd;
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci		/* Make sure we do not exceed the maximum possible
129262306a36Sopenharmony_ci		 * scaled window.
129362306a36Sopenharmony_ci		 */
129462306a36Sopenharmony_ci		if (unlikely(th->syn))
129562306a36Sopenharmony_ci			new_win = min(new_win, 65535U) << tp->rx_opt.rcv_wscale;
129662306a36Sopenharmony_ci		if (!tp->rx_opt.rcv_wscale &&
129762306a36Sopenharmony_ci		    READ_ONCE(sock_net(ssk)->ipv4.sysctl_tcp_workaround_signed_windows))
129862306a36Sopenharmony_ci			new_win = min(new_win, MAX_TCP_WINDOW);
129962306a36Sopenharmony_ci		else
130062306a36Sopenharmony_ci			new_win = min(new_win, (65535U << tp->rx_opt.rcv_wscale));
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci		/* RFC1323 scaling applied */
130362306a36Sopenharmony_ci		new_win >>= tp->rx_opt.rcv_wscale;
130462306a36Sopenharmony_ci		th->window = htons(new_win);
130562306a36Sopenharmony_ci		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDSHARED);
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci__sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum)
131062306a36Sopenharmony_ci{
131162306a36Sopenharmony_ci	struct csum_pseudo_header header;
131262306a36Sopenharmony_ci	__wsum csum;
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	/* cfr RFC 8684 3.3.1.:
131562306a36Sopenharmony_ci	 * the data sequence number used in the pseudo-header is
131662306a36Sopenharmony_ci	 * always the 64-bit value, irrespective of what length is used in the
131762306a36Sopenharmony_ci	 * DSS option itself.
131862306a36Sopenharmony_ci	 */
131962306a36Sopenharmony_ci	header.data_seq = cpu_to_be64(data_seq);
132062306a36Sopenharmony_ci	header.subflow_seq = htonl(subflow_seq);
132162306a36Sopenharmony_ci	header.data_len = htons(data_len);
132262306a36Sopenharmony_ci	header.csum = 0;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	csum = csum_partial(&header, sizeof(header), sum);
132562306a36Sopenharmony_ci	return csum_fold(csum);
132662306a36Sopenharmony_ci}
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_cistatic __sum16 mptcp_make_csum(const struct mptcp_ext *mpext)
132962306a36Sopenharmony_ci{
133062306a36Sopenharmony_ci	return __mptcp_make_csum(mpext->data_seq, mpext->subflow_seq, mpext->data_len,
133162306a36Sopenharmony_ci				 ~csum_unfold(mpext->csum));
133262306a36Sopenharmony_ci}
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_cistatic void put_len_csum(u16 len, __sum16 csum, void *data)
133562306a36Sopenharmony_ci{
133662306a36Sopenharmony_ci	__sum16 *sumptr = data + 2;
133762306a36Sopenharmony_ci	__be16 *ptr = data;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	put_unaligned_be16(len, ptr);
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	put_unaligned(csum, sumptr);
134262306a36Sopenharmony_ci}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_civoid mptcp_write_options(struct tcphdr *th, __be32 *ptr, struct tcp_sock *tp,
134562306a36Sopenharmony_ci			 struct mptcp_out_options *opts)
134662306a36Sopenharmony_ci{
134762306a36Sopenharmony_ci	const struct sock *ssk = (const struct sock *)tp;
134862306a36Sopenharmony_ci	struct mptcp_subflow_context *subflow;
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	/* Which options can be used together?
135162306a36Sopenharmony_ci	 *
135262306a36Sopenharmony_ci	 * X: mutually exclusive
135362306a36Sopenharmony_ci	 * O: often used together
135462306a36Sopenharmony_ci	 * C: can be used together in some cases
135562306a36Sopenharmony_ci	 * P: could be used together but we prefer not to (optimisations)
135662306a36Sopenharmony_ci	 *
135762306a36Sopenharmony_ci	 *  Opt: | MPC  | MPJ  | DSS  | ADD  |  RM  | PRIO | FAIL |  FC  |
135862306a36Sopenharmony_ci	 * ------|------|------|------|------|------|------|------|------|
135962306a36Sopenharmony_ci	 *  MPC  |------|------|------|------|------|------|------|------|
136062306a36Sopenharmony_ci	 *  MPJ  |  X   |------|------|------|------|------|------|------|
136162306a36Sopenharmony_ci	 *  DSS  |  X   |  X   |------|------|------|------|------|------|
136262306a36Sopenharmony_ci	 *  ADD  |  X   |  X   |  P   |------|------|------|------|------|
136362306a36Sopenharmony_ci	 *  RM   |  C   |  C   |  C   |  P   |------|------|------|------|
136462306a36Sopenharmony_ci	 *  PRIO |  X   |  C   |  C   |  C   |  C   |------|------|------|
136562306a36Sopenharmony_ci	 *  FAIL |  X   |  X   |  C   |  X   |  X   |  X   |------|------|
136662306a36Sopenharmony_ci	 *  FC   |  X   |  X   |  X   |  X   |  X   |  X   |  X   |------|
136762306a36Sopenharmony_ci	 *  RST  |  X   |  X   |  X   |  X   |  X   |  X   |  O   |  O   |
136862306a36Sopenharmony_ci	 * ------|------|------|------|------|------|------|------|------|
136962306a36Sopenharmony_ci	 *
137062306a36Sopenharmony_ci	 * The same applies in mptcp_established_options() function.
137162306a36Sopenharmony_ci	 */
137262306a36Sopenharmony_ci	if (likely(OPTION_MPTCP_DSS & opts->suboptions)) {
137362306a36Sopenharmony_ci		struct mptcp_ext *mpext = &opts->ext_copy;
137462306a36Sopenharmony_ci		u8 len = TCPOLEN_MPTCP_DSS_BASE;
137562306a36Sopenharmony_ci		u8 flags = 0;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci		if (mpext->use_ack) {
137862306a36Sopenharmony_ci			flags = MPTCP_DSS_HAS_ACK;
137962306a36Sopenharmony_ci			if (mpext->ack64) {
138062306a36Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_ACK64;
138162306a36Sopenharmony_ci				flags |= MPTCP_DSS_ACK64;
138262306a36Sopenharmony_ci			} else {
138362306a36Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_ACK32;
138462306a36Sopenharmony_ci			}
138562306a36Sopenharmony_ci		}
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci		if (mpext->use_map) {
138862306a36Sopenharmony_ci			len += TCPOLEN_MPTCP_DSS_MAP64;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci			/* Use only 64-bit mapping flags for now, add
139162306a36Sopenharmony_ci			 * support for optional 32-bit mappings later.
139262306a36Sopenharmony_ci			 */
139362306a36Sopenharmony_ci			flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64;
139462306a36Sopenharmony_ci			if (mpext->data_fin)
139562306a36Sopenharmony_ci				flags |= MPTCP_DSS_DATA_FIN;
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci			if (opts->csum_reqd)
139862306a36Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_CHECKSUM;
139962306a36Sopenharmony_ci		}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci		if (mpext->use_ack) {
140462306a36Sopenharmony_ci			if (mpext->ack64) {
140562306a36Sopenharmony_ci				put_unaligned_be64(mpext->data_ack, ptr);
140662306a36Sopenharmony_ci				ptr += 2;
140762306a36Sopenharmony_ci			} else {
140862306a36Sopenharmony_ci				put_unaligned_be32(mpext->data_ack32, ptr);
140962306a36Sopenharmony_ci				ptr += 1;
141062306a36Sopenharmony_ci			}
141162306a36Sopenharmony_ci		}
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci		if (mpext->use_map) {
141462306a36Sopenharmony_ci			put_unaligned_be64(mpext->data_seq, ptr);
141562306a36Sopenharmony_ci			ptr += 2;
141662306a36Sopenharmony_ci			put_unaligned_be32(mpext->subflow_seq, ptr);
141762306a36Sopenharmony_ci			ptr += 1;
141862306a36Sopenharmony_ci			if (opts->csum_reqd) {
141962306a36Sopenharmony_ci				/* data_len == 0 is reserved for the infinite mapping,
142062306a36Sopenharmony_ci				 * the checksum will also be set to 0.
142162306a36Sopenharmony_ci				 */
142262306a36Sopenharmony_ci				put_len_csum(mpext->data_len,
142362306a36Sopenharmony_ci					     (mpext->data_len ? mptcp_make_csum(mpext) : 0),
142462306a36Sopenharmony_ci					     ptr);
142562306a36Sopenharmony_ci			} else {
142662306a36Sopenharmony_ci				put_unaligned_be32(mpext->data_len << 16 |
142762306a36Sopenharmony_ci						   TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
142862306a36Sopenharmony_ci			}
142962306a36Sopenharmony_ci			ptr += 1;
143062306a36Sopenharmony_ci		}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci		/* We might need to add MP_FAIL options in rare cases */
143362306a36Sopenharmony_ci		if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions))
143462306a36Sopenharmony_ci			goto mp_fail;
143562306a36Sopenharmony_ci	} else if (OPTIONS_MPTCP_MPC & opts->suboptions) {
143662306a36Sopenharmony_ci		u8 len, flag = MPTCP_CAP_HMAC_SHA256;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci		if (OPTION_MPTCP_MPC_SYN & opts->suboptions) {
143962306a36Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_SYN;
144062306a36Sopenharmony_ci		} else if (OPTION_MPTCP_MPC_SYNACK & opts->suboptions) {
144162306a36Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_SYNACK;
144262306a36Sopenharmony_ci		} else if (opts->data_len) {
144362306a36Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_ACK_DATA;
144462306a36Sopenharmony_ci			if (opts->csum_reqd)
144562306a36Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_CHECKSUM;
144662306a36Sopenharmony_ci		} else {
144762306a36Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_ACK;
144862306a36Sopenharmony_ci		}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci		if (opts->csum_reqd)
145162306a36Sopenharmony_ci			flag |= MPTCP_CAP_CHECKSUM_REQD;
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci		if (!opts->allow_join_id0)
145462306a36Sopenharmony_ci			flag |= MPTCP_CAP_DENY_JOIN_ID0;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_CAPABLE, len,
145762306a36Sopenharmony_ci				      MPTCP_SUPPORTED_VERSION,
145862306a36Sopenharmony_ci				      flag);
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci		if (!((OPTION_MPTCP_MPC_SYNACK | OPTION_MPTCP_MPC_ACK) &
146162306a36Sopenharmony_ci		    opts->suboptions))
146262306a36Sopenharmony_ci			goto mp_capable_done;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci		put_unaligned_be64(opts->sndr_key, ptr);
146562306a36Sopenharmony_ci		ptr += 2;
146662306a36Sopenharmony_ci		if (!((OPTION_MPTCP_MPC_ACK) & opts->suboptions))
146762306a36Sopenharmony_ci			goto mp_capable_done;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci		put_unaligned_be64(opts->rcvr_key, ptr);
147062306a36Sopenharmony_ci		ptr += 2;
147162306a36Sopenharmony_ci		if (!opts->data_len)
147262306a36Sopenharmony_ci			goto mp_capable_done;
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci		if (opts->csum_reqd) {
147562306a36Sopenharmony_ci			put_len_csum(opts->data_len,
147662306a36Sopenharmony_ci				     __mptcp_make_csum(opts->data_seq,
147762306a36Sopenharmony_ci						       opts->subflow_seq,
147862306a36Sopenharmony_ci						       opts->data_len,
147962306a36Sopenharmony_ci						       ~csum_unfold(opts->csum)),
148062306a36Sopenharmony_ci				     ptr);
148162306a36Sopenharmony_ci		} else {
148262306a36Sopenharmony_ci			put_unaligned_be32(opts->data_len << 16 |
148362306a36Sopenharmony_ci					   TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
148462306a36Sopenharmony_ci		}
148562306a36Sopenharmony_ci		ptr += 1;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci		/* MPC is additionally mutually exclusive with MP_PRIO */
148862306a36Sopenharmony_ci		goto mp_capable_done;
148962306a36Sopenharmony_ci	} else if (OPTIONS_MPTCP_MPJ & opts->suboptions) {
149062306a36Sopenharmony_ci		if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
149162306a36Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
149262306a36Sopenharmony_ci					      TCPOLEN_MPTCP_MPJ_SYN,
149362306a36Sopenharmony_ci					      opts->backup, opts->join_id);
149462306a36Sopenharmony_ci			put_unaligned_be32(opts->token, ptr);
149562306a36Sopenharmony_ci			ptr += 1;
149662306a36Sopenharmony_ci			put_unaligned_be32(opts->nonce, ptr);
149762306a36Sopenharmony_ci			ptr += 1;
149862306a36Sopenharmony_ci		} else if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
149962306a36Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
150062306a36Sopenharmony_ci					      TCPOLEN_MPTCP_MPJ_SYNACK,
150162306a36Sopenharmony_ci					      opts->backup, opts->join_id);
150262306a36Sopenharmony_ci			put_unaligned_be64(opts->thmac, ptr);
150362306a36Sopenharmony_ci			ptr += 2;
150462306a36Sopenharmony_ci			put_unaligned_be32(opts->nonce, ptr);
150562306a36Sopenharmony_ci			ptr += 1;
150662306a36Sopenharmony_ci		} else {
150762306a36Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
150862306a36Sopenharmony_ci					      TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
150962306a36Sopenharmony_ci			memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
151062306a36Sopenharmony_ci			ptr += 5;
151162306a36Sopenharmony_ci		}
151262306a36Sopenharmony_ci	} else if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) {
151362306a36Sopenharmony_ci		u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE;
151462306a36Sopenharmony_ci		u8 echo = MPTCP_ADDR_ECHO;
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
151762306a36Sopenharmony_ci		if (opts->addr.family == AF_INET6)
151862306a36Sopenharmony_ci			len = TCPOLEN_MPTCP_ADD_ADDR6_BASE;
151962306a36Sopenharmony_ci#endif
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci		if (opts->addr.port)
152262306a36Sopenharmony_ci			len += TCPOLEN_MPTCP_PORT_LEN;
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci		if (opts->ahmac) {
152562306a36Sopenharmony_ci			len += sizeof(opts->ahmac);
152662306a36Sopenharmony_ci			echo = 0;
152762306a36Sopenharmony_ci		}
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_ADD_ADDR,
153062306a36Sopenharmony_ci				      len, echo, opts->addr.id);
153162306a36Sopenharmony_ci		if (opts->addr.family == AF_INET) {
153262306a36Sopenharmony_ci			memcpy((u8 *)ptr, (u8 *)&opts->addr.addr.s_addr, 4);
153362306a36Sopenharmony_ci			ptr += 1;
153462306a36Sopenharmony_ci		}
153562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
153662306a36Sopenharmony_ci		else if (opts->addr.family == AF_INET6) {
153762306a36Sopenharmony_ci			memcpy((u8 *)ptr, opts->addr.addr6.s6_addr, 16);
153862306a36Sopenharmony_ci			ptr += 4;
153962306a36Sopenharmony_ci		}
154062306a36Sopenharmony_ci#endif
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci		if (!opts->addr.port) {
154362306a36Sopenharmony_ci			if (opts->ahmac) {
154462306a36Sopenharmony_ci				put_unaligned_be64(opts->ahmac, ptr);
154562306a36Sopenharmony_ci				ptr += 2;
154662306a36Sopenharmony_ci			}
154762306a36Sopenharmony_ci		} else {
154862306a36Sopenharmony_ci			u16 port = ntohs(opts->addr.port);
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci			if (opts->ahmac) {
155162306a36Sopenharmony_ci				u8 *bptr = (u8 *)ptr;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci				put_unaligned_be16(port, bptr);
155462306a36Sopenharmony_ci				bptr += 2;
155562306a36Sopenharmony_ci				put_unaligned_be64(opts->ahmac, bptr);
155662306a36Sopenharmony_ci				bptr += 8;
155762306a36Sopenharmony_ci				put_unaligned_be16(TCPOPT_NOP << 8 |
155862306a36Sopenharmony_ci						   TCPOPT_NOP, bptr);
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci				ptr += 3;
156162306a36Sopenharmony_ci			} else {
156262306a36Sopenharmony_ci				put_unaligned_be32(port << 16 |
156362306a36Sopenharmony_ci						   TCPOPT_NOP << 8 |
156462306a36Sopenharmony_ci						   TCPOPT_NOP, ptr);
156562306a36Sopenharmony_ci				ptr += 1;
156662306a36Sopenharmony_ci			}
156762306a36Sopenharmony_ci		}
156862306a36Sopenharmony_ci	} else if (unlikely(OPTION_MPTCP_FASTCLOSE & opts->suboptions)) {
156962306a36Sopenharmony_ci		/* FASTCLOSE is mutually exclusive with others except RST */
157062306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_FASTCLOSE,
157162306a36Sopenharmony_ci				      TCPOLEN_MPTCP_FASTCLOSE,
157262306a36Sopenharmony_ci				      0, 0);
157362306a36Sopenharmony_ci		put_unaligned_be64(opts->rcvr_key, ptr);
157462306a36Sopenharmony_ci		ptr += 2;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci		if (OPTION_MPTCP_RST & opts->suboptions)
157762306a36Sopenharmony_ci			goto mp_rst;
157862306a36Sopenharmony_ci		return;
157962306a36Sopenharmony_ci	} else if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions)) {
158062306a36Sopenharmony_cimp_fail:
158162306a36Sopenharmony_ci		/* MP_FAIL is mutually exclusive with others except RST */
158262306a36Sopenharmony_ci		subflow = mptcp_subflow_ctx(ssk);
158362306a36Sopenharmony_ci		subflow->send_mp_fail = 0;
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_FAIL,
158662306a36Sopenharmony_ci				      TCPOLEN_MPTCP_FAIL,
158762306a36Sopenharmony_ci				      0, 0);
158862306a36Sopenharmony_ci		put_unaligned_be64(opts->fail_seq, ptr);
158962306a36Sopenharmony_ci		ptr += 2;
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci		if (OPTION_MPTCP_RST & opts->suboptions)
159262306a36Sopenharmony_ci			goto mp_rst;
159362306a36Sopenharmony_ci		return;
159462306a36Sopenharmony_ci	} else if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) {
159562306a36Sopenharmony_cimp_rst:
159662306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_RST,
159762306a36Sopenharmony_ci				      TCPOLEN_MPTCP_RST,
159862306a36Sopenharmony_ci				      opts->reset_transient,
159962306a36Sopenharmony_ci				      opts->reset_reason);
160062306a36Sopenharmony_ci		return;
160162306a36Sopenharmony_ci	}
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	if (OPTION_MPTCP_PRIO & opts->suboptions) {
160462306a36Sopenharmony_ci		subflow = mptcp_subflow_ctx(ssk);
160562306a36Sopenharmony_ci		subflow->send_mp_prio = 0;
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_PRIO,
160862306a36Sopenharmony_ci				      TCPOLEN_MPTCP_PRIO,
160962306a36Sopenharmony_ci				      opts->backup, TCPOPT_NOP);
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci		MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPPRIOTX);
161262306a36Sopenharmony_ci	}
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_cimp_capable_done:
161562306a36Sopenharmony_ci	if (OPTION_MPTCP_RM_ADDR & opts->suboptions) {
161662306a36Sopenharmony_ci		u8 i = 1;
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_RM_ADDR,
161962306a36Sopenharmony_ci				      TCPOLEN_MPTCP_RM_ADDR_BASE + opts->rm_list.nr,
162062306a36Sopenharmony_ci				      0, opts->rm_list.ids[0]);
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci		while (i < opts->rm_list.nr) {
162362306a36Sopenharmony_ci			u8 id1, id2, id3, id4;
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci			id1 = opts->rm_list.ids[i];
162662306a36Sopenharmony_ci			id2 = i + 1 < opts->rm_list.nr ? opts->rm_list.ids[i + 1] : TCPOPT_NOP;
162762306a36Sopenharmony_ci			id3 = i + 2 < opts->rm_list.nr ? opts->rm_list.ids[i + 2] : TCPOPT_NOP;
162862306a36Sopenharmony_ci			id4 = i + 3 < opts->rm_list.nr ? opts->rm_list.ids[i + 3] : TCPOPT_NOP;
162962306a36Sopenharmony_ci			put_unaligned_be32(id1 << 24 | id2 << 16 | id3 << 8 | id4, ptr);
163062306a36Sopenharmony_ci			ptr += 1;
163162306a36Sopenharmony_ci			i += 4;
163262306a36Sopenharmony_ci		}
163362306a36Sopenharmony_ci	}
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	if (tp)
163662306a36Sopenharmony_ci		mptcp_set_rwin(tp, th);
163762306a36Sopenharmony_ci}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_ci__be32 mptcp_get_reset_option(const struct sk_buff *skb)
164062306a36Sopenharmony_ci{
164162306a36Sopenharmony_ci	const struct mptcp_ext *ext = mptcp_get_ext(skb);
164262306a36Sopenharmony_ci	u8 flags, reason;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	if (ext) {
164562306a36Sopenharmony_ci		flags = ext->reset_transient;
164662306a36Sopenharmony_ci		reason = ext->reset_reason;
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci		return mptcp_option(MPTCPOPT_RST, TCPOLEN_MPTCP_RST,
164962306a36Sopenharmony_ci				    flags, reason);
165062306a36Sopenharmony_ci	}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	return htonl(0u);
165362306a36Sopenharmony_ci}
165462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mptcp_get_reset_option);
1655