diff options
author | Andrea Bittau <a.bittau@cs.ucl.ac.uk> | 2006-03-20 20:43:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:43:56 -0500 |
commit | afe00251dd9b53d51de91ff0099961f42bbf3754 (patch) | |
tree | a56aa987140662cf3e6e65be402b8591298c5ced /net/dccp/proto.c | |
parent | 2a91aa3967398fb94eccc8da67c82bce9f67afdf (diff) |
[DCCP]: Initial feature negotiation implementation
Still needs more work, but boots and doesn't crashes, even
does some negotiation!
18:38:52.174934 127.0.0.1.43458 > 127.0.0.1.5001: request <change_l ack_ratio 2, change_r ccid 2, change_l ccid 2>
18:38:52.218526 127.0.0.1.5001 > 127.0.0.1.43458: response <nop, nop, change_l ack_ratio 2, confirm_r ccid 2 2, confirm_l ccid 2 2, confirm_r ack_ratio 2>
18:38:52.185398 127.0.0.1.43458 > 127.0.0.1.5001: <nop, confirm_r ack_ratio 2, ack_vector0 0x00, elapsed_time 212>
:-)
Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r-- | net/dccp/proto.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 81ad24953710..1a8cf8ecfe63 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include "ccid.h" | 38 | #include "ccid.h" |
39 | #include "dccp.h" | 39 | #include "dccp.h" |
40 | #include "feat.h" | ||
40 | 41 | ||
41 | DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; | 42 | DEFINE_SNMP_STAT(struct dccp_mib, dccp_statistics) __read_mostly; |
42 | 43 | ||
@@ -255,6 +256,39 @@ static int dccp_setsockopt_service(struct sock *sk, const u32 service, | |||
255 | return 0; | 256 | return 0; |
256 | } | 257 | } |
257 | 258 | ||
259 | /* byte 1 is feature. the rest is the preference list */ | ||
260 | static int dccp_setsockopt_change(struct sock *sk, int type, | ||
261 | struct dccp_so_feat __user *optval) | ||
262 | { | ||
263 | struct dccp_so_feat opt; | ||
264 | u8 *val; | ||
265 | int rc; | ||
266 | |||
267 | if (copy_from_user(&opt, optval, sizeof(opt))) | ||
268 | return -EFAULT; | ||
269 | |||
270 | val = kmalloc(opt.dccpsf_len, GFP_KERNEL); | ||
271 | if (!val) | ||
272 | return -ENOMEM; | ||
273 | |||
274 | if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) { | ||
275 | rc = -EFAULT; | ||
276 | goto out_free_val; | ||
277 | } | ||
278 | |||
279 | rc = dccp_feat_change(sk, type, opt.dccpsf_feat, val, opt.dccpsf_len, | ||
280 | GFP_KERNEL); | ||
281 | if (rc) | ||
282 | goto out_free_val; | ||
283 | |||
284 | out: | ||
285 | return rc; | ||
286 | |||
287 | out_free_val: | ||
288 | kfree(val); | ||
289 | goto out; | ||
290 | } | ||
291 | |||
258 | int dccp_setsockopt(struct sock *sk, int level, int optname, | 292 | int dccp_setsockopt(struct sock *sk, int level, int optname, |
259 | char __user *optval, int optlen) | 293 | char __user *optval, int optlen) |
260 | { | 294 | { |
@@ -284,6 +318,25 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, | |||
284 | case DCCP_SOCKOPT_PACKET_SIZE: | 318 | case DCCP_SOCKOPT_PACKET_SIZE: |
285 | dp->dccps_packet_size = val; | 319 | dp->dccps_packet_size = val; |
286 | break; | 320 | break; |
321 | |||
322 | case DCCP_SOCKOPT_CHANGE_L: | ||
323 | if (optlen != sizeof(struct dccp_so_feat)) | ||
324 | err = -EINVAL; | ||
325 | else | ||
326 | err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L, | ||
327 | (struct dccp_so_feat *) | ||
328 | optval); | ||
329 | break; | ||
330 | |||
331 | case DCCP_SOCKOPT_CHANGE_R: | ||
332 | if (optlen != sizeof(struct dccp_so_feat)) | ||
333 | err = -EINVAL; | ||
334 | else | ||
335 | err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R, | ||
336 | (struct dccp_so_feat *) | ||
337 | optval); | ||
338 | break; | ||
339 | |||
287 | default: | 340 | default: |
288 | err = -ENOPROTOOPT; | 341 | err = -ENOPROTOOPT; |
289 | break; | 342 | break; |