aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
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
commit668144f7b41716a9efe1b398e15ead32a26cd101 (patch)
treeed535a5e2e2dc2dd8509336d2682aeaae66e4c00 /net/dccp/proto.c
parentd4c8741c431e07cfc66eb2b4c3a17b8d4975d9c0 (diff)
dccp: Deprecate old setsockopt framework
The previous setsockopt interface, which passed socket options via struct dccp_so_feat, is complicated/difficult to use. Continuing to support it leads to ugly code since the old approach did not distinguish between NN and SP values. This patch removes the old setsockopt interface and replaces it with two new functions to register NN/SP values for feature negotiation. These are essentially wrappers around the internal __feat_register functions, with checking added to avoid * wrong usage (type); * changing values while the connection is in progress. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r--net/dccp/proto.c53
1 files changed, 2 insertions, 51 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 46cb3490d48..108d56bd25c 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -470,44 +470,6 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
470 return 0; 470 return 0;
471} 471}
472 472
473/* byte 1 is feature. the rest is the preference list */
474static int dccp_setsockopt_change(struct sock *sk, int type,
475 struct dccp_so_feat __user *optval)
476{
477 struct dccp_so_feat opt;
478 u8 *val;
479 int rc;
480
481 if (copy_from_user(&opt, optval, sizeof(opt)))
482 return -EFAULT;
483 /*
484 * rfc4340: 6.1. Change Options
485 */
486 if (opt.dccpsf_len < 1)
487 return -EINVAL;
488
489 val = kmalloc(opt.dccpsf_len, GFP_KERNEL);
490 if (!val)
491 return -ENOMEM;
492
493 if (copy_from_user(val, opt.dccpsf_val, opt.dccpsf_len)) {
494 rc = -EFAULT;
495 goto out_free_val;
496 }
497
498 rc = dccp_feat_change(dccp_msk(sk), type, opt.dccpsf_feat,
499 val, opt.dccpsf_len, GFP_KERNEL);
500 if (rc)
501 goto out_free_val;
502
503out:
504 return rc;
505
506out_free_val:
507 kfree(val);
508 goto out;
509}
510
511static int do_dccp_setsockopt(struct sock *sk, int level, int optname, 473static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
512 char __user *optval, int optlen) 474 char __user *optval, int optlen)
513{ 475{
@@ -530,20 +492,9 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
530 err = 0; 492 err = 0;
531 break; 493 break;
532 case DCCP_SOCKOPT_CHANGE_L: 494 case DCCP_SOCKOPT_CHANGE_L:
533 if (optlen != sizeof(struct dccp_so_feat))
534 err = -EINVAL;
535 else
536 err = dccp_setsockopt_change(sk, DCCPO_CHANGE_L,
537 (struct dccp_so_feat __user *)
538 optval);
539 break;
540 case DCCP_SOCKOPT_CHANGE_R: 495 case DCCP_SOCKOPT_CHANGE_R:
541 if (optlen != sizeof(struct dccp_so_feat)) 496 DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");
542 err = -EINVAL; 497 err = 0;
543 else
544 err = dccp_setsockopt_change(sk, DCCPO_CHANGE_R,
545 (struct dccp_so_feat __user *)
546 optval);
547 break; 498 break;
548 case DCCP_SOCKOPT_SERVER_TIMEWAIT: 499 case DCCP_SOCKOPT_SERVER_TIMEWAIT:
549 if (dp->dccps_role != DCCP_ROLE_SERVER) 500 if (dp->dccps_role != DCCP_ROLE_SERVER)