aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/debug.c4
-rw-r--r--net/sctp/input.c14
-rw-r--r--net/sctp/ipv6.c36
-rw-r--r--net/sctp/output.c16
-rw-r--r--net/sctp/outqueue.c3
-rw-r--r--net/sctp/protocol.c31
-rw-r--r--net/sctp/sm_make_chunk.c4
-rw-r--r--net/sctp/sm_sideeffect.c43
-rw-r--r--net/sctp/sm_statefuns.c6
-rw-r--r--net/sctp/socket.c64
-rw-r--r--net/sctp/transport.c9
11 files changed, 114 insertions, 116 deletions
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index 67715f4eb849..7ff548a30cfb 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -86,6 +86,9 @@ const char *sctp_cname(const sctp_subtype_t cid)
86 case SCTP_CID_FWD_TSN: 86 case SCTP_CID_FWD_TSN:
87 return "FWD_TSN"; 87 return "FWD_TSN";
88 88
89 case SCTP_CID_AUTH:
90 return "AUTH";
91
89 default: 92 default:
90 break; 93 break;
91 } 94 }
@@ -135,6 +138,7 @@ static const char *sctp_primitive_tbl[SCTP_NUM_PRIMITIVE_TYPES] = {
135 "PRIMITIVE_ABORT", 138 "PRIMITIVE_ABORT",
136 "PRIMITIVE_SEND", 139 "PRIMITIVE_SEND",
137 "PRIMITIVE_REQUESTHEARTBEAT", 140 "PRIMITIVE_REQUESTHEARTBEAT",
141 "PRIMITIVE_ASCONF",
138}; 142};
139 143
140/* Lookup primitive debug name. */ 144/* Lookup primitive debug name. */
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 2e4a8646dbc3..d2e98803ffe3 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -83,14 +83,15 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
83{ 83{
84 struct sk_buff *list = skb_shinfo(skb)->frag_list; 84 struct sk_buff *list = skb_shinfo(skb)->frag_list;
85 struct sctphdr *sh = sctp_hdr(skb); 85 struct sctphdr *sh = sctp_hdr(skb);
86 __be32 cmp = sh->checksum; 86 __le32 cmp = sh->checksum;
87 __be32 val = sctp_start_cksum((__u8 *)sh, skb_headlen(skb)); 87 __le32 val;
88 __u32 tmp = sctp_start_cksum((__u8 *)sh, skb_headlen(skb));
88 89
89 for (; list; list = list->next) 90 for (; list; list = list->next)
90 val = sctp_update_cksum((__u8 *)list->data, skb_headlen(list), 91 tmp = sctp_update_cksum((__u8 *)list->data, skb_headlen(list),
91 val); 92 tmp);
92 93
93 val = sctp_end_cksum(val); 94 val = sctp_end_cksum(tmp);
94 95
95 if (val != cmp) { 96 if (val != cmp) {
96 /* CRC failure, dump it. */ 97 /* CRC failure, dump it. */
@@ -142,7 +143,8 @@ int sctp_rcv(struct sk_buff *skb)
142 __skb_pull(skb, skb_transport_offset(skb)); 143 __skb_pull(skb, skb_transport_offset(skb));
143 if (skb->len < sizeof(struct sctphdr)) 144 if (skb->len < sizeof(struct sctphdr))
144 goto discard_it; 145 goto discard_it;
145 if (!skb_csum_unnecessary(skb) && sctp_rcv_checksum(skb) < 0) 146 if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) &&
147 sctp_rcv_checksum(skb) < 0)
146 goto discard_it; 148 goto discard_it;
147 149
148 skb_pull(skb, sizeof(struct sctphdr)); 150 skb_pull(skb, sizeof(struct sctphdr));
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ceaa4aa066ea..a63de3f7f185 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -97,8 +97,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
97 if (addr) { 97 if (addr) {
98 addr->a.v6.sin6_family = AF_INET6; 98 addr->a.v6.sin6_family = AF_INET6;
99 addr->a.v6.sin6_port = 0; 99 addr->a.v6.sin6_port = 0;
100 memcpy(&addr->a.v6.sin6_addr, &ifa->addr, 100 ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifa->addr);
101 sizeof(struct in6_addr));
102 addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; 101 addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
103 addr->valid = 1; 102 addr->valid = 1;
104 spin_lock_bh(&sctp_local_addr_lock); 103 spin_lock_bh(&sctp_local_addr_lock);
@@ -628,9 +627,7 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
628static struct sock *sctp_v6_create_accept_sk(struct sock *sk, 627static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
629 struct sctp_association *asoc) 628 struct sctp_association *asoc)
630{ 629{
631 struct inet_sock *inet = inet_sk(sk);
632 struct sock *newsk; 630 struct sock *newsk;
633 struct inet_sock *newinet;
634 struct ipv6_pinfo *newnp, *np = inet6_sk(sk); 631 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
635 struct sctp6_sock *newsctp6sk; 632 struct sctp6_sock *newsctp6sk;
636 633
@@ -640,17 +637,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
640 637
641 sock_init_data(NULL, newsk); 638 sock_init_data(NULL, newsk);
642 639
643 newsk->sk_type = SOCK_STREAM; 640 sctp_copy_sock(newsk, sk, asoc);
644
645 newsk->sk_prot = sk->sk_prot;
646 newsk->sk_no_check = sk->sk_no_check;
647 newsk->sk_reuse = sk->sk_reuse;
648
649 newsk->sk_destruct = inet_sock_destruct;
650 newsk->sk_family = PF_INET6;
651 newsk->sk_protocol = IPPROTO_SCTP;
652 newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
653 newsk->sk_shutdown = sk->sk_shutdown;
654 sock_reset_flag(sk, SOCK_ZAPPED); 641 sock_reset_flag(sk, SOCK_ZAPPED);
655 642
656 newsctp6sk = (struct sctp6_sock *)newsk; 643 newsctp6sk = (struct sctp6_sock *)newsk;
@@ -658,7 +645,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
658 645
659 sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; 646 sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped;
660 647
661 newinet = inet_sk(newsk);
662 newnp = inet6_sk(newsk); 648 newnp = inet6_sk(newsk);
663 649
664 memcpy(newnp, np, sizeof(struct ipv6_pinfo)); 650 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
@@ -666,26 +652,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
666 /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() 652 /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
667 * and getpeername(). 653 * and getpeername().
668 */ 654 */
669 newinet->sport = inet->sport;
670 newnp->saddr = np->saddr;
671 newnp->rcv_saddr = np->rcv_saddr;
672 newinet->dport = htons(asoc->peer.port);
673 sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); 655 sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
674 656
675 /* Init the ipv4 part of the socket since we can have sockets
676 * using v6 API for ipv4.
677 */
678 newinet->uc_ttl = -1;
679 newinet->mc_loop = 1;
680 newinet->mc_ttl = 1;
681 newinet->mc_index = 0;
682 newinet->mc_list = NULL;
683
684 if (ipv4_config.no_pmtu_disc)
685 newinet->pmtudisc = IP_PMTUDISC_DONT;
686 else
687 newinet->pmtudisc = IP_PMTUDISC_WANT;
688
689 sk_refcnt_debug_inc(newsk); 657 sk_refcnt_debug_inc(newsk);
690 658
691 if (newsk->sk_prot->init(newsk)) { 659 if (newsk->sk_prot->init(newsk)) {
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 73639355157e..07d58903a746 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -367,7 +367,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
367 struct sctp_transport *tp = packet->transport; 367 struct sctp_transport *tp = packet->transport;
368 struct sctp_association *asoc = tp->asoc; 368 struct sctp_association *asoc = tp->asoc;
369 struct sctphdr *sh; 369 struct sctphdr *sh;
370 __be32 crc32 = __constant_cpu_to_be32(0);
371 struct sk_buff *nskb; 370 struct sk_buff *nskb;
372 struct sctp_chunk *chunk, *tmp; 371 struct sctp_chunk *chunk, *tmp;
373 struct sock *sk; 372 struct sock *sk;
@@ -531,17 +530,16 @@ int sctp_packet_transmit(struct sctp_packet *packet)
531 * Note: Adler-32 is no longer applicable, as has been replaced 530 * Note: Adler-32 is no longer applicable, as has been replaced
532 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. 531 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
533 */ 532 */
534 if (!(dst->dev->features & NETIF_F_NO_CSUM)) { 533 if (!sctp_checksum_disable && !(dst->dev->features & NETIF_F_NO_CSUM)) {
535 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); 534 __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
536 crc32 = sctp_end_cksum(crc32); 535
536 /* 3) Put the resultant value into the checksum field in the
537 * common header, and leave the rest of the bits unchanged.
538 */
539 sh->checksum = sctp_end_cksum(crc32);
537 } else 540 } else
538 nskb->ip_summed = CHECKSUM_UNNECESSARY; 541 nskb->ip_summed = CHECKSUM_UNNECESSARY;
539 542
540 /* 3) Put the resultant value into the checksum field in the
541 * common header, and leave the rest of the bits unchanged.
542 */
543 sh->checksum = crc32;
544
545 /* IP layer ECN support 543 /* IP layer ECN support
546 * From RFC 2481 544 * From RFC 2481
547 * "The ECN-Capable Transport (ECT) bit would be set by the 545 * "The ECN-Capable Transport (ECT) bit would be set by the
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index bc411c896216..a367d15a21aa 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -428,7 +428,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
428 * retransmitting due to T3 timeout. 428 * retransmitting due to T3 timeout.
429 */ 429 */
430 if (reason == SCTP_RTXR_T3_RTX && 430 if (reason == SCTP_RTXR_T3_RTX &&
431 (jiffies - chunk->sent_at) < transport->last_rto) 431 time_before(jiffies, chunk->sent_at +
432 transport->last_rto))
432 continue; 433 continue;
433 434
434 /* RFC 2960 6.2.1 Processing a Received SACK 435 /* RFC 2960 6.2.1 Processing a Received SACK
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index c4986d0f7419..cb198af8887c 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -589,46 +589,21 @@ static int sctp_v4_is_ce(const struct sk_buff *skb)
589static struct sock *sctp_v4_create_accept_sk(struct sock *sk, 589static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
590 struct sctp_association *asoc) 590 struct sctp_association *asoc)
591{ 591{
592 struct inet_sock *inet = inet_sk(sk);
593 struct inet_sock *newinet;
594 struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL, 592 struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
595 sk->sk_prot); 593 sk->sk_prot);
594 struct inet_sock *newinet;
596 595
597 if (!newsk) 596 if (!newsk)
598 goto out; 597 goto out;
599 598
600 sock_init_data(NULL, newsk); 599 sock_init_data(NULL, newsk);
601 600
602 newsk->sk_type = SOCK_STREAM; 601 sctp_copy_sock(newsk, sk, asoc);
603
604 newsk->sk_no_check = sk->sk_no_check;
605 newsk->sk_reuse = sk->sk_reuse;
606 newsk->sk_shutdown = sk->sk_shutdown;
607
608 newsk->sk_destruct = inet_sock_destruct;
609 newsk->sk_family = PF_INET;
610 newsk->sk_protocol = IPPROTO_SCTP;
611 newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
612 sock_reset_flag(newsk, SOCK_ZAPPED); 602 sock_reset_flag(newsk, SOCK_ZAPPED);
613 603
614 newinet = inet_sk(newsk); 604 newinet = inet_sk(newsk);
615 605
616 /* Initialize sk's sport, dport, rcv_saddr and daddr for
617 * getsockname() and getpeername()
618 */
619 newinet->sport = inet->sport;
620 newinet->saddr = inet->saddr;
621 newinet->rcv_saddr = inet->rcv_saddr;
622 newinet->dport = htons(asoc->peer.port);
623 newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; 606 newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
624 newinet->pmtudisc = inet->pmtudisc;
625 newinet->id = asoc->next_tsn ^ jiffies;
626
627 newinet->uc_ttl = -1;
628 newinet->mc_loop = 1;
629 newinet->mc_ttl = 1;
630 newinet->mc_index = 0;
631 newinet->mc_list = NULL;
632 607
633 sk_refcnt_debug_inc(newsk); 608 sk_refcnt_debug_inc(newsk);
634 609
@@ -1413,4 +1388,6 @@ MODULE_ALIAS("net-pf-" __stringify(PF_INET) "-proto-132");
1413MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); 1388MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132");
1414MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>"); 1389MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>");
1415MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); 1390MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)");
1391module_param_named(no_checksums, sctp_checksum_disable, bool, 0644);
1392MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification");
1416MODULE_LICENSE("GPL"); 1393MODULE_LICENSE("GPL");
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index fd8acb48c3f2..b40e95f9851b 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -100,11 +100,11 @@ int sctp_chunk_iif(const struct sctp_chunk *chunk)
100 */ 100 */
101static const struct sctp_paramhdr ecap_param = { 101static const struct sctp_paramhdr ecap_param = {
102 SCTP_PARAM_ECN_CAPABLE, 102 SCTP_PARAM_ECN_CAPABLE,
103 __constant_htons(sizeof(struct sctp_paramhdr)), 103 cpu_to_be16(sizeof(struct sctp_paramhdr)),
104}; 104};
105static const struct sctp_paramhdr prsctp_param = { 105static const struct sctp_paramhdr prsctp_param = {
106 SCTP_PARAM_FWD_TSN_SUPPORT, 106 SCTP_PARAM_FWD_TSN_SUPPORT,
107 __constant_htons(sizeof(struct sctp_paramhdr)), 107 cpu_to_be16(sizeof(struct sctp_paramhdr)),
108}; 108};
109 109
110/* A helper to initialize to initialize an op error inside a 110/* A helper to initialize to initialize an op error inside a
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index b5495aecab60..e2020eb2c8ca 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -434,7 +434,8 @@ sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES] = {
434 * 434 *
435 */ 435 */
436static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, 436static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
437 struct sctp_transport *transport) 437 struct sctp_transport *transport,
438 int is_hb)
438{ 439{
439 /* The check for association's overall error counter exceeding the 440 /* The check for association's overall error counter exceeding the
440 * threshold is done in the state function. 441 * threshold is done in the state function.
@@ -461,9 +462,15 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
461 * expires, set RTO <- RTO * 2 ("back off the timer"). The 462 * expires, set RTO <- RTO * 2 ("back off the timer"). The
462 * maximum value discussed in rule C7 above (RTO.max) may be 463 * maximum value discussed in rule C7 above (RTO.max) may be
463 * used to provide an upper bound to this doubling operation. 464 * used to provide an upper bound to this doubling operation.
465 *
466 * Special Case: the first HB doesn't trigger exponential backoff.
467 * The first unacknowleged HB triggers it. We do this with a flag
468 * that indicates that we have an outstanding HB.
464 */ 469 */
465 transport->last_rto = transport->rto; 470 if (!is_hb || transport->hb_sent) {
466 transport->rto = min((transport->rto * 2), transport->asoc->rto_max); 471 transport->last_rto = transport->rto;
472 transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
473 }
467} 474}
468 475
469/* Worker routine to handle INIT command failure. */ 476/* Worker routine to handle INIT command failure. */
@@ -621,6 +628,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
621 t->error_count = 0; 628 t->error_count = 0;
622 t->asoc->overall_error_count = 0; 629 t->asoc->overall_error_count = 0;
623 630
631 /* Clear the hb_sent flag to signal that we had a good
632 * acknowledgement.
633 */
634 t->hb_sent = 0;
635
624 /* Mark the destination transport address as active if it is not so 636 /* Mark the destination transport address as active if it is not so
625 * marked. 637 * marked.
626 */ 638 */
@@ -646,18 +658,6 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
646 sctp_transport_hold(t); 658 sctp_transport_hold(t);
647} 659}
648 660
649/* Helper function to do a transport reset at the expiry of the hearbeat
650 * timer.
651 */
652static void sctp_cmd_transport_reset(sctp_cmd_seq_t *cmds,
653 struct sctp_association *asoc,
654 struct sctp_transport *t)
655{
656 sctp_transport_lower_cwnd(t, SCTP_LOWER_CWND_INACTIVE);
657
658 /* Mark one strike against a transport. */
659 sctp_do_8_2_transport_strike(asoc, t);
660}
661 661
662/* Helper function to process the process SACK command. */ 662/* Helper function to process the process SACK command. */
663static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, 663static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
@@ -1458,12 +1458,19 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1458 1458
1459 case SCTP_CMD_STRIKE: 1459 case SCTP_CMD_STRIKE:
1460 /* Mark one strike against a transport. */ 1460 /* Mark one strike against a transport. */
1461 sctp_do_8_2_transport_strike(asoc, cmd->obj.transport); 1461 sctp_do_8_2_transport_strike(asoc, cmd->obj.transport,
1462 0);
1463 break;
1464
1465 case SCTP_CMD_TRANSPORT_IDLE:
1466 t = cmd->obj.transport;
1467 sctp_transport_lower_cwnd(t, SCTP_LOWER_CWND_INACTIVE);
1462 break; 1468 break;
1463 1469
1464 case SCTP_CMD_TRANSPORT_RESET: 1470 case SCTP_CMD_TRANSPORT_HB_SENT:
1465 t = cmd->obj.transport; 1471 t = cmd->obj.transport;
1466 sctp_cmd_transport_reset(commands, asoc, t); 1472 sctp_do_8_2_transport_strike(asoc, t, 1);
1473 t->hb_sent = 1;
1467 break; 1474 break;
1468 1475
1469 case SCTP_CMD_TRANSPORT_ON: 1476 case SCTP_CMD_TRANSPORT_ON:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f88dfded0e3a..55a61aa69662 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -988,7 +988,9 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
988 /* Set transport error counter and association error counter 988 /* Set transport error counter and association error counter
989 * when sending heartbeat. 989 * when sending heartbeat.
990 */ 990 */
991 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET, 991 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
992 SCTP_TRANSPORT(transport));
993 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT,
992 SCTP_TRANSPORT(transport)); 994 SCTP_TRANSPORT(transport));
993 } 995 }
994 sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE, 996 sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
@@ -4955,7 +4957,7 @@ sctp_disposition_t sctp_sf_do_prm_requestheartbeat(
4955 * to that address and not acknowledged within one RTO. 4957 * to that address and not acknowledged within one RTO.
4956 * 4958 *
4957 */ 4959 */
4958 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET, 4960 sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT,
4959 SCTP_TRANSPORT(arg)); 4961 SCTP_TRANSPORT(arg));
4960 return SCTP_DISPOSITION_CONSUME; 4962 return SCTP_DISPOSITION_CONSUME;
4961} 4963}
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index ff0a8f88de04..bbd3cd238d7f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3069,9 +3069,6 @@ static int sctp_setsockopt_maxburst(struct sock *sk,
3069 int val; 3069 int val;
3070 int assoc_id = 0; 3070 int assoc_id = 0;
3071 3071
3072 if (optlen < sizeof(int))
3073 return -EINVAL;
3074
3075 if (optlen == sizeof(int)) { 3072 if (optlen == sizeof(int)) {
3076 printk(KERN_WARNING 3073 printk(KERN_WARNING
3077 "SCTP: Use of int in max_burst socket option deprecated\n"); 3074 "SCTP: Use of int in max_burst socket option deprecated\n");
@@ -3939,7 +3936,6 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
3939{ 3936{
3940 struct sock *sk = asoc->base.sk; 3937 struct sock *sk = asoc->base.sk;
3941 struct socket *sock; 3938 struct socket *sock;
3942 struct inet_sock *inetsk;
3943 struct sctp_af *af; 3939 struct sctp_af *af;
3944 int err = 0; 3940 int err = 0;
3945 3941
@@ -3954,18 +3950,18 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
3954 if (err < 0) 3950 if (err < 0)
3955 return err; 3951 return err;
3956 3952
3957 /* Populate the fields of the newsk from the oldsk and migrate the 3953 sctp_copy_sock(sock->sk, sk, asoc);
3958 * asoc to the newsk.
3959 */
3960 sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
3961 3954
3962 /* Make peeled-off sockets more like 1-1 accepted sockets. 3955 /* Make peeled-off sockets more like 1-1 accepted sockets.
3963 * Set the daddr and initialize id to something more random 3956 * Set the daddr and initialize id to something more random
3964 */ 3957 */
3965 af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); 3958 af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family);
3966 af->to_sk_daddr(&asoc->peer.primary_addr, sk); 3959 af->to_sk_daddr(&asoc->peer.primary_addr, sk);
3967 inetsk = inet_sk(sock->sk); 3960
3968 inetsk->id = asoc->next_tsn ^ jiffies; 3961 /* Populate the fields of the newsk from the oldsk and migrate the
3962 * asoc to the newsk.
3963 */
3964 sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
3969 3965
3970 *sockp = sock; 3966 *sockp = sock;
3971 3967
@@ -5284,16 +5280,14 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
5284 struct sctp_sock *sp; 5280 struct sctp_sock *sp;
5285 struct sctp_association *asoc; 5281 struct sctp_association *asoc;
5286 5282
5287 if (len < sizeof(int))
5288 return -EINVAL;
5289
5290 if (len == sizeof(int)) { 5283 if (len == sizeof(int)) {
5291 printk(KERN_WARNING 5284 printk(KERN_WARNING
5292 "SCTP: Use of int in max_burst socket option deprecated\n"); 5285 "SCTP: Use of int in max_burst socket option deprecated\n");
5293 printk(KERN_WARNING 5286 printk(KERN_WARNING
5294 "SCTP: Use struct sctp_assoc_value instead\n"); 5287 "SCTP: Use struct sctp_assoc_value instead\n");
5295 params.assoc_id = 0; 5288 params.assoc_id = 0;
5296 } else if (len == sizeof (struct sctp_assoc_value)) { 5289 } else if (len >= sizeof(struct sctp_assoc_value)) {
5290 len = sizeof(struct sctp_assoc_value);
5297 if (copy_from_user(&params, optval, len)) 5291 if (copy_from_user(&params, optval, len))
5298 return -EFAULT; 5292 return -EFAULT;
5299 } else 5293 } else
@@ -6700,6 +6694,48 @@ done:
6700 sctp_skb_set_owner_r(skb, sk); 6694 sctp_skb_set_owner_r(skb, sk);
6701} 6695}
6702 6696
6697void sctp_copy_sock(struct sock *newsk, struct sock *sk,
6698 struct sctp_association *asoc)
6699{
6700 struct inet_sock *inet = inet_sk(sk);
6701 struct inet_sock *newinet = inet_sk(newsk);
6702
6703 newsk->sk_type = sk->sk_type;
6704 newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
6705 newsk->sk_flags = sk->sk_flags;
6706 newsk->sk_no_check = sk->sk_no_check;
6707 newsk->sk_reuse = sk->sk_reuse;
6708
6709 newsk->sk_shutdown = sk->sk_shutdown;
6710 newsk->sk_destruct = inet_sock_destruct;
6711 newsk->sk_family = sk->sk_family;
6712 newsk->sk_protocol = IPPROTO_SCTP;
6713 newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
6714 newsk->sk_sndbuf = sk->sk_sndbuf;
6715 newsk->sk_rcvbuf = sk->sk_rcvbuf;
6716 newsk->sk_lingertime = sk->sk_lingertime;
6717 newsk->sk_rcvtimeo = sk->sk_rcvtimeo;
6718 newsk->sk_sndtimeo = sk->sk_sndtimeo;
6719
6720 newinet = inet_sk(newsk);
6721
6722 /* Initialize sk's sport, dport, rcv_saddr and daddr for
6723 * getsockname() and getpeername()
6724 */
6725 newinet->sport = inet->sport;
6726 newinet->saddr = inet->saddr;
6727 newinet->rcv_saddr = inet->rcv_saddr;
6728 newinet->dport = htons(asoc->peer.port);
6729 newinet->pmtudisc = inet->pmtudisc;
6730 newinet->id = asoc->next_tsn ^ jiffies;
6731
6732 newinet->uc_ttl = inet->uc_ttl;
6733 newinet->mc_loop = 1;
6734 newinet->mc_ttl = 1;
6735 newinet->mc_index = 0;
6736 newinet->mc_list = NULL;
6737}
6738
6703/* Populate the fields of the newsk from the oldsk and migrate the assoc 6739/* Populate the fields of the newsk from the oldsk and migrate the assoc
6704 * and its messages to the newsk. 6740 * and its messages to the newsk.
6705 */ 6741 */
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index e745c118f239..e5dde45c79d3 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -79,6 +79,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
79 peer->rttvar = 0; 79 peer->rttvar = 0;
80 peer->srtt = 0; 80 peer->srtt = 0;
81 peer->rto_pending = 0; 81 peer->rto_pending = 0;
82 peer->hb_sent = 0;
82 peer->fast_recovery = 0; 83 peer->fast_recovery = 0;
83 84
84 peer->last_time_heard = jiffies; 85 peer->last_time_heard = jiffies;
@@ -542,8 +543,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
542 * congestion indications more than once every window of 543 * congestion indications more than once every window of
543 * data (or more loosely more than once every round-trip time). 544 * data (or more loosely more than once every round-trip time).
544 */ 545 */
545 if ((jiffies - transport->last_time_ecne_reduced) > 546 if (time_after(jiffies, transport->last_time_ecne_reduced +
546 transport->rtt) { 547 transport->rtt)) {
547 transport->ssthresh = max(transport->cwnd/2, 548 transport->ssthresh = max(transport->cwnd/2,
548 4*transport->asoc->pathmtu); 549 4*transport->asoc->pathmtu);
549 transport->cwnd = transport->ssthresh; 550 transport->cwnd = transport->ssthresh;
@@ -560,7 +561,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
560 * to be done every RTO interval, we do it every hearbeat 561 * to be done every RTO interval, we do it every hearbeat
561 * interval. 562 * interval.
562 */ 563 */
563 if ((jiffies - transport->last_time_used) > transport->rto) 564 if (time_after(jiffies, transport->last_time_used +
565 transport->rto))
564 transport->cwnd = max(transport->cwnd/2, 566 transport->cwnd = max(transport->cwnd/2,
565 4*transport->asoc->pathmtu); 567 4*transport->asoc->pathmtu);
566 break; 568 break;
@@ -608,6 +610,7 @@ void sctp_transport_reset(struct sctp_transport *t)
608 t->flight_size = 0; 610 t->flight_size = 0;
609 t->error_count = 0; 611 t->error_count = 0;
610 t->rto_pending = 0; 612 t->rto_pending = 0;
613 t->hb_sent = 0;
611 t->fast_recovery = 0; 614 t->fast_recovery = 0;
612 615
613 /* Initialize the state information for SFR-CACC */ 616 /* Initialize the state information for SFR-CACC */