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>