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:31 -0400
commit09856c108956c99088ead9267ccbd1dab77f7043 (patch)
tree39e29187c87429530f83d3aa672ec5b6214c8136 /net/dccp
parent5d3dac267a7fd0811ec777e76a81f97f5cdcb395 (diff)
dccp: Auto-load (when supported) CCID plugins for negotiation
This adds auto-loading of CCIDs (when module loading is enabled) for the purpose of feature negotiation. The problem with loading the CCIDs at the end of feature negotiation is that this would happen in software interrupt context. Besides, if the host advertises CCIDs during negotiation, it should have them ready to use, in case an agreeing peer wants to use it for the connection. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ccid.c39
-rw-r--r--net/dccp/ccid.h1
-rw-r--r--net/dccp/feat.c5
3 files changed, 35 insertions, 10 deletions
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 330372a1a0b6..e3fb52b4f5c6 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -196,22 +196,41 @@ int ccid_unregister(struct ccid_operations *ccid_ops)
196 196
197EXPORT_SYMBOL_GPL(ccid_unregister); 197EXPORT_SYMBOL_GPL(ccid_unregister);
198 198
199/**
200 * ccid_request_module - Pre-load CCID module for later use
201 * This should be called only from process context (e.g. during connection
202 * setup) and is necessary for later calls to ccid_new (typically in software
203 * interrupt), so that it has the modules available when they are needed.
204 */
205static int ccid_request_module(u8 id)
206{
207 if (!in_atomic()) {
208 ccids_read_lock();
209 if (ccids[id] == NULL) {
210 ccids_read_unlock();
211 return request_module("net-dccp-ccid-%d", id);
212 }
213 ccids_read_unlock();
214 }
215 return 0;
216}
217
218int ccid_request_modules(u8 const *ccid_array, u8 array_len)
219{
220#ifdef CONFIG_KMOD
221 while (array_len--)
222 if (ccid_request_module(ccid_array[array_len]))
223 return -1;
224#endif
225 return 0;
226}
227
199struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) 228struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
200{ 229{
201 struct ccid_operations *ccid_ops; 230 struct ccid_operations *ccid_ops;
202 struct ccid *ccid = NULL; 231 struct ccid *ccid = NULL;
203 232
204 ccids_read_lock(); 233 ccids_read_lock();
205#ifdef CONFIG_KMOD
206 if (ccids[id] == NULL) {
207 /* We only try to load if in process context */
208 ccids_read_unlock();
209 if (gfp & GFP_ATOMIC)
210 goto out;
211 request_module("net-dccp-ccid-%d", id);
212 ccids_read_lock();
213 }
214#endif
215 ccid_ops = ccids[id]; 234 ccid_ops = ccids[id];
216 if (ccid_ops == NULL) 235 if (ccid_ops == NULL)
217 goto out_unlock; 236 goto out_unlock;
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 18f69423a708..20ba066b2775 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -108,6 +108,7 @@ extern int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
108extern int ccid_getsockopt_builtin_ccids(struct sock *sk, int len, 108extern int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
109 char __user *, int __user *); 109 char __user *, int __user *);
110 110
111extern int ccid_request_modules(u8 const *ccid_array, u8 array_len);
111extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, 112extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
112 gfp_t gfp); 113 gfp_t gfp);
113 114
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index a687740e4420..9a4938092783 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -1158,6 +1158,11 @@ int dccp_feat_init(struct sock *sk)
1158 ccid_get_builtin_ccids(&rx.val, &rx.len)) 1158 ccid_get_builtin_ccids(&rx.val, &rx.len))
1159 return -ENOBUFS; 1159 return -ENOBUFS;
1160 1160
1161 /* Pre-load all CCID modules that are going to be advertised */
1162 rc = -EUNATCH;
1163 if (ccid_request_modules(tx.val, tx.len))
1164 goto free_ccid_lists;
1165
1161 if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) || 1166 if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) ||
1162 !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len)) 1167 !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len))
1163 goto free_ccid_lists; 1168 goto free_ccid_lists;