Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_attribute.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Tobias Brunner
                      3:  * Copyright (C) 2008 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 "stroke_attribute.h"
                     18: 
                     19: #include <daemon.h>
                     20: #include <collections/linked_list.h>
                     21: #include <threading/rwlock.h>
                     22: 
                     23: typedef struct private_stroke_attribute_t private_stroke_attribute_t;
                     24: 
                     25: /**
                     26:  * private data of stroke_attribute
                     27:  */
                     28: struct private_stroke_attribute_t {
                     29: 
                     30:        /**
                     31:         * public functions
                     32:         */
                     33:        stroke_attribute_t public;
                     34: 
                     35:        /**
                     36:         * list of pools, contains mem_pool_t
                     37:         */
                     38:        linked_list_t *pools;
                     39: 
                     40:        /**
                     41:         * List of connection specific attributes, as attributes_t
                     42:         */
                     43:        linked_list_t *attrs;
                     44: 
                     45:        /**
                     46:         * rwlock to lock access to pools
                     47:         */
                     48:        rwlock_t *lock;
                     49: };
                     50: 
                     51: /**
                     52:  * Attributes assigned to a connection
                     53:  */
                     54: typedef struct {
                     55:        /** name of the connection */
                     56:        char *name;
                     57:        /** list of DNS attributes, as host_t */
                     58:        linked_list_t *dns;
                     59: } attributes_t;
                     60: 
                     61: /**
                     62:  * Destroy an attributes_t entry
                     63:  */
                     64: static void attributes_destroy(attributes_t *this)
                     65: {
                     66:        this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
                     67:        free(this->name);
                     68:        free(this);
                     69: }
                     70: 
                     71: /**
                     72:  * find a pool by name
                     73:  */
                     74: static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
                     75: {
                     76:        enumerator_t *enumerator;
                     77:        mem_pool_t *current, *found = NULL;
                     78: 
                     79:        enumerator = this->pools->create_enumerator(this->pools);
                     80:        while (enumerator->enumerate(enumerator, &current))
                     81:        {
                     82:                if (streq(name, current->get_name(current)))
                     83:                {
                     84:                        found = current;
                     85:                        break;
                     86:                }
                     87:        }
                     88:        enumerator->destroy(enumerator);
                     89:        return found;
                     90: }
                     91: 
                     92: /**
                     93:  * Find an existing or not yet existing lease
                     94:  */
                     95: static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools,
                     96:                                                 identification_t *id, host_t *requested,
                     97:                                                 mem_pool_op_t operation, host_t *peer)
                     98: {
                     99:        host_t *addr = NULL;
                    100:        enumerator_t *enumerator;
                    101:        mem_pool_t *pool;
                    102:        char *name;
                    103: 
                    104:        enumerator = pools->create_enumerator(pools);
                    105:        while (enumerator->enumerate(enumerator, &name))
                    106:        {
                    107:                pool = find_pool(this, name);
                    108:                if (pool)
                    109:                {
                    110:                        addr = pool->acquire_address(pool, id, requested, operation, peer);
                    111:                        if (addr)
                    112:                        {
                    113:                                break;
                    114:                        }
                    115:                }
                    116:        }
                    117:        enumerator->destroy(enumerator);
                    118: 
                    119:        return addr;
                    120: }
                    121: 
                    122: METHOD(attribute_provider_t, acquire_address, host_t*,
                    123:        private_stroke_attribute_t *this, linked_list_t *pools, ike_sa_t *ike_sa,
                    124:        host_t *requested)
                    125: {
                    126:        identification_t *id;
                    127:        host_t *addr, *peer;
                    128: 
                    129:        id = ike_sa->get_other_eap_id(ike_sa);
                    130:        peer = ike_sa->get_other_host(ike_sa);
                    131: 
                    132:        this->lock->read_lock(this->lock);
                    133: 
                    134:        addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING, peer);
                    135:        if (!addr)
                    136:        {
                    137:                addr = find_addr(this, pools, id, requested, MEM_POOL_NEW, peer);
                    138:                if (!addr)
                    139:                {
                    140:                        addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN, peer);
                    141:                }
                    142:        }
                    143: 
                    144:        this->lock->unlock(this->lock);
                    145: 
                    146:        return addr;
                    147: }
                    148: 
                    149: METHOD(attribute_provider_t, release_address, bool,
                    150:        private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
                    151:        ike_sa_t *ike_sa)
                    152: {
                    153:        enumerator_t *enumerator;
                    154:        identification_t *id;
                    155:        mem_pool_t *pool;
                    156:        bool found = FALSE;
                    157:        char *name;
                    158: 
                    159:        id = ike_sa->get_other_eap_id(ike_sa);
                    160: 
                    161:        enumerator = pools->create_enumerator(pools);
                    162:        this->lock->read_lock(this->lock);
                    163:        while (enumerator->enumerate(enumerator, &name))
                    164:        {
                    165:                pool = find_pool(this, name);
                    166:                if (pool)
                    167:                {
                    168:                        found = pool->release_address(pool, address, id);
                    169:                        if (found)
                    170:                        {
                    171:                                break;
                    172:                        }
                    173:                }
                    174:        }
                    175:        this->lock->unlock(this->lock);
                    176:        enumerator->destroy(enumerator);
                    177: 
                    178:        return found;
                    179: }
                    180: 
                    181: CALLBACK(attr_filter, bool,
                    182:        void *lock, enumerator_t *orig, va_list args)
                    183: {
                    184:        configuration_attribute_type_t *type;
                    185:        chunk_t *data;
                    186:        host_t *host;
                    187: 
                    188:        VA_ARGS_VGET(args, type, data);
                    189: 
                    190:        while (orig->enumerate(orig, &host))
                    191:        {
                    192:                switch (host->get_family(host))
                    193:                {
                    194:                        case AF_INET:
                    195:                                *type = INTERNAL_IP4_DNS;
                    196:                                break;
                    197:                        case AF_INET6:
                    198:                                *type = INTERNAL_IP6_DNS;
                    199:                                break;
                    200:                        default:
                    201:                                continue;
                    202:                }
                    203:                *data = host->get_address(host);
                    204:                return TRUE;
                    205:        }
                    206:        return FALSE;
                    207: }
                    208: 
                    209: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
                    210:        private_stroke_attribute_t *this, linked_list_t *pools,
                    211:        ike_sa_t *ike_sa, linked_list_t *vips)
                    212: {
                    213:        peer_cfg_t *peer_cfg;
                    214:        enumerator_t *enumerator;
                    215:        attributes_t *attr;
                    216: 
                    217:        ike_sa = charon->bus->get_sa(charon->bus);
                    218:        if (ike_sa)
                    219:        {
                    220:                peer_cfg = ike_sa->get_peer_cfg(ike_sa);
                    221:                this->lock->read_lock(this->lock);
                    222:                enumerator = this->attrs->create_enumerator(this->attrs);
                    223:                while (enumerator->enumerate(enumerator, &attr))
                    224:                {
                    225:                        if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
                    226:                        {
                    227:                                enumerator->destroy(enumerator);
                    228:                                return enumerator_create_filter(
                    229:                                                                        attr->dns->create_enumerator(attr->dns),
                    230:                                                                        attr_filter, this->lock,
                    231:                                                                        (void*)this->lock->unlock);
                    232:                        }
                    233:                }
                    234:                enumerator->destroy(enumerator);
                    235:                this->lock->unlock(this->lock);
                    236:        }
                    237:        return enumerator_create_empty();
                    238: }
                    239: 
                    240: METHOD(stroke_attribute_t, add_pool, void,
                    241:        private_stroke_attribute_t *this, mem_pool_t *pool)
                    242: {
                    243:        enumerator_t *enumerator;
                    244:        mem_pool_t *current;
                    245:        host_t *base;
                    246:        int size;
                    247: 
                    248:        base = pool->get_base(pool);
                    249:        size = pool->get_size(pool);
                    250: 
                    251:        this->lock->write_lock(this->lock);
                    252: 
                    253:        enumerator = this->pools->create_enumerator(this->pools);
                    254:        while (enumerator->enumerate(enumerator, &current))
                    255:        {
                    256:                if (base && current->get_base(current) &&
                    257:                        base->ip_equals(base, current->get_base(current)) &&
                    258:                        size == current->get_size(current))
                    259:                {
                    260:                        DBG1(DBG_CFG, "reusing virtual IP address pool %s",
                    261:                                 current->get_name(current));
                    262:                        pool->destroy(pool);
                    263:                        pool = NULL;
                    264:                        break;
                    265:                }
                    266:        }
                    267:        enumerator->destroy(enumerator);
                    268: 
                    269:        if (pool)
                    270:        {
                    271:                if (base)
                    272:                {
                    273:                        DBG1(DBG_CFG, "adding virtual IP address pool %s",
                    274:                                 pool->get_name(pool));
                    275:                }
                    276:                this->pools->insert_last(this->pools, pool);
                    277:        }
                    278: 
                    279:        this->lock->unlock(this->lock);
                    280: }
                    281: 
                    282: METHOD(stroke_attribute_t, add_dns, void,
                    283:        private_stroke_attribute_t *this, stroke_msg_t *msg)
                    284: {
                    285:        if (msg->add_conn.other.dns)
                    286:        {
                    287:                enumerator_t *enumerator;
                    288:                attributes_t *attr = NULL;
                    289:                host_t *host;
                    290:                char *token;
                    291: 
                    292:                enumerator = enumerator_create_token(msg->add_conn.other.dns, ",", " ");
                    293:                while (enumerator->enumerate(enumerator, &token))
                    294:                {
                    295:                        host = host_create_from_string(token, 0);
                    296:                        if (host)
                    297:                        {
                    298:                                if (!attr)
                    299:                                {
                    300:                                        INIT(attr,
                    301:                                                .name = strdup(msg->add_conn.name),
                    302:                                                .dns = linked_list_create(),
                    303:                                        );
                    304:                                }
                    305:                                attr->dns->insert_last(attr->dns, host);
                    306:                        }
                    307:                        else
                    308:                        {
                    309:                                DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
                    310:                        }
                    311:                }
                    312:                enumerator->destroy(enumerator);
                    313:                if (attr)
                    314:                {
                    315:                        this->lock->write_lock(this->lock);
                    316:                        this->attrs->insert_last(this->attrs, attr);
                    317:                        this->lock->unlock(this->lock);
                    318:                }
                    319:        }
                    320: }
                    321: 
                    322: METHOD(stroke_attribute_t, del_dns, void,
                    323:        private_stroke_attribute_t *this, stroke_msg_t *msg)
                    324: {
                    325:        enumerator_t *enumerator;
                    326:        attributes_t *attr;
                    327: 
                    328:        this->lock->write_lock(this->lock);
                    329: 
                    330:        enumerator = this->attrs->create_enumerator(this->attrs);
                    331:        while (enumerator->enumerate(enumerator, &attr))
                    332:        {
                    333:                if (streq(msg->del_conn.name, attr->name))
                    334:                {
                    335:                        this->attrs->remove_at(this->attrs, enumerator);
                    336:                        attributes_destroy(attr);
                    337:                        break;
                    338:                }
                    339:        }
                    340:        enumerator->destroy(enumerator);
                    341: 
                    342:        this->lock->unlock(this->lock);
                    343: }
                    344: 
                    345: CALLBACK(pool_filter, bool,
                    346:        void *lock, enumerator_t *orig, va_list args)
                    347: {
                    348:        mem_pool_t *pool;
                    349:        const char **name;
                    350:        u_int *size, *online, *offline;
                    351: 
                    352:        VA_ARGS_VGET(args, name, size, online, offline);
                    353: 
                    354:        while (orig->enumerate(orig, &pool))
                    355:        {
                    356:                if (pool->get_size(pool) == 0)
                    357:                {
                    358:                        continue;
                    359:                }
                    360:                *name = pool->get_name(pool);
                    361:                *size = pool->get_size(pool);
                    362:                *online = pool->get_online(pool);
                    363:                *offline = pool->get_offline(pool);
                    364:                return TRUE;
                    365:        }
                    366:        return FALSE;
                    367: }
                    368: 
                    369: METHOD(stroke_attribute_t, create_pool_enumerator, enumerator_t*,
                    370:        private_stroke_attribute_t *this)
                    371: {
                    372:        this->lock->read_lock(this->lock);
                    373:        return enumerator_create_filter(this->pools->create_enumerator(this->pools),
                    374:                                                                        pool_filter,
                    375:                                                                        this->lock, (void*)this->lock->unlock);
                    376: }
                    377: 
                    378: METHOD(stroke_attribute_t, create_lease_enumerator, enumerator_t*,
                    379:        private_stroke_attribute_t *this, char *name)
                    380: {
                    381:        mem_pool_t *pool;
                    382:        this->lock->read_lock(this->lock);
                    383:        pool = find_pool(this, name);
                    384:        if (!pool)
                    385:        {
                    386:                this->lock->unlock(this->lock);
                    387:                return NULL;
                    388:        }
                    389:        return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
                    390:                                                                         (void*)this->lock->unlock, this->lock);
                    391: }
                    392: 
                    393: METHOD(stroke_attribute_t, destroy, void,
                    394:        private_stroke_attribute_t *this)
                    395: {
                    396:        this->lock->destroy(this->lock);
                    397:        this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
                    398:        this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
                    399:        free(this);
                    400: }
                    401: 
                    402: /*
                    403:  * see header file
                    404:  */
                    405: stroke_attribute_t *stroke_attribute_create()
                    406: {
                    407:        private_stroke_attribute_t *this;
                    408: 
                    409:        INIT(this,
                    410:                .public = {
                    411:                        .provider = {
                    412:                                .acquire_address = _acquire_address,
                    413:                                .release_address = _release_address,
                    414:                                .create_attribute_enumerator = _create_attribute_enumerator,
                    415:                        },
                    416:                        .add_pool = _add_pool,
                    417:                        .add_dns = _add_dns,
                    418:                        .del_dns = _del_dns,
                    419:                        .create_pool_enumerator = _create_pool_enumerator,
                    420:                        .create_lease_enumerator = _create_lease_enumerator,
                    421:                        .destroy = _destroy,
                    422:                },
                    423:                .pools = linked_list_create(),
                    424:                .attrs = linked_list_create(),
                    425:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    426:        );
                    427: 
                    428:        return &this->public;
                    429: }

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