Annotation of embedaddon/strongswan/src/libcharon/sa/trap_manager.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011-2017 Tobias Brunner
! 3: * Copyright (C) 2009 Martin Willi
! 4: * HSR 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.
! 15: */
! 16:
! 17: #include "trap_manager.h"
! 18:
! 19: #include <daemon.h>
! 20: #include <threading/mutex.h>
! 21: #include <threading/rwlock.h>
! 22: #include <threading/rwlock_condvar.h>
! 23: #include <collections/linked_list.h>
! 24:
! 25: #define INSTALL_DISABLED ((u_int)~0)
! 26:
! 27: typedef struct private_trap_manager_t private_trap_manager_t;
! 28: typedef struct trap_listener_t trap_listener_t;
! 29:
! 30: /**
! 31: * listener to track acquires
! 32: */
! 33: struct trap_listener_t {
! 34:
! 35: /**
! 36: * Implements listener interface
! 37: */
! 38: listener_t listener;
! 39:
! 40: /**
! 41: * points to trap_manager
! 42: */
! 43: private_trap_manager_t *traps;
! 44: };
! 45:
! 46: /**
! 47: * Private data of an trap_manager_t object.
! 48: */
! 49: struct private_trap_manager_t {
! 50:
! 51: /**
! 52: * Public trap_manager_t interface.
! 53: */
! 54: trap_manager_t public;
! 55:
! 56: /**
! 57: * Installed traps, as entry_t
! 58: */
! 59: linked_list_t *traps;
! 60:
! 61: /**
! 62: * read write lock for traps list
! 63: */
! 64: rwlock_t *lock;
! 65:
! 66: /**
! 67: * listener to track acquiring IKE_SAs
! 68: */
! 69: trap_listener_t listener;
! 70:
! 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:
! 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:
! 91: /**
! 92: * Whether to ignore traffic selectors from acquires
! 93: */
! 94: bool ignore_acquire_ts;
! 95: };
! 96:
! 97: /**
! 98: * A installed trap entry
! 99: */
! 100: typedef struct {
! 101: /** name of the trapped CHILD_SA */
! 102: char *name;
! 103: /** ref to peer_cfg to initiate */
! 104: peer_cfg_t *peer_cfg;
! 105: /** ref to instantiated CHILD_SA (i.e the trap policy) */
! 106: child_sa_t *child_sa;
! 107: /** TRUE in case of wildcard Transport Mode SA */
! 108: bool wildcard;
! 109: } entry_t;
! 110:
! 111: /**
! 112: * A handled acquire
! 113: */
! 114: typedef struct {
! 115: /** pending IKE_SA connecting upon acquire */
! 116: ike_sa_t *ike_sa;
! 117: /** reqid of pending trap policy */
! 118: uint32_t reqid;
! 119: /** destination address (wildcard case) */
! 120: host_t *dst;
! 121: } acquire_t;
! 122:
! 123: /**
! 124: * actually uninstall and destroy an installed entry
! 125: */
! 126: static 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: */
! 137: static void destroy_acquire(acquire_t *this)
! 138: {
! 139: DESTROY_IF(this->dst);
! 140: free(this);
! 141: }
! 142:
! 143: CALLBACK(acquire_by_reqid, bool,
! 144: acquire_t *this, va_list args)
! 145: {
! 146: uint32_t reqid;
! 147:
! 148: VA_ARGS_VGET(args, reqid);
! 149: return this->reqid == reqid;
! 150: }
! 151:
! 152: CALLBACK(acquire_by_dst, bool,
! 153: acquire_t *this, va_list args)
! 154: {
! 155: host_t *dst;
! 156:
! 157: VA_ARGS_VGET(args, dst);
! 158: return this->dst && this->dst->ip_equals(this->dst, dst);
! 159: }
! 160:
! 161: /**
! 162: * Check if any remote TS are dynamic
! 163: */
! 164: static 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:
! 171: other_ts = child->get_traffic_selectors(child, FALSE, NULL, NULL, FALSE);
! 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:
! 186: METHOD(trap_manager_t, install, bool,
! 187: private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child)
! 188: {
! 189: entry_t *entry, *found = NULL;
! 190: ike_cfg_t *ike_cfg;
! 191: child_sa_t *child_sa;
! 192: host_t *me, *other;
! 193: linked_list_t *my_ts, *other_ts, *list;
! 194: enumerator_t *enumerator;
! 195: status_t status;
! 196: linked_list_t *proposals;
! 197: proposal_t *proposal;
! 198: protocol_id_t proto = PROTO_ESP;
! 199: bool result = FALSE, wildcard = FALSE;
! 200:
! 201: /* try to resolve addresses */
! 202: ike_cfg = peer->get_ike_cfg(peer);
! 203: other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
! 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: }
! 211: else if (other && other->is_anyaddr(other))
! 212: {
! 213: other->destroy(other);
! 214: DBG1(DBG_CFG, "installing trap failed, remote address unknown");
! 215: return FALSE;
! 216: }
! 217: else
! 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");
! 225: return FALSE;
! 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))
! 235: {
! 236: DESTROY_IF(me);
! 237: me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
! 238: }
! 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));
! 244: }
! 245:
! 246: this->lock->write_lock(this->lock);
! 247: if (this->installing == INSTALL_DISABLED)
! 248: { /* flush() has been called */
! 249: this->lock->unlock(this->lock);
! 250: other->destroy(other);
! 251: me->destroy(me);
! 252: return FALSE;
! 253: }
! 254: enumerator = this->traps->create_enumerator(this->traps);
! 255: while (enumerator->enumerate(enumerator, &entry))
! 256: {
! 257: if (streq(entry->name, child->get_name(child)) &&
! 258: streq(entry->peer_cfg->get_name(entry->peer_cfg),
! 259: peer->get_name(peer)))
! 260: {
! 261: found = entry;
! 262: if (entry->child_sa)
! 263: { /* replace it with an updated version, if already installed */
! 264: this->traps->remove_at(this->traps, enumerator);
! 265: }
! 266: break;
! 267: }
! 268: }
! 269: enumerator->destroy(enumerator);
! 270:
! 271: if (found)
! 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);
! 277: other->destroy(other);
! 278: me->destroy(me);
! 279: return FALSE;
! 280: }
! 281: /* config might have changed so update everything */
! 282: DBG1(DBG_CFG, "updating already routed CHILD_SA '%s'", found->name);
! 283: }
! 284:
! 285: INIT(entry,
! 286: .name = strdup(child->get_name(child)),
! 287: .peer_cfg = peer->get_ref(peer),
! 288: .wildcard = wildcard,
! 289: );
! 290: this->traps->insert_first(this->traps, entry);
! 291: this->installing++;
! 292: /* don't hold lock while creating CHILD_SA and installing policies */
! 293: this->lock->unlock(this->lock);
! 294:
! 295: /* create and route CHILD_SA */
! 296: child_sa_create_t child_data = {
! 297: /* TODO: no reason to allocate unique interface IDs, there is currently
! 298: * no event to use them upon trap installation and we'd also have to
! 299: * pass them in a later initiate() call */
! 300: .if_id_in_def = peer->get_if_id(peer, TRUE),
! 301: .if_id_out_def = peer->get_if_id(peer, FALSE),
! 302: };
! 303: child_sa = child_sa_create(me, other, child, &child_data);
! 304:
! 305: list = linked_list_create_with_items(me, NULL);
! 306: my_ts = child->get_traffic_selectors(child, TRUE, NULL, list, FALSE);
! 307: list->destroy_offset(list, offsetof(host_t, destroy));
! 308:
! 309: list = linked_list_create_with_items(other, NULL);
! 310: other_ts = child->get_traffic_selectors(child, FALSE, NULL, list, FALSE);
! 311: list->destroy_offset(list, offsetof(host_t, destroy));
! 312:
! 313: /* We don't know the finally negotiated protocol (ESP|AH), we install
! 314: * the SA with the protocol of the first proposal */
! 315: proposals = child->get_proposals(child, TRUE);
! 316: if (proposals->get_first(proposals, (void**)&proposal) == SUCCESS)
! 317: {
! 318: proto = proposal->get_protocol(proposal);
! 319: }
! 320: proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
! 321: child_sa->set_protocol(child_sa, proto);
! 322: child_sa->set_mode(child_sa, child->get_mode(child));
! 323: child_sa->set_policies(child_sa, my_ts, other_ts);
! 324: status = child_sa->install_policies(child_sa);
! 325: my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
! 326: other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
! 327: if (status != SUCCESS)
! 328: {
! 329: DBG1(DBG_CFG, "installing trap failed");
! 330: this->lock->write_lock(this->lock);
! 331: this->traps->remove(this->traps, entry, NULL);
! 332: this->lock->unlock(this->lock);
! 333: entry->child_sa = child_sa;
! 334: destroy_entry(entry);
! 335: }
! 336: else
! 337: {
! 338: this->lock->write_lock(this->lock);
! 339: entry->child_sa = child_sa;
! 340: this->lock->unlock(this->lock);
! 341: result = TRUE;
! 342: }
! 343: if (found)
! 344: {
! 345: destroy_entry(found);
! 346: }
! 347: this->lock->write_lock(this->lock);
! 348: /* do this at the end, so entries created temporarily are also destroyed */
! 349: this->installing--;
! 350: this->condvar->signal(this->condvar);
! 351: this->lock->unlock(this->lock);
! 352: return result;
! 353: }
! 354:
! 355: METHOD(trap_manager_t, uninstall, bool,
! 356: private_trap_manager_t *this, char *peer, char *child)
! 357: {
! 358: enumerator_t *enumerator;
! 359: entry_t *entry, *found = NULL;
! 360:
! 361: this->lock->write_lock(this->lock);
! 362: while (this->installing)
! 363: {
! 364: this->condvar->wait(this->condvar, this->lock);
! 365: }
! 366: enumerator = this->traps->create_enumerator(this->traps);
! 367: while (enumerator->enumerate(enumerator, &entry))
! 368: {
! 369: if (streq(entry->name, child) &&
! 370: (!peer || streq(peer, entry->peer_cfg->get_name(entry->peer_cfg))))
! 371: {
! 372: this->traps->remove_at(this->traps, enumerator);
! 373: found = entry;
! 374: break;
! 375: }
! 376: }
! 377: enumerator->destroy(enumerator);
! 378: this->lock->unlock(this->lock);
! 379:
! 380: if (!found)
! 381: {
! 382: return FALSE;
! 383: }
! 384: destroy_entry(found);
! 385: return TRUE;
! 386: }
! 387:
! 388: CALLBACK(trap_filter, bool,
! 389: rwlock_t *lock, enumerator_t *orig, va_list args)
! 390: {
! 391: entry_t *entry;
! 392: peer_cfg_t **peer_cfg;
! 393: child_sa_t **child_sa;
! 394:
! 395: VA_ARGS_VGET(args, peer_cfg, child_sa);
! 396:
! 397: while (orig->enumerate(orig, &entry))
! 398: {
! 399: if (!entry->child_sa)
! 400: { /* skip entries that are currently being installed */
! 401: continue;
! 402: }
! 403: if (peer_cfg)
! 404: {
! 405: *peer_cfg = entry->peer_cfg;
! 406: }
! 407: if (child_sa)
! 408: {
! 409: *child_sa = entry->child_sa;
! 410: }
! 411: return TRUE;
! 412: }
! 413: return FALSE;
! 414: }
! 415:
! 416: METHOD(trap_manager_t, create_enumerator, enumerator_t*,
! 417: private_trap_manager_t *this)
! 418: {
! 419: this->lock->read_lock(this->lock);
! 420: return enumerator_create_filter(this->traps->create_enumerator(this->traps),
! 421: trap_filter, this->lock,
! 422: (void*)this->lock->unlock);
! 423: }
! 424:
! 425: METHOD(trap_manager_t, acquire, void,
! 426: private_trap_manager_t *this, uint32_t reqid,
! 427: traffic_selector_t *src, traffic_selector_t *dst)
! 428: {
! 429: enumerator_t *enumerator;
! 430: entry_t *entry, *found = NULL;
! 431: acquire_t *acquire;
! 432: peer_cfg_t *peer;
! 433: child_cfg_t *child;
! 434: ike_sa_t *ike_sa;
! 435: host_t *host;
! 436: bool wildcard, ignore = FALSE;
! 437:
! 438: this->lock->read_lock(this->lock);
! 439: enumerator = this->traps->create_enumerator(this->traps);
! 440: while (enumerator->enumerate(enumerator, &entry))
! 441: {
! 442: if (entry->child_sa &&
! 443: entry->child_sa->get_reqid(entry->child_sa) == reqid)
! 444: {
! 445: found = entry;
! 446: break;
! 447: }
! 448: }
! 449: enumerator->destroy(enumerator);
! 450:
! 451: if (!found)
! 452: {
! 453: DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d", reqid);
! 454: this->lock->unlock(this->lock);
! 455: return;
! 456: }
! 457: reqid = found->child_sa->get_reqid(found->child_sa);
! 458: wildcard = found->wildcard;
! 459:
! 460: this->mutex->lock(this->mutex);
! 461: if (wildcard)
! 462: { /* for wildcard acquires we check that we don't have a pending acquire
! 463: * with the same peer */
! 464: uint8_t mask;
! 465:
! 466: dst->to_subnet(dst, &host, &mask);
! 467: if (this->acquires->find_first(this->acquires, acquire_by_dst,
! 468: (void**)&acquire, host))
! 469: {
! 470: host->destroy(host);
! 471: ignore = TRUE;
! 472: }
! 473: else
! 474: {
! 475: INIT(acquire,
! 476: .dst = host,
! 477: .reqid = reqid,
! 478: );
! 479: this->acquires->insert_last(this->acquires, acquire);
! 480: }
! 481: }
! 482: else
! 483: {
! 484: if (this->acquires->find_first(this->acquires, acquire_by_reqid,
! 485: (void**)&acquire, reqid))
! 486: {
! 487: ignore = TRUE;
! 488: }
! 489: else
! 490: {
! 491: INIT(acquire,
! 492: .reqid = reqid,
! 493: );
! 494: this->acquires->insert_last(this->acquires, acquire);
! 495: }
! 496: }
! 497: this->mutex->unlock(this->mutex);
! 498: if (ignore)
! 499: {
! 500: DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
! 501: this->lock->unlock(this->lock);
! 502: return;
! 503: }
! 504: peer = found->peer_cfg->get_ref(found->peer_cfg);
! 505: child = found->child_sa->get_config(found->child_sa);
! 506: child = child->get_ref(child);
! 507: /* don't hold the lock while checking out the IKE_SA */
! 508: this->lock->unlock(this->lock);
! 509:
! 510: if (wildcard)
! 511: { /* the peer config would match IKE_SAs with other peers */
! 512: ike_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
! 513: peer->get_ike_version(peer), TRUE);
! 514: if (ike_sa)
! 515: {
! 516: ike_cfg_t *ike_cfg;
! 517: uint16_t port;
! 518: uint8_t mask;
! 519:
! 520: ike_sa->set_peer_cfg(ike_sa, peer);
! 521: ike_cfg = ike_sa->get_ike_cfg(ike_sa);
! 522:
! 523: port = ike_cfg->get_other_port(ike_cfg);
! 524: dst->to_subnet(dst, &host, &mask);
! 525: host->set_port(host, port);
! 526: ike_sa->set_other_host(ike_sa, host);
! 527:
! 528: port = ike_cfg->get_my_port(ike_cfg);
! 529: src->to_subnet(src, &host, &mask);
! 530: host->set_port(host, port);
! 531: ike_sa->set_my_host(ike_sa, host);
! 532:
! 533: charon->bus->set_sa(charon->bus, ike_sa);
! 534: }
! 535: }
! 536: else
! 537: {
! 538: ike_sa = charon->ike_sa_manager->checkout_by_config(
! 539: charon->ike_sa_manager, peer);
! 540: }
! 541: if (ike_sa)
! 542: {
! 543: if (ike_sa->get_peer_cfg(ike_sa) == NULL)
! 544: {
! 545: ike_sa->set_peer_cfg(ike_sa, peer);
! 546: }
! 547: if (this->ignore_acquire_ts || ike_sa->get_version(ike_sa) == IKEV1)
! 548: { /* in IKEv1, don't prepend the acquiring packet TS, as we only
! 549: * have a single TS that we can establish in a Quick Mode. */
! 550: src = dst = NULL;
! 551: }
! 552:
! 553: this->mutex->lock(this->mutex);
! 554: acquire->ike_sa = ike_sa;
! 555: this->mutex->unlock(this->mutex);
! 556:
! 557: if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
! 558: {
! 559: charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
! 560: }
! 561: else
! 562: {
! 563: charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
! 564: ike_sa);
! 565: }
! 566: }
! 567: else
! 568: {
! 569: this->mutex->lock(this->mutex);
! 570: this->acquires->remove(this->acquires, acquire, NULL);
! 571: this->mutex->unlock(this->mutex);
! 572: destroy_acquire(acquire);
! 573: child->destroy(child);
! 574: }
! 575: peer->destroy(peer);
! 576: }
! 577:
! 578: /**
! 579: * Complete the acquire, if successful or failed
! 580: */
! 581: static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
! 582: child_sa_t *child_sa)
! 583: {
! 584: enumerator_t *enumerator;
! 585: acquire_t *acquire;
! 586:
! 587: this->mutex->lock(this->mutex);
! 588: enumerator = this->acquires->create_enumerator(this->acquires);
! 589: while (enumerator->enumerate(enumerator, &acquire))
! 590: {
! 591: if (!acquire->ike_sa || acquire->ike_sa != ike_sa)
! 592: {
! 593: continue;
! 594: }
! 595: if (child_sa)
! 596: {
! 597: if (acquire->dst)
! 598: {
! 599: /* since every wildcard acquire results in a separate IKE_SA
! 600: * there is no need to compare the destination address */
! 601: }
! 602: else if (child_sa->get_reqid(child_sa) != acquire->reqid)
! 603: {
! 604: continue;
! 605: }
! 606: }
! 607: this->acquires->remove_at(this->acquires, enumerator);
! 608: destroy_acquire(acquire);
! 609: }
! 610: enumerator->destroy(enumerator);
! 611: this->mutex->unlock(this->mutex);
! 612: }
! 613:
! 614: METHOD(listener_t, ike_state_change, bool,
! 615: trap_listener_t *listener, ike_sa_t *ike_sa, ike_sa_state_t state)
! 616: {
! 617: switch (state)
! 618: {
! 619: case IKE_DESTROYING:
! 620: complete(listener->traps, ike_sa, NULL);
! 621: return TRUE;
! 622: default:
! 623: return TRUE;
! 624: }
! 625: }
! 626:
! 627: METHOD(listener_t, child_state_change, bool,
! 628: trap_listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa,
! 629: child_sa_state_t state)
! 630: {
! 631: switch (state)
! 632: {
! 633: case CHILD_INSTALLED:
! 634: case CHILD_DESTROYING:
! 635: complete(listener->traps, ike_sa, child_sa);
! 636: return TRUE;
! 637: default:
! 638: return TRUE;
! 639: }
! 640: }
! 641:
! 642: METHOD(trap_manager_t, flush, void,
! 643: private_trap_manager_t *this)
! 644: {
! 645: this->lock->write_lock(this->lock);
! 646: while (this->installing)
! 647: {
! 648: this->condvar->wait(this->condvar, this->lock);
! 649: }
! 650: this->traps->destroy_function(this->traps, (void*)destroy_entry);
! 651: this->traps = linked_list_create();
! 652: this->installing = INSTALL_DISABLED;
! 653: this->lock->unlock(this->lock);
! 654: }
! 655:
! 656: METHOD(trap_manager_t, destroy, void,
! 657: private_trap_manager_t *this)
! 658: {
! 659: charon->bus->remove_listener(charon->bus, &this->listener.listener);
! 660: this->traps->destroy_function(this->traps, (void*)destroy_entry);
! 661: this->acquires->destroy_function(this->acquires, (void*)destroy_acquire);
! 662: this->condvar->destroy(this->condvar);
! 663: this->mutex->destroy(this->mutex);
! 664: this->lock->destroy(this->lock);
! 665: free(this);
! 666: }
! 667:
! 668: /**
! 669: * See header
! 670: */
! 671: trap_manager_t *trap_manager_create(void)
! 672: {
! 673: private_trap_manager_t *this;
! 674:
! 675: INIT(this,
! 676: .public = {
! 677: .install = _install,
! 678: .uninstall = _uninstall,
! 679: .create_enumerator = _create_enumerator,
! 680: .acquire = _acquire,
! 681: .flush = _flush,
! 682: .destroy = _destroy,
! 683: },
! 684: .listener = {
! 685: .traps = this,
! 686: .listener = {
! 687: .ike_state_change = _ike_state_change,
! 688: .child_state_change = _child_state_change,
! 689: },
! 690: },
! 691: .traps = linked_list_create(),
! 692: .acquires = linked_list_create(),
! 693: .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
! 694: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
! 695: .condvar = rwlock_condvar_create(),
! 696: .ignore_acquire_ts = lib->settings->get_bool(lib->settings,
! 697: "%s.ignore_acquire_ts", FALSE, lib->ns),
! 698: );
! 699: charon->bus->add_listener(charon->bus, &this->listener.listener);
! 700:
! 701: return &this->public;
! 702: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>