net/mptcp/options.c

Source file repositories/reference/linux-study-clean/net/mptcp/options.c

File Facts

System
Linux kernel
Corpus path
net/mptcp/options.c
Extension
.c
Size
49402 bytes
Lines
1708
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
			if (skb->len > tcp_hdr(skb)->doff << 2)
				expected_opsize = TCPOLEN_MPTCP_MPC_ACK_DATA;
			else
				expected_opsize = TCPOLEN_MPTCP_MPC_ACK;
			subopt = OPTION_MPTCP_MPC_ACK;
		} else {
			if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_ACK) {
				expected_opsize = TCPOLEN_MPTCP_MPC_SYNACK;
				subopt = OPTION_MPTCP_MPC_SYNACK;
			} else {
				expected_opsize = TCPOLEN_MPTCP_MPC_SYN;
				subopt = OPTION_MPTCP_MPC_SYN;
			}
		}

		/* Cfr RFC 8684 Section 3.3.0:
		 * If a checksum is present but its use had
		 * not been negotiated in the MP_CAPABLE handshake, the receiver MUST
		 * close the subflow with a RST, as it is not behaving as negotiated.
		 * If a checksum is not present when its use has been negotiated, the
		 * receiver MUST close the subflow with a RST, as it is considered
		 * broken
		 * We parse even option with mismatching csum presence, so that
		 * later in subflow_data_ready we can trigger the reset.
		 */
		if (opsize != expected_opsize &&
		    (expected_opsize != TCPOLEN_MPTCP_MPC_ACK_DATA ||
		     opsize != TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM))
			break;

		/* try to be gentle vs future versions on the initial syn */
		version = *ptr++ & MPTCP_VERSION_MASK;
		if (opsize != TCPOLEN_MPTCP_MPC_SYN) {
			if (version != MPTCP_SUPPORTED_VERSION)
				break;
		} else if (version < MPTCP_SUPPORTED_VERSION) {
			break;
		}

		flags = *ptr++;
		if (!mptcp_cap_flag_sha256(flags) ||
		    (flags & MPTCP_CAP_EXTENSIBILITY))
			break;

		/* RFC 6824, Section 3.1:
		 * "For the Checksum Required bit (labeled "A"), if either
		 * host requires the use of checksums, checksums MUST be used.
		 * In other words, the only way for checksums not to be used
		 * is if both hosts in their SYNs set A=0."
		 */
		if (flags & MPTCP_CAP_CHECKSUM_REQD)
			mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;

		mp_opt->deny_join_id0 = !!(flags & MPTCP_CAP_DENY_JOIN_ID0);

		mp_opt->suboptions |= subopt;
		if (opsize >= TCPOLEN_MPTCP_MPC_SYNACK) {
			mp_opt->sndr_key = get_unaligned_be64(ptr);
			ptr += 8;
		}
		if (opsize >= TCPOLEN_MPTCP_MPC_ACK) {
			mp_opt->rcvr_key = get_unaligned_be64(ptr);
			ptr += 8;
		}
		if (opsize >= TCPOLEN_MPTCP_MPC_ACK_DATA) {
			/* Section 3.1.:
			 * "the data parameters in a MP_CAPABLE are semantically
			 * equivalent to those in a DSS option and can be used
			 * interchangeably."
			 */
			mp_opt->suboptions |= OPTION_MPTCP_DSS;
			mp_opt->use_map = 1;
			mp_opt->mpc_map = 1;
			mp_opt->data_len = get_unaligned_be16(ptr);
			ptr += 2;
		}
		if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM) {
			mp_opt->csum = get_unaligned((__force __sum16 *)ptr);
			mp_opt->suboptions |= OPTION_MPTCP_CSUMREQD;
			ptr += 2;
		}
		pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d csum=%u\n",
			 version, flags, opsize, mp_opt->sndr_key,
			 mp_opt->rcvr_key, mp_opt->data_len, mp_opt->csum);
		break;

	case MPTCPOPT_MP_JOIN:
		if (opsize == TCPOLEN_MPTCP_MPJ_SYN) {
			mp_opt->suboptions |= OPTION_MPTCP_MPJ_SYN;

Annotation

Implementation Notes