^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * net/dccp/ccid.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * An implementation of the DCCP protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * CCID infrastructure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "ccid.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "ccids/lib/tfrc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static struct ccid_operations *ccids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) &ccid2_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef CONFIG_IP_DCCP_CCID3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) &ccid3_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #endif
^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) static struct ccid_operations *ccid_by_number(const u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) for (i = 0; i < ARRAY_SIZE(ccids); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (ccids[i]->ccid_id == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return ccids[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return NULL;
^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) /* check that up to @array_len members in @ccid_array are supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) bool ccid_support_check(u8 const *ccid_array, u8 array_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) while (array_len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (ccid_by_number(ccid_array[--array_len]) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * ccid_get_builtin_ccids - Populate a list of built-in CCIDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @ccid_array: pointer to copy into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @array_len: value to return length into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * This function allocates memory - caller must see that it is freed after use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *ccid_array = kmalloc(ARRAY_SIZE(ccids), gfp_any());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (*ccid_array == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (*array_len = 0; *array_len < ARRAY_SIZE(ccids); *array_len += 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) (*ccid_array)[*array_len] = ccids[*array_len]->ccid_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char __user *optval, int __user *optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 *ccid_array, array_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (ccid_get_builtin_ccids(&ccid_array, &array_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (put_user(array_len, optlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) else if (len > 0 && copy_to_user(optval, ccid_array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) len > array_len ? array_len : len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) kfree(ccid_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static struct kmem_cache *ccid_kmem_cache_create(int obj_size, char *slab_name_fmt, const char *fmt,...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct kmem_cache *slab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) vsnprintf(slab_name_fmt, CCID_SLAB_NAME_LENGTH, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) slab = kmem_cache_create(slab_name_fmt, sizeof(struct ccid) + obj_size, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) SLAB_HWCACHE_ALIGN, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return slab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) kmem_cache_destroy(slab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int __init ccid_activate(struct ccid_operations *ccid_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int err = -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ccid_ops->ccid_hc_rx_slab =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ccid_ops->ccid_hc_rx_slab_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "ccid%u_hc_rx_sock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ccid_ops->ccid_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (ccid_ops->ccid_hc_rx_slab == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ccid_ops->ccid_hc_tx_slab =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ccid_ops->ccid_hc_tx_slab_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) "ccid%u_hc_tx_sock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ccid_ops->ccid_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (ccid_ops->ccid_hc_tx_slab == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto out_free_rx_slab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) pr_info("DCCP: Activated CCID %d (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ccid_ops->ccid_id, ccid_ops->ccid_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) out_free_rx_slab:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ccid_ops->ccid_hc_rx_slab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static void ccid_deactivate(struct ccid_operations *ccid_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ccid_ops->ccid_hc_tx_slab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ccid_ops->ccid_hc_rx_slab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pr_info("DCCP: Deactivated CCID %d (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ccid_ops->ccid_id, ccid_ops->ccid_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct ccid_operations *ccid_ops = ccid_by_number(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct ccid *ccid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (ccid_ops == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ccid_ops->ccid_hc_tx_slab, gfp_any());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (ccid == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ccid->ccid_ops = ccid_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (ccid->ccid_ops->ccid_hc_rx_init != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) goto out_free_ccid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ccid->ccid_ops->ccid_hc_tx_init != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) goto out_free_ccid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ccid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) out_free_ccid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ccid_ops->ccid_hc_tx_slab, ccid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ccid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (ccid != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (ccid->ccid_ops->ccid_hc_rx_exit != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ccid->ccid_ops->ccid_hc_rx_exit(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) kmem_cache_free(ccid->ccid_ops->ccid_hc_rx_slab, ccid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (ccid != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (ccid->ccid_ops->ccid_hc_tx_exit != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ccid->ccid_ops->ccid_hc_tx_exit(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) kmem_cache_free(ccid->ccid_ops->ccid_hc_tx_slab, ccid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int __init ccid_initialize_builtins(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int i, err = tfrc_lib_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (i = 0; i < ARRAY_SIZE(ccids); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) err = ccid_activate(ccids[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) goto unwind_registrations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unwind_registrations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) while(--i >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ccid_deactivate(ccids[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) tfrc_lib_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) void ccid_cleanup_builtins(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) for (i = 0; i < ARRAY_SIZE(ccids); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ccid_deactivate(ccids[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) tfrc_lib_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }