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/sm_statefuns.c | |
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/sm_statefuns.c')
-rw-r--r-- | net/sctp/sm_statefuns.c | 148 |
1 files changed, 98 insertions, 50 deletions
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 |