diff options
author | Frank Filz <ffilzlnx@us.ibm.com> | 2005-06-20 16:14:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-06-20 16:14:57 -0400 |
commit | 3f7a87d2fa9b42f7aade43914f060df68cc89cc7 (patch) | |
tree | 15162d2dd770428f98a0d39f8dc6063aba0ad1e6 /net/sctp | |
parent | 8b22c249e7de453961e4d253b19fc2a0bdd65d53 (diff) |
[SCTP] sctp_connectx() API support
Implements sctp_connectx() as defined in the SCTP sockets API draft by
tunneling the request through a setsockopt().
Signed-off-by: Frank Filz <ffilzlnx@us.ibm.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 151 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 1 | ||||
-rw-r--r-- | net/sctp/input.c | 2 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 11 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 20 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 105 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 148 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 6 | ||||
-rw-r--r-- | net/sctp/socket.c | 405 | ||||
-rw-r--r-- | net/sctp/transport.c | 4 |
10 files changed, 615 insertions, 238 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 663843d97a92..7ae6aa772dab 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; | 191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; |
192 | asoc->unack_data = 0; | 192 | asoc->unack_data = 0; |
193 | 193 | ||
194 | SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n", | ||
195 | asoc->ep->debug_name, | ||
196 | asoc->ctsn_ack_point); | ||
197 | |||
198 | /* ADDIP Section 4.1 Asconf Chunk Procedures | 194 | /* ADDIP Section 4.1 Asconf Chunk Procedures |
199 | * | 195 | * |
200 | * When an endpoint has an ASCONF signaled change to be sent to the | 196 | * When an endpoint has an ASCONF signaled change to be sent to the |
@@ -211,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
211 | 207 | ||
212 | /* Make an empty list of remote transport addresses. */ | 208 | /* Make an empty list of remote transport addresses. */ |
213 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); | 209 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); |
210 | asoc->peer.transport_count = 0; | ||
214 | 211 | ||
215 | /* RFC 2960 5.1 Normal Establishment of an Association | 212 | /* RFC 2960 5.1 Normal Establishment of an Association |
216 | * | 213 | * |
@@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, | |||
288 | 285 | ||
289 | asoc->base.malloced = 1; | 286 | asoc->base.malloced = 1; |
290 | SCTP_DBG_OBJCNT_INC(assoc); | 287 | SCTP_DBG_OBJCNT_INC(assoc); |
288 | SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc); | ||
291 | 289 | ||
292 | return asoc; | 290 | return asoc; |
293 | 291 | ||
@@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc) | |||
356 | sctp_transport_free(transport); | 354 | sctp_transport_free(transport); |
357 | } | 355 | } |
358 | 356 | ||
357 | asoc->peer.transport_count = 0; | ||
358 | |||
359 | /* Free any cached ASCONF_ACK chunk. */ | 359 | /* Free any cached ASCONF_ACK chunk. */ |
360 | if (asoc->addip_last_asconf_ack) | 360 | if (asoc->addip_last_asconf_ack) |
361 | sctp_chunk_free(asoc->addip_last_asconf_ack); | 361 | sctp_chunk_free(asoc->addip_last_asconf_ack); |
@@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
400 | /* If the primary path is changing, assume that the | 400 | /* If the primary path is changing, assume that the |
401 | * user wants to use this new path. | 401 | * user wants to use this new path. |
402 | */ | 402 | */ |
403 | if (transport->active) | 403 | if (transport->state != SCTP_INACTIVE) |
404 | asoc->peer.active_path = transport; | 404 | asoc->peer.active_path = transport; |
405 | 405 | ||
406 | /* | 406 | /* |
@@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; | 428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* Remove a transport from an association. */ | ||
432 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
433 | struct sctp_transport *peer) | ||
434 | { | ||
435 | struct list_head *pos; | ||
436 | struct sctp_transport *transport; | ||
437 | |||
438 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", | ||
439 | " port: %d\n", | ||
440 | asoc, | ||
441 | (&peer->ipaddr), | ||
442 | peer->ipaddr.v4.sin_port); | ||
443 | |||
444 | /* If we are to remove the current retran_path, update it | ||
445 | * to the next peer before removing this peer from the list. | ||
446 | */ | ||
447 | if (asoc->peer.retran_path == peer) | ||
448 | sctp_assoc_update_retran_path(asoc); | ||
449 | |||
450 | /* Remove this peer from the list. */ | ||
451 | list_del(&peer->transports); | ||
452 | |||
453 | /* Get the first transport of asoc. */ | ||
454 | pos = asoc->peer.transport_addr_list.next; | ||
455 | transport = list_entry(pos, struct sctp_transport, transports); | ||
456 | |||
457 | /* Update any entries that match the peer to be deleted. */ | ||
458 | if (asoc->peer.primary_path == peer) | ||
459 | sctp_assoc_set_primary(asoc, transport); | ||
460 | if (asoc->peer.active_path == peer) | ||
461 | asoc->peer.active_path = transport; | ||
462 | if (asoc->peer.last_data_from == peer) | ||
463 | asoc->peer.last_data_from = transport; | ||
464 | |||
465 | /* If we remove the transport an INIT was last sent to, set it to | ||
466 | * NULL. Combined with the update of the retran path above, this | ||
467 | * will cause the next INIT to be sent to the next available | ||
468 | * transport, maintaining the cycle. | ||
469 | */ | ||
470 | if (asoc->init_last_sent_to == peer) | ||
471 | asoc->init_last_sent_to = NULL; | ||
472 | |||
473 | asoc->peer.transport_count--; | ||
474 | |||
475 | sctp_transport_free(peer); | ||
476 | } | ||
477 | |||
431 | /* Add a transport address to an association. */ | 478 | /* Add a transport address to an association. */ |
432 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | 479 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, |
433 | const union sctp_addr *addr, | 480 | const union sctp_addr *addr, |
434 | int gfp) | 481 | const int gfp, |
482 | const int peer_state) | ||
435 | { | 483 | { |
436 | struct sctp_transport *peer; | 484 | struct sctp_transport *peer; |
437 | struct sctp_sock *sp; | 485 | struct sctp_sock *sp; |
@@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
442 | /* AF_INET and AF_INET6 share common port field. */ | 490 | /* AF_INET and AF_INET6 share common port field. */ |
443 | port = addr->v4.sin_port; | 491 | port = addr->v4.sin_port; |
444 | 492 | ||
493 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", | ||
494 | " port: %d state:%s\n", | ||
495 | asoc, | ||
496 | addr, | ||
497 | addr->v4.sin_port, | ||
498 | peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE"); | ||
499 | |||
445 | /* Set the port if it has not been set yet. */ | 500 | /* Set the port if it has not been set yet. */ |
446 | if (0 == asoc->peer.port) | 501 | if (0 == asoc->peer.port) |
447 | asoc->peer.port = port; | 502 | asoc->peer.port = port; |
448 | 503 | ||
449 | /* Check to see if this is a duplicate. */ | 504 | /* Check to see if this is a duplicate. */ |
450 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 505 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
451 | if (peer) | 506 | if (peer) { |
507 | if (peer_state == SCTP_ACTIVE && | ||
508 | peer->state == SCTP_UNKNOWN) | ||
509 | peer->state = SCTP_ACTIVE; | ||
452 | return peer; | 510 | return peer; |
511 | } | ||
453 | 512 | ||
454 | peer = sctp_transport_new(addr, gfp); | 513 | peer = sctp_transport_new(addr, gfp); |
455 | if (!peer) | 514 | if (!peer) |
@@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
516 | /* Set the transport's RTO.initial value */ | 575 | /* Set the transport's RTO.initial value */ |
517 | peer->rto = asoc->rto_initial; | 576 | peer->rto = asoc->rto_initial; |
518 | 577 | ||
578 | /* Set the peer's active state. */ | ||
579 | peer->state = peer_state; | ||
580 | |||
519 | /* Attach the remote transport to our asoc. */ | 581 | /* Attach the remote transport to our asoc. */ |
520 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); | 582 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); |
583 | asoc->peer.transport_count++; | ||
521 | 584 | ||
522 | /* If we do not yet have a primary path, set one. */ | 585 | /* If we do not yet have a primary path, set one. */ |
523 | if (!asoc->peer.primary_path) { | 586 | if (!asoc->peer.primary_path) { |
@@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
525 | asoc->peer.retran_path = peer; | 588 | asoc->peer.retran_path = peer; |
526 | } | 589 | } |
527 | 590 | ||
528 | if (asoc->peer.active_path == asoc->peer.retran_path) | 591 | if (asoc->peer.active_path == asoc->peer.retran_path) { |
529 | asoc->peer.retran_path = peer; | 592 | asoc->peer.retran_path = peer; |
593 | } | ||
530 | 594 | ||
531 | return peer; | 595 | return peer; |
532 | } | 596 | } |
@@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, | |||
537 | { | 601 | { |
538 | struct list_head *pos; | 602 | struct list_head *pos; |
539 | struct list_head *temp; | 603 | struct list_head *temp; |
540 | struct sctp_transport *peer = NULL; | ||
541 | struct sctp_transport *transport; | 604 | struct sctp_transport *transport; |
542 | 605 | ||
543 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 606 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
544 | transport = list_entry(pos, struct sctp_transport, transports); | 607 | transport = list_entry(pos, struct sctp_transport, transports); |
545 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { | 608 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { |
546 | peer = transport; | 609 | /* Do book keeping for removing the peer and free it. */ |
547 | list_del(pos); | 610 | sctp_assoc_rm_peer(asoc, transport); |
548 | break; | 611 | break; |
549 | } | 612 | } |
550 | } | 613 | } |
551 | |||
552 | /* The address we want delete is not in the association. */ | ||
553 | if (!peer) | ||
554 | return; | ||
555 | |||
556 | /* Get the first transport of asoc. */ | ||
557 | pos = asoc->peer.transport_addr_list.next; | ||
558 | transport = list_entry(pos, struct sctp_transport, transports); | ||
559 | |||
560 | /* Update any entries that match the peer to be deleted. */ | ||
561 | if (asoc->peer.primary_path == peer) | ||
562 | sctp_assoc_set_primary(asoc, transport); | ||
563 | if (asoc->peer.active_path == peer) | ||
564 | asoc->peer.active_path = transport; | ||
565 | if (asoc->peer.retran_path == peer) | ||
566 | asoc->peer.retran_path = transport; | ||
567 | if (asoc->peer.last_data_from == peer) | ||
568 | asoc->peer.last_data_from = transport; | ||
569 | |||
570 | sctp_transport_free(peer); | ||
571 | } | 614 | } |
572 | 615 | ||
573 | /* Lookup a transport by address. */ | 616 | /* Lookup a transport by address. */ |
@@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
608 | /* Record the transition on the transport. */ | 651 | /* Record the transition on the transport. */ |
609 | switch (command) { | 652 | switch (command) { |
610 | case SCTP_TRANSPORT_UP: | 653 | case SCTP_TRANSPORT_UP: |
611 | transport->active = SCTP_ACTIVE; | 654 | transport->state = SCTP_ACTIVE; |
612 | spc_state = SCTP_ADDR_AVAILABLE; | 655 | spc_state = SCTP_ADDR_AVAILABLE; |
613 | break; | 656 | break; |
614 | 657 | ||
615 | case SCTP_TRANSPORT_DOWN: | 658 | case SCTP_TRANSPORT_DOWN: |
616 | transport->active = SCTP_INACTIVE; | 659 | transport->state = SCTP_INACTIVE; |
617 | spc_state = SCTP_ADDR_UNREACHABLE; | 660 | spc_state = SCTP_ADDR_UNREACHABLE; |
618 | break; | 661 | break; |
619 | 662 | ||
@@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
643 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 686 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
644 | t = list_entry(pos, struct sctp_transport, transports); | 687 | t = list_entry(pos, struct sctp_transport, transports); |
645 | 688 | ||
646 | if (!t->active) | 689 | if (t->state == SCTP_INACTIVE) |
647 | continue; | 690 | continue; |
648 | if (!first || t->last_time_heard > first->last_time_heard) { | 691 | if (!first || t->last_time_heard > first->last_time_heard) { |
649 | second = first; | 692 | second = first; |
@@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
663 | * [If the primary is active but not most recent, bump the most | 706 | * [If the primary is active but not most recent, bump the most |
664 | * recently used transport.] | 707 | * recently used transport.] |
665 | */ | 708 | */ |
666 | if (asoc->peer.primary_path->active && | 709 | if (asoc->peer.primary_path->state != SCTP_INACTIVE && |
667 | first != asoc->peer.primary_path) { | 710 | first != asoc->peer.primary_path) { |
668 | second = first; | 711 | second = first; |
669 | first = asoc->peer.primary_path; | 712 | first = asoc->peer.primary_path; |
@@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
958 | transports); | 1001 | transports); |
959 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) | 1002 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) |
960 | sctp_assoc_add_peer(asoc, &trans->ipaddr, | 1003 | sctp_assoc_add_peer(asoc, &trans->ipaddr, |
961 | GFP_ATOMIC); | 1004 | GFP_ATOMIC, SCTP_ACTIVE); |
962 | } | 1005 | } |
963 | 1006 | ||
964 | asoc->ctsn_ack_point = asoc->next_tsn - 1; | 1007 | asoc->ctsn_ack_point = asoc->next_tsn - 1; |
@@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
998 | 1041 | ||
999 | /* Try to find an active transport. */ | 1042 | /* Try to find an active transport. */ |
1000 | 1043 | ||
1001 | if (t->active) { | 1044 | if (t->state != SCTP_INACTIVE) { |
1002 | break; | 1045 | break; |
1003 | } else { | 1046 | } else { |
1004 | /* Keep track of the next transport in case | 1047 | /* Keep track of the next transport in case |
@@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1019 | } | 1062 | } |
1020 | 1063 | ||
1021 | asoc->peer.retran_path = t; | 1064 | asoc->peer.retran_path = t; |
1065 | |||
1066 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1067 | " %p addr: ", | ||
1068 | " port: %d\n", | ||
1069 | asoc, | ||
1070 | (&t->ipaddr), | ||
1071 | t->ipaddr.v4.sin_port); | ||
1072 | } | ||
1073 | |||
1074 | /* Choose the transport for sending a INIT packet. */ | ||
1075 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
1076 | struct sctp_association *asoc) | ||
1077 | { | ||
1078 | struct sctp_transport *t; | ||
1079 | |||
1080 | /* Use the retran path. If the last INIT was sent over the | ||
1081 | * retran path, update the retran path and use it. | ||
1082 | */ | ||
1083 | if (!asoc->init_last_sent_to) { | ||
1084 | t = asoc->peer.active_path; | ||
1085 | } else { | ||
1086 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
1087 | sctp_assoc_update_retran_path(asoc); | ||
1088 | t = asoc->peer.retran_path; | ||
1089 | } | ||
1090 | |||
1091 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1092 | " %p addr: ", | ||
1093 | " port: %d\n", | ||
1094 | asoc, | ||
1095 | (&t->ipaddr), | ||
1096 | t->ipaddr.v4.sin_port); | ||
1097 | |||
1098 | return t; | ||
1022 | } | 1099 | } |
1023 | 1100 | ||
1024 | /* Choose the transport for sending a SHUTDOWN packet. */ | 1101 | /* Choose the transport for sending a SHUTDOWN packet. */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 334f61773e6d..2ec0320fac3b 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
134 | ep->last_key = ep->current_key = 0; | 134 | ep->last_key = ep->current_key = 0; |
135 | ep->key_changed_at = jiffies; | 135 | ep->key_changed_at = jiffies; |
136 | 136 | ||
137 | ep->debug_name = "unnamedEndpoint"; | ||
138 | return ep; | 137 | return ep; |
139 | } | 138 | } |
140 | 139 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index fffc880a646d..339f7acfdb64 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -353,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
353 | 353 | ||
354 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 354 | sctp_do_sm(SCTP_EVENT_T_OTHER, |
355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), |
356 | asoc->state, asoc->ep, asoc, NULL, | 356 | asoc->state, asoc->ep, asoc, t, |
357 | GFP_ATOMIC); | 357 | GFP_ATOMIC); |
358 | 358 | ||
359 | } | 359 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1b2d4adc4ddb..4eb81a1407b7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
682 | 682 | ||
683 | if (!new_transport) { | 683 | if (!new_transport) { |
684 | new_transport = asoc->peer.active_path; | 684 | new_transport = asoc->peer.active_path; |
685 | } else if (!new_transport->active) { | 685 | } else if (new_transport->state == SCTP_INACTIVE) { |
686 | /* If the chunk is Heartbeat or Heartbeat Ack, | 686 | /* If the chunk is Heartbeat or Heartbeat Ack, |
687 | * send it to chunk->transport, even if it's | 687 | * send it to chunk->transport, even if it's |
688 | * inactive. | 688 | * inactive. |
689 | * | 689 | * |
690 | * 3.3.6 Heartbeat Acknowledgement: | 690 | * 3.3.6 Heartbeat Acknowledgement: |
@@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
840 | * Otherwise, we want to use the active path. | 840 | * Otherwise, we want to use the active path. |
841 | */ | 841 | */ |
842 | new_transport = chunk->transport; | 842 | new_transport = chunk->transport; |
843 | if (!new_transport || !new_transport->active) | 843 | if (!new_transport || |
844 | new_transport->state == SCTP_INACTIVE) | ||
844 | new_transport = asoc->peer.active_path; | 845 | new_transport = asoc->peer.active_path; |
845 | 846 | ||
846 | /* Change packets if necessary. */ | 847 | /* Change packets if necessary. */ |
@@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1454 | /* Mark the destination transport address as | 1455 | /* Mark the destination transport address as |
1455 | * active if it is not so marked. | 1456 | * active if it is not so marked. |
1456 | */ | 1457 | */ |
1457 | if (!transport->active) { | 1458 | if (transport->state == SCTP_INACTIVE) { |
1458 | sctp_assoc_control_transport( | 1459 | sctp_assoc_control_transport( |
1459 | transport->asoc, | 1460 | transport->asoc, |
1460 | transport, | 1461 | transport, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 33ac8bf47b0e..5baed9bb7de5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1830 | * be a a better choice than any of the embedded addresses. | 1830 | * be a a better choice than any of the embedded addresses. |
1831 | */ | 1831 | */ |
1832 | if (peer_addr) | 1832 | if (peer_addr) |
1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp)) | 1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
1834 | goto nomem; | 1834 | goto nomem; |
1835 | 1835 | ||
1836 | /* Process the initialization parameters. */ | 1836 | /* Process the initialization parameters. */ |
@@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1841 | goto clean_up; | 1841 | goto clean_up; |
1842 | } | 1842 | } |
1843 | 1843 | ||
1844 | /* Walk list of transports, removing transports in the UNKNOWN state. */ | ||
1845 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | ||
1846 | transport = list_entry(pos, struct sctp_transport, transports); | ||
1847 | if (transport->state == SCTP_UNKNOWN) { | ||
1848 | sctp_assoc_rm_peer(asoc, transport); | ||
1849 | } | ||
1850 | } | ||
1851 | |||
1844 | /* The fixed INIT headers are always in network byte | 1852 | /* The fixed INIT headers are always in network byte |
1845 | * order. | 1853 | * order. |
1846 | */ | 1854 | */ |
@@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
1906 | * stream sequence number shall be set to 0. | 1914 | * stream sequence number shall be set to 0. |
1907 | */ | 1915 | */ |
1908 | 1916 | ||
1909 | /* Allocate storage for the negotiated streams if it is not a temporary * association. | 1917 | /* Allocate storage for the negotiated streams if it is not a temporary |
1918 | * association. | ||
1910 | */ | 1919 | */ |
1911 | if (!asoc->temp) { | 1920 | if (!asoc->temp) { |
1912 | int assoc_id; | 1921 | int assoc_id; |
@@ -1952,6 +1961,9 @@ clean_up: | |||
1952 | list_del_init(pos); | 1961 | list_del_init(pos); |
1953 | sctp_transport_free(transport); | 1962 | sctp_transport_free(transport); |
1954 | } | 1963 | } |
1964 | |||
1965 | asoc->peer.transport_count = 0; | ||
1966 | |||
1955 | nomem: | 1967 | nomem: |
1956 | return 0; | 1968 | return 0; |
1957 | } | 1969 | } |
@@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
1995 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); | 2007 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); |
1996 | scope = sctp_scope(peer_addr); | 2008 | scope = sctp_scope(peer_addr); |
1997 | if (sctp_in_scope(&addr, scope)) | 2009 | if (sctp_in_scope(&addr, scope)) |
1998 | if (!sctp_assoc_add_peer(asoc, &addr, gfp)) | 2010 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE)) |
1999 | return 0; | 2011 | return 0; |
2000 | break; | 2012 | break; |
2001 | 2013 | ||
@@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2396 | * Due to Resource Shortage'. | 2408 | * Due to Resource Shortage'. |
2397 | */ | 2409 | */ |
2398 | 2410 | ||
2399 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC); | 2411 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE); |
2400 | if (!peer) | 2412 | if (!peer) |
2401 | return SCTP_ERROR_RSRC_LOW; | 2413 | return SCTP_ERROR_RSRC_LOW; |
2402 | 2414 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index f65fa441952f..778639db125a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
414 | */ | 414 | */ |
415 | asoc->overall_error_count++; | 415 | asoc->overall_error_count++; |
416 | 416 | ||
417 | if (transport->active && | 417 | if (transport->state != SCTP_INACTIVE && |
418 | (transport->error_count++ >= transport->max_retrans)) { | 418 | (transport->error_count++ >= transport->max_retrans)) { |
419 | SCTP_DEBUG_PRINTK("transport_strike: transport " | 419 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
420 | "IP:%d.%d.%d.%d failed.\n", | 420 | " transport IP: port:%d failed.\n", |
421 | NIPQUAD(transport->ipaddr.v4.sin_addr)); | 421 | asoc, |
422 | (&transport->ipaddr), | ||
423 | transport->ipaddr.v4.sin_port); | ||
422 | sctp_assoc_control_transport(asoc, transport, | 424 | sctp_assoc_control_transport(asoc, transport, |
423 | SCTP_TRANSPORT_DOWN, | 425 | SCTP_TRANSPORT_DOWN, |
424 | SCTP_FAILED_THRESHOLD); | 426 | SCTP_FAILED_THRESHOLD); |
@@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
593 | /* Mark the destination transport address as active if it is not so | 595 | /* Mark the destination transport address as active if it is not so |
594 | * marked. | 596 | * marked. |
595 | */ | 597 | */ |
596 | if (!t->active) | 598 | if (t->state == SCTP_INACTIVE) |
597 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 599 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
598 | SCTP_HEARTBEAT_SUCCESS); | 600 | SCTP_HEARTBEAT_SUCCESS); |
599 | 601 | ||
@@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
665 | 667 | ||
666 | asoc->state = state; | 668 | asoc->state = state; |
667 | 669 | ||
670 | SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n", | ||
671 | asoc, sctp_state_tbl[state]); | ||
672 | |||
668 | if (sctp_style(sk, TCP)) { | 673 | if (sctp_style(sk, TCP)) { |
669 | /* Change the sk->sk_state of a TCP-style socket that has | 674 | /* Change the sk->sk_state of a TCP-style socket that has |
670 | * sucessfully completed a connect() call. | 675 | * sucessfully completed a connect() call. |
671 | */ | 676 | */ |
672 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 677 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
@@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
678 | sk->sk_shutdown |= RCV_SHUTDOWN; | 683 | sk->sk_shutdown |= RCV_SHUTDOWN; |
679 | } | 684 | } |
680 | 685 | ||
686 | if (sctp_state(asoc, COOKIE_WAIT)) { | ||
687 | /* Reset init timeouts since they may have been | ||
688 | * increased due to timer expirations. | ||
689 | */ | ||
690 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
691 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]; | ||
692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
693 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]; | ||
694 | } | ||
695 | |||
681 | if (sctp_state(asoc, ESTABLISHED) || | 696 | if (sctp_state(asoc, ESTABLISHED) || |
682 | sctp_state(asoc, CLOSED) || | 697 | sctp_state(asoc, CLOSED) || |
683 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { | 698 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { |
@@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1120 | * to be executed only during failed attempts of | 1135 | * to be executed only during failed attempts of |
1121 | * association establishment. | 1136 | * association establishment. |
1122 | */ | 1137 | */ |
1123 | if ((asoc->peer.retran_path != | 1138 | if ((asoc->peer.retran_path != |
1124 | asoc->peer.primary_path) && | 1139 | asoc->peer.primary_path) && |
1125 | (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) { | 1140 | (asoc->init_err_counter > 0)) { |
1126 | sctp_add_cmd_sf(commands, | 1141 | sctp_add_cmd_sf(commands, |
1127 | SCTP_CMD_FORCE_PRIM_RETRAN, | 1142 | SCTP_CMD_FORCE_PRIM_RETRAN, |
1128 | SCTP_NULL()); | 1143 | SCTP_NULL()); |
1129 | } | 1144 | } |
@@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1237 | sctp_association_put(asoc); | 1252 | sctp_association_put(asoc); |
1238 | break; | 1253 | break; |
1239 | 1254 | ||
1255 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | ||
1256 | chunk = cmd->obj.ptr; | ||
1257 | t = sctp_assoc_choose_init_transport(asoc); | ||
1258 | asoc->init_last_sent_to = t; | ||
1259 | chunk->transport = t; | ||
1260 | t->init_sent_count++; | ||
1261 | break; | ||
1262 | |||
1240 | case SCTP_CMD_INIT_RESTART: | 1263 | case SCTP_CMD_INIT_RESTART: |
1241 | /* Do the needed accounting and updates | 1264 | /* Do the needed accounting and updates |
1242 | * associated with restarting an initialization | 1265 | * associated with restarting an initialization |
1243 | * timer. | 1266 | * timer. Only multiply the timeout by two if |
1267 | * all transports have been tried at the current | ||
1268 | * timeout. | ||
1269 | */ | ||
1270 | t = asoc->init_last_sent_to; | ||
1271 | asoc->init_err_counter++; | ||
1272 | |||
1273 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
1274 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
1275 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
1276 | asoc->max_init_timeo) { | ||
1277 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
1278 | asoc->max_init_timeo; | ||
1279 | } | ||
1280 | asoc->init_cycle++; | ||
1281 | SCTP_DEBUG_PRINTK( | ||
1282 | "T1 INIT Timeout adjustment" | ||
1283 | " init_err_counter: %d" | ||
1284 | " cycle: %d" | ||
1285 | " timeout: %d\n", | ||
1286 | asoc->init_err_counter, | ||
1287 | asoc->init_cycle, | ||
1288 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
1289 | } | ||
1290 | |||
1291 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | ||
1292 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
1293 | break; | ||
1294 | |||
1295 | case SCTP_CMD_COOKIEECHO_RESTART: | ||
1296 | /* Do the needed accounting and updates | ||
1297 | * associated with restarting an initialization | ||
1298 | * timer. Only multiply the timeout by two if | ||
1299 | * all transports have been tried at the current | ||
1300 | * timeout. | ||
1244 | */ | 1301 | */ |
1245 | asoc->counters[SCTP_COUNTER_INIT_ERROR]++; | 1302 | asoc->init_err_counter++; |
1246 | asoc->timeouts[cmd->obj.to] *= 2; | 1303 | |
1247 | if (asoc->timeouts[cmd->obj.to] > | 1304 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; |
1305 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
1248 | asoc->max_init_timeo) { | 1306 | asoc->max_init_timeo) { |
1249 | asoc->timeouts[cmd->obj.to] = | 1307 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = |
1250 | asoc->max_init_timeo; | 1308 | asoc->max_init_timeo; |
1251 | } | 1309 | } |
1310 | SCTP_DEBUG_PRINTK( | ||
1311 | "T1 COOKIE Timeout adjustment" | ||
1312 | " init_err_counter: %d" | ||
1313 | " timeout: %d\n", | ||
1314 | asoc->init_err_counter, | ||
1315 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
1252 | 1316 | ||
1253 | /* If we've sent any data bundled with | 1317 | /* If we've sent any data bundled with |
1254 | * COOKIE-ECHO we need to resend. | 1318 | * COOKIE-ECHO we need to resend. |
@@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1261 | 1325 | ||
1262 | sctp_add_cmd_sf(commands, | 1326 | sctp_add_cmd_sf(commands, |
1263 | SCTP_CMD_TIMER_RESTART, | 1327 | SCTP_CMD_TIMER_RESTART, |
1264 | SCTP_TO(cmd->obj.to)); | 1328 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
1265 | break; | 1329 | break; |
1266 | 1330 | ||
1267 | case SCTP_CMD_INIT_FAILED: | 1331 | case SCTP_CMD_INIT_FAILED: |
@@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1273 | subtype, chunk, cmd->obj.u32); | 1337 | subtype, chunk, cmd->obj.u32); |
1274 | break; | 1338 | break; |
1275 | 1339 | ||
1276 | case SCTP_CMD_COUNTER_INC: | 1340 | case SCTP_CMD_INIT_COUNTER_INC: |
1277 | asoc->counters[cmd->obj.counter]++; | 1341 | asoc->init_err_counter++; |
1278 | break; | 1342 | break; |
1279 | 1343 | ||
1280 | case SCTP_CMD_COUNTER_RESET: | 1344 | case SCTP_CMD_INIT_COUNTER_RESET: |
1281 | asoc->counters[cmd->obj.counter] = 0; | 1345 | asoc->init_err_counter = 0; |
1346 | asoc->init_cycle = 0; | ||
1282 | break; | 1347 | break; |
1283 | 1348 | ||
1284 | case SCTP_CMD_REPORT_DUP: | 1349 | case SCTP_CMD_REPORT_DUP: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8e01b8f09ac2..058189684c7c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -533,6 +533,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, | 533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, |
534 | SCTP_PEER_INIT(initchunk)); | 534 | SCTP_PEER_INIT(initchunk)); |
535 | 535 | ||
536 | /* Reset init error count upon receipt of INIT-ACK. */ | ||
537 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); | ||
538 | |||
536 | /* 5.1 C) "A" shall stop the T1-init timer and leave | 539 | /* 5.1 C) "A" shall stop the T1-init timer and leave |
537 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie | 540 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie |
538 | * timer, and enter the COOKIE-ECHOED state. | 541 | * timer, and enter the COOKIE-ECHOED state. |
@@ -775,8 +778,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
775 | * from the COOKIE-ECHOED state to the COOKIE-WAIT | 778 | * from the COOKIE-ECHOED state to the COOKIE-WAIT |
776 | * state is performed. | 779 | * state is performed. |
777 | */ | 780 | */ |
778 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET, | 781 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); |
779 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
780 | 782 | ||
781 | /* RFC 2960 5.1 Normal Establishment of an Association | 783 | /* RFC 2960 5.1 Normal Establishment of an Association |
782 | * | 784 | * |
@@ -1019,10 +1021,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1019 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); | 1021 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); |
1020 | 1022 | ||
1021 | /* This should never happen, but lets log it if so. */ | 1023 | /* This should never happen, but lets log it if so. */ |
1022 | if (!link) { | 1024 | if (unlikely(!link)) { |
1023 | printk(KERN_WARNING | 1025 | if (from_addr.sa.sa_family == AF_INET6) { |
1024 | "%s: Could not find address %d.%d.%d.%d\n", | 1026 | printk(KERN_WARNING |
1025 | __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr)); | 1027 | "%s association %p could not find address " |
1028 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
1029 | __FUNCTION__, | ||
1030 | asoc, | ||
1031 | NIP6(from_addr.v6.sin6_addr)); | ||
1032 | } else { | ||
1033 | printk(KERN_WARNING | ||
1034 | "%s association %p could not find address " | ||
1035 | "%u.%u.%u.%u\n", | ||
1036 | __FUNCTION__, | ||
1037 | asoc, | ||
1038 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | ||
1039 | } | ||
1026 | return SCTP_DISPOSITION_DISCARD; | 1040 | return SCTP_DISPOSITION_DISCARD; |
1027 | } | 1041 | } |
1028 | 1042 | ||
@@ -2095,9 +2109,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
2095 | sctp_errhdr_t *err; | 2109 | sctp_errhdr_t *err; |
2096 | struct sctp_chunk *reply; | 2110 | struct sctp_chunk *reply; |
2097 | struct sctp_bind_addr *bp; | 2111 | struct sctp_bind_addr *bp; |
2098 | int attempts; | 2112 | int attempts = asoc->init_err_counter + 1; |
2099 | |||
2100 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
2101 | 2113 | ||
2102 | if (attempts >= asoc->max_init_attempts) { | 2114 | if (attempts >= asoc->max_init_attempts) { |
2103 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2115 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
@@ -2157,8 +2169,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
2157 | /* Cast away the const modifier, as we want to just | 2169 | /* Cast away the const modifier, as we want to just |
2158 | * rerun it through as a sideffect. | 2170 | * rerun it through as a sideffect. |
2159 | */ | 2171 | */ |
2160 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC, | 2172 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL()); |
2161 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
2162 | 2173 | ||
2163 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2174 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2164 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 2175 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
@@ -2281,8 +2292,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2281 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2292 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2282 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2293 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2283 | 2294 | ||
2284 | sctp_stop_t1_and_abort(commands, error); | 2295 | return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); |
2285 | return SCTP_DISPOSITION_ABORT; | ||
2286 | } | 2296 | } |
2287 | 2297 | ||
2288 | /* | 2298 | /* |
@@ -2294,8 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
2294 | void *arg, | 2304 | void *arg, |
2295 | sctp_cmd_seq_t *commands) | 2305 | sctp_cmd_seq_t *commands) |
2296 | { | 2306 | { |
2297 | sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR); | 2307 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, |
2298 | return SCTP_DISPOSITION_ABORT; | 2308 | (struct sctp_transport *)arg); |
2299 | } | 2309 | } |
2300 | 2310 | ||
2301 | /* | 2311 | /* |
@@ -2318,8 +2328,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
2318 | * | 2328 | * |
2319 | * This is common code called by several sctp_sf_*_abort() functions above. | 2329 | * This is common code called by several sctp_sf_*_abort() functions above. |
2320 | */ | 2330 | */ |
2321 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | 2331 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
2332 | __u16 error, | ||
2333 | const struct sctp_association *asoc, | ||
2334 | struct sctp_transport *transport) | ||
2322 | { | 2335 | { |
2336 | SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); | ||
2323 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 2337 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
2324 | SCTP_STATE(SCTP_STATE_CLOSED)); | 2338 | SCTP_STATE(SCTP_STATE_CLOSED)); |
2325 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2339 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -2328,6 +2342,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | |||
2328 | /* CMD_INIT_FAILED will DELETE_TCB. */ | 2342 | /* CMD_INIT_FAILED will DELETE_TCB. */ |
2329 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2343 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
2330 | SCTP_U32(error)); | 2344 | SCTP_U32(error)); |
2345 | return SCTP_DISPOSITION_ABORT; | ||
2331 | } | 2346 | } |
2332 | 2347 | ||
2333 | /* | 2348 | /* |
@@ -3805,6 +3820,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, | |||
3805 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, | 3820 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, |
3806 | SCTP_ASOC((struct sctp_association *) asoc)); | 3821 | SCTP_ASOC((struct sctp_association *) asoc)); |
3807 | 3822 | ||
3823 | /* Choose transport for INIT. */ | ||
3824 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
3825 | SCTP_CHUNK(repl)); | ||
3826 | |||
3808 | /* After sending the INIT, "A" starts the T1-init timer and | 3827 | /* After sending the INIT, "A" starts the T1-init timer and |
3809 | * enters the COOKIE-WAIT state. | 3828 | * enters the COOKIE-WAIT state. |
3810 | */ | 3829 | */ |
@@ -4589,7 +4608,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
4589 | } | 4608 | } |
4590 | 4609 | ||
4591 | /* | 4610 | /* |
4592 | * sctp_sf_t1_timer_expire | 4611 | * sctp_sf_t1_init_timer_expire |
4593 | * | 4612 | * |
4594 | * Section: 4 Note: 2 | 4613 | * Section: 4 Note: 2 |
4595 | * Verification Tag: | 4614 | * Verification Tag: |
@@ -4603,7 +4622,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
4603 | * endpoint MUST abort the initialization process and report the | 4622 | * endpoint MUST abort the initialization process and report the |
4604 | * error to SCTP user. | 4623 | * error to SCTP user. |
4605 | * | 4624 | * |
4606 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | 4625 | * Outputs |
4626 | * (timers, events) | ||
4627 | * | ||
4628 | */ | ||
4629 | sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | ||
4630 | const struct sctp_association *asoc, | ||
4631 | const sctp_subtype_t type, | ||
4632 | void *arg, | ||
4633 | sctp_cmd_seq_t *commands) | ||
4634 | { | ||
4635 | struct sctp_chunk *repl = NULL; | ||
4636 | struct sctp_bind_addr *bp; | ||
4637 | int attempts = asoc->init_err_counter + 1; | ||
4638 | |||
4639 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); | ||
4640 | |||
4641 | if (attempts < asoc->max_init_attempts) { | ||
4642 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
4643 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
4644 | if (!repl) | ||
4645 | return SCTP_DISPOSITION_NOMEM; | ||
4646 | |||
4647 | /* Choose transport for INIT. */ | ||
4648 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
4649 | SCTP_CHUNK(repl)); | ||
4650 | |||
4651 | /* Issue a sideeffect to do the needed accounting. */ | ||
4652 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | ||
4653 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
4654 | |||
4655 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
4656 | } else { | ||
4657 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" | ||
4658 | " max_init_attempts: %d\n", | ||
4659 | attempts, asoc->max_init_attempts); | ||
4660 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | ||
4661 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | ||
4662 | return SCTP_DISPOSITION_DELETE_TCB; | ||
4663 | } | ||
4664 | |||
4665 | return SCTP_DISPOSITION_CONSUME; | ||
4666 | } | ||
4667 | |||
4668 | /* | ||
4669 | * sctp_sf_t1_cookie_timer_expire | ||
4670 | * | ||
4671 | * Section: 4 Note: 2 | ||
4672 | * Verification Tag: | ||
4673 | * Inputs | ||
4674 | * (endpoint, asoc) | ||
4675 | * | ||
4676 | * RFC 2960 Section 4 Notes | ||
4677 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | ||
4607 | * COOKIE ECHO and re-start the T1-cookie timer without changing | 4678 | * COOKIE ECHO and re-start the T1-cookie timer without changing |
4608 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. | 4679 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. |
4609 | * After that, the endpoint MUST abort the initialization process and | 4680 | * After that, the endpoint MUST abort the initialization process and |
@@ -4613,46 +4684,26 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
4613 | * (timers, events) | 4684 | * (timers, events) |
4614 | * | 4685 | * |
4615 | */ | 4686 | */ |
4616 | sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | 4687 | sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep, |
4617 | const struct sctp_association *asoc, | 4688 | const struct sctp_association *asoc, |
4618 | const sctp_subtype_t type, | 4689 | const sctp_subtype_t type, |
4619 | void *arg, | 4690 | void *arg, |
4620 | sctp_cmd_seq_t *commands) | 4691 | sctp_cmd_seq_t *commands) |
4621 | { | 4692 | { |
4622 | struct sctp_chunk *repl; | 4693 | struct sctp_chunk *repl = NULL; |
4623 | struct sctp_bind_addr *bp; | 4694 | int attempts = asoc->init_err_counter + 1; |
4624 | sctp_event_timeout_t timer = (sctp_event_timeout_t) arg; | ||
4625 | int timeout; | ||
4626 | int attempts; | ||
4627 | |||
4628 | timeout = asoc->timeouts[timer]; | ||
4629 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
4630 | repl = NULL; | ||
4631 | 4695 | ||
4632 | SCTP_DEBUG_PRINTK("Timer T1 expired.\n"); | 4696 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); |
4633 | 4697 | ||
4634 | if (attempts < asoc->max_init_attempts) { | 4698 | if (attempts < asoc->max_init_attempts) { |
4635 | switch (timer) { | 4699 | repl = sctp_make_cookie_echo(asoc, NULL); |
4636 | case SCTP_EVENT_TIMEOUT_T1_INIT: | ||
4637 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
4638 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
4639 | break; | ||
4640 | |||
4641 | case SCTP_EVENT_TIMEOUT_T1_COOKIE: | ||
4642 | repl = sctp_make_cookie_echo(asoc, NULL); | ||
4643 | break; | ||
4644 | |||
4645 | default: | ||
4646 | BUG(); | ||
4647 | break; | ||
4648 | }; | ||
4649 | |||
4650 | if (!repl) | 4700 | if (!repl) |
4651 | goto nomem; | 4701 | return SCTP_DISPOSITION_NOMEM; |
4652 | 4702 | ||
4653 | /* Issue a sideeffect to do the needed accounting. */ | 4703 | /* Issue a sideeffect to do the needed accounting. */ |
4654 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | 4704 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, |
4655 | SCTP_TO(timer)); | 4705 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
4706 | |||
4656 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 4707 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
4657 | } else { | 4708 | } else { |
4658 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4709 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
@@ -4661,9 +4712,6 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | |||
4661 | } | 4712 | } |
4662 | 4713 | ||
4663 | return SCTP_DISPOSITION_CONSUME; | 4714 | return SCTP_DISPOSITION_CONSUME; |
4664 | |||
4665 | nomem: | ||
4666 | return SCTP_DISPOSITION_NOMEM; | ||
4667 | } | 4715 | } |
4668 | 4716 | ||
4669 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN | 4717 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 8967846f69e8..75ef10408764 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
783 | /* SCTP_STATE_COOKIE_WAIT */ \ | 783 | /* SCTP_STATE_COOKIE_WAIT */ \ |
784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ | 784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ |
785 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 785 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
786 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 786 | {.fn = sctp_sf_t1_cookie_timer_expire, \ |
787 | .name = "sctp_sf_t1_cookie_timer_expire"}, \ | ||
787 | /* SCTP_STATE_ESTABLISHED */ \ | 788 | /* SCTP_STATE_ESTABLISHED */ \ |
788 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 789 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
789 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 790 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
@@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
802 | /* SCTP_STATE_CLOSED */ \ | 803 | /* SCTP_STATE_CLOSED */ \ |
803 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 804 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
804 | /* SCTP_STATE_COOKIE_WAIT */ \ | 805 | /* SCTP_STATE_COOKIE_WAIT */ \ |
805 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 806 | {.fn = sctp_sf_t1_init_timer_expire, \ |
807 | .name = "sctp_sf_t1_init_timer_expire"}, \ | ||
806 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 808 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
807 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 809 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
808 | /* SCTP_STATE_ESTABLISHED */ \ | 810 | /* SCTP_STATE_ESTABLISHED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e6926cb19420..aad55dc3792b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, | |||
262 | * sockaddr_in6 [RFC 2553]), | 262 | * sockaddr_in6 [RFC 2553]), |
263 | * addr_len - the size of the address structure. | 263 | * addr_len - the size of the address structure. |
264 | */ | 264 | */ |
265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) |
266 | { | 266 | { |
267 | int retval = 0; | 267 | int retval = 0; |
268 | 268 | ||
269 | sctp_lock_sock(sk); | 269 | sctp_lock_sock(sk); |
270 | 270 | ||
271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n", | 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n", |
272 | sk, uaddr, addr_len); | 272 | sk, addr, addr_len); |
273 | 273 | ||
274 | /* Disallow binding twice. */ | 274 | /* Disallow binding twice. */ |
275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) | 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) |
276 | retval = sctp_do_bind(sk, (union sctp_addr *)uaddr, | 276 | retval = sctp_do_bind(sk, (union sctp_addr *)addr, |
277 | addr_len); | 277 | addr_len); |
278 | else | 278 | else |
279 | retval = -EINVAL; | 279 | retval = -EINVAL; |
@@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
318 | unsigned short snum; | 318 | unsigned short snum; |
319 | int ret = 0; | 319 | int ret = 0; |
320 | 320 | ||
321 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n", | ||
322 | sk, addr, len); | ||
323 | |||
324 | /* Common sockaddr verification. */ | 321 | /* Common sockaddr verification. */ |
325 | af = sctp_sockaddr_af(sp, addr, len); | 322 | af = sctp_sockaddr_af(sp, addr, len); |
326 | if (!af) | 323 | if (!af) { |
324 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n", | ||
325 | sk, addr, len); | ||
327 | return -EINVAL; | 326 | return -EINVAL; |
327 | } | ||
328 | |||
329 | snum = ntohs(addr->v4.sin_port); | ||
330 | |||
331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ", | ||
332 | ", port: %d, new port: %d, len: %d)\n", | ||
333 | sk, | ||
334 | addr, | ||
335 | bp->port, snum, | ||
336 | len); | ||
328 | 337 | ||
329 | /* PF specific bind() address verification. */ | 338 | /* PF specific bind() address verification. */ |
330 | if (!sp->pf->bind_verify(sp, addr)) | 339 | if (!sp->pf->bind_verify(sp, addr)) |
331 | return -EADDRNOTAVAIL; | 340 | return -EADDRNOTAVAIL; |
332 | 341 | ||
333 | snum= ntohs(addr->v4.sin_port); | ||
334 | |||
335 | SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n", | ||
336 | bp->port, snum); | ||
337 | |||
338 | /* We must either be unbound, or bind to the same port. */ | 342 | /* We must either be unbound, or bind to the same port. */ |
339 | if (bp->port && (snum != bp->port)) { | 343 | if (bp->port && (snum != bp->port)) { |
340 | SCTP_DEBUG_PRINTK("sctp_do_bind:" | 344 | SCTP_DEBUG_PRINTK("sctp_do_bind:" |
@@ -816,7 +820,8 @@ out: | |||
816 | * | 820 | * |
817 | * Basically do nothing but copying the addresses from user to kernel | 821 | * Basically do nothing but copying the addresses from user to kernel |
818 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. | 822 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. |
819 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. | 823 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() |
824 | * from userspace. | ||
820 | * | 825 | * |
821 | * We don't use copy_from_user() for optimization: we first do the | 826 | * We don't use copy_from_user() for optimization: we first do the |
822 | * sanity checks (buffer size -fast- and access check-healthy | 827 | * sanity checks (buffer size -fast- and access check-healthy |
@@ -913,6 +918,243 @@ out: | |||
913 | return err; | 918 | return err; |
914 | } | 919 | } |
915 | 920 | ||
921 | /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) | ||
922 | * | ||
923 | * Common routine for handling connect() and sctp_connectx(). | ||
924 | * Connect will come in with just a single address. | ||
925 | */ | ||
926 | static int __sctp_connect(struct sock* sk, | ||
927 | struct sockaddr *kaddrs, | ||
928 | int addrs_size) | ||
929 | { | ||
930 | struct sctp_sock *sp; | ||
931 | struct sctp_endpoint *ep; | ||
932 | struct sctp_association *asoc = NULL; | ||
933 | struct sctp_association *asoc2; | ||
934 | struct sctp_transport *transport; | ||
935 | union sctp_addr to; | ||
936 | struct sctp_af *af; | ||
937 | sctp_scope_t scope; | ||
938 | long timeo; | ||
939 | int err = 0; | ||
940 | int addrcnt = 0; | ||
941 | int walk_size = 0; | ||
942 | struct sockaddr *sa_addr; | ||
943 | void *addr_buf; | ||
944 | |||
945 | sp = sctp_sk(sk); | ||
946 | ep = sp->ep; | ||
947 | |||
948 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
949 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
950 | * is already connected. | ||
951 | * It cannot be done even on a TCP-style listening socket. | ||
952 | */ | ||
953 | if (sctp_sstate(sk, ESTABLISHED) || | ||
954 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
955 | err = -EISCONN; | ||
956 | goto out_free; | ||
957 | } | ||
958 | |||
959 | /* Walk through the addrs buffer and count the number of addresses. */ | ||
960 | addr_buf = kaddrs; | ||
961 | while (walk_size < addrs_size) { | ||
962 | sa_addr = (struct sockaddr *)addr_buf; | ||
963 | af = sctp_get_af_specific(sa_addr->sa_family); | ||
964 | |||
965 | /* If the address family is not supported or if this address | ||
966 | * causes the address buffer to overflow return EINVAL. | ||
967 | */ | ||
968 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | ||
969 | err = -EINVAL; | ||
970 | goto out_free; | ||
971 | } | ||
972 | |||
973 | err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr, | ||
974 | af->sockaddr_len); | ||
975 | if (err) | ||
976 | goto out_free; | ||
977 | |||
978 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
979 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
980 | |||
981 | /* Check if there already is a matching association on the | ||
982 | * endpoint (other than the one created here). | ||
983 | */ | ||
984 | asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
985 | if (asoc2 && asoc2 != asoc) { | ||
986 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) | ||
987 | err = -EISCONN; | ||
988 | else | ||
989 | err = -EALREADY; | ||
990 | goto out_free; | ||
991 | } | ||
992 | |||
993 | /* If we could not find a matching association on the endpoint, | ||
994 | * make sure that there is no peeled-off association matching | ||
995 | * the peer address even on another socket. | ||
996 | */ | ||
997 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
998 | err = -EADDRNOTAVAIL; | ||
999 | goto out_free; | ||
1000 | } | ||
1001 | |||
1002 | if (!asoc) { | ||
1003 | /* If a bind() or sctp_bindx() is not called prior to | ||
1004 | * an sctp_connectx() call, the system picks an | ||
1005 | * ephemeral port and will choose an address set | ||
1006 | * equivalent to binding with a wildcard address. | ||
1007 | */ | ||
1008 | if (!ep->base.bind_addr.port) { | ||
1009 | if (sctp_autobind(sk)) { | ||
1010 | err = -EAGAIN; | ||
1011 | goto out_free; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | scope = sctp_scope(&to); | ||
1016 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
1017 | if (!asoc) { | ||
1018 | err = -ENOMEM; | ||
1019 | goto out_free; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | /* Prime the peer's transport structures. */ | ||
1024 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, | ||
1025 | SCTP_UNKNOWN); | ||
1026 | if (!transport) { | ||
1027 | err = -ENOMEM; | ||
1028 | goto out_free; | ||
1029 | } | ||
1030 | |||
1031 | addrcnt++; | ||
1032 | addr_buf += af->sockaddr_len; | ||
1033 | walk_size += af->sockaddr_len; | ||
1034 | } | ||
1035 | |||
1036 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | ||
1037 | if (err < 0) { | ||
1038 | goto out_free; | ||
1039 | } | ||
1040 | |||
1041 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
1042 | if (err < 0) { | ||
1043 | goto out_free; | ||
1044 | } | ||
1045 | |||
1046 | /* Initialize sk's dport and daddr for getpeername() */ | ||
1047 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
1048 | af = sctp_get_af_specific(to.sa.sa_family); | ||
1049 | af->to_sk_daddr(&to, sk); | ||
1050 | |||
1051 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
1052 | err = sctp_wait_for_connect(asoc, &timeo); | ||
1053 | |||
1054 | /* Don't free association on exit. */ | ||
1055 | asoc = NULL; | ||
1056 | |||
1057 | out_free: | ||
1058 | |||
1059 | SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" | ||
1060 | " kaddrs: %p err: %d\n", | ||
1061 | asoc, kaddrs, err); | ||
1062 | if (asoc) | ||
1063 | sctp_association_free(asoc); | ||
1064 | return err; | ||
1065 | } | ||
1066 | |||
1067 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | ||
1068 | * | ||
1069 | * API 8.9 | ||
1070 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | ||
1071 | * | ||
1072 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | ||
1073 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | ||
1074 | * or IPv6 addresses. | ||
1075 | * | ||
1076 | * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see | ||
1077 | * Section 3.1.2 for this usage. | ||
1078 | * | ||
1079 | * addrs is a pointer to an array of one or more socket addresses. Each | ||
1080 | * address is contained in its appropriate structure (i.e. struct | ||
1081 | * sockaddr_in or struct sockaddr_in6) the family of the address type | ||
1082 | * must be used to distengish the address length (note that this | ||
1083 | * representation is termed a "packed array" of addresses). The caller | ||
1084 | * specifies the number of addresses in the array with addrcnt. | ||
1085 | * | ||
1086 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | ||
1087 | * -1, and sets errno to the appropriate error code. | ||
1088 | * | ||
1089 | * For SCTP, the port given in each socket address must be the same, or | ||
1090 | * sctp_connectx() will fail, setting errno to EINVAL. | ||
1091 | * | ||
1092 | * An application can use sctp_connectx to initiate an association with | ||
1093 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | ||
1094 | * allows a caller to specify multiple addresses at which a peer can be | ||
1095 | * reached. The way the SCTP stack uses the list of addresses to set up | ||
1096 | * the association is implementation dependant. This function only | ||
1097 | * specifies that the stack will try to make use of all the addresses in | ||
1098 | * the list when needed. | ||
1099 | * | ||
1100 | * Note that the list of addresses passed in is only used for setting up | ||
1101 | * the association. It does not necessarily equal the set of addresses | ||
1102 | * the peer uses for the resulting association. If the caller wants to | ||
1103 | * find out the set of peer addresses, it must use sctp_getpaddrs() to | ||
1104 | * retrieve them after the association has been set up. | ||
1105 | * | ||
1106 | * Basically do nothing but copying the addresses from user to kernel | ||
1107 | * land and invoking either sctp_connectx(). This is used for tunneling | ||
1108 | * the sctp_connectx() request through sctp_setsockopt() from userspace. | ||
1109 | * | ||
1110 | * We don't use copy_from_user() for optimization: we first do the | ||
1111 | * sanity checks (buffer size -fast- and access check-healthy | ||
1112 | * pointer); if all of those succeed, then we can alloc the memory | ||
1113 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
1114 | * the copying without checking the user space area | ||
1115 | * (__copy_from_user()). | ||
1116 | * | ||
1117 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | ||
1118 | * it. | ||
1119 | * | ||
1120 | * sk The sk of the socket | ||
1121 | * addrs The pointer to the addresses in user land | ||
1122 | * addrssize Size of the addrs buffer | ||
1123 | * | ||
1124 | * Returns 0 if ok, <0 errno code on error. | ||
1125 | */ | ||
1126 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
1127 | struct sockaddr __user *addrs, | ||
1128 | int addrs_size) | ||
1129 | { | ||
1130 | int err = 0; | ||
1131 | struct sockaddr *kaddrs; | ||
1132 | |||
1133 | SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", | ||
1134 | __FUNCTION__, sk, addrs, addrs_size); | ||
1135 | |||
1136 | if (unlikely(addrs_size <= 0)) | ||
1137 | return -EINVAL; | ||
1138 | |||
1139 | /* Check the user passed a healthy pointer. */ | ||
1140 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | ||
1141 | return -EFAULT; | ||
1142 | |||
1143 | /* Alloc space for the address array in kernel memory. */ | ||
1144 | kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); | ||
1145 | if (unlikely(!kaddrs)) | ||
1146 | return -ENOMEM; | ||
1147 | |||
1148 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
1149 | err = -EFAULT; | ||
1150 | } else { | ||
1151 | err = __sctp_connect(sk, kaddrs, addrs_size); | ||
1152 | } | ||
1153 | |||
1154 | kfree(kaddrs); | ||
1155 | return err; | ||
1156 | } | ||
1157 | |||
916 | /* API 3.1.4 close() - UDP Style Syntax | 1158 | /* API 3.1.4 close() - UDP Style Syntax |
917 | * Applications use close() to perform graceful shutdown (as described in | 1159 | * Applications use close() to perform graceful shutdown (as described in |
918 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1160 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
@@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1095 | sp = sctp_sk(sk); | 1337 | sp = sctp_sk(sk); |
1096 | ep = sp->ep; | 1338 | ep = sp->ep; |
1097 | 1339 | ||
1098 | SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name); | 1340 | SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep); |
1099 | 1341 | ||
1100 | /* We cannot send a message over a TCP-style listening socket. */ | 1342 | /* We cannot send a message over a TCP-style listening socket. */ |
1101 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { | 1343 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { |
@@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1306 | } | 1548 | } |
1307 | 1549 | ||
1308 | /* Prime the peer's transport structures. */ | 1550 | /* Prime the peer's transport structures. */ |
1309 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 1551 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); |
1310 | if (!transport) { | 1552 | if (!transport) { |
1311 | err = -ENOMEM; | 1553 | err = -ENOMEM; |
1312 | goto out_free; | 1554 | goto out_free; |
@@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
2208 | optlen, SCTP_BINDX_REM_ADDR); | 2450 | optlen, SCTP_BINDX_REM_ADDR); |
2209 | break; | 2451 | break; |
2210 | 2452 | ||
2453 | case SCTP_SOCKOPT_CONNECTX: | ||
2454 | /* 'optlen' is the size of the addresses buffer. */ | ||
2455 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | ||
2456 | optlen); | ||
2457 | break; | ||
2458 | |||
2211 | case SCTP_DISABLE_FRAGMENTS: | 2459 | case SCTP_DISABLE_FRAGMENTS: |
2212 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); | 2460 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); |
2213 | break; | 2461 | break; |
@@ -2283,112 +2531,29 @@ out_nounlock: | |||
2283 | * | 2531 | * |
2284 | * len: the size of the address. | 2532 | * len: the size of the address. |
2285 | */ | 2533 | */ |
2286 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, | 2534 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, |
2287 | int addr_len) | 2535 | int addr_len) |
2288 | { | 2536 | { |
2289 | struct sctp_sock *sp; | ||
2290 | struct sctp_endpoint *ep; | ||
2291 | struct sctp_association *asoc; | ||
2292 | struct sctp_transport *transport; | ||
2293 | union sctp_addr to; | ||
2294 | struct sctp_af *af; | ||
2295 | sctp_scope_t scope; | ||
2296 | long timeo; | ||
2297 | int err = 0; | 2537 | int err = 0; |
2538 | struct sctp_af *af; | ||
2298 | 2539 | ||
2299 | sctp_lock_sock(sk); | 2540 | sctp_lock_sock(sk); |
2300 | 2541 | ||
2301 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n", | 2542 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", |
2302 | __FUNCTION__, sk, uaddr, addr_len); | 2543 | __FUNCTION__, sk, addr, addr_len); |
2303 | |||
2304 | sp = sctp_sk(sk); | ||
2305 | ep = sp->ep; | ||
2306 | |||
2307 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
2308 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
2309 | * is already connected. | ||
2310 | * It cannot be done even on a TCP-style listening socket. | ||
2311 | */ | ||
2312 | if (sctp_sstate(sk, ESTABLISHED) || | ||
2313 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
2314 | err = -EISCONN; | ||
2315 | goto out_unlock; | ||
2316 | } | ||
2317 | |||
2318 | err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len); | ||
2319 | if (err) | ||
2320 | goto out_unlock; | ||
2321 | |||
2322 | if (addr_len > sizeof(to)) | ||
2323 | addr_len = sizeof(to); | ||
2324 | memcpy(&to, uaddr, addr_len); | ||
2325 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
2326 | |||
2327 | asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
2328 | if (asoc) { | ||
2329 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | ||
2330 | err = -EISCONN; | ||
2331 | else | ||
2332 | err = -EALREADY; | ||
2333 | goto out_unlock; | ||
2334 | } | ||
2335 | |||
2336 | /* If we could not find a matching association on the endpoint, | ||
2337 | * make sure that there is no peeled-off association matching the | ||
2338 | * peer address even on another socket. | ||
2339 | */ | ||
2340 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
2341 | err = -EADDRNOTAVAIL; | ||
2342 | goto out_unlock; | ||
2343 | } | ||
2344 | |||
2345 | /* If a bind() or sctp_bindx() is not called prior to a connect() | ||
2346 | * call, the system picks an ephemeral port and will choose an address | ||
2347 | * set equivalent to binding with a wildcard address. | ||
2348 | */ | ||
2349 | if (!ep->base.bind_addr.port) { | ||
2350 | if (sctp_autobind(sk)) { | ||
2351 | err = -EAGAIN; | ||
2352 | goto out_unlock; | ||
2353 | } | ||
2354 | } | ||
2355 | |||
2356 | scope = sctp_scope(&to); | ||
2357 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
2358 | if (!asoc) { | ||
2359 | err = -ENOMEM; | ||
2360 | goto out_unlock; | ||
2361 | } | ||
2362 | 2544 | ||
2363 | /* Prime the peer's transport structures. */ | 2545 | /* Validate addr_len before calling common connect/connectx routine. */ |
2364 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 2546 | af = sctp_get_af_specific(addr->sa_family); |
2365 | if (!transport) { | 2547 | if (!af || addr_len < af->sockaddr_len) { |
2366 | sctp_association_free(asoc); | 2548 | err = -EINVAL; |
2367 | goto out_unlock; | 2549 | } else { |
2368 | } | 2550 | /* Pass correct addr len to common routine (so it knows there |
2369 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | 2551 | * is only one address being passed. |
2370 | if (err < 0) { | 2552 | */ |
2371 | sctp_association_free(asoc); | 2553 | err = __sctp_connect(sk, addr, af->sockaddr_len); |
2372 | goto out_unlock; | ||
2373 | } | ||
2374 | |||
2375 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
2376 | if (err < 0) { | ||
2377 | sctp_association_free(asoc); | ||
2378 | goto out_unlock; | ||
2379 | } | 2554 | } |
2380 | 2555 | ||
2381 | /* Initialize sk's dport and daddr for getpeername() */ | ||
2382 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
2383 | af = sctp_get_af_specific(to.sa.sa_family); | ||
2384 | af->to_sk_daddr(&to, sk); | ||
2385 | |||
2386 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
2387 | err = sctp_wait_for_connect(asoc, &timeo); | ||
2388 | |||
2389 | out_unlock: | ||
2390 | sctp_release_sock(sk); | 2556 | sctp_release_sock(sk); |
2391 | |||
2392 | return err; | 2557 | return err; |
2393 | } | 2558 | } |
2394 | 2559 | ||
@@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
2677 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 2842 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
2678 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 2843 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), |
2679 | (union sctp_addr *)&status.sstat_primary.spinfo_address); | 2844 | (union sctp_addr *)&status.sstat_primary.spinfo_address); |
2680 | status.sstat_primary.spinfo_state = transport->active; | 2845 | status.sstat_primary.spinfo_state = transport->state; |
2681 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 2846 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
2682 | status.sstat_primary.spinfo_srtt = transport->srtt; | 2847 | status.sstat_primary.spinfo_srtt = transport->srtt; |
2683 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); | 2848 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); |
2684 | status.sstat_primary.spinfo_mtu = transport->pmtu; | 2849 | status.sstat_primary.spinfo_mtu = transport->pmtu; |
2685 | 2850 | ||
2851 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) | ||
2852 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; | ||
2853 | |||
2686 | if (put_user(len, optlen)) { | 2854 | if (put_user(len, optlen)) { |
2687 | retval = -EFAULT; | 2855 | retval = -EFAULT; |
2688 | goto out; | 2856 | goto out; |
@@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
2733 | return -EINVAL; | 2901 | return -EINVAL; |
2734 | 2902 | ||
2735 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); | 2903 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); |
2736 | pinfo.spinfo_state = transport->active; | 2904 | pinfo.spinfo_state = transport->state; |
2737 | pinfo.spinfo_cwnd = transport->cwnd; | 2905 | pinfo.spinfo_cwnd = transport->cwnd; |
2738 | pinfo.spinfo_srtt = transport->srtt; | 2906 | pinfo.spinfo_srtt = transport->srtt; |
2739 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); | 2907 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); |
2740 | pinfo.spinfo_mtu = transport->pmtu; | 2908 | pinfo.spinfo_mtu = transport->pmtu; |
2741 | 2909 | ||
2910 | if (pinfo.spinfo_state == SCTP_UNKNOWN) | ||
2911 | pinfo.spinfo_state = SCTP_ACTIVE; | ||
2912 | |||
2742 | if (put_user(len, optlen)) { | 2913 | if (put_user(len, optlen)) { |
2743 | retval = -EFAULT; | 2914 | retval = -EFAULT; |
2744 | goto out; | 2915 | goto out; |
@@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
3591 | int retval = 0; | 3762 | int retval = 0; |
3592 | int len; | 3763 | int len; |
3593 | 3764 | ||
3594 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk); | 3765 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n", |
3766 | sk, optname); | ||
3595 | 3767 | ||
3596 | /* I can hardly begin to describe how wrong this is. This is | 3768 | /* I can hardly begin to describe how wrong this is. This is |
3597 | * so broken as to be worse than useless. The API draft | 3769 | * so broken as to be worse than useless. The API draft |
@@ -4596,8 +4768,7 @@ out: | |||
4596 | return err; | 4768 | return err; |
4597 | 4769 | ||
4598 | do_error: | 4770 | do_error: |
4599 | if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >= | 4771 | if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) |
4600 | asoc->max_init_attempts) | ||
4601 | err = -ETIMEDOUT; | 4772 | err = -ETIMEDOUT; |
4602 | else | 4773 | else |
4603 | err = -ECONNREFUSED; | 4774 | err = -ECONNREFUSED; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index f30882e1e96a..0ec0fde6e6c5 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
83 | peer->last_time_used = jiffies; | 83 | peer->last_time_used = jiffies; |
84 | peer->last_time_ecne_reduced = jiffies; | 84 | peer->last_time_ecne_reduced = jiffies; |
85 | 85 | ||
86 | peer->active = SCTP_ACTIVE; | 86 | peer->init_sent_count = 0; |
87 | |||
88 | peer->state = SCTP_ACTIVE; | ||
87 | peer->hb_allowed = 0; | 89 | peer->hb_allowed = 0; |
88 | 90 | ||
89 | /* Initialize the default path max_retrans. */ | 91 | /* Initialize the default path max_retrans. */ |