diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/debug.c | 4 | ||||
-rw-r--r-- | net/sctp/input.c | 14 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 36 | ||||
-rw-r--r-- | net/sctp/output.c | 16 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 3 | ||||
-rw-r--r-- | net/sctp/protocol.c | 31 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 4 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 43 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 6 | ||||
-rw-r--r-- | net/sctp/socket.c | 64 | ||||
-rw-r--r-- | net/sctp/transport.c | 9 |
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) | |||
628 | static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | 627 | static 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) | |||
589 | static struct sock *sctp_v4_create_accept_sk(struct sock *sk, | 589 | static 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"); | |||
1413 | MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); | 1388 | MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-132"); |
1414 | MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>"); | 1389 | MODULE_AUTHOR("Linux Kernel SCTP developers <lksctp-developers@lists.sourceforge.net>"); |
1415 | MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); | 1390 | MODULE_DESCRIPTION("Support for the SCTP protocol (RFC2960)"); |
1391 | module_param_named(no_checksums, sctp_checksum_disable, bool, 0644); | ||
1392 | MODULE_PARM_DESC(no_checksums, "Disable checksums computing and verification"); | ||
1416 | MODULE_LICENSE("GPL"); | 1393 | MODULE_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 | */ |
101 | static const struct sctp_paramhdr ecap_param = { | 101 | static 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 | }; |
105 | static const struct sctp_paramhdr prsctp_param = { | 105 | static 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 | */ |
436 | static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | 436 | static 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 | */ | ||
652 | static 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. */ |
663 | static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, | 663 | static 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(¶ms, optval, len)) | 5291 | if (copy_from_user(¶ms, 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 | ||
6697 | void 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 */ |