]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/trap_manager.c
child-sa: Split in- and outbound policy de-/installation
[thirdparty/strongswan.git] / src / libcharon / sa / trap_manager.c
CommitLineData
eb8ed130 1/*
a229bdce 2 * Copyright (C) 2011-2015 Tobias Brunner
eb8ed130
MW
3 * Copyright (C) 2009 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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
143/**
144 * match an acquire entry by reqid
145 */
b12c53ce 146static bool acquire_by_reqid(acquire_t *this, uint32_t *reqid)
a229bdce
TB
147{
148 return this->reqid == *reqid;
eb8ed130
MW
149}
150
301a0bad
TB
151/**
152 * match an acquire entry by destination address
153 */
154static bool acquire_by_dst(acquire_t *this, host_t *dst)
155{
156 return this->dst && this->dst->ip_equals(this->dst, dst);
157}
158
b12c53ce 159METHOD(trap_manager_t, install, uint32_t,
4c74fa66 160 private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child,
b12c53ce 161 uint32_t reqid)
eb8ed130 162{
21037942 163 entry_t *entry, *found = NULL;
eb8ed130
MW
164 ike_cfg_t *ike_cfg;
165 child_sa_t *child_sa;
166 host_t *me, *other;
7ee37114 167 linked_list_t *my_ts, *other_ts, *list;
eb8ed130 168 enumerator_t *enumerator;
eb8ed130 169 status_t status;
5d569e07
MW
170 linked_list_t *proposals;
171 proposal_t *proposal;
172 protocol_id_t proto = PROTO_ESP;
301a0bad 173 bool wildcard = FALSE;
7daf5226 174
eb8ed130
MW
175 /* try to resolve addresses */
176 ike_cfg = peer->get_ike_cfg(peer);
7446fa28 177 other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
301a0bad
TB
178 if (other && other->is_anyaddr(other) &&
179 child->get_mode(child) == MODE_TRANSPORT)
180 {
181 /* allow wildcard for Transport Mode SAs */
182 me = host_create_any(other->get_family(other));
183 wildcard = TRUE;
184 }
185 else if (!other || other->is_anyaddr(other))
eb8ed130 186 {
ae131e6b 187 DESTROY_IF(other);
eb8ed130
MW
188 DBG1(DBG_CFG, "installing trap failed, remote address unknown");
189 return 0;
190 }
301a0bad 191 else
eb8ed130 192 {
301a0bad
TB
193 me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
194 if (!me || me->is_anyaddr(me))
eb8ed130 195 {
301a0bad 196 DESTROY_IF(me);
8394ea2a 197 me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
301a0bad
TB
198 if (!me)
199 {
9c01e014 200 me = host_create_any(other->get_family(other));
301a0bad
TB
201 }
202 me->set_port(me, ike_cfg->get_my_port(ike_cfg));
eb8ed130 203 }
eb8ed130 204 }
7daf5226 205
21037942 206 this->lock->write_lock(this->lock);
12b3cdba
TB
207 if (this->installing == INSTALL_DISABLED)
208 { /* flush() has been called */
209 this->lock->unlock(this->lock);
e8f2c13f 210 other->destroy(other);
03024f4c 211 me->destroy(me);
12b3cdba
TB
212 return 0;
213 }
21037942
TB
214 enumerator = this->traps->create_enumerator(this->traps);
215 while (enumerator->enumerate(enumerator, &entry))
216 {
bb492d80 217 if (streq(entry->name, child->get_name(child)))
21037942 218 {
21037942 219 found = entry;
bb492d80
TB
220 if (entry->child_sa)
221 { /* replace it with an updated version, if already installed */
222 this->traps->remove_at(this->traps, enumerator);
223 }
21037942
TB
224 break;
225 }
226 }
227 enumerator->destroy(enumerator);
2dcfc698 228
21037942 229 if (found)
bb492d80
TB
230 {
231 if (!found->child_sa)
232 {
233 DBG1(DBG_CFG, "CHILD_SA '%s' is already being routed", found->name);
234 this->lock->unlock(this->lock);
e8f2c13f 235 other->destroy(other);
03024f4c 236 me->destroy(me);
bb492d80
TB
237 return 0;
238 }
239 /* config might have changed so update everything */
240 DBG1(DBG_CFG, "updating already routed CHILD_SA '%s'", found->name);
21037942
TB
241 reqid = found->child_sa->get_reqid(found->child_sa);
242 }
243
bb492d80
TB
244 INIT(entry,
245 .name = strdup(child->get_name(child)),
246 .peer_cfg = peer->get_ref(peer),
301a0bad 247 .wildcard = wildcard,
bb492d80
TB
248 );
249 this->traps->insert_first(this->traps, entry);
12b3cdba 250 this->installing++;
bb492d80
TB
251 /* don't hold lock while creating CHILD_SA and installing policies */
252 this->lock->unlock(this->lock);
253
eb8ed130 254 /* create and route CHILD_SA */
85b23888 255 child_sa = child_sa_create(me, other, child, reqid, FALSE, 0, 0);
7ee37114
MW
256
257 list = linked_list_create_with_items(me, NULL);
258 my_ts = child->get_traffic_selectors(child, TRUE, NULL, list);
259 list->destroy_offset(list, offsetof(host_t, destroy));
260
261 list = linked_list_create_with_items(other, NULL);
262 other_ts = child->get_traffic_selectors(child, FALSE, NULL, list);
263 list->destroy_offset(list, offsetof(host_t, destroy));
7daf5226 264
5d569e07
MW
265 /* We don't know the finally negotiated protocol (ESP|AH), we install
266 * the SA with the protocol of the first proposal */
267 proposals = child->get_proposals(child, TRUE);
268 if (proposals->get_first(proposals, (void**)&proposal) == SUCCESS)
269 {
270 proto = proposal->get_protocol(proposal);
271 }
272 proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
273 child_sa->set_protocol(child_sa, proto);
eb8ed130
MW
274 child_sa->set_mode(child_sa, child->get_mode(child));
275 status = child_sa->add_policies(child_sa, my_ts, other_ts);
276 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
277 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
278 if (status != SUCCESS)
279 {
eb8ed130 280 DBG1(DBG_CFG, "installing trap failed");
bb492d80
TB
281 this->lock->write_lock(this->lock);
282 this->traps->remove(this->traps, entry, NULL);
283 this->lock->unlock(this->lock);
284 entry->child_sa = child_sa;
285 destroy_entry(entry);
21037942
TB
286 reqid = 0;
287 }
288 else
289 {
21037942 290 reqid = child_sa->get_reqid(child_sa);
bb492d80
TB
291 this->lock->write_lock(this->lock);
292 entry->child_sa = child_sa;
293 this->lock->unlock(this->lock);
4eb09d14 294 }
21037942
TB
295 if (found)
296 {
297 destroy_entry(found);
298 }
12b3cdba
TB
299 this->lock->write_lock(this->lock);
300 /* do this at the end, so entries created temporarily are also destroyed */
301 this->installing--;
302 this->condvar->signal(this->condvar);
303 this->lock->unlock(this->lock);
eb8ed130
MW
304 return reqid;
305}
306
06356a29 307METHOD(trap_manager_t, uninstall, bool,
b12c53ce 308 private_trap_manager_t *this, uint32_t reqid)
eb8ed130
MW
309{
310 enumerator_t *enumerator;
311 entry_t *entry, *found = NULL;
7daf5226 312
fcb06fdb 313 this->lock->write_lock(this->lock);
eb8ed130
MW
314 enumerator = this->traps->create_enumerator(this->traps);
315 while (enumerator->enumerate(enumerator, &entry))
316 {
bb492d80
TB
317 if (entry->child_sa &&
318 entry->child_sa->get_reqid(entry->child_sa) == reqid)
eb8ed130
MW
319 {
320 this->traps->remove_at(this->traps, enumerator);
321 found = entry;
322 break;
323 }
324 }
325 enumerator->destroy(enumerator);
fcb06fdb 326 this->lock->unlock(this->lock);
7daf5226 327
eb8ed130
MW
328 if (!found)
329 {
330 DBG1(DBG_CFG, "trap %d not found to uninstall", reqid);
331 return FALSE;
332 }
eb8ed130
MW
333 destroy_entry(found);
334 return TRUE;
335}
336
337/**
338 * convert enumerated entries to peer_cfg, child_sa
339 */
fcb06fdb 340static bool trap_filter(rwlock_t *lock, entry_t **entry, peer_cfg_t **peer_cfg,
eb8ed130
MW
341 void *none, child_sa_t **child_sa)
342{
bb492d80
TB
343 if (!(*entry)->child_sa)
344 { /* skip entries that are currently being installed */
345 return FALSE;
346 }
eb8ed130
MW
347 if (peer_cfg)
348 {
349 *peer_cfg = (*entry)->peer_cfg;
350 }
351 if (child_sa)
352 {
353 *child_sa = (*entry)->child_sa;
354 }
355 return TRUE;
356}
357
06356a29
AS
358METHOD(trap_manager_t, create_enumerator, enumerator_t*,
359 private_trap_manager_t *this)
eb8ed130 360{
fcb06fdb 361 this->lock->read_lock(this->lock);
eb8ed130 362 return enumerator_create_filter(this->traps->create_enumerator(this->traps),
fcb06fdb
MW
363 (void*)trap_filter, this->lock,
364 (void*)this->lock->unlock);
eb8ed130
MW
365}
366
b12c53ce 367METHOD(trap_manager_t, find_reqid, uint32_t,
2dcfc698
MW
368 private_trap_manager_t *this, child_cfg_t *child)
369{
370 enumerator_t *enumerator;
2dcfc698 371 entry_t *entry;
b12c53ce 372 uint32_t reqid = 0;
2dcfc698
MW
373
374 this->lock->read_lock(this->lock);
375 enumerator = this->traps->create_enumerator(this->traps);
376 while (enumerator->enumerate(enumerator, &entry))
377 {
bb492d80 378 if (streq(entry->name, child->get_name(child)))
2dcfc698 379 {
bb492d80
TB
380 if (entry->child_sa)
381 {
382 reqid = entry->child_sa->get_reqid(entry->child_sa);
383 }
2dcfc698
MW
384 break;
385 }
386 }
387 enumerator->destroy(enumerator);
388 this->lock->unlock(this->lock);
2dcfc698
MW
389 return reqid;
390}
391
06356a29 392METHOD(trap_manager_t, acquire, void,
b12c53ce 393 private_trap_manager_t *this, uint32_t reqid,
06356a29 394 traffic_selector_t *src, traffic_selector_t *dst)
eb8ed130
MW
395{
396 enumerator_t *enumerator;
397 entry_t *entry, *found = NULL;
a229bdce 398 acquire_t *acquire;
eb8ed130
MW
399 peer_cfg_t *peer;
400 child_cfg_t *child;
401 ike_sa_t *ike_sa;
301a0bad
TB
402 host_t *host;
403 bool wildcard, ignore = FALSE;
7daf5226 404
fcb06fdb 405 this->lock->read_lock(this->lock);
eb8ed130
MW
406 enumerator = this->traps->create_enumerator(this->traps);
407 while (enumerator->enumerate(enumerator, &entry))
408 {
bb492d80
TB
409 if (entry->child_sa &&
410 entry->child_sa->get_reqid(entry->child_sa) == reqid)
eb8ed130
MW
411 {
412 found = entry;
413 break;
414 }
415 }
416 enumerator->destroy(enumerator);
7daf5226 417
eb8ed130
MW
418 if (!found)
419 {
301a0bad 420 DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d", reqid);
fc726f13
TB
421 this->lock->unlock(this->lock);
422 return;
eb8ed130 423 }
a229bdce 424 reqid = found->child_sa->get_reqid(found->child_sa);
301a0bad 425 wildcard = found->wildcard;
a229bdce
TB
426
427 this->mutex->lock(this->mutex);
301a0bad
TB
428 if (wildcard)
429 { /* for wildcard acquires we check that we don't have a pending acquire
430 * with the same peer */
b12c53ce 431 uint8_t mask;
301a0bad
TB
432
433 dst->to_subnet(dst, &host, &mask);
434 if (this->acquires->find_first(this->acquires, (void*)acquire_by_dst,
435 (void**)&acquire, host) == SUCCESS)
436 {
437 host->destroy(host);
438 ignore = TRUE;
439 }
440 else
441 {
442 INIT(acquire,
443 .dst = host,
444 .reqid = reqid,
445 );
446 this->acquires->insert_last(this->acquires, acquire);
447 }
9d737ecf 448 }
a229bdce
TB
449 else
450 {
301a0bad
TB
451 if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
452 (void**)&acquire, &reqid) == SUCCESS)
453 {
454 ignore = TRUE;
455 }
456 else
457 {
458 INIT(acquire,
459 .reqid = reqid,
460 );
461 this->acquires->insert_last(this->acquires, acquire);
462 }
a229bdce
TB
463 }
464 this->mutex->unlock(this->mutex);
301a0bad
TB
465 if (ignore)
466 {
467 DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
468 this->lock->unlock(this->lock);
469 return;
470 }
fc726f13
TB
471 peer = found->peer_cfg->get_ref(found->peer_cfg);
472 child = found->child_sa->get_config(found->child_sa);
473 child = child->get_ref(child);
fc726f13
TB
474 /* don't hold the lock while checking out the IKE_SA */
475 this->lock->unlock(this->lock);
476
301a0bad
TB
477 if (wildcard)
478 { /* the peer config would match IKE_SAs with other peers */
479 ike_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
480 peer->get_ike_version(peer), TRUE);
481 if (ike_sa)
482 {
483 ike_cfg_t *ike_cfg;
b12c53ce
AS
484 uint16_t port;
485 uint8_t mask;
301a0bad
TB
486
487 ike_sa->set_peer_cfg(ike_sa, peer);
488 ike_cfg = ike_sa->get_ike_cfg(ike_sa);
489
490 port = ike_cfg->get_other_port(ike_cfg);
491 dst->to_subnet(dst, &host, &mask);
492 host->set_port(host, port);
493 ike_sa->set_other_host(ike_sa, host);
494
495 port = ike_cfg->get_my_port(ike_cfg);
496 src->to_subnet(src, &host, &mask);
497 host->set_port(host, port);
498 ike_sa->set_my_host(ike_sa, host);
499
500 charon->bus->set_sa(charon->bus, ike_sa);
501 }
502 }
503 else
504 {
505 ike_sa = charon->ike_sa_manager->checkout_by_config(
fc726f13 506 charon->ike_sa_manager, peer);
301a0bad 507 }
b1f2f05c 508 if (ike_sa)
9d737ecf 509 {
b1f2f05c 510 if (ike_sa->get_peer_cfg(ike_sa) == NULL)
9d737ecf 511 {
b1f2f05c
MW
512 ike_sa->set_peer_cfg(ike_sa, peer);
513 }
7fa03b30 514 if (this->ignore_acquire_ts || ike_sa->get_version(ike_sa) == IKEV1)
777bcdc0
MW
515 { /* in IKEv1, don't prepend the acquiring packet TS, as we only
516 * have a single TS that we can establish in a Quick Mode. */
517 src = dst = NULL;
518 }
a229bdce
TB
519
520 this->mutex->lock(this->mutex);
521 acquire->ike_sa = ike_sa;
522 this->mutex->unlock(this->mutex);
523
b1f2f05c
MW
524 if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
525 {
b1f2f05c
MW
526 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
527 }
528 else
529 {
773fcb16
TB
530 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
531 ike_sa);
9d737ecf 532 }
fc726f13 533 }
a229bdce
TB
534 else
535 {
536 this->mutex->lock(this->mutex);
537 this->acquires->remove(this->acquires, acquire, NULL);
538 this->mutex->unlock(this->mutex);
539 destroy_acquire(acquire);
540 child->destroy(child);
541 }
fc726f13 542 peer->destroy(peer);
9d737ecf
MW
543}
544
545/**
991f7ccd 546 * Complete the acquire, if successful or failed
9d737ecf 547 */
991f7ccd
MW
548static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
549 child_sa_t *child_sa)
9d737ecf 550{
9d737ecf 551 enumerator_t *enumerator;
a229bdce 552 acquire_t *acquire;
7daf5226 553
a229bdce
TB
554 this->mutex->lock(this->mutex);
555 enumerator = this->acquires->create_enumerator(this->acquires);
556 while (enumerator->enumerate(enumerator, &acquire))
9d737ecf 557 {
a229bdce 558 if (!acquire->ike_sa || acquire->ike_sa != ike_sa)
991f7ccd
MW
559 {
560 continue;
561 }
301a0bad 562 if (child_sa)
9d737ecf 563 {
301a0bad
TB
564 if (acquire->dst)
565 {
566 /* since every wildcard acquire results in a separate IKE_SA
567 * there is no need to compare the destination address */
568 }
569 else if (child_sa->get_reqid(child_sa) != acquire->reqid)
570 {
571 continue;
572 }
9d737ecf 573 }
a229bdce
TB
574 this->acquires->remove_at(this->acquires, enumerator);
575 destroy_acquire(acquire);
9d737ecf
MW
576 }
577 enumerator->destroy(enumerator);
a229bdce 578 this->mutex->unlock(this->mutex);
991f7ccd
MW
579}
580
06356a29
AS
581METHOD(listener_t, ike_state_change, bool,
582 trap_listener_t *listener, ike_sa_t *ike_sa, ike_sa_state_t state)
991f7ccd
MW
583{
584 switch (state)
585 {
586 case IKE_DESTROYING:
587 complete(listener->traps, ike_sa, NULL);
588 return TRUE;
589 default:
590 return TRUE;
591 }
592}
593
06356a29
AS
594METHOD(listener_t, child_state_change, bool,
595 trap_listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa,
596 child_sa_state_t state)
991f7ccd
MW
597{
598 switch (state)
599 {
600 case CHILD_INSTALLED:
601 case CHILD_DESTROYING:
602 complete(listener->traps, ike_sa, child_sa);
603 return TRUE;
604 default:
605 return TRUE;
606 }
eb8ed130
MW
607}
608
f8437dd8
MW
609METHOD(trap_manager_t, flush, void,
610 private_trap_manager_t *this)
611{
d6656f11 612 this->lock->write_lock(this->lock);
12b3cdba
TB
613 while (this->installing)
614 {
615 this->condvar->wait(this->condvar, this->lock);
616 }
a229bdce 617 this->traps->destroy_function(this->traps, (void*)destroy_entry);
d6656f11 618 this->traps = linked_list_create();
12b3cdba 619 this->installing = INSTALL_DISABLED;
d6656f11 620 this->lock->unlock(this->lock);
f8437dd8
MW
621}
622
06356a29
AS
623METHOD(trap_manager_t, destroy, void,
624 private_trap_manager_t *this)
eb8ed130 625{
9d737ecf 626 charon->bus->remove_listener(charon->bus, &this->listener.listener);
d6656f11 627 this->traps->destroy_function(this->traps, (void*)destroy_entry);
a229bdce 628 this->acquires->destroy_function(this->acquires, (void*)destroy_acquire);
12b3cdba 629 this->condvar->destroy(this->condvar);
a229bdce 630 this->mutex->destroy(this->mutex);
fcb06fdb 631 this->lock->destroy(this->lock);
eb8ed130
MW
632 free(this);
633}
634
635/**
636 * See header
637 */
06356a29 638trap_manager_t *trap_manager_create(void)
eb8ed130 639{
06356a29
AS
640 private_trap_manager_t *this;
641
642 INIT(this,
643 .public = {
644 .install = _install,
645 .uninstall = _uninstall,
646 .create_enumerator = _create_enumerator,
2dcfc698 647 .find_reqid = _find_reqid,
06356a29 648 .acquire = _acquire,
f8437dd8 649 .flush = _flush,
06356a29
AS
650 .destroy = _destroy,
651 },
6a5c8ee7
MW
652 .listener = {
653 .traps = this,
654 .listener = {
655 .ike_state_change = _ike_state_change,
656 .child_state_change = _child_state_change,
657 },
658 },
06356a29 659 .traps = linked_list_create(),
a229bdce
TB
660 .acquires = linked_list_create(),
661 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
06356a29 662 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
12b3cdba 663 .condvar = rwlock_condvar_create(),
7fa03b30
TB
664 .ignore_acquire_ts = lib->settings->get_bool(lib->settings,
665 "%s.ignore_acquire_ts", FALSE, lib->ns),
06356a29 666 );
9d737ecf 667 charon->bus->add_listener(charon->bus, &this->listener.listener);
7daf5226 668
eb8ed130
MW
669 return &this->public;
670}