Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/skbuff.h>
0003 
0004 #include "protocol.h"
0005 
0006 /* Syncookies do not work for JOIN requests.
0007  *
0008  * Unlike MP_CAPABLE, where the ACK cookie contains the needed MPTCP
0009  * options to reconstruct the initial syn state, MP_JOIN does not contain
0010  * the token to obtain the mptcp socket nor the server-generated nonce
0011  * that was used in the cookie SYN/ACK response.
0012  *
0013  * Keep a small best effort state table to store the syn/synack data,
0014  * indexed by skb hash.
0015  *
0016  * A MP_JOIN SYN packet handled by syn cookies is only stored if the 32bit
0017  * token matches a known mptcp connection that can still accept more subflows.
0018  *
0019  * There is no timeout handling -- state is only re-constructed
0020  * when the TCP ACK passed the cookie validation check.
0021  */
0022 
0023 struct join_entry {
0024     u32 token;
0025     u32 remote_nonce;
0026     u32 local_nonce;
0027     u8 join_id;
0028     u8 local_id;
0029     u8 backup;
0030     u8 valid;
0031 };
0032 
0033 #define COOKIE_JOIN_SLOTS   1024
0034 
0035 static struct join_entry join_entries[COOKIE_JOIN_SLOTS] __cacheline_aligned_in_smp;
0036 static spinlock_t join_entry_locks[COOKIE_JOIN_SLOTS] __cacheline_aligned_in_smp;
0037 
0038 static u32 mptcp_join_entry_hash(struct sk_buff *skb, struct net *net)
0039 {
0040     static u32 mptcp_join_hash_secret __read_mostly;
0041     struct tcphdr *th = tcp_hdr(skb);
0042     u32 seq, i;
0043 
0044     net_get_random_once(&mptcp_join_hash_secret,
0045                 sizeof(mptcp_join_hash_secret));
0046 
0047     if (th->syn)
0048         seq = TCP_SKB_CB(skb)->seq;
0049     else
0050         seq = TCP_SKB_CB(skb)->seq - 1;
0051 
0052     i = jhash_3words(seq, net_hash_mix(net),
0053              (__force __u32)th->source << 16 | (__force __u32)th->dest,
0054              mptcp_join_hash_secret);
0055 
0056     return i % ARRAY_SIZE(join_entries);
0057 }
0058 
0059 static void mptcp_join_store_state(struct join_entry *entry,
0060                    const struct mptcp_subflow_request_sock *subflow_req)
0061 {
0062     entry->token = subflow_req->token;
0063     entry->remote_nonce = subflow_req->remote_nonce;
0064     entry->local_nonce = subflow_req->local_nonce;
0065     entry->backup = subflow_req->backup;
0066     entry->join_id = subflow_req->remote_id;
0067     entry->local_id = subflow_req->local_id;
0068     entry->valid = 1;
0069 }
0070 
0071 void subflow_init_req_cookie_join_save(const struct mptcp_subflow_request_sock *subflow_req,
0072                        struct sk_buff *skb)
0073 {
0074     struct net *net = read_pnet(&subflow_req->sk.req.ireq_net);
0075     u32 i = mptcp_join_entry_hash(skb, net);
0076 
0077     /* No use in waiting if other cpu is already using this slot --
0078      * would overwrite the data that got stored.
0079      */
0080     spin_lock_bh(&join_entry_locks[i]);
0081     mptcp_join_store_state(&join_entries[i], subflow_req);
0082     spin_unlock_bh(&join_entry_locks[i]);
0083 }
0084 
0085 /* Called for a cookie-ack with MP_JOIN option present.
0086  * Look up the saved state based on skb hash & check token matches msk
0087  * in same netns.
0088  *
0089  * Caller will check msk can still accept another subflow.  The hmac
0090  * present in the cookie ACK mptcp option space will be checked later.
0091  */
0092 bool mptcp_token_join_cookie_init_state(struct mptcp_subflow_request_sock *subflow_req,
0093                     struct sk_buff *skb)
0094 {
0095     struct net *net = read_pnet(&subflow_req->sk.req.ireq_net);
0096     u32 i = mptcp_join_entry_hash(skb, net);
0097     struct mptcp_sock *msk;
0098     struct join_entry *e;
0099 
0100     e = &join_entries[i];
0101 
0102     spin_lock_bh(&join_entry_locks[i]);
0103 
0104     if (e->valid == 0) {
0105         spin_unlock_bh(&join_entry_locks[i]);
0106         return false;
0107     }
0108 
0109     e->valid = 0;
0110 
0111     msk = mptcp_token_get_sock(net, e->token);
0112     if (!msk) {
0113         spin_unlock_bh(&join_entry_locks[i]);
0114         return false;
0115     }
0116 
0117     subflow_req->remote_nonce = e->remote_nonce;
0118     subflow_req->local_nonce = e->local_nonce;
0119     subflow_req->backup = e->backup;
0120     subflow_req->remote_id = e->join_id;
0121     subflow_req->token = e->token;
0122     subflow_req->msk = msk;
0123     spin_unlock_bh(&join_entry_locks[i]);
0124     return true;
0125 }
0126 
0127 void __init mptcp_join_cookie_init(void)
0128 {
0129     int i;
0130 
0131     for (i = 0; i < COOKIE_JOIN_SLOTS; i++)
0132         spin_lock_init(&join_entry_locks[i]);
0133 }