Annotation of embedaddon/strongswan/src/libcharon/attributes/mem_pool.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Tobias Brunner
                      3:  * Copyright (C) 2008-2010 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 "mem_pool.h"
                     18: 
                     19: #include <library.h>
                     20: #include <utils/debug.h>
                     21: #include <collections/hashtable.h>
                     22: #include <collections/array.h>
                     23: #include <threading/mutex.h>
                     24: 
                     25: #define POOL_LIMIT (sizeof(u_int)*8 - 1)
                     26: 
                     27: typedef struct private_mem_pool_t private_mem_pool_t;
                     28: 
                     29: /**
                     30:  * private data of mem_pool_t
                     31:  */
                     32: struct private_mem_pool_t {
                     33:        /**
                     34:         * public interface
                     35:         */
                     36:        mem_pool_t public;
                     37: 
                     38:        /**
                     39:         * name of the pool
                     40:         */
                     41:        char *name;
                     42: 
                     43:        /**
                     44:         * base address of the pool
                     45:         */
                     46:        host_t *base;
                     47: 
                     48:        /**
                     49:         * whether base is the network id of the subnet on which the pool is based
                     50:         */
                     51:        bool base_is_network_id;
                     52: 
                     53:        /**
                     54:         * size of the pool
                     55:         */
                     56:        u_int size;
                     57: 
                     58:        /**
                     59:         * next unused address
                     60:         */
                     61:        u_int unused;
                     62: 
                     63:        /**
                     64:         * lease hashtable [identity => entry]
                     65:         */
                     66:        hashtable_t *leases;
                     67: 
                     68:        /**
                     69:         * lock to safely access the pool
                     70:         */
                     71:        mutex_t *mutex;
                     72: };
                     73: 
                     74: /**
                     75:  * A unique lease address offset, with a hash of the peer host address
                     76:  */
                     77: typedef struct {
                     78:        /** lease, as offset */
                     79:        u_int offset;
                     80:        /** hash of remote address, to allow duplicates */
                     81:        u_int hash;
                     82: } unique_lease_t;
                     83: 
                     84: /**
                     85:  * Lease entry.
                     86:  */
                     87: typedef struct {
                     88:        /* identity reference */
                     89:        identification_t *id;
                     90:        /* array of online leases, as unique_lease_t */
                     91:        array_t *online;
                     92:        /* array of offline leases, as u_int offset */
                     93:        array_t *offline;
                     94: } entry_t;
                     95: 
                     96: /**
                     97:  * Create a new entry
                     98:  */
                     99: static entry_t* entry_create(identification_t *id)
                    100: {
                    101:        entry_t *entry;
                    102: 
                    103:        INIT(entry,
                    104:                .id = id->clone(id),
                    105:                .online = array_create(sizeof(unique_lease_t), 0),
                    106:                .offline = array_create(sizeof(u_int), 0),
                    107:        );
                    108:        return entry;
                    109: }
                    110: 
                    111: /**
                    112:  * Destroy an entry
                    113:  */
                    114: static void entry_destroy(entry_t *this)
                    115: {
                    116:        this->id->destroy(this->id);
                    117:        array_destroy(this->online);
                    118:        array_destroy(this->offline);
                    119:        free(this);
                    120: }
                    121: 
                    122: /**
                    123:  * hashtable hash function for identities
                    124:  */
                    125: static u_int id_hash(identification_t *id)
                    126: {
                    127:        return chunk_hash(id->get_encoding(id));
                    128: }
                    129: 
                    130: /**
                    131:  * hashtable equals function for identities
                    132:  */
                    133: static bool id_equals(identification_t *a, identification_t *b)
                    134: {
                    135:        return a->equals(a, b);
                    136: }
                    137: 
                    138: /**
                    139:  * convert a pool offset to an address
                    140:  */
                    141: static host_t* offset2host(private_mem_pool_t *pool, int offset)
                    142: {
                    143:        chunk_t addr;
                    144:        host_t *host;
                    145:        uint32_t *pos;
                    146: 
                    147:        offset--;
                    148:        if (offset > pool->size)
                    149:        {
                    150:                return NULL;
                    151:        }
                    152: 
                    153:        addr = chunk_clone(pool->base->get_address(pool->base));
                    154:        if (pool->base->get_family(pool->base) == AF_INET6)
                    155:        {
                    156:                pos = (uint32_t*)(addr.ptr + 12);
                    157:        }
                    158:        else
                    159:        {
                    160:                pos = (uint32_t*)addr.ptr;
                    161:        }
                    162:        *pos = htonl(offset + ntohl(*pos));
                    163:        host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0);
                    164:        free(addr.ptr);
                    165:        return host;
                    166: }
                    167: 
                    168: /**
                    169:  * convert a host to a pool offset
                    170:  */
                    171: static int host2offset(private_mem_pool_t *pool, host_t *addr)
                    172: {
                    173:        chunk_t host, base;
                    174:        uint32_t hosti, basei;
                    175: 
                    176:        if (addr->get_family(addr) != pool->base->get_family(pool->base))
                    177:        {
                    178:                return -1;
                    179:        }
                    180:        host = addr->get_address(addr);
                    181:        base = pool->base->get_address(pool->base);
                    182:        if (addr->get_family(addr) == AF_INET6)
                    183:        {
                    184:                /* only look at last /32 block */
                    185:                if (!memeq(host.ptr, base.ptr, 12))
                    186:                {
                    187:                        return -1;
                    188:                }
                    189:                host = chunk_skip(host, 12);
                    190:                base = chunk_skip(base, 12);
                    191:        }
                    192:        hosti = ntohl(*(uint32_t*)(host.ptr));
                    193:        basei = ntohl(*(uint32_t*)(base.ptr));
                    194:        if (hosti > basei + pool->size)
                    195:        {
                    196:                return -1;
                    197:        }
                    198:        return hosti - basei + 1;
                    199: }
                    200: 
                    201: METHOD(mem_pool_t, get_name, const char*,
                    202:        private_mem_pool_t *this)
                    203: {
                    204:        return this->name;
                    205: }
                    206: 
                    207: METHOD(mem_pool_t, get_base, host_t*,
                    208:        private_mem_pool_t *this)
                    209: {
                    210:        return this->base;
                    211: }
                    212: 
                    213: METHOD(mem_pool_t, get_size, u_int,
                    214:        private_mem_pool_t *this)
                    215: {
                    216:        return this->size;
                    217: }
                    218: 
                    219: METHOD(mem_pool_t, get_online, u_int,
                    220:        private_mem_pool_t *this)
                    221: {
                    222:        enumerator_t *enumerator;
                    223:        entry_t *entry;
                    224:        u_int count = 0;
                    225: 
                    226:        this->mutex->lock(this->mutex);
                    227:        enumerator = this->leases->create_enumerator(this->leases);
                    228:        while (enumerator->enumerate(enumerator, NULL, &entry))
                    229:        {
                    230:                count += array_count(entry->online);
                    231:        }
                    232:        enumerator->destroy(enumerator);
                    233:        this->mutex->unlock(this->mutex);
                    234: 
                    235:        return count;
                    236: }
                    237: 
                    238: METHOD(mem_pool_t, get_offline, u_int,
                    239:        private_mem_pool_t *this)
                    240: {
                    241:        enumerator_t *enumerator;
                    242:        entry_t *entry;
                    243:        u_int count = 0;
                    244: 
                    245:        this->mutex->lock(this->mutex);
                    246:        enumerator = this->leases->create_enumerator(this->leases);
                    247:        while (enumerator->enumerate(enumerator, NULL, &entry))
                    248:        {
                    249:                count += array_count(entry->offline);
                    250:        }
                    251:        enumerator->destroy(enumerator);
                    252:        this->mutex->unlock(this->mutex);
                    253: 
                    254:        return count;
                    255: }
                    256: 
                    257: /**
                    258:  * Create a unique hash for a remote address
                    259:  */
                    260: static u_int hash_addr(host_t *addr)
                    261: {
                    262:        if (addr)
                    263:        {
                    264:                return chunk_hash_inc(addr->get_address(addr), addr->get_port(addr));
                    265:        }
                    266:        return 0;
                    267: }
                    268: 
                    269: /**
                    270:  * Get an existing lease for id
                    271:  */
                    272: static int get_existing(private_mem_pool_t *this, identification_t *id,
                    273:                                                host_t *requested, host_t *peer)
                    274: {
                    275:        enumerator_t *enumerator;
                    276:        unique_lease_t *lease, reassign;
                    277:        u_int *current;
                    278:        entry_t *entry;
                    279:        int offset = 0;
                    280: 
                    281:        entry = this->leases->get(this->leases, id);
                    282:        if (!entry)
                    283:        {
                    284:                return 0;
                    285:        }
                    286: 
                    287:        /* check for a valid offline lease, refresh */
                    288:        enumerator = array_create_enumerator(entry->offline);
                    289:        if (enumerator->enumerate(enumerator, &current))
                    290:        {
                    291:                reassign.offset = offset = *current;
                    292:                reassign.hash = hash_addr(peer);
                    293:                array_insert(entry->online, ARRAY_TAIL, &reassign);
                    294:                array_remove_at(entry->offline, enumerator);
                    295:        }
                    296:        enumerator->destroy(enumerator);
                    297:        if (offset)
                    298:        {
                    299:                DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
                    300:                return offset;
                    301:        }
                    302:        if (!peer)
                    303:        {
                    304:                return 0;
                    305:        }
                    306:        /* check for a valid online lease to reassign */
                    307:        enumerator = array_create_enumerator(entry->online);
                    308:        while (enumerator->enumerate(enumerator, &lease))
                    309:        {
1.1.1.2 ! misho     310:                if (lease->hash == hash_addr(peer) &&
        !           311:                        (requested->is_anyaddr(requested) ||
        !           312:                         lease->offset == host2offset(this, requested)))
1.1       misho     313:                {
                    314:                        offset = lease->offset;
                    315:                        /* add an additional "online" entry */
                    316:                        array_insert(entry->online, ARRAY_TAIL, lease);
                    317:                        break;
                    318:                }
                    319:        }
                    320:        enumerator->destroy(enumerator);
                    321:        if (offset)
                    322:        {
                    323:                DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
                    324:        }
                    325:        return offset;
                    326: }
                    327: 
                    328: /**
                    329:  * Get a new lease for id
                    330:  */
                    331: static int get_new(private_mem_pool_t *this, identification_t *id, host_t *peer)
                    332: {
                    333:        entry_t *entry;
                    334:        unique_lease_t lease = {};
                    335: 
                    336:        if (this->unused < this->size)
                    337:        {
                    338:                entry = this->leases->get(this->leases, id);
                    339:                if (!entry)
                    340:                {
                    341:                        entry = entry_create(id);
                    342:                        this->leases->put(this->leases, entry->id, entry);
                    343:                }
                    344:                /* assigning offset, starting by 1 */
                    345:                lease.offset = ++this->unused + (this->base_is_network_id ? 1 : 0);
                    346:                lease.hash = hash_addr(peer);
                    347:                array_insert(entry->online, ARRAY_TAIL, &lease);
                    348:                DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
                    349:        }
                    350:        return lease.offset;
                    351: }
                    352: 
                    353: /**
                    354:  * Get a reassigned lease for id in case the pool is full
                    355:  */
                    356: static int get_reassigned(private_mem_pool_t *this, identification_t *id,
                    357:                                                  host_t *peer)
                    358: {
                    359:        enumerator_t *enumerator;
                    360:        entry_t *entry;
                    361:        u_int current;
                    362:        unique_lease_t lease = {};
                    363: 
                    364:        enumerator = this->leases->create_enumerator(this->leases);
                    365:        while (enumerator->enumerate(enumerator, NULL, &entry))
                    366:        {
                    367:                if (array_remove(entry->offline, ARRAY_HEAD, &current))
                    368:                {
                    369:                        lease.offset = current;
                    370:                        DBG1(DBG_CFG, "reassigning existing offline lease by '%Y' "
                    371:                                 "to '%Y'", entry->id, id);
                    372:                }
                    373:                if (!array_count(entry->online) && !array_count(entry->offline))
                    374:                {
                    375:                        this->leases->remove_at(this->leases, enumerator);
                    376:                        entry_destroy(entry);
                    377:                }
                    378:                if (lease.offset)
                    379:                {
                    380:                        break;
                    381:                }
                    382:        }
                    383:        enumerator->destroy(enumerator);
                    384: 
                    385:        if (lease.offset)
                    386:        {
                    387:                entry = this->leases->get(this->leases, id);
                    388:                if (!entry)
                    389:                {
                    390:                        entry = entry_create(id);
                    391:                        this->leases->put(this->leases, entry->id, entry);
                    392:                }
                    393:                lease.hash = hash_addr(peer);
                    394:                array_insert(entry->online, ARRAY_TAIL, &lease);
                    395:        }
                    396:        return lease.offset;
                    397: }
                    398: 
                    399: METHOD(mem_pool_t, acquire_address, host_t*,
                    400:        private_mem_pool_t *this, identification_t *id, host_t *requested,
                    401:        mem_pool_op_t operation, host_t *peer)
                    402: {
                    403:        int offset = 0;
                    404: 
                    405:        /* if the pool is empty (e.g. in the %config case) we simply return the
                    406:         * requested address */
                    407:        if (this->size == 0)
                    408:        {
                    409:                return requested->clone(requested);
                    410:        }
                    411: 
                    412:        if (requested->get_family(requested) !=
                    413:                this->base->get_family(this->base))
                    414:        {
                    415:                return NULL;
                    416:        }
                    417: 
                    418:        this->mutex->lock(this->mutex);
                    419:        switch (operation)
                    420:        {
                    421:                case MEM_POOL_EXISTING:
                    422:                        offset = get_existing(this, id, requested, peer);
                    423:                        break;
                    424:                case MEM_POOL_NEW:
                    425:                        offset = get_new(this, id, peer);
                    426:                        break;
                    427:                case MEM_POOL_REASSIGN:
                    428:                        offset = get_reassigned(this, id, peer);
                    429:                        if (!offset)
                    430:                        {
                    431:                                DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
                    432:                                         this->name);
                    433:                        }
                    434:                        break;
                    435:                default:
                    436:                        break;
                    437:        }
                    438:        this->mutex->unlock(this->mutex);
                    439: 
                    440:        if (offset)
                    441:        {
                    442:                return offset2host(this, offset);
                    443:        }
                    444:        return NULL;
                    445: }
                    446: 
                    447: METHOD(mem_pool_t, release_address, bool,
                    448:        private_mem_pool_t *this, host_t *address, identification_t *id)
                    449: {
                    450:        enumerator_t *enumerator;
                    451:        bool found = FALSE, more = FALSE;
                    452:        entry_t *entry;
                    453:        u_int offset;
                    454:        unique_lease_t *current;
                    455: 
                    456:        if (this->size != 0)
                    457:        {
                    458:                this->mutex->lock(this->mutex);
                    459:                entry = this->leases->get(this->leases, id);
                    460:                if (entry)
                    461:                {
                    462:                        offset = host2offset(this, address);
                    463: 
                    464:                        enumerator = array_create_enumerator(entry->online);
                    465:                        while (enumerator->enumerate(enumerator, &current))
                    466:                        {
                    467:                                if (current->offset == offset)
                    468:                                {
                    469:                                        if (!found)
                    470:                                        {       /* remove the first entry only */
                    471:                                                array_remove_at(entry->online, enumerator);
                    472:                                                found = TRUE;
                    473:                                        }
                    474:                                        else
                    475:                                        {       /* but check for more entries */
                    476:                                                more = TRUE;
                    477:                                                break;
                    478:                                        }
                    479:                                }
                    480:                        }
                    481:                        enumerator->destroy(enumerator);
                    482: 
                    483:                        if (found && !more)
                    484:                        {
                    485:                                /* no tunnels are online anymore for this lease, make offline */
                    486:                                array_insert(entry->offline, ARRAY_TAIL, &offset);
                    487:                                DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
                    488:                        }
                    489:                }
                    490:                this->mutex->unlock(this->mutex);
                    491:        }
                    492:        return found;
                    493: }
                    494: 
                    495: /**
                    496:  * lease enumerator
                    497:  */
                    498: typedef struct {
                    499:        /** implemented enumerator interface */
                    500:        enumerator_t public;
                    501:        /** hash-table enumerator */
                    502:        enumerator_t *entries;
                    503:        /** online enumerator */
                    504:        enumerator_t *online;
                    505:        /** offline enumerator */
                    506:        enumerator_t *offline;
                    507:        /** enumerated pool */
                    508:        private_mem_pool_t *pool;
                    509:        /** currently enumerated entry */
                    510:        entry_t *entry;
                    511:        /** currently enumerated lease address */
                    512:        host_t *addr;
                    513: } lease_enumerator_t;
                    514: 
                    515: METHOD(enumerator_t, lease_enumerate, bool,
                    516:        lease_enumerator_t *this, va_list args)
                    517: {
                    518:        identification_t **id;
                    519:        unique_lease_t *lease;
                    520:        host_t **addr;
                    521:        u_int *offset;
                    522:        bool *online;
                    523: 
                    524:        VA_ARGS_VGET(args, id, addr, online);
                    525: 
                    526:        DESTROY_IF(this->addr);
                    527:        this->addr = NULL;
                    528: 
                    529:        while (TRUE)
                    530:        {
                    531:                if (this->entry)
                    532:                {
                    533:                        if (this->online->enumerate(this->online, &lease))
                    534:                        {
                    535:                                *id = this->entry->id;
                    536:                                *addr = this->addr = offset2host(this->pool, lease->offset);
                    537:                                *online = TRUE;
                    538:                                return TRUE;
                    539:                        }
                    540:                        if (this->offline->enumerate(this->offline, &offset))
                    541:                        {
                    542:                                *id = this->entry->id;
                    543:                                *addr = this->addr = offset2host(this->pool, *offset);
                    544:                                *online = FALSE;
                    545:                                return TRUE;
                    546:                        }
                    547:                        this->online->destroy(this->online);
                    548:                        this->offline->destroy(this->offline);
                    549:                        this->online = this->offline = NULL;
                    550:                }
                    551:                if (!this->entries->enumerate(this->entries, NULL, &this->entry))
                    552:                {
                    553:                        return FALSE;
                    554:                }
                    555:                this->online = array_create_enumerator(this->entry->online);
                    556:                this->offline = array_create_enumerator(this->entry->offline);
                    557:        }
                    558: }
                    559: 
                    560: METHOD(enumerator_t, lease_enumerator_destroy, void,
                    561:        lease_enumerator_t *this)
                    562: {
                    563:        DESTROY_IF(this->addr);
                    564:        DESTROY_IF(this->online);
                    565:        DESTROY_IF(this->offline);
                    566:        this->entries->destroy(this->entries);
                    567:        this->pool->mutex->unlock(this->pool->mutex);
                    568:        free(this);
                    569: }
                    570: 
                    571: METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
                    572:           private_mem_pool_t *this)
                    573: {
                    574:        lease_enumerator_t *enumerator;
                    575: 
                    576:        this->mutex->lock(this->mutex);
                    577:        INIT(enumerator,
                    578:                .public = {
                    579:                        .enumerate = enumerator_enumerate_default,
                    580:                        .venumerate = _lease_enumerate,
                    581:                        .destroy = _lease_enumerator_destroy,
                    582:                },
                    583:                .pool = this,
                    584:                .entries = this->leases->create_enumerator(this->leases),
                    585:        );
                    586:        return &enumerator->public;
                    587: }
                    588: 
                    589: METHOD(mem_pool_t, destroy, void,
                    590:        private_mem_pool_t *this)
                    591: {
                    592:        enumerator_t *enumerator;
                    593:        entry_t *entry;
                    594: 
                    595:        enumerator = this->leases->create_enumerator(this->leases);
                    596:        while (enumerator->enumerate(enumerator, NULL, &entry))
                    597:        {
                    598:                entry_destroy(entry);
                    599:        }
                    600:        enumerator->destroy(enumerator);
                    601: 
                    602:        this->leases->destroy(this->leases);
                    603:        this->mutex->destroy(this->mutex);
                    604:        DESTROY_IF(this->base);
                    605:        free(this->name);
                    606:        free(this);
                    607: }
                    608: 
                    609: /**
                    610:  * Generic constructor
                    611:  */
                    612: static private_mem_pool_t *create_generic(char *name)
                    613: {
                    614:        private_mem_pool_t *this;
                    615: 
                    616:        INIT(this,
                    617:                .public = {
                    618:                        .get_name = _get_name,
                    619:                        .get_base = _get_base,
                    620:                        .get_size = _get_size,
                    621:                        .get_online = _get_online,
                    622:                        .get_offline = _get_offline,
                    623:                        .acquire_address = _acquire_address,
                    624:                        .release_address = _release_address,
                    625:                        .create_lease_enumerator = _create_lease_enumerator,
                    626:                        .destroy = _destroy,
                    627:                },
                    628:                .name = strdup(name),
                    629:                .leases = hashtable_create((hashtable_hash_t)id_hash,
                    630:                                                                   (hashtable_equals_t)id_equals, 16),
                    631:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    632:        );
                    633: 
                    634:        return this;
                    635: }
                    636: 
                    637: /**
                    638:  * Check if the given host is the network ID of a subnet, that is, if hostbits
                    639:  * are zero.  Since we limit pools to 2^31 addresses we only have to check the
                    640:  * last 4 bytes.
                    641:  */
                    642: static u_int network_id_diff(host_t *host, int hostbits)
                    643: {
                    644:        uint32_t last;
                    645:        chunk_t addr;
                    646: 
                    647:        if (!hostbits)
                    648:        {
                    649:                return 0;
                    650:        }
                    651:        addr = host->get_address(host);
                    652:        last = untoh32(addr.ptr + addr.len - sizeof(last));
                    653:        hostbits = sizeof(last) * 8 - hostbits;
                    654:        return (last << hostbits) >> hostbits;
                    655: }
                    656: 
                    657: /**
                    658:  * Described in header
                    659:  */
                    660: mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
                    661: {
                    662:        private_mem_pool_t *this;
                    663:        u_int diff;
                    664:        int addr_bits;
                    665: 
                    666:        this = create_generic(name);
                    667:        if (base)
                    668:        {
                    669:                addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
                    670:                bits = max(0, min(bits, addr_bits));
                    671:                /* net bits -> host bits */
                    672:                bits = addr_bits - bits;
                    673:                if (bits > POOL_LIMIT)
                    674:                {
                    675:                        bits = POOL_LIMIT;
                    676:                        DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d",
                    677:                                 base, addr_bits - bits);
                    678:                }
                    679:                this->size = 1 << bits;
                    680:                this->base = base->clone(base);
                    681: 
                    682:                if (this->size > 2)
                    683:                {
                    684:                        /* if base is the network id we later skip the first address,
                    685:                         * otherwise adjust the size to represent the actual number
                    686:                         * of assignable addresses */
                    687:                        diff = network_id_diff(base, bits);
                    688:                        if (!diff)
                    689:                        {
                    690:                                this->base_is_network_id = TRUE;
                    691:                                this->size--;
                    692:                        }
                    693:                        else
                    694:                        {
                    695:                                this->size -= diff;
                    696:                        }
                    697:                        /* skip the last address (broadcast) of the subnet */
                    698:                        this->size--;
                    699:                }
                    700:                else if (network_id_diff(base, bits))
                    701:                {       /* only serve the second address of the subnet */
                    702:                        this->size--;
                    703:                }
                    704:        }
                    705:        return &this->public;
                    706: }
                    707: 
                    708: /**
                    709:  * Described in header
                    710:  */
                    711: mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to)
                    712: {
                    713:        private_mem_pool_t *this;
                    714:        chunk_t fromaddr, toaddr;
                    715:        uint32_t diff;
                    716: 
                    717:        fromaddr = from->get_address(from);
                    718:        toaddr = to->get_address(to);
                    719: 
                    720:        if (from->get_family(from) != to->get_family(to) ||
                    721:                fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) ||
                    722:                memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0)
                    723:        {
                    724:                DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to);
                    725:                return NULL;
                    726:        }
                    727:        if (fromaddr.len > sizeof(diff) &&
                    728:                !chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)),
                    729:                                          chunk_create(toaddr.ptr, toaddr.len - sizeof(diff))))
                    730:        {
                    731:                DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to);
                    732:                return NULL;
                    733:        }
                    734:        this = create_generic(name);
                    735:        this->base = from->clone(from);
                    736:        diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) -
                    737:                   untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff));
                    738:        this->size = diff + 1;
                    739: 
                    740:        return &this->public;
                    741: }

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