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 e29bbf914057..2cd56df44d8e 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -506,6 +506,36 @@ static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx)
506 return rc; 506 return rc;
507} 507}
508 508
509static int dccp_setsockopt_ccid(struct sock *sk, int type,
510 char __user *optval, int optlen)
511{
512 u8 *val;
513 int rc = 0;
514
515 if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS)
516 return -EINVAL;
517
518 val = kmalloc(optlen, GFP_KERNEL);
519 if (val == NULL)
520 return -ENOMEM;
521
522 if (copy_from_user(val, optval, optlen)) {
523 kfree(val);
524 return -EFAULT;
525 }
526
527 lock_sock(sk);
528 if (type == DCCP_SOCKOPT_TX_CCID || type == DCCP_SOCKOPT_CCID)
529 rc = dccp_feat_register_sp(sk, DCCPF_CCID, 1, val, optlen);
530
531 if (!rc && (type == DCCP_SOCKOPT_RX_CCID || type == DCCP_SOCKOPT_CCID))
532 rc = dccp_feat_register_sp(sk, DCCPF_CCID, 0, val, optlen);
533 release_sock(sk);
534
535 kfree(val);
536 return rc;
537}
538
509static int do_dccp_setsockopt(struct sock *sk, int level, int optname, 539static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
510 char __user *optval, int optlen) 540 char __user *optval, int optlen)
511{ 541{
@@ -520,6 +550,10 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
520 case DCCP_SOCKOPT_CHANGE_R: 550 case DCCP_SOCKOPT_CHANGE_R:
521 DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n"); 551 DCCP_WARN("sockopt(CHANGE_L/R) is deprecated: fix your app\n");
522 return 0; 552 return 0;
553 case DCCP_SOCKOPT_CCID:
554 case DCCP_SOCKOPT_RX_CCID:
555 case DCCP_SOCKOPT_TX_CCID:
556 return dccp_setsockopt_ccid(sk, optname, optval, optlen);
523 } 557 }
524 558
525 if (optlen < (int)sizeof(int)) 559 if (optlen < (int)sizeof(int))