diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-11-12 21:16:13 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-11-12 21:16:13 -0500 |
commit | bce943278dc4aa03b0ef9c7cf8b1b7110eda8b91 (patch) | |
tree | 4225e979eb543e1970eb2b38174bd5dbdfd42237 /net | |
parent | 91cf45f02af5c871251165d000c3f42a2a0b0552 (diff) | |
parent | 9abed245a6dc94c32b2f45a1ecc51a0829d11470 (diff) |
Merge branch 'pending' of master.kernel.org:/pub/scm/linux/kernel/git/vxy/lksctp-dev
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/associola.c | 10 | ||||
-rw-r--r-- | net/sctp/bind_addr.c | 13 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 35 | ||||
-rw-r--r-- | net/sctp/input.c | 43 | ||||
-rw-r--r-- | net/sctp/inqueue.c | 4 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 41 | ||||
-rw-r--r-- | net/sctp/proc.c | 6 | ||||
-rw-r--r-- | net/sctp/protocol.c | 7 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 170 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 10 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 12 | ||||
-rw-r--r-- | net/sctp/socket.c | 16 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 9 | ||||
-rw-r--r-- | net/sctp/transport.c | 5 | ||||
-rw-r--r-- | net/sctp/ulpqueue.c | 2 |
15 files changed, 202 insertions, 181 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 03158e3665da..013e3d3ab0f1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -262,10 +262,14 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
262 | */ | 262 | */ |
263 | asoc->peer.sack_needed = 1; | 263 | asoc->peer.sack_needed = 1; |
264 | 264 | ||
265 | /* Assume that the peer recongizes ASCONF until reported otherwise | 265 | /* Assume that the peer will tell us if he recognizes ASCONF |
266 | * via an ERROR chunk. | 266 | * as part of INIT exchange. |
267 | * The sctp_addip_noauth option is there for backward compatibilty | ||
268 | * and will revert old behavior. | ||
267 | */ | 269 | */ |
268 | asoc->peer.asconf_capable = 1; | 270 | asoc->peer.asconf_capable = 0; |
271 | if (sctp_addip_noauth) | ||
272 | asoc->peer.asconf_capable = 1; | ||
269 | 273 | ||
270 | /* Create an input queue. */ | 274 | /* Create an input queue. */ |
271 | sctp_inq_init(&asoc->base.inqueue); | 275 | sctp_inq_init(&asoc->base.inqueue); |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index dfffa94fb9f6..cae95af9a8cc 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, | |||
180 | /* Delete an address from the bind address list in the SCTP_bind_addr | 180 | /* Delete an address from the bind address list in the SCTP_bind_addr |
181 | * structure. | 181 | * structure. |
182 | */ | 182 | */ |
183 | int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, | 183 | int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) |
184 | void fastcall (*rcu_call)(struct rcu_head *head, | ||
185 | void (*func)(struct rcu_head *head))) | ||
186 | { | 184 | { |
187 | struct sctp_sockaddr_entry *addr, *temp; | 185 | struct sctp_sockaddr_entry *addr, *temp; |
188 | 186 | ||
@@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, | |||
198 | } | 196 | } |
199 | } | 197 | } |
200 | 198 | ||
201 | /* Call the rcu callback provided in the args. This function is | ||
202 | * called by both BH packet processing and user side socket option | ||
203 | * processing, but it works on different lists in those 2 contexts. | ||
204 | * Each context provides it's own callback, whether call_rcu_bh() | ||
205 | * or call_rcu(), to make sure that we wait for an appropriate time. | ||
206 | */ | ||
207 | if (addr && !addr->valid) { | 199 | if (addr && !addr->valid) { |
208 | rcu_call(&addr->rcu, sctp_local_addr_free); | 200 | call_rcu(&addr->rcu, sctp_local_addr_free); |
209 | SCTP_DBG_OBJCNT_DEC(addr); | 201 | SCTP_DBG_OBJCNT_DEC(addr); |
202 | return 0; | ||
210 | } | 203 | } |
211 | 204 | ||
212 | return -EINVAL; | 205 | return -EINVAL; |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 2d2d81ef4a69..de6f505d6ff8 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -328,24 +328,35 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
328 | const union sctp_addr *paddr, | 328 | const union sctp_addr *paddr, |
329 | struct sctp_transport **transport) | 329 | struct sctp_transport **transport) |
330 | { | 330 | { |
331 | struct sctp_association *asoc = NULL; | ||
332 | struct sctp_transport *t = NULL; | ||
333 | struct sctp_hashbucket *head; | ||
334 | struct sctp_ep_common *epb; | ||
335 | struct hlist_node *node; | ||
336 | int hash; | ||
331 | int rport; | 337 | int rport; |
332 | struct sctp_association *asoc; | ||
333 | struct list_head *pos; | ||
334 | 338 | ||
339 | *transport = NULL; | ||
335 | rport = ntohs(paddr->v4.sin_port); | 340 | rport = ntohs(paddr->v4.sin_port); |
336 | 341 | ||
337 | list_for_each(pos, &ep->asocs) { | 342 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); |
338 | asoc = list_entry(pos, struct sctp_association, asocs); | 343 | head = &sctp_assoc_hashtable[hash]; |
339 | if (rport == asoc->peer.port) { | 344 | read_lock(&head->lock); |
340 | *transport = sctp_assoc_lookup_paddr(asoc, paddr); | 345 | sctp_for_each_hentry(epb, node, &head->chain) { |
341 | 346 | asoc = sctp_assoc(epb); | |
342 | if (*transport) | 347 | if (asoc->ep != ep || rport != asoc->peer.port) |
343 | return asoc; | 348 | goto next; |
349 | |||
350 | t = sctp_assoc_lookup_paddr(asoc, paddr); | ||
351 | if (t) { | ||
352 | *transport = t; | ||
353 | break; | ||
344 | } | 354 | } |
355 | next: | ||
356 | asoc = NULL; | ||
345 | } | 357 | } |
346 | 358 | read_unlock(&head->lock); | |
347 | *transport = NULL; | 359 | return asoc; |
348 | return NULL; | ||
349 | } | 360 | } |
350 | 361 | ||
351 | /* Lookup association on an endpoint based on a peer address. BH-safe. */ | 362 | /* Lookup association on an endpoint based on a peer address. BH-safe. */ |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 86503e7fa21e..91ae463b079b 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -656,7 +656,6 @@ discard: | |||
656 | /* Insert endpoint into the hash table. */ | 656 | /* Insert endpoint into the hash table. */ |
657 | static void __sctp_hash_endpoint(struct sctp_endpoint *ep) | 657 | static void __sctp_hash_endpoint(struct sctp_endpoint *ep) |
658 | { | 658 | { |
659 | struct sctp_ep_common **epp; | ||
660 | struct sctp_ep_common *epb; | 659 | struct sctp_ep_common *epb; |
661 | struct sctp_hashbucket *head; | 660 | struct sctp_hashbucket *head; |
662 | 661 | ||
@@ -666,12 +665,7 @@ static void __sctp_hash_endpoint(struct sctp_endpoint *ep) | |||
666 | head = &sctp_ep_hashtable[epb->hashent]; | 665 | head = &sctp_ep_hashtable[epb->hashent]; |
667 | 666 | ||
668 | sctp_write_lock(&head->lock); | 667 | sctp_write_lock(&head->lock); |
669 | epp = &head->chain; | 668 | hlist_add_head(&epb->node, &head->chain); |
670 | epb->next = *epp; | ||
671 | if (epb->next) | ||
672 | (*epp)->pprev = &epb->next; | ||
673 | *epp = epb; | ||
674 | epb->pprev = epp; | ||
675 | sctp_write_unlock(&head->lock); | 669 | sctp_write_unlock(&head->lock); |
676 | } | 670 | } |
677 | 671 | ||
@@ -691,19 +685,15 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) | |||
691 | 685 | ||
692 | epb = &ep->base; | 686 | epb = &ep->base; |
693 | 687 | ||
688 | if (hlist_unhashed(&epb->node)) | ||
689 | return; | ||
690 | |||
694 | epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); | 691 | epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); |
695 | 692 | ||
696 | head = &sctp_ep_hashtable[epb->hashent]; | 693 | head = &sctp_ep_hashtable[epb->hashent]; |
697 | 694 | ||
698 | sctp_write_lock(&head->lock); | 695 | sctp_write_lock(&head->lock); |
699 | 696 | __hlist_del(&epb->node); | |
700 | if (epb->pprev) { | ||
701 | if (epb->next) | ||
702 | epb->next->pprev = epb->pprev; | ||
703 | *epb->pprev = epb->next; | ||
704 | epb->pprev = NULL; | ||
705 | } | ||
706 | |||
707 | sctp_write_unlock(&head->lock); | 697 | sctp_write_unlock(&head->lock); |
708 | } | 698 | } |
709 | 699 | ||
@@ -721,12 +711,13 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l | |||
721 | struct sctp_hashbucket *head; | 711 | struct sctp_hashbucket *head; |
722 | struct sctp_ep_common *epb; | 712 | struct sctp_ep_common *epb; |
723 | struct sctp_endpoint *ep; | 713 | struct sctp_endpoint *ep; |
714 | struct hlist_node *node; | ||
724 | int hash; | 715 | int hash; |
725 | 716 | ||
726 | hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); | 717 | hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); |
727 | head = &sctp_ep_hashtable[hash]; | 718 | head = &sctp_ep_hashtable[hash]; |
728 | read_lock(&head->lock); | 719 | read_lock(&head->lock); |
729 | for (epb = head->chain; epb; epb = epb->next) { | 720 | sctp_for_each_hentry(epb, node, &head->chain) { |
730 | ep = sctp_ep(epb); | 721 | ep = sctp_ep(epb); |
731 | if (sctp_endpoint_is_match(ep, laddr)) | 722 | if (sctp_endpoint_is_match(ep, laddr)) |
732 | goto hit; | 723 | goto hit; |
@@ -744,7 +735,6 @@ hit: | |||
744 | /* Insert association into the hash table. */ | 735 | /* Insert association into the hash table. */ |
745 | static void __sctp_hash_established(struct sctp_association *asoc) | 736 | static void __sctp_hash_established(struct sctp_association *asoc) |
746 | { | 737 | { |
747 | struct sctp_ep_common **epp; | ||
748 | struct sctp_ep_common *epb; | 738 | struct sctp_ep_common *epb; |
749 | struct sctp_hashbucket *head; | 739 | struct sctp_hashbucket *head; |
750 | 740 | ||
@@ -756,12 +746,7 @@ static void __sctp_hash_established(struct sctp_association *asoc) | |||
756 | head = &sctp_assoc_hashtable[epb->hashent]; | 746 | head = &sctp_assoc_hashtable[epb->hashent]; |
757 | 747 | ||
758 | sctp_write_lock(&head->lock); | 748 | sctp_write_lock(&head->lock); |
759 | epp = &head->chain; | 749 | hlist_add_head(&epb->node, &head->chain); |
760 | epb->next = *epp; | ||
761 | if (epb->next) | ||
762 | (*epp)->pprev = &epb->next; | ||
763 | *epp = epb; | ||
764 | epb->pprev = epp; | ||
765 | sctp_write_unlock(&head->lock); | 750 | sctp_write_unlock(&head->lock); |
766 | } | 751 | } |
767 | 752 | ||
@@ -790,14 +775,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) | |||
790 | head = &sctp_assoc_hashtable[epb->hashent]; | 775 | head = &sctp_assoc_hashtable[epb->hashent]; |
791 | 776 | ||
792 | sctp_write_lock(&head->lock); | 777 | sctp_write_lock(&head->lock); |
793 | 778 | __hlist_del(&epb->node); | |
794 | if (epb->pprev) { | ||
795 | if (epb->next) | ||
796 | epb->next->pprev = epb->pprev; | ||
797 | *epb->pprev = epb->next; | ||
798 | epb->pprev = NULL; | ||
799 | } | ||
800 | |||
801 | sctp_write_unlock(&head->lock); | 779 | sctp_write_unlock(&head->lock); |
802 | } | 780 | } |
803 | 781 | ||
@@ -822,6 +800,7 @@ static struct sctp_association *__sctp_lookup_association( | |||
822 | struct sctp_ep_common *epb; | 800 | struct sctp_ep_common *epb; |
823 | struct sctp_association *asoc; | 801 | struct sctp_association *asoc; |
824 | struct sctp_transport *transport; | 802 | struct sctp_transport *transport; |
803 | struct hlist_node *node; | ||
825 | int hash; | 804 | int hash; |
826 | 805 | ||
827 | /* Optimize here for direct hit, only listening connections can | 806 | /* Optimize here for direct hit, only listening connections can |
@@ -830,7 +809,7 @@ static struct sctp_association *__sctp_lookup_association( | |||
830 | hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); | 809 | hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); |
831 | head = &sctp_assoc_hashtable[hash]; | 810 | head = &sctp_assoc_hashtable[hash]; |
832 | read_lock(&head->lock); | 811 | read_lock(&head->lock); |
833 | for (epb = head->chain; epb; epb = epb->next) { | 812 | sctp_for_each_hentry(epb, node, &head->chain) { |
834 | asoc = sctp_assoc(epb); | 813 | asoc = sctp_assoc(epb); |
835 | transport = sctp_assoc_is_match(asoc, local, peer); | 814 | transport = sctp_assoc_is_match(asoc, local, peer); |
836 | if (transport) | 815 | if (transport) |
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index f10fe7fbf24c..cf4b7eb023b3 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c | |||
@@ -90,6 +90,10 @@ void sctp_inq_free(struct sctp_inq *queue) | |||
90 | void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) | 90 | void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) |
91 | { | 91 | { |
92 | /* Directly call the packet handling routine. */ | 92 | /* Directly call the packet handling routine. */ |
93 | if (chunk->rcvr->dead) { | ||
94 | sctp_chunk_free(chunk); | ||
95 | return; | ||
96 | } | ||
93 | 97 | ||
94 | /* We are now calling this either from the soft interrupt | 98 | /* We are now calling this either from the soft interrupt |
95 | * or from the backlog processing. | 99 | * or from the backlog processing. |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 28f4fe77ceee..fa76f235169b 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -382,7 +382,7 @@ static void sctp_insert_list(struct list_head *head, struct list_head *new) | |||
382 | /* Mark all the eligible packets on a transport for retransmission. */ | 382 | /* Mark all the eligible packets on a transport for retransmission. */ |
383 | void sctp_retransmit_mark(struct sctp_outq *q, | 383 | void sctp_retransmit_mark(struct sctp_outq *q, |
384 | struct sctp_transport *transport, | 384 | struct sctp_transport *transport, |
385 | __u8 fast_retransmit) | 385 | __u8 reason) |
386 | { | 386 | { |
387 | struct list_head *lchunk, *ltemp; | 387 | struct list_head *lchunk, *ltemp; |
388 | struct sctp_chunk *chunk; | 388 | struct sctp_chunk *chunk; |
@@ -412,20 +412,20 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
412 | continue; | 412 | continue; |
413 | } | 413 | } |
414 | 414 | ||
415 | /* If we are doing retransmission due to a fast retransmit, | 415 | /* If we are doing retransmission due to a timeout or pmtu |
416 | * only the chunk's that are marked for fast retransmit | 416 | * discovery, only the chunks that are not yet acked should |
417 | * should be added to the retransmit queue. If we are doing | 417 | * be added to the retransmit queue. |
418 | * retransmission due to a timeout or pmtu discovery, only the | ||
419 | * chunks that are not yet acked should be added to the | ||
420 | * retransmit queue. | ||
421 | */ | 418 | */ |
422 | if ((fast_retransmit && (chunk->fast_retransmit > 0)) || | 419 | if ((reason == SCTP_RTXR_FAST_RTX && |
423 | (!fast_retransmit && !chunk->tsn_gap_acked)) { | 420 | (chunk->fast_retransmit > 0)) || |
421 | (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { | ||
424 | /* If this chunk was sent less then 1 rto ago, do not | 422 | /* If this chunk was sent less then 1 rto ago, do not |
425 | * retransmit this chunk, but give the peer time | 423 | * retransmit this chunk, but give the peer time |
426 | * to acknowlege it. | 424 | * to acknowlege it. Do this only when |
425 | * retransmitting due to T3 timeout. | ||
427 | */ | 426 | */ |
428 | if ((jiffies - chunk->sent_at) < transport->rto) | 427 | if (reason == SCTP_RTXR_T3_RTX && |
428 | (jiffies - chunk->sent_at) < transport->last_rto) | ||
429 | continue; | 429 | continue; |
430 | 430 | ||
431 | /* RFC 2960 6.2.1 Processing a Received SACK | 431 | /* RFC 2960 6.2.1 Processing a Received SACK |
@@ -467,10 +467,10 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
467 | } | 467 | } |
468 | } | 468 | } |
469 | 469 | ||
470 | SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, " | 470 | SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, " |
471 | "cwnd: %d, ssthresh: %d, flight_size: %d, " | 471 | "cwnd: %d, ssthresh: %d, flight_size: %d, " |
472 | "pba: %d\n", __FUNCTION__, | 472 | "pba: %d\n", __FUNCTION__, |
473 | transport, fast_retransmit, | 473 | transport, reason, |
474 | transport->cwnd, transport->ssthresh, | 474 | transport->cwnd, transport->ssthresh, |
475 | transport->flight_size, | 475 | transport->flight_size, |
476 | transport->partial_bytes_acked); | 476 | transport->partial_bytes_acked); |
@@ -484,7 +484,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, | |||
484 | sctp_retransmit_reason_t reason) | 484 | sctp_retransmit_reason_t reason) |
485 | { | 485 | { |
486 | int error = 0; | 486 | int error = 0; |
487 | __u8 fast_retransmit = 0; | ||
488 | 487 | ||
489 | switch(reason) { | 488 | switch(reason) { |
490 | case SCTP_RTXR_T3_RTX: | 489 | case SCTP_RTXR_T3_RTX: |
@@ -499,16 +498,18 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, | |||
499 | case SCTP_RTXR_FAST_RTX: | 498 | case SCTP_RTXR_FAST_RTX: |
500 | SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); | 499 | SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); |
501 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); | 500 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); |
502 | fast_retransmit = 1; | ||
503 | break; | 501 | break; |
504 | case SCTP_RTXR_PMTUD: | 502 | case SCTP_RTXR_PMTUD: |
505 | SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); | 503 | SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); |
506 | break; | 504 | break; |
505 | case SCTP_RTXR_T1_RTX: | ||
506 | SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS); | ||
507 | break; | ||
507 | default: | 508 | default: |
508 | BUG(); | 509 | BUG(); |
509 | } | 510 | } |
510 | 511 | ||
511 | sctp_retransmit_mark(q, transport, fast_retransmit); | 512 | sctp_retransmit_mark(q, transport, reason); |
512 | 513 | ||
513 | /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination, | 514 | /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination, |
514 | * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by | 515 | * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by |
@@ -641,7 +642,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
641 | 642 | ||
642 | /* If we are here due to a retransmit timeout or a fast | 643 | /* If we are here due to a retransmit timeout or a fast |
643 | * retransmit and if there are any chunks left in the retransmit | 644 | * retransmit and if there are any chunks left in the retransmit |
644 | * queue that could not fit in the PMTU sized packet, they need * to be marked as ineligible for a subsequent fast retransmit. | 645 | * queue that could not fit in the PMTU sized packet, they need |
646 | * to be marked as ineligible for a subsequent fast retransmit. | ||
645 | */ | 647 | */ |
646 | if (rtx_timeout && !lchunk) { | 648 | if (rtx_timeout && !lchunk) { |
647 | list_for_each(lchunk1, lqueue) { | 649 | list_for_each(lchunk1, lqueue) { |
@@ -660,10 +662,9 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
660 | int sctp_outq_uncork(struct sctp_outq *q) | 662 | int sctp_outq_uncork(struct sctp_outq *q) |
661 | { | 663 | { |
662 | int error = 0; | 664 | int error = 0; |
663 | if (q->cork) { | 665 | if (q->cork) |
664 | q->cork = 0; | 666 | q->cork = 0; |
665 | error = sctp_outq_flush(q, 0); | 667 | error = sctp_outq_flush(q, 0); |
666 | } | ||
667 | return error; | 668 | return error; |
668 | } | 669 | } |
669 | 670 | ||
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index e4cd841a22e4..249973204070 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -225,6 +225,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
225 | struct sctp_ep_common *epb; | 225 | struct sctp_ep_common *epb; |
226 | struct sctp_endpoint *ep; | 226 | struct sctp_endpoint *ep; |
227 | struct sock *sk; | 227 | struct sock *sk; |
228 | struct hlist_node *node; | ||
228 | int hash = *(loff_t *)v; | 229 | int hash = *(loff_t *)v; |
229 | 230 | ||
230 | if (hash >= sctp_ep_hashsize) | 231 | if (hash >= sctp_ep_hashsize) |
@@ -233,7 +234,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
233 | head = &sctp_ep_hashtable[hash]; | 234 | head = &sctp_ep_hashtable[hash]; |
234 | sctp_local_bh_disable(); | 235 | sctp_local_bh_disable(); |
235 | read_lock(&head->lock); | 236 | read_lock(&head->lock); |
236 | for (epb = head->chain; epb; epb = epb->next) { | 237 | sctp_for_each_hentry(epb, node, &head->chain) { |
237 | ep = sctp_ep(epb); | 238 | ep = sctp_ep(epb); |
238 | sk = epb->sk; | 239 | sk = epb->sk; |
239 | seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, | 240 | seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, |
@@ -328,6 +329,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
328 | struct sctp_ep_common *epb; | 329 | struct sctp_ep_common *epb; |
329 | struct sctp_association *assoc; | 330 | struct sctp_association *assoc; |
330 | struct sock *sk; | 331 | struct sock *sk; |
332 | struct hlist_node *node; | ||
331 | int hash = *(loff_t *)v; | 333 | int hash = *(loff_t *)v; |
332 | 334 | ||
333 | if (hash >= sctp_assoc_hashsize) | 335 | if (hash >= sctp_assoc_hashsize) |
@@ -336,7 +338,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
336 | head = &sctp_assoc_hashtable[hash]; | 338 | head = &sctp_assoc_hashtable[hash]; |
337 | sctp_local_bh_disable(); | 339 | sctp_local_bh_disable(); |
338 | read_lock(&head->lock); | 340 | read_lock(&head->lock); |
339 | for (epb = head->chain; epb; epb = epb->next) { | 341 | sctp_for_each_hentry(epb, node, &head->chain) { |
340 | assoc = sctp_assoc(epb); | 342 | assoc = sctp_assoc(epb); |
341 | sk = epb->sk; | 343 | sk = epb->sk; |
342 | seq_printf(seq, | 344 | seq_printf(seq, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 40c1a47d1b8d..d50f610d1b02 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1137,7 +1137,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1137 | } | 1137 | } |
1138 | for (i = 0; i < sctp_assoc_hashsize; i++) { | 1138 | for (i = 0; i < sctp_assoc_hashsize; i++) { |
1139 | rwlock_init(&sctp_assoc_hashtable[i].lock); | 1139 | rwlock_init(&sctp_assoc_hashtable[i].lock); |
1140 | sctp_assoc_hashtable[i].chain = NULL; | 1140 | INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain); |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | /* Allocate and initialize the endpoint hash table. */ | 1143 | /* Allocate and initialize the endpoint hash table. */ |
@@ -1151,7 +1151,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1151 | } | 1151 | } |
1152 | for (i = 0; i < sctp_ep_hashsize; i++) { | 1152 | for (i = 0; i < sctp_ep_hashsize; i++) { |
1153 | rwlock_init(&sctp_ep_hashtable[i].lock); | 1153 | rwlock_init(&sctp_ep_hashtable[i].lock); |
1154 | sctp_ep_hashtable[i].chain = NULL; | 1154 | INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | /* Allocate and initialize the SCTP port hash table. */ | 1157 | /* Allocate and initialize the SCTP port hash table. */ |
@@ -1170,7 +1170,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1170 | } | 1170 | } |
1171 | for (i = 0; i < sctp_port_hashsize; i++) { | 1171 | for (i = 0; i < sctp_port_hashsize; i++) { |
1172 | spin_lock_init(&sctp_port_hashtable[i].lock); | 1172 | spin_lock_init(&sctp_port_hashtable[i].lock); |
1173 | sctp_port_hashtable[i].chain = NULL; | 1173 | INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); |
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | printk(KERN_INFO "SCTP: Hash tables configured " | 1176 | printk(KERN_INFO "SCTP: Hash tables configured " |
@@ -1179,6 +1179,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1179 | 1179 | ||
1180 | /* Disable ADDIP by default. */ | 1180 | /* Disable ADDIP by default. */ |
1181 | sctp_addip_enable = 0; | 1181 | sctp_addip_enable = 0; |
1182 | sctp_addip_noauth = 0; | ||
1182 | 1183 | ||
1183 | /* Enable PR-SCTP by default. */ | 1184 | /* Enable PR-SCTP by default. */ |
1184 | sctp_prsctp_enable = 1; | 1185 | sctp_prsctp_enable = 1; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index c377e4e8f653..5a9783c38de1 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1788,9 +1788,14 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1788 | sizeof(sctp_paramhdr_t); | 1788 | sizeof(sctp_paramhdr_t); |
1789 | 1789 | ||
1790 | 1790 | ||
1791 | /* This is a fatal error. Any accumulated non-fatal errors are | ||
1792 | * not reported. | ||
1793 | */ | ||
1794 | if (*errp) | ||
1795 | sctp_chunk_free(*errp); | ||
1796 | |||
1791 | /* Create an error chunk and fill it in with our payload. */ | 1797 | /* Create an error chunk and fill it in with our payload. */ |
1792 | if (!*errp) | 1798 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); |
1793 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | ||
1794 | 1799 | ||
1795 | if (*errp) { | 1800 | if (*errp) { |
1796 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, | 1801 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, |
@@ -1813,9 +1818,15 @@ static int sctp_process_hn_param(const struct sctp_association *asoc, | |||
1813 | { | 1818 | { |
1814 | __u16 len = ntohs(param.p->length); | 1819 | __u16 len = ntohs(param.p->length); |
1815 | 1820 | ||
1816 | /* Make an ERROR chunk. */ | 1821 | /* Processing of the HOST_NAME parameter will generate an |
1817 | if (!*errp) | 1822 | * ABORT. If we've accumulated any non-fatal errors, they |
1818 | *errp = sctp_make_op_error_space(asoc, chunk, len); | 1823 | * would be unrecognized parameters and we should not include |
1824 | * them in the ABORT. | ||
1825 | */ | ||
1826 | if (*errp) | ||
1827 | sctp_chunk_free(*errp); | ||
1828 | |||
1829 | *errp = sctp_make_op_error_space(asoc, chunk, len); | ||
1819 | 1830 | ||
1820 | if (*errp) { | 1831 | if (*errp) { |
1821 | sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len); | 1832 | sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len); |
@@ -1847,7 +1858,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1847 | break; | 1858 | break; |
1848 | case SCTP_CID_ASCONF: | 1859 | case SCTP_CID_ASCONF: |
1849 | case SCTP_CID_ASCONF_ACK: | 1860 | case SCTP_CID_ASCONF_ACK: |
1850 | asoc->peer.addip_capable = 1; | 1861 | asoc->peer.asconf_capable = 1; |
1851 | break; | 1862 | break; |
1852 | default: | 1863 | default: |
1853 | break; | 1864 | break; |
@@ -1862,56 +1873,40 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1862 | * taken if the processing endpoint does not recognize the | 1873 | * taken if the processing endpoint does not recognize the |
1863 | * Parameter Type. | 1874 | * Parameter Type. |
1864 | * | 1875 | * |
1865 | * 00 - Stop processing this SCTP chunk and discard it, | 1876 | * 00 - Stop processing this parameter; do not process any further |
1866 | * do not process any further chunks within it. | 1877 | * parameters within this chunk |
1867 | * | 1878 | * |
1868 | * 01 - Stop processing this SCTP chunk and discard it, | 1879 | * 01 - Stop processing this parameter, do not process any further |
1869 | * do not process any further chunks within it, and report | 1880 | * parameters within this chunk, and report the unrecognized |
1870 | * the unrecognized parameter in an 'Unrecognized | 1881 | * parameter in an 'Unrecognized Parameter' ERROR chunk. |
1871 | * Parameter Type' (in either an ERROR or in the INIT ACK). | ||
1872 | * | 1882 | * |
1873 | * 10 - Skip this parameter and continue processing. | 1883 | * 10 - Skip this parameter and continue processing. |
1874 | * | 1884 | * |
1875 | * 11 - Skip this parameter and continue processing but | 1885 | * 11 - Skip this parameter and continue processing but |
1876 | * report the unrecognized parameter in an | 1886 | * report the unrecognized parameter in an |
1877 | * 'Unrecognized Parameter Type' (in either an ERROR or in | 1887 | * 'Unrecognized Parameter' ERROR chunk. |
1878 | * the INIT ACK). | ||
1879 | * | 1888 | * |
1880 | * Return value: | 1889 | * Return value: |
1881 | * 0 - discard the chunk | 1890 | * SCTP_IERROR_NO_ERROR - continue with the chunk |
1882 | * 1 - continue with the chunk | 1891 | * SCTP_IERROR_ERROR - stop and report an error. |
1892 | * SCTP_IERROR_NOMEME - out of memory. | ||
1883 | */ | 1893 | */ |
1884 | static int sctp_process_unk_param(const struct sctp_association *asoc, | 1894 | static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, |
1885 | union sctp_params param, | 1895 | union sctp_params param, |
1886 | struct sctp_chunk *chunk, | 1896 | struct sctp_chunk *chunk, |
1887 | struct sctp_chunk **errp) | 1897 | struct sctp_chunk **errp) |
1888 | { | 1898 | { |
1889 | int retval = 1; | 1899 | int retval = SCTP_IERROR_NO_ERROR; |
1890 | 1900 | ||
1891 | switch (param.p->type & SCTP_PARAM_ACTION_MASK) { | 1901 | switch (param.p->type & SCTP_PARAM_ACTION_MASK) { |
1892 | case SCTP_PARAM_ACTION_DISCARD: | 1902 | case SCTP_PARAM_ACTION_DISCARD: |
1893 | retval = 0; | 1903 | retval = SCTP_IERROR_ERROR; |
1894 | break; | ||
1895 | case SCTP_PARAM_ACTION_DISCARD_ERR: | ||
1896 | retval = 0; | ||
1897 | /* Make an ERROR chunk, preparing enough room for | ||
1898 | * returning multiple unknown parameters. | ||
1899 | */ | ||
1900 | if (NULL == *errp) | ||
1901 | *errp = sctp_make_op_error_space(asoc, chunk, | ||
1902 | ntohs(chunk->chunk_hdr->length)); | ||
1903 | |||
1904 | if (*errp) { | ||
1905 | sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, | ||
1906 | WORD_ROUND(ntohs(param.p->length))); | ||
1907 | sctp_addto_chunk(*errp, | ||
1908 | WORD_ROUND(ntohs(param.p->length)), | ||
1909 | param.v); | ||
1910 | } | ||
1911 | |||
1912 | break; | 1904 | break; |
1913 | case SCTP_PARAM_ACTION_SKIP: | 1905 | case SCTP_PARAM_ACTION_SKIP: |
1914 | break; | 1906 | break; |
1907 | case SCTP_PARAM_ACTION_DISCARD_ERR: | ||
1908 | retval = SCTP_IERROR_ERROR; | ||
1909 | /* Fall through */ | ||
1915 | case SCTP_PARAM_ACTION_SKIP_ERR: | 1910 | case SCTP_PARAM_ACTION_SKIP_ERR: |
1916 | /* Make an ERROR chunk, preparing enough room for | 1911 | /* Make an ERROR chunk, preparing enough room for |
1917 | * returning multiple unknown parameters. | 1912 | * returning multiple unknown parameters. |
@@ -1932,9 +1927,8 @@ static int sctp_process_unk_param(const struct sctp_association *asoc, | |||
1932 | * to the peer and the association won't be | 1927 | * to the peer and the association won't be |
1933 | * established. | 1928 | * established. |
1934 | */ | 1929 | */ |
1935 | retval = 0; | 1930 | retval = SCTP_IERROR_NOMEM; |
1936 | } | 1931 | } |
1937 | |||
1938 | break; | 1932 | break; |
1939 | default: | 1933 | default: |
1940 | break; | 1934 | break; |
@@ -1943,18 +1937,20 @@ static int sctp_process_unk_param(const struct sctp_association *asoc, | |||
1943 | return retval; | 1937 | return retval; |
1944 | } | 1938 | } |
1945 | 1939 | ||
1946 | /* Find unrecognized parameters in the chunk. | 1940 | /* Verify variable length parameters |
1947 | * Return values: | 1941 | * Return values: |
1948 | * 0 - discard the chunk | 1942 | * SCTP_IERROR_ABORT - trigger an ABORT |
1949 | * 1 - continue with the chunk | 1943 | * SCTP_IERROR_NOMEM - out of memory (abort) |
1944 | * SCTP_IERROR_ERROR - stop processing, trigger an ERROR | ||
1945 | * SCTP_IERROR_NO_ERROR - continue with the chunk | ||
1950 | */ | 1946 | */ |
1951 | static int sctp_verify_param(const struct sctp_association *asoc, | 1947 | static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, |
1952 | union sctp_params param, | 1948 | union sctp_params param, |
1953 | sctp_cid_t cid, | 1949 | sctp_cid_t cid, |
1954 | struct sctp_chunk *chunk, | 1950 | struct sctp_chunk *chunk, |
1955 | struct sctp_chunk **err_chunk) | 1951 | struct sctp_chunk **err_chunk) |
1956 | { | 1952 | { |
1957 | int retval = 1; | 1953 | int retval = SCTP_IERROR_NO_ERROR; |
1958 | 1954 | ||
1959 | /* FIXME - This routine is not looking at each parameter per the | 1955 | /* FIXME - This routine is not looking at each parameter per the |
1960 | * chunk type, i.e., unrecognized parameters should be further | 1956 | * chunk type, i.e., unrecognized parameters should be further |
@@ -1976,7 +1972,9 @@ static int sctp_verify_param(const struct sctp_association *asoc, | |||
1976 | 1972 | ||
1977 | case SCTP_PARAM_HOST_NAME_ADDRESS: | 1973 | case SCTP_PARAM_HOST_NAME_ADDRESS: |
1978 | /* Tell the peer, we won't support this param. */ | 1974 | /* Tell the peer, we won't support this param. */ |
1979 | return sctp_process_hn_param(asoc, param, chunk, err_chunk); | 1975 | sctp_process_hn_param(asoc, param, chunk, err_chunk); |
1976 | retval = SCTP_IERROR_ABORT; | ||
1977 | break; | ||
1980 | 1978 | ||
1981 | case SCTP_PARAM_FWD_TSN_SUPPORT: | 1979 | case SCTP_PARAM_FWD_TSN_SUPPORT: |
1982 | if (sctp_prsctp_enable) | 1980 | if (sctp_prsctp_enable) |
@@ -1993,9 +1991,11 @@ static int sctp_verify_param(const struct sctp_association *asoc, | |||
1993 | * cause 'Protocol Violation'. | 1991 | * cause 'Protocol Violation'. |
1994 | */ | 1992 | */ |
1995 | if (SCTP_AUTH_RANDOM_LENGTH != | 1993 | if (SCTP_AUTH_RANDOM_LENGTH != |
1996 | ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) | 1994 | ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) { |
1997 | return sctp_process_inv_paramlength(asoc, param.p, | 1995 | sctp_process_inv_paramlength(asoc, param.p, |
1998 | chunk, err_chunk); | 1996 | chunk, err_chunk); |
1997 | retval = SCTP_IERROR_ABORT; | ||
1998 | } | ||
1999 | break; | 1999 | break; |
2000 | 2000 | ||
2001 | case SCTP_PARAM_CHUNKS: | 2001 | case SCTP_PARAM_CHUNKS: |
@@ -2007,9 +2007,11 @@ static int sctp_verify_param(const struct sctp_association *asoc, | |||
2007 | * INIT-ACK chunk if the sender wants to receive authenticated | 2007 | * INIT-ACK chunk if the sender wants to receive authenticated |
2008 | * chunks. Its maximum length is 260 bytes. | 2008 | * chunks. Its maximum length is 260 bytes. |
2009 | */ | 2009 | */ |
2010 | if (260 < ntohs(param.p->length)) | 2010 | if (260 < ntohs(param.p->length)) { |
2011 | return sctp_process_inv_paramlength(asoc, param.p, | 2011 | sctp_process_inv_paramlength(asoc, param.p, |
2012 | chunk, err_chunk); | 2012 | chunk, err_chunk); |
2013 | retval = SCTP_IERROR_ABORT; | ||
2014 | } | ||
2013 | break; | 2015 | break; |
2014 | 2016 | ||
2015 | case SCTP_PARAM_HMAC_ALGO: | 2017 | case SCTP_PARAM_HMAC_ALGO: |
@@ -2020,8 +2022,7 @@ fallthrough: | |||
2020 | default: | 2022 | default: |
2021 | SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", | 2023 | SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", |
2022 | ntohs(param.p->type), cid); | 2024 | ntohs(param.p->type), cid); |
2023 | return sctp_process_unk_param(asoc, param, chunk, err_chunk); | 2025 | retval = sctp_process_unk_param(asoc, param, chunk, err_chunk); |
2024 | |||
2025 | break; | 2026 | break; |
2026 | } | 2027 | } |
2027 | return retval; | 2028 | return retval; |
@@ -2036,6 +2037,7 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2036 | { | 2037 | { |
2037 | union sctp_params param; | 2038 | union sctp_params param; |
2038 | int has_cookie = 0; | 2039 | int has_cookie = 0; |
2040 | int result; | ||
2039 | 2041 | ||
2040 | /* Verify stream values are non-zero. */ | 2042 | /* Verify stream values are non-zero. */ |
2041 | if ((0 == peer_init->init_hdr.num_outbound_streams) || | 2043 | if ((0 == peer_init->init_hdr.num_outbound_streams) || |
@@ -2043,8 +2045,7 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2043 | (0 == peer_init->init_hdr.init_tag) || | 2045 | (0 == peer_init->init_hdr.init_tag) || |
2044 | (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) { | 2046 | (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) { |
2045 | 2047 | ||
2046 | sctp_process_inv_mandatory(asoc, chunk, errp); | 2048 | return sctp_process_inv_mandatory(asoc, chunk, errp); |
2047 | return 0; | ||
2048 | } | 2049 | } |
2049 | 2050 | ||
2050 | /* Check for missing mandatory parameters. */ | 2051 | /* Check for missing mandatory parameters. */ |
@@ -2062,29 +2063,29 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2062 | * VIOLATION error. We build the ERROR chunk here and let the normal | 2063 | * VIOLATION error. We build the ERROR chunk here and let the normal |
2063 | * error handling code build and send the packet. | 2064 | * error handling code build and send the packet. |
2064 | */ | 2065 | */ |
2065 | if (param.v != (void*)chunk->chunk_end) { | 2066 | if (param.v != (void*)chunk->chunk_end) |
2066 | sctp_process_inv_paramlength(asoc, param.p, chunk, errp); | 2067 | return sctp_process_inv_paramlength(asoc, param.p, chunk, errp); |
2067 | return 0; | ||
2068 | } | ||
2069 | 2068 | ||
2070 | /* The only missing mandatory param possible today is | 2069 | /* The only missing mandatory param possible today is |
2071 | * the state cookie for an INIT-ACK chunk. | 2070 | * the state cookie for an INIT-ACK chunk. |
2072 | */ | 2071 | */ |
2073 | if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) { | 2072 | if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) |
2074 | sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE, | 2073 | return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE, |
2075 | chunk, errp); | 2074 | chunk, errp); |
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2079 | /* Find unrecognized parameters. */ | ||
2080 | 2075 | ||
2076 | /* Verify all the variable length parameters */ | ||
2081 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2077 | sctp_walk_params(param, peer_init, init_hdr.params) { |
2082 | 2078 | ||
2083 | if (!sctp_verify_param(asoc, param, cid, chunk, errp)) { | 2079 | result = sctp_verify_param(asoc, param, cid, chunk, errp); |
2084 | if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type) | 2080 | switch (result) { |
2081 | case SCTP_IERROR_ABORT: | ||
2082 | case SCTP_IERROR_NOMEM: | ||
2085 | return 0; | 2083 | return 0; |
2086 | else | 2084 | case SCTP_IERROR_ERROR: |
2087 | return 1; | 2085 | return 1; |
2086 | case SCTP_IERROR_NO_ERROR: | ||
2087 | default: | ||
2088 | break; | ||
2088 | } | 2089 | } |
2089 | 2090 | ||
2090 | } /* for (loop through all parameters) */ | 2091 | } /* for (loop through all parameters) */ |
@@ -2137,11 +2138,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
2137 | 2138 | ||
2138 | /* If the peer claims support for ADD-IP without support | 2139 | /* If the peer claims support for ADD-IP without support |
2139 | * for AUTH, disable support for ADD-IP. | 2140 | * for AUTH, disable support for ADD-IP. |
2141 | * Do this only if backward compatible mode is turned off. | ||
2140 | */ | 2142 | */ |
2141 | if (asoc->peer.addip_capable && !asoc->peer.auth_capable) { | 2143 | if (!sctp_addip_noauth && |
2144 | (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) { | ||
2142 | asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP | | 2145 | asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP | |
2143 | SCTP_PARAM_DEL_IP | | 2146 | SCTP_PARAM_DEL_IP | |
2144 | SCTP_PARAM_SET_PRIMARY); | 2147 | SCTP_PARAM_SET_PRIMARY); |
2148 | asoc->peer.asconf_capable = 0; | ||
2145 | } | 2149 | } |
2146 | 2150 | ||
2147 | /* Walk list of transports, removing transports in the UNKNOWN state. */ | 2151 | /* Walk list of transports, removing transports in the UNKNOWN state. */ |
@@ -2848,10 +2852,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, | |||
2848 | 2852 | ||
2849 | __be16 err_code; | 2853 | __be16 err_code; |
2850 | int length = 0; | 2854 | int length = 0; |
2851 | int chunk_len = asconf->skb->len; | 2855 | int chunk_len; |
2852 | __u32 serial; | 2856 | __u32 serial; |
2853 | int all_param_pass = 1; | 2857 | int all_param_pass = 1; |
2854 | 2858 | ||
2859 | chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); | ||
2855 | hdr = (sctp_addiphdr_t *)asconf->skb->data; | 2860 | hdr = (sctp_addiphdr_t *)asconf->skb->data; |
2856 | serial = ntohl(hdr->serial); | 2861 | serial = ntohl(hdr->serial); |
2857 | 2862 | ||
@@ -2952,13 +2957,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
2952 | /* This is always done in BH context with a socket lock | 2957 | /* This is always done in BH context with a socket lock |
2953 | * held, so the list can not change. | 2958 | * held, so the list can not change. |
2954 | */ | 2959 | */ |
2960 | local_bh_disable(); | ||
2955 | list_for_each_entry(saddr, &bp->address_list, list) { | 2961 | list_for_each_entry(saddr, &bp->address_list, list) { |
2956 | if (sctp_cmp_addr_exact(&saddr->a, &addr)) | 2962 | if (sctp_cmp_addr_exact(&saddr->a, &addr)) |
2957 | saddr->use_as_src = 1; | 2963 | saddr->use_as_src = 1; |
2958 | } | 2964 | } |
2965 | local_bh_enable(); | ||
2959 | break; | 2966 | break; |
2960 | case SCTP_PARAM_DEL_IP: | 2967 | case SCTP_PARAM_DEL_IP: |
2961 | retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh); | 2968 | local_bh_disable(); |
2969 | retval = sctp_del_bind_addr(bp, &addr); | ||
2970 | local_bh_enable(); | ||
2962 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 2971 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
2963 | transport = list_entry(pos, struct sctp_transport, | 2972 | transport = list_entry(pos, struct sctp_transport, |
2964 | transports); | 2973 | transports); |
@@ -2990,7 +2999,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, | |||
2990 | sctp_addip_param_t *asconf_ack_param; | 2999 | sctp_addip_param_t *asconf_ack_param; |
2991 | sctp_errhdr_t *err_param; | 3000 | sctp_errhdr_t *err_param; |
2992 | int length; | 3001 | int length; |
2993 | int asconf_ack_len = asconf_ack->skb->len; | 3002 | int asconf_ack_len; |
2994 | __be16 err_code; | 3003 | __be16 err_code; |
2995 | 3004 | ||
2996 | if (no_err) | 3005 | if (no_err) |
@@ -2998,6 +3007,9 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, | |||
2998 | else | 3007 | else |
2999 | err_code = SCTP_ERROR_REQ_REFUSED; | 3008 | err_code = SCTP_ERROR_REQ_REFUSED; |
3000 | 3009 | ||
3010 | asconf_ack_len = ntohs(asconf_ack->chunk_hdr->length) - | ||
3011 | sizeof(sctp_chunkhdr_t); | ||
3012 | |||
3001 | /* Skip the addiphdr from the asconf_ack chunk and store a pointer to | 3013 | /* Skip the addiphdr from the asconf_ack chunk and store a pointer to |
3002 | * the first asconf_ack parameter. | 3014 | * the first asconf_ack parameter. |
3003 | */ | 3015 | */ |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bbdc938da86f..78d1a8a49bd0 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -453,6 +453,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
453 | * maximum value discussed in rule C7 above (RTO.max) may be | 453 | * maximum value discussed in rule C7 above (RTO.max) may be |
454 | * used to provide an upper bound to this doubling operation. | 454 | * used to provide an upper bound to this doubling operation. |
455 | */ | 455 | */ |
456 | transport->last_rto = transport->rto; | ||
456 | transport->rto = min((transport->rto * 2), transport->asoc->rto_max); | 457 | transport->rto = min((transport->rto * 2), transport->asoc->rto_max); |
457 | } | 458 | } |
458 | 459 | ||
@@ -1267,6 +1268,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1267 | sctp_ootb_pkt_free(packet); | 1268 | sctp_ootb_pkt_free(packet); |
1268 | break; | 1269 | break; |
1269 | 1270 | ||
1271 | case SCTP_CMD_T1_RETRAN: | ||
1272 | /* Mark a transport for retransmission. */ | ||
1273 | sctp_retransmit(&asoc->outqueue, cmd->obj.transport, | ||
1274 | SCTP_RTXR_T1_RTX); | ||
1275 | break; | ||
1276 | |||
1270 | case SCTP_CMD_RETRAN: | 1277 | case SCTP_CMD_RETRAN: |
1271 | /* Mark a transport for retransmission. */ | 1278 | /* Mark a transport for retransmission. */ |
1272 | sctp_retransmit(&asoc->outqueue, cmd->obj.transport, | 1279 | sctp_retransmit(&asoc->outqueue, cmd->obj.transport, |
@@ -1393,7 +1400,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1393 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 1400 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
1394 | t = list_entry(pos, struct sctp_transport, | 1401 | t = list_entry(pos, struct sctp_transport, |
1395 | transports); | 1402 | transports); |
1396 | sctp_retransmit_mark(&asoc->outqueue, t, 0); | 1403 | sctp_retransmit_mark(&asoc->outqueue, t, |
1404 | SCTP_RTXR_T1_RTX); | ||
1397 | } | 1405 | } |
1398 | 1406 | ||
1399 | sctp_add_cmd_sf(commands, | 1407 | sctp_add_cmd_sf(commands, |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f01b408508ff..5ebbe808d801 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -2305,7 +2305,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
2305 | /* If we've sent any data bundled with COOKIE-ECHO we will need to | 2305 | /* If we've sent any data bundled with COOKIE-ECHO we will need to |
2306 | * resend | 2306 | * resend |
2307 | */ | 2307 | */ |
2308 | sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, | 2308 | sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN, |
2309 | SCTP_TRANSPORT(asoc->peer.primary_path)); | 2309 | SCTP_TRANSPORT(asoc->peer.primary_path)); |
2310 | 2310 | ||
2311 | /* Cast away the const modifier, as we want to just | 2311 | /* Cast away the const modifier, as we want to just |
@@ -4064,11 +4064,6 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4064 | struct sctp_chunk *chunk = arg; | 4064 | struct sctp_chunk *chunk = arg; |
4065 | struct sctp_chunk *abort = NULL; | 4065 | struct sctp_chunk *abort = NULL; |
4066 | 4066 | ||
4067 | /* Make the abort chunk. */ | ||
4068 | abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); | ||
4069 | if (!abort) | ||
4070 | goto nomem; | ||
4071 | |||
4072 | /* SCTP-AUTH, Section 6.3: | 4067 | /* SCTP-AUTH, Section 6.3: |
4073 | * It should be noted that if the receiver wants to tear | 4068 | * It should be noted that if the receiver wants to tear |
4074 | * down an association in an authenticated way only, the | 4069 | * down an association in an authenticated way only, the |
@@ -4083,6 +4078,11 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4083 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) | 4078 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
4084 | goto discard; | 4079 | goto discard; |
4085 | 4080 | ||
4081 | /* Make the abort chunk. */ | ||
4082 | abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); | ||
4083 | if (!abort) | ||
4084 | goto nomem; | ||
4085 | |||
4086 | if (asoc) { | 4086 | if (asoc) { |
4087 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | 4087 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
4088 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 4088 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a7ecf3159e53..ff8bc95670ed 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) | |||
660 | * socket routing and failover schemes. Refer to comments in | 660 | * socket routing and failover schemes. Refer to comments in |
661 | * sctp_do_bind(). -daisy | 661 | * sctp_do_bind(). -daisy |
662 | */ | 662 | */ |
663 | retval = sctp_del_bind_addr(bp, sa_addr, call_rcu); | 663 | retval = sctp_del_bind_addr(bp, sa_addr); |
664 | 664 | ||
665 | addr_buf += af->sockaddr_len; | 665 | addr_buf += af->sockaddr_len; |
666 | err_bindx_rem: | 666 | err_bindx_rem: |
@@ -5307,6 +5307,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5307 | { | 5307 | { |
5308 | struct sctp_bind_hashbucket *head; /* hash list */ | 5308 | struct sctp_bind_hashbucket *head; /* hash list */ |
5309 | struct sctp_bind_bucket *pp; /* hash list port iterator */ | 5309 | struct sctp_bind_bucket *pp; /* hash list port iterator */ |
5310 | struct hlist_node *node; | ||
5310 | unsigned short snum; | 5311 | unsigned short snum; |
5311 | int ret; | 5312 | int ret; |
5312 | 5313 | ||
@@ -5331,7 +5332,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5331 | index = sctp_phashfn(rover); | 5332 | index = sctp_phashfn(rover); |
5332 | head = &sctp_port_hashtable[index]; | 5333 | head = &sctp_port_hashtable[index]; |
5333 | sctp_spin_lock(&head->lock); | 5334 | sctp_spin_lock(&head->lock); |
5334 | for (pp = head->chain; pp; pp = pp->next) | 5335 | sctp_for_each_hentry(pp, node, &head->chain) |
5335 | if (pp->port == rover) | 5336 | if (pp->port == rover) |
5336 | goto next; | 5337 | goto next; |
5337 | break; | 5338 | break; |
@@ -5358,7 +5359,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5358 | */ | 5359 | */ |
5359 | head = &sctp_port_hashtable[sctp_phashfn(snum)]; | 5360 | head = &sctp_port_hashtable[sctp_phashfn(snum)]; |
5360 | sctp_spin_lock(&head->lock); | 5361 | sctp_spin_lock(&head->lock); |
5361 | for (pp = head->chain; pp; pp = pp->next) { | 5362 | sctp_for_each_hentry(pp, node, &head->chain) { |
5362 | if (pp->port == snum) | 5363 | if (pp->port == snum) |
5363 | goto pp_found; | 5364 | goto pp_found; |
5364 | } | 5365 | } |
@@ -5702,10 +5703,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
5702 | pp->port = snum; | 5703 | pp->port = snum; |
5703 | pp->fastreuse = 0; | 5704 | pp->fastreuse = 0; |
5704 | INIT_HLIST_HEAD(&pp->owner); | 5705 | INIT_HLIST_HEAD(&pp->owner); |
5705 | if ((pp->next = head->chain) != NULL) | 5706 | hlist_add_head(&pp->node, &head->chain); |
5706 | pp->next->pprev = &pp->next; | ||
5707 | head->chain = pp; | ||
5708 | pp->pprev = &head->chain; | ||
5709 | } | 5707 | } |
5710 | return pp; | 5708 | return pp; |
5711 | } | 5709 | } |
@@ -5714,9 +5712,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
5714 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) | 5712 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) |
5715 | { | 5713 | { |
5716 | if (pp && hlist_empty(&pp->owner)) { | 5714 | if (pp && hlist_empty(&pp->owner)) { |
5717 | if (pp->next) | 5715 | __hlist_del(&pp->node); |
5718 | pp->next->pprev = pp->pprev; | ||
5719 | *(pp->pprev) = pp->next; | ||
5720 | kmem_cache_free(sctp_bucket_cachep, pp); | 5716 | kmem_cache_free(sctp_bucket_cachep, pp); |
5721 | SCTP_DBG_OBJCNT_DEC(bind_bucket); | 5717 | SCTP_DBG_OBJCNT_DEC(bind_bucket); |
5722 | } | 5718 | } |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 0669778e4335..da4f15734fb1 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -263,6 +263,15 @@ static ctl_table sctp_table[] = { | |||
263 | .proc_handler = &proc_dointvec, | 263 | .proc_handler = &proc_dointvec, |
264 | .strategy = &sysctl_intvec | 264 | .strategy = &sysctl_intvec |
265 | }, | 265 | }, |
266 | { | ||
267 | .ctl_name = CTL_UNNUMBERED, | ||
268 | .procname = "addip_noauth_enable", | ||
269 | .data = &sctp_addip_noauth, | ||
270 | .maxlen = sizeof(int), | ||
271 | .mode = 0644, | ||
272 | .proc_handler = &proc_dointvec, | ||
273 | .strategy = &sysctl_intvec | ||
274 | }, | ||
266 | { .ctl_name = 0 } | 275 | { .ctl_name = 0 } |
267 | }; | 276 | }; |
268 | 277 | ||
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 5f467c914f80..d55ce83a020b 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -74,8 +74,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
74 | * given destination transport address, set RTO to the protocol | 74 | * given destination transport address, set RTO to the protocol |
75 | * parameter 'RTO.Initial'. | 75 | * parameter 'RTO.Initial'. |
76 | */ | 76 | */ |
77 | peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial); | ||
77 | peer->rtt = 0; | 78 | peer->rtt = 0; |
78 | peer->rto = msecs_to_jiffies(sctp_rto_initial); | ||
79 | peer->rttvar = 0; | 79 | peer->rttvar = 0; |
80 | peer->srtt = 0; | 80 | peer->srtt = 0; |
81 | peer->rto_pending = 0; | 81 | peer->rto_pending = 0; |
@@ -385,6 +385,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) | |||
385 | tp->rto = tp->asoc->rto_max; | 385 | tp->rto = tp->asoc->rto_max; |
386 | 386 | ||
387 | tp->rtt = rtt; | 387 | tp->rtt = rtt; |
388 | tp->last_rto = tp->rto; | ||
388 | 389 | ||
389 | /* Reset rto_pending so that a new RTT measurement is started when a | 390 | /* Reset rto_pending so that a new RTT measurement is started when a |
390 | * new data chunk is sent. | 391 | * new data chunk is sent. |
@@ -578,7 +579,7 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
578 | */ | 579 | */ |
579 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); | 580 | t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); |
580 | t->ssthresh = asoc->peer.i.a_rwnd; | 581 | t->ssthresh = asoc->peer.i.a_rwnd; |
581 | t->rto = asoc->rto_initial; | 582 | t->last_rto = t->rto = asoc->rto_initial; |
582 | t->rtt = 0; | 583 | t->rtt = 0; |
583 | t->srtt = 0; | 584 | t->srtt = 0; |
584 | t->rttvar = 0; | 585 | t->rttvar = 0; |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 4be92d0a2cab..4908041ffb31 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -862,7 +862,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) | |||
862 | continue; | 862 | continue; |
863 | 863 | ||
864 | /* see if this ssn has been marked by skipping */ | 864 | /* see if this ssn has been marked by skipping */ |
865 | if (!SSN_lt(cssn, sctp_ssn_peek(in, csid))) | 865 | if (!SSN_lte(cssn, sctp_ssn_peek(in, csid))) |
866 | break; | 866 | break; |
867 | 867 | ||
868 | __skb_unlink(pos, &ulpq->lobby); | 868 | __skb_unlink(pos, &ulpq->lobby); |