diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index af45213a5..7615177e4 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -53,7 +53,6 @@ processing/job_queue.c processing/job_queue.h \ processing/jobs/acquire_job.c processing/jobs/acquire_job.h \ processing/jobs/delete_child_sa_job.c processing/jobs/delete_child_sa_job.h \ processing/jobs/delete_ike_sa_job.c processing/jobs/delete_ike_sa_job.h \ -processing/jobs/initiate_job.c processing/jobs/initiate_job.h \ processing/jobs/job.c processing/jobs/job.h \ processing/jobs/process_message_job.c processing/jobs/process_message_job.h \ processing/jobs/rekey_child_sa_job.c processing/jobs/rekey_child_sa_job.h \ diff --git a/src/charon/control/interface_manager.c b/src/charon/control/interface_manager.c index a50b57412..79f412ef7 100644 --- a/src/charon/control/interface_manager.c +++ b/src/charon/control/interface_manager.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include typedef struct private_interface_manager_t private_interface_manager_t; @@ -82,6 +80,11 @@ struct interface_bus_listener_t { * user parameter to pass to callback */ void *param; + + /** + * caller has cancelled its listening subscription + */ + bool cancelled; }; /** @@ -93,86 +96,46 @@ static iterator_t* create_ike_sa_iterator(interface_manager_t *this) } /** - * Implementation of interface_manager_t.initiate. + * listener function for initiate */ -static status_t initiate(private_interface_manager_t *this, - peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - interface_manager_cb_t cb, void *param) -{ - ike_sa_t *ours = NULL; - job_t *job; - status_t retval; - - charon->bus->set_listen_state(charon->bus, TRUE); - - job = (job_t*)initiate_job_create(peer_cfg, child_cfg); - charon->job_queue->add(charon->job_queue, job); - - while (TRUE) - { - level_t level; - signal_t signal; - int thread; - ike_sa_t *ike_sa; - char* format; - va_list args; - - signal = charon->bus->listen(charon->bus, &level, &thread, - &ike_sa, &format, &args); - - if (cb && (ike_sa == ours || ours == NULL)) - { - if (!cb(param, signal, level, ike_sa, format, args)) - { - charon->bus->set_listen_state(charon->bus, FALSE); - return NEED_MORE; - } - } - - switch (signal) - { - case CHILD_UP_SUCCESS: - if (ike_sa == ours) - { - retval = SUCCESS; - break; - } - continue; - case CHILD_UP_FAILED: - case IKE_UP_FAILED: - if (ike_sa == ours) - { - retval = FAILED; - break; - } - continue; - case CHILD_UP_START: - case IKE_UP_START: - if (ours == NULL) - { - ours = ike_sa; - } - continue; - default: - continue; - } - break; - } - charon->bus->set_listen_state(charon->bus, FALSE); - return retval; -} - -/** - * listener function for terminate_ike - */ -static bool terminate_listener(interface_bus_listener_t *this, signal_t signal, - level_t level, int thread, ike_sa_t *ike_sa, - char* format, va_list args) +static bool initiate_listener(interface_bus_listener_t *this, signal_t signal, + level_t level, int thread, ike_sa_t *ike_sa, + char* format, va_list args) { if (this->ike_sa == ike_sa) { if (!this->callback(this->param, signal, level, ike_sa, format, args)) { + this->cancelled = TRUE; + return FALSE; + } + switch (signal) + { + case IKE_UP_FAILED: + case CHILD_UP_FAILED: + case CHILD_UP_SUCCESS: + { + return FALSE; + } + default: + break; + } + } + return TRUE; +} + +/** + * listener function for terminate_ike + */ +static bool terminate_ike_listener(interface_bus_listener_t *this, signal_t signal, + level_t level, int thread, ike_sa_t *ike_sa, + char* format, va_list args) +{ + if (this->ike_sa == ike_sa) + { + if (!this->callback(this->param, signal, level, ike_sa, format, args)) + { + this->cancelled = TRUE; return FALSE; } switch (signal) @@ -189,6 +152,117 @@ static bool terminate_listener(interface_bus_listener_t *this, signal_t signal, return TRUE; } +/** + * listener function for terminate_child + */ +static bool terminate_child_listener(interface_bus_listener_t *this, signal_t signal, + level_t level, int thread, ike_sa_t *ike_sa, + char* format, va_list args) +{ + if (this->ike_sa == ike_sa) + { + if (!this->callback(this->param, signal, level, ike_sa, format, args)) + { + this->cancelled = TRUE; + return FALSE; + } + switch (signal) + { + case IKE_DOWN_FAILED: + case IKE_DOWN_SUCCESS: + case CHILD_DOWN_FAILED: + case CHILD_DOWN_SUCCESS: + { + return FALSE; + } + default: + break; + } + } + return TRUE; +} + +/** + * Implementation of interface_manager_t.initiate. + */ +static status_t initiate(private_interface_manager_t *this, + peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, + interface_manager_cb_t callback, void *param) +{ + ike_sa_t *ike_sa; + ike_cfg_t *ike_cfg; + status_t retval = FAILED; + interface_bus_listener_t listener; + + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); + ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager, + ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg), + peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg)); + + if (ike_sa->get_peer_cfg(ike_sa) == NULL) + { + ike_sa->set_peer_cfg(ike_sa, peer_cfg); + } + + listener.listener.signal = (void*)initiate_listener; + listener.callback = callback; + listener.ike_sa = ike_sa; + listener.param = param; + listener.cancelled = FALSE; + + /* we listen passively to catch the signals we are raising in + * ike_sa->delete(). */ + if (callback) + { + charon->bus->add_listener(charon->bus, &listener.listener); + } + charon->bus->set_listen_state(charon->bus, TRUE); + if (ike_sa->initiate(ike_sa, child_cfg) != SUCCESS) + { + charon->bus->set_listen_state(charon->bus, FALSE); + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); + return FAILED; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + + /* wait until we get a result */ + while (TRUE) + { + level_t level; + signal_t signal; + int thread; + ike_sa_t *current; + char* format; + va_list args; + + /* stop listening if the passive listener returned FALSE */ + if (listener.cancelled) + { + retval = NEED_MORE; + break; + } + signal = charon->bus->listen(charon->bus, &level, &thread, + ¤t, &format, &args); + /* ike_sa is a valid pointer until we get one of the signals */ + if (ike_sa == current) + { + switch (signal) + { + case CHILD_UP_SUCCESS: + retval = SUCCESS; + case CHILD_UP_FAILED: + case IKE_UP_FAILED: + break; + default: + continue; + } + break; + } + } + charon->bus->set_listen_state(charon->bus, FALSE); + return retval; +} + /** * Implementation of interface_manager_t.terminate_ike. */ @@ -196,7 +270,8 @@ static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, interface_manager_cb_t callback, void *param) { ike_sa_t *ike_sa; - status_t status; + status_t status = FAILED;; + interface_bus_listener_t listener; ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, unique_id, FALSE); @@ -205,15 +280,15 @@ static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, return NOT_FOUND; } - /* we listen passively first, to catch the signals we are raising */ + /* we listen passively to catch the signals we are raising in + * ike_sa->delete(). */ + listener.listener.signal = (void*)terminate_ike_listener; + listener.callback = callback; + listener.ike_sa = ike_sa; + listener.param = param; + listener.cancelled = FALSE; if (callback) { - interface_bus_listener_t listener; - - listener.listener.signal = (void*)terminate_listener; - listener.callback = callback; - listener.ike_sa = ike_sa; - listener.param = param; charon->bus->add_listener(charon->bus, &listener.listener); } charon->bus->set_listen_state(charon->bus, TRUE); @@ -236,9 +311,17 @@ static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, char* format; va_list args; + /* stop listening if the passive listener returned FALSE */ + if (listener.cancelled) + { + status = NEED_MORE; + break; + } signal = charon->bus->listen(charon->bus, &level, &thread, ¤t, &format, &args); - + + /* even if we checked in the IKE_SA, the pointer is valid until + * we get an IKE_DOWN_... */ if (ike_sa == current) { switch (signal) @@ -246,7 +329,8 @@ static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, case IKE_DOWN_FAILED: case IKE_DOWN_SUCCESS: { - break; + status = SUCCESS; + break; } default: continue; @@ -257,7 +341,7 @@ static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, } charon->bus->set_listen_state(charon->bus, FALSE); - return SUCCESS; + return status; } /** @@ -266,7 +350,100 @@ static status_t terminate_ike(interface_manager_t *this, u_int32_t unique_id, static status_t terminate_child(interface_manager_t *this, u_int32_t reqid, interface_manager_cb_t callback, void *param) { - return FAILED; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + iterator_t *iterator; + status_t status = FAILED; + interface_bus_listener_t listener; + + ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, + reqid, TRUE); + if (ike_sa == NULL) + { + return NOT_FOUND; + } + + iterator = ike_sa->create_child_sa_iterator(ike_sa); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + if (child_sa->get_state(child_sa) != CHILD_ROUTED && + child_sa->get_reqid(child_sa) == reqid) + { + break; + } + child_sa = NULL; + } + iterator->destroy(iterator); + + if (child_sa == NULL) + { + return NOT_FOUND; + } + + listener.listener.signal = (void*)terminate_child_listener; + listener.callback = callback; + listener.ike_sa = ike_sa; + listener.param = param; + listener.cancelled = FALSE; + + /* we listen passively to catch the signals we are raising */ + if (callback) + { + charon->bus->add_listener(charon->bus, &listener.listener); + } + charon->bus->set_listen_state(charon->bus, TRUE); + status = ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + if (status == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + + /* wait until CHILD_SA is cleanly deleted using a delete message */ + while (TRUE) + { + level_t level; + signal_t signal; + int thread; + ike_sa_t *current; + char* format; + va_list args; + + /* stop listening if the passive listener returned FALSE */ + if (listener.cancelled) + { + status = NEED_MORE; + break; + } + signal = charon->bus->listen(charon->bus, &level, &thread, + ¤t, &format, &args); + /* even if we checked in the IKE_SA, the pointer is valid until + * we get an IKE_DOWN_... */ + if (ike_sa == current) + { + switch (signal) + { + case IKE_DOWN_FAILED: + case IKE_DOWN_SUCCESS: + case CHILD_DOWN_FAILED: + case CHILD_DOWN_SUCCESS: + { + status = SUCCESS; + break; + } + default: + continue; + } + break; + } + } + } + charon->bus->set_listen_state(charon->bus, FALSE); + + return status; } /** diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index d84199220..26a031b14 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -661,9 +660,12 @@ static bool stroke_log(stroke_log_info_t *info, signal_t signal, level_t level, { if (level <= info->level) { - vfprintf(info->out, format, args); - fprintf(info->out, "\n"); - fflush(info->out); + if (vfprintf(info->out, format, args) < 0 || + fprintf(info->out, "\n") < 0 || + fflush(info->out) != 0) + { + return FALSE; + } } return TRUE; } @@ -748,6 +750,8 @@ static void stroke_initiate(private_stroke_interface_t *this, charon->interfaces->initiate(charon->interfaces, peer_cfg, child_cfg, (interface_manager_cb_t)stroke_log, &info); + peer_cfg->destroy(peer_cfg); + child_cfg->destroy(child_cfg); } /** @@ -799,8 +803,9 @@ static void stroke_terminate(private_stroke_interface_t *this, u_int32_t id = 0; bool child; int len; - status_t status = SUCCESS;; ike_sa_t *ike_sa; + iterator_t *iterator; + stroke_log_info_t info; pop_string(msg, &(msg->terminate.name)); string = msg->terminate.name; @@ -829,20 +834,16 @@ static void stroke_terminate(private_stroke_interface_t *this, } if (name) - { /* must be a single name */ - DBG1(DBG_CFG, "check out by single name '%s'", name); - ike_sa = charon->ike_sa_manager->checkout_by_name(charon->ike_sa_manager, - name, child); + { + /* is a single name */ } else if (pos == string + len - 2) - { /* must be name[] or name{} */ + { /* is name[] or name{} */ string[len-2] = '\0'; - DBG1(DBG_CFG, "check out by name '%s'", string); - ike_sa = charon->ike_sa_manager->checkout_by_name(charon->ike_sa_manager, - string, child); + name = string; } else - { /* must be name[123] or name{23} */ + { /* is name[123] or name{23} */ string[len-1] = '\0'; id = atoi(pos + 1); if (id == 0) @@ -850,45 +851,51 @@ static void stroke_terminate(private_stroke_interface_t *this, DBG1(DBG_CFG, "error parsing string"); return; } - DBG1(DBG_CFG, "check out by id '%d'", id); - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - id, child); - } - if (ike_sa == NULL) - { - DBG1(DBG_CFG, "no such IKE_SA found"); - return; } - if (!child) - { - status = ike_sa->delete(ike_sa); - } - else + info.out = out; + info.level = msg->output_verbosity; + + iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces); + while (iterator->iterate(iterator, (void**)&ike_sa)) { child_sa_t *child_sa; - iterator_t *iterator = ike_sa->create_child_sa_iterator(ike_sa); - while (iterator->iterate(iterator, (void**)&child_sa)) + iterator_t *children; + + if (child) { - if ((id && id == child_sa->get_reqid(child_sa)) || - (string && streq(string, child_sa->get_name(child_sa)))) + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) { - u_int32_t spi = child_sa->get_spi(child_sa, TRUE); - protocol_id_t proto = child_sa->get_protocol(child_sa); - - status = ike_sa->delete_child_sa(ike_sa, proto, spi); - break; + if ((name && streq(name, child_sa->get_name(child_sa))) || + (id && id == child_sa->get_reqid(child_sa))) + { + id = child_sa->get_reqid(child_sa); + children->destroy(children); + iterator->destroy(iterator); + + charon->interfaces->terminate_child(charon->interfaces, id, + (interface_manager_cb_t)stroke_log, &info); + return; + } } + children->destroy(children); } - iterator->destroy(iterator); + else if ((name && streq(name, ike_sa->get_name(ike_sa))) || + (id && id == ike_sa->get_unique_id(ike_sa))) + { + id = ike_sa->get_unique_id(ike_sa); + /* unlock manager first */ + iterator->destroy(iterator); + + charon->interfaces->terminate_ike(charon->interfaces, id, + (interface_manager_cb_t)stroke_log, &info); + return; + } + } - if (status == DESTROY_ME) - { - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - ike_sa); - return; - } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + iterator->destroy(iterator); + DBG1(DBG_CFG, "no such SA found"); } /** @@ -1528,8 +1535,8 @@ static void stroke_receive(private_stroke_interface_t *this) int oldstate; int strokefd; - /* drop threads capabilities */ - charon->drop_capabilities(charon, TRUE, FALSE, FALSE); + /* drop threads capabilities, keep NET_ADMIN to query use times for status */ + charon->drop_capabilities(charon, TRUE, TRUE, FALSE); /* ignore sigpipe. writing over the pipe back to the console * only fails if SIGPIPE is ignored. */ diff --git a/src/charon/daemon.c b/src/charon/daemon.c index e266c967d..467725249 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -569,7 +569,7 @@ int main(int argc, char *argv[]) list->destroy(list); /* change UID */ - drop_capabilities(private_charon, TRUE, FALSE, FALSE); + drop_capabilities(private_charon, TRUE, TRUE, FALSE); /* run daemon */ run(private_charon); diff --git a/src/charon/processing/jobs/initiate_job.c b/src/charon/processing/jobs/initiate_job.c deleted file mode 100644 index 68ca17258..000000000 --- a/src/charon/processing/jobs/initiate_job.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file initiate_job.c - * - * @brief Implementation of initiate_job_t. - * - */ - -/* - * Copyright (C) 2005-2007 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - - -#include - -#include "initiate_job.h" - -#include - -typedef struct private_initiate_job_t private_initiate_job_t; - -/** - * Private data of an initiate_job_t Object - */ -struct private_initiate_job_t { - /** - * public initiate_job_t interface - */ - initiate_job_t public; - - /** - * associated peer config to use for IKE_SA setup - */ - peer_cfg_t *peer_cfg; - - /** - * child config to use for CHILD_SA - */ - child_cfg_t *child_cfg; -}; - -/** - * Implements initiate_job_t.get_type. - */ -static job_type_t get_type(private_initiate_job_t *this) -{ - return INITIATE; -} - -/** - * Implementation of job_t.execute. - */ -static status_t execute(private_initiate_job_t *this) -{ - ike_sa_t *ike_sa; - ike_cfg_t *ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg); - - ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager, - ike_cfg->get_my_host(ike_cfg), - ike_cfg->get_other_host(ike_cfg), - this->peer_cfg->get_my_id(this->peer_cfg), - this->peer_cfg->get_other_id(this->peer_cfg)); - - if (ike_sa->get_peer_cfg(ike_sa) == NULL) - { - ike_sa->set_peer_cfg(ike_sa, this->peer_cfg); - } - - if (ike_sa->initiate(ike_sa, this->child_cfg) != SUCCESS) - { - DBG1(DBG_JOB, "initiation failed, going to delete IKE_SA"); - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa); - return DESTROY_ME; - } - - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - return DESTROY_ME; -} - -/** - * Implements job_t.destroy. - */ -static void destroy(private_initiate_job_t *this) -{ - this->peer_cfg->destroy(this->peer_cfg); - this->child_cfg->destroy(this->child_cfg); - free(this); -} - -/* - * Described in header - */ -initiate_job_t *initiate_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg) -{ - private_initiate_job_t *this = malloc_thing(private_initiate_job_t); - - /* interface functions */ - this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type; - this->public.job_interface.execute = (status_t (*) (job_t *)) execute; - this->public.job_interface.destroy = (void (*) (job_t *)) destroy; - - /* private variables */ - this->peer_cfg = peer_cfg; - this->child_cfg = child_cfg; - - return &this->public; -} diff --git a/src/charon/processing/jobs/initiate_job.h b/src/charon/processing/jobs/initiate_job.h deleted file mode 100644 index 15b46a74c..000000000 --- a/src/charon/processing/jobs/initiate_job.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file initiate_job.h - * - * @brief Interface of initiate_job_t. - */ - -/* - * Copyright (C) 2005-2007 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef INITIATE_JOB_H_ -#define INITIATE_JOB_H_ - -typedef struct initiate_job_t initiate_job_t; - -#include -#include -#include -#include - -/** - * @brief Class representing an INITIATE_IKE_SA Job. - * - * This job is created if an IKE_SA should be iniated. - * - * @b Constructors: - * - initiate_job_create() - * - * @ingroup jobs - */ -struct initiate_job_t { - /** - * implements job_t interface - */ - job_t job_interface; -}; - -/** - * @brief Creates a job of type INITIATE. - * - * @param peer_cfg peer configuration to use (if not yet established) - * @param child_cfg config to create a CHILD from - * @return initiate_job_t object - * - * @ingroup jobs - */ -initiate_job_t *initiate_job_create(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg); - -#endif /*INITIATE_JOB_H_*/ diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index e9c56dcbc..16c87bf86 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -63,7 +63,6 @@ #include #include #include -#include #ifndef RESOLV_CONF @@ -1512,8 +1511,6 @@ static status_t delete_(private_ike_sa_t *this) switch (this->state) { case IKE_ESTABLISHED: - DBG1(DBG_IKE, "deleting IKE_SA"); - /* do not log when rekeyed */ case IKE_REKEYING: ike_delete = ike_delete_create(&this->public, TRUE); this->task_manager->queue_task(this->task_manager, &ike_delete->task); diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c index 23d509de5..d0b34a276 100644 --- a/src/charon/sa/tasks/child_delete.c +++ b/src/charon/sa/tasks/child_delete.c @@ -176,11 +176,30 @@ static void destroy_children(private_child_delete_t *this) iterator->destroy(iterator); } +/** + * send closing signals for all CHILD_SAs over the bus + */ +static void log_children(private_child_delete_t *this) +{ + iterator_t *iterator; + child_sa_t *child_sa; + + iterator = this->child_sas->create_iterator(this->child_sas, TRUE); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + SIG(CHILD_DOWN_START, "closing CHILD_SA %#R=== %#R", + child_sa->get_traffic_selectors(child_sa, TRUE), + child_sa->get_traffic_selectors(child_sa, FALSE)); + } + iterator->destroy(iterator); +} + /** * Implementation of task_t.build for initiator */ static status_t build_i(private_child_delete_t *this, message_t *message) { + log_children(this); build_payloads(this, message); return NEED_MORE; } @@ -196,6 +215,7 @@ static status_t process_i(private_child_delete_t *this, message_t *message) process_payloads(this, message); destroy_children(this); + SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed"); return SUCCESS; } @@ -205,6 +225,7 @@ static status_t process_i(private_child_delete_t *this, message_t *message) static status_t process_r(private_child_delete_t *this, message_t *message) { process_payloads(this, message); + log_children(this); return NEED_MORE; } @@ -219,6 +240,7 @@ static status_t build_r(private_child_delete_t *this, message_t *message) build_payloads(this, message); } destroy_children(this); + SIG(CHILD_DOWN_SUCCESS, "CHILD_SA closed"); return SUCCESS; }