aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:27 -0400
commit71bb49596bbf4e5a3328e1704d18604e822ba181 (patch)
tree75f64f2f0fea482efc3bdcac407ab187d9e78b5a /net/dccp
parent86349c8d9c6892b57aff4549256ab1aa65aed0f0 (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>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ccid.c48
-rw-r--r--net/dccp/ccid.h5
-rw-r--r--net/dccp/feat.c4
-rw-r--r--net/dccp/proto.c2
4 files changed, 59 insertions, 0 deletions
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 4809753d12ae..f72ca83df552 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;
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index fdeae7b57319..259f5469d7d0 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -103,6 +103,11 @@ static inline void *ccid_priv(const struct ccid *ccid)
103 return (void *)ccid->ccid_priv; 103 return (void *)ccid->ccid_priv;
104} 104}
105 105
106extern bool ccid_support_check(u8 const *ccid_array, u8 array_len);
107extern int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
108extern int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
109 char __user *, int __user *);
110
106extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, 111extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
107 gfp_t gfp); 112 gfp_t gfp);
108 113
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index b859722fba72..9399554878cc 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -383,6 +383,10 @@ static int __feat_register_sp(struct list_head *fn, u8 feat, u8 is_local,
383 !dccp_feat_sp_list_ok(feat, sp_val, sp_len)) 383 !dccp_feat_sp_list_ok(feat, sp_val, sp_len))
384 return -EINVAL; 384 return -EINVAL;
385 385
386 /* Avoid negotiating alien CCIDs by only advertising supported ones */
387 if (feat == DCCPF_CCID && !ccid_support_check(sp_val, sp_len))
388 return -EOPNOTSUPP;
389
386 if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len)) 390 if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len))
387 return -ENOMEM; 391 return -ENOMEM;
388 392
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 01332fe7a99a..b4b10cbd8880 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -649,6 +649,8 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
649 case DCCP_SOCKOPT_GET_CUR_MPS: 649 case DCCP_SOCKOPT_GET_CUR_MPS:
650 val = dp->dccps_mss_cache; 650 val = dp->dccps_mss_cache;
651 break; 651 break;
652 case DCCP_SOCKOPT_AVAILABLE_CCIDS:
653 return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen);
652 case DCCP_SOCKOPT_SERVER_TIMEWAIT: 654 case DCCP_SOCKOPT_SERVER_TIMEWAIT:
653 val = dp->dccps_server_timewait; 655 val = dp->dccps_server_timewait;
654 break; 656 break;