1eda7acddSPeter Krystad // SPDX-License-Identifier: GPL-2.0 2eda7acddSPeter Krystad /* Multipath TCP 3eda7acddSPeter Krystad * 4eda7acddSPeter Krystad * Copyright (c) 2017 - 2019, Intel Corporation. 5eda7acddSPeter Krystad */ 6eda7acddSPeter Krystad 7eda7acddSPeter Krystad #include <linux/kernel.h> 8eda7acddSPeter Krystad #include <net/tcp.h> 9eda7acddSPeter Krystad #include <net/mptcp.h> 10eda7acddSPeter Krystad #include "protocol.h" 11eda7acddSPeter Krystad 12eda7acddSPeter Krystad void mptcp_parse_option(const unsigned char *ptr, int opsize, 13eda7acddSPeter Krystad struct tcp_options_received *opt_rx) 14eda7acddSPeter Krystad { 15eda7acddSPeter Krystad struct mptcp_options_received *mp_opt = &opt_rx->mptcp; 16eda7acddSPeter Krystad u8 subtype = *ptr >> 4; 17eda7acddSPeter Krystad u8 version; 18eda7acddSPeter Krystad u8 flags; 19eda7acddSPeter Krystad 20eda7acddSPeter Krystad switch (subtype) { 21eda7acddSPeter Krystad case MPTCPOPT_MP_CAPABLE: 22eda7acddSPeter Krystad if (opsize != TCPOLEN_MPTCP_MPC_SYN && 23eda7acddSPeter Krystad opsize != TCPOLEN_MPTCP_MPC_ACK) 24eda7acddSPeter Krystad break; 25eda7acddSPeter Krystad 26eda7acddSPeter Krystad version = *ptr++ & MPTCP_VERSION_MASK; 27eda7acddSPeter Krystad if (version != MPTCP_SUPPORTED_VERSION) 28eda7acddSPeter Krystad break; 29eda7acddSPeter Krystad 30eda7acddSPeter Krystad flags = *ptr++; 31eda7acddSPeter Krystad if (!((flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) || 32eda7acddSPeter Krystad (flags & MPTCP_CAP_EXTENSIBILITY)) 33eda7acddSPeter Krystad break; 34eda7acddSPeter Krystad 35eda7acddSPeter Krystad /* RFC 6824, Section 3.1: 36eda7acddSPeter Krystad * "For the Checksum Required bit (labeled "A"), if either 37eda7acddSPeter Krystad * host requires the use of checksums, checksums MUST be used. 38eda7acddSPeter Krystad * In other words, the only way for checksums not to be used 39eda7acddSPeter Krystad * is if both hosts in their SYNs set A=0." 40eda7acddSPeter Krystad * 41eda7acddSPeter Krystad * Section 3.3.0: 42eda7acddSPeter Krystad * "If a checksum is not present when its use has been 43eda7acddSPeter Krystad * negotiated, the receiver MUST close the subflow with a RST as 44eda7acddSPeter Krystad * it is considered broken." 45eda7acddSPeter Krystad * 46eda7acddSPeter Krystad * We don't implement DSS checksum - fall back to TCP. 47eda7acddSPeter Krystad */ 48eda7acddSPeter Krystad if (flags & MPTCP_CAP_CHECKSUM_REQD) 49eda7acddSPeter Krystad break; 50eda7acddSPeter Krystad 51eda7acddSPeter Krystad mp_opt->mp_capable = 1; 52eda7acddSPeter Krystad mp_opt->sndr_key = get_unaligned_be64(ptr); 53eda7acddSPeter Krystad ptr += 8; 54eda7acddSPeter Krystad 55eda7acddSPeter Krystad if (opsize == TCPOLEN_MPTCP_MPC_ACK) { 56eda7acddSPeter Krystad mp_opt->rcvr_key = get_unaligned_be64(ptr); 57eda7acddSPeter Krystad ptr += 8; 58eda7acddSPeter Krystad pr_debug("MP_CAPABLE sndr=%llu, rcvr=%llu", 59eda7acddSPeter Krystad mp_opt->sndr_key, mp_opt->rcvr_key); 60eda7acddSPeter Krystad } else { 61eda7acddSPeter Krystad pr_debug("MP_CAPABLE sndr=%llu", mp_opt->sndr_key); 62eda7acddSPeter Krystad } 63eda7acddSPeter Krystad break; 64eda7acddSPeter Krystad 65eda7acddSPeter Krystad case MPTCPOPT_DSS: 66eda7acddSPeter Krystad pr_debug("DSS"); 67eda7acddSPeter Krystad mp_opt->dss = 1; 68eda7acddSPeter Krystad break; 69eda7acddSPeter Krystad 70eda7acddSPeter Krystad default: 71eda7acddSPeter Krystad break; 72eda7acddSPeter Krystad } 73eda7acddSPeter Krystad } 74eda7acddSPeter Krystad 75*cec37a6eSPeter Krystad void mptcp_get_options(const struct sk_buff *skb, 76*cec37a6eSPeter Krystad struct tcp_options_received *opt_rx) 77*cec37a6eSPeter Krystad { 78*cec37a6eSPeter Krystad const unsigned char *ptr; 79*cec37a6eSPeter Krystad const struct tcphdr *th = tcp_hdr(skb); 80*cec37a6eSPeter Krystad int length = (th->doff * 4) - sizeof(struct tcphdr); 81*cec37a6eSPeter Krystad 82*cec37a6eSPeter Krystad ptr = (const unsigned char *)(th + 1); 83*cec37a6eSPeter Krystad 84*cec37a6eSPeter Krystad while (length > 0) { 85*cec37a6eSPeter Krystad int opcode = *ptr++; 86*cec37a6eSPeter Krystad int opsize; 87*cec37a6eSPeter Krystad 88*cec37a6eSPeter Krystad switch (opcode) { 89*cec37a6eSPeter Krystad case TCPOPT_EOL: 90*cec37a6eSPeter Krystad return; 91*cec37a6eSPeter Krystad case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ 92*cec37a6eSPeter Krystad length--; 93*cec37a6eSPeter Krystad continue; 94*cec37a6eSPeter Krystad default: 95*cec37a6eSPeter Krystad opsize = *ptr++; 96*cec37a6eSPeter Krystad if (opsize < 2) /* "silly options" */ 97*cec37a6eSPeter Krystad return; 98*cec37a6eSPeter Krystad if (opsize > length) 99*cec37a6eSPeter Krystad return; /* don't parse partial options */ 100*cec37a6eSPeter Krystad if (opcode == TCPOPT_MPTCP) 101*cec37a6eSPeter Krystad mptcp_parse_option(ptr, opsize, opt_rx); 102*cec37a6eSPeter Krystad ptr += opsize - 2; 103*cec37a6eSPeter Krystad length -= opsize; 104*cec37a6eSPeter Krystad } 105*cec37a6eSPeter Krystad } 106*cec37a6eSPeter Krystad } 107*cec37a6eSPeter Krystad 108*cec37a6eSPeter Krystad bool mptcp_syn_options(struct sock *sk, unsigned int *size, 109*cec37a6eSPeter Krystad struct mptcp_out_options *opts) 110*cec37a6eSPeter Krystad { 111*cec37a6eSPeter Krystad struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 112*cec37a6eSPeter Krystad 113*cec37a6eSPeter Krystad if (subflow->request_mptcp) { 114*cec37a6eSPeter Krystad pr_debug("local_key=%llu", subflow->local_key); 115*cec37a6eSPeter Krystad opts->suboptions = OPTION_MPTCP_MPC_SYN; 116*cec37a6eSPeter Krystad opts->sndr_key = subflow->local_key; 117*cec37a6eSPeter Krystad *size = TCPOLEN_MPTCP_MPC_SYN; 118*cec37a6eSPeter Krystad return true; 119*cec37a6eSPeter Krystad } 120*cec37a6eSPeter Krystad return false; 121*cec37a6eSPeter Krystad } 122*cec37a6eSPeter Krystad 123*cec37a6eSPeter Krystad void mptcp_rcv_synsent(struct sock *sk) 124*cec37a6eSPeter Krystad { 125*cec37a6eSPeter Krystad struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 126*cec37a6eSPeter Krystad struct tcp_sock *tp = tcp_sk(sk); 127*cec37a6eSPeter Krystad 128*cec37a6eSPeter Krystad pr_debug("subflow=%p", subflow); 129*cec37a6eSPeter Krystad if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) { 130*cec37a6eSPeter Krystad subflow->mp_capable = 1; 131*cec37a6eSPeter Krystad subflow->remote_key = tp->rx_opt.mptcp.sndr_key; 132*cec37a6eSPeter Krystad } else { 133*cec37a6eSPeter Krystad tcp_sk(sk)->is_mptcp = 0; 134*cec37a6eSPeter Krystad } 135*cec37a6eSPeter Krystad } 136*cec37a6eSPeter Krystad 137*cec37a6eSPeter Krystad bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, 138*cec37a6eSPeter Krystad unsigned int *size, unsigned int remaining, 139*cec37a6eSPeter Krystad struct mptcp_out_options *opts) 140*cec37a6eSPeter Krystad { 141*cec37a6eSPeter Krystad struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 142*cec37a6eSPeter Krystad 143*cec37a6eSPeter Krystad if (subflow->mp_capable && !subflow->fourth_ack) { 144*cec37a6eSPeter Krystad opts->suboptions = OPTION_MPTCP_MPC_ACK; 145*cec37a6eSPeter Krystad opts->sndr_key = subflow->local_key; 146*cec37a6eSPeter Krystad opts->rcvr_key = subflow->remote_key; 147*cec37a6eSPeter Krystad *size = TCPOLEN_MPTCP_MPC_ACK; 148*cec37a6eSPeter Krystad subflow->fourth_ack = 1; 149*cec37a6eSPeter Krystad pr_debug("subflow=%p, local_key=%llu, remote_key=%llu", 150*cec37a6eSPeter Krystad subflow, subflow->local_key, subflow->remote_key); 151*cec37a6eSPeter Krystad return true; 152*cec37a6eSPeter Krystad } 153*cec37a6eSPeter Krystad return false; 154*cec37a6eSPeter Krystad } 155*cec37a6eSPeter Krystad 156*cec37a6eSPeter Krystad bool mptcp_synack_options(const struct request_sock *req, unsigned int *size, 157*cec37a6eSPeter Krystad struct mptcp_out_options *opts) 158*cec37a6eSPeter Krystad { 159*cec37a6eSPeter Krystad struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req); 160*cec37a6eSPeter Krystad 161*cec37a6eSPeter Krystad if (subflow_req->mp_capable) { 162*cec37a6eSPeter Krystad opts->suboptions = OPTION_MPTCP_MPC_SYNACK; 163*cec37a6eSPeter Krystad opts->sndr_key = subflow_req->local_key; 164*cec37a6eSPeter Krystad *size = TCPOLEN_MPTCP_MPC_SYNACK; 165*cec37a6eSPeter Krystad pr_debug("subflow_req=%p, local_key=%llu", 166*cec37a6eSPeter Krystad subflow_req, subflow_req->local_key); 167*cec37a6eSPeter Krystad return true; 168*cec37a6eSPeter Krystad } 169*cec37a6eSPeter Krystad return false; 170*cec37a6eSPeter Krystad } 171*cec37a6eSPeter Krystad 172eda7acddSPeter Krystad void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts) 173eda7acddSPeter Krystad { 174eda7acddSPeter Krystad if ((OPTION_MPTCP_MPC_SYN | 175*cec37a6eSPeter Krystad OPTION_MPTCP_MPC_SYNACK | 176eda7acddSPeter Krystad OPTION_MPTCP_MPC_ACK) & opts->suboptions) { 177eda7acddSPeter Krystad u8 len; 178eda7acddSPeter Krystad 179eda7acddSPeter Krystad if (OPTION_MPTCP_MPC_SYN & opts->suboptions) 180eda7acddSPeter Krystad len = TCPOLEN_MPTCP_MPC_SYN; 181*cec37a6eSPeter Krystad else if (OPTION_MPTCP_MPC_SYNACK & opts->suboptions) 182*cec37a6eSPeter Krystad len = TCPOLEN_MPTCP_MPC_SYNACK; 183eda7acddSPeter Krystad else 184eda7acddSPeter Krystad len = TCPOLEN_MPTCP_MPC_ACK; 185eda7acddSPeter Krystad 186eda7acddSPeter Krystad *ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) | 187eda7acddSPeter Krystad (MPTCPOPT_MP_CAPABLE << 12) | 188eda7acddSPeter Krystad (MPTCP_SUPPORTED_VERSION << 8) | 189eda7acddSPeter Krystad MPTCP_CAP_HMAC_SHA1); 190eda7acddSPeter Krystad put_unaligned_be64(opts->sndr_key, ptr); 191eda7acddSPeter Krystad ptr += 2; 192eda7acddSPeter Krystad if (OPTION_MPTCP_MPC_ACK & opts->suboptions) { 193eda7acddSPeter Krystad put_unaligned_be64(opts->rcvr_key, ptr); 194eda7acddSPeter Krystad ptr += 2; 195eda7acddSPeter Krystad } 196eda7acddSPeter Krystad } 197eda7acddSPeter Krystad } 198