diff options
Diffstat (limited to 'net/sctp/sm_statefuns.c')
-rw-r--r-- | net/sctp/sm_statefuns.c | 140 |
1 files changed, 98 insertions, 42 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 2b9a832b29a7..8bc279219a72 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | |||
93 | static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); | 93 | static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); |
94 | 94 | ||
95 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | 95 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
96 | __u16 error, | 96 | __u16 error, int sk_err, |
97 | const struct sctp_association *asoc, | 97 | const struct sctp_association *asoc, |
98 | struct sctp_transport *transport); | 98 | struct sctp_transport *transport); |
99 | 99 | ||
@@ -448,7 +448,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
448 | __u32 init_tag; | 448 | __u32 init_tag; |
449 | struct sctp_chunk *err_chunk; | 449 | struct sctp_chunk *err_chunk; |
450 | struct sctp_packet *packet; | 450 | struct sctp_packet *packet; |
451 | sctp_disposition_t ret; | 451 | __u16 error; |
452 | 452 | ||
453 | if (!sctp_vtag_verify(chunk, asoc)) | 453 | if (!sctp_vtag_verify(chunk, asoc)) |
454 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 454 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
@@ -480,11 +480,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
480 | goto nomem; | 480 | goto nomem; |
481 | 481 | ||
482 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); | 482 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); |
483 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 483 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM, |
484 | SCTP_STATE(SCTP_STATE_CLOSED)); | 484 | ECONNREFUSED, asoc, |
485 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 485 | chunk->transport); |
486 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | ||
487 | return SCTP_DISPOSITION_DELETE_TCB; | ||
488 | } | 486 | } |
489 | 487 | ||
490 | /* Verify the INIT chunk before processing it. */ | 488 | /* Verify the INIT chunk before processing it. */ |
@@ -511,27 +509,16 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
511 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 509 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
512 | SCTP_PACKET(packet)); | 510 | SCTP_PACKET(packet)); |
513 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 511 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); |
514 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 512 | error = SCTP_ERROR_INV_PARAM; |
515 | SCTP_STATE(SCTP_STATE_CLOSED)); | ||
516 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, | ||
517 | SCTP_NULL()); | ||
518 | return SCTP_DISPOSITION_CONSUME; | ||
519 | } else { | 513 | } else { |
520 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 514 | error = SCTP_ERROR_NO_RESOURCE; |
521 | SCTP_STATE(SCTP_STATE_CLOSED)); | ||
522 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, | ||
523 | SCTP_NULL()); | ||
524 | return SCTP_DISPOSITION_NOMEM; | ||
525 | } | 515 | } |
526 | } else { | 516 | } else { |
527 | ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg, | 517 | sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
528 | commands); | 518 | error = SCTP_ERROR_INV_PARAM; |
529 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | ||
530 | SCTP_STATE(SCTP_STATE_CLOSED)); | ||
531 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, | ||
532 | SCTP_NULL()); | ||
533 | return ret; | ||
534 | } | 519 | } |
520 | return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, | ||
521 | asoc, chunk->transport); | ||
535 | } | 522 | } |
536 | 523 | ||
537 | /* Tag the variable length parameters. Note that we never | 524 | /* Tag the variable length parameters. Note that we never |
@@ -636,8 +623,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
636 | */ | 623 | */ |
637 | chunk->subh.cookie_hdr = | 624 | chunk->subh.cookie_hdr = |
638 | (struct sctp_signed_cookie *)chunk->skb->data; | 625 | (struct sctp_signed_cookie *)chunk->skb->data; |
639 | skb_pull(chunk->skb, | 626 | if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - |
640 | ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); | 627 | sizeof(sctp_chunkhdr_t))) |
628 | goto nomem; | ||
641 | 629 | ||
642 | /* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint | 630 | /* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint |
643 | * "Z" will reply with a COOKIE ACK chunk after building a TCB | 631 | * "Z" will reply with a COOKIE ACK chunk after building a TCB |
@@ -885,6 +873,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | |||
885 | struct sctp_transport *transport = (struct sctp_transport *) arg; | 873 | struct sctp_transport *transport = (struct sctp_transport *) arg; |
886 | 874 | ||
887 | if (asoc->overall_error_count >= asoc->max_retrans) { | 875 | if (asoc->overall_error_count >= asoc->max_retrans) { |
876 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
877 | SCTP_ERROR(ETIMEDOUT)); | ||
888 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 878 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
889 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 879 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
890 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 880 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
@@ -965,7 +955,8 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep, | |||
965 | */ | 955 | */ |
966 | chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data; | 956 | chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data; |
967 | paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); | 957 | paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); |
968 | skb_pull(chunk->skb, paylen); | 958 | if (!pskb_pull(chunk->skb, paylen)) |
959 | goto nomem; | ||
969 | 960 | ||
970 | reply = sctp_make_heartbeat_ack(asoc, chunk, | 961 | reply = sctp_make_heartbeat_ack(asoc, chunk, |
971 | chunk->subh.hb_hdr, paylen); | 962 | chunk->subh.hb_hdr, paylen); |
@@ -1028,6 +1019,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1028 | commands); | 1019 | commands); |
1029 | 1020 | ||
1030 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; | 1021 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; |
1022 | /* Make sure that the length of the parameter is what we expect */ | ||
1023 | if (ntohs(hbinfo->param_hdr.length) != | ||
1024 | sizeof(sctp_sender_hb_info_t)) { | ||
1025 | return SCTP_DISPOSITION_DISCARD; | ||
1026 | } | ||
1027 | |||
1031 | from_addr = hbinfo->daddr; | 1028 | from_addr = hbinfo->daddr; |
1032 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); | 1029 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); |
1033 | 1030 | ||
@@ -1860,8 +1857,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | |||
1860 | * are in good shape. | 1857 | * are in good shape. |
1861 | */ | 1858 | */ |
1862 | chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; | 1859 | chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; |
1863 | skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - | 1860 | if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - |
1864 | sizeof(sctp_chunkhdr_t)); | 1861 | sizeof(sctp_chunkhdr_t))) |
1862 | goto nomem; | ||
1865 | 1863 | ||
1866 | /* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie | 1864 | /* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie |
1867 | * of a duplicate COOKIE ECHO match the Verification Tags of the | 1865 | * of a duplicate COOKIE ECHO match the Verification Tags of the |
@@ -2123,6 +2121,8 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
2123 | int attempts = asoc->init_err_counter + 1; | 2121 | int attempts = asoc->init_err_counter + 1; |
2124 | 2122 | ||
2125 | if (attempts > asoc->max_init_attempts) { | 2123 | if (attempts > asoc->max_init_attempts) { |
2124 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
2125 | SCTP_ERROR(ETIMEDOUT)); | ||
2126 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2126 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
2127 | SCTP_U32(SCTP_ERROR_STALE_COOKIE)); | 2127 | SCTP_U32(SCTP_ERROR_STALE_COOKIE)); |
2128 | return SCTP_DISPOSITION_DELETE_TCB; | 2128 | return SCTP_DISPOSITION_DELETE_TCB; |
@@ -2259,6 +2259,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2259 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2259 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2260 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2260 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2261 | 2261 | ||
2262 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); | ||
2262 | /* ASSOC_FAILED will DELETE_TCB. */ | 2263 | /* ASSOC_FAILED will DELETE_TCB. */ |
2263 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); | 2264 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); |
2264 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2265 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -2303,7 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2303 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2304 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2304 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2305 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2305 | 2306 | ||
2306 | return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); | 2307 | return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc, |
2308 | chunk->transport); | ||
2307 | } | 2309 | } |
2308 | 2310 | ||
2309 | /* | 2311 | /* |
@@ -2315,7 +2317,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
2315 | void *arg, | 2317 | void *arg, |
2316 | sctp_cmd_seq_t *commands) | 2318 | sctp_cmd_seq_t *commands) |
2317 | { | 2319 | { |
2318 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, | 2320 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, |
2321 | ENOPROTOOPT, asoc, | ||
2319 | (struct sctp_transport *)arg); | 2322 | (struct sctp_transport *)arg); |
2320 | } | 2323 | } |
2321 | 2324 | ||
@@ -2340,7 +2343,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
2340 | * This is common code called by several sctp_sf_*_abort() functions above. | 2343 | * This is common code called by several sctp_sf_*_abort() functions above. |
2341 | */ | 2344 | */ |
2342 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | 2345 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
2343 | __u16 error, | 2346 | __u16 error, int sk_err, |
2344 | const struct sctp_association *asoc, | 2347 | const struct sctp_association *asoc, |
2345 | struct sctp_transport *transport) | 2348 | struct sctp_transport *transport) |
2346 | { | 2349 | { |
@@ -2350,6 +2353,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | |||
2350 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2353 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
2351 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2354 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2352 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 2355 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
2356 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); | ||
2353 | /* CMD_INIT_FAILED will DELETE_TCB. */ | 2357 | /* CMD_INIT_FAILED will DELETE_TCB. */ |
2354 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2358 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
2355 | SCTP_U32(error)); | 2359 | SCTP_U32(error)); |
@@ -3333,6 +3337,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3333 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 3337 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
3334 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 3338 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
3335 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); | 3339 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); |
3340 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3341 | SCTP_ERROR(ECONNABORTED)); | ||
3336 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3342 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3337 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); | 3343 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); |
3338 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 3344 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -3359,6 +3365,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3359 | * processing the rest of the chunks in the packet. | 3365 | * processing the rest of the chunks in the packet. |
3360 | */ | 3366 | */ |
3361 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); | 3367 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); |
3368 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3369 | SCTP_ERROR(ECONNABORTED)); | ||
3362 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3370 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3363 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); | 3371 | SCTP_U32(SCTP_ERROR_ASCONF_ACK)); |
3364 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 3372 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -3711,9 +3719,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
3711 | if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { | 3719 | if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { |
3712 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 3720 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
3713 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 3721 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
3722 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3723 | SCTP_ERROR(ECONNREFUSED)); | ||
3714 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 3724 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
3715 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); | 3725 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); |
3716 | } else { | 3726 | } else { |
3727 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
3728 | SCTP_ERROR(ECONNABORTED)); | ||
3717 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3729 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3718 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); | 3730 | SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); |
3719 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 3731 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); |
@@ -4031,6 +4043,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
4031 | * TCB. This is a departure from our typical NOMEM handling. | 4043 | * TCB. This is a departure from our typical NOMEM handling. |
4032 | */ | 4044 | */ |
4033 | 4045 | ||
4046 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4047 | SCTP_ERROR(ECONNABORTED)); | ||
4034 | /* Delete the established association. */ | 4048 | /* Delete the established association. */ |
4035 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4049 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4036 | SCTP_U32(SCTP_ERROR_USER_ABORT)); | 4050 | SCTP_U32(SCTP_ERROR_USER_ABORT)); |
@@ -4172,6 +4186,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4172 | * TCB. This is a departure from our typical NOMEM handling. | 4186 | * TCB. This is a departure from our typical NOMEM handling. |
4173 | */ | 4187 | */ |
4174 | 4188 | ||
4189 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4190 | SCTP_ERROR(ECONNREFUSED)); | ||
4175 | /* Delete the established association. */ | 4191 | /* Delete the established association. */ |
4176 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4192 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4177 | SCTP_U32(SCTP_ERROR_USER_ABORT)); | 4193 | SCTP_U32(SCTP_ERROR_USER_ABORT)); |
@@ -4540,6 +4556,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
4540 | struct sctp_transport *transport = arg; | 4556 | struct sctp_transport *transport = arg; |
4541 | 4557 | ||
4542 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4558 | if (asoc->overall_error_count >= asoc->max_retrans) { |
4559 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4560 | SCTP_ERROR(ETIMEDOUT)); | ||
4543 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 4561 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
4544 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4562 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4545 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4563 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
@@ -4659,6 +4677,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | |||
4659 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" | 4677 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" |
4660 | " max_init_attempts: %d\n", | 4678 | " max_init_attempts: %d\n", |
4661 | attempts, asoc->max_init_attempts); | 4679 | attempts, asoc->max_init_attempts); |
4680 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4681 | SCTP_ERROR(ETIMEDOUT)); | ||
4662 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4682 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4663 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4683 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4664 | return SCTP_DISPOSITION_DELETE_TCB; | 4684 | return SCTP_DISPOSITION_DELETE_TCB; |
@@ -4708,6 +4728,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
4708 | 4728 | ||
4709 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 4729 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
4710 | } else { | 4730 | } else { |
4731 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4732 | SCTP_ERROR(ETIMEDOUT)); | ||
4711 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4733 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
4712 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4734 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4713 | return SCTP_DISPOSITION_DELETE_TCB; | 4735 | return SCTP_DISPOSITION_DELETE_TCB; |
@@ -4739,6 +4761,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
4739 | 4761 | ||
4740 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); | 4762 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); |
4741 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4763 | if (asoc->overall_error_count >= asoc->max_retrans) { |
4764 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4765 | SCTP_ERROR(ETIMEDOUT)); | ||
4742 | /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 4766 | /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
4743 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4767 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4744 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4768 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
@@ -4814,6 +4838,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
4814 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4838 | if (asoc->overall_error_count >= asoc->max_retrans) { |
4815 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 4839 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4816 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 4840 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
4841 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4842 | SCTP_ERROR(ETIMEDOUT)); | ||
4817 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4843 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4818 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4844 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4819 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4845 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
@@ -4867,6 +4893,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | |||
4867 | goto nomem; | 4893 | goto nomem; |
4868 | 4894 | ||
4869 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); | 4895 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); |
4896 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4897 | SCTP_ERROR(ETIMEDOUT)); | ||
4870 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4898 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4871 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | 4899 | SCTP_U32(SCTP_ERROR_NO_ERROR)); |
4872 | 4900 | ||
@@ -5151,7 +5179,9 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5151 | int tmp; | 5179 | int tmp; |
5152 | __u32 tsn; | 5180 | __u32 tsn; |
5153 | int account_value; | 5181 | int account_value; |
5182 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; | ||
5154 | struct sock *sk = asoc->base.sk; | 5183 | struct sock *sk = asoc->base.sk; |
5184 | int rcvbuf_over = 0; | ||
5155 | 5185 | ||
5156 | data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; | 5186 | data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; |
5157 | skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); | 5187 | skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); |
@@ -5162,10 +5192,16 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5162 | /* ASSERT: Now skb->data is really the user data. */ | 5192 | /* ASSERT: Now skb->data is really the user data. */ |
5163 | 5193 | ||
5164 | /* | 5194 | /* |
5165 | * if we are established, and we have used up our receive | 5195 | * If we are established, and we have used up our receive buffer |
5166 | * buffer memory, drop the frame | 5196 | * memory, think about droping the frame. |
5167 | */ | 5197 | * Note that we have an opportunity to improve performance here. |
5168 | if (asoc->state == SCTP_STATE_ESTABLISHED) { | 5198 | * If we accept one chunk from an skbuff, we have to keep all the |
5199 | * memory of that skbuff around until the chunk is read into user | ||
5200 | * space. Therefore, once we accept 1 chunk we may as well accept all | ||
5201 | * remaining chunks in the skbuff. The data_accepted flag helps us do | ||
5202 | * that. | ||
5203 | */ | ||
5204 | if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) { | ||
5169 | /* | 5205 | /* |
5170 | * If the receive buffer policy is 1, then each | 5206 | * If the receive buffer policy is 1, then each |
5171 | * association can allocate up to sk_rcvbuf bytes | 5207 | * association can allocate up to sk_rcvbuf bytes |
@@ -5176,9 +5212,25 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5176 | account_value = atomic_read(&asoc->rmem_alloc); | 5212 | account_value = atomic_read(&asoc->rmem_alloc); |
5177 | else | 5213 | else |
5178 | account_value = atomic_read(&sk->sk_rmem_alloc); | 5214 | account_value = atomic_read(&sk->sk_rmem_alloc); |
5179 | 5215 | if (account_value > sk->sk_rcvbuf) { | |
5180 | if (account_value > sk->sk_rcvbuf) | 5216 | /* |
5181 | return SCTP_IERROR_IGNORE_TSN; | 5217 | * We need to make forward progress, even when we are |
5218 | * under memory pressure, so we always allow the | ||
5219 | * next tsn after the ctsn ack point to be accepted. | ||
5220 | * This lets us avoid deadlocks in which we have to | ||
5221 | * drop frames that would otherwise let us drain the | ||
5222 | * receive queue. | ||
5223 | */ | ||
5224 | if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn) | ||
5225 | return SCTP_IERROR_IGNORE_TSN; | ||
5226 | |||
5227 | /* | ||
5228 | * We're going to accept the frame but we should renege | ||
5229 | * to make space for it. This will send us down that | ||
5230 | * path later in this function. | ||
5231 | */ | ||
5232 | rcvbuf_over = 1; | ||
5233 | } | ||
5182 | } | 5234 | } |
5183 | 5235 | ||
5184 | /* Process ECN based congestion. | 5236 | /* Process ECN based congestion. |
@@ -5226,6 +5278,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5226 | datalen -= sizeof(sctp_data_chunk_t); | 5278 | datalen -= sizeof(sctp_data_chunk_t); |
5227 | 5279 | ||
5228 | deliver = SCTP_CMD_CHUNK_ULP; | 5280 | deliver = SCTP_CMD_CHUNK_ULP; |
5281 | chunk->data_accepted = 1; | ||
5229 | 5282 | ||
5230 | /* Think about partial delivery. */ | 5283 | /* Think about partial delivery. */ |
5231 | if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { | 5284 | if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { |
@@ -5242,7 +5295,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5242 | * large spill over. | 5295 | * large spill over. |
5243 | */ | 5296 | */ |
5244 | if (!asoc->rwnd || asoc->rwnd_over || | 5297 | if (!asoc->rwnd || asoc->rwnd_over || |
5245 | (datalen > asoc->rwnd + asoc->frag_point)) { | 5298 | (datalen > asoc->rwnd + asoc->frag_point) || |
5299 | rcvbuf_over) { | ||
5246 | 5300 | ||
5247 | /* If this is the next TSN, consider reneging to make | 5301 | /* If this is the next TSN, consider reneging to make |
5248 | * room. Note: Playing nice with a confused sender. A | 5302 | * room. Note: Playing nice with a confused sender. A |
@@ -5250,8 +5304,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5250 | * space and in the future we may want to detect and | 5304 | * space and in the future we may want to detect and |
5251 | * do more drastic reneging. | 5305 | * do more drastic reneging. |
5252 | */ | 5306 | */ |
5253 | if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) && | 5307 | if (sctp_tsnmap_has_gap(map) && |
5254 | (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) { | 5308 | (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { |
5255 | SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); | 5309 | SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); |
5256 | deliver = SCTP_CMD_RENEGE; | 5310 | deliver = SCTP_CMD_RENEGE; |
5257 | } else { | 5311 | } else { |
@@ -5280,6 +5334,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5280 | * processing the rest of the chunks in the packet. | 5334 | * processing the rest of the chunks in the packet. |
5281 | */ | 5335 | */ |
5282 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); | 5336 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); |
5337 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
5338 | SCTP_ERROR(ECONNABORTED)); | ||
5283 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5339 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5284 | SCTP_U32(SCTP_ERROR_NO_DATA)); | 5340 | SCTP_U32(SCTP_ERROR_NO_DATA)); |
5285 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5341 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |