diff options
Diffstat (limited to 'net/sctp/sm_statefuns.c')
| -rw-r--r-- | net/sctp/sm_statefuns.c | 202 |
1 files changed, 112 insertions, 90 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 9e58144f4851..1c42fe983a5b 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -187,10 +187,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
| 187 | */ | 187 | */ |
| 188 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, | 188 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, |
| 189 | 0, 0, 0, GFP_ATOMIC); | 189 | 0, 0, 0, GFP_ATOMIC); |
| 190 | if (!ev) | 190 | if (ev) |
| 191 | goto nomem; | 191 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, |
| 192 | 192 | SCTP_ULPEVENT(ev)); | |
| 193 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); | ||
| 194 | 193 | ||
| 195 | /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint | 194 | /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint |
| 196 | * will verify that it is in SHUTDOWN-ACK-SENT state, if it is | 195 | * will verify that it is in SHUTDOWN-ACK-SENT state, if it is |
| @@ -215,9 +214,6 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
| 215 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 214 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
| 216 | 215 | ||
| 217 | return SCTP_DISPOSITION_DELETE_TCB; | 216 | return SCTP_DISPOSITION_DELETE_TCB; |
| 218 | |||
| 219 | nomem: | ||
| 220 | return SCTP_DISPOSITION_NOMEM; | ||
| 221 | } | 217 | } |
| 222 | 218 | ||
| 223 | /* | 219 | /* |
| @@ -347,8 +343,6 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
| 347 | GFP_ATOMIC)) | 343 | GFP_ATOMIC)) |
| 348 | goto nomem_init; | 344 | goto nomem_init; |
| 349 | 345 | ||
| 350 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); | ||
| 351 | |||
| 352 | /* B) "Z" shall respond immediately with an INIT ACK chunk. */ | 346 | /* B) "Z" shall respond immediately with an INIT ACK chunk. */ |
| 353 | 347 | ||
| 354 | /* If there are errors need to be reported for unknown parameters, | 348 | /* If there are errors need to be reported for unknown parameters, |
| @@ -360,11 +354,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
| 360 | sizeof(sctp_chunkhdr_t); | 354 | sizeof(sctp_chunkhdr_t); |
| 361 | 355 | ||
| 362 | if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0) | 356 | if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0) |
| 363 | goto nomem_ack; | 357 | goto nomem_init; |
| 364 | 358 | ||
| 365 | repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); | 359 | repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); |
| 366 | if (!repl) | 360 | if (!repl) |
| 367 | goto nomem_ack; | 361 | goto nomem_init; |
| 368 | 362 | ||
| 369 | /* If there are errors need to be reported for unknown parameters, | 363 | /* If there are errors need to be reported for unknown parameters, |
| 370 | * include them in the outgoing INIT ACK as "Unrecognized parameter" | 364 | * include them in the outgoing INIT ACK as "Unrecognized parameter" |
| @@ -388,6 +382,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
| 388 | sctp_chunk_free(err_chunk); | 382 | sctp_chunk_free(err_chunk); |
| 389 | } | 383 | } |
| 390 | 384 | ||
| 385 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); | ||
| 386 | |||
| 391 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 387 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
| 392 | 388 | ||
| 393 | /* | 389 | /* |
| @@ -400,12 +396,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
| 400 | 396 | ||
| 401 | return SCTP_DISPOSITION_DELETE_TCB; | 397 | return SCTP_DISPOSITION_DELETE_TCB; |
| 402 | 398 | ||
| 403 | nomem_ack: | ||
| 404 | if (err_chunk) | ||
| 405 | sctp_chunk_free(err_chunk); | ||
| 406 | nomem_init: | 399 | nomem_init: |
| 407 | sctp_association_free(new_asoc); | 400 | sctp_association_free(new_asoc); |
| 408 | nomem: | 401 | nomem: |
| 402 | if (err_chunk) | ||
| 403 | sctp_chunk_free(err_chunk); | ||
| 409 | return SCTP_DISPOSITION_NOMEM; | 404 | return SCTP_DISPOSITION_NOMEM; |
| 410 | } | 405 | } |
| 411 | 406 | ||
| @@ -600,7 +595,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
| 600 | struct sctp_association *new_asoc; | 595 | struct sctp_association *new_asoc; |
| 601 | sctp_init_chunk_t *peer_init; | 596 | sctp_init_chunk_t *peer_init; |
| 602 | struct sctp_chunk *repl; | 597 | struct sctp_chunk *repl; |
| 603 | struct sctp_ulpevent *ev; | 598 | struct sctp_ulpevent *ev, *ai_ev = NULL; |
| 604 | int error = 0; | 599 | int error = 0; |
| 605 | struct sctp_chunk *err_chk_p; | 600 | struct sctp_chunk *err_chk_p; |
| 606 | 601 | ||
| @@ -659,20 +654,10 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
| 659 | }; | 654 | }; |
| 660 | } | 655 | } |
| 661 | 656 | ||
| 662 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); | ||
| 663 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | ||
| 664 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); | ||
| 665 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | ||
| 666 | SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS); | ||
| 667 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | ||
| 668 | |||
| 669 | if (new_asoc->autoclose) | ||
| 670 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
| 671 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | ||
| 672 | |||
| 673 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
| 674 | 657 | ||
| 675 | /* Re-build the bind address for the association is done in | 658 | /* Delay state machine commands until later. |
| 659 | * | ||
| 660 | * Re-build the bind address for the association is done in | ||
| 676 | * the sctp_unpack_cookie() already. | 661 | * the sctp_unpack_cookie() already. |
| 677 | */ | 662 | */ |
| 678 | /* This is a brand-new association, so these are not yet side | 663 | /* This is a brand-new association, so these are not yet side |
| @@ -687,9 +672,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
| 687 | 672 | ||
| 688 | repl = sctp_make_cookie_ack(new_asoc, chunk); | 673 | repl = sctp_make_cookie_ack(new_asoc, chunk); |
| 689 | if (!repl) | 674 | if (!repl) |
| 690 | goto nomem_repl; | 675 | goto nomem_init; |
| 691 | |||
| 692 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
| 693 | 676 | ||
| 694 | /* RFC 2960 5.1 Normal Establishment of an Association | 677 | /* RFC 2960 5.1 Normal Establishment of an Association |
| 695 | * | 678 | * |
| @@ -704,28 +687,53 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
| 704 | if (!ev) | 687 | if (!ev) |
| 705 | goto nomem_ev; | 688 | goto nomem_ev; |
| 706 | 689 | ||
| 707 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); | ||
| 708 | |||
| 709 | /* Sockets API Draft Section 5.3.1.6 | 690 | /* Sockets API Draft Section 5.3.1.6 |
| 710 | * When a peer sends a Adaption Layer Indication parameter , SCTP | 691 | * When a peer sends a Adaption Layer Indication parameter , SCTP |
| 711 | * delivers this notification to inform the application that of the | 692 | * delivers this notification to inform the application that of the |
| 712 | * peers requested adaption layer. | 693 | * peers requested adaption layer. |
| 713 | */ | 694 | */ |
| 714 | if (new_asoc->peer.adaption_ind) { | 695 | if (new_asoc->peer.adaption_ind) { |
| 715 | ev = sctp_ulpevent_make_adaption_indication(new_asoc, | 696 | ai_ev = sctp_ulpevent_make_adaption_indication(new_asoc, |
| 716 | GFP_ATOMIC); | 697 | GFP_ATOMIC); |
| 717 | if (!ev) | 698 | if (!ai_ev) |
| 718 | goto nomem_ev; | 699 | goto nomem_aiev; |
| 700 | } | ||
| 701 | |||
| 702 | /* Add all the state machine commands now since we've created | ||
| 703 | * everything. This way we don't introduce memory corruptions | ||
| 704 | * during side-effect processing and correclty count established | ||
| 705 | * associations. | ||
| 706 | */ | ||
| 707 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); | ||
| 708 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | ||
| 709 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); | ||
| 710 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | ||
| 711 | SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS); | ||
| 712 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | ||
| 713 | |||
| 714 | if (new_asoc->autoclose) | ||
| 715 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
| 716 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | ||
| 719 | 717 | ||
| 718 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
| 719 | |||
| 720 | /* This will send the COOKIE ACK */ | ||
| 721 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
| 722 | |||
| 723 | /* Queue the ASSOC_CHANGE event */ | ||
| 724 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); | ||
| 725 | |||
| 726 | /* Send up the Adaptation Layer Indication event */ | ||
| 727 | if (ai_ev) | ||
| 720 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | 728 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, |
| 721 | SCTP_ULPEVENT(ev)); | 729 | SCTP_ULPEVENT(ai_ev)); |
| 722 | } | ||
| 723 | 730 | ||
| 724 | return SCTP_DISPOSITION_CONSUME; | 731 | return SCTP_DISPOSITION_CONSUME; |
| 725 | 732 | ||
| 733 | nomem_aiev: | ||
| 734 | sctp_ulpevent_free(ev); | ||
| 726 | nomem_ev: | 735 | nomem_ev: |
| 727 | sctp_chunk_free(repl); | 736 | sctp_chunk_free(repl); |
| 728 | nomem_repl: | ||
| 729 | nomem_init: | 737 | nomem_init: |
| 730 | sctp_association_free(new_asoc); | 738 | sctp_association_free(new_asoc); |
| 731 | nomem: | 739 | nomem: |
| @@ -846,6 +854,7 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, | |||
| 846 | hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); | 854 | hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); |
| 847 | hbinfo.daddr = transport->ipaddr; | 855 | hbinfo.daddr = transport->ipaddr; |
| 848 | hbinfo.sent_at = jiffies; | 856 | hbinfo.sent_at = jiffies; |
| 857 | hbinfo.hb_nonce = transport->hb_nonce; | ||
| 849 | 858 | ||
| 850 | /* Send a heartbeat to our peer. */ | 859 | /* Send a heartbeat to our peer. */ |
| 851 | paylen = sizeof(sctp_sender_hb_info_t); | 860 | paylen = sizeof(sctp_sender_hb_info_t); |
| @@ -1048,6 +1057,10 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
| 1048 | return SCTP_DISPOSITION_DISCARD; | 1057 | return SCTP_DISPOSITION_DISCARD; |
| 1049 | } | 1058 | } |
| 1050 | 1059 | ||
| 1060 | /* Validate the 64-bit random nonce. */ | ||
| 1061 | if (hbinfo->hb_nonce != link->hb_nonce) | ||
| 1062 | return SCTP_DISPOSITION_DISCARD; | ||
| 1063 | |||
| 1051 | max_interval = link->hbinterval + link->rto; | 1064 | max_interval = link->hbinterval + link->rto; |
| 1052 | 1065 | ||
| 1053 | /* Check if the timestamp looks valid. */ | 1066 | /* Check if the timestamp looks valid. */ |
| @@ -1355,10 +1368,8 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
| 1355 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1368 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, |
| 1356 | sctp_source(chunk), | 1369 | sctp_source(chunk), |
| 1357 | (sctp_init_chunk_t *)chunk->chunk_hdr, | 1370 | (sctp_init_chunk_t *)chunk->chunk_hdr, |
| 1358 | GFP_ATOMIC)) { | 1371 | GFP_ATOMIC)) |
| 1359 | retval = SCTP_DISPOSITION_NOMEM; | 1372 | goto nomem; |
| 1360 | goto nomem_init; | ||
| 1361 | } | ||
| 1362 | 1373 | ||
| 1363 | /* Make sure no new addresses are being added during the | 1374 | /* Make sure no new addresses are being added during the |
| 1364 | * restart. Do not do this check for COOKIE-WAIT state, | 1375 | * restart. Do not do this check for COOKIE-WAIT state, |
| @@ -1369,7 +1380,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
| 1369 | if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, | 1380 | if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, |
| 1370 | commands)) { | 1381 | commands)) { |
| 1371 | retval = SCTP_DISPOSITION_CONSUME; | 1382 | retval = SCTP_DISPOSITION_CONSUME; |
| 1372 | goto cleanup_asoc; | 1383 | goto nomem_retval; |
| 1373 | } | 1384 | } |
| 1374 | } | 1385 | } |
| 1375 | 1386 | ||
| @@ -1425,17 +1436,17 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
| 1425 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 1436 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
| 1426 | retval = SCTP_DISPOSITION_CONSUME; | 1437 | retval = SCTP_DISPOSITION_CONSUME; |
| 1427 | 1438 | ||
| 1439 | return retval; | ||
| 1440 | |||
| 1441 | nomem: | ||
| 1442 | retval = SCTP_DISPOSITION_NOMEM; | ||
| 1443 | nomem_retval: | ||
| 1444 | if (new_asoc) | ||
| 1445 | sctp_association_free(new_asoc); | ||
| 1428 | cleanup: | 1446 | cleanup: |
| 1429 | if (err_chunk) | 1447 | if (err_chunk) |
| 1430 | sctp_chunk_free(err_chunk); | 1448 | sctp_chunk_free(err_chunk); |
| 1431 | return retval; | 1449 | return retval; |
| 1432 | nomem: | ||
| 1433 | retval = SCTP_DISPOSITION_NOMEM; | ||
| 1434 | goto cleanup; | ||
| 1435 | nomem_init: | ||
| 1436 | cleanup_asoc: | ||
| 1437 | sctp_association_free(new_asoc); | ||
| 1438 | goto cleanup; | ||
| 1439 | } | 1450 | } |
| 1440 | 1451 | ||
| 1441 | /* | 1452 | /* |
| @@ -1606,15 +1617,10 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
| 1606 | */ | 1617 | */ |
| 1607 | sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); | 1618 | sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); |
| 1608 | 1619 | ||
| 1609 | /* Update the content of current association. */ | ||
| 1610 | sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); | ||
| 1611 | |||
| 1612 | repl = sctp_make_cookie_ack(new_asoc, chunk); | 1620 | repl = sctp_make_cookie_ack(new_asoc, chunk); |
| 1613 | if (!repl) | 1621 | if (!repl) |
| 1614 | goto nomem; | 1622 | goto nomem; |
| 1615 | 1623 | ||
| 1616 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
| 1617 | |||
| 1618 | /* Report association restart to upper layer. */ | 1624 | /* Report association restart to upper layer. */ |
| 1619 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, | 1625 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, |
| 1620 | new_asoc->c.sinit_num_ostreams, | 1626 | new_asoc->c.sinit_num_ostreams, |
| @@ -1623,6 +1629,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
| 1623 | if (!ev) | 1629 | if (!ev) |
| 1624 | goto nomem_ev; | 1630 | goto nomem_ev; |
| 1625 | 1631 | ||
| 1632 | /* Update the content of current association. */ | ||
| 1633 | sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); | ||
| 1634 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
| 1626 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); | 1635 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); |
| 1627 | return SCTP_DISPOSITION_CONSUME; | 1636 | return SCTP_DISPOSITION_CONSUME; |
| 1628 | 1637 | ||
| @@ -1746,7 +1755,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
| 1746 | sctp_cmd_seq_t *commands, | 1755 | sctp_cmd_seq_t *commands, |
| 1747 | struct sctp_association *new_asoc) | 1756 | struct sctp_association *new_asoc) |
| 1748 | { | 1757 | { |
| 1749 | struct sctp_ulpevent *ev = NULL; | 1758 | struct sctp_ulpevent *ev = NULL, *ai_ev = NULL; |
| 1750 | struct sctp_chunk *repl; | 1759 | struct sctp_chunk *repl; |
| 1751 | 1760 | ||
| 1752 | /* Clarification from Implementor's Guide: | 1761 | /* Clarification from Implementor's Guide: |
| @@ -1773,29 +1782,25 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
| 1773 | * SCTP user upon reception of a valid COOKIE | 1782 | * SCTP user upon reception of a valid COOKIE |
| 1774 | * ECHO chunk. | 1783 | * ECHO chunk. |
| 1775 | */ | 1784 | */ |
| 1776 | ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, | 1785 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, |
| 1777 | SCTP_COMM_UP, 0, | 1786 | SCTP_COMM_UP, 0, |
| 1778 | new_asoc->c.sinit_num_ostreams, | 1787 | asoc->c.sinit_num_ostreams, |
| 1779 | new_asoc->c.sinit_max_instreams, | 1788 | asoc->c.sinit_max_instreams, |
| 1780 | GFP_ATOMIC); | 1789 | GFP_ATOMIC); |
| 1781 | if (!ev) | 1790 | if (!ev) |
| 1782 | goto nomem; | 1791 | goto nomem; |
| 1783 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
| 1784 | SCTP_ULPEVENT(ev)); | ||
| 1785 | 1792 | ||
| 1786 | /* Sockets API Draft Section 5.3.1.6 | 1793 | /* Sockets API Draft Section 5.3.1.6 |
| 1787 | * When a peer sends a Adaption Layer Indication parameter, | 1794 | * When a peer sends a Adaption Layer Indication parameter, |
| 1788 | * SCTP delivers this notification to inform the application | 1795 | * SCTP delivers this notification to inform the application |
| 1789 | * that of the peers requested adaption layer. | 1796 | * that of the peers requested adaption layer. |
| 1790 | */ | 1797 | */ |
| 1791 | if (new_asoc->peer.adaption_ind) { | 1798 | if (asoc->peer.adaption_ind) { |
| 1792 | ev = sctp_ulpevent_make_adaption_indication(new_asoc, | 1799 | ai_ev = sctp_ulpevent_make_adaption_indication(asoc, |
| 1793 | GFP_ATOMIC); | 1800 | GFP_ATOMIC); |
| 1794 | if (!ev) | 1801 | if (!ai_ev) |
| 1795 | goto nomem; | 1802 | goto nomem; |
| 1796 | 1803 | ||
| 1797 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
| 1798 | SCTP_ULPEVENT(ev)); | ||
| 1799 | } | 1804 | } |
| 1800 | } | 1805 | } |
| 1801 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | 1806 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); |
| @@ -1804,12 +1809,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
| 1804 | if (!repl) | 1809 | if (!repl) |
| 1805 | goto nomem; | 1810 | goto nomem; |
| 1806 | 1811 | ||
| 1812 | if (ev) | ||
| 1813 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
| 1814 | SCTP_ULPEVENT(ev)); | ||
| 1815 | if (ai_ev) | ||
| 1816 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
| 1817 | SCTP_ULPEVENT(ai_ev)); | ||
| 1818 | |||
| 1807 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 1819 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
| 1808 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | 1820 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); |
| 1809 | 1821 | ||
| 1810 | return SCTP_DISPOSITION_CONSUME; | 1822 | return SCTP_DISPOSITION_CONSUME; |
| 1811 | 1823 | ||
| 1812 | nomem: | 1824 | nomem: |
| 1825 | if (ai_ev) | ||
| 1826 | sctp_ulpevent_free(ai_ev); | ||
| 1813 | if (ev) | 1827 | if (ev) |
| 1814 | sctp_ulpevent_free(ev); | 1828 | sctp_ulpevent_free(ev); |
| 1815 | return SCTP_DISPOSITION_NOMEM; | 1829 | return SCTP_DISPOSITION_NOMEM; |
| @@ -2658,9 +2672,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | |||
| 2658 | break; | 2672 | break; |
| 2659 | case SCTP_IERROR_HIGH_TSN: | 2673 | case SCTP_IERROR_HIGH_TSN: |
| 2660 | case SCTP_IERROR_BAD_STREAM: | 2674 | case SCTP_IERROR_BAD_STREAM: |
| 2675 | SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS); | ||
| 2661 | goto discard_noforce; | 2676 | goto discard_noforce; |
| 2662 | case SCTP_IERROR_DUP_TSN: | 2677 | case SCTP_IERROR_DUP_TSN: |
| 2663 | case SCTP_IERROR_IGNORE_TSN: | 2678 | case SCTP_IERROR_IGNORE_TSN: |
| 2679 | SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS); | ||
| 2664 | goto discard_force; | 2680 | goto discard_force; |
| 2665 | case SCTP_IERROR_NO_DATA: | 2681 | case SCTP_IERROR_NO_DATA: |
| 2666 | goto consume; | 2682 | goto consume; |
| @@ -3012,7 +3028,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
| 3012 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 3028 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
| 3013 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3029 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, |
| 3014 | commands); | 3030 | commands); |
| 3015 | |||
| 3016 | /* 10.2 H) SHUTDOWN COMPLETE notification | 3031 | /* 10.2 H) SHUTDOWN COMPLETE notification |
| 3017 | * | 3032 | * |
| 3018 | * When SCTP completes the shutdown procedures (section 9.2) this | 3033 | * When SCTP completes the shutdown procedures (section 9.2) this |
| @@ -3023,6 +3038,14 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
| 3023 | if (!ev) | 3038 | if (!ev) |
| 3024 | goto nomem; | 3039 | goto nomem; |
| 3025 | 3040 | ||
| 3041 | /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ | ||
| 3042 | reply = sctp_make_shutdown_complete(asoc, chunk); | ||
| 3043 | if (!reply) | ||
| 3044 | goto nomem_chunk; | ||
| 3045 | |||
| 3046 | /* Do all the commands now (after allocation), so that we | ||
| 3047 | * have consistent state if memory allocation failes | ||
| 3048 | */ | ||
| 3026 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); | 3049 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); |
| 3027 | 3050 | ||
| 3028 | /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall | 3051 | /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall |
| @@ -3034,11 +3057,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
| 3034 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 3057 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
| 3035 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 3058 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
| 3036 | 3059 | ||
| 3037 | /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ | ||
| 3038 | reply = sctp_make_shutdown_complete(asoc, chunk); | ||
| 3039 | if (!reply) | ||
| 3040 | goto nomem; | ||
| 3041 | |||
| 3042 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 3060 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
| 3043 | SCTP_STATE(SCTP_STATE_CLOSED)); | 3061 | SCTP_STATE(SCTP_STATE_CLOSED)); |
| 3044 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); | 3062 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); |
| @@ -3049,6 +3067,8 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
| 3049 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 3067 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
| 3050 | return SCTP_DISPOSITION_DELETE_TCB; | 3068 | return SCTP_DISPOSITION_DELETE_TCB; |
| 3051 | 3069 | ||
| 3070 | nomem_chunk: | ||
| 3071 | sctp_ulpevent_free(ev); | ||
| 3052 | nomem: | 3072 | nomem: |
| 3053 | return SCTP_DISPOSITION_NOMEM; | 3073 | return SCTP_DISPOSITION_NOMEM; |
| 3054 | } | 3074 | } |
| @@ -3647,6 +3667,7 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep, | |||
| 3647 | void *arg, | 3667 | void *arg, |
| 3648 | sctp_cmd_seq_t *commands) | 3668 | sctp_cmd_seq_t *commands) |
| 3649 | { | 3669 | { |
| 3670 | SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS); | ||
| 3650 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); | 3671 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); |
| 3651 | 3672 | ||
| 3652 | return SCTP_DISPOSITION_CONSUME; | 3673 | return SCTP_DISPOSITION_CONSUME; |
| @@ -4026,18 +4047,12 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
| 4026 | * from its upper layer, but retransmits data to the far end | 4047 | * from its upper layer, but retransmits data to the far end |
| 4027 | * if necessary to fill gaps. | 4048 | * if necessary to fill gaps. |
| 4028 | */ | 4049 | */ |
| 4029 | struct msghdr *msg = arg; | 4050 | struct sctp_chunk *abort = arg; |
| 4030 | struct sctp_chunk *abort; | ||
| 4031 | sctp_disposition_t retval; | 4051 | sctp_disposition_t retval; |
| 4032 | 4052 | ||
| 4033 | retval = SCTP_DISPOSITION_CONSUME; | 4053 | retval = SCTP_DISPOSITION_CONSUME; |
| 4034 | 4054 | ||
| 4035 | /* Generate ABORT chunk to send the peer. */ | 4055 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
| 4036 | abort = sctp_make_abort_user(asoc, NULL, msg); | ||
| 4037 | if (!abort) | ||
| 4038 | retval = SCTP_DISPOSITION_NOMEM; | ||
| 4039 | else | ||
| 4040 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
| 4041 | 4056 | ||
| 4042 | /* Even if we can't send the ABORT due to low memory delete the | 4057 | /* Even if we can't send the ABORT due to low memory delete the |
| 4043 | * TCB. This is a departure from our typical NOMEM handling. | 4058 | * TCB. This is a departure from our typical NOMEM handling. |
| @@ -4161,8 +4176,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
| 4161 | void *arg, | 4176 | void *arg, |
| 4162 | sctp_cmd_seq_t *commands) | 4177 | sctp_cmd_seq_t *commands) |
| 4163 | { | 4178 | { |
| 4164 | struct msghdr *msg = arg; | 4179 | struct sctp_chunk *abort = arg; |
| 4165 | struct sctp_chunk *abort; | ||
| 4166 | sctp_disposition_t retval; | 4180 | sctp_disposition_t retval; |
| 4167 | 4181 | ||
| 4168 | /* Stop T1-init timer */ | 4182 | /* Stop T1-init timer */ |
| @@ -4170,12 +4184,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
| 4170 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 4184 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
| 4171 | retval = SCTP_DISPOSITION_CONSUME; | 4185 | retval = SCTP_DISPOSITION_CONSUME; |
| 4172 | 4186 | ||
| 4173 | /* Generate ABORT chunk to send the peer */ | 4187 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
| 4174 | abort = sctp_make_abort_user(asoc, NULL, msg); | ||
| 4175 | if (!abort) | ||
| 4176 | retval = SCTP_DISPOSITION_NOMEM; | ||
| 4177 | else | ||
| 4178 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
| 4179 | 4188 | ||
| 4180 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4189 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
| 4181 | SCTP_STATE(SCTP_STATE_CLOSED)); | 4190 | SCTP_STATE(SCTP_STATE_CLOSED)); |
| @@ -4555,6 +4564,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
| 4555 | { | 4564 | { |
| 4556 | struct sctp_transport *transport = arg; | 4565 | struct sctp_transport *transport = arg; |
| 4557 | 4566 | ||
| 4567 | SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); | ||
| 4568 | |||
| 4558 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4569 | if (asoc->overall_error_count >= asoc->max_retrans) { |
| 4559 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | 4570 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, |
| 4560 | SCTP_ERROR(ETIMEDOUT)); | 4571 | SCTP_ERROR(ETIMEDOUT)); |
| @@ -4623,6 +4634,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4623 | void *arg, | 4634 | void *arg, |
| 4624 | sctp_cmd_seq_t *commands) | 4635 | sctp_cmd_seq_t *commands) |
| 4625 | { | 4636 | { |
| 4637 | SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS); | ||
| 4626 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); | 4638 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); |
| 4627 | return SCTP_DISPOSITION_CONSUME; | 4639 | return SCTP_DISPOSITION_CONSUME; |
| 4628 | } | 4640 | } |
| @@ -4657,6 +4669,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | |||
| 4657 | int attempts = asoc->init_err_counter + 1; | 4669 | int attempts = asoc->init_err_counter + 1; |
| 4658 | 4670 | ||
| 4659 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); | 4671 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); |
| 4672 | SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS); | ||
| 4660 | 4673 | ||
| 4661 | if (attempts <= asoc->max_init_attempts) { | 4674 | if (attempts <= asoc->max_init_attempts) { |
| 4662 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | 4675 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; |
| @@ -4716,6 +4729,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
| 4716 | int attempts = asoc->init_err_counter + 1; | 4729 | int attempts = asoc->init_err_counter + 1; |
| 4717 | 4730 | ||
| 4718 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); | 4731 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); |
| 4732 | SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS); | ||
| 4719 | 4733 | ||
| 4720 | if (attempts <= asoc->max_init_attempts) { | 4734 | if (attempts <= asoc->max_init_attempts) { |
| 4721 | repl = sctp_make_cookie_echo(asoc, NULL); | 4735 | repl = sctp_make_cookie_echo(asoc, NULL); |
| @@ -4760,6 +4774,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
| 4760 | struct sctp_chunk *reply = NULL; | 4774 | struct sctp_chunk *reply = NULL; |
| 4761 | 4775 | ||
| 4762 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); | 4776 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); |
| 4777 | SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS); | ||
| 4778 | |||
| 4763 | if (asoc->overall_error_count >= asoc->max_retrans) { | 4779 | if (asoc->overall_error_count >= asoc->max_retrans) { |
| 4764 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | 4780 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, |
| 4765 | SCTP_ERROR(ETIMEDOUT)); | 4781 | SCTP_ERROR(ETIMEDOUT)); |
| @@ -4821,6 +4837,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
| 4821 | struct sctp_chunk *chunk = asoc->addip_last_asconf; | 4837 | struct sctp_chunk *chunk = asoc->addip_last_asconf; |
| 4822 | struct sctp_transport *transport = chunk->transport; | 4838 | struct sctp_transport *transport = chunk->transport; |
| 4823 | 4839 | ||
| 4840 | SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS); | ||
| 4841 | |||
| 4824 | /* ADDIP 4.1 B1) Increment the error counters and perform path failure | 4842 | /* ADDIP 4.1 B1) Increment the error counters and perform path failure |
| 4825 | * detection on the appropriate destination address as defined in | 4843 | * detection on the appropriate destination address as defined in |
| 4826 | * RFC2960 [5] section 8.1 and 8.2. | 4844 | * RFC2960 [5] section 8.1 and 8.2. |
| @@ -4887,6 +4905,7 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | |||
| 4887 | struct sctp_chunk *reply = NULL; | 4905 | struct sctp_chunk *reply = NULL; |
| 4888 | 4906 | ||
| 4889 | SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); | 4907 | SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); |
| 4908 | SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); | ||
| 4890 | 4909 | ||
| 4891 | reply = sctp_make_abort(asoc, NULL, 0); | 4910 | reply = sctp_make_abort(asoc, NULL, 0); |
| 4892 | if (!reply) | 4911 | if (!reply) |
| @@ -4917,6 +4936,8 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( | |||
| 4917 | { | 4936 | { |
| 4918 | int disposition; | 4937 | int disposition; |
| 4919 | 4938 | ||
| 4939 | SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS); | ||
| 4940 | |||
| 4920 | /* From 9.2 Shutdown of an Association | 4941 | /* From 9.2 Shutdown of an Association |
| 4921 | * Upon receipt of the SHUTDOWN primitive from its upper | 4942 | * Upon receipt of the SHUTDOWN primitive from its upper |
| 4922 | * layer, the endpoint enters SHUTDOWN-PENDING state and | 4943 | * layer, the endpoint enters SHUTDOWN-PENDING state and |
| @@ -5278,7 +5299,6 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 5278 | datalen -= sizeof(sctp_data_chunk_t); | 5299 | datalen -= sizeof(sctp_data_chunk_t); |
| 5279 | 5300 | ||
| 5280 | deliver = SCTP_CMD_CHUNK_ULP; | 5301 | deliver = SCTP_CMD_CHUNK_ULP; |
| 5281 | chunk->data_accepted = 1; | ||
| 5282 | 5302 | ||
| 5283 | /* Think about partial delivery. */ | 5303 | /* Think about partial delivery. */ |
| 5284 | if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { | 5304 | if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { |
| @@ -5357,6 +5377,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 5357 | if (SCTP_CMD_CHUNK_ULP == deliver) | 5377 | if (SCTP_CMD_CHUNK_ULP == deliver) |
| 5358 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); | 5378 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); |
| 5359 | 5379 | ||
| 5380 | chunk->data_accepted = 1; | ||
| 5381 | |||
| 5360 | /* Note: Some chunks may get overcounted (if we drop) or overcounted | 5382 | /* Note: Some chunks may get overcounted (if we drop) or overcounted |
| 5361 | * if we renege and the chunk arrives again. | 5383 | * if we renege and the chunk arrives again. |
| 5362 | */ | 5384 | */ |
