aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-11-23 19:02:31 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-23 19:02:31 -0500
commitb20a9c24d5c5d466d7e4a25c6f1bedbd2d16ad4f (patch)
tree17789215657f693caf36e22d3e724cc1b1e07ba6 /net/dccp/proto.c
parent2c62ad7b56fa8e2658253c0256ef4c4de228a0b9 (diff)
dccp: Set per-connection CCIDs via socket options
With this patch, TX/RX CCIDs can now be changed on a per-connection basis, which overrides the defaults set by the global sysctl variables for TX/RX CCIDs. To make full use of this facility, the remaining patches of this patch set are needed, which track dependencies and activate negotiated feature values. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
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))