diff options
author | Vladislav Yasevich <vladislav.yasevich@hp.com> | 2006-08-22 03:19:51 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 17:55:17 -0400 |
commit | df7deeb5402087ea0387173aaf067d37a264a8f0 (patch) | |
tree | 3001b220fe38b48a0bf2d7a4f4590fd2c8ed87e3 | |
parent | ac0b04627269ff16c3c7ab854a65fe6780c6e3e5 (diff) |
[SCTP]: Cleanup nomem handling in the state functions.
This patch cleans up the "nomem" conditions that may occur during the
processing by the state machine functions. In most cases we delay adding
side-effect commands until all memory allocations are done.
Signed-off-by: Vladislav Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/sctp/sm_statefuns.c | 159 |
1 files changed, 86 insertions, 73 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 32f57f42af9e..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 | 657 | ||
669 | if (new_asoc->autoclose) | 658 | /* Delay state machine commands until later. |
670 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 659 | * |
671 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 660 | * Re-build the bind address for the association is done in |
672 | |||
673 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
674 | |||
675 | /* 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)); | ||
717 | |||
718 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
719 | 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: |
@@ -1360,10 +1368,8 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1360 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1368 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, |
1361 | sctp_source(chunk), | 1369 | sctp_source(chunk), |
1362 | (sctp_init_chunk_t *)chunk->chunk_hdr, | 1370 | (sctp_init_chunk_t *)chunk->chunk_hdr, |
1363 | GFP_ATOMIC)) { | 1371 | GFP_ATOMIC)) |
1364 | retval = SCTP_DISPOSITION_NOMEM; | 1372 | goto nomem; |
1365 | goto nomem_init; | ||
1366 | } | ||
1367 | 1373 | ||
1368 | /* Make sure no new addresses are being added during the | 1374 | /* Make sure no new addresses are being added during the |
1369 | * restart. Do not do this check for COOKIE-WAIT state, | 1375 | * restart. Do not do this check for COOKIE-WAIT state, |
@@ -1374,7 +1380,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1374 | if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, | 1380 | if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, |
1375 | commands)) { | 1381 | commands)) { |
1376 | retval = SCTP_DISPOSITION_CONSUME; | 1382 | retval = SCTP_DISPOSITION_CONSUME; |
1377 | goto cleanup_asoc; | 1383 | goto nomem_retval; |
1378 | } | 1384 | } |
1379 | } | 1385 | } |
1380 | 1386 | ||
@@ -1430,17 +1436,17 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1430 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 1436 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
1431 | retval = SCTP_DISPOSITION_CONSUME; | 1437 | retval = SCTP_DISPOSITION_CONSUME; |
1432 | 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); | ||
1433 | cleanup: | 1446 | cleanup: |
1434 | if (err_chunk) | 1447 | if (err_chunk) |
1435 | sctp_chunk_free(err_chunk); | 1448 | sctp_chunk_free(err_chunk); |
1436 | return retval; | 1449 | return retval; |
1437 | nomem: | ||
1438 | retval = SCTP_DISPOSITION_NOMEM; | ||
1439 | goto cleanup; | ||
1440 | nomem_init: | ||
1441 | cleanup_asoc: | ||
1442 | sctp_association_free(new_asoc); | ||
1443 | goto cleanup; | ||
1444 | } | 1450 | } |
1445 | 1451 | ||
1446 | /* | 1452 | /* |
@@ -1611,15 +1617,10 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1611 | */ | 1617 | */ |
1612 | sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); | 1618 | sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); |
1613 | 1619 | ||
1614 | /* Update the content of current association. */ | ||
1615 | sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); | ||
1616 | |||
1617 | repl = sctp_make_cookie_ack(new_asoc, chunk); | 1620 | repl = sctp_make_cookie_ack(new_asoc, chunk); |
1618 | if (!repl) | 1621 | if (!repl) |
1619 | goto nomem; | 1622 | goto nomem; |
1620 | 1623 | ||
1621 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
1622 | |||
1623 | /* Report association restart to upper layer. */ | 1624 | /* Report association restart to upper layer. */ |
1624 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, | 1625 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, |
1625 | new_asoc->c.sinit_num_ostreams, | 1626 | new_asoc->c.sinit_num_ostreams, |
@@ -1628,6 +1629,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1628 | if (!ev) | 1629 | if (!ev) |
1629 | goto nomem_ev; | 1630 | goto nomem_ev; |
1630 | 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)); | ||
1631 | 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)); |
1632 | return SCTP_DISPOSITION_CONSUME; | 1636 | return SCTP_DISPOSITION_CONSUME; |
1633 | 1637 | ||
@@ -1751,7 +1755,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1751 | sctp_cmd_seq_t *commands, | 1755 | sctp_cmd_seq_t *commands, |
1752 | struct sctp_association *new_asoc) | 1756 | struct sctp_association *new_asoc) |
1753 | { | 1757 | { |
1754 | struct sctp_ulpevent *ev = NULL; | 1758 | struct sctp_ulpevent *ev = NULL, *ai_ev = NULL; |
1755 | struct sctp_chunk *repl; | 1759 | struct sctp_chunk *repl; |
1756 | 1760 | ||
1757 | /* Clarification from Implementor's Guide: | 1761 | /* Clarification from Implementor's Guide: |
@@ -1778,29 +1782,25 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1778 | * SCTP user upon reception of a valid COOKIE | 1782 | * SCTP user upon reception of a valid COOKIE |
1779 | * ECHO chunk. | 1783 | * ECHO chunk. |
1780 | */ | 1784 | */ |
1781 | ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, | 1785 | ev = sctp_ulpevent_make_assoc_change(asoc, 0, |
1782 | SCTP_COMM_UP, 0, | 1786 | SCTP_COMM_UP, 0, |
1783 | new_asoc->c.sinit_num_ostreams, | 1787 | asoc->c.sinit_num_ostreams, |
1784 | new_asoc->c.sinit_max_instreams, | 1788 | asoc->c.sinit_max_instreams, |
1785 | GFP_ATOMIC); | 1789 | GFP_ATOMIC); |
1786 | if (!ev) | 1790 | if (!ev) |
1787 | goto nomem; | 1791 | goto nomem; |
1788 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
1789 | SCTP_ULPEVENT(ev)); | ||
1790 | 1792 | ||
1791 | /* Sockets API Draft Section 5.3.1.6 | 1793 | /* Sockets API Draft Section 5.3.1.6 |
1792 | * When a peer sends a Adaption Layer Indication parameter, | 1794 | * When a peer sends a Adaption Layer Indication parameter, |
1793 | * SCTP delivers this notification to inform the application | 1795 | * SCTP delivers this notification to inform the application |
1794 | * that of the peers requested adaption layer. | 1796 | * that of the peers requested adaption layer. |
1795 | */ | 1797 | */ |
1796 | if (new_asoc->peer.adaption_ind) { | 1798 | if (asoc->peer.adaption_ind) { |
1797 | ev = sctp_ulpevent_make_adaption_indication(new_asoc, | 1799 | ai_ev = sctp_ulpevent_make_adaption_indication(asoc, |
1798 | GFP_ATOMIC); | 1800 | GFP_ATOMIC); |
1799 | if (!ev) | 1801 | if (!ai_ev) |
1800 | goto nomem; | 1802 | goto nomem; |
1801 | 1803 | ||
1802 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | ||
1803 | SCTP_ULPEVENT(ev)); | ||
1804 | } | 1804 | } |
1805 | } | 1805 | } |
1806 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | 1806 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); |
@@ -1809,12 +1809,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1809 | if (!repl) | 1809 | if (!repl) |
1810 | goto nomem; | 1810 | goto nomem; |
1811 | 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 | |||
1812 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 1819 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
1813 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | 1820 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); |
1814 | 1821 | ||
1815 | return SCTP_DISPOSITION_CONSUME; | 1822 | return SCTP_DISPOSITION_CONSUME; |
1816 | 1823 | ||
1817 | nomem: | 1824 | nomem: |
1825 | if (ai_ev) | ||
1826 | sctp_ulpevent_free(ai_ev); | ||
1818 | if (ev) | 1827 | if (ev) |
1819 | sctp_ulpevent_free(ev); | 1828 | sctp_ulpevent_free(ev); |
1820 | return SCTP_DISPOSITION_NOMEM; | 1829 | return SCTP_DISPOSITION_NOMEM; |
@@ -3019,7 +3028,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3019 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 3028 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
3020 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3029 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, |
3021 | commands); | 3030 | commands); |
3022 | |||
3023 | /* 10.2 H) SHUTDOWN COMPLETE notification | 3031 | /* 10.2 H) SHUTDOWN COMPLETE notification |
3024 | * | 3032 | * |
3025 | * When SCTP completes the shutdown procedures (section 9.2) this | 3033 | * When SCTP completes the shutdown procedures (section 9.2) this |
@@ -3030,6 +3038,14 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3030 | if (!ev) | 3038 | if (!ev) |
3031 | goto nomem; | 3039 | goto nomem; |
3032 | 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 | */ | ||
3033 | 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)); |
3034 | 3050 | ||
3035 | /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall | 3051 | /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall |
@@ -3041,11 +3057,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3041 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 3057 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
3042 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 3058 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
3043 | 3059 | ||
3044 | /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ | ||
3045 | reply = sctp_make_shutdown_complete(asoc, chunk); | ||
3046 | if (!reply) | ||
3047 | goto nomem; | ||
3048 | |||
3049 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 3060 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
3050 | SCTP_STATE(SCTP_STATE_CLOSED)); | 3061 | SCTP_STATE(SCTP_STATE_CLOSED)); |
3051 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); | 3062 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); |
@@ -3056,6 +3067,8 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3056 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 3067 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
3057 | return SCTP_DISPOSITION_DELETE_TCB; | 3068 | return SCTP_DISPOSITION_DELETE_TCB; |
3058 | 3069 | ||
3070 | nomem_chunk: | ||
3071 | sctp_ulpevent_free(ev); | ||
3059 | nomem: | 3072 | nomem: |
3060 | return SCTP_DISPOSITION_NOMEM; | 3073 | return SCTP_DISPOSITION_NOMEM; |
3061 | } | 3074 | } |