aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r--net/dccp/proto.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 8b63394ec24c..445884cf1c29 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -501,6 +501,36 @@ static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx)
501 return rc; 501 return rc;
502} 502}
503 503
504static int dccp_setsockopt_ccid(struct sock *sk, int type,
505 char __user *optval, int optlen)
506{
507 u8 *val;
508 int rc = 0;
509
510 if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS)
511 return -EINVAL;
512
513 val = kmalloc(optlen, GFP_KERNEL);
514 if (val == NULL)
515 return -ENOMEM;
516
517 if (copy_from_user(val, optval, optlen)) {
518 kfree(val);
519 return -EFAULT;
520 }
521
522 lock_sock(sk);
523 if (type == DCCP_SOCKOPT_TX_CCID || type == DCCP_SOCKOPT_CCID)
524 rc = dccp_feat_register_sp(sk, DCCPF_CCID, 1, val, optlen);
525
526 if (!rc && (type == DCCP_SOCKOPT_RX_CCID || type == DCCP_SOCKOPT_CCID))
527 rc = dccp_feat_register_sp(sk, DCCPF_CCID, 0, val, optlen);
528 release_sock(sk);
529
530 kfree(val);
531 return rc;
532}
533
504static int do_dccp_setsockopt(struct sock *sk, int level, int optname, 534static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
505 char __user *optval, int optlen) 535 char __user *optval, int optlen)
506{ 536{
@@ -515,6 +545,10 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
515 case DCCP_SOCKOPT_CHANGE_R: 545 case DCCP_SOCKOPT_CHANGE_R:
516 DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n"); 546 DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");
517 return 0; 547 return 0;
548 case DCCP_SOCKOPT_CCID:
549 case DCCP_SOCKOPT_RX_CCID:
550 case DCCP_SOCKOPT_TX_CCID:
551 return dccp_setsockopt_ccid(sk, optname, optval, optlen);
518 } 552 }
519 553
520 if (optlen < (int)sizeof(int)) 554 if (optlen < (int)sizeof(int))