]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/trap_manager.c
trap-manager: Wait for install to finish before uninstalling
[thirdparty/strongswan.git] / src / libcharon / sa / trap_manager.c
CommitLineData
eb8ed130 1/*
ca213e19 2 * Copyright (C) 2011-2017 Tobias Brunner
eb8ed130 3 * Copyright (C) 2009 Martin Willi
ca213e19 4 * HSR Hochschule fuer Technik Rapperswil
eb8ed130
MW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
eb8ed130
MW
15 */
16
17#include "trap_manager.h"
18
19#include <daemon.h>
a229bdce 20#include <threading/mutex.h>
eba64cef 21#include <threading/rwlock.h>
12b3cdba 22#include <threading/rwlock_condvar.h>
12642a68 23#include <collections/linked_list.h>
eb8ed130 24
12b3cdba
TB
25#define INSTALL_DISABLED ((u_int)~0)
26
eb8ed130 27typedef struct private_trap_manager_t private_trap_manager_t;
9d737ecf
MW
28typedef struct trap_listener_t trap_listener_t;
29
30/**
31 * listener to track acquires
32 */
33struct trap_listener_t {
7daf5226 34
9d737ecf
MW
35 /**
36 * Implements listener interface
37 */
38 listener_t listener;
7daf5226 39
9d737ecf
MW
40 /**
41 * points to trap_manager
42 */
43 private_trap_manager_t *traps;
44};
eb8ed130
MW
45
46/**
47 * Private data of an trap_manager_t object.
48 */
49struct private_trap_manager_t {
7daf5226 50
eb8ed130
MW
51 /**
52 * Public trap_manager_t interface.
53 */
54 trap_manager_t public;
7daf5226 55
eb8ed130
MW
56 /**
57 * Installed traps, as entry_t
58 */
59 linked_list_t *traps;
7daf5226 60
eb8ed130 61 /**
fcb06fdb 62 * read write lock for traps list
eb8ed130 63 */
fcb06fdb 64 rwlock_t *lock;
7daf5226 65
9d737ecf
MW
66 /**
67 * listener to track acquiring IKE_SAs
68 */
69 trap_listener_t listener;
7fa03b30 70
a229bdce
TB
71 /**
72 * list of acquires we currently handle
73 */
74 linked_list_t *acquires;
75
76 /**
77 * mutex for list of acquires
78 */
79 mutex_t *mutex;
80
12b3cdba
TB
81 /**
82 * number of threads currently installing trap policies, or INSTALL_DISABLED
83 */
84 u_int installing;
85
86 /**
87 * condvar to signal trap policy installation
88 */
89 rwlock_condvar_t *condvar;
90
7fa03b30
TB
91 /**
92 * Whether to ignore traffic selectors from acquires
93 */
94 bool ignore_acquire_ts;
eb8ed130
MW
95};
96
97/**
98 * A installed trap entry
99 */
100typedef struct {
bb492d80
TB
101 /** name of the trapped CHILD_SA */
102 char *name;
eb8ed130
MW
103 /** ref to peer_cfg to initiate */
104 peer_cfg_t *peer_cfg;
a229bdce 105 /** ref to instantiated CHILD_SA (i.e the trap policy) */
eb8ed130 106 child_sa_t *child_sa;
301a0bad
TB
107 /** TRUE in case of wildcard Transport Mode SA */
108 bool wildcard;
a229bdce
TB
109} entry_t;
110
111/**
112 * A handled acquire
113 */
114typedef struct {
9d737ecf 115 /** pending IKE_SA connecting upon acquire */
fc726f13 116 ike_sa_t *ike_sa;
a229bdce 117 /** reqid of pending trap policy */
b12c53ce 118 uint32_t reqid;
301a0bad
TB
119 /** destination address (wildcard case) */
120 host_t *dst;
a229bdce 121} acquire_t;
eb8ed130
MW
122
123/**
124 * actually uninstall and destroy an installed entry
125 */
a229bdce
TB
126static void destroy_entry(entry_t *this)
127{
128 this->child_sa->destroy(this->child_sa);
129 this->peer_cfg->destroy(this->peer_cfg);
130 free(this->name);
131 free(this);
132}
133
134/**
135 * destroy a cached acquire entry
136 */
137static void destroy_acquire(acquire_t *this)
eb8ed130 138{
301a0bad 139 DESTROY_IF(this->dst);
a229bdce
TB
140 free(this);
141}
142
2e4d110d
TB
143CALLBACK(acquire_by_reqid, bool,
144 acquire_t *this, va_list args)
a229bdce 145{
2e4d110d
TB
146 uint32_t reqid;
147
148 VA_ARGS_VGET(args, reqid);
149 return this->reqid == reqid;
eb8ed130
MW
150}
151
2e4d110d
TB
152CALLBACK(acquire_by_dst, bool,
153 acquire_t *this, va_list args)
301a0bad 154{
2e4d110d
TB
155 host_t *dst;
156
157 VA_ARGS_VGET(args, dst);
301a0bad
TB
158 return this->dst && this->dst->ip_equals(this->dst, dst);
159}
160
1a822642
TB
161/**
162 * Check if any remote TS are dynamic
163 */
164static bool dynamic_remote_ts(child_cfg_t *child)
165{
166 enumerator_t *enumerator;
167 linked_list_t *other_ts;
168 traffic_selector_t *ts;
169 bool found = FALSE;
170
84cdfbc9 171 other_ts = child->get_traffic_selectors(child, FALSE, NULL, NULL, FALSE);
1a822642
TB
172 enumerator = other_ts->create_enumerator(other_ts);
173 while (enumerator->enumerate(enumerator, &ts))
174 {
175 if (ts->is_dynamic(ts))
176 {
177 found = TRUE;
178 break;
179 }
180 }
181 enumerator->destroy(enumerator);
182 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
183 return found;
184}
185
24fa1bb0
TB
186METHOD(trap_manager_t, install, bool,
187 private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child)
eb8ed130 188{
21037942 189 entry_t *entry, *found = NULL;
eb8ed130
MW
190 ike_cfg_t *ike_cfg;
191 child_sa_t *child_sa;
192 host_t *me, *other;
7ee37114 193 linked_list_t *my_ts, *other_ts, *list;
eb8ed130 194 enumerator_t *enumerator;
eb8ed130 195 status_t status;
5d569e07
MW
196 linked_list_t *proposals;
197 proposal_t *proposal;
198 protocol_id_t proto = PROTO_ESP;
24fa1bb0 199 bool result = FALSE, wildcard = FALSE;
7daf5226 200
eb8ed130
MW
201 /* try to resolve addresses */
202 ike_cfg = peer->get_ike_cfg(peer);
7446fa28 203 other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
301a0bad
TB
204 if (other && other->is_anyaddr(other) &&
205 child->get_mode(child) == MODE_TRANSPORT)
206 {
207 /* allow wildcard for Transport Mode SAs */
208 me = host_create_any(other->get_family(other));
209 wildcard = TRUE;
210 }
1a822642 211 else if (other && other->is_anyaddr(other))
eb8ed130 212 {
1a822642 213 other->destroy(other);
eb8ed130 214 DBG1(DBG_CFG, "installing trap failed, remote address unknown");
24fa1bb0 215 return FALSE;
eb8ed130 216 }
301a0bad 217 else
1a822642
TB
218 { /* depending on the traffic selectors we don't really need a remote
219 * host yet, but we might fail later if no IP can be resolved */
220 if (!other && dynamic_remote_ts(child))
221 { /* with dynamic TS we do need a host, otherwise 0.0.0.0/0 is used,
222 * which is probably not what users expect*/
223 DBG1(DBG_CFG, "installing trap failed, remote address unknown with "
224 "dynamic traffic selector");
24fa1bb0 225 return FALSE;
1a822642
TB
226 }
227 me = ike_cfg->resolve_me(ike_cfg, other ? other->get_family(other)
228 : AF_UNSPEC);
229 if (!other)
230 {
231 other = host_create_any(me ? me->get_family(me) : AF_INET);
232 }
233 other->set_port(other, ike_cfg->get_other_port(ike_cfg));
234 if ((!me || me->is_anyaddr(me)) && !other->is_anyaddr(other))
eb8ed130 235 {
301a0bad 236 DESTROY_IF(me);
8394ea2a 237 me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
eb8ed130 238 }
1a822642
TB
239 if (!me)
240 {
241 me = host_create_any(other->get_family(other));
242 }
243 me->set_port(me, ike_cfg->get_my_port(ike_cfg));
eb8ed130 244 }
7daf5226 245
21037942 246 this->lock->write_lock(this->lock);
12b3cdba
TB
247 if (this->installing == INSTALL_DISABLED)
248 { /* flush() has been called */
249 this->lock->unlock(this->lock);
e8f2c13f 250 other->destroy(other);
03024f4c 251 me->destroy(me);
24fa1bb0 252 return FALSE;
12b3cdba 253 }
21037942
TB
254 enumerator = this->traps->create_enumerator(this->traps);
255 while (enumerator->enumerate(enumerator, &entry))
256 {
f42dd430
TB
257 if (streq(entry->name, child->get_name(child)) &&
258 streq(entry->peer_cfg->get_name(entry->peer_cfg),
259 peer->get_name(peer)))
21037942 260 {
21037942 261 found = entry;
bb492d80
TB
262 if (entry->child_sa)
263 { /* replace it with an updated version, if already installed */
264 this->traps->remove_at(this->traps, enumerator);
265 }
21037942
TB
266 break;
267 }
268 }
269 enumerator->destroy(enumerator);
2dcfc698 270
21037942 271 if (found)
bb492d80
TB
272 {
273 if (!found->child_sa)
274 {
275 DBG1(DBG_CFG, "CHILD_SA '%s' is already being routed", found->name);
276 this->lock->unlock(this->lock);
e8f2c13f 277 other->destroy(other);
03024f4c 278 me->destroy(me);
24fa1bb0 279 return FALSE;
bb492d80
TB
280 }
281 /* config might have changed so update everything */
282 DBG1(DBG_CFG, "updating already routed CHILD_SA '%s'", found->name);
21037942
TB
283 }
284
bb492d80
TB
285 INIT(entry,
286 .name = strdup(child->get_name(child)),
287 .peer_cfg = peer->get_ref(peer),
301a0bad 288 .wildcard = wildcard,
bb492d80
TB
289 );
290 this->traps->insert_first(this->traps, entry);
12b3cdba 291 this->installing++;
bb492d80
TB
292 /* don't hold lock while creating CHILD_SA and installing policies */
293 this->lock->unlock(this->lock);
294
eb8ed130 295 /* create and route CHILD_SA */
24fa1bb0 296 child_sa = child_sa_create(me, other, child, 0, FALSE, 0, 0);
7ee37114
MW
297
298 list = linked_list_create_with_items(me, NULL);
84cdfbc9 299 my_ts = child->get_traffic_selectors(child, TRUE, NULL, list, FALSE);
7ee37114
MW
300 list->destroy_offset(list, offsetof(host_t, destroy));
301
302 list = linked_list_create_with_items(other, NULL);
84cdfbc9 303 other_ts = child->get_traffic_selectors(child, FALSE, NULL, list, FALSE);
7ee37114 304 list->destroy_offset(list, offsetof(host_t, destroy));
7daf5226 305
5d569e07
MW
306 /* We don't know the finally negotiated protocol (ESP|AH), we install
307 * the SA with the protocol of the first proposal */
308 proposals = child->get_proposals(child, TRUE);
309 if (proposals->get_first(proposals, (void**)&proposal) == SUCCESS)
310 {
311 proto = proposal->get_protocol(proposal);
312 }
313 proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
314 child_sa->set_protocol(child_sa, proto);
eb8ed130 315 child_sa->set_mode(child_sa, child->get_mode(child));
4989aba8
TB
316 child_sa->set_policies(child_sa, my_ts, other_ts);
317 status = child_sa->install_policies(child_sa);
eb8ed130
MW
318 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
319 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
320 if (status != SUCCESS)
321 {
eb8ed130 322 DBG1(DBG_CFG, "installing trap failed");
bb492d80
TB
323 this->lock->write_lock(this->lock);
324 this->traps->remove(this->traps, entry, NULL);
325 this->lock->unlock(this->lock);
326 entry->child_sa = child_sa;
327 destroy_entry(entry);
21037942
TB
328 }
329 else
330 {
bb492d80
TB
331 this->lock->write_lock(this->lock);
332 entry->child_sa = child_sa;
333 this->lock->unlock(this->lock);
24fa1bb0 334 result = TRUE;
4eb09d14 335 }
21037942
TB
336 if (found)
337 {
338 destroy_entry(found);
339 }
12b3cdba
TB
340 this->lock->write_lock(this->lock);
341 /* do this at the end, so entries created temporarily are also destroyed */
342 this->installing--;
343 this->condvar->signal(this->condvar);
344 this->lock->unlock(this->lock);
24fa1bb0 345 return result;
eb8ed130
MW
346}
347
06356a29 348METHOD(trap_manager_t, uninstall, bool,
ca213e19 349 private_trap_manager_t *this, char *peer, char *child)
eb8ed130
MW
350{
351 enumerator_t *enumerator;
352 entry_t *entry, *found = NULL;
7daf5226 353
fcb06fdb 354 this->lock->write_lock(this->lock);
69cbe2ca
SM
355 while (this->installing)
356 {
357 this->condvar->wait(this->condvar, this->lock);
358 }
eb8ed130
MW
359 enumerator = this->traps->create_enumerator(this->traps);
360 while (enumerator->enumerate(enumerator, &entry))
361 {
ca213e19
TB
362 if (streq(entry->name, child) &&
363 (!peer || streq(peer, entry->peer_cfg->get_name(entry->peer_cfg))))
eb8ed130
MW
364 {
365 this->traps->remove_at(this->traps, enumerator);
366 found = entry;
367 break;
368 }
369 }
370 enumerator->destroy(enumerator);
fcb06fdb 371 this->lock->unlock(this->lock);
7daf5226 372
eb8ed130
MW
373 if (!found)
374 {
eb8ed130
MW
375 return FALSE;
376 }
eb8ed130
MW
377 destroy_entry(found);
378 return TRUE;
379}
380
525cc46c
TB
381CALLBACK(trap_filter, bool,
382 rwlock_t *lock, enumerator_t *orig, va_list args)
eb8ed130 383{
525cc46c
TB
384 entry_t *entry;
385 peer_cfg_t **peer_cfg;
386 child_sa_t **child_sa;
387
388 VA_ARGS_VGET(args, peer_cfg, child_sa);
389
390 while (orig->enumerate(orig, &entry))
eb8ed130 391 {
525cc46c
TB
392 if (!entry->child_sa)
393 { /* skip entries that are currently being installed */
394 continue;
395 }
396 if (peer_cfg)
397 {
398 *peer_cfg = entry->peer_cfg;
399 }
400 if (child_sa)
401 {
402 *child_sa = entry->child_sa;
403 }
404 return TRUE;
eb8ed130 405 }
525cc46c 406 return FALSE;
eb8ed130
MW
407}
408
06356a29
AS
409METHOD(trap_manager_t, create_enumerator, enumerator_t*,
410 private_trap_manager_t *this)
eb8ed130 411{
fcb06fdb 412 this->lock->read_lock(this->lock);
eb8ed130 413 return enumerator_create_filter(this->traps->create_enumerator(this->traps),
525cc46c 414 trap_filter, this->lock,
fcb06fdb 415 (void*)this->lock->unlock);
eb8ed130
MW
416}
417
06356a29 418METHOD(trap_manager_t, acquire, void,
b12c53ce 419 private_trap_manager_t *this, uint32_t reqid,
06356a29 420 traffic_selector_t *src, traffic_selector_t *dst)
eb8ed130
MW
421{
422 enumerator_t *enumerator;
423 entry_t *entry, *found = NULL;
a229bdce 424 acquire_t *acquire;
eb8ed130
MW
425 peer_cfg_t *peer;
426 child_cfg_t *child;
427 ike_sa_t *ike_sa;
301a0bad
TB
428 host_t *host;
429 bool wildcard, ignore = FALSE;
7daf5226 430
fcb06fdb 431 this->lock->read_lock(this->lock);
eb8ed130
MW
432 enumerator = this->traps->create_enumerator(this->traps);
433 while (enumerator->enumerate(enumerator, &entry))
434 {
bb492d80
TB
435 if (entry->child_sa &&
436 entry->child_sa->get_reqid(entry->child_sa) == reqid)
eb8ed130
MW
437 {
438 found = entry;
439 break;
440 }
441 }
442 enumerator->destroy(enumerator);
7daf5226 443
eb8ed130
MW
444 if (!found)
445 {
301a0bad 446 DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d", reqid);
fc726f13
TB
447 this->lock->unlock(this->lock);
448 return;
eb8ed130 449 }
a229bdce 450 reqid = found->child_sa->get_reqid(found->child_sa);
301a0bad 451 wildcard = found->wildcard;
a229bdce
TB
452
453 this->mutex->lock(this->mutex);
301a0bad
TB
454 if (wildcard)
455 { /* for wildcard acquires we check that we don't have a pending acquire
456 * with the same peer */
b12c53ce 457 uint8_t mask;
301a0bad
TB
458
459 dst->to_subnet(dst, &host, &mask);
2e4d110d
TB
460 if (this->acquires->find_first(this->acquires, acquire_by_dst,
461 (void**)&acquire, host))
301a0bad
TB
462 {
463 host->destroy(host);
464 ignore = TRUE;
465 }
466 else
467 {
468 INIT(acquire,
469 .dst = host,
470 .reqid = reqid,
471 );
472 this->acquires->insert_last(this->acquires, acquire);
473 }
9d737ecf 474 }
a229bdce
TB
475 else
476 {
2e4d110d
TB
477 if (this->acquires->find_first(this->acquires, acquire_by_reqid,
478 (void**)&acquire, reqid))
301a0bad
TB
479 {
480 ignore = TRUE;
481 }
482 else
483 {
484 INIT(acquire,
485 .reqid = reqid,
486 );
487 this->acquires->insert_last(this->acquires, acquire);
488 }
a229bdce
TB
489 }
490 this->mutex->unlock(this->mutex);
301a0bad
TB
491 if (ignore)
492 {
493 DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
494 this->lock->unlock(this->lock);
495 return;
496 }
fc726f13
TB
497 peer = found->peer_cfg->get_ref(found->peer_cfg);
498 child = found->child_sa->get_config(found->child_sa);
499 child = child->get_ref(child);
fc726f13
TB
500 /* don't hold the lock while checking out the IKE_SA */
501 this->lock->unlock(this->lock);
502
301a0bad
TB
503 if (wildcard)
504 { /* the peer config would match IKE_SAs with other peers */
505 ike_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
506 peer->get_ike_version(peer), TRUE);
507 if (ike_sa)
508 {
509 ike_cfg_t *ike_cfg;
b12c53ce
AS
510 uint16_t port;
511 uint8_t mask;
301a0bad
TB
512
513 ike_sa->set_peer_cfg(ike_sa, peer);
514 ike_cfg = ike_sa->get_ike_cfg(ike_sa);
515
516 port = ike_cfg->get_other_port(ike_cfg);
517 dst->to_subnet(dst, &host, &mask);
518 host->set_port(host, port);
519 ike_sa->set_other_host(ike_sa, host);
520
521 port = ike_cfg->get_my_port(ike_cfg);
522 src->to_subnet(src, &host, &mask);
523 host->set_port(host, port);
524 ike_sa->set_my_host(ike_sa, host);
525
526 charon->bus->set_sa(charon->bus, ike_sa);
527 }
528 }
529 else
530 {
531 ike_sa = charon->ike_sa_manager->checkout_by_config(
fc726f13 532 charon->ike_sa_manager, peer);
301a0bad 533 }
b1f2f05c 534 if (ike_sa)
9d737ecf 535 {
b1f2f05c 536 if (ike_sa->get_peer_cfg(ike_sa) == NULL)
9d737ecf 537 {
b1f2f05c
MW
538 ike_sa->set_peer_cfg(ike_sa, peer);
539 }
7fa03b30 540 if (this->ignore_acquire_ts || ike_sa->get_version(ike_sa) == IKEV1)
777bcdc0
MW
541 { /* in IKEv1, don't prepend the acquiring packet TS, as we only
542 * have a single TS that we can establish in a Quick Mode. */
543 src = dst = NULL;
544 }
a229bdce
TB
545
546 this->mutex->lock(this->mutex);
547 acquire->ike_sa = ike_sa;
548 this->mutex->unlock(this->mutex);
549
b1f2f05c
MW
550 if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
551 {
b1f2f05c
MW
552 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
553 }
554 else
555 {
773fcb16
TB
556 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
557 ike_sa);
9d737ecf 558 }
fc726f13 559 }
a229bdce
TB
560 else
561 {
562 this->mutex->lock(this->mutex);
563 this->acquires->remove(this->acquires, acquire, NULL);
564 this->mutex->unlock(this->mutex);
565 destroy_acquire(acquire);
566 child->destroy(child);
567 }
fc726f13 568 peer->destroy(peer);
9d737ecf
MW
569}
570
571/**
991f7ccd 572 * Complete the acquire, if successful or failed
9d737ecf 573 */
991f7ccd
MW
574static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
575 child_sa_t *child_sa)
9d737ecf 576{
9d737ecf 577 enumerator_t *enumerator;
a229bdce 578 acquire_t *acquire;
7daf5226 579
a229bdce
TB
580 this->mutex->lock(this->mutex);
581 enumerator = this->acquires->create_enumerator(this->acquires);
582 while (enumerator->enumerate(enumerator, &acquire))
9d737ecf 583 {
a229bdce 584 if (!acquire->ike_sa || acquire->ike_sa != ike_sa)
991f7ccd
MW
585 {
586 continue;
587 }
301a0bad 588 if (child_sa)
9d737ecf 589 {
301a0bad
TB
590 if (acquire->dst)
591 {
592 /* since every wildcard acquire results in a separate IKE_SA
593 * there is no need to compare the destination address */
594 }
595 else if (child_sa->get_reqid(child_sa) != acquire->reqid)
596 {
597 continue;
598 }
9d737ecf 599 }
a229bdce
TB
600 this->acquires->remove_at(this->acquires, enumerator);
601 destroy_acquire(acquire);
9d737ecf
MW
602 }
603 enumerator->destroy(enumerator);
a229bdce 604 this->mutex->unlock(this->mutex);
991f7ccd
MW
605}
606
06356a29
AS
607METHOD(listener_t, ike_state_change, bool,
608 trap_listener_t *listener, ike_sa_t *ike_sa, ike_sa_state_t state)
991f7ccd
MW
609{
610 switch (state)
611 {
612 case IKE_DESTROYING:
613 complete(listener->traps, ike_sa, NULL);
614 return TRUE;
615 default:
616 return TRUE;
617 }
618}
619
06356a29
AS
620METHOD(listener_t, child_state_change, bool,
621 trap_listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa,
622 child_sa_state_t state)
991f7ccd
MW
623{
624 switch (state)
625 {
626 case CHILD_INSTALLED:
627 case CHILD_DESTROYING:
628 complete(listener->traps, ike_sa, child_sa);
629 return TRUE;
630 default:
631 return TRUE;
632 }
eb8ed130
MW
633}
634
f8437dd8
MW
635METHOD(trap_manager_t, flush, void,
636 private_trap_manager_t *this)
637{
d6656f11 638 this->lock->write_lock(this->lock);
12b3cdba
TB
639 while (this->installing)
640 {
641 this->condvar->wait(this->condvar, this->lock);
642 }
a229bdce 643 this->traps->destroy_function(this->traps, (void*)destroy_entry);
d6656f11 644 this->traps = linked_list_create();
12b3cdba 645 this->installing = INSTALL_DISABLED;
d6656f11 646 this->lock->unlock(this->lock);
f8437dd8
MW
647}
648
06356a29
AS
649METHOD(trap_manager_t, destroy, void,
650 private_trap_manager_t *this)
eb8ed130 651{
9d737ecf 652 charon->bus->remove_listener(charon->bus, &this->listener.listener);
d6656f11 653 this->traps->destroy_function(this->traps, (void*)destroy_entry);
a229bdce 654 this->acquires->destroy_function(this->acquires, (void*)destroy_acquire);
12b3cdba 655 this->condvar->destroy(this->condvar);
a229bdce 656 this->mutex->destroy(this->mutex);
fcb06fdb 657 this->lock->destroy(this->lock);
eb8ed130
MW
658 free(this);
659}
660
661/**
662 * See header
663 */
06356a29 664trap_manager_t *trap_manager_create(void)
eb8ed130 665{
06356a29
AS
666 private_trap_manager_t *this;
667
668 INIT(this,
669 .public = {
670 .install = _install,
671 .uninstall = _uninstall,
672 .create_enumerator = _create_enumerator,
673 .acquire = _acquire,
f8437dd8 674 .flush = _flush,
06356a29
AS
675 .destroy = _destroy,
676 },
6a5c8ee7
MW
677 .listener = {
678 .traps = this,
679 .listener = {
680 .ike_state_change = _ike_state_change,
681 .child_state_change = _child_state_change,
682 },
683 },
06356a29 684 .traps = linked_list_create(),
a229bdce
TB
685 .acquires = linked_list_create(),
686 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
06356a29 687 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
12b3cdba 688 .condvar = rwlock_condvar_create(),
7fa03b30
TB
689 .ignore_acquire_ts = lib->settings->get_bool(lib->settings,
690 "%s.ignore_acquire_ts", FALSE, lib->ns),
06356a29 691 );
9d737ecf 692 charon->bus->add_listener(charon->bus, &this->listener.listener);
7daf5226 693
eb8ed130
MW
694 return &this->public;
695}