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