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
18 #include "controller.h"
20 #include <sys/types.h>
29 typedef struct private_controller_t private_controller_t
;
30 typedef struct interface_bus_listener_t interface_bus_listener_t
;
33 * Private data of an stroke_t object.
35 struct private_controller_t
{
38 * Public part of stroke_t object.
45 * helper struct to map bus listener callbacks to interface callbacks
47 struct interface_bus_listener_t
{
50 * public bus listener interface
52 bus_listener_t
public;
55 * status of the operation, return to method callers
60 * IKE SA to filter log output
65 * interface callback (listener gets redirected to here)
67 controller_cb_t callback
;
70 * user parameter to pass to callback
75 * child configuration, used for initiate
77 child_cfg_t
*child_cfg
;
80 * peer configuration, used for initiate
85 * unique ID, used for various methods
91 typedef struct interface_job_t interface_job_t
;
94 * job for asynchronous listen operations
96 struct interface_job_t
{
103 * associated listener
105 interface_bus_listener_t listener
;
109 * Implementation of controller_t.create_ike_sa_iterator.
111 static enumerator_t
* create_ike_sa_enumerator(controller_t
*this)
113 return charon
->ike_sa_manager
->create_enumerator(charon
->ike_sa_manager
);
117 * listener function for initiate
119 static bool initiate_listener(interface_bus_listener_t
*this, signal_t signal
,
120 level_t level
, int thread
, ike_sa_t
*ike_sa
,
121 void* data
, char* format
, va_list args
)
123 if (this->ike_sa
== ike_sa
)
125 if (!this->callback(this->param
, signal
, level
, ike_sa
, data
,
133 this->status
= SUCCESS
;
146 * execute function for initiate
148 static status_t
initiate_execute(interface_job_t
*job
)
151 interface_bus_listener_t
*listener
= &job
->listener
;
152 peer_cfg_t
*peer_cfg
= listener
->peer_cfg
;
154 ike_sa
= charon
->ike_sa_manager
->checkout_by_config(charon
->ike_sa_manager
,
156 listener
->ike_sa
= ike_sa
;
158 if (ike_sa
->get_peer_cfg(ike_sa
) == NULL
)
160 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
162 peer_cfg
->destroy(peer_cfg
);
164 if (ike_sa
->initiate(ike_sa
, listener
->child_cfg
) != SUCCESS
)
166 return charon
->ike_sa_manager
->checkin_and_destroy(
167 charon
->ike_sa_manager
, ike_sa
);
169 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
173 * Implementation of controller_t.initiate.
175 static status_t
initiate(private_controller_t
*this,
176 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
177 controller_cb_t callback
, void *param
)
181 job
.listener
.public.signal
= (void*)initiate_listener
;
182 job
.listener
.ike_sa
= NULL
;
183 job
.listener
.callback
= callback
;
184 job
.listener
.param
= param
;
185 job
.listener
.status
= FAILED
;
186 job
.listener
.child_cfg
= child_cfg
;
187 job
.listener
.peer_cfg
= peer_cfg
;
188 job
.public.execute
= (void*)initiate_execute
;
189 job
.public.destroy
= nop
;
191 if (callback
== NULL
)
193 return initiate_execute(&job
);
195 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
196 return job
.listener
.status
;
200 * listener function for terminate_ike
202 static bool terminate_ike_listener(interface_bus_listener_t
*this, signal_t signal
,
203 level_t level
, int thread
, ike_sa_t
*ike_sa
,
204 void* data
, char* format
, va_list args
)
206 if (this->ike_sa
== ike_sa
)
208 if (!this->callback(this->param
, signal
, level
, ike_sa
,
215 case IKE_DOWN_SUCCESS
:
216 this->status
= SUCCESS
;
218 case IKE_DOWN_FAILED
:
228 * execute function for terminate_ike
230 static status_t
terminate_ike_execute(interface_job_t
*job
)
233 interface_bus_listener_t
*listener
= &job
->listener
;
235 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
236 listener
->id
, FALSE
);
239 SIG_IKE(DOWN_FAILED
, "unable to terminate, IKE_SA with "
240 "ID %d not found", listener
->id
);
243 listener
->ike_sa
= ike_sa
;
245 if (ike_sa
->delete(ike_sa
) == DESTROY_ME
)
247 return charon
->ike_sa_manager
->checkin_and_destroy(
248 charon
->ike_sa_manager
, ike_sa
);
250 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
254 * Implementation of controller_t.terminate_ike.
256 static status_t
terminate_ike(controller_t
*this, u_int32_t unique_id
,
257 controller_cb_t callback
, void *param
)
261 job
.listener
.public.signal
= (void*)terminate_ike_listener
;
262 job
.listener
.ike_sa
= NULL
;
263 job
.listener
.callback
= callback
;
264 job
.listener
.param
= param
;
265 job
.listener
.status
= FAILED
;
266 job
.listener
.id
= unique_id
;
267 job
.public.execute
= (void*)terminate_ike_execute
;
268 job
.public.destroy
= nop
;
270 if (callback
== NULL
)
272 return terminate_ike_execute(&job
);
274 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
275 return job
.listener
.status
;
278 * listener function for terminate_child
280 static bool terminate_child_listener(interface_bus_listener_t
*this, signal_t signal
,
281 level_t level
, int thread
, ike_sa_t
*ike_sa
,
282 void* data
, char* format
, va_list args
)
284 if (this->ike_sa
== ike_sa
)
286 if (!this->callback(this->param
, signal
, level
, ike_sa
,
293 case CHD_DOWN_SUCCESS
:
294 case IKE_DOWN_SUCCESS
:
295 this->status
= SUCCESS
;
297 case IKE_DOWN_FAILED
:
298 case CHD_DOWN_FAILED
:
308 * execute function for terminate_child
310 static status_t
terminate_child_execute(interface_job_t
*job
)
313 child_sa_t
*child_sa
;
314 iterator_t
*iterator
;
315 interface_bus_listener_t
*listener
= &job
->listener
;
317 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
321 SIG_CHD(DOWN_FAILED
, NULL
, "unable to terminate, CHILD_SA with "
322 "ID %d not found", listener
->id
);
325 listener
->ike_sa
= ike_sa
;
327 iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
328 while (iterator
->iterate(iterator
, (void**)&child_sa
))
330 if (child_sa
->get_state(child_sa
) != CHILD_ROUTED
&&
331 child_sa
->get_reqid(child_sa
) == listener
->id
)
337 iterator
->destroy(iterator
);
339 if (child_sa
== NULL
)
341 SIG_CHD(DOWN_FAILED
, NULL
, "unable to terminate, established "
342 "CHILD_SA with ID %d not found", listener
->id
);
343 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
347 if (ike_sa
->delete_child_sa(ike_sa
, child_sa
->get_protocol(child_sa
),
348 child_sa
->get_spi(child_sa
, TRUE
)) == DESTROY_ME
)
350 return charon
->ike_sa_manager
->checkin_and_destroy(
351 charon
->ike_sa_manager
, ike_sa
);
353 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
357 * Implementation of controller_t.terminate_child.
359 static status_t
terminate_child(controller_t
*this, u_int32_t reqid
,
360 controller_cb_t callback
, void *param
)
364 job
.listener
.public.signal
= (void*)terminate_child_listener
;
365 job
.listener
.ike_sa
= NULL
;
366 job
.listener
.callback
= callback
;
367 job
.listener
.param
= param
;
368 job
.listener
.status
= FAILED
;
369 job
.listener
.id
= reqid
;
370 job
.public.execute
= (void*)terminate_child_execute
;
371 job
.public.destroy
= nop
;
373 if (callback
== NULL
)
375 return terminate_child_execute(&job
);
377 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
378 return job
.listener
.status
;
382 * listener function for route
384 static bool route_listener(interface_bus_listener_t
*this, signal_t signal
,
385 level_t level
, int thread
, ike_sa_t
*ike_sa
,
386 void* data
, char* format
, va_list args
)
388 if (this->ike_sa
== ike_sa
)
390 if (!this->callback(this->param
, signal
, level
, ike_sa
,
397 case CHD_ROUTE_SUCCESS
:
398 this->status
= SUCCESS
;
400 case CHD_ROUTE_FAILED
:
410 * execute function for route
412 static status_t
route_execute(interface_job_t
*job
)
415 interface_bus_listener_t
*listener
= &job
->listener
;
416 peer_cfg_t
*peer_cfg
= listener
->peer_cfg
;
417 ike_sa
= charon
->ike_sa_manager
->checkout_by_config(charon
->ike_sa_manager
,
419 listener
->ike_sa
= ike_sa
;
421 if (ike_sa
->get_peer_cfg(ike_sa
) == NULL
)
423 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
425 if (ike_sa
->route(ike_sa
, listener
->child_cfg
) == DESTROY_ME
)
427 return charon
->ike_sa_manager
->checkin_and_destroy(
428 charon
->ike_sa_manager
, ike_sa
);
430 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
434 * Implementation of controller_t.route.
436 static status_t
route(controller_t
*this,
437 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
438 controller_cb_t callback
, void *param
)
442 job
.listener
.public.signal
= (void*)route_listener
;
443 job
.listener
.ike_sa
= NULL
;
444 job
.listener
.callback
= callback
;
445 job
.listener
.param
= param
;
446 job
.listener
.status
= FAILED
;
447 job
.listener
.peer_cfg
= peer_cfg
;
448 job
.listener
.child_cfg
= child_cfg
;
449 job
.public.execute
= (void*)route_execute
;
450 job
.public.destroy
= nop
;
452 if (callback
== NULL
)
454 return route_execute(&job
);
456 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
457 return job
.listener
.status
;
461 * listener function for unroute
463 static bool unroute_listener(interface_bus_listener_t
*this, signal_t signal
,
464 level_t level
, int thread
, ike_sa_t
*ike_sa
,
465 void* data
, char* format
, va_list args
)
467 if (this->ike_sa
== ike_sa
)
469 if (!this->callback(this->param
, signal
, level
, ike_sa
,
476 case CHD_UNROUTE_SUCCESS
:
477 this->status
= SUCCESS
;
479 case CHD_UNROUTE_FAILED
:
488 * execute function for unroute
490 static status_t
unroute_execute(interface_job_t
*job
)
493 interface_bus_listener_t
*listener
= &job
->listener
;
495 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
499 SIG_CHD(DOWN_FAILED
, NULL
, "unable to unroute, CHILD_SA with "
500 "ID %d not found", listener
->id
);
503 listener
->ike_sa
= ike_sa
;
504 if (ike_sa
->unroute(ike_sa
, listener
->id
) == DESTROY_ME
)
506 return charon
->ike_sa_manager
->checkin_and_destroy(
507 charon
->ike_sa_manager
, ike_sa
);
509 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
513 * Implementation of controller_t.unroute.
515 static status_t
unroute(controller_t
*this, u_int32_t reqid
,
516 controller_cb_t callback
, void *param
)
520 job
.listener
.public.signal
= (void*)unroute_listener
;
521 job
.listener
.ike_sa
= NULL
;
522 job
.listener
.callback
= callback
;
523 job
.listener
.param
= param
;
524 job
.listener
.status
= FAILED
;
525 job
.listener
.id
= reqid
;
526 job
.public.execute
= (void*)unroute_execute
;
527 job
.public.destroy
= nop
;
529 if (callback
== NULL
)
531 return unroute_execute(&job
);
533 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
534 return job
.listener
.status
;
540 bool controller_cb_empty(void *param
, signal_t signal
, level_t level
,
541 ike_sa_t
*ike_sa
, void *data
, char *format
, va_list args
)
547 * Implementation of stroke_t.destroy.
549 static void destroy(private_controller_t
*this)
555 * Described in header-file
557 controller_t
*controller_create(void)
559 private_controller_t
*this = malloc_thing(private_controller_t
);
561 this->public.create_ike_sa_enumerator
= (enumerator_t
*(*)(controller_t
*))create_ike_sa_enumerator
;
562 this->public.initiate
= (status_t(*)(controller_t
*,peer_cfg_t
*,child_cfg_t
*,controller_cb_t
,void*))initiate
;
563 this->public.terminate_ike
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
, void*))terminate_ike
;
564 this->public.terminate_child
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
, void *param
))terminate_child
;
565 this->public.route
= (status_t(*)(controller_t
*,peer_cfg_t
*, child_cfg_t
*,controller_cb_t
,void*))route
;
566 this->public.unroute
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
,void*))unroute
;
567 this->public.destroy
= (void (*)(controller_t
*))destroy
;
569 return &this->public;