@@ -520,6 +520,35 @@ static bool mptcp_check_data_fin(struct sock *sk)
return ret;
}
+static bool mptcp_validate_data_checksum(struct sock *ssk)
+{
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
+ struct mptcp_sock *msk = mptcp_sk(subflow->conn);
+ struct csum_pseudo_header header;
+ __wsum csum;
+
+ if (__mptcp_check_fallback(msk))
+ goto out;
+
+ if (subflow->csum_len < subflow->map_data_len)
+ goto out;
+
+ header.data_seq = subflow->map_seq;
+ header.subflow_seq = subflow->map_subflow_seq;
+ header.data_len = subflow->map_data_len;
+ header.csum = subflow->map_csum;
+
+ csum = csum_partial(&header, sizeof(header), subflow->data_csum);
+
+ if (csum_fold(csum))
+ return false;
+ subflow->data_csum = 0;
+ subflow->csum_len = 0;
+
+out:
+ return true;
+}
+
static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
struct sock *ssk,
unsigned int *bytes)
@@ -588,6 +617,12 @@ static bool __mptcp_move_skbs_from_subflow(struct mptcp_sock *msk,
if (tp->urg_data)
done = true;
+ if (READ_ONCE(msk->csum_enabled)) {
+ subflow->data_csum = skb_checksum(skb, offset, len,
+ subflow->data_csum);
+ subflow->csum_len += len;
+ mptcp_validate_data_checksum(ssk);
+ }
if (__mptcp_move_skb(msk, ssk, skb, offset, len))
moved += len;
seq += len;
@@ -399,6 +399,9 @@ struct mptcp_subflow_context {
u32 map_subflow_seq;
u32 ssn_offset;
u32 map_data_len;
+ __wsum data_csum;
+ u32 csum_len;
+ __sum16 map_csum;
u32 request_mptcp : 1, /* send MP_CAPABLE */
request_join : 1, /* send MP_JOIN */
request_bkup : 1,
@@ -948,9 +948,12 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
subflow->map_data_len = data_len;
subflow->map_valid = 1;
subflow->mpc_map = mpext->mpc_map;
- pr_debug("new map seq=%llu subflow_seq=%u data_len=%u",
+ subflow->data_csum = 0;
+ subflow->csum_len = 0;
+ subflow->map_csum = mpext->csum;
+ pr_debug("new map seq=%llu subflow_seq=%u data_len=%u csum=%u",
subflow->map_seq, subflow->map_subflow_seq,
- subflow->map_data_len);
+ subflow->map_data_len, subflow->map_csum);
validate_seq:
/* we revalidate valid mapping on new skb, because we must ensure