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 char* format
, va_list args
)
123 if (this->ike_sa
== ike_sa
)
125 if (!this->callback(this->param
, signal
, level
, ike_sa
, format
, args
))
131 case CHILD_UP_SUCCESS
:
132 this->status
= SUCCESS
;
135 case CHILD_UP_FAILED
:
145 * execute function for initiate
147 static status_t
initiate_execute(interface_job_t
*job
)
150 interface_bus_listener_t
*listener
= &job
->listener
;
151 peer_cfg_t
*peer_cfg
= listener
->peer_cfg
;
153 ike_sa
= charon
->ike_sa_manager
->checkout_by_config(charon
->ike_sa_manager
,
155 listener
->ike_sa
= ike_sa
;
157 if (ike_sa
->get_peer_cfg(ike_sa
) == NULL
)
159 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
161 peer_cfg
->destroy(peer_cfg
);
163 if (ike_sa
->initiate(ike_sa
, listener
->child_cfg
) != SUCCESS
)
165 return charon
->ike_sa_manager
->checkin_and_destroy(
166 charon
->ike_sa_manager
, ike_sa
);
168 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
172 * Implementation of controller_t.initiate.
174 static status_t
initiate(private_controller_t
*this,
175 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
176 controller_cb_t callback
, void *param
)
180 job
.listener
.public.signal
= (void*)initiate_listener
;
181 job
.listener
.ike_sa
= NULL
;
182 job
.listener
.callback
= callback
;
183 job
.listener
.param
= param
;
184 job
.listener
.status
= FAILED
;
185 job
.listener
.child_cfg
= child_cfg
;
186 job
.listener
.peer_cfg
= peer_cfg
;
187 job
.public.execute
= (void*)initiate_execute
;
188 job
.public.destroy
= nop
;
190 if (callback
== NULL
)
192 return initiate_execute(&job
);
194 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
195 return job
.listener
.status
;
199 * listener function for terminate_ike
201 static bool terminate_ike_listener(interface_bus_listener_t
*this, signal_t signal
,
202 level_t level
, int thread
, ike_sa_t
*ike_sa
,
203 char* format
, va_list args
)
205 if (this->ike_sa
== ike_sa
)
207 if (!this->callback(this->param
, signal
, level
, ike_sa
, format
, args
))
213 case IKE_DOWN_SUCCESS
:
214 this->status
= SUCCESS
;
216 case IKE_DOWN_FAILED
:
226 * execute function for terminate_ike
228 static status_t
terminate_ike_execute(interface_job_t
*job
)
231 interface_bus_listener_t
*listener
= &job
->listener
;
233 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
234 listener
->id
, FALSE
);
237 SIG(IKE_DOWN_FAILED
, "unable to terminate, IKE_SA with "
238 "ID %d not found", listener
->id
);
241 listener
->ike_sa
= ike_sa
;
243 if (ike_sa
->delete(ike_sa
) == DESTROY_ME
)
245 return charon
->ike_sa_manager
->checkin_and_destroy(
246 charon
->ike_sa_manager
, ike_sa
);
248 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
252 * Implementation of controller_t.terminate_ike.
254 static status_t
terminate_ike(controller_t
*this, u_int32_t unique_id
,
255 controller_cb_t callback
, void *param
)
259 job
.listener
.public.signal
= (void*)terminate_ike_listener
;
260 job
.listener
.ike_sa
= NULL
;
261 job
.listener
.callback
= callback
;
262 job
.listener
.param
= param
;
263 job
.listener
.status
= FAILED
;
264 job
.listener
.id
= unique_id
;
265 job
.public.execute
= (void*)terminate_ike_execute
;
266 job
.public.destroy
= nop
;
268 if (callback
== NULL
)
270 return terminate_ike_execute(&job
);
272 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
273 return job
.listener
.status
;
276 * listener function for terminate_child
278 static bool terminate_child_listener(interface_bus_listener_t
*this, signal_t signal
,
279 level_t level
, int thread
, ike_sa_t
*ike_sa
,
280 char* format
, va_list args
)
282 if (this->ike_sa
== ike_sa
)
284 if (!this->callback(this->param
, signal
, level
, ike_sa
, format
, args
))
290 case CHILD_DOWN_SUCCESS
:
291 case IKE_DOWN_SUCCESS
:
292 this->status
= SUCCESS
;
294 case IKE_DOWN_FAILED
:
295 case CHILD_DOWN_FAILED
:
305 * execute function for terminate_child
307 static status_t
terminate_child_execute(interface_job_t
*job
)
310 child_sa_t
*child_sa
;
311 iterator_t
*iterator
;
312 interface_bus_listener_t
*listener
= &job
->listener
;
314 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
318 SIG(CHILD_DOWN_FAILED
, "unable to terminate, CHILD_SA with "
319 "ID %d not found", listener
->id
);
322 listener
->ike_sa
= ike_sa
;
324 iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
325 while (iterator
->iterate(iterator
, (void**)&child_sa
))
327 if (child_sa
->get_state(child_sa
) != CHILD_ROUTED
&&
328 child_sa
->get_reqid(child_sa
) == listener
->id
)
334 iterator
->destroy(iterator
);
336 if (child_sa
== NULL
)
338 SIG(CHILD_DOWN_FAILED
, "unable to terminate, established CHILD_SA with "
339 "ID %d not found", listener
->id
);
340 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
344 if (ike_sa
->delete_child_sa(ike_sa
, child_sa
->get_protocol(child_sa
),
345 child_sa
->get_spi(child_sa
, TRUE
)) == DESTROY_ME
)
347 return charon
->ike_sa_manager
->checkin_and_destroy(
348 charon
->ike_sa_manager
, ike_sa
);
350 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
354 * Implementation of controller_t.terminate_child.
356 static status_t
terminate_child(controller_t
*this, u_int32_t reqid
,
357 controller_cb_t callback
, void *param
)
361 job
.listener
.public.signal
= (void*)terminate_child_listener
;
362 job
.listener
.ike_sa
= NULL
;
363 job
.listener
.callback
= callback
;
364 job
.listener
.param
= param
;
365 job
.listener
.status
= FAILED
;
366 job
.listener
.id
= reqid
;
367 job
.public.execute
= (void*)terminate_child_execute
;
368 job
.public.destroy
= nop
;
370 if (callback
== NULL
)
372 return terminate_child_execute(&job
);
374 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
375 return job
.listener
.status
;
379 * listener function for route
381 static bool route_listener(interface_bus_listener_t
*this, signal_t signal
,
382 level_t level
, int thread
, ike_sa_t
*ike_sa
,
383 char* format
, va_list args
)
385 if (this->ike_sa
== ike_sa
)
387 if (!this->callback(this->param
, signal
, level
, ike_sa
, format
, args
))
393 case CHILD_ROUTE_SUCCESS
:
394 this->status
= SUCCESS
;
396 case CHILD_ROUTE_FAILED
:
406 * execute function for route
408 static status_t
route_execute(interface_job_t
*job
)
411 interface_bus_listener_t
*listener
= &job
->listener
;
412 peer_cfg_t
*peer_cfg
= listener
->peer_cfg
;
413 ike_sa
= charon
->ike_sa_manager
->checkout_by_config(charon
->ike_sa_manager
,
415 listener
->ike_sa
= ike_sa
;
417 if (ike_sa
->get_peer_cfg(ike_sa
) == NULL
)
419 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
421 if (ike_sa
->route(ike_sa
, listener
->child_cfg
) == DESTROY_ME
)
423 return charon
->ike_sa_manager
->checkin_and_destroy(
424 charon
->ike_sa_manager
, ike_sa
);
426 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
430 * Implementation of controller_t.route.
432 static status_t
route(controller_t
*this,
433 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
434 controller_cb_t callback
, void *param
)
438 job
.listener
.public.signal
= (void*)route_listener
;
439 job
.listener
.ike_sa
= NULL
;
440 job
.listener
.callback
= callback
;
441 job
.listener
.param
= param
;
442 job
.listener
.status
= FAILED
;
443 job
.listener
.peer_cfg
= peer_cfg
;
444 job
.listener
.child_cfg
= child_cfg
;
445 job
.public.execute
= (void*)route_execute
;
446 job
.public.destroy
= nop
;
448 if (callback
== NULL
)
450 return route_execute(&job
);
452 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
453 return job
.listener
.status
;
457 * listener function for unroute
459 static bool unroute_listener(interface_bus_listener_t
*this, signal_t signal
,
460 level_t level
, int thread
, ike_sa_t
*ike_sa
,
461 char* format
, va_list args
)
463 if (this->ike_sa
== ike_sa
)
465 if (!this->callback(this->param
, signal
, level
, ike_sa
, format
, args
))
471 case CHILD_UNROUTE_SUCCESS
:
472 this->status
= SUCCESS
;
474 case CHILD_UNROUTE_FAILED
:
483 * execute function for unroute
485 static status_t
unroute_execute(interface_job_t
*job
)
488 interface_bus_listener_t
*listener
= &job
->listener
;
490 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
494 SIG(CHILD_DOWN_FAILED
, "unable to unroute, CHILD_SA with "
495 "ID %d not found", listener
->id
);
498 listener
->ike_sa
= ike_sa
;
499 if (ike_sa
->unroute(ike_sa
, listener
->id
) == DESTROY_ME
)
501 return charon
->ike_sa_manager
->checkin_and_destroy(
502 charon
->ike_sa_manager
, ike_sa
);
504 return charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
508 * Implementation of controller_t.unroute.
510 static status_t
unroute(controller_t
*this, u_int32_t reqid
,
511 controller_cb_t callback
, void *param
)
515 job
.listener
.public.signal
= (void*)unroute_listener
;
516 job
.listener
.ike_sa
= NULL
;
517 job
.listener
.callback
= callback
;
518 job
.listener
.param
= param
;
519 job
.listener
.status
= FAILED
;
520 job
.listener
.id
= reqid
;
521 job
.public.execute
= (void*)unroute_execute
;
522 job
.public.destroy
= nop
;
524 if (callback
== NULL
)
526 return unroute_execute(&job
);
528 charon
->bus
->listen(charon
->bus
, (bus_listener_t
*)&job
.listener
, (job_t
*)&job
);
529 return job
.listener
.status
;
535 bool controller_cb_empty(void *param
, signal_t signal
, level_t level
,
536 ike_sa_t
*ike_sa
, char *format
, va_list args
)
542 * Implementation of stroke_t.destroy.
544 static void destroy(private_controller_t
*this)
550 * Described in header-file
552 controller_t
*controller_create(void)
554 private_controller_t
*this = malloc_thing(private_controller_t
);
556 this->public.create_ike_sa_enumerator
= (enumerator_t
*(*)(controller_t
*))create_ike_sa_enumerator
;
557 this->public.initiate
= (status_t(*)(controller_t
*,peer_cfg_t
*,child_cfg_t
*,bool(*)(void*,signal_t
,level_t
,ike_sa_t
*,char*,va_list),void*))initiate
;
558 this->public.terminate_ike
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
, void*))terminate_ike
;
559 this->public.terminate_child
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
, void *param
))terminate_child
;
560 this->public.route
= (status_t(*)(controller_t
*,peer_cfg_t
*, child_cfg_t
*,controller_cb_t
,void*))route
;
561 this->public.unroute
= (status_t(*)(controller_t
*,u_int32_t
,controller_cb_t
,void*))unroute
;
562 this->public.destroy
= (void (*)(controller_t
*))destroy
;
564 return &this->public;