^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "protocol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /* Syncookies do not work for JOIN requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Unlike MP_CAPABLE, where the ACK cookie contains the needed MPTCP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * options to reconstruct the initial syn state, MP_JOIN does not contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * the token to obtain the mptcp socket nor the server-generated nonce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * that was used in the cookie SYN/ACK response.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Keep a small best effort state table to store the syn/synack data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * indexed by skb hash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * A MP_JOIN SYN packet handled by syn cookies is only stored if the 32bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * token matches a known mptcp connection that can still accept more subflows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * There is no timeout handling -- state is only re-constructed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * when the TCP ACK passed the cookie validation check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct join_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u32 remote_nonce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u32 local_nonce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u8 join_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u8 local_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u8 backup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u8 valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define COOKIE_JOIN_SLOTS 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static struct join_entry join_entries[COOKIE_JOIN_SLOTS] __cacheline_aligned_in_smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static spinlock_t join_entry_locks[COOKIE_JOIN_SLOTS] __cacheline_aligned_in_smp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static u32 mptcp_join_entry_hash(struct sk_buff *skb, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static u32 mptcp_join_hash_secret __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct tcphdr *th = tcp_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 seq, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) net_get_random_once(&mptcp_join_hash_secret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) sizeof(mptcp_join_hash_secret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (th->syn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) seq = TCP_SKB_CB(skb)->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) seq = TCP_SKB_CB(skb)->seq - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) i = jhash_3words(seq, net_hash_mix(net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) (__force __u32)th->source << 16 | (__force __u32)th->dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) mptcp_join_hash_secret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return i % ARRAY_SIZE(join_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void mptcp_join_store_state(struct join_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const struct mptcp_subflow_request_sock *subflow_req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) entry->token = subflow_req->token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) entry->remote_nonce = subflow_req->remote_nonce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) entry->local_nonce = subflow_req->local_nonce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) entry->backup = subflow_req->backup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) entry->join_id = subflow_req->remote_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) entry->local_id = subflow_req->local_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) entry->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void subflow_init_req_cookie_join_save(const struct mptcp_subflow_request_sock *subflow_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct net *net = read_pnet(&subflow_req->sk.req.ireq_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 i = mptcp_join_entry_hash(skb, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* No use in waiting if other cpu is already using this slot --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * would overwrite the data that got stored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) spin_lock_bh(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) mptcp_join_store_state(&join_entries[i], subflow_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) spin_unlock_bh(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Called for a cookie-ack with MP_JOIN option present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Look up the saved state based on skb hash & check token matches msk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * in same netns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Caller will check msk can still accept another subflow. The hmac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * present in the cookie ACK mptcp option space will be checked later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) bool mptcp_token_join_cookie_init_state(struct mptcp_subflow_request_sock *subflow_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct net *net = read_pnet(&subflow_req->sk.req.ireq_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u32 i = mptcp_join_entry_hash(skb, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct mptcp_sock *msk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct join_entry *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) e = &join_entries[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) spin_lock_bh(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (e->valid == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) spin_unlock_bh(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) e->valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) msk = mptcp_token_get_sock(net, e->token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!msk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) spin_unlock_bh(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) subflow_req->remote_nonce = e->remote_nonce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) subflow_req->local_nonce = e->local_nonce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) subflow_req->backup = e->backup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) subflow_req->remote_id = e->join_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) subflow_req->token = e->token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) subflow_req->msk = msk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) spin_unlock_bh(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void __init mptcp_join_cookie_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (i = 0; i < COOKIE_JOIN_SLOTS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) spin_lock_init(&join_entry_locks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }