diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/debug.c | 4 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 3 | ||||
-rw-r--r-- | net/sctp/input.c | 14 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 36 | ||||
-rw-r--r-- | net/sctp/output.c | 21 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 6 | ||||
-rw-r--r-- | net/sctp/protocol.c | 31 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 37 | ||||
-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 | 216 | ||||
-rw-r--r-- | net/sctp/transport.c | 9 |
12 files changed, 191 insertions, 235 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/endpointola.c b/net/sctp/endpointola.c index 4c8d9f45ce09..905fda582b92 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -111,7 +111,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
111 | if (sctp_addip_enable) { | 111 | if (sctp_addip_enable) { |
112 | auth_chunks->chunks[0] = SCTP_CID_ASCONF; | 112 | auth_chunks->chunks[0] = SCTP_CID_ASCONF; |
113 | auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; | 113 | auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; |
114 | auth_chunks->param_hdr.length += htons(2); | 114 | auth_chunks->param_hdr.length = |
115 | htons(sizeof(sctp_paramhdr_t) + 2); | ||
115 | } | 116 | } |
116 | } | 117 | } |
117 | 118 | ||
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..7d08f522ec84 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -49,13 +49,10 @@ | |||
49 | #include <linux/ipv6.h> | 49 | #include <linux/ipv6.h> |
50 | #include <linux/init.h> | 50 | #include <linux/init.h> |
51 | #include <net/inet_ecn.h> | 51 | #include <net/inet_ecn.h> |
52 | #include <net/ip.h> | ||
52 | #include <net/icmp.h> | 53 | #include <net/icmp.h> |
53 | #include <net/net_namespace.h> | 54 | #include <net/net_namespace.h> |
54 | 55 | ||
55 | #ifndef TEST_FRAME | ||
56 | #include <net/tcp.h> | ||
57 | #endif /* TEST_FRAME (not defined) */ | ||
58 | |||
59 | #include <linux/socket.h> /* for sa_family_t */ | 56 | #include <linux/socket.h> /* for sa_family_t */ |
60 | #include <net/sock.h> | 57 | #include <net/sock.h> |
61 | 58 | ||
@@ -367,7 +364,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
367 | struct sctp_transport *tp = packet->transport; | 364 | struct sctp_transport *tp = packet->transport; |
368 | struct sctp_association *asoc = tp->asoc; | 365 | struct sctp_association *asoc = tp->asoc; |
369 | struct sctphdr *sh; | 366 | struct sctphdr *sh; |
370 | __be32 crc32 = __constant_cpu_to_be32(0); | ||
371 | struct sk_buff *nskb; | 367 | struct sk_buff *nskb; |
372 | struct sctp_chunk *chunk, *tmp; | 368 | struct sctp_chunk *chunk, *tmp; |
373 | struct sock *sk; | 369 | struct sock *sk; |
@@ -531,17 +527,16 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
531 | * Note: Adler-32 is no longer applicable, as has been replaced | 527 | * Note: Adler-32 is no longer applicable, as has been replaced |
532 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. | 528 | * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. |
533 | */ | 529 | */ |
534 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { | 530 | if (!sctp_checksum_disable && !(dst->dev->features & NETIF_F_NO_CSUM)) { |
535 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 531 | __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); |
536 | crc32 = sctp_end_cksum(crc32); | 532 | |
533 | /* 3) Put the resultant value into the checksum field in the | ||
534 | * common header, and leave the rest of the bits unchanged. | ||
535 | */ | ||
536 | sh->checksum = sctp_end_cksum(crc32); | ||
537 | } else | 537 | } else |
538 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | 538 | nskb->ip_summed = CHECKSUM_UNNECESSARY; |
539 | 539 | ||
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 | 540 | /* IP layer ECN support |
546 | * From RFC 2481 | 541 | * From RFC 2481 |
547 | * "The ECN-Capable Transport (ECT) bit would be set by the | 542 | * "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..d765fc53e74d 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 |
@@ -1757,6 +1758,9 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) | |||
1757 | struct sctp_chunk *chunk; | 1758 | struct sctp_chunk *chunk; |
1758 | struct list_head *lchunk, *temp; | 1759 | struct list_head *lchunk, *temp; |
1759 | 1760 | ||
1761 | if (!asoc->peer.prsctp_capable) | ||
1762 | return; | ||
1763 | |||
1760 | /* PR-SCTP C1) Let SackCumAck be the Cumulative TSN ACK carried in the | 1764 | /* PR-SCTP C1) Let SackCumAck be the Cumulative TSN ACK carried in the |
1761 | * received SACK. | 1765 | * received SACK. |
1762 | * | 1766 | * |
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..6851ee94e974 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 |
@@ -224,7 +224,9 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
224 | num_ext += 2; | 224 | num_ext += 2; |
225 | } | 225 | } |
226 | 226 | ||
227 | chunksize += sizeof(aiparam); | 227 | if (sp->adaptation_ind) |
228 | chunksize += sizeof(aiparam); | ||
229 | |||
228 | chunksize += vparam_len; | 230 | chunksize += vparam_len; |
229 | 231 | ||
230 | /* Account for AUTH related parameters */ | 232 | /* Account for AUTH related parameters */ |
@@ -304,10 +306,12 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
304 | if (sctp_prsctp_enable) | 306 | if (sctp_prsctp_enable) |
305 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); | 307 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); |
306 | 308 | ||
307 | aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; | 309 | if (sp->adaptation_ind) { |
308 | aiparam.param_hdr.length = htons(sizeof(aiparam)); | 310 | aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; |
309 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); | 311 | aiparam.param_hdr.length = htons(sizeof(aiparam)); |
310 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | 312 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); |
313 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | ||
314 | } | ||
311 | 315 | ||
312 | /* Add SCTP-AUTH chunks to the parameter list */ | 316 | /* Add SCTP-AUTH chunks to the parameter list */ |
313 | if (sctp_auth_enable) { | 317 | if (sctp_auth_enable) { |
@@ -332,6 +336,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
332 | sctp_inithdr_t initack; | 336 | sctp_inithdr_t initack; |
333 | struct sctp_chunk *retval; | 337 | struct sctp_chunk *retval; |
334 | union sctp_params addrs; | 338 | union sctp_params addrs; |
339 | struct sctp_sock *sp; | ||
335 | int addrs_len; | 340 | int addrs_len; |
336 | sctp_cookie_param_t *cookie; | 341 | sctp_cookie_param_t *cookie; |
337 | int cookie_len; | 342 | int cookie_len; |
@@ -366,22 +371,24 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
366 | /* Calculate the total size of allocation, include the reserved | 371 | /* Calculate the total size of allocation, include the reserved |
367 | * space for reporting unknown parameters if it is specified. | 372 | * space for reporting unknown parameters if it is specified. |
368 | */ | 373 | */ |
374 | sp = sctp_sk(asoc->base.sk); | ||
369 | chunksize = sizeof(initack) + addrs_len + cookie_len + unkparam_len; | 375 | chunksize = sizeof(initack) + addrs_len + cookie_len + unkparam_len; |
370 | 376 | ||
371 | /* Tell peer that we'll do ECN only if peer advertised such cap. */ | 377 | /* Tell peer that we'll do ECN only if peer advertised such cap. */ |
372 | if (asoc->peer.ecn_capable) | 378 | if (asoc->peer.ecn_capable) |
373 | chunksize += sizeof(ecap_param); | 379 | chunksize += sizeof(ecap_param); |
374 | 380 | ||
375 | if (sctp_prsctp_enable) | 381 | if (asoc->peer.prsctp_capable) |
376 | chunksize += sizeof(prsctp_param); | 382 | chunksize += sizeof(prsctp_param); |
377 | 383 | ||
378 | if (sctp_addip_enable) { | 384 | if (asoc->peer.asconf_capable) { |
379 | extensions[num_ext] = SCTP_CID_ASCONF; | 385 | extensions[num_ext] = SCTP_CID_ASCONF; |
380 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; | 386 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; |
381 | num_ext += 2; | 387 | num_ext += 2; |
382 | } | 388 | } |
383 | 389 | ||
384 | chunksize += sizeof(aiparam); | 390 | if (sp->adaptation_ind) |
391 | chunksize += sizeof(aiparam); | ||
385 | 392 | ||
386 | if (asoc->peer.auth_capable) { | 393 | if (asoc->peer.auth_capable) { |
387 | auth_random = (sctp_paramhdr_t *)asoc->c.auth_random; | 394 | auth_random = (sctp_paramhdr_t *)asoc->c.auth_random; |
@@ -432,10 +439,12 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
432 | if (asoc->peer.prsctp_capable) | 439 | if (asoc->peer.prsctp_capable) |
433 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); | 440 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); |
434 | 441 | ||
435 | aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; | 442 | if (sp->adaptation_ind) { |
436 | aiparam.param_hdr.length = htons(sizeof(aiparam)); | 443 | aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; |
437 | aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind); | 444 | aiparam.param_hdr.length = htons(sizeof(aiparam)); |
438 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | 445 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); |
446 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | ||
447 | } | ||
439 | 448 | ||
440 | if (asoc->peer.auth_capable) { | 449 | if (asoc->peer.auth_capable) { |
441 | sctp_addto_chunk(retval, ntohs(auth_random->length), | 450 | sctp_addto_chunk(retval, ntohs(auth_random->length), |
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..5fb3a8c9792e 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 |
@@ -5849,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) | |||
5849 | } | 5843 | } |
5850 | 5844 | ||
5851 | /* | 5845 | /* |
5852 | * 3.1.3 listen() - UDP Style Syntax | 5846 | * Move a socket to LISTENING state. |
5853 | * | ||
5854 | * By default, new associations are not accepted for UDP style sockets. | ||
5855 | * An application uses listen() to mark a socket as being able to | ||
5856 | * accept new associations. | ||
5857 | */ | 5847 | */ |
5858 | SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | 5848 | SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) |
5859 | { | 5849 | { |
5860 | struct sctp_sock *sp = sctp_sk(sk); | 5850 | struct sctp_sock *sp = sctp_sk(sk); |
5861 | struct sctp_endpoint *ep = sp->ep; | 5851 | struct sctp_endpoint *ep = sp->ep; |
5852 | struct crypto_hash *tfm = NULL; | ||
5862 | 5853 | ||
5863 | /* Only UDP style sockets that are not peeled off are allowed to | 5854 | /* Allocate HMAC for generating cookie. */ |
5864 | * listen(). | 5855 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { |
5865 | */ | 5856 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); |
5866 | if (!sctp_style(sk, UDP)) | 5857 | if (IS_ERR(tfm)) { |
5867 | return -EINVAL; | 5858 | if (net_ratelimit()) { |
5868 | 5859 | printk(KERN_INFO | |
5869 | /* If backlog is zero, disable listening. */ | 5860 | "SCTP: failed to load transform for %s: %ld\n", |
5870 | if (!backlog) { | 5861 | sctp_hmac_alg, PTR_ERR(tfm)); |
5871 | if (sctp_sstate(sk, CLOSED)) | 5862 | } |
5872 | return 0; | 5863 | return -ENOSYS; |
5873 | 5864 | } | |
5874 | sctp_unhash_endpoint(ep); | 5865 | sctp_sk(sk)->hmac = tfm; |
5875 | sk->sk_state = SCTP_SS_CLOSED; | ||
5876 | return 0; | ||
5877 | } | 5866 | } |
5878 | 5867 | ||
5879 | /* Return if we are already listening. */ | ||
5880 | if (sctp_sstate(sk, LISTENING)) | ||
5881 | return 0; | ||
5882 | |||
5883 | /* | 5868 | /* |
5884 | * If a bind() or sctp_bindx() is not called prior to a listen() | 5869 | * If a bind() or sctp_bindx() is not called prior to a listen() |
5885 | * call that allows new associations to be accepted, the system | 5870 | * call that allows new associations to be accepted, the system |
@@ -5890,7 +5875,6 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5890 | * extensions draft, but follows the practice as seen in TCP | 5875 | * extensions draft, but follows the practice as seen in TCP |
5891 | * sockets. | 5876 | * sockets. |
5892 | * | 5877 | * |
5893 | * Additionally, turn off fastreuse flag since we are not listening | ||
5894 | */ | 5878 | */ |
5895 | sk->sk_state = SCTP_SS_LISTENING; | 5879 | sk->sk_state = SCTP_SS_LISTENING; |
5896 | if (!ep->base.bind_addr.port) { | 5880 | if (!ep->base.bind_addr.port) { |
@@ -5901,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5901 | sk->sk_state = SCTP_SS_CLOSED; | 5885 | sk->sk_state = SCTP_SS_CLOSED; |
5902 | return -EADDRINUSE; | 5886 | return -EADDRINUSE; |
5903 | } | 5887 | } |
5904 | sctp_sk(sk)->bind_hash->fastreuse = 0; | ||
5905 | } | 5888 | } |
5906 | 5889 | ||
5907 | sctp_hash_endpoint(ep); | ||
5908 | return 0; | ||
5909 | } | ||
5910 | |||
5911 | /* | ||
5912 | * 4.1.3 listen() - TCP Style Syntax | ||
5913 | * | ||
5914 | * Applications uses listen() to ready the SCTP endpoint for accepting | ||
5915 | * inbound associations. | ||
5916 | */ | ||
5917 | SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) | ||
5918 | { | ||
5919 | struct sctp_sock *sp = sctp_sk(sk); | ||
5920 | struct sctp_endpoint *ep = sp->ep; | ||
5921 | |||
5922 | /* If backlog is zero, disable listening. */ | ||
5923 | if (!backlog) { | ||
5924 | if (sctp_sstate(sk, CLOSED)) | ||
5925 | return 0; | ||
5926 | |||
5927 | sctp_unhash_endpoint(ep); | ||
5928 | sk->sk_state = SCTP_SS_CLOSED; | ||
5929 | return 0; | ||
5930 | } | ||
5931 | |||
5932 | if (sctp_sstate(sk, LISTENING)) | ||
5933 | return 0; | ||
5934 | |||
5935 | /* | ||
5936 | * If a bind() or sctp_bindx() is not called prior to a listen() | ||
5937 | * call that allows new associations to be accepted, the system | ||
5938 | * picks an ephemeral port and will choose an address set equivalent | ||
5939 | * to binding with a wildcard address. | ||
5940 | * | ||
5941 | * This is not currently spelled out in the SCTP sockets | ||
5942 | * extensions draft, but follows the practice as seen in TCP | ||
5943 | * sockets. | ||
5944 | */ | ||
5945 | sk->sk_state = SCTP_SS_LISTENING; | ||
5946 | if (!ep->base.bind_addr.port) { | ||
5947 | if (sctp_autobind(sk)) | ||
5948 | return -EAGAIN; | ||
5949 | } else | ||
5950 | sctp_sk(sk)->bind_hash->fastreuse = 0; | ||
5951 | |||
5952 | sk->sk_max_ack_backlog = backlog; | 5890 | sk->sk_max_ack_backlog = backlog; |
5953 | sctp_hash_endpoint(ep); | 5891 | sctp_hash_endpoint(ep); |
5954 | return 0; | 5892 | return 0; |
5955 | } | 5893 | } |
5956 | 5894 | ||
5957 | /* | 5895 | /* |
5896 | * 4.1.3 / 5.1.3 listen() | ||
5897 | * | ||
5898 | * By default, new associations are not accepted for UDP style sockets. | ||
5899 | * An application uses listen() to mark a socket as being able to | ||
5900 | * accept new associations. | ||
5901 | * | ||
5902 | * On TCP style sockets, applications use listen() to ready the SCTP | ||
5903 | * endpoint for accepting inbound associations. | ||
5904 | * | ||
5905 | * On both types of endpoints a backlog of '0' disables listening. | ||
5906 | * | ||
5958 | * Move a socket to LISTENING state. | 5907 | * Move a socket to LISTENING state. |
5959 | */ | 5908 | */ |
5960 | int sctp_inet_listen(struct socket *sock, int backlog) | 5909 | int sctp_inet_listen(struct socket *sock, int backlog) |
5961 | { | 5910 | { |
5962 | struct sock *sk = sock->sk; | 5911 | struct sock *sk = sock->sk; |
5963 | struct crypto_hash *tfm = NULL; | 5912 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5964 | int err = -EINVAL; | 5913 | int err = -EINVAL; |
5965 | 5914 | ||
5966 | if (unlikely(backlog < 0)) | 5915 | if (unlikely(backlog < 0)) |
5967 | goto out; | 5916 | return err; |
5968 | 5917 | ||
5969 | sctp_lock_sock(sk); | 5918 | sctp_lock_sock(sk); |
5970 | 5919 | ||
5920 | /* Peeled-off sockets are not allowed to listen(). */ | ||
5921 | if (sctp_style(sk, UDP_HIGH_BANDWIDTH)) | ||
5922 | goto out; | ||
5923 | |||
5971 | if (sock->state != SS_UNCONNECTED) | 5924 | if (sock->state != SS_UNCONNECTED) |
5972 | goto out; | 5925 | goto out; |
5973 | 5926 | ||
5974 | /* Allocate HMAC for generating cookie. */ | 5927 | /* If backlog is zero, disable listening. */ |
5975 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { | 5928 | if (!backlog) { |
5976 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); | 5929 | if (sctp_sstate(sk, CLOSED)) |
5977 | if (IS_ERR(tfm)) { | ||
5978 | if (net_ratelimit()) { | ||
5979 | printk(KERN_INFO | ||
5980 | "SCTP: failed to load transform for %s: %ld\n", | ||
5981 | sctp_hmac_alg, PTR_ERR(tfm)); | ||
5982 | } | ||
5983 | err = -ENOSYS; | ||
5984 | goto out; | 5930 | goto out; |
5985 | } | ||
5986 | } | ||
5987 | 5931 | ||
5988 | switch (sock->type) { | 5932 | err = 0; |
5989 | case SOCK_SEQPACKET: | 5933 | sctp_unhash_endpoint(ep); |
5990 | err = sctp_seqpacket_listen(sk, backlog); | 5934 | sk->sk_state = SCTP_SS_CLOSED; |
5991 | break; | 5935 | if (sk->sk_reuse) |
5992 | case SOCK_STREAM: | 5936 | sctp_sk(sk)->bind_hash->fastreuse = 1; |
5993 | err = sctp_stream_listen(sk, backlog); | 5937 | goto out; |
5994 | break; | ||
5995 | default: | ||
5996 | break; | ||
5997 | } | 5938 | } |
5998 | 5939 | ||
5999 | if (err) | 5940 | /* If we are already listening, just update the backlog */ |
6000 | goto cleanup; | 5941 | if (sctp_sstate(sk, LISTENING)) |
5942 | sk->sk_max_ack_backlog = backlog; | ||
5943 | else { | ||
5944 | err = sctp_listen_start(sk, backlog); | ||
5945 | if (err) | ||
5946 | goto out; | ||
5947 | } | ||
6001 | 5948 | ||
6002 | /* Store away the transform reference. */ | 5949 | err = 0; |
6003 | if (!sctp_sk(sk)->hmac) | ||
6004 | sctp_sk(sk)->hmac = tfm; | ||
6005 | out: | 5950 | out: |
6006 | sctp_release_sock(sk); | 5951 | sctp_release_sock(sk); |
6007 | return err; | 5952 | return err; |
6008 | cleanup: | ||
6009 | crypto_free_hash(tfm); | ||
6010 | goto out; | ||
6011 | } | 5953 | } |
6012 | 5954 | ||
6013 | /* | 5955 | /* |
@@ -6700,6 +6642,48 @@ done: | |||
6700 | sctp_skb_set_owner_r(skb, sk); | 6642 | sctp_skb_set_owner_r(skb, sk); |
6701 | } | 6643 | } |
6702 | 6644 | ||
6645 | void sctp_copy_sock(struct sock *newsk, struct sock *sk, | ||
6646 | struct sctp_association *asoc) | ||
6647 | { | ||
6648 | struct inet_sock *inet = inet_sk(sk); | ||
6649 | struct inet_sock *newinet = inet_sk(newsk); | ||
6650 | |||
6651 | newsk->sk_type = sk->sk_type; | ||
6652 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | ||
6653 | newsk->sk_flags = sk->sk_flags; | ||
6654 | newsk->sk_no_check = sk->sk_no_check; | ||
6655 | newsk->sk_reuse = sk->sk_reuse; | ||
6656 | |||
6657 | newsk->sk_shutdown = sk->sk_shutdown; | ||
6658 | newsk->sk_destruct = inet_sock_destruct; | ||
6659 | newsk->sk_family = sk->sk_family; | ||
6660 | newsk->sk_protocol = IPPROTO_SCTP; | ||
6661 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
6662 | newsk->sk_sndbuf = sk->sk_sndbuf; | ||
6663 | newsk->sk_rcvbuf = sk->sk_rcvbuf; | ||
6664 | newsk->sk_lingertime = sk->sk_lingertime; | ||
6665 | newsk->sk_rcvtimeo = sk->sk_rcvtimeo; | ||
6666 | newsk->sk_sndtimeo = sk->sk_sndtimeo; | ||
6667 | |||
6668 | newinet = inet_sk(newsk); | ||
6669 | |||
6670 | /* Initialize sk's sport, dport, rcv_saddr and daddr for | ||
6671 | * getsockname() and getpeername() | ||
6672 | */ | ||
6673 | newinet->sport = inet->sport; | ||
6674 | newinet->saddr = inet->saddr; | ||
6675 | newinet->rcv_saddr = inet->rcv_saddr; | ||
6676 | newinet->dport = htons(asoc->peer.port); | ||
6677 | newinet->pmtudisc = inet->pmtudisc; | ||
6678 | newinet->id = asoc->next_tsn ^ jiffies; | ||
6679 | |||
6680 | newinet->uc_ttl = inet->uc_ttl; | ||
6681 | newinet->mc_loop = 1; | ||
6682 | newinet->mc_ttl = 1; | ||
6683 | newinet->mc_index = 0; | ||
6684 | newinet->mc_list = NULL; | ||
6685 | } | ||
6686 | |||
6703 | /* Populate the fields of the newsk from the oldsk and migrate the assoc | 6687 | /* Populate the fields of the newsk from the oldsk and migrate the assoc |
6704 | * and its messages to the newsk. | 6688 | * and its messages to the newsk. |
6705 | */ | 6689 | */ |
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 */ |