1*eda7acddSPeter Krystad // SPDX-License-Identifier: GPL-2.0 2*eda7acddSPeter Krystad /* Multipath TCP 3*eda7acddSPeter Krystad * 4*eda7acddSPeter Krystad * Copyright (c) 2017 - 2019, Intel Corporation. 5*eda7acddSPeter Krystad */ 6*eda7acddSPeter Krystad 7*eda7acddSPeter Krystad #include <linux/kernel.h> 8*eda7acddSPeter Krystad #include <net/tcp.h> 9*eda7acddSPeter Krystad #include <net/mptcp.h> 10*eda7acddSPeter Krystad #include "protocol.h" 11*eda7acddSPeter Krystad 12*eda7acddSPeter Krystad void mptcp_parse_option(const unsigned char *ptr, int opsize, 13*eda7acddSPeter Krystad struct tcp_options_received *opt_rx) 14*eda7acddSPeter Krystad { 15*eda7acddSPeter Krystad struct mptcp_options_received *mp_opt = &opt_rx->mptcp; 16*eda7acddSPeter Krystad u8 subtype = *ptr >> 4; 17*eda7acddSPeter Krystad u8 version; 18*eda7acddSPeter Krystad u8 flags; 19*eda7acddSPeter Krystad 20*eda7acddSPeter Krystad switch (subtype) { 21*eda7acddSPeter Krystad case MPTCPOPT_MP_CAPABLE: 22*eda7acddSPeter Krystad if (opsize != TCPOLEN_MPTCP_MPC_SYN && 23*eda7acddSPeter Krystad opsize != TCPOLEN_MPTCP_MPC_ACK) 24*eda7acddSPeter Krystad break; 25*eda7acddSPeter Krystad 26*eda7acddSPeter Krystad version = *ptr++ & MPTCP_VERSION_MASK; 27*eda7acddSPeter Krystad if (version != MPTCP_SUPPORTED_VERSION) 28*eda7acddSPeter Krystad break; 29*eda7acddSPeter Krystad 30*eda7acddSPeter Krystad flags = *ptr++; 31*eda7acddSPeter Krystad if (!((flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) || 32*eda7acddSPeter Krystad (flags & MPTCP_CAP_EXTENSIBILITY)) 33*eda7acddSPeter Krystad break; 34*eda7acddSPeter Krystad 35*eda7acddSPeter Krystad /* RFC 6824, Section 3.1: 36*eda7acddSPeter Krystad * "For the Checksum Required bit (labeled "A"), if either 37*eda7acddSPeter Krystad * host requires the use of checksums, checksums MUST be used. 38*eda7acddSPeter Krystad * In other words, the only way for checksums not to be used 39*eda7acddSPeter Krystad * is if both hosts in their SYNs set A=0." 40*eda7acddSPeter Krystad * 41*eda7acddSPeter Krystad * Section 3.3.0: 42*eda7acddSPeter Krystad * "If a checksum is not present when its use has been 43*eda7acddSPeter Krystad * negotiated, the receiver MUST close the subflow with a RST as 44*eda7acddSPeter Krystad * it is considered broken." 45*eda7acddSPeter Krystad * 46*eda7acddSPeter Krystad * We don't implement DSS checksum - fall back to TCP. 47*eda7acddSPeter Krystad */ 48*eda7acddSPeter Krystad if (flags & MPTCP_CAP_CHECKSUM_REQD) 49*eda7acddSPeter Krystad break; 50*eda7acddSPeter Krystad 51*eda7acddSPeter Krystad mp_opt->mp_capable = 1; 52*eda7acddSPeter Krystad mp_opt->sndr_key = get_unaligned_be64(ptr); 53*eda7acddSPeter Krystad ptr += 8; 54*eda7acddSPeter Krystad 55*eda7acddSPeter Krystad if (opsize == TCPOLEN_MPTCP_MPC_ACK) { 56*eda7acddSPeter Krystad mp_opt->rcvr_key = get_unaligned_be64(ptr); 57*eda7acddSPeter Krystad ptr += 8; 58*eda7acddSPeter Krystad pr_debug("MP_CAPABLE sndr=%llu, rcvr=%llu", 59*eda7acddSPeter Krystad mp_opt->sndr_key, mp_opt->rcvr_key); 60*eda7acddSPeter Krystad } else { 61*eda7acddSPeter Krystad pr_debug("MP_CAPABLE sndr=%llu", mp_opt->sndr_key); 62*eda7acddSPeter Krystad } 63*eda7acddSPeter Krystad break; 64*eda7acddSPeter Krystad 65*eda7acddSPeter Krystad case MPTCPOPT_DSS: 66*eda7acddSPeter Krystad pr_debug("DSS"); 67*eda7acddSPeter Krystad mp_opt->dss = 1; 68*eda7acddSPeter Krystad break; 69*eda7acddSPeter Krystad 70*eda7acddSPeter Krystad default: 71*eda7acddSPeter Krystad break; 72*eda7acddSPeter Krystad } 73*eda7acddSPeter Krystad } 74*eda7acddSPeter Krystad 75*eda7acddSPeter Krystad void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts) 76*eda7acddSPeter Krystad { 77*eda7acddSPeter Krystad if ((OPTION_MPTCP_MPC_SYN | 78*eda7acddSPeter Krystad OPTION_MPTCP_MPC_ACK) & opts->suboptions) { 79*eda7acddSPeter Krystad u8 len; 80*eda7acddSPeter Krystad 81*eda7acddSPeter Krystad if (OPTION_MPTCP_MPC_SYN & opts->suboptions) 82*eda7acddSPeter Krystad len = TCPOLEN_MPTCP_MPC_SYN; 83*eda7acddSPeter Krystad else 84*eda7acddSPeter Krystad len = TCPOLEN_MPTCP_MPC_ACK; 85*eda7acddSPeter Krystad 86*eda7acddSPeter Krystad *ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) | 87*eda7acddSPeter Krystad (MPTCPOPT_MP_CAPABLE << 12) | 88*eda7acddSPeter Krystad (MPTCP_SUPPORTED_VERSION << 8) | 89*eda7acddSPeter Krystad MPTCP_CAP_HMAC_SHA1); 90*eda7acddSPeter Krystad put_unaligned_be64(opts->sndr_key, ptr); 91*eda7acddSPeter Krystad ptr += 2; 92*eda7acddSPeter Krystad if (OPTION_MPTCP_MPC_ACK & opts->suboptions) { 93*eda7acddSPeter Krystad put_unaligned_be64(opts->rcvr_key, ptr); 94*eda7acddSPeter Krystad ptr += 2; 95*eda7acddSPeter Krystad } 96*eda7acddSPeter Krystad } 97*eda7acddSPeter Krystad } 98