summaryrefslogtreecommitdiff
path: root/src/charon/control/controller.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/control/controller.c')
-rw-r--r--src/charon/control/controller.c505
1 files changed, 254 insertions, 251 deletions
diff --git a/src/charon/control/controller.c b/src/charon/control/controller.c
index c124f439a..ed52cb0d6 100644
--- a/src/charon/control/controller.c
+++ b/src/charon/control/controller.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: controller.c 4192 2008-07-18 15:51:40Z martin $
+ * $Id: controller.c 4434 2008-10-14 08:52:13Z martin $
*/
#include "controller.h"
@@ -27,7 +27,7 @@
typedef struct private_controller_t private_controller_t;
-typedef struct interface_bus_listener_t interface_bus_listener_t;
+typedef struct interface_listener_t interface_listener_t;
/**
* Private data of an stroke_t object.
@@ -40,16 +40,15 @@ struct private_controller_t {
controller_t public;
};
-
/**
- * helper struct to map bus listener callbacks to interface callbacks
+ * helper struct to map listener callbacks to interface callbacks
*/
-struct interface_bus_listener_t {
+struct interface_listener_t {
/**
* public bus listener interface
*/
- bus_listener_t public;
+ listener_t public;
/**
* status of the operation, return to method callers
@@ -57,11 +56,6 @@ struct interface_bus_listener_t {
status_t status;
/**
- * IKE SA to filter log output
- */
- ike_sa_t *ike_sa;
-
- /**
* interface callback (listener gets redirected to here)
*/
controller_cb_t callback;
@@ -82,6 +76,16 @@ struct interface_bus_listener_t {
peer_cfg_t *peer_cfg;
/**
+ * IKE_SA to handle
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * CHILD_SA to handle
+ */
+ child_sa_t *child_sa;
+
+ /**
* unique ID, used for various methods
*/
u_int32_t id;
@@ -102,38 +106,88 @@ struct interface_job_t {
/**
* associated listener
*/
- interface_bus_listener_t listener;
+ interface_listener_t listener;
};
/**
- * Implementation of controller_t.create_ike_sa_iterator.
+ * listener log function
*/
-static enumerator_t* create_ike_sa_enumerator(controller_t *this)
+static bool listener_log(interface_listener_t *this, debug_t group,
+ level_t level, int thread, ike_sa_t *ike_sa,
+ char* format, va_list args)
{
- return charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+ if (this->ike_sa == ike_sa)
+ {
+ if (!this->callback(this->param, group, level, ike_sa, format, args))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
}
/**
- * listener function for initiate
+ * Implementation of listener_t.ike_state_change
*/
-static bool initiate_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
+static bool listener_ike_state(interface_listener_t *this, ike_sa_t *ike_sa,
+ ike_sa_state_t state)
{
if (this->ike_sa == ike_sa)
{
- if (!this->callback(this->param, signal, level, ike_sa, data,
- format, args))
+ switch (state)
{
- return FALSE;
+#ifdef ME
+ case IKE_ESTABLISHED:
+ { /* mediation connections are complete without CHILD_SA */
+ peer_cfg_t *peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+
+ if (peer_cfg->is_mediation(peer_cfg))
+ {
+ this->status = SUCCESS;
+ return FALSE;
+ }
+ break;
+ }
+#endif /* ME */
+ case IKE_DESTROYING:
+ if (ike_sa->get_state(ike_sa) == IKE_DELETING)
+ { /* proper termination */
+ this->status = SUCCESS;
+ }
+ return FALSE;
+ default:
+ break;
}
- switch (signal)
+ }
+ return TRUE;
+}
+
+/**
+ * Implementation of listener_t.child_state_change
+ */
+static bool listener_child_state(interface_listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
+{
+ if (this->ike_sa == ike_sa)
+ {
+ switch (state)
{
- case CHD_UP_SUCCESS:
+ case CHILD_ROUTED:
+ case CHILD_INSTALLED:
this->status = SUCCESS;
return FALSE;
- case IKE_UP_FAILED:
- case CHD_UP_FAILED:
+ case CHILD_DESTROYING:
+ switch (child_sa->get_state(child_sa))
+ {
+ case CHILD_ROUTED:
+ /* has been unrouted */
+ case CHILD_DELETING:
+ /* proper delete */
+ this->status = SUCCESS;
+ break;
+ default:
+ break;
+ }
return FALSE;
default:
break;
@@ -143,12 +197,32 @@ static bool initiate_listener(interface_bus_listener_t *this, signal_t signal,
}
/**
+ * cleanup job if job is never executed
+ */
+static void recheckin(interface_job_t *job)
+{
+ if (job->listener.ike_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ job->listener.ike_sa);
+ }
+}
+
+/**
+ * Implementation of controller_t.create_ike_sa_iterator.
+ */
+static enumerator_t* create_ike_sa_enumerator(controller_t *this)
+{
+ return charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager);
+}
+
+/**
* execute function for initiate
*/
static status_t initiate_execute(interface_job_t *job)
{
ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
+ interface_listener_t *listener = &job->listener;
peer_cfg_t *peer_cfg = listener->peer_cfg;
ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
@@ -176,72 +250,41 @@ static status_t initiate(private_controller_t *this,
peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
controller_cb_t callback, void *param)
{
- interface_job_t job;
-
- job.listener.public.signal = (void*)initiate_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.child_cfg = child_cfg;
- job.listener.peer_cfg = peer_cfg;
- job.public.execute = (void*)initiate_execute;
- job.public.destroy = nop;
-
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .child_cfg = child_cfg,
+ .peer_cfg = peer_cfg,
+ },
+ .public = {
+ .execute = (void*)initiate_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
if (callback == NULL)
{
return initiate_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
- * 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,
- void* data, char* format, va_list args)
-{
- if (this->ike_sa == ike_sa)
- {
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case IKE_DOWN_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case IKE_DOWN_FAILED:
- return FALSE;
- default:
- break;
- }
- }
- return TRUE;
-}
-
-/**
* execute function for terminate_ike
*/
static status_t terminate_ike_execute(interface_job_t *job)
{
- ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
-
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- listener->id, FALSE);
- if (ike_sa == NULL)
- {
- SIG_IKE(DOWN_FAILED, "unable to terminate, IKE_SA with "
- "ID %d not found", listener->id);
- return NOT_FOUND;
- }
- listener->ike_sa = ike_sa;
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
+ charon->bus->set_sa(charon->bus, ike_sa);
if (ike_sa->delete(ike_sa) == DESTROY_ME)
{
return charon->ike_sa_manager->checkin_and_destroy(
@@ -256,79 +299,103 @@ static status_t terminate_ike_execute(interface_job_t *job)
static status_t terminate_ike(controller_t *this, u_int32_t unique_id,
controller_cb_t callback, void *param)
{
- interface_job_t job;
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = unique_id,
+ },
+ .public = {
+ .execute = (void*)terminate_ike_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
+
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ unique_id, FALSE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to terminate IKE_SA: ID %d not found", unique_id);
+ return NOT_FOUND;
+ }
+ job.listener.ike_sa = ike_sa;
- job.listener.public.signal = (void*)terminate_ike_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.id = unique_id;
- job.public.execute = (void*)terminate_ike_execute;
- job.public.destroy = nop;
-
if (callback == NULL)
{
return terminate_ike_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
+
/**
- * listener function for terminate_child
+ * execute 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,
- void* data, char* format, va_list args)
+static status_t terminate_child_execute(interface_job_t *job)
{
- if (this->ike_sa == ike_sa)
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
+ child_sa_t *child_sa = listener->child_sa;
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+ if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE)) == DESTROY_ME)
{
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case CHD_DOWN_SUCCESS:
- case IKE_DOWN_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case IKE_DOWN_FAILED:
- case CHD_DOWN_FAILED:
- return FALSE;
- default:
- break;
- }
+ return charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
}
- return TRUE;
+ return charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
/**
- * execute function for terminate_child
+ * Implementation of controller_t.terminate_child.
*/
-static status_t terminate_child_execute(interface_job_t *job)
+static status_t terminate_child(controller_t *this, u_int32_t reqid,
+ controller_cb_t callback, void *param)
{
ike_sa_t *ike_sa;
child_sa_t *child_sa;
iterator_t *iterator;
- interface_bus_listener_t *listener = &job->listener;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = reqid,
+ },
+ .public = {
+ .execute = (void*)terminate_child_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- listener->id, TRUE);
+ reqid, TRUE);
if (ike_sa == NULL)
{
- SIG_CHD(DOWN_FAILED, NULL, "unable to terminate, CHILD_SA with "
- "ID %d not found", listener->id);
+ DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found",
+ reqid);
return NOT_FOUND;
}
- listener->ike_sa = ike_sa;
+ job.listener.ike_sa = ike_sa;
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) == listener->id)
+ child_sa->get_reqid(child_sa) == reqid)
{
break;
}
@@ -338,90 +405,30 @@ static status_t terminate_child_execute(interface_job_t *job)
if (child_sa == NULL)
{
- SIG_CHD(DOWN_FAILED, NULL, "unable to terminate, established "
- "CHILD_SA with ID %d not found", listener->id);
+ DBG1(DBG_IKE, "unable to terminate, established "
+ "CHILD_SA with ID %d not found", reqid);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
return NOT_FOUND;
}
-
- if (ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa),
- child_sa->get_spi(child_sa, TRUE)) == DESTROY_ME)
- {
- return 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);
-}
-
-/**
- * Implementation of controller_t.terminate_child.
- */
-static status_t terminate_child(controller_t *this, u_int32_t reqid,
- controller_cb_t callback, void *param)
-{
- interface_job_t job;
-
- job.listener.public.signal = (void*)terminate_child_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.id = reqid;
- job.public.execute = (void*)terminate_child_execute;
- job.public.destroy = nop;
+ job.listener.child_sa = child_sa;
if (callback == NULL)
{
return terminate_child_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
- * listener function for route
- */
-static bool route_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
-{
- if (this->ike_sa == ike_sa)
- {
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case CHD_ROUTE_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case CHD_ROUTE_FAILED:
- return FALSE;
- default:
- break;
- }
- }
- return TRUE;
-}
-
-/**
* execute function for route
*/
static status_t route_execute(interface_job_t *job)
{
- ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
- peer_cfg_t *peer_cfg = listener->peer_cfg;
- ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
- peer_cfg);
- listener->ike_sa = ike_sa;
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
- if (ike_sa->get_peer_cfg(ike_sa) == NULL)
- {
- ike_sa->set_peer_cfg(ike_sa, peer_cfg);
- }
+ charon->bus->set_sa(charon->bus, ike_sa);
if (ike_sa->route(ike_sa, listener->child_cfg) == DESTROY_ME)
{
return charon->ike_sa_manager->checkin_and_destroy(
@@ -437,70 +444,49 @@ static status_t route(controller_t *this,
peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
controller_cb_t callback, void *param)
{
- interface_job_t job;
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .peer_cfg = peer_cfg,
+ .child_cfg = child_cfg,
+ },
+ .public = {
+ .execute = (void*)route_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
- job.listener.public.signal = (void*)route_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.peer_cfg = peer_cfg;
- job.listener.child_cfg = child_cfg;
- job.public.execute = (void*)route_execute;
- job.public.destroy = nop;
-
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
+ if (ike_sa->get_peer_cfg(ike_sa) == NULL)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ }
+ job.listener.ike_sa = ike_sa;
if (callback == NULL)
{
return route_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
- * listener function for unroute
- */
-static bool unroute_listener(interface_bus_listener_t *this, signal_t signal,
- level_t level, int thread, ike_sa_t *ike_sa,
- void* data, char* format, va_list args)
-{
- if (this->ike_sa == ike_sa)
- {
- if (!this->callback(this->param, signal, level, ike_sa,
- data, format, args))
- {
- return FALSE;
- }
- switch (signal)
- {
- case CHD_UNROUTE_SUCCESS:
- this->status = SUCCESS;
- return FALSE;
- case CHD_UNROUTE_FAILED:
- return FALSE;
- default:
- break;
- }
- }
- return TRUE;
-}
-/**
* execute function for unroute
*/
static status_t unroute_execute(interface_job_t *job)
{
- ike_sa_t *ike_sa;
- interface_bus_listener_t *listener = &job->listener;
+ interface_listener_t *listener = &job->listener;
+ ike_sa_t *ike_sa = listener->ike_sa;
- ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
- listener->id, TRUE);
- if (ike_sa == NULL)
- {
- SIG_CHD(DOWN_FAILED, NULL, "unable to unroute, CHILD_SA with "
- "ID %d not found", listener->id);
- return NOT_FOUND;
- }
- listener->ike_sa = ike_sa;
if (ike_sa->unroute(ike_sa, listener->id) == DESTROY_ME)
{
return charon->ike_sa_manager->checkin_and_destroy(
@@ -515,30 +501,47 @@ static status_t unroute_execute(interface_job_t *job)
static status_t unroute(controller_t *this, u_int32_t reqid,
controller_cb_t callback, void *param)
{
- interface_job_t job;
+ ike_sa_t *ike_sa;
+ interface_job_t job = {
+ .listener = {
+ .public = {
+ .log = (void*)listener_log,
+ .ike_state_change = (void*)listener_ike_state,
+ .child_state_change = (void*)listener_child_state,
+ },
+ .callback = callback,
+ .param = param,
+ .status = FAILED,
+ .id = reqid,
+ },
+ .public = {
+ .execute = (void*)unroute_execute,
+ .destroy = (void*)recheckin,
+ },
+ };
- job.listener.public.signal = (void*)unroute_listener;
- job.listener.ike_sa = NULL;
- job.listener.callback = callback;
- job.listener.param = param;
- job.listener.status = FAILED;
- job.listener.id = reqid;
- job.public.execute = (void*)unroute_execute;
- job.public.destroy = nop;
+ ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+ reqid, TRUE);
+ if (ike_sa == NULL)
+ {
+ DBG1(DBG_IKE, "unable to unroute, CHILD_SA with ID %d not found", reqid);
+ return NOT_FOUND;
+ }
+ job.listener.ike_sa = ike_sa;
if (callback == NULL)
{
return unroute_execute(&job);
}
- charon->bus->listen(charon->bus, (bus_listener_t*)&job.listener, (job_t*)&job);
+ charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job);
return job.listener.status;
}
/**
* See header
*/
-bool controller_cb_empty(void *param, signal_t signal, level_t level,
- ike_sa_t *ike_sa, void *data, char *format, va_list args)
+bool controller_cb_empty(void *param, debug_t group, level_t level,
+ ike_sa_t *ike_sa, char *format, va_list args)
{
return TRUE;
}