2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "controller.h"
18 #include <sys/types.h>
27 typedef struct private_controller_t private_controller_t
;
28 typedef struct interface_listener_t interface_listener_t
;
31 * Private data of an stroke_t object.
33 struct private_controller_t
{
36 * Public part of stroke_t object.
42 * helper struct to map listener callbacks to interface callbacks
44 struct interface_listener_t
{
47 * public bus listener interface
52 * status of the operation, return to method callers
57 * interface callback (listener gets redirected to here)
59 controller_cb_t callback
;
62 * user parameter to pass to callback
67 * child configuration, used for initiate
69 child_cfg_t
*child_cfg
;
72 * peer configuration, used for initiate
87 * unique ID, used for various methods
93 typedef struct interface_job_t interface_job_t
;
96 * job for asynchronous listen operations
98 struct interface_job_t
{
105 * associated listener
107 interface_listener_t listener
;
111 * listener log function
113 static bool listener_log(interface_listener_t
*this, debug_t group
,
114 level_t level
, int thread
, ike_sa_t
*ike_sa
,
115 char* format
, va_list args
)
117 if (this->ike_sa
== ike_sa
)
119 if (!this->callback(this->param
, group
, level
, ike_sa
, format
, args
))
128 * Implementation of listener_t.ike_state_change
130 static bool listener_ike_state(interface_listener_t
*this, ike_sa_t
*ike_sa
,
131 ike_sa_state_t state
)
133 if (this->ike_sa
== ike_sa
)
138 case IKE_ESTABLISHED
:
139 { /* mediation connections are complete without CHILD_SA */
140 peer_cfg_t
*peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
142 if (peer_cfg
->is_mediation(peer_cfg
))
144 this->status
= SUCCESS
;
151 if (ike_sa
->get_state(ike_sa
) == IKE_DELETING
)
152 { /* proper termination */
153 this->status
= SUCCESS
;
164 * Implementation of listener_t.child_state_change
166 static bool listener_child_state(interface_listener_t
*this, ike_sa_t
*ike_sa
,
167 child_sa_t
*child_sa
, child_sa_state_t state
)
169 if (this->ike_sa
== ike_sa
)
173 case CHILD_INSTALLED
:
174 this->status
= SUCCESS
;
176 case CHILD_DESTROYING
:
177 switch (child_sa
->get_state(child_sa
))
181 this->status
= SUCCESS
;
195 * cleanup job if job is never executed
197 static void recheckin(interface_job_t
*job
)
199 if (job
->listener
.ike_sa
)
201 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
,
202 job
->listener
.ike_sa
);
207 * Implementation of controller_t.create_ike_sa_iterator.
209 static enumerator_t
* create_ike_sa_enumerator(controller_t
*this)
211 return charon
->ike_sa_manager
->create_enumerator(charon
->ike_sa_manager
);
215 * execute function for initiate
217 static status_t
initiate_execute(interface_job_t
*job
)
220 interface_listener_t
*listener
= &job
->listener
;
221 peer_cfg_t
*peer_cfg
= listener
->peer_cfg
;
223 ike_sa
= charon
->ike_sa_manager
->checkout_by_config(charon
->ike_sa_manager
,
225 listener
->ike_sa
= ike_sa
;
227 if (ike_sa
->get_peer_cfg(ike_sa
) == NULL
)
229 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
231 peer_cfg
->destroy(peer_cfg
);
233 if (ike_sa
->initiate(ike_sa
, listener
->child_cfg
, 0, NULL
, NULL
) == SUCCESS
)
235 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
238 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
, ike_sa
);
243 * Implementation of controller_t.initiate.
245 static status_t
initiate(private_controller_t
*this,
246 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
247 controller_cb_t callback
, void *param
)
249 interface_job_t job
= {
252 .log
= (void*)listener_log
,
253 .ike_state_change
= (void*)listener_ike_state
,
254 .child_state_change
= (void*)listener_child_state
,
256 .callback
= callback
,
259 .child_cfg
= child_cfg
,
260 .peer_cfg
= peer_cfg
,
263 .execute
= (void*)initiate_execute
,
264 .destroy
= (void*)recheckin
,
267 if (callback
== NULL
)
269 return initiate_execute(&job
);
271 charon
->bus
->listen(charon
->bus
, &job
.listener
.public, (job_t
*)&job
);
272 return job
.listener
.status
;
276 * execute function for terminate_ike
278 static status_t
terminate_ike_execute(interface_job_t
*job
)
280 interface_listener_t
*listener
= &job
->listener
;
281 ike_sa_t
*ike_sa
= listener
->ike_sa
;
283 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
285 if (ike_sa
->delete(ike_sa
) != DESTROY_ME
)
287 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
291 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
, ike_sa
);
296 * Implementation of controller_t.terminate_ike.
298 static status_t
terminate_ike(controller_t
*this, u_int32_t unique_id
,
299 controller_cb_t callback
, void *param
)
302 interface_job_t job
= {
305 .log
= (void*)listener_log
,
306 .ike_state_change
= (void*)listener_ike_state
,
307 .child_state_change
= (void*)listener_child_state
,
309 .callback
= callback
,
315 .execute
= (void*)terminate_ike_execute
,
316 .destroy
= (void*)recheckin
,
320 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
324 DBG1(DBG_IKE
, "unable to terminate IKE_SA: ID %d not found", unique_id
);
327 job
.listener
.ike_sa
= ike_sa
;
329 if (callback
== NULL
)
331 return terminate_ike_execute(&job
);
333 charon
->bus
->listen(charon
->bus
, &job
.listener
.public, (job_t
*)&job
);
334 /* checkin of the ike_sa happend in the thread that executed the job */
335 charon
->bus
->set_sa(charon
->bus
, NULL
);
336 return job
.listener
.status
;
340 * execute function for terminate_child
342 static status_t
terminate_child_execute(interface_job_t
*job
)
344 interface_listener_t
*listener
= &job
->listener
;
345 ike_sa_t
*ike_sa
= listener
->ike_sa
;
346 child_sa_t
*child_sa
= listener
->child_sa
;
348 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
349 if (ike_sa
->delete_child_sa(ike_sa
, child_sa
->get_protocol(child_sa
),
350 child_sa
->get_spi(child_sa
, TRUE
)) != DESTROY_ME
)
352 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
355 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
, ike_sa
);
360 * Implementation of controller_t.terminate_child.
362 static status_t
terminate_child(controller_t
*this, u_int32_t reqid
,
363 controller_cb_t callback
, void *param
)
366 child_sa_t
*child_sa
;
367 iterator_t
*iterator
;
368 interface_job_t job
= {
371 .log
= (void*)listener_log
,
372 .ike_state_change
= (void*)listener_ike_state
,
373 .child_state_change
= (void*)listener_child_state
,
375 .callback
= callback
,
381 .execute
= (void*)terminate_child_execute
,
382 .destroy
= (void*)recheckin
,
386 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
390 DBG1(DBG_IKE
, "unable to terminate, CHILD_SA with ID %d not found",
394 job
.listener
.ike_sa
= ike_sa
;
396 iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
397 while (iterator
->iterate(iterator
, (void**)&child_sa
))
399 if (child_sa
->get_state(child_sa
) != CHILD_ROUTED
&&
400 child_sa
->get_reqid(child_sa
) == reqid
)
406 iterator
->destroy(iterator
);
408 if (child_sa
== NULL
)
410 DBG1(DBG_IKE
, "unable to terminate, established "
411 "CHILD_SA with ID %d not found", reqid
);
412 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
415 job
.listener
.child_sa
= child_sa
;
417 if (callback
== NULL
)
419 return terminate_child_execute(&job
);
421 charon
->bus
->listen(charon
->bus
, &job
.listener
.public, (job_t
*)&job
);
422 /* checkin of the ike_sa happend in the thread that executed the job */
423 charon
->bus
->set_sa(charon
->bus
, NULL
);
424 return job
.listener
.status
;
430 bool controller_cb_empty(void *param
, debug_t group
, level_t level
,
431 ike_sa_t
*ike_sa
, char *format
, va_list args
)
437 * Implementation of stroke_t.destroy.
439 static void destroy(private_controller_t
*this)
445 * Described in header-file
447 controller_t
*controller_create(void)
449 private_controller_t
*this = malloc_thing(private_controller_t
);
451 this->public.create_ike_sa_enumerator
= (enumerator_t
*(*)(controller_t
*))create_ike_sa_enumerator
;
452 this->public.initiate
= (status_t(*)(controller_t
*,peer_cfg_t
*,child_cfg_t
*,controller_cb_t
,void*))initiate
;
453 this->public.terminate_ike
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
, void*))terminate_ike
;
454 this->public.terminate_child
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
, void *param
))terminate_child
;
455 this->public.destroy
= (void (*)(controller_t
*))destroy
;
457 return &this->public;