Annotation of embedaddon/strongswan/src/libcharon/sa/trap_manager.c, revision 1.1.1.2

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 */
1.1.1.2 ! misho     512:                ike_sa = charon->ike_sa_manager->create_new(charon->ike_sa_manager,
1.1       misho     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:        }
1.1.1.2 ! misho     541:        peer->destroy(peer);
        !           542: 
1.1       misho     543:        if (ike_sa)
                    544:        {
                    545:                if (this->ignore_acquire_ts || ike_sa->get_version(ike_sa) == IKEV1)
                    546:                {       /* in IKEv1, don't prepend the acquiring packet TS, as we only
                    547:                         * have a single TS that we can establish in a Quick Mode. */
                    548:                        src = dst = NULL;
                    549:                }
                    550: 
                    551:                this->mutex->lock(this->mutex);
                    552:                acquire->ike_sa = ike_sa;
                    553:                this->mutex->unlock(this->mutex);
                    554: 
                    555:                if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
                    556:                {
                    557:                        charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
                    558:                }
                    559:                else
                    560:                {
                    561:                        charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
                    562:                                                                                                                ike_sa);
                    563:                }
                    564:        }
                    565:        else
                    566:        {
                    567:                this->mutex->lock(this->mutex);
                    568:                this->acquires->remove(this->acquires, acquire, NULL);
                    569:                this->mutex->unlock(this->mutex);
                    570:                destroy_acquire(acquire);
                    571:                child->destroy(child);
                    572:        }
                    573: }
                    574: 
                    575: /**
                    576:  * Complete the acquire, if successful or failed
                    577:  */
                    578: static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
                    579:                                         child_sa_t *child_sa)
                    580: {
                    581:        enumerator_t *enumerator;
                    582:        acquire_t *acquire;
                    583: 
                    584:        this->mutex->lock(this->mutex);
                    585:        enumerator = this->acquires->create_enumerator(this->acquires);
                    586:        while (enumerator->enumerate(enumerator, &acquire))
                    587:        {
                    588:                if (!acquire->ike_sa || acquire->ike_sa != ike_sa)
                    589:                {
                    590:                        continue;
                    591:                }
                    592:                if (child_sa)
                    593:                {
                    594:                        if (acquire->dst)
                    595:                        {
                    596:                                /* since every wildcard acquire results in a separate IKE_SA
                    597:                                 * there is no need to compare the destination address */
                    598:                        }
                    599:                        else if (child_sa->get_reqid(child_sa) != acquire->reqid)
                    600:                        {
                    601:                                continue;
                    602:                        }
                    603:                }
                    604:                this->acquires->remove_at(this->acquires, enumerator);
                    605:                destroy_acquire(acquire);
                    606:        }
                    607:        enumerator->destroy(enumerator);
                    608:        this->mutex->unlock(this->mutex);
                    609: }
                    610: 
                    611: METHOD(listener_t, ike_state_change, bool,
                    612:        trap_listener_t *listener, ike_sa_t *ike_sa, ike_sa_state_t state)
                    613: {
                    614:        switch (state)
                    615:        {
                    616:                case IKE_DESTROYING:
                    617:                        complete(listener->traps, ike_sa, NULL);
                    618:                        return TRUE;
                    619:                default:
                    620:                        return TRUE;
                    621:        }
                    622: }
                    623: 
                    624: METHOD(listener_t, child_state_change, bool,
                    625:        trap_listener_t *listener, ike_sa_t *ike_sa, child_sa_t *child_sa,
                    626:        child_sa_state_t state)
                    627: {
                    628:        switch (state)
                    629:        {
                    630:                case CHILD_INSTALLED:
                    631:                case CHILD_DESTROYING:
                    632:                        complete(listener->traps, ike_sa, child_sa);
                    633:                        return TRUE;
                    634:                default:
                    635:                        return TRUE;
                    636:        }
                    637: }
                    638: 
                    639: METHOD(trap_manager_t, flush, void,
                    640:        private_trap_manager_t *this)
                    641: {
                    642:        this->lock->write_lock(this->lock);
                    643:        while (this->installing)
                    644:        {
                    645:                this->condvar->wait(this->condvar, this->lock);
                    646:        }
                    647:        this->traps->destroy_function(this->traps, (void*)destroy_entry);
                    648:        this->traps = linked_list_create();
                    649:        this->installing = INSTALL_DISABLED;
                    650:        this->lock->unlock(this->lock);
                    651: }
                    652: 
                    653: METHOD(trap_manager_t, destroy, void,
                    654:        private_trap_manager_t *this)
                    655: {
                    656:        charon->bus->remove_listener(charon->bus, &this->listener.listener);
                    657:        this->traps->destroy_function(this->traps, (void*)destroy_entry);
                    658:        this->acquires->destroy_function(this->acquires, (void*)destroy_acquire);
                    659:        this->condvar->destroy(this->condvar);
                    660:        this->mutex->destroy(this->mutex);
                    661:        this->lock->destroy(this->lock);
                    662:        free(this);
                    663: }
                    664: 
                    665: /**
                    666:  * See header
                    667:  */
                    668: trap_manager_t *trap_manager_create(void)
                    669: {
                    670:        private_trap_manager_t *this;
                    671: 
                    672:        INIT(this,
                    673:                .public = {
                    674:                        .install = _install,
                    675:                        .uninstall = _uninstall,
                    676:                        .create_enumerator = _create_enumerator,
                    677:                        .acquire = _acquire,
                    678:                        .flush = _flush,
                    679:                        .destroy = _destroy,
                    680:                },
                    681:                .listener = {
                    682:                        .traps = this,
                    683:                        .listener = {
                    684:                                .ike_state_change = _ike_state_change,
                    685:                                .child_state_change = _child_state_change,
                    686:                        },
                    687:                },
                    688:                .traps = linked_list_create(),
                    689:                .acquires = linked_list_create(),
                    690:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    691:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    692:                .condvar = rwlock_condvar_create(),
                    693:                .ignore_acquire_ts = lib->settings->get_bool(lib->settings,
                    694:                                                                                "%s.ignore_acquire_ts", FALSE, lib->ns),
                    695:        );
                    696:        charon->bus->add_listener(charon->bus, &this->listener.listener);
                    697: 
                    698:        return &this->public;
                    699: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>