18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Multipath TCP
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2017 - 2019, Intel Corporation.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "MPTCP: " fmt
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <crypto/sha.h>
118c2ecf20Sopenharmony_ci#include <net/tcp.h>
128c2ecf20Sopenharmony_ci#include <net/mptcp.h>
138c2ecf20Sopenharmony_ci#include "protocol.h"
148c2ecf20Sopenharmony_ci#include "mib.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic bool mptcp_cap_flag_sha256(u8 flags)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic void mptcp_parse_option(const struct sk_buff *skb,
228c2ecf20Sopenharmony_ci			       const unsigned char *ptr, int opsize,
238c2ecf20Sopenharmony_ci			       struct mptcp_options_received *mp_opt)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	u8 subtype = *ptr >> 4;
268c2ecf20Sopenharmony_ci	int expected_opsize;
278c2ecf20Sopenharmony_ci	u8 version;
288c2ecf20Sopenharmony_ci	u8 flags;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	switch (subtype) {
318c2ecf20Sopenharmony_ci	case MPTCPOPT_MP_CAPABLE:
328c2ecf20Sopenharmony_ci		/* strict size checking */
338c2ecf20Sopenharmony_ci		if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
348c2ecf20Sopenharmony_ci			if (skb->len > tcp_hdr(skb)->doff << 2)
358c2ecf20Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_ACK_DATA;
368c2ecf20Sopenharmony_ci			else
378c2ecf20Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_ACK;
388c2ecf20Sopenharmony_ci		} else {
398c2ecf20Sopenharmony_ci			if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_ACK)
408c2ecf20Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_SYNACK;
418c2ecf20Sopenharmony_ci			else
428c2ecf20Sopenharmony_ci				expected_opsize = TCPOLEN_MPTCP_MPC_SYN;
438c2ecf20Sopenharmony_ci		}
448c2ecf20Sopenharmony_ci		if (opsize != expected_opsize)
458c2ecf20Sopenharmony_ci			break;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci		/* try to be gentle vs future versions on the initial syn */
488c2ecf20Sopenharmony_ci		version = *ptr++ & MPTCP_VERSION_MASK;
498c2ecf20Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_MPC_SYN) {
508c2ecf20Sopenharmony_ci			if (version != MPTCP_SUPPORTED_VERSION)
518c2ecf20Sopenharmony_ci				break;
528c2ecf20Sopenharmony_ci		} else if (version < MPTCP_SUPPORTED_VERSION) {
538c2ecf20Sopenharmony_ci			break;
548c2ecf20Sopenharmony_ci		}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci		flags = *ptr++;
578c2ecf20Sopenharmony_ci		if (!mptcp_cap_flag_sha256(flags) ||
588c2ecf20Sopenharmony_ci		    (flags & MPTCP_CAP_EXTENSIBILITY))
598c2ecf20Sopenharmony_ci			break;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci		/* RFC 6824, Section 3.1:
628c2ecf20Sopenharmony_ci		 * "For the Checksum Required bit (labeled "A"), if either
638c2ecf20Sopenharmony_ci		 * host requires the use of checksums, checksums MUST be used.
648c2ecf20Sopenharmony_ci		 * In other words, the only way for checksums not to be used
658c2ecf20Sopenharmony_ci		 * is if both hosts in their SYNs set A=0."
668c2ecf20Sopenharmony_ci		 *
678c2ecf20Sopenharmony_ci		 * Section 3.3.0:
688c2ecf20Sopenharmony_ci		 * "If a checksum is not present when its use has been
698c2ecf20Sopenharmony_ci		 * negotiated, the receiver MUST close the subflow with a RST as
708c2ecf20Sopenharmony_ci		 * it is considered broken."
718c2ecf20Sopenharmony_ci		 *
728c2ecf20Sopenharmony_ci		 * We don't implement DSS checksum - fall back to TCP.
738c2ecf20Sopenharmony_ci		 */
748c2ecf20Sopenharmony_ci		if (flags & MPTCP_CAP_CHECKSUM_REQD)
758c2ecf20Sopenharmony_ci			break;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		mp_opt->mp_capable = 1;
788c2ecf20Sopenharmony_ci		if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK) {
798c2ecf20Sopenharmony_ci			mp_opt->sndr_key = get_unaligned_be64(ptr);
808c2ecf20Sopenharmony_ci			ptr += 8;
818c2ecf20Sopenharmony_ci		}
828c2ecf20Sopenharmony_ci		if (opsize >= TCPOLEN_MPTCP_MPC_ACK) {
838c2ecf20Sopenharmony_ci			mp_opt->rcvr_key = get_unaligned_be64(ptr);
848c2ecf20Sopenharmony_ci			ptr += 8;
858c2ecf20Sopenharmony_ci		}
868c2ecf20Sopenharmony_ci		if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA) {
878c2ecf20Sopenharmony_ci			/* Section 3.1.:
888c2ecf20Sopenharmony_ci			 * "the data parameters in a MP_CAPABLE are semantically
898c2ecf20Sopenharmony_ci			 * equivalent to those in a DSS option and can be used
908c2ecf20Sopenharmony_ci			 * interchangeably."
918c2ecf20Sopenharmony_ci			 */
928c2ecf20Sopenharmony_ci			mp_opt->dss = 1;
938c2ecf20Sopenharmony_ci			mp_opt->use_map = 1;
948c2ecf20Sopenharmony_ci			mp_opt->mpc_map = 1;
958c2ecf20Sopenharmony_ci			mp_opt->use_ack = 0;
968c2ecf20Sopenharmony_ci			mp_opt->data_len = get_unaligned_be16(ptr);
978c2ecf20Sopenharmony_ci			ptr += 2;
988c2ecf20Sopenharmony_ci		}
998c2ecf20Sopenharmony_ci		pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d",
1008c2ecf20Sopenharmony_ci			 version, flags, opsize, mp_opt->sndr_key,
1018c2ecf20Sopenharmony_ci			 mp_opt->rcvr_key, mp_opt->data_len);
1028c2ecf20Sopenharmony_ci		break;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	case MPTCPOPT_MP_JOIN:
1058c2ecf20Sopenharmony_ci		mp_opt->mp_join = 1;
1068c2ecf20Sopenharmony_ci		if (opsize == TCPOLEN_MPTCP_MPJ_SYN) {
1078c2ecf20Sopenharmony_ci			mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
1088c2ecf20Sopenharmony_ci			mp_opt->join_id = *ptr++;
1098c2ecf20Sopenharmony_ci			mp_opt->token = get_unaligned_be32(ptr);
1108c2ecf20Sopenharmony_ci			ptr += 4;
1118c2ecf20Sopenharmony_ci			mp_opt->nonce = get_unaligned_be32(ptr);
1128c2ecf20Sopenharmony_ci			ptr += 4;
1138c2ecf20Sopenharmony_ci			pr_debug("MP_JOIN bkup=%u, id=%u, token=%u, nonce=%u",
1148c2ecf20Sopenharmony_ci				 mp_opt->backup, mp_opt->join_id,
1158c2ecf20Sopenharmony_ci				 mp_opt->token, mp_opt->nonce);
1168c2ecf20Sopenharmony_ci		} else if (opsize == TCPOLEN_MPTCP_MPJ_SYNACK) {
1178c2ecf20Sopenharmony_ci			mp_opt->backup = *ptr++ & MPTCPOPT_BACKUP;
1188c2ecf20Sopenharmony_ci			mp_opt->join_id = *ptr++;
1198c2ecf20Sopenharmony_ci			mp_opt->thmac = get_unaligned_be64(ptr);
1208c2ecf20Sopenharmony_ci			ptr += 8;
1218c2ecf20Sopenharmony_ci			mp_opt->nonce = get_unaligned_be32(ptr);
1228c2ecf20Sopenharmony_ci			ptr += 4;
1238c2ecf20Sopenharmony_ci			pr_debug("MP_JOIN bkup=%u, id=%u, thmac=%llu, nonce=%u",
1248c2ecf20Sopenharmony_ci				 mp_opt->backup, mp_opt->join_id,
1258c2ecf20Sopenharmony_ci				 mp_opt->thmac, mp_opt->nonce);
1268c2ecf20Sopenharmony_ci		} else if (opsize == TCPOLEN_MPTCP_MPJ_ACK) {
1278c2ecf20Sopenharmony_ci			ptr += 2;
1288c2ecf20Sopenharmony_ci			memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN);
1298c2ecf20Sopenharmony_ci			pr_debug("MP_JOIN hmac");
1308c2ecf20Sopenharmony_ci		} else {
1318c2ecf20Sopenharmony_ci			mp_opt->mp_join = 0;
1328c2ecf20Sopenharmony_ci		}
1338c2ecf20Sopenharmony_ci		break;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	case MPTCPOPT_DSS:
1368c2ecf20Sopenharmony_ci		pr_debug("DSS");
1378c2ecf20Sopenharmony_ci		ptr++;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci		/* we must clear 'mpc_map' be able to detect MP_CAPABLE
1408c2ecf20Sopenharmony_ci		 * map vs DSS map in mptcp_incoming_options(), and reconstruct
1418c2ecf20Sopenharmony_ci		 * map info accordingly
1428c2ecf20Sopenharmony_ci		 */
1438c2ecf20Sopenharmony_ci		mp_opt->mpc_map = 0;
1448c2ecf20Sopenharmony_ci		flags = (*ptr++) & MPTCP_DSS_FLAG_MASK;
1458c2ecf20Sopenharmony_ci		mp_opt->data_fin = (flags & MPTCP_DSS_DATA_FIN) != 0;
1468c2ecf20Sopenharmony_ci		mp_opt->dsn64 = (flags & MPTCP_DSS_DSN64) != 0;
1478c2ecf20Sopenharmony_ci		mp_opt->use_map = (flags & MPTCP_DSS_HAS_MAP) != 0;
1488c2ecf20Sopenharmony_ci		mp_opt->ack64 = (flags & MPTCP_DSS_ACK64) != 0;
1498c2ecf20Sopenharmony_ci		mp_opt->use_ack = (flags & MPTCP_DSS_HAS_ACK);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci		pr_debug("data_fin=%d dsn64=%d use_map=%d ack64=%d use_ack=%d",
1528c2ecf20Sopenharmony_ci			 mp_opt->data_fin, mp_opt->dsn64,
1538c2ecf20Sopenharmony_ci			 mp_opt->use_map, mp_opt->ack64,
1548c2ecf20Sopenharmony_ci			 mp_opt->use_ack);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci		expected_opsize = TCPOLEN_MPTCP_DSS_BASE;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci		if (mp_opt->use_ack) {
1598c2ecf20Sopenharmony_ci			if (mp_opt->ack64)
1608c2ecf20Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_ACK64;
1618c2ecf20Sopenharmony_ci			else
1628c2ecf20Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_ACK32;
1638c2ecf20Sopenharmony_ci		}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		if (mp_opt->use_map) {
1668c2ecf20Sopenharmony_ci			if (mp_opt->dsn64)
1678c2ecf20Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_MAP64;
1688c2ecf20Sopenharmony_ci			else
1698c2ecf20Sopenharmony_ci				expected_opsize += TCPOLEN_MPTCP_DSS_MAP32;
1708c2ecf20Sopenharmony_ci		}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci		/* RFC 6824, Section 3.3:
1738c2ecf20Sopenharmony_ci		 * If a checksum is present, but its use had
1748c2ecf20Sopenharmony_ci		 * not been negotiated in the MP_CAPABLE handshake,
1758c2ecf20Sopenharmony_ci		 * the checksum field MUST be ignored.
1768c2ecf20Sopenharmony_ci		 */
1778c2ecf20Sopenharmony_ci		if (opsize != expected_opsize &&
1788c2ecf20Sopenharmony_ci		    opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM)
1798c2ecf20Sopenharmony_ci			break;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci		mp_opt->dss = 1;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci		if (mp_opt->use_ack) {
1848c2ecf20Sopenharmony_ci			if (mp_opt->ack64) {
1858c2ecf20Sopenharmony_ci				mp_opt->data_ack = get_unaligned_be64(ptr);
1868c2ecf20Sopenharmony_ci				ptr += 8;
1878c2ecf20Sopenharmony_ci			} else {
1888c2ecf20Sopenharmony_ci				mp_opt->data_ack = get_unaligned_be32(ptr);
1898c2ecf20Sopenharmony_ci				ptr += 4;
1908c2ecf20Sopenharmony_ci			}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci			pr_debug("data_ack=%llu", mp_opt->data_ack);
1938c2ecf20Sopenharmony_ci		}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		if (mp_opt->use_map) {
1968c2ecf20Sopenharmony_ci			if (mp_opt->dsn64) {
1978c2ecf20Sopenharmony_ci				mp_opt->data_seq = get_unaligned_be64(ptr);
1988c2ecf20Sopenharmony_ci				ptr += 8;
1998c2ecf20Sopenharmony_ci			} else {
2008c2ecf20Sopenharmony_ci				mp_opt->data_seq = get_unaligned_be32(ptr);
2018c2ecf20Sopenharmony_ci				ptr += 4;
2028c2ecf20Sopenharmony_ci			}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci			mp_opt->subflow_seq = get_unaligned_be32(ptr);
2058c2ecf20Sopenharmony_ci			ptr += 4;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci			mp_opt->data_len = get_unaligned_be16(ptr);
2088c2ecf20Sopenharmony_ci			ptr += 2;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci			pr_debug("data_seq=%llu subflow_seq=%u data_len=%u",
2118c2ecf20Sopenharmony_ci				 mp_opt->data_seq, mp_opt->subflow_seq,
2128c2ecf20Sopenharmony_ci				 mp_opt->data_len);
2138c2ecf20Sopenharmony_ci		}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci		break;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	case MPTCPOPT_ADD_ADDR:
2188c2ecf20Sopenharmony_ci		mp_opt->echo = (*ptr++) & MPTCP_ADDR_ECHO;
2198c2ecf20Sopenharmony_ci		if (!mp_opt->echo) {
2208c2ecf20Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR ||
2218c2ecf20Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR_PORT)
2228c2ecf20Sopenharmony_ci				mp_opt->family = MPTCP_ADDR_IPVERSION_4;
2238c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
2248c2ecf20Sopenharmony_ci			else if (opsize == TCPOLEN_MPTCP_ADD_ADDR6 ||
2258c2ecf20Sopenharmony_ci				 opsize == TCPOLEN_MPTCP_ADD_ADDR6_PORT)
2268c2ecf20Sopenharmony_ci				mp_opt->family = MPTCP_ADDR_IPVERSION_6;
2278c2ecf20Sopenharmony_ci#endif
2288c2ecf20Sopenharmony_ci			else
2298c2ecf20Sopenharmony_ci				break;
2308c2ecf20Sopenharmony_ci		} else {
2318c2ecf20Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE ||
2328c2ecf20Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT)
2338c2ecf20Sopenharmony_ci				mp_opt->family = MPTCP_ADDR_IPVERSION_4;
2348c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
2358c2ecf20Sopenharmony_ci			else if (opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE ||
2368c2ecf20Sopenharmony_ci				 opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT)
2378c2ecf20Sopenharmony_ci				mp_opt->family = MPTCP_ADDR_IPVERSION_6;
2388c2ecf20Sopenharmony_ci#endif
2398c2ecf20Sopenharmony_ci			else
2408c2ecf20Sopenharmony_ci				break;
2418c2ecf20Sopenharmony_ci		}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		mp_opt->add_addr = 1;
2448c2ecf20Sopenharmony_ci		mp_opt->addr_id = *ptr++;
2458c2ecf20Sopenharmony_ci		pr_debug("ADD_ADDR: id=%d, echo=%d", mp_opt->addr_id, mp_opt->echo);
2468c2ecf20Sopenharmony_ci		if (mp_opt->family == MPTCP_ADDR_IPVERSION_4) {
2478c2ecf20Sopenharmony_ci			memcpy((u8 *)&mp_opt->addr.s_addr, (u8 *)ptr, 4);
2488c2ecf20Sopenharmony_ci			ptr += 4;
2498c2ecf20Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR_PORT ||
2508c2ecf20Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR_BASE_PORT) {
2518c2ecf20Sopenharmony_ci				mp_opt->port = get_unaligned_be16(ptr);
2528c2ecf20Sopenharmony_ci				ptr += 2;
2538c2ecf20Sopenharmony_ci			}
2548c2ecf20Sopenharmony_ci		}
2558c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
2568c2ecf20Sopenharmony_ci		else {
2578c2ecf20Sopenharmony_ci			memcpy(mp_opt->addr6.s6_addr, (u8 *)ptr, 16);
2588c2ecf20Sopenharmony_ci			ptr += 16;
2598c2ecf20Sopenharmony_ci			if (opsize == TCPOLEN_MPTCP_ADD_ADDR6_PORT ||
2608c2ecf20Sopenharmony_ci			    opsize == TCPOLEN_MPTCP_ADD_ADDR6_BASE_PORT) {
2618c2ecf20Sopenharmony_ci				mp_opt->port = get_unaligned_be16(ptr);
2628c2ecf20Sopenharmony_ci				ptr += 2;
2638c2ecf20Sopenharmony_ci			}
2648c2ecf20Sopenharmony_ci		}
2658c2ecf20Sopenharmony_ci#endif
2668c2ecf20Sopenharmony_ci		if (!mp_opt->echo) {
2678c2ecf20Sopenharmony_ci			mp_opt->ahmac = get_unaligned_be64(ptr);
2688c2ecf20Sopenharmony_ci			ptr += 8;
2698c2ecf20Sopenharmony_ci		}
2708c2ecf20Sopenharmony_ci		break;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	case MPTCPOPT_RM_ADDR:
2738c2ecf20Sopenharmony_ci		if (opsize != TCPOLEN_MPTCP_RM_ADDR_BASE)
2748c2ecf20Sopenharmony_ci			break;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci		ptr++;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		mp_opt->rm_addr = 1;
2798c2ecf20Sopenharmony_ci		mp_opt->rm_id = *ptr++;
2808c2ecf20Sopenharmony_ci		pr_debug("RM_ADDR: id=%d", mp_opt->rm_id);
2818c2ecf20Sopenharmony_ci		break;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	default:
2848c2ecf20Sopenharmony_ci		break;
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_civoid mptcp_get_options(const struct sk_buff *skb,
2898c2ecf20Sopenharmony_ci		       struct mptcp_options_received *mp_opt)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	const struct tcphdr *th = tcp_hdr(skb);
2928c2ecf20Sopenharmony_ci	const unsigned char *ptr;
2938c2ecf20Sopenharmony_ci	int length;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	/* initialize option status */
2968c2ecf20Sopenharmony_ci	mp_opt->mp_capable = 0;
2978c2ecf20Sopenharmony_ci	mp_opt->mp_join = 0;
2988c2ecf20Sopenharmony_ci	mp_opt->add_addr = 0;
2998c2ecf20Sopenharmony_ci	mp_opt->ahmac = 0;
3008c2ecf20Sopenharmony_ci	mp_opt->port = 0;
3018c2ecf20Sopenharmony_ci	mp_opt->rm_addr = 0;
3028c2ecf20Sopenharmony_ci	mp_opt->dss = 0;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	length = (th->doff * 4) - sizeof(struct tcphdr);
3058c2ecf20Sopenharmony_ci	ptr = (const unsigned char *)(th + 1);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	while (length > 0) {
3088c2ecf20Sopenharmony_ci		int opcode = *ptr++;
3098c2ecf20Sopenharmony_ci		int opsize;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci		switch (opcode) {
3128c2ecf20Sopenharmony_ci		case TCPOPT_EOL:
3138c2ecf20Sopenharmony_ci			return;
3148c2ecf20Sopenharmony_ci		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
3158c2ecf20Sopenharmony_ci			length--;
3168c2ecf20Sopenharmony_ci			continue;
3178c2ecf20Sopenharmony_ci		default:
3188c2ecf20Sopenharmony_ci			if (length < 2)
3198c2ecf20Sopenharmony_ci				return;
3208c2ecf20Sopenharmony_ci			opsize = *ptr++;
3218c2ecf20Sopenharmony_ci			if (opsize < 2) /* "silly options" */
3228c2ecf20Sopenharmony_ci				return;
3238c2ecf20Sopenharmony_ci			if (opsize > length)
3248c2ecf20Sopenharmony_ci				return;	/* don't parse partial options */
3258c2ecf20Sopenharmony_ci			if (opcode == TCPOPT_MPTCP)
3268c2ecf20Sopenharmony_ci				mptcp_parse_option(skb, ptr, opsize, mp_opt);
3278c2ecf20Sopenharmony_ci			ptr += opsize - 2;
3288c2ecf20Sopenharmony_ci			length -= opsize;
3298c2ecf20Sopenharmony_ci		}
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cibool mptcp_syn_options(struct sock *sk, const struct sk_buff *skb,
3348c2ecf20Sopenharmony_ci		       unsigned int *size, struct mptcp_out_options *opts)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	/* we will use snd_isn to detect first pkt [re]transmission
3398c2ecf20Sopenharmony_ci	 * in mptcp_established_options_mp()
3408c2ecf20Sopenharmony_ci	 */
3418c2ecf20Sopenharmony_ci	subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
3428c2ecf20Sopenharmony_ci	if (subflow->request_mptcp) {
3438c2ecf20Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPC_SYN;
3448c2ecf20Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPC_SYN;
3458c2ecf20Sopenharmony_ci		return true;
3468c2ecf20Sopenharmony_ci	} else if (subflow->request_join) {
3478c2ecf20Sopenharmony_ci		pr_debug("remote_token=%u, nonce=%u", subflow->remote_token,
3488c2ecf20Sopenharmony_ci			 subflow->local_nonce);
3498c2ecf20Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPJ_SYN;
3508c2ecf20Sopenharmony_ci		opts->join_id = subflow->local_id;
3518c2ecf20Sopenharmony_ci		opts->token = subflow->remote_token;
3528c2ecf20Sopenharmony_ci		opts->nonce = subflow->local_nonce;
3538c2ecf20Sopenharmony_ci		opts->backup = subflow->request_bkup;
3548c2ecf20Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPJ_SYN;
3558c2ecf20Sopenharmony_ci		return true;
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci	return false;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci/* MP_JOIN client subflow must wait for 4th ack before sending any data:
3618c2ecf20Sopenharmony_ci * TCP can't schedule delack timer before the subflow is fully established.
3628c2ecf20Sopenharmony_ci * MPTCP uses the delack timer to do 3rd ack retransmissions
3638c2ecf20Sopenharmony_ci */
3648c2ecf20Sopenharmony_cistatic void schedule_3rdack_retransmission(struct sock *sk)
3658c2ecf20Sopenharmony_ci{
3668c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk = inet_csk(sk);
3678c2ecf20Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
3688c2ecf20Sopenharmony_ci	unsigned long timeout;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	/* reschedule with a timeout above RTT, as we must look only for drop */
3718c2ecf20Sopenharmony_ci	if (tp->srtt_us)
3728c2ecf20Sopenharmony_ci		timeout = usecs_to_jiffies(tp->srtt_us >> (3 - 1));
3738c2ecf20Sopenharmony_ci	else
3748c2ecf20Sopenharmony_ci		timeout = TCP_TIMEOUT_INIT;
3758c2ecf20Sopenharmony_ci	timeout += jiffies;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	WARN_ON_ONCE(icsk->icsk_ack.pending & ICSK_ACK_TIMER);
3788c2ecf20Sopenharmony_ci	icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER;
3798c2ecf20Sopenharmony_ci	icsk->icsk_ack.timeout = timeout;
3808c2ecf20Sopenharmony_ci	sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout);
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_cistatic void clear_3rdack_retransmission(struct sock *sk)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	struct inet_connection_sock *icsk = inet_csk(sk);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	sk_stop_timer(sk, &icsk->icsk_delack_timer);
3888c2ecf20Sopenharmony_ci	icsk->icsk_ack.timeout = 0;
3898c2ecf20Sopenharmony_ci	icsk->icsk_ack.ato = 0;
3908c2ecf20Sopenharmony_ci	icsk->icsk_ack.pending &= ~(ICSK_ACK_SCHED | ICSK_ACK_TIMER);
3918c2ecf20Sopenharmony_ci}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cistatic bool mptcp_established_options_mp(struct sock *sk, struct sk_buff *skb,
3948c2ecf20Sopenharmony_ci					 unsigned int *size,
3958c2ecf20Sopenharmony_ci					 unsigned int remaining,
3968c2ecf20Sopenharmony_ci					 struct mptcp_out_options *opts)
3978c2ecf20Sopenharmony_ci{
3988c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
3998c2ecf20Sopenharmony_ci	struct mptcp_ext *mpext;
4008c2ecf20Sopenharmony_ci	unsigned int data_len;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* When skb is not available, we better over-estimate the emitted
4038c2ecf20Sopenharmony_ci	 * options len. A full DSS option (28 bytes) is longer than
4048c2ecf20Sopenharmony_ci	 * TCPOLEN_MPTCP_MPC_ACK_DATA(22) or TCPOLEN_MPTCP_MPJ_ACK(24), so
4058c2ecf20Sopenharmony_ci	 * tell the caller to defer the estimate to
4068c2ecf20Sopenharmony_ci	 * mptcp_established_options_dss(), which will reserve enough space.
4078c2ecf20Sopenharmony_ci	 */
4088c2ecf20Sopenharmony_ci	if (!skb)
4098c2ecf20Sopenharmony_ci		return false;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	/* MPC/MPJ needed only on 3rd ack packet */
4128c2ecf20Sopenharmony_ci	if (subflow->fully_established ||
4138c2ecf20Sopenharmony_ci	    subflow->snd_isn != TCP_SKB_CB(skb)->seq)
4148c2ecf20Sopenharmony_ci		return false;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	if (subflow->mp_capable) {
4178c2ecf20Sopenharmony_ci		mpext = mptcp_get_ext(skb);
4188c2ecf20Sopenharmony_ci		data_len = mpext ? mpext->data_len : 0;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci		/* we will check ext_copy.data_len in mptcp_write_options() to
4218c2ecf20Sopenharmony_ci		 * discriminate between TCPOLEN_MPTCP_MPC_ACK_DATA and
4228c2ecf20Sopenharmony_ci		 * TCPOLEN_MPTCP_MPC_ACK
4238c2ecf20Sopenharmony_ci		 */
4248c2ecf20Sopenharmony_ci		opts->ext_copy.data_len = data_len;
4258c2ecf20Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPC_ACK;
4268c2ecf20Sopenharmony_ci		opts->sndr_key = subflow->local_key;
4278c2ecf20Sopenharmony_ci		opts->rcvr_key = subflow->remote_key;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci		/* Section 3.1.
4308c2ecf20Sopenharmony_ci		 * The MP_CAPABLE option is carried on the SYN, SYN/ACK, and ACK
4318c2ecf20Sopenharmony_ci		 * packets that start the first subflow of an MPTCP connection,
4328c2ecf20Sopenharmony_ci		 * as well as the first packet that carries data
4338c2ecf20Sopenharmony_ci		 */
4348c2ecf20Sopenharmony_ci		if (data_len > 0)
4358c2ecf20Sopenharmony_ci			*size = ALIGN(TCPOLEN_MPTCP_MPC_ACK_DATA, 4);
4368c2ecf20Sopenharmony_ci		else
4378c2ecf20Sopenharmony_ci			*size = TCPOLEN_MPTCP_MPC_ACK;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci		pr_debug("subflow=%p, local_key=%llu, remote_key=%llu map_len=%d",
4408c2ecf20Sopenharmony_ci			 subflow, subflow->local_key, subflow->remote_key,
4418c2ecf20Sopenharmony_ci			 data_len);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci		return true;
4448c2ecf20Sopenharmony_ci	} else if (subflow->mp_join) {
4458c2ecf20Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPJ_ACK;
4468c2ecf20Sopenharmony_ci		memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN);
4478c2ecf20Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPJ_ACK;
4488c2ecf20Sopenharmony_ci		pr_debug("subflow=%p", subflow);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci		schedule_3rdack_retransmission(sk);
4518c2ecf20Sopenharmony_ci		return true;
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci	return false;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cistatic void mptcp_write_data_fin(struct mptcp_subflow_context *subflow,
4578c2ecf20Sopenharmony_ci				 struct sk_buff *skb, struct mptcp_ext *ext)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	/* The write_seq value has already been incremented, so the actual
4608c2ecf20Sopenharmony_ci	 * sequence number for the DATA_FIN is one less.
4618c2ecf20Sopenharmony_ci	 */
4628c2ecf20Sopenharmony_ci	u64 data_fin_tx_seq = READ_ONCE(mptcp_sk(subflow->conn)->write_seq) - 1;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (!ext->use_map || !skb->len) {
4658c2ecf20Sopenharmony_ci		/* RFC6824 requires a DSS mapping with specific values
4668c2ecf20Sopenharmony_ci		 * if DATA_FIN is set but no data payload is mapped
4678c2ecf20Sopenharmony_ci		 */
4688c2ecf20Sopenharmony_ci		ext->data_fin = 1;
4698c2ecf20Sopenharmony_ci		ext->use_map = 1;
4708c2ecf20Sopenharmony_ci		ext->dsn64 = 1;
4718c2ecf20Sopenharmony_ci		ext->data_seq = data_fin_tx_seq;
4728c2ecf20Sopenharmony_ci		ext->subflow_seq = 0;
4738c2ecf20Sopenharmony_ci		ext->data_len = 1;
4748c2ecf20Sopenharmony_ci	} else if (ext->data_seq + ext->data_len == data_fin_tx_seq) {
4758c2ecf20Sopenharmony_ci		/* If there's an existing DSS mapping and it is the
4768c2ecf20Sopenharmony_ci		 * final mapping, DATA_FIN consumes 1 additional byte of
4778c2ecf20Sopenharmony_ci		 * mapping space.
4788c2ecf20Sopenharmony_ci		 */
4798c2ecf20Sopenharmony_ci		ext->data_fin = 1;
4808c2ecf20Sopenharmony_ci		ext->data_len++;
4818c2ecf20Sopenharmony_ci	}
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
4858c2ecf20Sopenharmony_ci					  unsigned int *size,
4868c2ecf20Sopenharmony_ci					  unsigned int remaining,
4878c2ecf20Sopenharmony_ci					  struct mptcp_out_options *opts)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
4908c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
4918c2ecf20Sopenharmony_ci	unsigned int dss_size = 0;
4928c2ecf20Sopenharmony_ci	u64 snd_data_fin_enable;
4938c2ecf20Sopenharmony_ci	struct mptcp_ext *mpext;
4948c2ecf20Sopenharmony_ci	unsigned int ack_size;
4958c2ecf20Sopenharmony_ci	bool ret = false;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	mpext = skb ? mptcp_get_ext(skb) : NULL;
4988c2ecf20Sopenharmony_ci	snd_data_fin_enable = READ_ONCE(msk->snd_data_fin_enable);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	if (!skb || (mpext && mpext->use_map) || snd_data_fin_enable) {
5018c2ecf20Sopenharmony_ci		unsigned int map_size;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci		map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci		remaining -= map_size;
5068c2ecf20Sopenharmony_ci		dss_size = map_size;
5078c2ecf20Sopenharmony_ci		if (mpext)
5088c2ecf20Sopenharmony_ci			opts->ext_copy = *mpext;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci		if (skb && snd_data_fin_enable)
5118c2ecf20Sopenharmony_ci			mptcp_write_data_fin(subflow, skb, &opts->ext_copy);
5128c2ecf20Sopenharmony_ci		ret = true;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/* passive sockets msk will set the 'can_ack' after accept(), even
5168c2ecf20Sopenharmony_ci	 * if the first subflow may have the already the remote key handy
5178c2ecf20Sopenharmony_ci	 */
5188c2ecf20Sopenharmony_ci	opts->ext_copy.use_ack = 0;
5198c2ecf20Sopenharmony_ci	if (!READ_ONCE(msk->can_ack)) {
5208c2ecf20Sopenharmony_ci		*size = ALIGN(dss_size, 4);
5218c2ecf20Sopenharmony_ci		return ret;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	if (READ_ONCE(msk->use_64bit_ack)) {
5258c2ecf20Sopenharmony_ci		ack_size = TCPOLEN_MPTCP_DSS_ACK64;
5268c2ecf20Sopenharmony_ci		opts->ext_copy.data_ack = READ_ONCE(msk->ack_seq);
5278c2ecf20Sopenharmony_ci		opts->ext_copy.ack64 = 1;
5288c2ecf20Sopenharmony_ci	} else {
5298c2ecf20Sopenharmony_ci		ack_size = TCPOLEN_MPTCP_DSS_ACK32;
5308c2ecf20Sopenharmony_ci		opts->ext_copy.data_ack32 = (uint32_t)READ_ONCE(msk->ack_seq);
5318c2ecf20Sopenharmony_ci		opts->ext_copy.ack64 = 0;
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci	opts->ext_copy.use_ack = 1;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	/* Add kind/length/subtype/flag overhead if mapping is not populated */
5368c2ecf20Sopenharmony_ci	if (dss_size == 0)
5378c2ecf20Sopenharmony_ci		ack_size += TCPOLEN_MPTCP_DSS_BASE;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	dss_size += ack_size;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	*size = ALIGN(dss_size, 4);
5428c2ecf20Sopenharmony_ci	return true;
5438c2ecf20Sopenharmony_ci}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cistatic u64 add_addr_generate_hmac(u64 key1, u64 key2, u8 addr_id,
5468c2ecf20Sopenharmony_ci				  struct in_addr *addr)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	u8 hmac[SHA256_DIGEST_SIZE];
5498c2ecf20Sopenharmony_ci	u8 msg[7];
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	msg[0] = addr_id;
5528c2ecf20Sopenharmony_ci	memcpy(&msg[1], &addr->s_addr, 4);
5538c2ecf20Sopenharmony_ci	msg[5] = 0;
5548c2ecf20Sopenharmony_ci	msg[6] = 0;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	mptcp_crypto_hmac_sha(key1, key2, msg, 7, hmac);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
5598c2ecf20Sopenharmony_ci}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
5628c2ecf20Sopenharmony_cistatic u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
5638c2ecf20Sopenharmony_ci				   struct in6_addr *addr)
5648c2ecf20Sopenharmony_ci{
5658c2ecf20Sopenharmony_ci	u8 hmac[SHA256_DIGEST_SIZE];
5668c2ecf20Sopenharmony_ci	u8 msg[19];
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	msg[0] = addr_id;
5698c2ecf20Sopenharmony_ci	memcpy(&msg[1], &addr->s6_addr, 16);
5708c2ecf20Sopenharmony_ci	msg[17] = 0;
5718c2ecf20Sopenharmony_ci	msg[18] = 0;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	mptcp_crypto_hmac_sha(key1, key2, msg, 19, hmac);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
5768c2ecf20Sopenharmony_ci}
5778c2ecf20Sopenharmony_ci#endif
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_cistatic bool mptcp_established_options_add_addr(struct sock *sk,
5808c2ecf20Sopenharmony_ci					       unsigned int *size,
5818c2ecf20Sopenharmony_ci					       unsigned int remaining,
5828c2ecf20Sopenharmony_ci					       struct mptcp_out_options *opts)
5838c2ecf20Sopenharmony_ci{
5848c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
5858c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
5868c2ecf20Sopenharmony_ci	struct mptcp_addr_info saddr;
5878c2ecf20Sopenharmony_ci	bool echo;
5888c2ecf20Sopenharmony_ci	int len;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (!mptcp_pm_should_add_signal(msk) ||
5918c2ecf20Sopenharmony_ci	    !(mptcp_pm_add_addr_signal(msk, remaining, &saddr, &echo)))
5928c2ecf20Sopenharmony_ci		return false;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	len = mptcp_add_addr_len(saddr.family, echo);
5958c2ecf20Sopenharmony_ci	if (remaining < len)
5968c2ecf20Sopenharmony_ci		return false;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	*size = len;
5998c2ecf20Sopenharmony_ci	opts->addr_id = saddr.id;
6008c2ecf20Sopenharmony_ci	if (saddr.family == AF_INET) {
6018c2ecf20Sopenharmony_ci		opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
6028c2ecf20Sopenharmony_ci		opts->addr = saddr.addr;
6038c2ecf20Sopenharmony_ci		if (!echo) {
6048c2ecf20Sopenharmony_ci			opts->ahmac = add_addr_generate_hmac(msk->local_key,
6058c2ecf20Sopenharmony_ci							     msk->remote_key,
6068c2ecf20Sopenharmony_ci							     opts->addr_id,
6078c2ecf20Sopenharmony_ci							     &opts->addr);
6088c2ecf20Sopenharmony_ci		}
6098c2ecf20Sopenharmony_ci	}
6108c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
6118c2ecf20Sopenharmony_ci	else if (saddr.family == AF_INET6) {
6128c2ecf20Sopenharmony_ci		opts->suboptions |= OPTION_MPTCP_ADD_ADDR6;
6138c2ecf20Sopenharmony_ci		opts->addr6 = saddr.addr6;
6148c2ecf20Sopenharmony_ci		if (!echo) {
6158c2ecf20Sopenharmony_ci			opts->ahmac = add_addr6_generate_hmac(msk->local_key,
6168c2ecf20Sopenharmony_ci							      msk->remote_key,
6178c2ecf20Sopenharmony_ci							      opts->addr_id,
6188c2ecf20Sopenharmony_ci							      &opts->addr6);
6198c2ecf20Sopenharmony_ci		}
6208c2ecf20Sopenharmony_ci	}
6218c2ecf20Sopenharmony_ci#endif
6228c2ecf20Sopenharmony_ci	pr_debug("addr_id=%d, ahmac=%llu, echo=%d", opts->addr_id, opts->ahmac, echo);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	return true;
6258c2ecf20Sopenharmony_ci}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_cistatic bool mptcp_established_options_rm_addr(struct sock *sk,
6288c2ecf20Sopenharmony_ci					      unsigned int *size,
6298c2ecf20Sopenharmony_ci					      unsigned int remaining,
6308c2ecf20Sopenharmony_ci					      struct mptcp_out_options *opts)
6318c2ecf20Sopenharmony_ci{
6328c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
6338c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
6348c2ecf20Sopenharmony_ci	u8 rm_id;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	if (!mptcp_pm_should_rm_signal(msk) ||
6378c2ecf20Sopenharmony_ci	    !(mptcp_pm_rm_addr_signal(msk, remaining, &rm_id)))
6388c2ecf20Sopenharmony_ci		return false;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	if (remaining < TCPOLEN_MPTCP_RM_ADDR_BASE)
6418c2ecf20Sopenharmony_ci		return false;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	*size = TCPOLEN_MPTCP_RM_ADDR_BASE;
6448c2ecf20Sopenharmony_ci	opts->suboptions |= OPTION_MPTCP_RM_ADDR;
6458c2ecf20Sopenharmony_ci	opts->rm_id = rm_id;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	pr_debug("rm_id=%d", opts->rm_id);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	return true;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_cibool mptcp_established_options(struct sock *sk, struct sk_buff *skb,
6538c2ecf20Sopenharmony_ci			       unsigned int *size, unsigned int remaining,
6548c2ecf20Sopenharmony_ci			       struct mptcp_out_options *opts)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	unsigned int opt_size = 0;
6578c2ecf20Sopenharmony_ci	bool ret = false;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	opts->suboptions = 0;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	if (unlikely(mptcp_check_fallback(sk)))
6628c2ecf20Sopenharmony_ci		return false;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	/* prevent adding of any MPTCP related options on reset packet
6658c2ecf20Sopenharmony_ci	 * until we support MP_TCPRST/MP_FASTCLOSE
6668c2ecf20Sopenharmony_ci	 */
6678c2ecf20Sopenharmony_ci	if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST))
6688c2ecf20Sopenharmony_ci		return false;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	if (mptcp_established_options_mp(sk, skb, &opt_size, remaining, opts))
6718c2ecf20Sopenharmony_ci		ret = true;
6728c2ecf20Sopenharmony_ci	else if (mptcp_established_options_dss(sk, skb, &opt_size, remaining,
6738c2ecf20Sopenharmony_ci					       opts))
6748c2ecf20Sopenharmony_ci		ret = true;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	/* we reserved enough space for the above options, and exceeding the
6778c2ecf20Sopenharmony_ci	 * TCP option space would be fatal
6788c2ecf20Sopenharmony_ci	 */
6798c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(opt_size > remaining))
6808c2ecf20Sopenharmony_ci		return false;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	*size += opt_size;
6838c2ecf20Sopenharmony_ci	remaining -= opt_size;
6848c2ecf20Sopenharmony_ci	if (mptcp_established_options_add_addr(sk, &opt_size, remaining, opts)) {
6858c2ecf20Sopenharmony_ci		*size += opt_size;
6868c2ecf20Sopenharmony_ci		remaining -= opt_size;
6878c2ecf20Sopenharmony_ci		ret = true;
6888c2ecf20Sopenharmony_ci	} else if (mptcp_established_options_rm_addr(sk, &opt_size, remaining, opts)) {
6898c2ecf20Sopenharmony_ci		*size += opt_size;
6908c2ecf20Sopenharmony_ci		remaining -= opt_size;
6918c2ecf20Sopenharmony_ci		ret = true;
6928c2ecf20Sopenharmony_ci	}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	return ret;
6958c2ecf20Sopenharmony_ci}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_cibool mptcp_synack_options(const struct request_sock *req, unsigned int *size,
6988c2ecf20Sopenharmony_ci			  struct mptcp_out_options *opts)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	if (subflow_req->mp_capable) {
7038c2ecf20Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPC_SYNACK;
7048c2ecf20Sopenharmony_ci		opts->sndr_key = subflow_req->local_key;
7058c2ecf20Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPC_SYNACK;
7068c2ecf20Sopenharmony_ci		pr_debug("subflow_req=%p, local_key=%llu",
7078c2ecf20Sopenharmony_ci			 subflow_req, subflow_req->local_key);
7088c2ecf20Sopenharmony_ci		return true;
7098c2ecf20Sopenharmony_ci	} else if (subflow_req->mp_join) {
7108c2ecf20Sopenharmony_ci		opts->suboptions = OPTION_MPTCP_MPJ_SYNACK;
7118c2ecf20Sopenharmony_ci		opts->backup = subflow_req->backup;
7128c2ecf20Sopenharmony_ci		opts->join_id = subflow_req->local_id;
7138c2ecf20Sopenharmony_ci		opts->thmac = subflow_req->thmac;
7148c2ecf20Sopenharmony_ci		opts->nonce = subflow_req->local_nonce;
7158c2ecf20Sopenharmony_ci		pr_debug("req=%p, bkup=%u, id=%u, thmac=%llu, nonce=%u",
7168c2ecf20Sopenharmony_ci			 subflow_req, opts->backup, opts->join_id,
7178c2ecf20Sopenharmony_ci			 opts->thmac, opts->nonce);
7188c2ecf20Sopenharmony_ci		*size = TCPOLEN_MPTCP_MPJ_SYNACK;
7198c2ecf20Sopenharmony_ci		return true;
7208c2ecf20Sopenharmony_ci	}
7218c2ecf20Sopenharmony_ci	return false;
7228c2ecf20Sopenharmony_ci}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_cistatic bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
7258c2ecf20Sopenharmony_ci				    struct mptcp_subflow_context *subflow,
7268c2ecf20Sopenharmony_ci				    struct sk_buff *skb,
7278c2ecf20Sopenharmony_ci				    struct mptcp_options_received *mp_opt)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	/* here we can process OoO, in-window pkts, only in-sequence 4th ack
7308c2ecf20Sopenharmony_ci	 * will make the subflow fully established
7318c2ecf20Sopenharmony_ci	 */
7328c2ecf20Sopenharmony_ci	if (likely(subflow->fully_established)) {
7338c2ecf20Sopenharmony_ci		/* on passive sockets, check for 3rd ack retransmission
7348c2ecf20Sopenharmony_ci		 * note that msk is always set by subflow_syn_recv_sock()
7358c2ecf20Sopenharmony_ci		 * for mp_join subflows
7368c2ecf20Sopenharmony_ci		 */
7378c2ecf20Sopenharmony_ci		if (TCP_SKB_CB(skb)->seq == subflow->ssn_offset + 1 &&
7388c2ecf20Sopenharmony_ci		    TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq &&
7398c2ecf20Sopenharmony_ci		    subflow->mp_join && mp_opt->mp_join &&
7408c2ecf20Sopenharmony_ci		    READ_ONCE(msk->pm.server_side))
7418c2ecf20Sopenharmony_ci			tcp_send_ack(ssk);
7428c2ecf20Sopenharmony_ci		goto fully_established;
7438c2ecf20Sopenharmony_ci	}
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	/* we must process OoO packets before the first subflow is fully
7468c2ecf20Sopenharmony_ci	 * established. OoO packets are instead a protocol violation
7478c2ecf20Sopenharmony_ci	 * for MP_JOIN subflows as the peer must not send any data
7488c2ecf20Sopenharmony_ci	 * before receiving the forth ack - cfr. RFC 8684 section 3.2.
7498c2ecf20Sopenharmony_ci	 */
7508c2ecf20Sopenharmony_ci	if (TCP_SKB_CB(skb)->seq != subflow->ssn_offset + 1) {
7518c2ecf20Sopenharmony_ci		if (subflow->mp_join)
7528c2ecf20Sopenharmony_ci			goto reset;
7538c2ecf20Sopenharmony_ci		return subflow->mp_capable;
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	if (mp_opt->dss && mp_opt->use_ack) {
7578c2ecf20Sopenharmony_ci		/* subflows are fully established as soon as we get any
7588c2ecf20Sopenharmony_ci		 * additional ack.
7598c2ecf20Sopenharmony_ci		 */
7608c2ecf20Sopenharmony_ci		subflow->fully_established = 1;
7618c2ecf20Sopenharmony_ci		WRITE_ONCE(msk->fully_established, true);
7628c2ecf20Sopenharmony_ci		goto fully_established;
7638c2ecf20Sopenharmony_ci	}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/* If the first established packet does not contain MP_CAPABLE + data
7668c2ecf20Sopenharmony_ci	 * then fallback to TCP. Fallback scenarios requires a reset for
7678c2ecf20Sopenharmony_ci	 * MP_JOIN subflows.
7688c2ecf20Sopenharmony_ci	 */
7698c2ecf20Sopenharmony_ci	if (!mp_opt->mp_capable) {
7708c2ecf20Sopenharmony_ci		if (subflow->mp_join)
7718c2ecf20Sopenharmony_ci			goto reset;
7728c2ecf20Sopenharmony_ci		subflow->mp_capable = 0;
7738c2ecf20Sopenharmony_ci		pr_fallback(msk);
7748c2ecf20Sopenharmony_ci		__mptcp_do_fallback(msk);
7758c2ecf20Sopenharmony_ci		return false;
7768c2ecf20Sopenharmony_ci	}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	if (unlikely(!READ_ONCE(msk->pm.server_side)))
7798c2ecf20Sopenharmony_ci		pr_warn_once("bogus mpc option on established client sk");
7808c2ecf20Sopenharmony_ci	mptcp_subflow_fully_established(subflow, mp_opt);
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cifully_established:
7838c2ecf20Sopenharmony_ci	if (likely(subflow->pm_notified))
7848c2ecf20Sopenharmony_ci		return true;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	subflow->pm_notified = 1;
7878c2ecf20Sopenharmony_ci	if (subflow->mp_join) {
7888c2ecf20Sopenharmony_ci		clear_3rdack_retransmission(ssk);
7898c2ecf20Sopenharmony_ci		mptcp_pm_subflow_established(msk, subflow);
7908c2ecf20Sopenharmony_ci	} else {
7918c2ecf20Sopenharmony_ci		mptcp_pm_fully_established(msk);
7928c2ecf20Sopenharmony_ci	}
7938c2ecf20Sopenharmony_ci	return true;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_cireset:
7968c2ecf20Sopenharmony_ci	mptcp_subflow_reset(ssk);
7978c2ecf20Sopenharmony_ci	return false;
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_cistatic u64 expand_ack(u64 old_ack, u64 cur_ack, bool use_64bit)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	u32 old_ack32, cur_ack32;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	if (use_64bit)
8058c2ecf20Sopenharmony_ci		return cur_ack;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	old_ack32 = (u32)old_ack;
8088c2ecf20Sopenharmony_ci	cur_ack32 = (u32)cur_ack;
8098c2ecf20Sopenharmony_ci	cur_ack = (old_ack & GENMASK_ULL(63, 32)) + cur_ack32;
8108c2ecf20Sopenharmony_ci	if (unlikely(before(cur_ack32, old_ack32)))
8118c2ecf20Sopenharmony_ci		return cur_ack + (1LL << 32);
8128c2ecf20Sopenharmony_ci	return cur_ack;
8138c2ecf20Sopenharmony_ci}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_cistatic void update_una(struct mptcp_sock *msk,
8168c2ecf20Sopenharmony_ci		       struct mptcp_options_received *mp_opt)
8178c2ecf20Sopenharmony_ci{
8188c2ecf20Sopenharmony_ci	u64 new_snd_una, snd_una, old_snd_una = atomic64_read(&msk->snd_una);
8198c2ecf20Sopenharmony_ci	u64 write_seq = READ_ONCE(msk->write_seq);
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	/* avoid ack expansion on update conflict, to reduce the risk of
8228c2ecf20Sopenharmony_ci	 * wrongly expanding to a future ack sequence number, which is way
8238c2ecf20Sopenharmony_ci	 * more dangerous than missing an ack
8248c2ecf20Sopenharmony_ci	 */
8258c2ecf20Sopenharmony_ci	new_snd_una = expand_ack(old_snd_una, mp_opt->data_ack, mp_opt->ack64);
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	/* ACK for data not even sent yet? Ignore. */
8288c2ecf20Sopenharmony_ci	if (after64(new_snd_una, write_seq))
8298c2ecf20Sopenharmony_ci		new_snd_una = old_snd_una;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	while (after64(new_snd_una, old_snd_una)) {
8328c2ecf20Sopenharmony_ci		snd_una = old_snd_una;
8338c2ecf20Sopenharmony_ci		old_snd_una = atomic64_cmpxchg(&msk->snd_una, snd_una,
8348c2ecf20Sopenharmony_ci					       new_snd_una);
8358c2ecf20Sopenharmony_ci		if (old_snd_una == snd_una) {
8368c2ecf20Sopenharmony_ci			mptcp_data_acked((struct sock *)msk);
8378c2ecf20Sopenharmony_ci			break;
8388c2ecf20Sopenharmony_ci		}
8398c2ecf20Sopenharmony_ci	}
8408c2ecf20Sopenharmony_ci}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_cibool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit)
8438c2ecf20Sopenharmony_ci{
8448c2ecf20Sopenharmony_ci	/* Skip if DATA_FIN was already received.
8458c2ecf20Sopenharmony_ci	 * If updating simultaneously with the recvmsg loop, values
8468c2ecf20Sopenharmony_ci	 * should match. If they mismatch, the peer is misbehaving and
8478c2ecf20Sopenharmony_ci	 * we will prefer the most recent information.
8488c2ecf20Sopenharmony_ci	 */
8498c2ecf20Sopenharmony_ci	if (READ_ONCE(msk->rcv_data_fin) || !READ_ONCE(msk->first))
8508c2ecf20Sopenharmony_ci		return false;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	WRITE_ONCE(msk->rcv_data_fin_seq,
8538c2ecf20Sopenharmony_ci		   expand_ack(READ_ONCE(msk->ack_seq), data_fin_seq, use_64bit));
8548c2ecf20Sopenharmony_ci	WRITE_ONCE(msk->rcv_data_fin, 1);
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	return true;
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_cistatic bool add_addr_hmac_valid(struct mptcp_sock *msk,
8608c2ecf20Sopenharmony_ci				struct mptcp_options_received *mp_opt)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	u64 hmac = 0;
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	if (mp_opt->echo)
8658c2ecf20Sopenharmony_ci		return true;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	if (mp_opt->family == MPTCP_ADDR_IPVERSION_4)
8688c2ecf20Sopenharmony_ci		hmac = add_addr_generate_hmac(msk->remote_key,
8698c2ecf20Sopenharmony_ci					      msk->local_key,
8708c2ecf20Sopenharmony_ci					      mp_opt->addr_id, &mp_opt->addr);
8718c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
8728c2ecf20Sopenharmony_ci	else
8738c2ecf20Sopenharmony_ci		hmac = add_addr6_generate_hmac(msk->remote_key,
8748c2ecf20Sopenharmony_ci					       msk->local_key,
8758c2ecf20Sopenharmony_ci					       mp_opt->addr_id, &mp_opt->addr6);
8768c2ecf20Sopenharmony_ci#endif
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	pr_debug("msk=%p, ahmac=%llu, mp_opt->ahmac=%llu\n",
8798c2ecf20Sopenharmony_ci		 msk, (unsigned long long)hmac,
8808c2ecf20Sopenharmony_ci		 (unsigned long long)mp_opt->ahmac);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	return hmac == mp_opt->ahmac;
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_civoid mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
8868c2ecf20Sopenharmony_ci{
8878c2ecf20Sopenharmony_ci	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
8888c2ecf20Sopenharmony_ci	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
8898c2ecf20Sopenharmony_ci	struct mptcp_options_received mp_opt;
8908c2ecf20Sopenharmony_ci	struct mptcp_ext *mpext;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	if (__mptcp_check_fallback(msk))
8938c2ecf20Sopenharmony_ci		return;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	mptcp_get_options(skb, &mp_opt);
8968c2ecf20Sopenharmony_ci	if (!check_fully_established(msk, sk, subflow, skb, &mp_opt))
8978c2ecf20Sopenharmony_ci		return;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	if (mp_opt.add_addr && add_addr_hmac_valid(msk, &mp_opt)) {
9008c2ecf20Sopenharmony_ci		struct mptcp_addr_info addr;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci		addr.port = htons(mp_opt.port);
9038c2ecf20Sopenharmony_ci		addr.id = mp_opt.addr_id;
9048c2ecf20Sopenharmony_ci		if (mp_opt.family == MPTCP_ADDR_IPVERSION_4) {
9058c2ecf20Sopenharmony_ci			addr.family = AF_INET;
9068c2ecf20Sopenharmony_ci			addr.addr = mp_opt.addr;
9078c2ecf20Sopenharmony_ci		}
9088c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
9098c2ecf20Sopenharmony_ci		else if (mp_opt.family == MPTCP_ADDR_IPVERSION_6) {
9108c2ecf20Sopenharmony_ci			addr.family = AF_INET6;
9118c2ecf20Sopenharmony_ci			addr.addr6 = mp_opt.addr6;
9128c2ecf20Sopenharmony_ci		}
9138c2ecf20Sopenharmony_ci#endif
9148c2ecf20Sopenharmony_ci		if (!mp_opt.echo) {
9158c2ecf20Sopenharmony_ci			mptcp_pm_add_addr_received(msk, &addr);
9168c2ecf20Sopenharmony_ci			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
9178c2ecf20Sopenharmony_ci		} else {
9188c2ecf20Sopenharmony_ci			mptcp_pm_del_add_timer(msk, &addr);
9198c2ecf20Sopenharmony_ci			MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
9208c2ecf20Sopenharmony_ci		}
9218c2ecf20Sopenharmony_ci		mp_opt.add_addr = 0;
9228c2ecf20Sopenharmony_ci	}
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	if (mp_opt.rm_addr) {
9258c2ecf20Sopenharmony_ci		mptcp_pm_rm_addr_received(msk, mp_opt.rm_id);
9268c2ecf20Sopenharmony_ci		mp_opt.rm_addr = 0;
9278c2ecf20Sopenharmony_ci	}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	if (!mp_opt.dss)
9308c2ecf20Sopenharmony_ci		return;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	/* we can't wait for recvmsg() to update the ack_seq, otherwise
9338c2ecf20Sopenharmony_ci	 * monodirectional flows will stuck
9348c2ecf20Sopenharmony_ci	 */
9358c2ecf20Sopenharmony_ci	if (mp_opt.use_ack)
9368c2ecf20Sopenharmony_ci		update_una(msk, &mp_opt);
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	/* Zero-data-length packets are dropped by the caller and not
9398c2ecf20Sopenharmony_ci	 * propagated to the MPTCP layer, so the skb extension does not
9408c2ecf20Sopenharmony_ci	 * need to be allocated or populated. DATA_FIN information, if
9418c2ecf20Sopenharmony_ci	 * present, needs to be updated here before the skb is freed.
9428c2ecf20Sopenharmony_ci	 */
9438c2ecf20Sopenharmony_ci	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
9448c2ecf20Sopenharmony_ci		if (mp_opt.data_fin && mp_opt.data_len == 1 &&
9458c2ecf20Sopenharmony_ci		    mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64) &&
9468c2ecf20Sopenharmony_ci		    schedule_work(&msk->work))
9478c2ecf20Sopenharmony_ci			sock_hold(subflow->conn);
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci		return;
9508c2ecf20Sopenharmony_ci	}
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
9538c2ecf20Sopenharmony_ci	if (!mpext)
9548c2ecf20Sopenharmony_ci		return;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	memset(mpext, 0, sizeof(*mpext));
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	if (mp_opt.use_map) {
9598c2ecf20Sopenharmony_ci		if (mp_opt.mpc_map) {
9608c2ecf20Sopenharmony_ci			/* this is an MP_CAPABLE carrying MPTCP data
9618c2ecf20Sopenharmony_ci			 * we know this map the first chunk of data
9628c2ecf20Sopenharmony_ci			 */
9638c2ecf20Sopenharmony_ci			mptcp_crypto_key_sha(subflow->remote_key, NULL,
9648c2ecf20Sopenharmony_ci					     &mpext->data_seq);
9658c2ecf20Sopenharmony_ci			mpext->data_seq++;
9668c2ecf20Sopenharmony_ci			mpext->subflow_seq = 1;
9678c2ecf20Sopenharmony_ci			mpext->dsn64 = 1;
9688c2ecf20Sopenharmony_ci			mpext->mpc_map = 1;
9698c2ecf20Sopenharmony_ci			mpext->data_fin = 0;
9708c2ecf20Sopenharmony_ci		} else {
9718c2ecf20Sopenharmony_ci			mpext->data_seq = mp_opt.data_seq;
9728c2ecf20Sopenharmony_ci			mpext->subflow_seq = mp_opt.subflow_seq;
9738c2ecf20Sopenharmony_ci			mpext->dsn64 = mp_opt.dsn64;
9748c2ecf20Sopenharmony_ci			mpext->data_fin = mp_opt.data_fin;
9758c2ecf20Sopenharmony_ci		}
9768c2ecf20Sopenharmony_ci		mpext->data_len = mp_opt.data_len;
9778c2ecf20Sopenharmony_ci		mpext->use_map = 1;
9788c2ecf20Sopenharmony_ci	}
9798c2ecf20Sopenharmony_ci}
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_civoid mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
9828c2ecf20Sopenharmony_ci{
9838c2ecf20Sopenharmony_ci	if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK |
9848c2ecf20Sopenharmony_ci	     OPTION_MPTCP_MPC_ACK) & opts->suboptions) {
9858c2ecf20Sopenharmony_ci		u8 len;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci		if (OPTION_MPTCP_MPC_SYN & opts->suboptions)
9888c2ecf20Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_SYN;
9898c2ecf20Sopenharmony_ci		else if (OPTION_MPTCP_MPC_SYNACK & opts->suboptions)
9908c2ecf20Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_SYNACK;
9918c2ecf20Sopenharmony_ci		else if (opts->ext_copy.data_len)
9928c2ecf20Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_ACK_DATA;
9938c2ecf20Sopenharmony_ci		else
9948c2ecf20Sopenharmony_ci			len = TCPOLEN_MPTCP_MPC_ACK;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_CAPABLE, len,
9978c2ecf20Sopenharmony_ci				      MPTCP_SUPPORTED_VERSION,
9988c2ecf20Sopenharmony_ci				      MPTCP_CAP_HMAC_SHA256);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci		if (!((OPTION_MPTCP_MPC_SYNACK | OPTION_MPTCP_MPC_ACK) &
10018c2ecf20Sopenharmony_ci		    opts->suboptions))
10028c2ecf20Sopenharmony_ci			goto mp_capable_done;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		put_unaligned_be64(opts->sndr_key, ptr);
10058c2ecf20Sopenharmony_ci		ptr += 2;
10068c2ecf20Sopenharmony_ci		if (!((OPTION_MPTCP_MPC_ACK) & opts->suboptions))
10078c2ecf20Sopenharmony_ci			goto mp_capable_done;
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci		put_unaligned_be64(opts->rcvr_key, ptr);
10108c2ecf20Sopenharmony_ci		ptr += 2;
10118c2ecf20Sopenharmony_ci		if (!opts->ext_copy.data_len)
10128c2ecf20Sopenharmony_ci			goto mp_capable_done;
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci		put_unaligned_be32(opts->ext_copy.data_len << 16 |
10158c2ecf20Sopenharmony_ci				   TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
10168c2ecf20Sopenharmony_ci		ptr += 1;
10178c2ecf20Sopenharmony_ci	}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_cimp_capable_done:
10208c2ecf20Sopenharmony_ci	if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) {
10218c2ecf20Sopenharmony_ci		if (opts->ahmac)
10228c2ecf20Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_ADD_ADDR,
10238c2ecf20Sopenharmony_ci					      TCPOLEN_MPTCP_ADD_ADDR, 0,
10248c2ecf20Sopenharmony_ci					      opts->addr_id);
10258c2ecf20Sopenharmony_ci		else
10268c2ecf20Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_ADD_ADDR,
10278c2ecf20Sopenharmony_ci					      TCPOLEN_MPTCP_ADD_ADDR_BASE,
10288c2ecf20Sopenharmony_ci					      MPTCP_ADDR_ECHO,
10298c2ecf20Sopenharmony_ci					      opts->addr_id);
10308c2ecf20Sopenharmony_ci		memcpy((u8 *)ptr, (u8 *)&opts->addr.s_addr, 4);
10318c2ecf20Sopenharmony_ci		ptr += 1;
10328c2ecf20Sopenharmony_ci		if (opts->ahmac) {
10338c2ecf20Sopenharmony_ci			put_unaligned_be64(opts->ahmac, ptr);
10348c2ecf20Sopenharmony_ci			ptr += 2;
10358c2ecf20Sopenharmony_ci		}
10368c2ecf20Sopenharmony_ci	}
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_MPTCP_IPV6)
10398c2ecf20Sopenharmony_ci	if (OPTION_MPTCP_ADD_ADDR6 & opts->suboptions) {
10408c2ecf20Sopenharmony_ci		if (opts->ahmac)
10418c2ecf20Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_ADD_ADDR,
10428c2ecf20Sopenharmony_ci					      TCPOLEN_MPTCP_ADD_ADDR6, 0,
10438c2ecf20Sopenharmony_ci					      opts->addr_id);
10448c2ecf20Sopenharmony_ci		else
10458c2ecf20Sopenharmony_ci			*ptr++ = mptcp_option(MPTCPOPT_ADD_ADDR,
10468c2ecf20Sopenharmony_ci					      TCPOLEN_MPTCP_ADD_ADDR6_BASE,
10478c2ecf20Sopenharmony_ci					      MPTCP_ADDR_ECHO,
10488c2ecf20Sopenharmony_ci					      opts->addr_id);
10498c2ecf20Sopenharmony_ci		memcpy((u8 *)ptr, opts->addr6.s6_addr, 16);
10508c2ecf20Sopenharmony_ci		ptr += 4;
10518c2ecf20Sopenharmony_ci		if (opts->ahmac) {
10528c2ecf20Sopenharmony_ci			put_unaligned_be64(opts->ahmac, ptr);
10538c2ecf20Sopenharmony_ci			ptr += 2;
10548c2ecf20Sopenharmony_ci		}
10558c2ecf20Sopenharmony_ci	}
10568c2ecf20Sopenharmony_ci#endif
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	if (OPTION_MPTCP_RM_ADDR & opts->suboptions) {
10598c2ecf20Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_RM_ADDR,
10608c2ecf20Sopenharmony_ci				      TCPOLEN_MPTCP_RM_ADDR_BASE,
10618c2ecf20Sopenharmony_ci				      0, opts->rm_id);
10628c2ecf20Sopenharmony_ci	}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) {
10658c2ecf20Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
10668c2ecf20Sopenharmony_ci				      TCPOLEN_MPTCP_MPJ_SYN,
10678c2ecf20Sopenharmony_ci				      opts->backup, opts->join_id);
10688c2ecf20Sopenharmony_ci		put_unaligned_be32(opts->token, ptr);
10698c2ecf20Sopenharmony_ci		ptr += 1;
10708c2ecf20Sopenharmony_ci		put_unaligned_be32(opts->nonce, ptr);
10718c2ecf20Sopenharmony_ci		ptr += 1;
10728c2ecf20Sopenharmony_ci	}
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) {
10758c2ecf20Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
10768c2ecf20Sopenharmony_ci				      TCPOLEN_MPTCP_MPJ_SYNACK,
10778c2ecf20Sopenharmony_ci				      opts->backup, opts->join_id);
10788c2ecf20Sopenharmony_ci		put_unaligned_be64(opts->thmac, ptr);
10798c2ecf20Sopenharmony_ci		ptr += 2;
10808c2ecf20Sopenharmony_ci		put_unaligned_be32(opts->nonce, ptr);
10818c2ecf20Sopenharmony_ci		ptr += 1;
10828c2ecf20Sopenharmony_ci	}
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) {
10858c2ecf20Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_MP_JOIN,
10868c2ecf20Sopenharmony_ci				      TCPOLEN_MPTCP_MPJ_ACK, 0, 0);
10878c2ecf20Sopenharmony_ci		memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN);
10888c2ecf20Sopenharmony_ci		ptr += 5;
10898c2ecf20Sopenharmony_ci	}
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	if (opts->ext_copy.use_ack || opts->ext_copy.use_map) {
10928c2ecf20Sopenharmony_ci		struct mptcp_ext *mpext = &opts->ext_copy;
10938c2ecf20Sopenharmony_ci		u8 len = TCPOLEN_MPTCP_DSS_BASE;
10948c2ecf20Sopenharmony_ci		u8 flags = 0;
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci		if (mpext->use_ack) {
10978c2ecf20Sopenharmony_ci			flags = MPTCP_DSS_HAS_ACK;
10988c2ecf20Sopenharmony_ci			if (mpext->ack64) {
10998c2ecf20Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_ACK64;
11008c2ecf20Sopenharmony_ci				flags |= MPTCP_DSS_ACK64;
11018c2ecf20Sopenharmony_ci			} else {
11028c2ecf20Sopenharmony_ci				len += TCPOLEN_MPTCP_DSS_ACK32;
11038c2ecf20Sopenharmony_ci			}
11048c2ecf20Sopenharmony_ci		}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci		if (mpext->use_map) {
11078c2ecf20Sopenharmony_ci			len += TCPOLEN_MPTCP_DSS_MAP64;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci			/* Use only 64-bit mapping flags for now, add
11108c2ecf20Sopenharmony_ci			 * support for optional 32-bit mappings later.
11118c2ecf20Sopenharmony_ci			 */
11128c2ecf20Sopenharmony_ci			flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64;
11138c2ecf20Sopenharmony_ci			if (mpext->data_fin)
11148c2ecf20Sopenharmony_ci				flags |= MPTCP_DSS_DATA_FIN;
11158c2ecf20Sopenharmony_ci		}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci		*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci		if (mpext->use_ack) {
11208c2ecf20Sopenharmony_ci			if (mpext->ack64) {
11218c2ecf20Sopenharmony_ci				put_unaligned_be64(mpext->data_ack, ptr);
11228c2ecf20Sopenharmony_ci				ptr += 2;
11238c2ecf20Sopenharmony_ci			} else {
11248c2ecf20Sopenharmony_ci				put_unaligned_be32(mpext->data_ack32, ptr);
11258c2ecf20Sopenharmony_ci				ptr += 1;
11268c2ecf20Sopenharmony_ci			}
11278c2ecf20Sopenharmony_ci		}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci		if (mpext->use_map) {
11308c2ecf20Sopenharmony_ci			put_unaligned_be64(mpext->data_seq, ptr);
11318c2ecf20Sopenharmony_ci			ptr += 2;
11328c2ecf20Sopenharmony_ci			put_unaligned_be32(mpext->subflow_seq, ptr);
11338c2ecf20Sopenharmony_ci			ptr += 1;
11348c2ecf20Sopenharmony_ci			put_unaligned_be32(mpext->data_len << 16 |
11358c2ecf20Sopenharmony_ci					   TCPOPT_NOP << 8 | TCPOPT_NOP, ptr);
11368c2ecf20Sopenharmony_ci		}
11378c2ecf20Sopenharmony_ci	}
11388c2ecf20Sopenharmony_ci}
1139