aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccid.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-11-12 03:47:26 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-12 03:47:26 -0500
commitd90ebcbfa7f5a8b4e20518c9f94c5c4e4cd3c2e5 (patch)
treeb1fb407c7ee1adbe8215311675d133a83a2d55b5 /net/dccp/ccid.c
parente8ef967a54f401ac5e8637b7f7f8bddb006144c4 (diff)
dccp: Query supported CCIDs
This provides a data structure to record which CCIDs are locally supported and three accessor functions: - a test function for internal use which is used to validate CCID requests made by the user; - a copy function so that the list can be used for feature-negotiation; - documented getsockopt() support so that the user can query capabilities. The data structure is a table which is filled in at compile-time with the list of available CCIDs (which in turn depends on the Kconfig choices). Using the copy function for cloning the list of supported CCIDs is useful for feature negotiation, since the negotiation is now with the full list of available CCIDs (e.g. {2, 3}) instead of the default value {2}. This means negotiation will not fail if the peer requests to use CCID3 instead of CCID2. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/ccid.c')
-rw-r--r--net/dccp/ccid.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 8fe931a3d7a1..647cb0614f84 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -13,6 +13,13 @@
13 13
14#include "ccid.h" 14#include "ccid.h"
15 15
16static u8 builtin_ccids[] = {
17 DCCPC_CCID2, /* CCID2 is supported by default */
18#if defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE)
19 DCCPC_CCID3,
20#endif
21};
22
16static struct ccid_operations *ccids[CCID_MAX]; 23static struct ccid_operations *ccids[CCID_MAX];
17#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) 24#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
18static atomic_t ccids_lockct = ATOMIC_INIT(0); 25static atomic_t ccids_lockct = ATOMIC_INIT(0);
@@ -86,6 +93,47 @@ static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
86 } 93 }
87} 94}
88 95
96/* check that up to @array_len members in @ccid_array are supported */
97bool ccid_support_check(u8 const *ccid_array, u8 array_len)
98{
99 u8 i, j, found;
100
101 for (i = 0, found = 0; i < array_len; i++, found = 0) {
102 for (j = 0; !found && j < ARRAY_SIZE(builtin_ccids); j++)
103 found = (ccid_array[i] == builtin_ccids[j]);
104 if (!found)
105 return false;
106 }
107 return true;
108}
109
110/**
111 * ccid_get_builtin_ccids - Provide copy of `builtin' CCID array
112 * @ccid_array: pointer to copy into
113 * @array_len: value to return length into
114 * This function allocates memory - caller must see that it is freed after use.
115 */
116int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)
117{
118 *ccid_array = kmemdup(builtin_ccids, sizeof(builtin_ccids), gfp_any());
119 if (*ccid_array == NULL)
120 return -ENOBUFS;
121 *array_len = ARRAY_SIZE(builtin_ccids);
122 return 0;
123}
124
125int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
126 char __user *optval, int __user *optlen)
127{
128 if (len < sizeof(builtin_ccids))
129 return -EINVAL;
130
131 if (put_user(sizeof(builtin_ccids), optlen) ||
132 copy_to_user(optval, builtin_ccids, sizeof(builtin_ccids)))
133 return -EFAULT;
134 return 0;
135}
136
89int ccid_register(struct ccid_operations *ccid_ops) 137int ccid_register(struct ccid_operations *ccid_ops)
90{ 138{
91 int err = -ENOBUFS; 139 int err = -ENOBUFS;