diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 27 | ||||
-rw-r--r-- | net/sctp/chunk.c | 15 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 21 | ||||
-rw-r--r-- | net/sctp/output.c | 50 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 26 | ||||
-rw-r--r-- | net/sctp/protocol.c | 19 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 13 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 7 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 28 | ||||
-rw-r--r-- | net/sctp/socket.c | 371 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 62 | ||||
-rw-r--r-- | net/sctp/transport.c | 45 |
12 files changed, 205 insertions, 479 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 7eed77a39d0d..df5abbff63e2 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -63,6 +63,12 @@ | |||
63 | static void sctp_assoc_bh_rcv(struct work_struct *work); | 63 | static void sctp_assoc_bh_rcv(struct work_struct *work); |
64 | static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc); | 64 | static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc); |
65 | 65 | ||
66 | /* Keep track of the new idr low so that we don't re-use association id | ||
67 | * numbers too fast. It is protected by they idr spin lock is in the | ||
68 | * range of 1 - INT_MAX. | ||
69 | */ | ||
70 | static u32 idr_low = 1; | ||
71 | |||
66 | 72 | ||
67 | /* 1st Level Abstractions. */ | 73 | /* 1st Level Abstractions. */ |
68 | 74 | ||
@@ -167,7 +173,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
167 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; | 173 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; |
168 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; | 174 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; |
169 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = | 175 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = |
170 | sp->autoclose * HZ; | 176 | (unsigned long)sp->autoclose * HZ; |
171 | 177 | ||
172 | /* Initilizes the timers */ | 178 | /* Initilizes the timers */ |
173 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) | 179 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) |
@@ -512,7 +518,13 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
512 | * to this destination address earlier. The sender MUST set | 518 | * to this destination address earlier. The sender MUST set |
513 | * CYCLING_CHANGEOVER to indicate that this switch is a | 519 | * CYCLING_CHANGEOVER to indicate that this switch is a |
514 | * double switch to the same destination address. | 520 | * double switch to the same destination address. |
521 | * | ||
522 | * Really, only bother is we have data queued or outstanding on | ||
523 | * the association. | ||
515 | */ | 524 | */ |
525 | if (!asoc->outqueue.outstanding_bytes && !asoc->outqueue.out_qlen) | ||
526 | return; | ||
527 | |||
516 | if (transport->cacc.changeover_active) | 528 | if (transport->cacc.changeover_active) |
517 | transport->cacc.cycling_changeover = changeover; | 529 | transport->cacc.cycling_changeover = changeover; |
518 | 530 | ||
@@ -732,6 +744,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
732 | 744 | ||
733 | peer->partial_bytes_acked = 0; | 745 | peer->partial_bytes_acked = 0; |
734 | peer->flight_size = 0; | 746 | peer->flight_size = 0; |
747 | peer->burst_limited = 0; | ||
735 | 748 | ||
736 | /* Set the transport's RTO.initial value */ | 749 | /* Set the transport's RTO.initial value */ |
737 | peer->rto = asoc->rto_initial; | 750 | peer->rto = asoc->rto_initial; |
@@ -1377,8 +1390,9 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc) | |||
1377 | case SCTP_STATE_SHUTDOWN_RECEIVED: | 1390 | case SCTP_STATE_SHUTDOWN_RECEIVED: |
1378 | case SCTP_STATE_SHUTDOWN_SENT: | 1391 | case SCTP_STATE_SHUTDOWN_SENT: |
1379 | if ((asoc->rwnd > asoc->a_rwnd) && | 1392 | if ((asoc->rwnd > asoc->a_rwnd) && |
1380 | ((asoc->rwnd - asoc->a_rwnd) >= | 1393 | ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32, |
1381 | min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pathmtu))) | 1394 | (asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift), |
1395 | asoc->pathmtu))) | ||
1382 | return 1; | 1396 | return 1; |
1383 | break; | 1397 | break; |
1384 | default: | 1398 | default: |
@@ -1545,7 +1559,12 @@ retry: | |||
1545 | 1559 | ||
1546 | spin_lock_bh(&sctp_assocs_id_lock); | 1560 | spin_lock_bh(&sctp_assocs_id_lock); |
1547 | error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, | 1561 | error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, |
1548 | 1, &assoc_id); | 1562 | idr_low, &assoc_id); |
1563 | if (!error) { | ||
1564 | idr_low = assoc_id + 1; | ||
1565 | if (idr_low == INT_MAX) | ||
1566 | idr_low = 1; | ||
1567 | } | ||
1549 | spin_unlock_bh(&sctp_assocs_id_lock); | 1568 | spin_unlock_bh(&sctp_assocs_id_lock); |
1550 | if (error == -EAGAIN) | 1569 | if (error == -EAGAIN) |
1551 | goto retry; | 1570 | goto retry; |
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index acf7c4d128f7..8e4320040f05 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -263,9 +263,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
263 | if (0 == i) | 263 | if (0 == i) |
264 | frag |= SCTP_DATA_FIRST_FRAG; | 264 | frag |= SCTP_DATA_FIRST_FRAG; |
265 | 265 | ||
266 | if ((i == (whole - 1)) && !over) | 266 | if ((i == (whole - 1)) && !over) { |
267 | frag |= SCTP_DATA_LAST_FRAG; | 267 | frag |= SCTP_DATA_LAST_FRAG; |
268 | 268 | ||
269 | /* The application requests to set the I-bit of the | ||
270 | * last DATA chunk of a user message when providing | ||
271 | * the user message to the SCTP implementation. | ||
272 | */ | ||
273 | if ((sinfo->sinfo_flags & SCTP_EOF) || | ||
274 | (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY)) | ||
275 | frag |= SCTP_DATA_SACK_IMM; | ||
276 | } | ||
277 | |||
269 | chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); | 278 | chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); |
270 | 279 | ||
271 | if (!chunk) | 280 | if (!chunk) |
@@ -297,6 +306,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
297 | else | 306 | else |
298 | frag = SCTP_DATA_LAST_FRAG; | 307 | frag = SCTP_DATA_LAST_FRAG; |
299 | 308 | ||
309 | if ((sinfo->sinfo_flags & SCTP_EOF) || | ||
310 | (sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY)) | ||
311 | frag |= SCTP_DATA_SACK_IMM; | ||
312 | |||
300 | chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); | 313 | chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); |
301 | 314 | ||
302 | if (!chunk) | 315 | if (!chunk) |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index bb280e60e00a..cc50fbe99291 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -837,15 +837,16 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
837 | if (type & IPV6_ADDR_LINKLOCAL) { | 837 | if (type & IPV6_ADDR_LINKLOCAL) { |
838 | if (!addr->v6.sin6_scope_id) | 838 | if (!addr->v6.sin6_scope_id) |
839 | return 0; | 839 | return 0; |
840 | dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id); | 840 | rcu_read_lock(); |
841 | if (!dev) | 841 | dev = dev_get_by_index_rcu(&init_net, |
842 | return 0; | 842 | addr->v6.sin6_scope_id); |
843 | if (!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, | 843 | if (!dev || |
844 | !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, | ||
844 | dev, 0)) { | 845 | dev, 0)) { |
845 | dev_put(dev); | 846 | rcu_read_unlock(); |
846 | return 0; | 847 | return 0; |
847 | } | 848 | } |
848 | dev_put(dev); | 849 | rcu_read_unlock(); |
849 | } else if (type == IPV6_ADDR_MAPPED) { | 850 | } else if (type == IPV6_ADDR_MAPPED) { |
850 | if (!opt->v4mapped) | 851 | if (!opt->v4mapped) |
851 | return 0; | 852 | return 0; |
@@ -873,10 +874,12 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
873 | if (type & IPV6_ADDR_LINKLOCAL) { | 874 | if (type & IPV6_ADDR_LINKLOCAL) { |
874 | if (!addr->v6.sin6_scope_id) | 875 | if (!addr->v6.sin6_scope_id) |
875 | return 0; | 876 | return 0; |
876 | dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id); | 877 | rcu_read_lock(); |
878 | dev = dev_get_by_index_rcu(&init_net, | ||
879 | addr->v6.sin6_scope_id); | ||
880 | rcu_read_unlock(); | ||
877 | if (!dev) | 881 | if (!dev) |
878 | return 0; | 882 | return 0; |
879 | dev_put(dev); | ||
880 | } | 883 | } |
881 | af = opt->pf->af; | 884 | af = opt->pf->af; |
882 | } | 885 | } |
@@ -930,7 +933,6 @@ static struct inet_protosw sctpv6_seqpacket_protosw = { | |||
930 | .protocol = IPPROTO_SCTP, | 933 | .protocol = IPPROTO_SCTP, |
931 | .prot = &sctpv6_prot, | 934 | .prot = &sctpv6_prot, |
932 | .ops = &inet6_seqpacket_ops, | 935 | .ops = &inet6_seqpacket_ops, |
933 | .capability = -1, | ||
934 | .no_check = 0, | 936 | .no_check = 0, |
935 | .flags = SCTP_PROTOSW_FLAG | 937 | .flags = SCTP_PROTOSW_FLAG |
936 | }; | 938 | }; |
@@ -939,7 +941,6 @@ static struct inet_protosw sctpv6_stream_protosw = { | |||
939 | .protocol = IPPROTO_SCTP, | 941 | .protocol = IPPROTO_SCTP, |
940 | .prot = &sctpv6_prot, | 942 | .prot = &sctpv6_prot, |
941 | .ops = &inet6_seqpacket_ops, | 943 | .ops = &inet6_seqpacket_ops, |
942 | .capability = -1, | ||
943 | .no_check = 0, | 944 | .no_check = 0, |
944 | .flags = SCTP_PROTOSW_FLAG, | 945 | .flags = SCTP_PROTOSW_FLAG, |
945 | }; | 946 | }; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 5cbda8f1ddfd..7c5589363433 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -429,23 +429,22 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
429 | list_del_init(&chunk->list); | 429 | list_del_init(&chunk->list); |
430 | if (sctp_chunk_is_data(chunk)) { | 430 | if (sctp_chunk_is_data(chunk)) { |
431 | 431 | ||
432 | if (!chunk->has_tsn) { | 432 | if (!chunk->resent) { |
433 | sctp_chunk_assign_ssn(chunk); | 433 | |
434 | sctp_chunk_assign_tsn(chunk); | 434 | /* 6.3.1 C4) When data is in flight and when allowed |
435 | 435 | * by rule C5, a new RTT measurement MUST be made each | |
436 | /* 6.3.1 C4) When data is in flight and when allowed | 436 | * round trip. Furthermore, new RTT measurements |
437 | * by rule C5, a new RTT measurement MUST be made each | 437 | * SHOULD be made no more than once per round-trip |
438 | * round trip. Furthermore, new RTT measurements | 438 | * for a given destination transport address. |
439 | * SHOULD be made no more than once per round-trip | 439 | */ |
440 | * for a given destination transport address. | ||
441 | */ | ||
442 | 440 | ||
443 | if (!tp->rto_pending) { | 441 | if (!tp->rto_pending) { |
444 | chunk->rtt_in_progress = 1; | 442 | chunk->rtt_in_progress = 1; |
445 | tp->rto_pending = 1; | 443 | tp->rto_pending = 1; |
446 | } | 444 | } |
447 | } else | 445 | } |
448 | chunk->resent = 1; | 446 | |
447 | chunk->resent = 1; | ||
449 | 448 | ||
450 | has_data = 1; | 449 | has_data = 1; |
451 | } | 450 | } |
@@ -557,8 +556,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
557 | struct timer_list *timer; | 556 | struct timer_list *timer; |
558 | unsigned long timeout; | 557 | unsigned long timeout; |
559 | 558 | ||
560 | tp->last_time_used = jiffies; | ||
561 | |||
562 | /* Restart the AUTOCLOSE timer when sending data. */ | 559 | /* Restart the AUTOCLOSE timer when sending data. */ |
563 | if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { | 560 | if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { |
564 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 561 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
@@ -617,7 +614,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | |||
617 | sctp_xmit_t retval = SCTP_XMIT_OK; | 614 | sctp_xmit_t retval = SCTP_XMIT_OK; |
618 | size_t datasize, rwnd, inflight, flight_size; | 615 | size_t datasize, rwnd, inflight, flight_size; |
619 | struct sctp_transport *transport = packet->transport; | 616 | struct sctp_transport *transport = packet->transport; |
620 | __u32 max_burst_bytes; | ||
621 | struct sctp_association *asoc = transport->asoc; | 617 | struct sctp_association *asoc = transport->asoc; |
622 | struct sctp_outq *q = &asoc->outqueue; | 618 | struct sctp_outq *q = &asoc->outqueue; |
623 | 619 | ||
@@ -650,28 +646,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | |||
650 | } | 646 | } |
651 | } | 647 | } |
652 | 648 | ||
653 | /* sctpimpguide-05 2.14.2 | ||
654 | * D) When the time comes for the sender to | ||
655 | * transmit new DATA chunks, the protocol parameter Max.Burst MUST | ||
656 | * first be applied to limit how many new DATA chunks may be sent. | ||
657 | * The limit is applied by adjusting cwnd as follows: | ||
658 | * if ((flightsize + Max.Burst * MTU) < cwnd) | ||
659 | * cwnd = flightsize + Max.Burst * MTU | ||
660 | */ | ||
661 | max_burst_bytes = asoc->max_burst * asoc->pathmtu; | ||
662 | if ((flight_size + max_burst_bytes) < transport->cwnd) { | ||
663 | transport->cwnd = flight_size + max_burst_bytes; | ||
664 | SCTP_DEBUG_PRINTK("%s: cwnd limited by max_burst: " | ||
665 | "transport: %p, cwnd: %d, " | ||
666 | "ssthresh: %d, flight_size: %d, " | ||
667 | "pba: %d\n", | ||
668 | __func__, transport, | ||
669 | transport->cwnd, | ||
670 | transport->ssthresh, | ||
671 | transport->flight_size, | ||
672 | transport->partial_bytes_acked); | ||
673 | } | ||
674 | |||
675 | /* RFC 2960 6.1 Transmission of DATA Chunks | 649 | /* RFC 2960 6.1 Transmission of DATA Chunks |
676 | * | 650 | * |
677 | * B) At any given time, the sender MUST NOT transmit new data | 651 | * B) At any given time, the sender MUST NOT transmit new data |
@@ -747,6 +721,8 @@ static void sctp_packet_append_data(struct sctp_packet *packet, | |||
747 | /* Has been accepted for transmission. */ | 721 | /* Has been accepted for transmission. */ |
748 | if (!asoc->peer.prsctp_capable) | 722 | if (!asoc->peer.prsctp_capable) |
749 | chunk->msg->can_abandon = 0; | 723 | chunk->msg->can_abandon = 0; |
724 | sctp_chunk_assign_tsn(chunk); | ||
725 | sctp_chunk_assign_ssn(chunk); | ||
750 | } | 726 | } |
751 | 727 | ||
752 | static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, | 728 | static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet, |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 23e5e97aa617..229690f02a1d 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -191,8 +191,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary, | |||
191 | __u32 tsn) | 191 | __u32 tsn) |
192 | { | 192 | { |
193 | if (primary->cacc.changeover_active && | 193 | if (primary->cacc.changeover_active && |
194 | (sctp_cacc_skip_3_1(primary, transport, count_of_newacks) | 194 | (sctp_cacc_skip_3_1(primary, transport, count_of_newacks) || |
195 | || sctp_cacc_skip_3_2(primary, tsn))) | 195 | sctp_cacc_skip_3_2(primary, tsn))) |
196 | return 1; | 196 | return 1; |
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
@@ -921,6 +921,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
921 | goto sctp_flush_out; | 921 | goto sctp_flush_out; |
922 | } | 922 | } |
923 | 923 | ||
924 | /* Apply Max.Burst limitation to the current transport in | ||
925 | * case it will be used for new data. We are going to | ||
926 | * rest it before we return, but we want to apply the limit | ||
927 | * to the currently queued data. | ||
928 | */ | ||
929 | if (transport) | ||
930 | sctp_transport_burst_limited(transport); | ||
931 | |||
924 | /* Finally, transmit new packets. */ | 932 | /* Finally, transmit new packets. */ |
925 | while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { | 933 | while ((chunk = sctp_outq_dequeue_data(q)) != NULL) { |
926 | /* RFC 2960 6.5 Every DATA chunk MUST carry a valid | 934 | /* RFC 2960 6.5 Every DATA chunk MUST carry a valid |
@@ -966,6 +974,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
966 | packet = &transport->packet; | 974 | packet = &transport->packet; |
967 | sctp_packet_config(packet, vtag, | 975 | sctp_packet_config(packet, vtag, |
968 | asoc->peer.ecn_capable); | 976 | asoc->peer.ecn_capable); |
977 | /* We've switched transports, so apply the | ||
978 | * Burst limit to the new transport. | ||
979 | */ | ||
980 | sctp_transport_burst_limited(transport); | ||
969 | } | 981 | } |
970 | 982 | ||
971 | SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", | 983 | SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", |
@@ -1001,6 +1013,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1001 | break; | 1013 | break; |
1002 | 1014 | ||
1003 | case SCTP_XMIT_OK: | 1015 | case SCTP_XMIT_OK: |
1016 | /* The sender is in the SHUTDOWN-PENDING state, | ||
1017 | * The sender MAY set the I-bit in the DATA | ||
1018 | * chunk header. | ||
1019 | */ | ||
1020 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) | ||
1021 | chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM; | ||
1022 | |||
1004 | break; | 1023 | break; |
1005 | 1024 | ||
1006 | default: | 1025 | default: |
@@ -1053,6 +1072,9 @@ sctp_flush_out: | |||
1053 | packet = &t->packet; | 1072 | packet = &t->packet; |
1054 | if (!sctp_packet_empty(packet)) | 1073 | if (!sctp_packet_empty(packet)) |
1055 | error = sctp_packet_transmit(packet); | 1074 | error = sctp_packet_transmit(packet); |
1075 | |||
1076 | /* Clear the burst limited state, if any */ | ||
1077 | sctp_transport_burst_reset(t); | ||
1056 | } | 1078 | } |
1057 | 1079 | ||
1058 | return error; | 1080 | return error; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 612dc878e05c..a3c8988758b1 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -205,14 +205,14 @@ static void sctp_get_local_addr_list(void) | |||
205 | struct list_head *pos; | 205 | struct list_head *pos; |
206 | struct sctp_af *af; | 206 | struct sctp_af *af; |
207 | 207 | ||
208 | read_lock(&dev_base_lock); | 208 | rcu_read_lock(); |
209 | for_each_netdev(&init_net, dev) { | 209 | for_each_netdev_rcu(&init_net, dev) { |
210 | __list_for_each(pos, &sctp_address_families) { | 210 | __list_for_each(pos, &sctp_address_families) { |
211 | af = list_entry(pos, struct sctp_af, list); | 211 | af = list_entry(pos, struct sctp_af, list); |
212 | af->copy_addrlist(&sctp_local_addr_list, dev); | 212 | af->copy_addrlist(&sctp_local_addr_list, dev); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | read_unlock(&dev_base_lock); | 215 | rcu_read_unlock(); |
216 | } | 216 | } |
217 | 217 | ||
218 | /* Free the existing local addresses. */ | 218 | /* Free the existing local addresses. */ |
@@ -296,19 +296,19 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk) | |||
296 | { | 296 | { |
297 | addr->v4.sin_family = AF_INET; | 297 | addr->v4.sin_family = AF_INET; |
298 | addr->v4.sin_port = 0; | 298 | addr->v4.sin_port = 0; |
299 | addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr; | 299 | addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr; |
300 | } | 300 | } |
301 | 301 | ||
302 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ | 302 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ |
303 | static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk) | 303 | static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk) |
304 | { | 304 | { |
305 | inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr; | 305 | inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr; |
306 | } | 306 | } |
307 | 307 | ||
308 | /* Initialize sk->sk_daddr from sctp_addr. */ | 308 | /* Initialize sk->sk_daddr from sctp_addr. */ |
309 | static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) | 309 | static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) |
310 | { | 310 | { |
311 | inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr; | 311 | inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr; |
312 | } | 312 | } |
313 | 313 | ||
314 | /* Initialize a sctp_addr from an address parameter. */ | 314 | /* Initialize a sctp_addr from an address parameter. */ |
@@ -598,7 +598,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk, | |||
598 | 598 | ||
599 | newinet = inet_sk(newsk); | 599 | newinet = inet_sk(newsk); |
600 | 600 | ||
601 | newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; | 601 | newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; |
602 | 602 | ||
603 | sk_refcnt_debug_inc(newsk); | 603 | sk_refcnt_debug_inc(newsk); |
604 | 604 | ||
@@ -909,7 +909,6 @@ static struct inet_protosw sctp_seqpacket_protosw = { | |||
909 | .protocol = IPPROTO_SCTP, | 909 | .protocol = IPPROTO_SCTP, |
910 | .prot = &sctp_prot, | 910 | .prot = &sctp_prot, |
911 | .ops = &inet_seqpacket_ops, | 911 | .ops = &inet_seqpacket_ops, |
912 | .capability = -1, | ||
913 | .no_check = 0, | 912 | .no_check = 0, |
914 | .flags = SCTP_PROTOSW_FLAG | 913 | .flags = SCTP_PROTOSW_FLAG |
915 | }; | 914 | }; |
@@ -918,7 +917,6 @@ static struct inet_protosw sctp_stream_protosw = { | |||
918 | .protocol = IPPROTO_SCTP, | 917 | .protocol = IPPROTO_SCTP, |
919 | .prot = &sctp_prot, | 918 | .prot = &sctp_prot, |
920 | .ops = &inet_seqpacket_ops, | 919 | .ops = &inet_seqpacket_ops, |
921 | .capability = -1, | ||
922 | .no_check = 0, | 920 | .no_check = 0, |
923 | .flags = SCTP_PROTOSW_FLAG | 921 | .flags = SCTP_PROTOSW_FLAG |
924 | }; | 922 | }; |
@@ -1260,6 +1258,9 @@ SCTP_STATIC __init int sctp_init(void) | |||
1260 | /* Set SCOPE policy to enabled */ | 1258 | /* Set SCOPE policy to enabled */ |
1261 | sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE; | 1259 | sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE; |
1262 | 1260 | ||
1261 | /* Set the default rwnd update threshold */ | ||
1262 | sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; | ||
1263 | |||
1263 | sctp_sysctl_register(); | 1264 | sctp_sysctl_register(); |
1264 | 1265 | ||
1265 | INIT_LIST_HEAD(&sctp_address_families); | 1266 | INIT_LIST_HEAD(&sctp_address_families); |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 9d881a61ac02..9e732916b671 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -987,7 +987,10 @@ static void *sctp_addto_param(struct sctp_chunk *chunk, int len, | |||
987 | 987 | ||
988 | target = skb_put(chunk->skb, len); | 988 | target = skb_put(chunk->skb, len); |
989 | 989 | ||
990 | memcpy(target, data, len); | 990 | if (data) |
991 | memcpy(target, data, len); | ||
992 | else | ||
993 | memset(target, 0, len); | ||
991 | 994 | ||
992 | /* Adjust the chunk length field. */ | 995 | /* Adjust the chunk length field. */ |
993 | chunk->chunk_hdr->length = htons(chunklen + len); | 996 | chunk->chunk_hdr->length = htons(chunklen + len); |
@@ -1129,16 +1132,18 @@ nodata: | |||
1129 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, | 1132 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, |
1130 | const struct sctp_chunk *chunk, | 1133 | const struct sctp_chunk *chunk, |
1131 | __be16 cause_code, const void *payload, | 1134 | __be16 cause_code, const void *payload, |
1132 | size_t paylen) | 1135 | size_t paylen, size_t reserve_tail) |
1133 | { | 1136 | { |
1134 | struct sctp_chunk *retval; | 1137 | struct sctp_chunk *retval; |
1135 | 1138 | ||
1136 | retval = sctp_make_op_error_space(asoc, chunk, paylen); | 1139 | retval = sctp_make_op_error_space(asoc, chunk, paylen + reserve_tail); |
1137 | if (!retval) | 1140 | if (!retval) |
1138 | goto nodata; | 1141 | goto nodata; |
1139 | 1142 | ||
1140 | sctp_init_cause(retval, cause_code, paylen); | 1143 | sctp_init_cause(retval, cause_code, paylen + reserve_tail); |
1141 | sctp_addto_chunk(retval, paylen, payload); | 1144 | sctp_addto_chunk(retval, paylen, payload); |
1145 | if (reserve_tail) | ||
1146 | sctp_addto_param(retval, reserve_tail, NULL); | ||
1142 | 1147 | ||
1143 | nodata: | 1148 | nodata: |
1144 | return retval; | 1149 | return retval; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index efa516b47e81..4e4ca65cd320 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -217,8 +217,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
217 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 217 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
218 | SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); | 218 | SCTP_TO(SCTP_EVENT_TIMEOUT_SACK)); |
219 | } else { | 219 | } else { |
220 | if (asoc->a_rwnd > asoc->rwnd) | 220 | asoc->a_rwnd = asoc->rwnd; |
221 | asoc->a_rwnd = asoc->rwnd; | ||
222 | sack = sctp_make_sack(asoc); | 221 | sack = sctp_make_sack(asoc); |
223 | if (!sack) | 222 | if (!sack) |
224 | goto nomem; | 223 | goto nomem; |
@@ -718,7 +717,7 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
718 | 717 | ||
719 | if (sctp_style(sk, TCP)) { | 718 | if (sctp_style(sk, TCP)) { |
720 | /* Change the sk->sk_state of a TCP-style socket that has | 719 | /* Change the sk->sk_state of a TCP-style socket that has |
721 | * sucessfully completed a connect() call. | 720 | * successfully completed a connect() call. |
722 | */ | 721 | */ |
723 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 722 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
724 | sk->sk_state = SCTP_SS_ESTABLISHED; | 723 | sk->sk_state = SCTP_SS_ESTABLISHED; |
@@ -1417,6 +1416,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1417 | asoc->init_last_sent_to = t; | 1416 | asoc->init_last_sent_to = t; |
1418 | chunk->transport = t; | 1417 | chunk->transport = t; |
1419 | t->init_sent_count++; | 1418 | t->init_sent_count++; |
1419 | /* Set the new transport as primary */ | ||
1420 | sctp_assoc_set_primary(asoc, t); | ||
1420 | break; | 1421 | break; |
1421 | 1422 | ||
1422 | case SCTP_CMD_INIT_RESTART: | 1423 | case SCTP_CMD_INIT_RESTART: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index d4df45022ffa..47bc20d3a85b 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -996,14 +996,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | |||
996 | sctp_sf_heartbeat(ep, asoc, type, arg, | 996 | sctp_sf_heartbeat(ep, asoc, type, arg, |
997 | commands)) | 997 | commands)) |
998 | return SCTP_DISPOSITION_NOMEM; | 998 | return SCTP_DISPOSITION_NOMEM; |
999 | |||
999 | /* Set transport error counter and association error counter | 1000 | /* Set transport error counter and association error counter |
1000 | * when sending heartbeat. | 1001 | * when sending heartbeat. |
1001 | */ | 1002 | */ |
1002 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE, | ||
1003 | SCTP_TRANSPORT(transport)); | ||
1004 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, | 1003 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT, |
1005 | SCTP_TRANSPORT(transport)); | 1004 | SCTP_TRANSPORT(transport)); |
1006 | } | 1005 | } |
1006 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE, | ||
1007 | SCTP_TRANSPORT(transport)); | ||
1007 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE, | 1008 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE, |
1008 | SCTP_TRANSPORT(transport)); | 1009 | SCTP_TRANSPORT(transport)); |
1009 | 1010 | ||
@@ -1720,7 +1721,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1720 | 1721 | ||
1721 | err = sctp_make_op_error(asoc, chunk, | 1722 | err = sctp_make_op_error(asoc, chunk, |
1722 | SCTP_ERROR_COOKIE_IN_SHUTDOWN, | 1723 | SCTP_ERROR_COOKIE_IN_SHUTDOWN, |
1723 | NULL, 0); | 1724 | NULL, 0, 0); |
1724 | if (err) | 1725 | if (err) |
1725 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 1726 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
1726 | SCTP_CHUNK(err)); | 1727 | SCTP_CHUNK(err)); |
@@ -2868,6 +2869,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | |||
2868 | sctp_cmd_seq_t *commands) | 2869 | sctp_cmd_seq_t *commands) |
2869 | { | 2870 | { |
2870 | struct sctp_chunk *chunk = arg; | 2871 | struct sctp_chunk *chunk = arg; |
2872 | sctp_arg_t force = SCTP_NOFORCE(); | ||
2871 | int error; | 2873 | int error; |
2872 | 2874 | ||
2873 | if (!sctp_vtag_verify(chunk, asoc)) { | 2875 | if (!sctp_vtag_verify(chunk, asoc)) { |
@@ -2901,6 +2903,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | |||
2901 | BUG(); | 2903 | BUG(); |
2902 | } | 2904 | } |
2903 | 2905 | ||
2906 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) | ||
2907 | force = SCTP_FORCE(); | ||
2908 | |||
2904 | if (asoc->autoclose) { | 2909 | if (asoc->autoclose) { |
2905 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 2910 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
2906 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 2911 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
@@ -2929,7 +2934,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | |||
2929 | * more aggressive than the following algorithms allow. | 2934 | * more aggressive than the following algorithms allow. |
2930 | */ | 2935 | */ |
2931 | if (chunk->end_of_packet) | 2936 | if (chunk->end_of_packet) |
2932 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE()); | 2937 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); |
2933 | 2938 | ||
2934 | return SCTP_DISPOSITION_CONSUME; | 2939 | return SCTP_DISPOSITION_CONSUME; |
2935 | 2940 | ||
@@ -2954,7 +2959,7 @@ discard_force: | |||
2954 | 2959 | ||
2955 | discard_noforce: | 2960 | discard_noforce: |
2956 | if (chunk->end_of_packet) | 2961 | if (chunk->end_of_packet) |
2957 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE()); | 2962 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force); |
2958 | 2963 | ||
2959 | return SCTP_DISPOSITION_DISCARD; | 2964 | return SCTP_DISPOSITION_DISCARD; |
2960 | consume: | 2965 | consume: |
@@ -3572,7 +3577,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3572 | * To do this properly, we'll set the destination address of the chunk | 3577 | * To do this properly, we'll set the destination address of the chunk |
3573 | * and at the transmit time, will try look up the transport to use. | 3578 | * and at the transmit time, will try look up the transport to use. |
3574 | * Since ASCONFs may be bundled, the correct transport may not be | 3579 | * Since ASCONFs may be bundled, the correct transport may not be |
3575 | * created untill we process the entire packet, thus this workaround. | 3580 | * created until we process the entire packet, thus this workaround. |
3576 | */ | 3581 | */ |
3577 | asconf_ack->dest = chunk->source; | 3582 | asconf_ack->dest = chunk->source; |
3578 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack)); | 3583 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(asconf_ack)); |
@@ -3973,7 +3978,7 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | |||
3973 | err_chunk = sctp_make_op_error(asoc, chunk, | 3978 | err_chunk = sctp_make_op_error(asoc, chunk, |
3974 | SCTP_ERROR_UNSUP_HMAC, | 3979 | SCTP_ERROR_UNSUP_HMAC, |
3975 | &auth_hdr->hmac_id, | 3980 | &auth_hdr->hmac_id, |
3976 | sizeof(__u16)); | 3981 | sizeof(__u16), 0); |
3977 | if (err_chunk) { | 3982 | if (err_chunk) { |
3978 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 3983 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
3979 | SCTP_CHUNK(err_chunk)); | 3984 | SCTP_CHUNK(err_chunk)); |
@@ -4065,7 +4070,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
4065 | hdr = unk_chunk->chunk_hdr; | 4070 | hdr = unk_chunk->chunk_hdr; |
4066 | err_chunk = sctp_make_op_error(asoc, unk_chunk, | 4071 | err_chunk = sctp_make_op_error(asoc, unk_chunk, |
4067 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, | 4072 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, |
4068 | WORD_ROUND(ntohs(hdr->length))); | 4073 | WORD_ROUND(ntohs(hdr->length)), |
4074 | 0); | ||
4069 | if (err_chunk) { | 4075 | if (err_chunk) { |
4070 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 4076 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
4071 | SCTP_CHUNK(err_chunk)); | 4077 | SCTP_CHUNK(err_chunk)); |
@@ -4084,7 +4090,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
4084 | hdr = unk_chunk->chunk_hdr; | 4090 | hdr = unk_chunk->chunk_hdr; |
4085 | err_chunk = sctp_make_op_error(asoc, unk_chunk, | 4091 | err_chunk = sctp_make_op_error(asoc, unk_chunk, |
4086 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, | 4092 | SCTP_ERROR_UNKNOWN_CHUNK, hdr, |
4087 | WORD_ROUND(ntohs(hdr->length))); | 4093 | WORD_ROUND(ntohs(hdr->length)), |
4094 | 0); | ||
4088 | if (err_chunk) { | 4095 | if (err_chunk) { |
4089 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 4096 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
4090 | SCTP_CHUNK(err_chunk)); | 4097 | SCTP_CHUNK(err_chunk)); |
@@ -6048,7 +6055,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
6048 | 6055 | ||
6049 | err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, | 6056 | err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM, |
6050 | &data_hdr->stream, | 6057 | &data_hdr->stream, |
6051 | sizeof(data_hdr->stream)); | 6058 | sizeof(data_hdr->stream), |
6059 | sizeof(u16)); | ||
6052 | if (err) | 6060 | if (err) |
6053 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 6061 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
6054 | SCTP_CHUNK(err)); | 6062 | SCTP_CHUNK(err)); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3a95fcb17a9e..89ab66e54740 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -394,7 +394,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
394 | 394 | ||
395 | /* Refresh ephemeral port. */ | 395 | /* Refresh ephemeral port. */ |
396 | if (!bp->port) | 396 | if (!bp->port) |
397 | bp->port = inet_sk(sk)->num; | 397 | bp->port = inet_sk(sk)->inet_num; |
398 | 398 | ||
399 | /* Add the address to the bind address list. | 399 | /* Add the address to the bind address list. |
400 | * Use GFP_ATOMIC since BHs will be disabled. | 400 | * Use GFP_ATOMIC since BHs will be disabled. |
@@ -403,7 +403,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
403 | 403 | ||
404 | /* Copy back into socket for getsockname() use. */ | 404 | /* Copy back into socket for getsockname() use. */ |
405 | if (!ret) { | 405 | if (!ret) { |
406 | inet_sk(sk)->sport = htons(inet_sk(sk)->num); | 406 | inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num); |
407 | af->to_sk_saddr(addr, sk); | 407 | af->to_sk_saddr(addr, sk); |
408 | } | 408 | } |
409 | 409 | ||
@@ -1117,7 +1117,7 @@ static int __sctp_connect(struct sock* sk, | |||
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | /* Initialize sk's dport and daddr for getpeername() */ | 1119 | /* Initialize sk's dport and daddr for getpeername() */ |
1120 | inet_sk(sk)->dport = htons(asoc->peer.port); | 1120 | inet_sk(sk)->inet_dport = htons(asoc->peer.port); |
1121 | af = sctp_get_af_specific(sa_addr->sa.sa_family); | 1121 | af = sctp_get_af_specific(sa_addr->sa.sa_family); |
1122 | af->to_sk_daddr(sa_addr, sk); | 1122 | af->to_sk_daddr(sa_addr, sk); |
1123 | sk->sk_err = 0; | 1123 | sk->sk_err = 0; |
@@ -1968,7 +1968,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
1968 | if (err) | 1968 | if (err) |
1969 | goto out_free; | 1969 | goto out_free; |
1970 | 1970 | ||
1971 | sock_recv_timestamp(msg, sk, skb); | 1971 | sock_recv_ts_and_drops(msg, sk, skb); |
1972 | if (sctp_ulpevent_is_notification(event)) { | 1972 | if (sctp_ulpevent_is_notification(event)) { |
1973 | msg->msg_flags |= MSG_NOTIFICATION; | 1973 | msg->msg_flags |= MSG_NOTIFICATION; |
1974 | sp->pf->event_msgname(event, msg->msg_name, addr_len); | 1974 | sp->pf->event_msgname(event, msg->msg_name, addr_len); |
@@ -2086,6 +2086,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
2086 | return -EINVAL; | 2086 | return -EINVAL; |
2087 | if (copy_from_user(&sp->autoclose, optval, optlen)) | 2087 | if (copy_from_user(&sp->autoclose, optval, optlen)) |
2088 | return -EFAULT; | 2088 | return -EFAULT; |
2089 | /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */ | ||
2090 | if (sp->autoclose > (MAX_SCHEDULE_TIMEOUT / HZ) ) | ||
2091 | sp->autoclose = (__u32)(MAX_SCHEDULE_TIMEOUT / HZ) ; | ||
2089 | 2092 | ||
2090 | return 0; | 2093 | return 0; |
2091 | } | 2094 | } |
@@ -2311,11 +2314,10 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2311 | } | 2314 | } |
2312 | } | 2315 | } |
2313 | 2316 | ||
2314 | /* Note that unless the spp_flag is set to SPP_PMTUD_ENABLE the value | 2317 | /* Note that a value of zero indicates the current setting should be |
2315 | * of this field is ignored. Note also that a value of zero | 2318 | left unchanged. |
2316 | * indicates the current setting should be left unchanged. | ||
2317 | */ | 2319 | */ |
2318 | if ((params->spp_flags & SPP_PMTUD_ENABLE) && params->spp_pathmaxrxt) { | 2320 | if (params->spp_pathmaxrxt) { |
2319 | if (trans) { | 2321 | if (trans) { |
2320 | trans->pathmaxrxt = params->spp_pathmaxrxt; | 2322 | trans->pathmaxrxt = params->spp_pathmaxrxt; |
2321 | } else if (asoc) { | 2323 | } else if (asoc) { |
@@ -2354,8 +2356,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2354 | pmtud_change == SPP_PMTUD || | 2356 | pmtud_change == SPP_PMTUD || |
2355 | sackdelay_change == SPP_SACKDELAY || | 2357 | sackdelay_change == SPP_SACKDELAY || |
2356 | params.spp_sackdelay > 500 || | 2358 | params.spp_sackdelay > 500 || |
2357 | (params.spp_pathmtu | 2359 | (params.spp_pathmtu && |
2358 | && params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT)) | 2360 | params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT)) |
2359 | return -EINVAL; | 2361 | return -EINVAL; |
2360 | 2362 | ||
2361 | /* If an address other than INADDR_ANY is specified, and | 2363 | /* If an address other than INADDR_ANY is specified, and |
@@ -4349,90 +4351,6 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval | |||
4349 | return 0; | 4351 | return 0; |
4350 | } | 4352 | } |
4351 | 4353 | ||
4352 | static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, | ||
4353 | char __user *optval, | ||
4354 | int __user *optlen) | ||
4355 | { | ||
4356 | sctp_assoc_t id; | ||
4357 | struct sctp_association *asoc; | ||
4358 | struct list_head *pos; | ||
4359 | int cnt = 0; | ||
4360 | |||
4361 | if (len < sizeof(sctp_assoc_t)) | ||
4362 | return -EINVAL; | ||
4363 | |||
4364 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) | ||
4365 | return -EFAULT; | ||
4366 | |||
4367 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_NUM_OLD " | ||
4368 | "socket option deprecated\n"); | ||
4369 | /* For UDP-style sockets, id specifies the association to query. */ | ||
4370 | asoc = sctp_id2assoc(sk, id); | ||
4371 | if (!asoc) | ||
4372 | return -EINVAL; | ||
4373 | |||
4374 | list_for_each(pos, &asoc->peer.transport_addr_list) { | ||
4375 | cnt ++; | ||
4376 | } | ||
4377 | |||
4378 | return cnt; | ||
4379 | } | ||
4380 | |||
4381 | /* | ||
4382 | * Old API for getting list of peer addresses. Does not work for 32-bit | ||
4383 | * programs running on a 64-bit kernel | ||
4384 | */ | ||
4385 | static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, | ||
4386 | char __user *optval, | ||
4387 | int __user *optlen) | ||
4388 | { | ||
4389 | struct sctp_association *asoc; | ||
4390 | int cnt = 0; | ||
4391 | struct sctp_getaddrs_old getaddrs; | ||
4392 | struct sctp_transport *from; | ||
4393 | void __user *to; | ||
4394 | union sctp_addr temp; | ||
4395 | struct sctp_sock *sp = sctp_sk(sk); | ||
4396 | int addrlen; | ||
4397 | |||
4398 | if (len < sizeof(struct sctp_getaddrs_old)) | ||
4399 | return -EINVAL; | ||
4400 | |||
4401 | len = sizeof(struct sctp_getaddrs_old); | ||
4402 | |||
4403 | if (copy_from_user(&getaddrs, optval, len)) | ||
4404 | return -EFAULT; | ||
4405 | |||
4406 | if (getaddrs.addr_num <= 0) return -EINVAL; | ||
4407 | |||
4408 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_OLD " | ||
4409 | "socket option deprecated\n"); | ||
4410 | |||
4411 | /* For UDP-style sockets, id specifies the association to query. */ | ||
4412 | asoc = sctp_id2assoc(sk, getaddrs.assoc_id); | ||
4413 | if (!asoc) | ||
4414 | return -EINVAL; | ||
4415 | |||
4416 | to = (void __user *)getaddrs.addrs; | ||
4417 | list_for_each_entry(from, &asoc->peer.transport_addr_list, | ||
4418 | transports) { | ||
4419 | memcpy(&temp, &from->ipaddr, sizeof(temp)); | ||
4420 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | ||
4421 | addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; | ||
4422 | if (copy_to_user(to, &temp, addrlen)) | ||
4423 | return -EFAULT; | ||
4424 | to += addrlen ; | ||
4425 | cnt ++; | ||
4426 | if (cnt >= getaddrs.addr_num) break; | ||
4427 | } | ||
4428 | getaddrs.addr_num = cnt; | ||
4429 | if (put_user(len, optlen)) | ||
4430 | return -EFAULT; | ||
4431 | if (copy_to_user(optval, &getaddrs, len)) | ||
4432 | return -EFAULT; | ||
4433 | |||
4434 | return 0; | ||
4435 | } | ||
4436 | 4354 | ||
4437 | static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | 4355 | static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, |
4438 | char __user *optval, int __user *optlen) | 4356 | char __user *optval, int __user *optlen) |
@@ -4485,125 +4403,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | |||
4485 | return 0; | 4403 | return 0; |
4486 | } | 4404 | } |
4487 | 4405 | ||
4488 | static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, | ||
4489 | char __user *optval, | ||
4490 | int __user *optlen) | ||
4491 | { | ||
4492 | sctp_assoc_t id; | ||
4493 | struct sctp_bind_addr *bp; | ||
4494 | struct sctp_association *asoc; | ||
4495 | struct sctp_sockaddr_entry *addr; | ||
4496 | int cnt = 0; | ||
4497 | |||
4498 | if (len < sizeof(sctp_assoc_t)) | ||
4499 | return -EINVAL; | ||
4500 | |||
4501 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) | ||
4502 | return -EFAULT; | ||
4503 | |||
4504 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_NUM_OLD " | ||
4505 | "socket option deprecated\n"); | ||
4506 | |||
4507 | /* | ||
4508 | * For UDP-style sockets, id specifies the association to query. | ||
4509 | * If the id field is set to the value '0' then the locally bound | ||
4510 | * addresses are returned without regard to any particular | ||
4511 | * association. | ||
4512 | */ | ||
4513 | if (0 == id) { | ||
4514 | bp = &sctp_sk(sk)->ep->base.bind_addr; | ||
4515 | } else { | ||
4516 | asoc = sctp_id2assoc(sk, id); | ||
4517 | if (!asoc) | ||
4518 | return -EINVAL; | ||
4519 | bp = &asoc->base.bind_addr; | ||
4520 | } | ||
4521 | |||
4522 | /* If the endpoint is bound to 0.0.0.0 or ::0, count the valid | ||
4523 | * addresses from the global local address list. | ||
4524 | */ | ||
4525 | if (sctp_list_single_entry(&bp->address_list)) { | ||
4526 | addr = list_entry(bp->address_list.next, | ||
4527 | struct sctp_sockaddr_entry, list); | ||
4528 | if (sctp_is_any(sk, &addr->a)) { | ||
4529 | rcu_read_lock(); | ||
4530 | list_for_each_entry_rcu(addr, | ||
4531 | &sctp_local_addr_list, list) { | ||
4532 | if (!addr->valid) | ||
4533 | continue; | ||
4534 | |||
4535 | if ((PF_INET == sk->sk_family) && | ||
4536 | (AF_INET6 == addr->a.sa.sa_family)) | ||
4537 | continue; | ||
4538 | |||
4539 | if ((PF_INET6 == sk->sk_family) && | ||
4540 | inet_v6_ipv6only(sk) && | ||
4541 | (AF_INET == addr->a.sa.sa_family)) | ||
4542 | continue; | ||
4543 | |||
4544 | cnt++; | ||
4545 | } | ||
4546 | rcu_read_unlock(); | ||
4547 | } else { | ||
4548 | cnt = 1; | ||
4549 | } | ||
4550 | goto done; | ||
4551 | } | ||
4552 | |||
4553 | /* Protection on the bound address list is not needed, | ||
4554 | * since in the socket option context we hold the socket lock, | ||
4555 | * so there is no way that the bound address list can change. | ||
4556 | */ | ||
4557 | list_for_each_entry(addr, &bp->address_list, list) { | ||
4558 | cnt ++; | ||
4559 | } | ||
4560 | done: | ||
4561 | return cnt; | ||
4562 | } | ||
4563 | |||
4564 | /* Helper function that copies local addresses to user and returns the number | ||
4565 | * of addresses copied. | ||
4566 | */ | ||
4567 | static int sctp_copy_laddrs_old(struct sock *sk, __u16 port, | ||
4568 | int max_addrs, void *to, | ||
4569 | int *bytes_copied) | ||
4570 | { | ||
4571 | struct sctp_sockaddr_entry *addr; | ||
4572 | union sctp_addr temp; | ||
4573 | int cnt = 0; | ||
4574 | int addrlen; | ||
4575 | |||
4576 | rcu_read_lock(); | ||
4577 | list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { | ||
4578 | if (!addr->valid) | ||
4579 | continue; | ||
4580 | |||
4581 | if ((PF_INET == sk->sk_family) && | ||
4582 | (AF_INET6 == addr->a.sa.sa_family)) | ||
4583 | continue; | ||
4584 | if ((PF_INET6 == sk->sk_family) && | ||
4585 | inet_v6_ipv6only(sk) && | ||
4586 | (AF_INET == addr->a.sa.sa_family)) | ||
4587 | continue; | ||
4588 | memcpy(&temp, &addr->a, sizeof(temp)); | ||
4589 | if (!temp.v4.sin_port) | ||
4590 | temp.v4.sin_port = htons(port); | ||
4591 | |||
4592 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | ||
4593 | &temp); | ||
4594 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | ||
4595 | memcpy(to, &temp, addrlen); | ||
4596 | |||
4597 | to += addrlen; | ||
4598 | *bytes_copied += addrlen; | ||
4599 | cnt ++; | ||
4600 | if (cnt >= max_addrs) break; | ||
4601 | } | ||
4602 | rcu_read_unlock(); | ||
4603 | |||
4604 | return cnt; | ||
4605 | } | ||
4606 | |||
4607 | static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, | 4406 | static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, |
4608 | size_t space_left, int *bytes_copied) | 4407 | size_t space_left, int *bytes_copied) |
4609 | { | 4408 | { |
@@ -4647,112 +4446,6 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, | |||
4647 | return cnt; | 4446 | return cnt; |
4648 | } | 4447 | } |
4649 | 4448 | ||
4650 | /* Old API for getting list of local addresses. Does not work for 32-bit | ||
4651 | * programs running on a 64-bit kernel | ||
4652 | */ | ||
4653 | static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, | ||
4654 | char __user *optval, int __user *optlen) | ||
4655 | { | ||
4656 | struct sctp_bind_addr *bp; | ||
4657 | struct sctp_association *asoc; | ||
4658 | int cnt = 0; | ||
4659 | struct sctp_getaddrs_old getaddrs; | ||
4660 | struct sctp_sockaddr_entry *addr; | ||
4661 | void __user *to; | ||
4662 | union sctp_addr temp; | ||
4663 | struct sctp_sock *sp = sctp_sk(sk); | ||
4664 | int addrlen; | ||
4665 | int err = 0; | ||
4666 | void *addrs; | ||
4667 | void *buf; | ||
4668 | int bytes_copied = 0; | ||
4669 | |||
4670 | if (len < sizeof(struct sctp_getaddrs_old)) | ||
4671 | return -EINVAL; | ||
4672 | |||
4673 | len = sizeof(struct sctp_getaddrs_old); | ||
4674 | if (copy_from_user(&getaddrs, optval, len)) | ||
4675 | return -EFAULT; | ||
4676 | |||
4677 | if (getaddrs.addr_num <= 0 || | ||
4678 | getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr))) | ||
4679 | return -EINVAL; | ||
4680 | |||
4681 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_OLD " | ||
4682 | "socket option deprecated\n"); | ||
4683 | |||
4684 | /* | ||
4685 | * For UDP-style sockets, id specifies the association to query. | ||
4686 | * If the id field is set to the value '0' then the locally bound | ||
4687 | * addresses are returned without regard to any particular | ||
4688 | * association. | ||
4689 | */ | ||
4690 | if (0 == getaddrs.assoc_id) { | ||
4691 | bp = &sctp_sk(sk)->ep->base.bind_addr; | ||
4692 | } else { | ||
4693 | asoc = sctp_id2assoc(sk, getaddrs.assoc_id); | ||
4694 | if (!asoc) | ||
4695 | return -EINVAL; | ||
4696 | bp = &asoc->base.bind_addr; | ||
4697 | } | ||
4698 | |||
4699 | to = getaddrs.addrs; | ||
4700 | |||
4701 | /* Allocate space for a local instance of packed array to hold all | ||
4702 | * the data. We store addresses here first and then put write them | ||
4703 | * to the user in one shot. | ||
4704 | */ | ||
4705 | addrs = kmalloc(sizeof(union sctp_addr) * getaddrs.addr_num, | ||
4706 | GFP_KERNEL); | ||
4707 | if (!addrs) | ||
4708 | return -ENOMEM; | ||
4709 | |||
4710 | /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid | ||
4711 | * addresses from the global local address list. | ||
4712 | */ | ||
4713 | if (sctp_list_single_entry(&bp->address_list)) { | ||
4714 | addr = list_entry(bp->address_list.next, | ||
4715 | struct sctp_sockaddr_entry, list); | ||
4716 | if (sctp_is_any(sk, &addr->a)) { | ||
4717 | cnt = sctp_copy_laddrs_old(sk, bp->port, | ||
4718 | getaddrs.addr_num, | ||
4719 | addrs, &bytes_copied); | ||
4720 | goto copy_getaddrs; | ||
4721 | } | ||
4722 | } | ||
4723 | |||
4724 | buf = addrs; | ||
4725 | /* Protection on the bound address list is not needed since | ||
4726 | * in the socket option context we hold a socket lock and | ||
4727 | * thus the bound address list can't change. | ||
4728 | */ | ||
4729 | list_for_each_entry(addr, &bp->address_list, list) { | ||
4730 | memcpy(&temp, &addr->a, sizeof(temp)); | ||
4731 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | ||
4732 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | ||
4733 | memcpy(buf, &temp, addrlen); | ||
4734 | buf += addrlen; | ||
4735 | bytes_copied += addrlen; | ||
4736 | cnt ++; | ||
4737 | if (cnt >= getaddrs.addr_num) break; | ||
4738 | } | ||
4739 | |||
4740 | copy_getaddrs: | ||
4741 | /* copy the entire address list into the user provided space */ | ||
4742 | if (copy_to_user(to, addrs, bytes_copied)) { | ||
4743 | err = -EFAULT; | ||
4744 | goto error; | ||
4745 | } | ||
4746 | |||
4747 | /* copy the leading structure back to user */ | ||
4748 | getaddrs.addr_num = cnt; | ||
4749 | if (copy_to_user(optval, &getaddrs, len)) | ||
4750 | err = -EFAULT; | ||
4751 | |||
4752 | error: | ||
4753 | kfree(addrs); | ||
4754 | return err; | ||
4755 | } | ||
4756 | 4449 | ||
4757 | static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | 4450 | static int sctp_getsockopt_local_addrs(struct sock *sk, int len, |
4758 | char __user *optval, int __user *optlen) | 4451 | char __user *optval, int __user *optlen) |
@@ -5603,22 +5296,6 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5603 | case SCTP_INITMSG: | 5296 | case SCTP_INITMSG: |
5604 | retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); | 5297 | retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); |
5605 | break; | 5298 | break; |
5606 | case SCTP_GET_PEER_ADDRS_NUM_OLD: | ||
5607 | retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval, | ||
5608 | optlen); | ||
5609 | break; | ||
5610 | case SCTP_GET_LOCAL_ADDRS_NUM_OLD: | ||
5611 | retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval, | ||
5612 | optlen); | ||
5613 | break; | ||
5614 | case SCTP_GET_PEER_ADDRS_OLD: | ||
5615 | retval = sctp_getsockopt_peer_addrs_old(sk, len, optval, | ||
5616 | optlen); | ||
5617 | break; | ||
5618 | case SCTP_GET_LOCAL_ADDRS_OLD: | ||
5619 | retval = sctp_getsockopt_local_addrs_old(sk, len, optval, | ||
5620 | optlen); | ||
5621 | break; | ||
5622 | case SCTP_GET_PEER_ADDRS: | 5299 | case SCTP_GET_PEER_ADDRS: |
5623 | retval = sctp_getsockopt_peer_addrs(sk, len, optval, | 5300 | retval = sctp_getsockopt_peer_addrs(sk, len, optval, |
5624 | optlen); | 5301 | optlen); |
@@ -5861,7 +5538,7 @@ pp_not_found: | |||
5861 | */ | 5538 | */ |
5862 | success: | 5539 | success: |
5863 | if (!sctp_sk(sk)->bind_hash) { | 5540 | if (!sctp_sk(sk)->bind_hash) { |
5864 | inet_sk(sk)->num = snum; | 5541 | inet_sk(sk)->inet_num = snum; |
5865 | sk_add_bind_node(sk, &pp->owner); | 5542 | sk_add_bind_node(sk, &pp->owner); |
5866 | sctp_sk(sk)->bind_hash = pp; | 5543 | sctp_sk(sk)->bind_hash = pp; |
5867 | } | 5544 | } |
@@ -5933,7 +5610,7 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) | |||
5933 | if (sctp_autobind(sk)) | 5610 | if (sctp_autobind(sk)) |
5934 | return -EAGAIN; | 5611 | return -EAGAIN; |
5935 | } else { | 5612 | } else { |
5936 | if (sctp_get_port(sk, inet_sk(sk)->num)) { | 5613 | if (sctp_get_port(sk, inet_sk(sk)->inet_num)) { |
5937 | sk->sk_state = SCTP_SS_CLOSED; | 5614 | sk->sk_state = SCTP_SS_CLOSED; |
5938 | return -EADDRINUSE; | 5615 | return -EADDRINUSE; |
5939 | } | 5616 | } |
@@ -6104,14 +5781,14 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) | |||
6104 | static inline void __sctp_put_port(struct sock *sk) | 5781 | static inline void __sctp_put_port(struct sock *sk) |
6105 | { | 5782 | { |
6106 | struct sctp_bind_hashbucket *head = | 5783 | struct sctp_bind_hashbucket *head = |
6107 | &sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->num)]; | 5784 | &sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)]; |
6108 | struct sctp_bind_bucket *pp; | 5785 | struct sctp_bind_bucket *pp; |
6109 | 5786 | ||
6110 | sctp_spin_lock(&head->lock); | 5787 | sctp_spin_lock(&head->lock); |
6111 | pp = sctp_sk(sk)->bind_hash; | 5788 | pp = sctp_sk(sk)->bind_hash; |
6112 | __sk_del_bind_node(sk); | 5789 | __sk_del_bind_node(sk); |
6113 | sctp_sk(sk)->bind_hash = NULL; | 5790 | sctp_sk(sk)->bind_hash = NULL; |
6114 | inet_sk(sk)->num = 0; | 5791 | inet_sk(sk)->inet_num = 0; |
6115 | sctp_bucket_destroy(pp); | 5792 | sctp_bucket_destroy(pp); |
6116 | sctp_spin_unlock(&head->lock); | 5793 | sctp_spin_unlock(&head->lock); |
6117 | } | 5794 | } |
@@ -6138,7 +5815,7 @@ static int sctp_autobind(struct sock *sk) | |||
6138 | /* Initialize a local sockaddr structure to INADDR_ANY. */ | 5815 | /* Initialize a local sockaddr structure to INADDR_ANY. */ |
6139 | af = sctp_sk(sk)->pf->af; | 5816 | af = sctp_sk(sk)->pf->af; |
6140 | 5817 | ||
6141 | port = htons(inet_sk(sk)->num); | 5818 | port = htons(inet_sk(sk)->inet_num); |
6142 | af->inaddr_any(&autoaddr, port); | 5819 | af->inaddr_any(&autoaddr, port); |
6143 | 5820 | ||
6144 | return sctp_do_bind(sk, &autoaddr, af->sockaddr_len); | 5821 | return sctp_do_bind(sk, &autoaddr, af->sockaddr_len); |
@@ -6707,12 +6384,12 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, | |||
6707 | /* Initialize sk's sport, dport, rcv_saddr and daddr for | 6384 | /* Initialize sk's sport, dport, rcv_saddr and daddr for |
6708 | * getsockname() and getpeername() | 6385 | * getsockname() and getpeername() |
6709 | */ | 6386 | */ |
6710 | newinet->sport = inet->sport; | 6387 | newinet->inet_sport = inet->inet_sport; |
6711 | newinet->saddr = inet->saddr; | 6388 | newinet->inet_saddr = inet->inet_saddr; |
6712 | newinet->rcv_saddr = inet->rcv_saddr; | 6389 | newinet->inet_rcv_saddr = inet->inet_rcv_saddr; |
6713 | newinet->dport = htons(asoc->peer.port); | 6390 | newinet->inet_dport = htons(asoc->peer.port); |
6714 | newinet->pmtudisc = inet->pmtudisc; | 6391 | newinet->pmtudisc = inet->pmtudisc; |
6715 | newinet->id = asoc->next_tsn ^ jiffies; | 6392 | newinet->inet_id = asoc->next_tsn ^ jiffies; |
6716 | 6393 | ||
6717 | newinet->uc_ttl = inet->uc_ttl; | 6394 | newinet->uc_ttl = inet->uc_ttl; |
6718 | newinet->mc_loop = 1; | 6395 | newinet->mc_loop = 1; |
@@ -6751,13 +6428,13 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6751 | newsp->hmac = NULL; | 6428 | newsp->hmac = NULL; |
6752 | 6429 | ||
6753 | /* Hook this new socket in to the bind_hash list. */ | 6430 | /* Hook this new socket in to the bind_hash list. */ |
6754 | head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->num)]; | 6431 | head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)]; |
6755 | sctp_local_bh_disable(); | 6432 | sctp_local_bh_disable(); |
6756 | sctp_spin_lock(&head->lock); | 6433 | sctp_spin_lock(&head->lock); |
6757 | pp = sctp_sk(oldsk)->bind_hash; | 6434 | pp = sctp_sk(oldsk)->bind_hash; |
6758 | sk_add_bind_node(newsk, &pp->owner); | 6435 | sk_add_bind_node(newsk, &pp->owner); |
6759 | sctp_sk(newsk)->bind_hash = pp; | 6436 | sctp_sk(newsk)->bind_hash = pp; |
6760 | inet_sk(newsk)->num = inet_sk(oldsk)->num; | 6437 | inet_sk(newsk)->inet_num = inet_sk(oldsk)->inet_num; |
6761 | sctp_spin_unlock(&head->lock); | 6438 | sctp_spin_unlock(&head->lock); |
6762 | sctp_local_bh_enable(); | 6439 | sctp_local_bh_enable(); |
6763 | 6440 | ||
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index ab7151da120f..832590bbe0c0 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -52,6 +52,7 @@ static int int_max = INT_MAX; | |||
52 | static int sack_timer_min = 1; | 52 | static int sack_timer_min = 1; |
53 | static int sack_timer_max = 500; | 53 | static int sack_timer_max = 500; |
54 | static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ | 54 | static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ |
55 | static int rwnd_scale_max = 16; | ||
55 | 56 | ||
56 | extern int sysctl_sctp_mem[3]; | 57 | extern int sysctl_sctp_mem[3]; |
57 | extern int sysctl_sctp_rmem[3]; | 58 | extern int sysctl_sctp_rmem[3]; |
@@ -59,180 +60,145 @@ extern int sysctl_sctp_wmem[3]; | |||
59 | 60 | ||
60 | static ctl_table sctp_table[] = { | 61 | static ctl_table sctp_table[] = { |
61 | { | 62 | { |
62 | .ctl_name = NET_SCTP_RTO_INITIAL, | ||
63 | .procname = "rto_initial", | 63 | .procname = "rto_initial", |
64 | .data = &sctp_rto_initial, | 64 | .data = &sctp_rto_initial, |
65 | .maxlen = sizeof(unsigned int), | 65 | .maxlen = sizeof(unsigned int), |
66 | .mode = 0644, | 66 | .mode = 0644, |
67 | .proc_handler = proc_dointvec_minmax, | 67 | .proc_handler = proc_dointvec_minmax, |
68 | .strategy = sysctl_intvec, | ||
69 | .extra1 = &one, | 68 | .extra1 = &one, |
70 | .extra2 = &timer_max | 69 | .extra2 = &timer_max |
71 | }, | 70 | }, |
72 | { | 71 | { |
73 | .ctl_name = NET_SCTP_RTO_MIN, | ||
74 | .procname = "rto_min", | 72 | .procname = "rto_min", |
75 | .data = &sctp_rto_min, | 73 | .data = &sctp_rto_min, |
76 | .maxlen = sizeof(unsigned int), | 74 | .maxlen = sizeof(unsigned int), |
77 | .mode = 0644, | 75 | .mode = 0644, |
78 | .proc_handler = proc_dointvec_minmax, | 76 | .proc_handler = proc_dointvec_minmax, |
79 | .strategy = sysctl_intvec, | ||
80 | .extra1 = &one, | 77 | .extra1 = &one, |
81 | .extra2 = &timer_max | 78 | .extra2 = &timer_max |
82 | }, | 79 | }, |
83 | { | 80 | { |
84 | .ctl_name = NET_SCTP_RTO_MAX, | ||
85 | .procname = "rto_max", | 81 | .procname = "rto_max", |
86 | .data = &sctp_rto_max, | 82 | .data = &sctp_rto_max, |
87 | .maxlen = sizeof(unsigned int), | 83 | .maxlen = sizeof(unsigned int), |
88 | .mode = 0644, | 84 | .mode = 0644, |
89 | .proc_handler = proc_dointvec_minmax, | 85 | .proc_handler = proc_dointvec_minmax, |
90 | .strategy = sysctl_intvec, | ||
91 | .extra1 = &one, | 86 | .extra1 = &one, |
92 | .extra2 = &timer_max | 87 | .extra2 = &timer_max |
93 | }, | 88 | }, |
94 | { | 89 | { |
95 | .ctl_name = NET_SCTP_VALID_COOKIE_LIFE, | ||
96 | .procname = "valid_cookie_life", | 90 | .procname = "valid_cookie_life", |
97 | .data = &sctp_valid_cookie_life, | 91 | .data = &sctp_valid_cookie_life, |
98 | .maxlen = sizeof(unsigned int), | 92 | .maxlen = sizeof(unsigned int), |
99 | .mode = 0644, | 93 | .mode = 0644, |
100 | .proc_handler = proc_dointvec_minmax, | 94 | .proc_handler = proc_dointvec_minmax, |
101 | .strategy = sysctl_intvec, | ||
102 | .extra1 = &one, | 95 | .extra1 = &one, |
103 | .extra2 = &timer_max | 96 | .extra2 = &timer_max |
104 | }, | 97 | }, |
105 | { | 98 | { |
106 | .ctl_name = NET_SCTP_MAX_BURST, | ||
107 | .procname = "max_burst", | 99 | .procname = "max_burst", |
108 | .data = &sctp_max_burst, | 100 | .data = &sctp_max_burst, |
109 | .maxlen = sizeof(int), | 101 | .maxlen = sizeof(int), |
110 | .mode = 0644, | 102 | .mode = 0644, |
111 | .proc_handler = proc_dointvec_minmax, | 103 | .proc_handler = proc_dointvec_minmax, |
112 | .strategy = sysctl_intvec, | ||
113 | .extra1 = &zero, | 104 | .extra1 = &zero, |
114 | .extra2 = &int_max | 105 | .extra2 = &int_max |
115 | }, | 106 | }, |
116 | { | 107 | { |
117 | .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS, | ||
118 | .procname = "association_max_retrans", | 108 | .procname = "association_max_retrans", |
119 | .data = &sctp_max_retrans_association, | 109 | .data = &sctp_max_retrans_association, |
120 | .maxlen = sizeof(int), | 110 | .maxlen = sizeof(int), |
121 | .mode = 0644, | 111 | .mode = 0644, |
122 | .proc_handler = proc_dointvec_minmax, | 112 | .proc_handler = proc_dointvec_minmax, |
123 | .strategy = sysctl_intvec, | ||
124 | .extra1 = &one, | 113 | .extra1 = &one, |
125 | .extra2 = &int_max | 114 | .extra2 = &int_max |
126 | }, | 115 | }, |
127 | { | 116 | { |
128 | .ctl_name = NET_SCTP_SNDBUF_POLICY, | ||
129 | .procname = "sndbuf_policy", | 117 | .procname = "sndbuf_policy", |
130 | .data = &sctp_sndbuf_policy, | 118 | .data = &sctp_sndbuf_policy, |
131 | .maxlen = sizeof(int), | 119 | .maxlen = sizeof(int), |
132 | .mode = 0644, | 120 | .mode = 0644, |
133 | .proc_handler = proc_dointvec, | 121 | .proc_handler = proc_dointvec, |
134 | .strategy = sysctl_intvec | ||
135 | }, | 122 | }, |
136 | { | 123 | { |
137 | .ctl_name = NET_SCTP_RCVBUF_POLICY, | ||
138 | .procname = "rcvbuf_policy", | 124 | .procname = "rcvbuf_policy", |
139 | .data = &sctp_rcvbuf_policy, | 125 | .data = &sctp_rcvbuf_policy, |
140 | .maxlen = sizeof(int), | 126 | .maxlen = sizeof(int), |
141 | .mode = 0644, | 127 | .mode = 0644, |
142 | .proc_handler = proc_dointvec, | 128 | .proc_handler = proc_dointvec, |
143 | .strategy = sysctl_intvec | ||
144 | }, | 129 | }, |
145 | { | 130 | { |
146 | .ctl_name = NET_SCTP_PATH_MAX_RETRANS, | ||
147 | .procname = "path_max_retrans", | 131 | .procname = "path_max_retrans", |
148 | .data = &sctp_max_retrans_path, | 132 | .data = &sctp_max_retrans_path, |
149 | .maxlen = sizeof(int), | 133 | .maxlen = sizeof(int), |
150 | .mode = 0644, | 134 | .mode = 0644, |
151 | .proc_handler = proc_dointvec_minmax, | 135 | .proc_handler = proc_dointvec_minmax, |
152 | .strategy = sysctl_intvec, | ||
153 | .extra1 = &one, | 136 | .extra1 = &one, |
154 | .extra2 = &int_max | 137 | .extra2 = &int_max |
155 | }, | 138 | }, |
156 | { | 139 | { |
157 | .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS, | ||
158 | .procname = "max_init_retransmits", | 140 | .procname = "max_init_retransmits", |
159 | .data = &sctp_max_retrans_init, | 141 | .data = &sctp_max_retrans_init, |
160 | .maxlen = sizeof(int), | 142 | .maxlen = sizeof(int), |
161 | .mode = 0644, | 143 | .mode = 0644, |
162 | .proc_handler = proc_dointvec_minmax, | 144 | .proc_handler = proc_dointvec_minmax, |
163 | .strategy = sysctl_intvec, | ||
164 | .extra1 = &one, | 145 | .extra1 = &one, |
165 | .extra2 = &int_max | 146 | .extra2 = &int_max |
166 | }, | 147 | }, |
167 | { | 148 | { |
168 | .ctl_name = NET_SCTP_HB_INTERVAL, | ||
169 | .procname = "hb_interval", | 149 | .procname = "hb_interval", |
170 | .data = &sctp_hb_interval, | 150 | .data = &sctp_hb_interval, |
171 | .maxlen = sizeof(unsigned int), | 151 | .maxlen = sizeof(unsigned int), |
172 | .mode = 0644, | 152 | .mode = 0644, |
173 | .proc_handler = proc_dointvec_minmax, | 153 | .proc_handler = proc_dointvec_minmax, |
174 | .strategy = sysctl_intvec, | ||
175 | .extra1 = &one, | 154 | .extra1 = &one, |
176 | .extra2 = &timer_max | 155 | .extra2 = &timer_max |
177 | }, | 156 | }, |
178 | { | 157 | { |
179 | .ctl_name = NET_SCTP_PRESERVE_ENABLE, | ||
180 | .procname = "cookie_preserve_enable", | 158 | .procname = "cookie_preserve_enable", |
181 | .data = &sctp_cookie_preserve_enable, | 159 | .data = &sctp_cookie_preserve_enable, |
182 | .maxlen = sizeof(int), | 160 | .maxlen = sizeof(int), |
183 | .mode = 0644, | 161 | .mode = 0644, |
184 | .proc_handler = proc_dointvec, | 162 | .proc_handler = proc_dointvec, |
185 | .strategy = sysctl_intvec | ||
186 | }, | 163 | }, |
187 | { | 164 | { |
188 | .ctl_name = NET_SCTP_RTO_ALPHA, | ||
189 | .procname = "rto_alpha_exp_divisor", | 165 | .procname = "rto_alpha_exp_divisor", |
190 | .data = &sctp_rto_alpha, | 166 | .data = &sctp_rto_alpha, |
191 | .maxlen = sizeof(int), | 167 | .maxlen = sizeof(int), |
192 | .mode = 0444, | 168 | .mode = 0444, |
193 | .proc_handler = proc_dointvec, | 169 | .proc_handler = proc_dointvec, |
194 | .strategy = sysctl_intvec | ||
195 | }, | 170 | }, |
196 | { | 171 | { |
197 | .ctl_name = NET_SCTP_RTO_BETA, | ||
198 | .procname = "rto_beta_exp_divisor", | 172 | .procname = "rto_beta_exp_divisor", |
199 | .data = &sctp_rto_beta, | 173 | .data = &sctp_rto_beta, |
200 | .maxlen = sizeof(int), | 174 | .maxlen = sizeof(int), |
201 | .mode = 0444, | 175 | .mode = 0444, |
202 | .proc_handler = proc_dointvec, | 176 | .proc_handler = proc_dointvec, |
203 | .strategy = sysctl_intvec | ||
204 | }, | 177 | }, |
205 | { | 178 | { |
206 | .ctl_name = NET_SCTP_ADDIP_ENABLE, | ||
207 | .procname = "addip_enable", | 179 | .procname = "addip_enable", |
208 | .data = &sctp_addip_enable, | 180 | .data = &sctp_addip_enable, |
209 | .maxlen = sizeof(int), | 181 | .maxlen = sizeof(int), |
210 | .mode = 0644, | 182 | .mode = 0644, |
211 | .proc_handler = proc_dointvec, | 183 | .proc_handler = proc_dointvec, |
212 | .strategy = sysctl_intvec | ||
213 | }, | 184 | }, |
214 | { | 185 | { |
215 | .ctl_name = NET_SCTP_PRSCTP_ENABLE, | ||
216 | .procname = "prsctp_enable", | 186 | .procname = "prsctp_enable", |
217 | .data = &sctp_prsctp_enable, | 187 | .data = &sctp_prsctp_enable, |
218 | .maxlen = sizeof(int), | 188 | .maxlen = sizeof(int), |
219 | .mode = 0644, | 189 | .mode = 0644, |
220 | .proc_handler = proc_dointvec, | 190 | .proc_handler = proc_dointvec, |
221 | .strategy = sysctl_intvec | ||
222 | }, | 191 | }, |
223 | { | 192 | { |
224 | .ctl_name = NET_SCTP_SACK_TIMEOUT, | ||
225 | .procname = "sack_timeout", | 193 | .procname = "sack_timeout", |
226 | .data = &sctp_sack_timeout, | 194 | .data = &sctp_sack_timeout, |
227 | .maxlen = sizeof(int), | 195 | .maxlen = sizeof(int), |
228 | .mode = 0644, | 196 | .mode = 0644, |
229 | .proc_handler = proc_dointvec_minmax, | 197 | .proc_handler = proc_dointvec_minmax, |
230 | .strategy = sysctl_intvec, | ||
231 | .extra1 = &sack_timer_min, | 198 | .extra1 = &sack_timer_min, |
232 | .extra2 = &sack_timer_max, | 199 | .extra2 = &sack_timer_max, |
233 | }, | 200 | }, |
234 | { | 201 | { |
235 | .ctl_name = CTL_UNNUMBERED, | ||
236 | .procname = "sctp_mem", | 202 | .procname = "sctp_mem", |
237 | .data = &sysctl_sctp_mem, | 203 | .data = &sysctl_sctp_mem, |
238 | .maxlen = sizeof(sysctl_sctp_mem), | 204 | .maxlen = sizeof(sysctl_sctp_mem), |
@@ -240,7 +206,6 @@ static ctl_table sctp_table[] = { | |||
240 | .proc_handler = proc_dointvec, | 206 | .proc_handler = proc_dointvec, |
241 | }, | 207 | }, |
242 | { | 208 | { |
243 | .ctl_name = CTL_UNNUMBERED, | ||
244 | .procname = "sctp_rmem", | 209 | .procname = "sctp_rmem", |
245 | .data = &sysctl_sctp_rmem, | 210 | .data = &sysctl_sctp_rmem, |
246 | .maxlen = sizeof(sysctl_sctp_rmem), | 211 | .maxlen = sizeof(sysctl_sctp_rmem), |
@@ -248,7 +213,6 @@ static ctl_table sctp_table[] = { | |||
248 | .proc_handler = proc_dointvec, | 213 | .proc_handler = proc_dointvec, |
249 | }, | 214 | }, |
250 | { | 215 | { |
251 | .ctl_name = CTL_UNNUMBERED, | ||
252 | .procname = "sctp_wmem", | 216 | .procname = "sctp_wmem", |
253 | .data = &sysctl_sctp_wmem, | 217 | .data = &sysctl_sctp_wmem, |
254 | .maxlen = sizeof(sysctl_sctp_wmem), | 218 | .maxlen = sizeof(sysctl_sctp_wmem), |
@@ -256,40 +220,44 @@ static ctl_table sctp_table[] = { | |||
256 | .proc_handler = proc_dointvec, | 220 | .proc_handler = proc_dointvec, |
257 | }, | 221 | }, |
258 | { | 222 | { |
259 | .ctl_name = CTL_UNNUMBERED, | ||
260 | .procname = "auth_enable", | 223 | .procname = "auth_enable", |
261 | .data = &sctp_auth_enable, | 224 | .data = &sctp_auth_enable, |
262 | .maxlen = sizeof(int), | 225 | .maxlen = sizeof(int), |
263 | .mode = 0644, | 226 | .mode = 0644, |
264 | .proc_handler = proc_dointvec, | 227 | .proc_handler = proc_dointvec, |
265 | .strategy = sysctl_intvec | ||
266 | }, | 228 | }, |
267 | { | 229 | { |
268 | .ctl_name = CTL_UNNUMBERED, | ||
269 | .procname = "addip_noauth_enable", | 230 | .procname = "addip_noauth_enable", |
270 | .data = &sctp_addip_noauth, | 231 | .data = &sctp_addip_noauth, |
271 | .maxlen = sizeof(int), | 232 | .maxlen = sizeof(int), |
272 | .mode = 0644, | 233 | .mode = 0644, |
273 | .proc_handler = proc_dointvec, | 234 | .proc_handler = proc_dointvec, |
274 | .strategy = sysctl_intvec | ||
275 | }, | 235 | }, |
276 | { | 236 | { |
277 | .ctl_name = CTL_UNNUMBERED, | ||
278 | .procname = "addr_scope_policy", | 237 | .procname = "addr_scope_policy", |
279 | .data = &sctp_scope_policy, | 238 | .data = &sctp_scope_policy, |
280 | .maxlen = sizeof(int), | 239 | .maxlen = sizeof(int), |
281 | .mode = 0644, | 240 | .mode = 0644, |
282 | .proc_handler = &proc_dointvec_minmax, | 241 | .proc_handler = proc_dointvec_minmax, |
283 | .strategy = &sysctl_intvec, | ||
284 | .extra1 = &zero, | 242 | .extra1 = &zero, |
285 | .extra2 = &addr_scope_max, | 243 | .extra2 = &addr_scope_max, |
286 | }, | 244 | }, |
287 | { .ctl_name = 0 } | 245 | { |
246 | .procname = "rwnd_update_shift", | ||
247 | .data = &sctp_rwnd_upd_shift, | ||
248 | .maxlen = sizeof(int), | ||
249 | .mode = 0644, | ||
250 | .proc_handler = &proc_dointvec_minmax, | ||
251 | .extra1 = &one, | ||
252 | .extra2 = &rwnd_scale_max, | ||
253 | }, | ||
254 | |||
255 | { /* sentinel */ } | ||
288 | }; | 256 | }; |
289 | 257 | ||
290 | static struct ctl_path sctp_path[] = { | 258 | static struct ctl_path sctp_path[] = { |
291 | { .procname = "net", .ctl_name = CTL_NET, }, | 259 | { .procname = "net", }, |
292 | { .procname = "sctp", .ctl_name = NET_SCTP, }, | 260 | { .procname = "sctp", }, |
293 | { } | 261 | { } |
294 | }; | 262 | }; |
295 | 263 | ||
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 37a1184d789f..b827d21dbe54 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -83,7 +83,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
83 | peer->fast_recovery = 0; | 83 | peer->fast_recovery = 0; |
84 | 84 | ||
85 | peer->last_time_heard = jiffies; | 85 | peer->last_time_heard = jiffies; |
86 | peer->last_time_used = jiffies; | ||
87 | peer->last_time_ecne_reduced = jiffies; | 86 | peer->last_time_ecne_reduced = jiffies; |
88 | 87 | ||
89 | peer->init_sent_count = 0; | 88 | peer->init_sent_count = 0; |
@@ -564,10 +563,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
564 | * to be done every RTO interval, we do it every hearbeat | 563 | * to be done every RTO interval, we do it every hearbeat |
565 | * interval. | 564 | * interval. |
566 | */ | 565 | */ |
567 | if (time_after(jiffies, transport->last_time_used + | 566 | transport->cwnd = max(transport->cwnd/2, |
568 | transport->rto)) | 567 | 4*transport->asoc->pathmtu); |
569 | transport->cwnd = max(transport->cwnd/2, | ||
570 | 4*transport->asoc->pathmtu); | ||
571 | break; | 568 | break; |
572 | } | 569 | } |
573 | 570 | ||
@@ -578,6 +575,43 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
578 | transport->cwnd, transport->ssthresh); | 575 | transport->cwnd, transport->ssthresh); |
579 | } | 576 | } |
580 | 577 | ||
578 | /* Apply Max.Burst limit to the congestion window: | ||
579 | * sctpimpguide-05 2.14.2 | ||
580 | * D) When the time comes for the sender to | ||
581 | * transmit new DATA chunks, the protocol parameter Max.Burst MUST | ||
582 | * first be applied to limit how many new DATA chunks may be sent. | ||
583 | * The limit is applied by adjusting cwnd as follows: | ||
584 | * if ((flightsize+ Max.Burst * MTU) < cwnd) | ||
585 | * cwnd = flightsize + Max.Burst * MTU | ||
586 | */ | ||
587 | |||
588 | void sctp_transport_burst_limited(struct sctp_transport *t) | ||
589 | { | ||
590 | struct sctp_association *asoc = t->asoc; | ||
591 | u32 old_cwnd = t->cwnd; | ||
592 | u32 max_burst_bytes; | ||
593 | |||
594 | if (t->burst_limited) | ||
595 | return; | ||
596 | |||
597 | max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu); | ||
598 | if (max_burst_bytes < old_cwnd) { | ||
599 | t->cwnd = max_burst_bytes; | ||
600 | t->burst_limited = old_cwnd; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | /* Restore the old cwnd congestion window, after the burst had it's | ||
605 | * desired effect. | ||
606 | */ | ||
607 | void sctp_transport_burst_reset(struct sctp_transport *t) | ||
608 | { | ||
609 | if (t->burst_limited) { | ||
610 | t->cwnd = t->burst_limited; | ||
611 | t->burst_limited = 0; | ||
612 | } | ||
613 | } | ||
614 | |||
581 | /* What is the next timeout value for this transport? */ | 615 | /* What is the next timeout value for this transport? */ |
582 | unsigned long sctp_transport_timeout(struct sctp_transport *t) | 616 | unsigned long sctp_transport_timeout(struct sctp_transport *t) |
583 | { | 617 | { |
@@ -600,6 +634,7 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
600 | * (see Section 6.2.1) | 634 | * (see Section 6.2.1) |
601 | */ | 635 | */ |
602 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); | 636 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); |
637 | t->burst_limited = 0; | ||
603 | t->ssthresh = asoc->peer.i.a_rwnd; | 638 | t->ssthresh = asoc->peer.i.a_rwnd; |
604 | t->rto = asoc->rto_initial; | 639 | t->rto = asoc->rto_initial; |
605 | t->rtt = 0; | 640 | t->rtt = 0; |