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.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 72cbdcfc2c65..5ec47d9ee447 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -52,6 +52,9 @@ struct inet_hashinfo __cacheline_aligned dccp_hashinfo = {
52 52
53EXPORT_SYMBOL_GPL(dccp_hashinfo); 53EXPORT_SYMBOL_GPL(dccp_hashinfo);
54 54
55/* the maximum queue length for tx in packets. 0 is no limit */
56int sysctl_dccp_tx_qlen __read_mostly = 5;
57
55void dccp_set_state(struct sock *sk, const int state) 58void dccp_set_state(struct sock *sk, const int state)
56{ 59{
57 const int oldstate = sk->sk_state; 60 const int oldstate = sk->sk_state;
@@ -212,6 +215,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
212 215
213 dccp_init_xmit_timers(sk); 216 dccp_init_xmit_timers(sk);
214 icsk->icsk_rto = DCCP_TIMEOUT_INIT; 217 icsk->icsk_rto = DCCP_TIMEOUT_INIT;
218 icsk->icsk_syn_retries = sysctl_dccp_request_retries;
215 sk->sk_state = DCCP_CLOSED; 219 sk->sk_state = DCCP_CLOSED;
216 sk->sk_write_space = dccp_write_space; 220 sk->sk_write_space = dccp_write_space;
217 icsk->icsk_sync_mss = dccp_sync_mss; 221 icsk->icsk_sync_mss = dccp_sync_mss;
@@ -262,12 +266,12 @@ int dccp_destroy_sock(struct sock *sk)
262 266
263EXPORT_SYMBOL_GPL(dccp_destroy_sock); 267EXPORT_SYMBOL_GPL(dccp_destroy_sock);
264 268
265static inline int dccp_listen_start(struct sock *sk) 269static inline int dccp_listen_start(struct sock *sk, int backlog)
266{ 270{
267 struct dccp_sock *dp = dccp_sk(sk); 271 struct dccp_sock *dp = dccp_sk(sk);
268 272
269 dp->dccps_role = DCCP_ROLE_LISTEN; 273 dp->dccps_role = DCCP_ROLE_LISTEN;
270 return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); 274 return inet_csk_listen_start(sk, backlog);
271} 275}
272 276
273int dccp_disconnect(struct sock *sk, int flags) 277int dccp_disconnect(struct sock *sk, int flags)
@@ -451,9 +455,8 @@ out_free_val:
451static int do_dccp_setsockopt(struct sock *sk, int level, int optname, 455static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
452 char __user *optval, int optlen) 456 char __user *optval, int optlen)
453{ 457{
454 struct dccp_sock *dp; 458 struct dccp_sock *dp = dccp_sk(sk);
455 int err; 459 int val, err = 0;
456 int val;
457 460
458 if (optlen < sizeof(int)) 461 if (optlen < sizeof(int))
459 return -EINVAL; 462 return -EINVAL;
@@ -465,14 +468,11 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
465 return dccp_setsockopt_service(sk, val, optval, optlen); 468 return dccp_setsockopt_service(sk, val, optval, optlen);
466 469
467 lock_sock(sk); 470 lock_sock(sk);
468 dp = dccp_sk(sk);
469 err = 0;
470
471 switch (optname) { 471 switch (optname) {
472 case DCCP_SOCKOPT_PACKET_SIZE: 472 case DCCP_SOCKOPT_PACKET_SIZE:
473 dp->dccps_packet_size = val; 473 DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
474 err = 0;
474 break; 475 break;
475
476 case DCCP_SOCKOPT_CHANGE_L: 476 case DCCP_SOCKOPT_CHANGE_L:
477 if (optlen != sizeof(struct dccp_so_feat)) 477 if (optlen != sizeof(struct dccp_so_feat))
478 err = -EINVAL; 478 err = -EINVAL;
@@ -481,7 +481,6 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
481 (struct dccp_so_feat __user *) 481 (struct dccp_so_feat __user *)
482 optval); 482 optval);
483 break; 483 break;
484
485 case DCCP_SOCKOPT_CHANGE_R: 484 case DCCP_SOCKOPT_CHANGE_R:
486 if (optlen != sizeof(struct dccp_so_feat)) 485 if (optlen != sizeof(struct dccp_so_feat))
487 err = -EINVAL; 486 err = -EINVAL;
@@ -490,12 +489,26 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
490 (struct dccp_so_feat __user *) 489 (struct dccp_so_feat __user *)
491 optval); 490 optval);
492 break; 491 break;
493 492 case DCCP_SOCKOPT_SEND_CSCOV: /* sender side, RFC 4340, sec. 9.2 */
493 if (val < 0 || val > 15)
494 err = -EINVAL;
495 else
496 dp->dccps_pcslen = val;
497 break;
498 case DCCP_SOCKOPT_RECV_CSCOV: /* receiver side, RFC 4340 sec. 9.2.1 */
499 if (val < 0 || val > 15)
500 err = -EINVAL;
501 else {
502 dp->dccps_pcrlen = val;
503 /* FIXME: add feature negotiation,
504 * ChangeL(MinimumChecksumCoverage, val) */
505 }
506 break;
494 default: 507 default:
495 err = -ENOPROTOOPT; 508 err = -ENOPROTOOPT;
496 break; 509 break;
497 } 510 }
498 511
499 release_sock(sk); 512 release_sock(sk);
500 return err; 513 return err;
501} 514}
@@ -569,12 +582,17 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
569 582
570 switch (optname) { 583 switch (optname) {
571 case DCCP_SOCKOPT_PACKET_SIZE: 584 case DCCP_SOCKOPT_PACKET_SIZE:
572 val = dp->dccps_packet_size; 585 DCCP_WARN("sockopt(PACKET_SIZE) is deprecated: fix your app\n");
573 len = sizeof(dp->dccps_packet_size); 586 return 0;
574 break;
575 case DCCP_SOCKOPT_SERVICE: 587 case DCCP_SOCKOPT_SERVICE:
576 return dccp_getsockopt_service(sk, len, 588 return dccp_getsockopt_service(sk, len,
577 (__be32 __user *)optval, optlen); 589 (__be32 __user *)optval, optlen);
590 case DCCP_SOCKOPT_SEND_CSCOV:
591 val = dp->dccps_pcslen;
592 break;
593 case DCCP_SOCKOPT_RECV_CSCOV:
594 val = dp->dccps_pcrlen;
595 break;
578 case 128 ... 191: 596 case 128 ... 191:
579 return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, 597 return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
580 len, (u32 __user *)optval, optlen); 598 len, (u32 __user *)optval, optlen);
@@ -630,6 +648,13 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
630 return -EMSGSIZE; 648 return -EMSGSIZE;
631 649
632 lock_sock(sk); 650 lock_sock(sk);
651
652 if (sysctl_dccp_tx_qlen &&
653 (sk->sk_write_queue.qlen >= sysctl_dccp_tx_qlen)) {
654 rc = -EAGAIN;
655 goto out_release;
656 }
657
633 timeo = sock_sndtimeo(sk, noblock); 658 timeo = sock_sndtimeo(sk, noblock);
634 659
635 /* 660 /*
@@ -788,7 +813,7 @@ int inet_dccp_listen(struct socket *sock, int backlog)
788 * FIXME: here it probably should be sk->sk_prot->listen_start 813 * FIXME: here it probably should be sk->sk_prot->listen_start
789 * see tcp_listen_start 814 * see tcp_listen_start
790 */ 815 */
791 err = dccp_listen_start(sk); 816 err = dccp_listen_start(sk, backlog);
792 if (err) 817 if (err)
793 goto out; 818 goto out;
794 } 819 }
@@ -1008,8 +1033,7 @@ static int __init dccp_init(void)
1008 } while (!dccp_hashinfo.ehash && --ehash_order > 0); 1033 } while (!dccp_hashinfo.ehash && --ehash_order > 0);
1009 1034
1010 if (!dccp_hashinfo.ehash) { 1035 if (!dccp_hashinfo.ehash) {
1011 printk(KERN_CRIT "Failed to allocate DCCP " 1036 DCCP_CRIT("Failed to allocate DCCP established hash table");
1012 "established hash table\n");
1013 goto out_free_bind_bucket_cachep; 1037 goto out_free_bind_bucket_cachep;
1014 } 1038 }
1015 1039
@@ -1031,7 +1055,7 @@ static int __init dccp_init(void)
1031 } while (!dccp_hashinfo.bhash && --bhash_order >= 0); 1055 } while (!dccp_hashinfo.bhash && --bhash_order >= 0);
1032 1056
1033 if (!dccp_hashinfo.bhash) { 1057 if (!dccp_hashinfo.bhash) {
1034 printk(KERN_CRIT "Failed to allocate DCCP bind hash table\n"); 1058 DCCP_CRIT("Failed to allocate DCCP bind hash table");
1035 goto out_free_dccp_ehash; 1059 goto out_free_dccp_ehash;
1036 } 1060 }
1037 1061