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

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:        {
                    310:                if (lease->offset == host2offset(this, requested) &&
                    311:                        lease->hash == hash_addr(peer))
                    312:                {
                    313:                        offset = lease->offset;
                    314:                        /* add an additional "online" entry */
                    315:                        array_insert(entry->online, ARRAY_TAIL, lease);
                    316:                        break;
                    317:                }
                    318:        }
                    319:        enumerator->destroy(enumerator);
                    320:        if (offset)
                    321:        {
                    322:                DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
                    323:        }
                    324:        return offset;
                    325: }
                    326: 
                    327: /**
                    328:  * Get a new lease for id
                    329:  */
                    330: static int get_new(private_mem_pool_t *this, identification_t *id, host_t *peer)
                    331: {
                    332:        entry_t *entry;
                    333:        unique_lease_t lease = {};
                    334: 
                    335:        if (this->unused < this->size)
                    336:        {
                    337:                entry = this->leases->get(this->leases, id);
                    338:                if (!entry)
                    339:                {
                    340:                        entry = entry_create(id);
                    341:                        this->leases->put(this->leases, entry->id, entry);
                    342:                }
                    343:                /* assigning offset, starting by 1 */
                    344:                lease.offset = ++this->unused + (this->base_is_network_id ? 1 : 0);
                    345:                lease.hash = hash_addr(peer);
                    346:                array_insert(entry->online, ARRAY_TAIL, &lease);
                    347:                DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
                    348:        }
                    349:        return lease.offset;
                    350: }
                    351: 
                    352: /**
                    353:  * Get a reassigned lease for id in case the pool is full
                    354:  */
                    355: static int get_reassigned(private_mem_pool_t *this, identification_t *id,
                    356:                                                  host_t *peer)
                    357: {
                    358:        enumerator_t *enumerator;
                    359:        entry_t *entry;
                    360:        u_int current;
                    361:        unique_lease_t lease = {};
                    362: 
                    363:        enumerator = this->leases->create_enumerator(this->leases);
                    364:        while (enumerator->enumerate(enumerator, NULL, &entry))
                    365:        {
                    366:                if (array_remove(entry->offline, ARRAY_HEAD, &current))
                    367:                {
                    368:                        lease.offset = current;
                    369:                        DBG1(DBG_CFG, "reassigning existing offline lease by '%Y' "
                    370:                                 "to '%Y'", entry->id, id);
                    371:                }
                    372:                if (!array_count(entry->online) && !array_count(entry->offline))
                    373:                {
                    374:                        this->leases->remove_at(this->leases, enumerator);
                    375:                        entry_destroy(entry);
                    376:                }
                    377:                if (lease.offset)
                    378:                {
                    379:                        break;
                    380:                }
                    381:        }
                    382:        enumerator->destroy(enumerator);
                    383: 
                    384:        if (lease.offset)
                    385:        {
                    386:                entry = this->leases->get(this->leases, id);
                    387:                if (!entry)
                    388:                {
                    389:                        entry = entry_create(id);
                    390:                        this->leases->put(this->leases, entry->id, entry);
                    391:                }
                    392:                lease.hash = hash_addr(peer);
                    393:                array_insert(entry->online, ARRAY_TAIL, &lease);
                    394:        }
                    395:        return lease.offset;
                    396: }
                    397: 
                    398: METHOD(mem_pool_t, acquire_address, host_t*,
                    399:        private_mem_pool_t *this, identification_t *id, host_t *requested,
                    400:        mem_pool_op_t operation, host_t *peer)
                    401: {
                    402:        int offset = 0;
                    403: 
                    404:        /* if the pool is empty (e.g. in the %config case) we simply return the
                    405:         * requested address */
                    406:        if (this->size == 0)
                    407:        {
                    408:                return requested->clone(requested);
                    409:        }
                    410: 
                    411:        if (requested->get_family(requested) !=
                    412:                this->base->get_family(this->base))
                    413:        {
                    414:                return NULL;
                    415:        }
                    416: 
                    417:        this->mutex->lock(this->mutex);
                    418:        switch (operation)
                    419:        {
                    420:                case MEM_POOL_EXISTING:
                    421:                        offset = get_existing(this, id, requested, peer);
                    422:                        break;
                    423:                case MEM_POOL_NEW:
                    424:                        offset = get_new(this, id, peer);
                    425:                        break;
                    426:                case MEM_POOL_REASSIGN:
                    427:                        offset = get_reassigned(this, id, peer);
                    428:                        if (!offset)
                    429:                        {
                    430:                                DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
                    431:                                         this->name);
                    432:                        }
                    433:                        break;
                    434:                default:
                    435:                        break;
                    436:        }
                    437:        this->mutex->unlock(this->mutex);
                    438: 
                    439:        if (offset)
                    440:        {
                    441:                return offset2host(this, offset);
                    442:        }
                    443:        return NULL;
                    444: }
                    445: 
                    446: METHOD(mem_pool_t, release_address, bool,
                    447:        private_mem_pool_t *this, host_t *address, identification_t *id)
                    448: {
                    449:        enumerator_t *enumerator;
                    450:        bool found = FALSE, more = FALSE;
                    451:        entry_t *entry;
                    452:        u_int offset;
                    453:        unique_lease_t *current;
                    454: 
                    455:        if (this->size != 0)
                    456:        {
                    457:                this->mutex->lock(this->mutex);
                    458:                entry = this->leases->get(this->leases, id);
                    459:                if (entry)
                    460:                {
                    461:                        offset = host2offset(this, address);
                    462: 
                    463:                        enumerator = array_create_enumerator(entry->online);
                    464:                        while (enumerator->enumerate(enumerator, &current))
                    465:                        {
                    466:                                if (current->offset == offset)
                    467:                                {
                    468:                                        if (!found)
                    469:                                        {       /* remove the first entry only */
                    470:                                                array_remove_at(entry->online, enumerator);
                    471:                                                found = TRUE;
                    472:                                        }
                    473:                                        else
                    474:                                        {       /* but check for more entries */
                    475:                                                more = TRUE;
                    476:                                                break;
                    477:                                        }
                    478:                                }
                    479:                        }
                    480:                        enumerator->destroy(enumerator);
                    481: 
                    482:                        if (found && !more)
                    483:                        {
                    484:                                /* no tunnels are online anymore for this lease, make offline */
                    485:                                array_insert(entry->offline, ARRAY_TAIL, &offset);
                    486:                                DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
                    487:                        }
                    488:                }
                    489:                this->mutex->unlock(this->mutex);
                    490:        }
                    491:        return found;
                    492: }
                    493: 
                    494: /**
                    495:  * lease enumerator
                    496:  */
                    497: typedef struct {
                    498:        /** implemented enumerator interface */
                    499:        enumerator_t public;
                    500:        /** hash-table enumerator */
                    501:        enumerator_t *entries;
                    502:        /** online enumerator */
                    503:        enumerator_t *online;
                    504:        /** offline enumerator */
                    505:        enumerator_t *offline;
                    506:        /** enumerated pool */
                    507:        private_mem_pool_t *pool;
                    508:        /** currently enumerated entry */
                    509:        entry_t *entry;
                    510:        /** currently enumerated lease address */
                    511:        host_t *addr;
                    512: } lease_enumerator_t;
                    513: 
                    514: METHOD(enumerator_t, lease_enumerate, bool,
                    515:        lease_enumerator_t *this, va_list args)
                    516: {
                    517:        identification_t **id;
                    518:        unique_lease_t *lease;
                    519:        host_t **addr;
                    520:        u_int *offset;
                    521:        bool *online;
                    522: 
                    523:        VA_ARGS_VGET(args, id, addr, online);
                    524: 
                    525:        DESTROY_IF(this->addr);
                    526:        this->addr = NULL;
                    527: 
                    528:        while (TRUE)
                    529:        {
                    530:                if (this->entry)
                    531:                {
                    532:                        if (this->online->enumerate(this->online, &lease))
                    533:                        {
                    534:                                *id = this->entry->id;
                    535:                                *addr = this->addr = offset2host(this->pool, lease->offset);
                    536:                                *online = TRUE;
                    537:                                return TRUE;
                    538:                        }
                    539:                        if (this->offline->enumerate(this->offline, &offset))
                    540:                        {
                    541:                                *id = this->entry->id;
                    542:                                *addr = this->addr = offset2host(this->pool, *offset);
                    543:                                *online = FALSE;
                    544:                                return TRUE;
                    545:                        }
                    546:                        this->online->destroy(this->online);
                    547:                        this->offline->destroy(this->offline);
                    548:                        this->online = this->offline = NULL;
                    549:                }
                    550:                if (!this->entries->enumerate(this->entries, NULL, &this->entry))
                    551:                {
                    552:                        return FALSE;
                    553:                }
                    554:                this->online = array_create_enumerator(this->entry->online);
                    555:                this->offline = array_create_enumerator(this->entry->offline);
                    556:        }
                    557: }
                    558: 
                    559: METHOD(enumerator_t, lease_enumerator_destroy, void,
                    560:        lease_enumerator_t *this)
                    561: {
                    562:        DESTROY_IF(this->addr);
                    563:        DESTROY_IF(this->online);
                    564:        DESTROY_IF(this->offline);
                    565:        this->entries->destroy(this->entries);
                    566:        this->pool->mutex->unlock(this->pool->mutex);
                    567:        free(this);
                    568: }
                    569: 
                    570: METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
                    571:           private_mem_pool_t *this)
                    572: {
                    573:        lease_enumerator_t *enumerator;
                    574: 
                    575:        this->mutex->lock(this->mutex);
                    576:        INIT(enumerator,
                    577:                .public = {
                    578:                        .enumerate = enumerator_enumerate_default,
                    579:                        .venumerate = _lease_enumerate,
                    580:                        .destroy = _lease_enumerator_destroy,
                    581:                },
                    582:                .pool = this,
                    583:                .entries = this->leases->create_enumerator(this->leases),
                    584:        );
                    585:        return &enumerator->public;
                    586: }
                    587: 
                    588: METHOD(mem_pool_t, destroy, void,
                    589:        private_mem_pool_t *this)
                    590: {
                    591:        enumerator_t *enumerator;
                    592:        entry_t *entry;
                    593: 
                    594:        enumerator = this->leases->create_enumerator(this->leases);
                    595:        while (enumerator->enumerate(enumerator, NULL, &entry))
                    596:        {
                    597:                entry_destroy(entry);
                    598:        }
                    599:        enumerator->destroy(enumerator);
                    600: 
                    601:        this->leases->destroy(this->leases);
                    602:        this->mutex->destroy(this->mutex);
                    603:        DESTROY_IF(this->base);
                    604:        free(this->name);
                    605:        free(this);
                    606: }
                    607: 
                    608: /**
                    609:  * Generic constructor
                    610:  */
                    611: static private_mem_pool_t *create_generic(char *name)
                    612: {
                    613:        private_mem_pool_t *this;
                    614: 
                    615:        INIT(this,
                    616:                .public = {
                    617:                        .get_name = _get_name,
                    618:                        .get_base = _get_base,
                    619:                        .get_size = _get_size,
                    620:                        .get_online = _get_online,
                    621:                        .get_offline = _get_offline,
                    622:                        .acquire_address = _acquire_address,
                    623:                        .release_address = _release_address,
                    624:                        .create_lease_enumerator = _create_lease_enumerator,
                    625:                        .destroy = _destroy,
                    626:                },
                    627:                .name = strdup(name),
                    628:                .leases = hashtable_create((hashtable_hash_t)id_hash,
                    629:                                                                   (hashtable_equals_t)id_equals, 16),
                    630:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    631:        );
                    632: 
                    633:        return this;
                    634: }
                    635: 
                    636: /**
                    637:  * Check if the given host is the network ID of a subnet, that is, if hostbits
                    638:  * are zero.  Since we limit pools to 2^31 addresses we only have to check the
                    639:  * last 4 bytes.
                    640:  */
                    641: static u_int network_id_diff(host_t *host, int hostbits)
                    642: {
                    643:        uint32_t last;
                    644:        chunk_t addr;
                    645: 
                    646:        if (!hostbits)
                    647:        {
                    648:                return 0;
                    649:        }
                    650:        addr = host->get_address(host);
                    651:        last = untoh32(addr.ptr + addr.len - sizeof(last));
                    652:        hostbits = sizeof(last) * 8 - hostbits;
                    653:        return (last << hostbits) >> hostbits;
                    654: }
                    655: 
                    656: /**
                    657:  * Described in header
                    658:  */
                    659: mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
                    660: {
                    661:        private_mem_pool_t *this;
                    662:        u_int diff;
                    663:        int addr_bits;
                    664: 
                    665:        this = create_generic(name);
                    666:        if (base)
                    667:        {
                    668:                addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
                    669:                bits = max(0, min(bits, addr_bits));
                    670:                /* net bits -> host bits */
                    671:                bits = addr_bits - bits;
                    672:                if (bits > POOL_LIMIT)
                    673:                {
                    674:                        bits = POOL_LIMIT;
                    675:                        DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d",
                    676:                                 base, addr_bits - bits);
                    677:                }
                    678:                this->size = 1 << bits;
                    679:                this->base = base->clone(base);
                    680: 
                    681:                if (this->size > 2)
                    682:                {
                    683:                        /* if base is the network id we later skip the first address,
                    684:                         * otherwise adjust the size to represent the actual number
                    685:                         * of assignable addresses */
                    686:                        diff = network_id_diff(base, bits);
                    687:                        if (!diff)
                    688:                        {
                    689:                                this->base_is_network_id = TRUE;
                    690:                                this->size--;
                    691:                        }
                    692:                        else
                    693:                        {
                    694:                                this->size -= diff;
                    695:                        }
                    696:                        /* skip the last address (broadcast) of the subnet */
                    697:                        this->size--;
                    698:                }
                    699:                else if (network_id_diff(base, bits))
                    700:                {       /* only serve the second address of the subnet */
                    701:                        this->size--;
                    702:                }
                    703:        }
                    704:        return &this->public;
                    705: }
                    706: 
                    707: /**
                    708:  * Described in header
                    709:  */
                    710: mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to)
                    711: {
                    712:        private_mem_pool_t *this;
                    713:        chunk_t fromaddr, toaddr;
                    714:        uint32_t diff;
                    715: 
                    716:        fromaddr = from->get_address(from);
                    717:        toaddr = to->get_address(to);
                    718: 
                    719:        if (from->get_family(from) != to->get_family(to) ||
                    720:                fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) ||
                    721:                memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0)
                    722:        {
                    723:                DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to);
                    724:                return NULL;
                    725:        }
                    726:        if (fromaddr.len > sizeof(diff) &&
                    727:                !chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)),
                    728:                                          chunk_create(toaddr.ptr, toaddr.len - sizeof(diff))))
                    729:        {
                    730:                DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to);
                    731:                return NULL;
                    732:        }
                    733:        this = create_generic(name);
                    734:        this->base = from->clone(from);
                    735:        diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) -
                    736:                   untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff));
                    737:        this->size = diff + 1;
                    738: 
                    739:        return &this->public;
                    740: }

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