diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 18 | ||||
-rw-r--r-- | net/sctp/bind_addr.c | 16 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 7 | ||||
-rw-r--r-- | net/sctp/output.c | 5 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 65 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 67 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 81 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 92 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 10 | ||||
-rw-r--r-- | net/sctp/tsnmap.c | 346 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 10 | ||||
-rw-r--r-- | net/sctp/ulpqueue.c | 5 |
13 files changed, 383 insertions, 341 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8472b8b349c4..f4b23043b610 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -283,8 +283,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
283 | if (!sctp_ulpq_init(&asoc->ulpq, asoc)) | 283 | if (!sctp_ulpq_init(&asoc->ulpq, asoc)) |
284 | goto fail_init; | 284 | goto fail_init; |
285 | 285 | ||
286 | /* Set up the tsn tracking. */ | 286 | memset(&asoc->peer.tsn_map, 0, sizeof(struct sctp_tsnmap)); |
287 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, 0); | ||
288 | 287 | ||
289 | asoc->need_ecne = 0; | 288 | asoc->need_ecne = 0; |
290 | 289 | ||
@@ -402,6 +401,8 @@ void sctp_association_free(struct sctp_association *asoc) | |||
402 | /* Dispose of any pending chunks on the inqueue. */ | 401 | /* Dispose of any pending chunks on the inqueue. */ |
403 | sctp_inq_free(&asoc->base.inqueue); | 402 | sctp_inq_free(&asoc->base.inqueue); |
404 | 403 | ||
404 | sctp_tsnmap_free(&asoc->peer.tsn_map); | ||
405 | |||
405 | /* Free ssnmap storage. */ | 406 | /* Free ssnmap storage. */ |
406 | sctp_ssnmap_free(asoc->ssnmap); | 407 | sctp_ssnmap_free(asoc->ssnmap); |
407 | 408 | ||
@@ -599,11 +600,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
599 | /* Check to see if this is a duplicate. */ | 600 | /* Check to see if this is a duplicate. */ |
600 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 601 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
601 | if (peer) { | 602 | if (peer) { |
603 | /* An UNKNOWN state is only set on transports added by | ||
604 | * user in sctp_connectx() call. Such transports should be | ||
605 | * considered CONFIRMED per RFC 4960, Section 5.4. | ||
606 | */ | ||
602 | if (peer->state == SCTP_UNKNOWN) { | 607 | if (peer->state == SCTP_UNKNOWN) { |
603 | if (peer_state == SCTP_ACTIVE) | 608 | peer->state = SCTP_ACTIVE; |
604 | peer->state = SCTP_ACTIVE; | ||
605 | if (peer_state == SCTP_UNCONFIRMED) | ||
606 | peer->state = SCTP_UNCONFIRMED; | ||
607 | } | 609 | } |
608 | return peer; | 610 | return peer; |
609 | } | 611 | } |
@@ -1121,8 +1123,8 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1121 | asoc->peer.rwnd = new->peer.rwnd; | 1123 | asoc->peer.rwnd = new->peer.rwnd; |
1122 | asoc->peer.sack_needed = new->peer.sack_needed; | 1124 | asoc->peer.sack_needed = new->peer.sack_needed; |
1123 | asoc->peer.i = new->peer.i; | 1125 | asoc->peer.i = new->peer.i; |
1124 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, | 1126 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, |
1125 | asoc->peer.i.initial_tsn); | 1127 | asoc->peer.i.initial_tsn, GFP_ATOMIC); |
1126 | 1128 | ||
1127 | /* Remove any peer addresses not present in the new association. */ | 1129 | /* Remove any peer addresses not present in the new association. */ |
1128 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 1130 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index f62bc2468935..6d5944a745d4 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -457,7 +457,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
457 | { | 457 | { |
458 | int error = 0; | 458 | int error = 0; |
459 | 459 | ||
460 | if (sctp_is_any(addr)) { | 460 | if (sctp_is_any(NULL, addr)) { |
461 | error = sctp_copy_local_addr_list(dest, scope, gfp, flags); | 461 | error = sctp_copy_local_addr_list(dest, scope, gfp, flags); |
462 | } else if (sctp_in_scope(addr, scope)) { | 462 | } else if (sctp_in_scope(addr, scope)) { |
463 | /* Now that the address is in scope, check to see if | 463 | /* Now that the address is in scope, check to see if |
@@ -477,11 +477,21 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
477 | } | 477 | } |
478 | 478 | ||
479 | /* Is this a wildcard address? */ | 479 | /* Is this a wildcard address? */ |
480 | int sctp_is_any(const union sctp_addr *addr) | 480 | int sctp_is_any(struct sock *sk, const union sctp_addr *addr) |
481 | { | 481 | { |
482 | struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family); | 482 | unsigned short fam = 0; |
483 | struct sctp_af *af; | ||
484 | |||
485 | /* Try to get the right address family */ | ||
486 | if (addr->sa.sa_family != AF_UNSPEC) | ||
487 | fam = addr->sa.sa_family; | ||
488 | else if (sk) | ||
489 | fam = sk->sk_family; | ||
490 | |||
491 | af = sctp_get_af_specific(fam); | ||
483 | if (!af) | 492 | if (!af) |
484 | return 0; | 493 | return 0; |
494 | |||
485 | return af->is_any(addr); | 495 | return af->is_any(addr); |
486 | } | 496 | } |
487 | 497 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 47f91afa0211..4124bbb99947 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -156,7 +156,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
156 | skb->network_header = saveip; | 156 | skb->network_header = saveip; |
157 | skb->transport_header = savesctp; | 157 | skb->transport_header = savesctp; |
158 | if (!sk) { | 158 | if (!sk) { |
159 | ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS); | 159 | ICMP6_INC_STATS_BH(dev_net(skb->dev), idev, ICMP6_MIB_INERRORS); |
160 | goto out; | 160 | goto out; |
161 | } | 161 | } |
162 | 162 | ||
@@ -837,6 +837,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, | |||
837 | struct sctp_sock *opt) | 837 | struct sctp_sock *opt) |
838 | { | 838 | { |
839 | struct sctp_af *af1, *af2; | 839 | struct sctp_af *af1, *af2; |
840 | struct sock *sk = sctp_opt2sk(opt); | ||
840 | 841 | ||
841 | af1 = sctp_get_af_specific(addr1->sa.sa_family); | 842 | af1 = sctp_get_af_specific(addr1->sa.sa_family); |
842 | af2 = sctp_get_af_specific(addr2->sa.sa_family); | 843 | af2 = sctp_get_af_specific(addr2->sa.sa_family); |
@@ -845,11 +846,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, | |||
845 | return 0; | 846 | return 0; |
846 | 847 | ||
847 | /* If the socket is IPv6 only, v4 addrs will not match */ | 848 | /* If the socket is IPv6 only, v4 addrs will not match */ |
848 | if (__ipv6_only_sock(sctp_opt2sk(opt)) && af1 != af2) | 849 | if (__ipv6_only_sock(sk) && af1 != af2) |
849 | return 0; | 850 | return 0; |
850 | 851 | ||
851 | /* Today, wildcard AF_INET/AF_INET6. */ | 852 | /* Today, wildcard AF_INET/AF_INET6. */ |
852 | if (sctp_is_any(addr1) || sctp_is_any(addr2)) | 853 | if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) |
853 | return 1; | 854 | return 1; |
854 | 855 | ||
855 | if (addr1->sa.sa_family != addr2->sa.sa_family) | 856 | if (addr1->sa.sa_family != addr2->sa.sa_family) |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 0dc4a7dfb234..c3f417f7ec6e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -533,7 +533,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
533 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { | 533 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { |
534 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 534 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); |
535 | crc32 = sctp_end_cksum(crc32); | 535 | crc32 = sctp_end_cksum(crc32); |
536 | } | 536 | } else |
537 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | ||
537 | 538 | ||
538 | /* 3) Put the resultant value into the checksum field in the | 539 | /* 3) Put the resultant value into the checksum field in the |
539 | * common header, and leave the rest of the bits unchanged. | 540 | * common header, and leave the rest of the bits unchanged. |
@@ -698,7 +699,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, | |||
698 | * When a Fast Retransmit is being performed the sender SHOULD | 699 | * When a Fast Retransmit is being performed the sender SHOULD |
699 | * ignore the value of cwnd and SHOULD NOT delay retransmission. | 700 | * ignore the value of cwnd and SHOULD NOT delay retransmission. |
700 | */ | 701 | */ |
701 | if (chunk->fast_retransmit <= 0) | 702 | if (chunk->fast_retransmit != SCTP_NEED_FRTX) |
702 | if (transport->flight_size >= transport->cwnd) { | 703 | if (transport->flight_size >= transport->cwnd) { |
703 | retval = SCTP_XMIT_RWND_FULL; | 704 | retval = SCTP_XMIT_RWND_FULL; |
704 | goto finish; | 705 | goto finish; |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 4328ad5439c9..247ebc95c1e5 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -420,7 +420,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
420 | * be added to the retransmit queue. | 420 | * be added to the retransmit queue. |
421 | */ | 421 | */ |
422 | if ((reason == SCTP_RTXR_FAST_RTX && | 422 | if ((reason == SCTP_RTXR_FAST_RTX && |
423 | (chunk->fast_retransmit > 0)) || | 423 | (chunk->fast_retransmit == SCTP_NEED_FRTX)) || |
424 | (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { | 424 | (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { |
425 | /* If this chunk was sent less then 1 rto ago, do not | 425 | /* If this chunk was sent less then 1 rto ago, do not |
426 | * retransmit this chunk, but give the peer time | 426 | * retransmit this chunk, but give the peer time |
@@ -650,8 +650,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
650 | /* Mark the chunk as ineligible for fast retransmit | 650 | /* Mark the chunk as ineligible for fast retransmit |
651 | * after it is retransmitted. | 651 | * after it is retransmitted. |
652 | */ | 652 | */ |
653 | if (chunk->fast_retransmit > 0) | 653 | if (chunk->fast_retransmit == SCTP_NEED_FRTX) |
654 | chunk->fast_retransmit = -1; | 654 | chunk->fast_retransmit = SCTP_DONT_FRTX; |
655 | 655 | ||
656 | /* Force start T3-rtx timer when fast retransmitting | 656 | /* Force start T3-rtx timer when fast retransmitting |
657 | * the earliest outstanding TSN | 657 | * the earliest outstanding TSN |
@@ -680,8 +680,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
680 | */ | 680 | */ |
681 | if (rtx_timeout || fast_rtx) { | 681 | if (rtx_timeout || fast_rtx) { |
682 | list_for_each_entry(chunk1, lqueue, transmitted_list) { | 682 | list_for_each_entry(chunk1, lqueue, transmitted_list) { |
683 | if (chunk1->fast_retransmit > 0) | 683 | if (chunk1->fast_retransmit == SCTP_NEED_FRTX) |
684 | chunk1->fast_retransmit = -1; | 684 | chunk1->fast_retransmit = SCTP_DONT_FRTX; |
685 | } | 685 | } |
686 | } | 686 | } |
687 | 687 | ||
@@ -1129,12 +1129,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1129 | unsigned outstanding; | 1129 | unsigned outstanding; |
1130 | struct sctp_transport *primary = asoc->peer.primary_path; | 1130 | struct sctp_transport *primary = asoc->peer.primary_path; |
1131 | int count_of_newacks = 0; | 1131 | int count_of_newacks = 0; |
1132 | int gap_ack_blocks; | ||
1132 | 1133 | ||
1133 | /* Grab the association's destination address list. */ | 1134 | /* Grab the association's destination address list. */ |
1134 | transport_list = &asoc->peer.transport_addr_list; | 1135 | transport_list = &asoc->peer.transport_addr_list; |
1135 | 1136 | ||
1136 | sack_ctsn = ntohl(sack->cum_tsn_ack); | 1137 | sack_ctsn = ntohl(sack->cum_tsn_ack); |
1137 | 1138 | gap_ack_blocks = ntohs(sack->num_gap_ack_blocks); | |
1138 | /* | 1139 | /* |
1139 | * SFR-CACC algorithm: | 1140 | * SFR-CACC algorithm: |
1140 | * On receipt of a SACK the sender SHOULD execute the | 1141 | * On receipt of a SACK the sender SHOULD execute the |
@@ -1144,35 +1145,38 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1144 | * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be | 1145 | * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be |
1145 | * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for | 1146 | * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for |
1146 | * all destinations. | 1147 | * all destinations. |
1147 | */ | ||
1148 | if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { | ||
1149 | primary->cacc.changeover_active = 0; | ||
1150 | list_for_each_entry(transport, transport_list, | ||
1151 | transports) { | ||
1152 | transport->cacc.cycling_changeover = 0; | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | /* | ||
1157 | * SFR-CACC algorithm: | ||
1158 | * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE | 1148 | * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE |
1159 | * is set the receiver of the SACK MUST take the following actions: | 1149 | * is set the receiver of the SACK MUST take the following actions: |
1160 | * | 1150 | * |
1161 | * A) Initialize the cacc_saw_newack to 0 for all destination | 1151 | * A) Initialize the cacc_saw_newack to 0 for all destination |
1162 | * addresses. | 1152 | * addresses. |
1153 | * | ||
1154 | * Only bother if changeover_active is set. Otherwise, this is | ||
1155 | * totally suboptimal to do on every SACK. | ||
1163 | */ | 1156 | */ |
1164 | if (sack->num_gap_ack_blocks && | 1157 | if (primary->cacc.changeover_active) { |
1165 | primary->cacc.changeover_active) { | 1158 | u8 clear_cycling = 0; |
1166 | list_for_each_entry(transport, transport_list, transports) { | 1159 | |
1167 | transport->cacc.cacc_saw_newack = 0; | 1160 | if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { |
1161 | primary->cacc.changeover_active = 0; | ||
1162 | clear_cycling = 1; | ||
1163 | } | ||
1164 | |||
1165 | if (clear_cycling || gap_ack_blocks) { | ||
1166 | list_for_each_entry(transport, transport_list, | ||
1167 | transports) { | ||
1168 | if (clear_cycling) | ||
1169 | transport->cacc.cycling_changeover = 0; | ||
1170 | if (gap_ack_blocks) | ||
1171 | transport->cacc.cacc_saw_newack = 0; | ||
1172 | } | ||
1168 | } | 1173 | } |
1169 | } | 1174 | } |
1170 | 1175 | ||
1171 | /* Get the highest TSN in the sack. */ | 1176 | /* Get the highest TSN in the sack. */ |
1172 | highest_tsn = sack_ctsn; | 1177 | highest_tsn = sack_ctsn; |
1173 | if (sack->num_gap_ack_blocks) | 1178 | if (gap_ack_blocks) |
1174 | highest_tsn += | 1179 | highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); |
1175 | ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); | ||
1176 | 1180 | ||
1177 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) { | 1181 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) { |
1178 | highest_new_tsn = highest_tsn; | 1182 | highest_new_tsn = highest_tsn; |
@@ -1181,11 +1185,11 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1181 | highest_new_tsn = sctp_highest_new_tsn(sack, asoc); | 1185 | highest_new_tsn = sctp_highest_new_tsn(sack, asoc); |
1182 | } | 1186 | } |
1183 | 1187 | ||
1188 | |||
1184 | /* Run through the retransmit queue. Credit bytes received | 1189 | /* Run through the retransmit queue. Credit bytes received |
1185 | * and free those chunks that we can. | 1190 | * and free those chunks that we can. |
1186 | */ | 1191 | */ |
1187 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); | 1192 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); |
1188 | sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); | ||
1189 | 1193 | ||
1190 | /* Run through the transmitted queue. | 1194 | /* Run through the transmitted queue. |
1191 | * Credit bytes received and free those chunks which we can. | 1195 | * Credit bytes received and free those chunks which we can. |
@@ -1204,9 +1208,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1204 | count_of_newacks ++; | 1208 | count_of_newacks ++; |
1205 | } | 1209 | } |
1206 | 1210 | ||
1207 | list_for_each_entry(transport, transport_list, transports) { | 1211 | if (gap_ack_blocks) { |
1208 | sctp_mark_missing(q, &transport->transmitted, transport, | 1212 | list_for_each_entry(transport, transport_list, transports) |
1209 | highest_new_tsn, count_of_newacks); | 1213 | sctp_mark_missing(q, &transport->transmitted, transport, |
1214 | highest_new_tsn, count_of_newacks); | ||
1210 | } | 1215 | } |
1211 | 1216 | ||
1212 | /* Move the Cumulative TSN Ack Point if appropriate. */ | 1217 | /* Move the Cumulative TSN Ack Point if appropriate. */ |
@@ -1651,7 +1656,7 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1651 | * chunk if it has NOT been fast retransmitted or marked for | 1656 | * chunk if it has NOT been fast retransmitted or marked for |
1652 | * fast retransmit already. | 1657 | * fast retransmit already. |
1653 | */ | 1658 | */ |
1654 | if (!chunk->fast_retransmit && | 1659 | if (chunk->fast_retransmit == SCTP_CAN_FRTX && |
1655 | !chunk->tsn_gap_acked && | 1660 | !chunk->tsn_gap_acked && |
1656 | TSN_lt(tsn, highest_new_tsn_in_sack)) { | 1661 | TSN_lt(tsn, highest_new_tsn_in_sack)) { |
1657 | 1662 | ||
@@ -1676,7 +1681,7 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1676 | */ | 1681 | */ |
1677 | 1682 | ||
1678 | if (chunk->tsn_missing_report >= 3) { | 1683 | if (chunk->tsn_missing_report >= 3) { |
1679 | chunk->fast_retransmit = 1; | 1684 | chunk->fast_retransmit = SCTP_NEED_FRTX; |
1680 | do_fast_retransmit = 1; | 1685 | do_fast_retransmit = 1; |
1681 | } | 1686 | } |
1682 | } | 1687 | } |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e8ca4e54981f..fd8acb48c3f2 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -702,12 +702,14 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
702 | __u32 ctsn; | 702 | __u32 ctsn; |
703 | __u16 num_gabs, num_dup_tsns; | 703 | __u16 num_gabs, num_dup_tsns; |
704 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; | 704 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; |
705 | struct sctp_gap_ack_block gabs[SCTP_MAX_GABS]; | ||
705 | 706 | ||
707 | memset(gabs, 0, sizeof(gabs)); | ||
706 | ctsn = sctp_tsnmap_get_ctsn(map); | 708 | ctsn = sctp_tsnmap_get_ctsn(map); |
707 | SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn); | 709 | SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn); |
708 | 710 | ||
709 | /* How much room is needed in the chunk? */ | 711 | /* How much room is needed in the chunk? */ |
710 | num_gabs = sctp_tsnmap_num_gabs(map); | 712 | num_gabs = sctp_tsnmap_num_gabs(map, gabs); |
711 | num_dup_tsns = sctp_tsnmap_num_dups(map); | 713 | num_dup_tsns = sctp_tsnmap_num_dups(map); |
712 | 714 | ||
713 | /* Initialize the SACK header. */ | 715 | /* Initialize the SACK header. */ |
@@ -763,7 +765,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
763 | /* Add the gap ack block information. */ | 765 | /* Add the gap ack block information. */ |
764 | if (num_gabs) | 766 | if (num_gabs) |
765 | sctp_addto_chunk(retval, sizeof(__u32) * num_gabs, | 767 | sctp_addto_chunk(retval, sizeof(__u32) * num_gabs, |
766 | sctp_tsnmap_get_gabs(map)); | 768 | gabs); |
767 | 769 | ||
768 | /* Add the duplicate TSN information. */ | 770 | /* Add the duplicate TSN information. */ |
769 | if (num_dup_tsns) | 771 | if (num_dup_tsns) |
@@ -1012,6 +1014,29 @@ end: | |||
1012 | return retval; | 1014 | return retval; |
1013 | } | 1015 | } |
1014 | 1016 | ||
1017 | struct sctp_chunk *sctp_make_violation_paramlen( | ||
1018 | const struct sctp_association *asoc, | ||
1019 | const struct sctp_chunk *chunk, | ||
1020 | struct sctp_paramhdr *param) | ||
1021 | { | ||
1022 | struct sctp_chunk *retval; | ||
1023 | static const char error[] = "The following parameter had invalid length:"; | ||
1024 | size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + | ||
1025 | sizeof(sctp_paramhdr_t); | ||
1026 | |||
1027 | retval = sctp_make_abort(asoc, chunk, payload_len); | ||
1028 | if (!retval) | ||
1029 | goto nodata; | ||
1030 | |||
1031 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, | ||
1032 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1033 | sctp_addto_chunk(retval, sizeof(error), error); | ||
1034 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); | ||
1035 | |||
1036 | nodata: | ||
1037 | return retval; | ||
1038 | } | ||
1039 | |||
1015 | /* Make a HEARTBEAT chunk. */ | 1040 | /* Make a HEARTBEAT chunk. */ |
1016 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1041 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1017 | const struct sctp_transport *transport, | 1042 | const struct sctp_transport *transport, |
@@ -1188,7 +1213,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, | |||
1188 | */ | 1213 | */ |
1189 | retval->tsn_missing_report = 0; | 1214 | retval->tsn_missing_report = 0; |
1190 | retval->tsn_gap_acked = 0; | 1215 | retval->tsn_gap_acked = 0; |
1191 | retval->fast_retransmit = 0; | 1216 | retval->fast_retransmit = SCTP_CAN_FRTX; |
1192 | 1217 | ||
1193 | /* If this is a fragmented message, track all fragments | 1218 | /* If this is a fragmented message, track all fragments |
1194 | * of the message (for SEND_FAILED). | 1219 | * of the message (for SEND_FAILED). |
@@ -1782,11 +1807,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1782 | const struct sctp_chunk *chunk, | 1807 | const struct sctp_chunk *chunk, |
1783 | struct sctp_chunk **errp) | 1808 | struct sctp_chunk **errp) |
1784 | { | 1809 | { |
1785 | static const char error[] = "The following parameter had invalid length:"; | ||
1786 | size_t payload_len = WORD_ROUND(sizeof(error)) + | ||
1787 | sizeof(sctp_paramhdr_t); | ||
1788 | |||
1789 | |||
1790 | /* This is a fatal error. Any accumulated non-fatal errors are | 1810 | /* This is a fatal error. Any accumulated non-fatal errors are |
1791 | * not reported. | 1811 | * not reported. |
1792 | */ | 1812 | */ |
@@ -1794,14 +1814,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1794 | sctp_chunk_free(*errp); | 1814 | sctp_chunk_free(*errp); |
1795 | 1815 | ||
1796 | /* Create an error chunk and fill it in with our payload. */ | 1816 | /* Create an error chunk and fill it in with our payload. */ |
1797 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1817 | *errp = sctp_make_violation_paramlen(asoc, chunk, param); |
1798 | |||
1799 | if (*errp) { | ||
1800 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, | ||
1801 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1802 | sctp_addto_chunk(*errp, sizeof(error), error); | ||
1803 | sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); | ||
1804 | } | ||
1805 | 1818 | ||
1806 | return 0; | 1819 | return 0; |
1807 | } | 1820 | } |
@@ -1886,11 +1899,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1886 | /* if the peer reports AUTH, assume that he | 1899 | /* if the peer reports AUTH, assume that he |
1887 | * supports AUTH. | 1900 | * supports AUTH. |
1888 | */ | 1901 | */ |
1889 | asoc->peer.auth_capable = 1; | 1902 | if (sctp_auth_enable) |
1903 | asoc->peer.auth_capable = 1; | ||
1890 | break; | 1904 | break; |
1891 | case SCTP_CID_ASCONF: | 1905 | case SCTP_CID_ASCONF: |
1892 | case SCTP_CID_ASCONF_ACK: | 1906 | case SCTP_CID_ASCONF_ACK: |
1893 | asoc->peer.asconf_capable = 1; | 1907 | if (sctp_addip_enable) |
1908 | asoc->peer.asconf_capable = 1; | ||
1894 | break; | 1909 | break; |
1895 | default: | 1910 | default: |
1896 | break; | 1911 | break; |
@@ -2275,8 +2290,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
2275 | } | 2290 | } |
2276 | 2291 | ||
2277 | /* Set up the TSN tracking pieces. */ | 2292 | /* Set up the TSN tracking pieces. */ |
2278 | sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE, | 2293 | if (!sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, |
2279 | asoc->peer.i.initial_tsn); | 2294 | asoc->peer.i.initial_tsn, gfp)) |
2295 | goto clean_up; | ||
2280 | 2296 | ||
2281 | /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number | 2297 | /* RFC 2960 6.5 Stream Identifier and Stream Sequence Number |
2282 | * | 2298 | * |
@@ -2319,12 +2335,10 @@ clean_up: | |||
2319 | /* Release the transport structures. */ | 2335 | /* Release the transport structures. */ |
2320 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 2336 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
2321 | transport = list_entry(pos, struct sctp_transport, transports); | 2337 | transport = list_entry(pos, struct sctp_transport, transports); |
2322 | list_del_init(pos); | 2338 | if (transport->state != SCTP_ACTIVE) |
2323 | sctp_transport_free(transport); | 2339 | sctp_assoc_rm_peer(asoc, transport); |
2324 | } | 2340 | } |
2325 | 2341 | ||
2326 | asoc->peer.transport_count = 0; | ||
2327 | |||
2328 | nomem: | 2342 | nomem: |
2329 | return 0; | 2343 | return 0; |
2330 | } | 2344 | } |
@@ -2456,10 +2470,13 @@ do_addr_param: | |||
2456 | break; | 2470 | break; |
2457 | 2471 | ||
2458 | case SCTP_PARAM_ADAPTATION_LAYER_IND: | 2472 | case SCTP_PARAM_ADAPTATION_LAYER_IND: |
2459 | asoc->peer.adaptation_ind = param.aind->adaptation_ind; | 2473 | asoc->peer.adaptation_ind = ntohl(param.aind->adaptation_ind); |
2460 | break; | 2474 | break; |
2461 | 2475 | ||
2462 | case SCTP_PARAM_SET_PRIMARY: | 2476 | case SCTP_PARAM_SET_PRIMARY: |
2477 | if (!sctp_addip_enable) | ||
2478 | goto fall_through; | ||
2479 | |||
2463 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2480 | addr_param = param.v + sizeof(sctp_addip_param_t); |
2464 | 2481 | ||
2465 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2482 | af = sctp_get_af_specific(param_type2af(param.p->type)); |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 9732c797e8ed..e1d6076b4f59 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -889,6 +889,35 @@ static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands, | |||
889 | sctp_ulpq_tail_event(&asoc->ulpq, ev); | 889 | sctp_ulpq_tail_event(&asoc->ulpq, ev); |
890 | } | 890 | } |
891 | 891 | ||
892 | |||
893 | static void sctp_cmd_t1_timer_update(struct sctp_association *asoc, | ||
894 | sctp_event_timeout_t timer, | ||
895 | char *name) | ||
896 | { | ||
897 | struct sctp_transport *t; | ||
898 | |||
899 | t = asoc->init_last_sent_to; | ||
900 | asoc->init_err_counter++; | ||
901 | |||
902 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
903 | asoc->timeouts[timer] *= 2; | ||
904 | if (asoc->timeouts[timer] > asoc->max_init_timeo) { | ||
905 | asoc->timeouts[timer] = asoc->max_init_timeo; | ||
906 | } | ||
907 | asoc->init_cycle++; | ||
908 | SCTP_DEBUG_PRINTK( | ||
909 | "T1 %s Timeout adjustment" | ||
910 | " init_err_counter: %d" | ||
911 | " cycle: %d" | ||
912 | " timeout: %ld\n", | ||
913 | name, | ||
914 | asoc->init_err_counter, | ||
915 | asoc->init_cycle, | ||
916 | asoc->timeouts[timer]); | ||
917 | } | ||
918 | |||
919 | } | ||
920 | |||
892 | /* These three macros allow us to pull the debugging code out of the | 921 | /* These three macros allow us to pull the debugging code out of the |
893 | * main flow of sctp_do_sm() to keep attention focused on the real | 922 | * main flow of sctp_do_sm() to keep attention focused on the real |
894 | * functionality there. | 923 | * functionality there. |
@@ -1123,7 +1152,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1123 | 1152 | ||
1124 | case SCTP_CMD_REPORT_TSN: | 1153 | case SCTP_CMD_REPORT_TSN: |
1125 | /* Record the arrival of a TSN. */ | 1154 | /* Record the arrival of a TSN. */ |
1126 | sctp_tsnmap_mark(&asoc->peer.tsn_map, cmd->obj.u32); | 1155 | error = sctp_tsnmap_mark(&asoc->peer.tsn_map, |
1156 | cmd->obj.u32); | ||
1127 | break; | 1157 | break; |
1128 | 1158 | ||
1129 | case SCTP_CMD_REPORT_FWDTSN: | 1159 | case SCTP_CMD_REPORT_FWDTSN: |
@@ -1196,6 +1226,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1196 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 1226 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
1197 | SCTP_CHUNK(cmd->obj.ptr)); | 1227 | SCTP_CHUNK(cmd->obj.ptr)); |
1198 | 1228 | ||
1229 | if (new_obj->transport) { | ||
1230 | new_obj->transport->init_sent_count++; | ||
1231 | asoc->init_last_sent_to = new_obj->transport; | ||
1232 | } | ||
1233 | |||
1199 | /* FIXME - Eventually come up with a cleaner way to | 1234 | /* FIXME - Eventually come up with a cleaner way to |
1200 | * enabling COOKIE-ECHO + DATA bundling during | 1235 | * enabling COOKIE-ECHO + DATA bundling during |
1201 | * multihoming stale cookie scenarios, the following | 1236 | * multihoming stale cookie scenarios, the following |
@@ -1345,26 +1380,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1345 | * all transports have been tried at the current | 1380 | * all transports have been tried at the current |
1346 | * timeout. | 1381 | * timeout. |
1347 | */ | 1382 | */ |
1348 | t = asoc->init_last_sent_to; | 1383 | sctp_cmd_t1_timer_update(asoc, |
1349 | asoc->init_err_counter++; | 1384 | SCTP_EVENT_TIMEOUT_T1_INIT, |
1350 | 1385 | "INIT"); | |
1351 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
1352 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
1353 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
1354 | asoc->max_init_timeo) { | ||
1355 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
1356 | asoc->max_init_timeo; | ||
1357 | } | ||
1358 | asoc->init_cycle++; | ||
1359 | SCTP_DEBUG_PRINTK( | ||
1360 | "T1 INIT Timeout adjustment" | ||
1361 | " init_err_counter: %d" | ||
1362 | " cycle: %d" | ||
1363 | " timeout: %ld\n", | ||
1364 | asoc->init_err_counter, | ||
1365 | asoc->init_cycle, | ||
1366 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
1367 | } | ||
1368 | 1386 | ||
1369 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 1387 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
1370 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 1388 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
@@ -1377,20 +1395,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1377 | * all transports have been tried at the current | 1395 | * all transports have been tried at the current |
1378 | * timeout. | 1396 | * timeout. |
1379 | */ | 1397 | */ |
1380 | asoc->init_err_counter++; | 1398 | sctp_cmd_t1_timer_update(asoc, |
1381 | 1399 | SCTP_EVENT_TIMEOUT_T1_COOKIE, | |
1382 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; | 1400 | "COOKIE"); |
1383 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
1384 | asoc->max_init_timeo) { | ||
1385 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
1386 | asoc->max_init_timeo; | ||
1387 | } | ||
1388 | SCTP_DEBUG_PRINTK( | ||
1389 | "T1 COOKIE Timeout adjustment" | ||
1390 | " init_err_counter: %d" | ||
1391 | " timeout: %ld\n", | ||
1392 | asoc->init_err_counter, | ||
1393 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
1394 | 1401 | ||
1395 | /* If we've sent any data bundled with | 1402 | /* If we've sent any data bundled with |
1396 | * COOKIE-ECHO we need to resend. | 1403 | * COOKIE-ECHO we need to resend. |
@@ -1422,6 +1429,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1422 | case SCTP_CMD_INIT_COUNTER_RESET: | 1429 | case SCTP_CMD_INIT_COUNTER_RESET: |
1423 | asoc->init_err_counter = 0; | 1430 | asoc->init_err_counter = 0; |
1424 | asoc->init_cycle = 0; | 1431 | asoc->init_cycle = 0; |
1432 | list_for_each_entry(t, &asoc->peer.transport_addr_list, | ||
1433 | transports) { | ||
1434 | t->init_sent_count = 0; | ||
1435 | } | ||
1425 | break; | 1436 | break; |
1426 | 1437 | ||
1427 | case SCTP_CMD_REPORT_DUP: | 1438 | case SCTP_CMD_REPORT_DUP: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2c..d4c3fbc4671e 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
119 | const struct sctp_endpoint *ep, | 119 | const struct sctp_endpoint *ep, |
120 | const struct sctp_association *asoc, | 120 | const struct sctp_association *asoc, |
121 | const sctp_subtype_t type, | 121 | const sctp_subtype_t type, |
122 | void *arg, | 122 | void *arg, void *ext, |
123 | sctp_cmd_seq_t *commands); | 123 | sctp_cmd_seq_t *commands); |
124 | 124 | ||
125 | static sctp_disposition_t sctp_sf_violation_ctsn( | 125 | static sctp_disposition_t sctp_sf_violation_ctsn( |
@@ -315,8 +315,10 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
315 | /* If the packet is an OOTB packet which is temporarily on the | 315 | /* If the packet is an OOTB packet which is temporarily on the |
316 | * control endpoint, respond with an ABORT. | 316 | * control endpoint, respond with an ABORT. |
317 | */ | 317 | */ |
318 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) | 318 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { |
319 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | ||
319 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 320 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
321 | } | ||
320 | 322 | ||
321 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification | 323 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification |
322 | * Tag. | 324 | * Tag. |
@@ -635,8 +637,10 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
635 | /* If the packet is an OOTB packet which is temporarily on the | 637 | /* If the packet is an OOTB packet which is temporarily on the |
636 | * control endpoint, respond with an ABORT. | 638 | * control endpoint, respond with an ABORT. |
637 | */ | 639 | */ |
638 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) | 640 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { |
641 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | ||
639 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 642 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
643 | } | ||
640 | 644 | ||
641 | /* Make sure that the COOKIE_ECHO chunk has a valid length. | 645 | /* Make sure that the COOKIE_ECHO chunk has a valid length. |
642 | * In this case, we check that we have enough for at least a | 646 | * In this case, we check that we have enough for at least a |
@@ -2076,10 +2080,6 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2076 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | 2080 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) |
2077 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 2081 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); |
2078 | 2082 | ||
2079 | /* Stop the T5-shutdown guard timer. */ | ||
2080 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | ||
2081 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
2082 | |||
2083 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2083 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); |
2084 | } | 2084 | } |
2085 | 2085 | ||
@@ -3382,6 +3382,8 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, | |||
3382 | * packet and the state function that handles OOTB SHUTDOWN_ACK is | 3382 | * packet and the state function that handles OOTB SHUTDOWN_ACK is |
3383 | * called with a NULL association. | 3383 | * called with a NULL association. |
3384 | */ | 3384 | */ |
3385 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | ||
3386 | |||
3385 | return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); | 3387 | return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); |
3386 | } | 3388 | } |
3387 | 3389 | ||
@@ -3425,7 +3427,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3425 | addr_param = (union sctp_addr_param *)hdr->params; | 3427 | addr_param = (union sctp_addr_param *)hdr->params; |
3426 | length = ntohs(addr_param->p.length); | 3428 | length = ntohs(addr_param->p.length); |
3427 | if (length < sizeof(sctp_paramhdr_t)) | 3429 | if (length < sizeof(sctp_paramhdr_t)) |
3428 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3430 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3429 | (void *)addr_param, commands); | 3431 | (void *)addr_param, commands); |
3430 | 3432 | ||
3431 | /* Verify the ASCONF chunk before processing it. */ | 3433 | /* Verify the ASCONF chunk before processing it. */ |
@@ -3433,8 +3435,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3433 | (sctp_paramhdr_t *)((void *)addr_param + length), | 3435 | (sctp_paramhdr_t *)((void *)addr_param + length), |
3434 | (void *)chunk->chunk_end, | 3436 | (void *)chunk->chunk_end, |
3435 | &err_param)) | 3437 | &err_param)) |
3436 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3438 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3437 | (void *)&err_param, commands); | 3439 | (void *)err_param, commands); |
3438 | 3440 | ||
3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value | 3441 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value |
3440 | * the endpoint stored in a new association variable | 3442 | * the endpoint stored in a new association variable |
@@ -3542,8 +3544,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3542 | (sctp_paramhdr_t *)addip_hdr->params, | 3544 | (sctp_paramhdr_t *)addip_hdr->params, |
3543 | (void *)asconf_ack->chunk_end, | 3545 | (void *)asconf_ack->chunk_end, |
3544 | &err_param)) | 3546 | &err_param)) |
3545 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3547 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3546 | (void *)&err_param, commands); | 3548 | (void *)err_param, commands); |
3547 | 3549 | ||
3548 | if (last_asconf) { | 3550 | if (last_asconf) { |
3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; | 3551 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; |
@@ -4186,11 +4188,10 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4186 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 4188 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); |
4187 | } | 4189 | } |
4188 | 4190 | ||
4189 | discard: | ||
4190 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
4191 | |||
4192 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4191 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
4193 | 4192 | ||
4193 | discard: | ||
4194 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
4194 | return SCTP_DISPOSITION_ABORT; | 4195 | return SCTP_DISPOSITION_ABORT; |
4195 | 4196 | ||
4196 | nomem_pkt: | 4197 | nomem_pkt: |
@@ -4240,12 +4241,36 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
4240 | const struct sctp_endpoint *ep, | 4241 | const struct sctp_endpoint *ep, |
4241 | const struct sctp_association *asoc, | 4242 | const struct sctp_association *asoc, |
4242 | const sctp_subtype_t type, | 4243 | const sctp_subtype_t type, |
4243 | void *arg, | 4244 | void *arg, void *ext, |
4244 | sctp_cmd_seq_t *commands) { | 4245 | sctp_cmd_seq_t *commands) |
4245 | static const char err_str[] = "The following parameter had invalid length:"; | 4246 | { |
4247 | struct sctp_chunk *chunk = arg; | ||
4248 | struct sctp_paramhdr *param = ext; | ||
4249 | struct sctp_chunk *abort = NULL; | ||
4246 | 4250 | ||
4247 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4251 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
4248 | sizeof(err_str)); | 4252 | goto discard; |
4253 | |||
4254 | /* Make the abort chunk. */ | ||
4255 | abort = sctp_make_violation_paramlen(asoc, chunk, param); | ||
4256 | if (!abort) | ||
4257 | goto nomem; | ||
4258 | |||
4259 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4260 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | ||
4261 | |||
4262 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4263 | SCTP_ERROR(ECONNABORTED)); | ||
4264 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
4265 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | ||
4266 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
4267 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
4268 | |||
4269 | discard: | ||
4270 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
4271 | return SCTP_DISPOSITION_ABORT; | ||
4272 | nomem: | ||
4273 | return SCTP_DISPOSITION_NOMEM; | ||
4249 | } | 4274 | } |
4250 | 4275 | ||
4251 | /* Handle a protocol violation when the peer trying to advance the | 4276 | /* Handle a protocol violation when the peer trying to advance the |
@@ -4517,13 +4542,6 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( | |||
4517 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4542 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
4518 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); | 4543 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); |
4519 | 4544 | ||
4520 | /* sctpimpguide-05 Section 2.12.2 | ||
4521 | * The sender of the SHUTDOWN MAY also start an overall guard timer | ||
4522 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | ||
4523 | */ | ||
4524 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
4525 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
4526 | |||
4527 | disposition = SCTP_DISPOSITION_CONSUME; | 4545 | disposition = SCTP_DISPOSITION_CONSUME; |
4528 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 4546 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
4529 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, | 4547 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, |
@@ -4968,6 +4986,13 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
4968 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 4986 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
4969 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 4987 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
4970 | 4988 | ||
4989 | /* RFC 4960 Section 9.2 | ||
4990 | * The sender of the SHUTDOWN MAY also start an overall guard timer | ||
4991 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | ||
4992 | */ | ||
4993 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
4994 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
4995 | |||
4971 | if (asoc->autoclose) | 4996 | if (asoc->autoclose) |
4972 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 4997 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4973 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 4998 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
@@ -5279,6 +5304,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
5279 | if (!repl) | 5304 | if (!repl) |
5280 | return SCTP_DISPOSITION_NOMEM; | 5305 | return SCTP_DISPOSITION_NOMEM; |
5281 | 5306 | ||
5307 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
5308 | SCTP_CHUNK(repl)); | ||
5282 | /* Issue a sideeffect to do the needed accounting. */ | 5309 | /* Issue a sideeffect to do the needed accounting. */ |
5283 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, | 5310 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, |
5284 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 5311 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
@@ -5406,7 +5433,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
5406 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5433 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5407 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5434 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
5408 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5435 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
5409 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | 5436 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); |
5410 | return SCTP_DISPOSITION_ABORT; | 5437 | return SCTP_DISPOSITION_ABORT; |
5411 | } | 5438 | } |
5412 | 5439 | ||
@@ -5462,6 +5489,9 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | |||
5462 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5489 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5463 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5490 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
5464 | 5491 | ||
5492 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
5493 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
5494 | |||
5465 | return SCTP_DISPOSITION_DELETE_TCB; | 5495 | return SCTP_DISPOSITION_DELETE_TCB; |
5466 | nomem: | 5496 | nomem: |
5467 | return SCTP_DISPOSITION_NOMEM; | 5497 | return SCTP_DISPOSITION_NOMEM; |
@@ -5494,12 +5524,6 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( | |||
5494 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 5524 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
5495 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); | 5525 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); |
5496 | 5526 | ||
5497 | /* sctpimpguide-05 Section 2.12.2 | ||
5498 | * The sender of the SHUTDOWN MAY also start an overall guard timer | ||
5499 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | ||
5500 | */ | ||
5501 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
5502 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
5503 | disposition = SCTP_DISPOSITION_CONSUME; | 5527 | disposition = SCTP_DISPOSITION_CONSUME; |
5504 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 5528 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
5505 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, | 5529 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index d991237fb400..dd4ddc40c0ad 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -897,7 +897,7 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
897 | /* SCTP_STATE_ESTABLISHED */ \ | 897 | /* SCTP_STATE_ESTABLISHED */ \ |
898 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 898 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
899 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 899 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
900 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ | 900 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
901 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 901 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
902 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ | 902 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ |
903 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ | 903 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5ffb9dec1c3f..a1b904529d5e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2309,7 +2309,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2309 | /* If an address other than INADDR_ANY is specified, and | 2309 | /* If an address other than INADDR_ANY is specified, and |
2310 | * no transport is found, then the request is invalid. | 2310 | * no transport is found, then the request is invalid. |
2311 | */ | 2311 | */ |
2312 | if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { | 2312 | if (!sctp_is_any(sk, ( union sctp_addr *)¶ms.spp_address)) { |
2313 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, | 2313 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
2314 | params.spp_assoc_id); | 2314 | params.spp_assoc_id); |
2315 | if (!trans) | 2315 | if (!trans) |
@@ -4062,7 +4062,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
4062 | /* If an address other than INADDR_ANY is specified, and | 4062 | /* If an address other than INADDR_ANY is specified, and |
4063 | * no transport is found, then the request is invalid. | 4063 | * no transport is found, then the request is invalid. |
4064 | */ | 4064 | */ |
4065 | if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { | 4065 | if (!sctp_is_any(sk, ( union sctp_addr *)¶ms.spp_address)) { |
4066 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, | 4066 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
4067 | params.spp_assoc_id); | 4067 | params.spp_assoc_id); |
4068 | if (!trans) { | 4068 | if (!trans) { |
@@ -4414,7 +4414,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, | |||
4414 | if (sctp_list_single_entry(&bp->address_list)) { | 4414 | if (sctp_list_single_entry(&bp->address_list)) { |
4415 | addr = list_entry(bp->address_list.next, | 4415 | addr = list_entry(bp->address_list.next, |
4416 | struct sctp_sockaddr_entry, list); | 4416 | struct sctp_sockaddr_entry, list); |
4417 | if (sctp_is_any(&addr->a)) { | 4417 | if (sctp_is_any(sk, &addr->a)) { |
4418 | rcu_read_lock(); | 4418 | rcu_read_lock(); |
4419 | list_for_each_entry_rcu(addr, | 4419 | list_for_each_entry_rcu(addr, |
4420 | &sctp_local_addr_list, list) { | 4420 | &sctp_local_addr_list, list) { |
@@ -4602,7 +4602,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, | |||
4602 | if (sctp_list_single_entry(&bp->address_list)) { | 4602 | if (sctp_list_single_entry(&bp->address_list)) { |
4603 | addr = list_entry(bp->address_list.next, | 4603 | addr = list_entry(bp->address_list.next, |
4604 | struct sctp_sockaddr_entry, list); | 4604 | struct sctp_sockaddr_entry, list); |
4605 | if (sctp_is_any(&addr->a)) { | 4605 | if (sctp_is_any(sk, &addr->a)) { |
4606 | cnt = sctp_copy_laddrs_old(sk, bp->port, | 4606 | cnt = sctp_copy_laddrs_old(sk, bp->port, |
4607 | getaddrs.addr_num, | 4607 | getaddrs.addr_num, |
4608 | addrs, &bytes_copied); | 4608 | addrs, &bytes_copied); |
@@ -4695,7 +4695,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
4695 | if (sctp_list_single_entry(&bp->address_list)) { | 4695 | if (sctp_list_single_entry(&bp->address_list)) { |
4696 | addr = list_entry(bp->address_list.next, | 4696 | addr = list_entry(bp->address_list.next, |
4697 | struct sctp_sockaddr_entry, list); | 4697 | struct sctp_sockaddr_entry, list); |
4698 | if (sctp_is_any(&addr->a)) { | 4698 | if (sctp_is_any(sk, &addr->a)) { |
4699 | cnt = sctp_copy_laddrs(sk, bp->port, addrs, | 4699 | cnt = sctp_copy_laddrs(sk, bp->port, addrs, |
4700 | space_left, &bytes_copied); | 4700 | space_left, &bytes_copied); |
4701 | if (cnt < 0) { | 4701 | if (cnt < 0) { |
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index f3e58b275905..35c73e82553a 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c | |||
@@ -43,37 +43,44 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <linux/types.h> | 45 | #include <linux/types.h> |
46 | #include <linux/bitmap.h> | ||
46 | #include <net/sctp/sctp.h> | 47 | #include <net/sctp/sctp.h> |
47 | #include <net/sctp/sm.h> | 48 | #include <net/sctp/sm.h> |
48 | 49 | ||
49 | static void sctp_tsnmap_update(struct sctp_tsnmap *map); | 50 | static void sctp_tsnmap_update(struct sctp_tsnmap *map); |
50 | static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off, | 51 | static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off, |
51 | __u16 len, __u16 base, | 52 | __u16 len, __u16 *start, __u16 *end); |
52 | int *started, __u16 *start, | 53 | static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap); |
53 | int *ended, __u16 *end); | ||
54 | 54 | ||
55 | /* Initialize a block of memory as a tsnmap. */ | 55 | /* Initialize a block of memory as a tsnmap. */ |
56 | struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, | 56 | struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, |
57 | __u32 initial_tsn) | 57 | __u32 initial_tsn, gfp_t gfp) |
58 | { | 58 | { |
59 | map->tsn_map = map->raw_map; | 59 | if (!map->tsn_map) { |
60 | map->overflow_map = map->tsn_map + len; | 60 | map->tsn_map = kzalloc(len>>3, gfp); |
61 | map->len = len; | 61 | if (map->tsn_map == NULL) |
62 | 62 | return NULL; | |
63 | /* Clear out a TSN ack status. */ | 63 | |
64 | memset(map->tsn_map, 0x00, map->len + map->len); | 64 | map->len = len; |
65 | } else { | ||
66 | bitmap_zero(map->tsn_map, map->len); | ||
67 | } | ||
65 | 68 | ||
66 | /* Keep track of TSNs represented by tsn_map. */ | 69 | /* Keep track of TSNs represented by tsn_map. */ |
67 | map->base_tsn = initial_tsn; | 70 | map->base_tsn = initial_tsn; |
68 | map->overflow_tsn = initial_tsn + map->len; | ||
69 | map->cumulative_tsn_ack_point = initial_tsn - 1; | 71 | map->cumulative_tsn_ack_point = initial_tsn - 1; |
70 | map->max_tsn_seen = map->cumulative_tsn_ack_point; | 72 | map->max_tsn_seen = map->cumulative_tsn_ack_point; |
71 | map->malloced = 0; | ||
72 | map->num_dup_tsns = 0; | 73 | map->num_dup_tsns = 0; |
73 | 74 | ||
74 | return map; | 75 | return map; |
75 | } | 76 | } |
76 | 77 | ||
78 | void sctp_tsnmap_free(struct sctp_tsnmap *map) | ||
79 | { | ||
80 | map->len = 0; | ||
81 | kfree(map->tsn_map); | ||
82 | } | ||
83 | |||
77 | /* Test the tracking state of this TSN. | 84 | /* Test the tracking state of this TSN. |
78 | * Returns: | 85 | * Returns: |
79 | * 0 if the TSN has not yet been seen | 86 | * 0 if the TSN has not yet been seen |
@@ -82,66 +89,69 @@ struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, | |||
82 | */ | 89 | */ |
83 | int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn) | 90 | int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn) |
84 | { | 91 | { |
85 | __s32 gap; | 92 | u32 gap; |
86 | int dup; | 93 | |
94 | /* Check to see if this is an old TSN */ | ||
95 | if (TSN_lte(tsn, map->cumulative_tsn_ack_point)) | ||
96 | return 1; | ||
97 | |||
98 | /* Verify that we can hold this TSN and that it will not | ||
99 | * overlfow our map | ||
100 | */ | ||
101 | if (!TSN_lt(tsn, map->base_tsn + SCTP_TSN_MAP_SIZE)) | ||
102 | return -1; | ||
87 | 103 | ||
88 | /* Calculate the index into the mapping arrays. */ | 104 | /* Calculate the index into the mapping arrays. */ |
89 | gap = tsn - map->base_tsn; | 105 | gap = tsn - map->base_tsn; |
90 | 106 | ||
91 | /* Verify that we can hold this TSN. */ | 107 | /* Check to see if TSN has already been recorded. */ |
92 | if (gap >= (/* base */ map->len + /* overflow */ map->len)) { | 108 | if (gap < map->len && test_bit(gap, map->tsn_map)) |
93 | dup = -1; | 109 | return 1; |
94 | goto out; | ||
95 | } | ||
96 | |||
97 | /* Honk if we've already seen this TSN. | ||
98 | * We have three cases: | ||
99 | * 1. The TSN is ancient or belongs to a previous tsn_map. | ||
100 | * 2. The TSN is already marked in the tsn_map. | ||
101 | * 3. The TSN is already marked in the tsn_map_overflow. | ||
102 | */ | ||
103 | if (gap < 0 || | ||
104 | (gap < map->len && map->tsn_map[gap]) || | ||
105 | (gap >= map->len && map->overflow_map[gap - map->len])) | ||
106 | dup = 1; | ||
107 | else | 110 | else |
108 | dup = 0; | 111 | return 0; |
109 | |||
110 | out: | ||
111 | return dup; | ||
112 | } | 112 | } |
113 | 113 | ||
114 | 114 | ||
115 | /* Mark this TSN as seen. */ | 115 | /* Mark this TSN as seen. */ |
116 | void sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) | 116 | int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) |
117 | { | 117 | { |
118 | __s32 gap; | 118 | u16 gap; |
119 | 119 | ||
120 | /* Vacuously mark any TSN which precedes the map base or | ||
121 | * exceeds the end of the map. | ||
122 | */ | ||
123 | if (TSN_lt(tsn, map->base_tsn)) | 120 | if (TSN_lt(tsn, map->base_tsn)) |
124 | return; | 121 | return 0; |
125 | if (!TSN_lt(tsn, map->base_tsn + map->len + map->len)) | ||
126 | return; | ||
127 | |||
128 | /* Bump the max. */ | ||
129 | if (TSN_lt(map->max_tsn_seen, tsn)) | ||
130 | map->max_tsn_seen = tsn; | ||
131 | 122 | ||
132 | /* Assert: TSN is in range. */ | ||
133 | gap = tsn - map->base_tsn; | 123 | gap = tsn - map->base_tsn; |
134 | 124 | ||
135 | /* Mark the TSN as received. */ | 125 | if (gap >= map->len && !sctp_tsnmap_grow(map, gap)) |
136 | if (gap < map->len) | 126 | return -ENOMEM; |
137 | map->tsn_map[gap]++; | ||
138 | else | ||
139 | map->overflow_map[gap - map->len]++; | ||
140 | 127 | ||
141 | /* Go fixup any internal TSN mapping variables including | 128 | if (!sctp_tsnmap_has_gap(map) && gap == 0) { |
142 | * cumulative_tsn_ack_point. | 129 | /* In this case the map has no gaps and the tsn we are |
143 | */ | 130 | * recording is the next expected tsn. We don't touch |
144 | sctp_tsnmap_update(map); | 131 | * the map but simply bump the values. |
132 | */ | ||
133 | map->max_tsn_seen++; | ||
134 | map->cumulative_tsn_ack_point++; | ||
135 | map->base_tsn++; | ||
136 | } else { | ||
137 | /* Either we already have a gap, or about to record a gap, so | ||
138 | * have work to do. | ||
139 | * | ||
140 | * Bump the max. | ||
141 | */ | ||
142 | if (TSN_lt(map->max_tsn_seen, tsn)) | ||
143 | map->max_tsn_seen = tsn; | ||
144 | |||
145 | /* Mark the TSN as received. */ | ||
146 | set_bit(gap, map->tsn_map); | ||
147 | |||
148 | /* Go fixup any internal TSN mapping variables including | ||
149 | * cumulative_tsn_ack_point. | ||
150 | */ | ||
151 | sctp_tsnmap_update(map); | ||
152 | } | ||
153 | |||
154 | return 0; | ||
145 | } | 155 | } |
146 | 156 | ||
147 | 157 | ||
@@ -160,66 +170,34 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, | |||
160 | struct sctp_tsnmap_iter *iter, | 170 | struct sctp_tsnmap_iter *iter, |
161 | __u16 *start, __u16 *end) | 171 | __u16 *start, __u16 *end) |
162 | { | 172 | { |
163 | int started, ended; | 173 | int ended = 0; |
164 | __u16 start_, end_, offset; | 174 | __u16 start_ = 0, end_ = 0, offset; |
165 | |||
166 | /* We haven't found a gap yet. */ | ||
167 | started = ended = 0; | ||
168 | 175 | ||
169 | /* If there are no more gap acks possible, get out fast. */ | 176 | /* If there are no more gap acks possible, get out fast. */ |
170 | if (TSN_lte(map->max_tsn_seen, iter->start)) | 177 | if (TSN_lte(map->max_tsn_seen, iter->start)) |
171 | return 0; | 178 | return 0; |
172 | 179 | ||
173 | /* Search the first mapping array. */ | 180 | offset = iter->start - map->base_tsn; |
174 | if (iter->start - map->base_tsn < map->len) { | 181 | sctp_tsnmap_find_gap_ack(map->tsn_map, offset, map->len, |
175 | 182 | &start_, &end_); | |
176 | offset = iter->start - map->base_tsn; | ||
177 | sctp_tsnmap_find_gap_ack(map->tsn_map, offset, map->len, 0, | ||
178 | &started, &start_, &ended, &end_); | ||
179 | } | ||
180 | |||
181 | /* Do we need to check the overflow map? */ | ||
182 | if (!ended) { | ||
183 | /* Fix up where we'd like to start searching in the | ||
184 | * overflow map. | ||
185 | */ | ||
186 | if (iter->start - map->base_tsn < map->len) | ||
187 | offset = 0; | ||
188 | else | ||
189 | offset = iter->start - map->base_tsn - map->len; | ||
190 | |||
191 | /* Search the overflow map. */ | ||
192 | sctp_tsnmap_find_gap_ack(map->overflow_map, | ||
193 | offset, | ||
194 | map->len, | ||
195 | map->len, | ||
196 | &started, &start_, | ||
197 | &ended, &end_); | ||
198 | } | ||
199 | 183 | ||
200 | /* The Gap Ack Block happens to end at the end of the | 184 | /* The Gap Ack Block happens to end at the end of the map. */ |
201 | * overflow map. | 185 | if (start_ && !end_) |
202 | */ | 186 | end_ = map->len - 1; |
203 | if (started && !ended) { | ||
204 | ended++; | ||
205 | end_ = map->len + map->len - 1; | ||
206 | } | ||
207 | 187 | ||
208 | /* If we found a Gap Ack Block, return the start and end and | 188 | /* If we found a Gap Ack Block, return the start and end and |
209 | * bump the iterator forward. | 189 | * bump the iterator forward. |
210 | */ | 190 | */ |
211 | if (ended) { | 191 | if (end_) { |
212 | /* Fix up the start and end based on the | 192 | /* Fix up the start and end based on the |
213 | * Cumulative TSN Ack offset into the map. | 193 | * Cumulative TSN Ack which is always 1 behind base. |
214 | */ | 194 | */ |
215 | int gap = map->cumulative_tsn_ack_point - | 195 | *start = start_ + 1; |
216 | map->base_tsn; | 196 | *end = end_ + 1; |
217 | |||
218 | *start = start_ - gap; | ||
219 | *end = end_ - gap; | ||
220 | 197 | ||
221 | /* Move the iterator forward. */ | 198 | /* Move the iterator forward. */ |
222 | iter->start = map->cumulative_tsn_ack_point + *end + 1; | 199 | iter->start = map->cumulative_tsn_ack_point + *end + 1; |
200 | ended = 1; | ||
223 | } | 201 | } |
224 | 202 | ||
225 | return ended; | 203 | return ended; |
@@ -228,35 +206,33 @@ SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, | |||
228 | /* Mark this and any lower TSN as seen. */ | 206 | /* Mark this and any lower TSN as seen. */ |
229 | void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn) | 207 | void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn) |
230 | { | 208 | { |
231 | __s32 gap; | 209 | u32 gap; |
232 | 210 | ||
233 | /* Vacuously mark any TSN which precedes the map base or | ||
234 | * exceeds the end of the map. | ||
235 | */ | ||
236 | if (TSN_lt(tsn, map->base_tsn)) | 211 | if (TSN_lt(tsn, map->base_tsn)) |
237 | return; | 212 | return; |
238 | if (!TSN_lt(tsn, map->base_tsn + map->len + map->len)) | 213 | if (!TSN_lt(tsn, map->base_tsn + SCTP_TSN_MAP_SIZE)) |
239 | return; | 214 | return; |
240 | 215 | ||
241 | /* Bump the max. */ | 216 | /* Bump the max. */ |
242 | if (TSN_lt(map->max_tsn_seen, tsn)) | 217 | if (TSN_lt(map->max_tsn_seen, tsn)) |
243 | map->max_tsn_seen = tsn; | 218 | map->max_tsn_seen = tsn; |
244 | 219 | ||
245 | /* Assert: TSN is in range. */ | ||
246 | gap = tsn - map->base_tsn + 1; | 220 | gap = tsn - map->base_tsn + 1; |
247 | 221 | ||
248 | /* Mark the TSNs as received. */ | 222 | map->base_tsn += gap; |
249 | if (gap <= map->len) | 223 | map->cumulative_tsn_ack_point += gap; |
250 | memset(map->tsn_map, 0x01, gap); | 224 | if (gap >= map->len) { |
251 | else { | 225 | /* If our gap is larger then the map size, just |
252 | memset(map->tsn_map, 0x01, map->len); | 226 | * zero out the map. |
253 | memset(map->overflow_map, 0x01, (gap - map->len)); | 227 | */ |
228 | bitmap_zero(map->tsn_map, map->len); | ||
229 | } else { | ||
230 | /* If the gap is smaller then the map size, | ||
231 | * shift the map by 'gap' bits and update further. | ||
232 | */ | ||
233 | bitmap_shift_right(map->tsn_map, map->tsn_map, gap, map->len); | ||
234 | sctp_tsnmap_update(map); | ||
254 | } | 235 | } |
255 | |||
256 | /* Go fixup any internal TSN mapping variables including | ||
257 | * cumulative_tsn_ack_point. | ||
258 | */ | ||
259 | sctp_tsnmap_update(map); | ||
260 | } | 236 | } |
261 | 237 | ||
262 | /******************************************************************** | 238 | /******************************************************************** |
@@ -268,27 +244,19 @@ void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn) | |||
268 | */ | 244 | */ |
269 | static void sctp_tsnmap_update(struct sctp_tsnmap *map) | 245 | static void sctp_tsnmap_update(struct sctp_tsnmap *map) |
270 | { | 246 | { |
271 | __u32 ctsn; | 247 | u16 len; |
272 | 248 | unsigned long zero_bit; | |
273 | ctsn = map->cumulative_tsn_ack_point; | 249 | |
274 | do { | 250 | |
275 | ctsn++; | 251 | len = map->max_tsn_seen - map->cumulative_tsn_ack_point; |
276 | if (ctsn == map->overflow_tsn) { | 252 | zero_bit = find_first_zero_bit(map->tsn_map, len); |
277 | /* Now tsn_map must have been all '1's, | 253 | if (!zero_bit) |
278 | * so we swap the map and check the overflow table | 254 | return; /* The first 0-bit is bit 0. nothing to do */ |
279 | */ | 255 | |
280 | __u8 *tmp = map->tsn_map; | 256 | map->base_tsn += zero_bit; |
281 | memset(tmp, 0, map->len); | 257 | map->cumulative_tsn_ack_point += zero_bit; |
282 | map->tsn_map = map->overflow_map; | ||
283 | map->overflow_map = tmp; | ||
284 | |||
285 | /* Update the tsn_map boundaries. */ | ||
286 | map->base_tsn += map->len; | ||
287 | map->overflow_tsn += map->len; | ||
288 | } | ||
289 | } while (map->tsn_map[ctsn - map->base_tsn]); | ||
290 | 258 | ||
291 | map->cumulative_tsn_ack_point = ctsn - 1; /* Back up one. */ | 259 | bitmap_shift_right(map->tsn_map, map->tsn_map, zero_bit, map->len); |
292 | } | 260 | } |
293 | 261 | ||
294 | /* How many data chunks are we missing from our peer? | 262 | /* How many data chunks are we missing from our peer? |
@@ -299,31 +267,19 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map) | |||
299 | __u32 max_tsn = map->max_tsn_seen; | 267 | __u32 max_tsn = map->max_tsn_seen; |
300 | __u32 base_tsn = map->base_tsn; | 268 | __u32 base_tsn = map->base_tsn; |
301 | __u16 pending_data; | 269 | __u16 pending_data; |
302 | __s32 gap, start, end, i; | 270 | u32 gap, i; |
303 | 271 | ||
304 | pending_data = max_tsn - cum_tsn; | 272 | pending_data = max_tsn - cum_tsn; |
305 | gap = max_tsn - base_tsn; | 273 | gap = max_tsn - base_tsn; |
306 | 274 | ||
307 | if (gap <= 0 || gap >= (map->len + map->len)) | 275 | if (gap == 0 || gap >= map->len) |
308 | goto out; | 276 | goto out; |
309 | 277 | ||
310 | start = ((cum_tsn >= base_tsn) ? (cum_tsn - base_tsn + 1) : 0); | 278 | for (i = 0; i < gap+1; i++) { |
311 | end = ((gap > map->len ) ? map->len : gap + 1); | 279 | if (test_bit(i, map->tsn_map)) |
312 | |||
313 | for (i = start; i < end; i++) { | ||
314 | if (map->tsn_map[i]) | ||
315 | pending_data--; | 280 | pending_data--; |
316 | } | 281 | } |
317 | 282 | ||
318 | if (gap >= map->len) { | ||
319 | start = 0; | ||
320 | end = gap - map->len + 1; | ||
321 | for (i = start; i < end; i++) { | ||
322 | if (map->overflow_map[i]) | ||
323 | pending_data--; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | out: | 283 | out: |
328 | return pending_data; | 284 | return pending_data; |
329 | } | 285 | } |
@@ -334,10 +290,8 @@ out: | |||
334 | * The flags "started" and "ended" tell is if we found the beginning | 290 | * The flags "started" and "ended" tell is if we found the beginning |
335 | * or (respectively) the end of a Gap Ack Block. | 291 | * or (respectively) the end of a Gap Ack Block. |
336 | */ | 292 | */ |
337 | static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off, | 293 | static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off, |
338 | __u16 len, __u16 base, | 294 | __u16 len, __u16 *start, __u16 *end) |
339 | int *started, __u16 *start, | ||
340 | int *ended, __u16 *end) | ||
341 | { | 295 | { |
342 | int i = off; | 296 | int i = off; |
343 | 297 | ||
@@ -348,56 +302,44 @@ static void sctp_tsnmap_find_gap_ack(__u8 *map, __u16 off, | |||
348 | /* Also, stop looking past the maximum TSN seen. */ | 302 | /* Also, stop looking past the maximum TSN seen. */ |
349 | 303 | ||
350 | /* Look for the start. */ | 304 | /* Look for the start. */ |
351 | if (!(*started)) { | 305 | i = find_next_bit(map, len, off); |
352 | for (; i < len; i++) { | 306 | if (i < len) |
353 | if (map[i]) { | 307 | *start = i; |
354 | (*started)++; | ||
355 | *start = base + i; | ||
356 | break; | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | 308 | ||
361 | /* Look for the end. */ | 309 | /* Look for the end. */ |
362 | if (*started) { | 310 | if (*start) { |
363 | /* We have found the start, let's find the | 311 | /* We have found the start, let's find the |
364 | * end. If we find the end, break out. | 312 | * end. If we find the end, break out. |
365 | */ | 313 | */ |
366 | for (; i < len; i++) { | 314 | i = find_next_zero_bit(map, len, i); |
367 | if (!map[i]) { | 315 | if (i < len) |
368 | (*ended)++; | 316 | *end = i - 1; |
369 | *end = base + i - 1; | ||
370 | break; | ||
371 | } | ||
372 | } | ||
373 | } | 317 | } |
374 | } | 318 | } |
375 | 319 | ||
376 | /* Renege that we have seen a TSN. */ | 320 | /* Renege that we have seen a TSN. */ |
377 | void sctp_tsnmap_renege(struct sctp_tsnmap *map, __u32 tsn) | 321 | void sctp_tsnmap_renege(struct sctp_tsnmap *map, __u32 tsn) |
378 | { | 322 | { |
379 | __s32 gap; | 323 | u32 gap; |
380 | 324 | ||
381 | if (TSN_lt(tsn, map->base_tsn)) | 325 | if (TSN_lt(tsn, map->base_tsn)) |
382 | return; | 326 | return; |
383 | if (!TSN_lt(tsn, map->base_tsn + map->len + map->len)) | 327 | /* Assert: TSN is in range. */ |
328 | if (!TSN_lt(tsn, map->base_tsn + map->len)) | ||
384 | return; | 329 | return; |
385 | 330 | ||
386 | /* Assert: TSN is in range. */ | ||
387 | gap = tsn - map->base_tsn; | 331 | gap = tsn - map->base_tsn; |
388 | 332 | ||
389 | /* Pretend we never saw the TSN. */ | 333 | /* Pretend we never saw the TSN. */ |
390 | if (gap < map->len) | 334 | clear_bit(gap, map->tsn_map); |
391 | map->tsn_map[gap] = 0; | ||
392 | else | ||
393 | map->overflow_map[gap - map->len] = 0; | ||
394 | } | 335 | } |
395 | 336 | ||
396 | /* How many gap ack blocks do we have recorded? */ | 337 | /* How many gap ack blocks do we have recorded? */ |
397 | __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map) | 338 | __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map, |
339 | struct sctp_gap_ack_block *gabs) | ||
398 | { | 340 | { |
399 | struct sctp_tsnmap_iter iter; | 341 | struct sctp_tsnmap_iter iter; |
400 | int gabs = 0; | 342 | int ngaps = 0; |
401 | 343 | ||
402 | /* Refresh the gap ack information. */ | 344 | /* Refresh the gap ack information. */ |
403 | if (sctp_tsnmap_has_gap(map)) { | 345 | if (sctp_tsnmap_has_gap(map)) { |
@@ -407,12 +349,36 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map) | |||
407 | &start, | 349 | &start, |
408 | &end)) { | 350 | &end)) { |
409 | 351 | ||
410 | map->gabs[gabs].start = htons(start); | 352 | gabs[ngaps].start = htons(start); |
411 | map->gabs[gabs].end = htons(end); | 353 | gabs[ngaps].end = htons(end); |
412 | gabs++; | 354 | ngaps++; |
413 | if (gabs >= SCTP_MAX_GABS) | 355 | if (ngaps >= SCTP_MAX_GABS) |
414 | break; | 356 | break; |
415 | } | 357 | } |
416 | } | 358 | } |
417 | return gabs; | 359 | return ngaps; |
360 | } | ||
361 | |||
362 | static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap) | ||
363 | { | ||
364 | unsigned long *new; | ||
365 | unsigned long inc; | ||
366 | u16 len; | ||
367 | |||
368 | if (gap >= SCTP_TSN_MAP_SIZE) | ||
369 | return 0; | ||
370 | |||
371 | inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; | ||
372 | len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE); | ||
373 | |||
374 | new = kzalloc(len>>3, GFP_ATOMIC); | ||
375 | if (!new) | ||
376 | return 0; | ||
377 | |||
378 | bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn); | ||
379 | kfree(map->tsn_map); | ||
380 | map->tsn_map = new; | ||
381 | map->len = len; | ||
382 | |||
383 | return 1; | ||
418 | } | 384 | } |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index a1f654aea268..5f186ca550d7 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -713,7 +713,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, | |||
713 | /* Now that all memory allocations for this chunk succeeded, we | 713 | /* Now that all memory allocations for this chunk succeeded, we |
714 | * can mark it as received so the tsn_map is updated correctly. | 714 | * can mark it as received so the tsn_map is updated correctly. |
715 | */ | 715 | */ |
716 | sctp_tsnmap_mark(&asoc->peer.tsn_map, ntohl(chunk->subh.data_hdr->tsn)); | 716 | if (sctp_tsnmap_mark(&asoc->peer.tsn_map, |
717 | ntohl(chunk->subh.data_hdr->tsn))) | ||
718 | goto fail_mark; | ||
717 | 719 | ||
718 | /* First calculate the padding, so we don't inadvertently | 720 | /* First calculate the padding, so we don't inadvertently |
719 | * pass up the wrong length to the user. | 721 | * pass up the wrong length to the user. |
@@ -755,8 +757,12 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, | |||
755 | event->msg_flags |= chunk->chunk_hdr->flags; | 757 | event->msg_flags |= chunk->chunk_hdr->flags; |
756 | event->iif = sctp_chunk_iif(chunk); | 758 | event->iif = sctp_chunk_iif(chunk); |
757 | 759 | ||
758 | fail: | ||
759 | return event; | 760 | return event; |
761 | |||
762 | fail_mark: | ||
763 | kfree_skb(skb); | ||
764 | fail: | ||
765 | return NULL; | ||
760 | } | 766 | } |
761 | 767 | ||
762 | /* Create a partial delivery related event. | 768 | /* Create a partial delivery related event. |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 5061a26c5028..7b23803343cc 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -317,7 +317,7 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, | |||
317 | } | 317 | } |
318 | 318 | ||
319 | /* Insert before pos. */ | 319 | /* Insert before pos. */ |
320 | __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->reasm); | 320 | __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event)); |
321 | 321 | ||
322 | } | 322 | } |
323 | 323 | ||
@@ -825,8 +825,7 @@ static void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq, | |||
825 | 825 | ||
826 | 826 | ||
827 | /* Insert before pos. */ | 827 | /* Insert before pos. */ |
828 | __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->lobby); | 828 | __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event)); |
829 | |||
830 | } | 829 | } |
831 | 830 | ||
832 | static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, | 831 | static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, |