Annotation of embedaddon/strongswan/src/libcharon/kernel/kernel_interface.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2008-2019 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2010 Martin Willi
                      6:  * Copyright (C) 2010 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: /*
                     20:  * Copyright (c) 2012 Nanoteq Pty Ltd
                     21:  *
                     22:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     23:  * of this software and associated documentation files (the "Software"), to deal
                     24:  * in the Software without restriction, including without limitation the rights
                     25:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     26:  * copies of the Software, and to permit persons to whom the Software is
                     27:  * furnished to do so, subject to the following conditions:
                     28:  *
                     29:  * The above copyright notice and this permission notice shall be included in
                     30:  * all copies or substantial portions of the Software.
                     31:  *
                     32:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     33:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     34:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     35:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     36:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     37:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     38:  * THE SOFTWARE.
                     39:  */
                     40: 
                     41: #include "kernel_interface.h"
                     42: 
                     43: #include <utils/debug.h>
                     44: #include <threading/mutex.h>
                     45: #include <collections/linked_list.h>
                     46: #include <collections/hashtable.h>
                     47: #include <collections/array.h>
                     48: 
                     49: typedef struct private_kernel_interface_t private_kernel_interface_t;
                     50: 
                     51: typedef struct kernel_algorithm_t kernel_algorithm_t;
                     52: 
                     53: /**
                     54:  * Mapping of IKE algorithms to kernel-specific algorithm identifiers
                     55:  */
                     56: struct kernel_algorithm_t {
                     57: 
                     58:        /**
                     59:         * Transform type of the algorithm
                     60:         */
                     61:        transform_type_t type;
                     62: 
                     63:        /**
                     64:         * Identifier specified in IKE
                     65:         */
                     66:        uint16_t ike;
                     67: 
                     68:        /**
                     69:         * Identifier as defined in pfkeyv2.h
                     70:         */
                     71:        uint16_t kernel;
                     72: 
                     73:        /**
                     74:         * Name of the algorithm in linux crypto API
                     75:         */
                     76:        char *name;
                     77: };
                     78: 
                     79: /**
                     80:  * Private data of a kernel_interface_t object.
                     81:  */
                     82: struct private_kernel_interface_t {
                     83: 
                     84:        /**
                     85:         * Public part of kernel_interface_t object.
                     86:         */
                     87:        kernel_interface_t public;
                     88: 
                     89:        /**
                     90:         * Registered IPsec constructor
                     91:         */
                     92:        kernel_ipsec_constructor_t ipsec_constructor;
                     93: 
                     94:        /**
                     95:         * Registered net constructor
                     96:         */
                     97:        kernel_net_constructor_t net_constructor;
                     98: 
                     99:        /**
                    100:         * ipsec interface
                    101:         */
                    102:        kernel_ipsec_t *ipsec;
                    103: 
                    104:        /**
                    105:         * network interface
                    106:         */
                    107:        kernel_net_t *net;
                    108: 
                    109:        /**
                    110:         * mutex for listeners
                    111:         */
                    112:        mutex_t *mutex;
                    113: 
                    114:        /**
                    115:         * list of registered listeners
                    116:         */
                    117:        linked_list_t *listeners;
                    118: 
                    119:        /**
                    120:         * Reqid entries indexed by reqids
                    121:         */
                    122:        hashtable_t *reqids;
                    123: 
                    124:        /**
                    125:         * Reqid entries indexed by traffic selectors
                    126:         */
                    127:        hashtable_t *reqids_by_ts;
                    128: 
                    129:        /**
                    130:         * Previously used reqids that have been released
                    131:         */
                    132:        array_t *released_reqids;
                    133: 
                    134:        /**
                    135:         * mutex for algorithm mappings
                    136:         */
                    137:        mutex_t *mutex_algs;
                    138: 
                    139:        /**
                    140:         * List of algorithm mappings (kernel_algorithm_t*)
                    141:         */
                    142:        linked_list_t *algorithms;
                    143: 
                    144:        /**
                    145:         * List of interface names to include or exclude (char*), NULL if interfaces
                    146:         * are not filtered
                    147:         */
                    148:        linked_list_t *ifaces_filter;
                    149: 
                    150:        /**
                    151:         * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider
                    152:         * only those listed there
                    153:         */
                    154:        bool ifaces_exclude;
                    155: };
                    156: 
                    157: METHOD(kernel_interface_t, get_features, kernel_feature_t,
                    158:        private_kernel_interface_t *this)
                    159: {
                    160:        kernel_feature_t features = 0;
                    161: 
                    162:        if (this->ipsec && this->ipsec->get_features)
                    163:        {
                    164:                features |= this->ipsec->get_features(this->ipsec);
                    165:        }
                    166:        if (this->net && this->net->get_features)
                    167:        {
                    168:                features |= this->net->get_features(this->net);
                    169:        }
                    170:        return features;
                    171: }
                    172: 
                    173: METHOD(kernel_interface_t, get_spi, status_t,
                    174:        private_kernel_interface_t *this, host_t *src, host_t *dst,
                    175:        uint8_t protocol, uint32_t *spi)
                    176: {
                    177:        if (!this->ipsec)
                    178:        {
                    179:                return NOT_SUPPORTED;
                    180:        }
                    181:        return this->ipsec->get_spi(this->ipsec, src, dst, protocol, spi);
                    182: }
                    183: 
                    184: METHOD(kernel_interface_t, get_cpi, status_t,
                    185:        private_kernel_interface_t *this, host_t *src, host_t *dst,
                    186:        uint16_t *cpi)
                    187: {
                    188:        if (!this->ipsec)
                    189:        {
                    190:                return NOT_SUPPORTED;
                    191:        }
                    192:        return this->ipsec->get_cpi(this->ipsec, src, dst, cpi);
                    193: }
                    194: 
                    195: /**
                    196:  * Reqid mapping entry
                    197:  */
                    198: typedef struct {
                    199:        /** allocated reqid */
                    200:        uint32_t reqid;
                    201:        /** references to this entry */
                    202:        u_int refs;
                    203:        /** inbound mark used for SA */
                    204:        mark_t mark_in;
                    205:        /** outbound mark used for SA */
                    206:        mark_t mark_out;
                    207:        /** inbound interface ID used for SA */
                    208:        uint32_t if_id_in;
                    209:        /** outbound interface ID used for SA */
                    210:        uint32_t if_id_out;
                    211:        /** local traffic selectors */
                    212:        array_t *local;
                    213:        /** remote traffic selectors */
                    214:        array_t *remote;
                    215: } reqid_entry_t;
                    216: 
                    217: /**
                    218:  * Destroy a reqid mapping entry
                    219:  */
                    220: static void reqid_entry_destroy(reqid_entry_t *entry)
                    221: {
                    222:        array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy));
                    223:        array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy));
                    224:        free(entry);
                    225: }
                    226: 
                    227: /**
                    228:  * Hashtable hash function for reqid entries using reqid as key
                    229:  */
                    230: static u_int hash_reqid(reqid_entry_t *entry)
                    231: {
                    232:        return chunk_hash_inc(chunk_from_thing(entry->reqid),
                    233:                                chunk_hash_inc(chunk_from_thing(entry->mark_in),
                    234:                                        chunk_hash_inc(chunk_from_thing(entry->mark_out),
                    235:                                                chunk_hash_inc(chunk_from_thing(entry->if_id_in),
                    236:                                                        chunk_hash(chunk_from_thing(entry->if_id_out))))));
                    237: }
                    238: 
                    239: /**
                    240:  * Hashtable equals function for reqid entries using reqid as key
                    241:  */
                    242: static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b)
                    243: {
                    244:        return a->reqid == b->reqid &&
                    245:                   a->mark_in.value == b->mark_in.value &&
                    246:                   a->mark_in.mask == b->mark_in.mask &&
                    247:                   a->mark_out.value == b->mark_out.value &&
                    248:                   a->mark_out.mask == b->mark_out.mask &&
                    249:                   a->if_id_in == b->if_id_in &&
                    250:                   a->if_id_out == b->if_id_out;
                    251: }
                    252: 
                    253: /**
                    254:  * Hash an array of traffic selectors
                    255:  */
                    256: static u_int hash_ts_array(array_t *array, u_int hash)
                    257: {
                    258:        enumerator_t *enumerator;
                    259:        traffic_selector_t *ts;
                    260: 
                    261:        enumerator = array_create_enumerator(array);
                    262:        while (enumerator->enumerate(enumerator, &ts))
                    263:        {
                    264:                hash = ts->hash(ts, hash);
                    265:        }
                    266:        enumerator->destroy(enumerator);
                    267: 
                    268:        return hash;
                    269: }
                    270: 
                    271: /**
                    272:  * Hashtable hash function for reqid entries using traffic selectors as key
                    273:  */
                    274: static u_int hash_reqid_by_ts(reqid_entry_t *entry)
                    275: {
                    276:        return hash_ts_array(entry->local, hash_ts_array(entry->remote,
                    277:                        chunk_hash_inc(chunk_from_thing(entry->mark_in),
                    278:                                chunk_hash_inc(chunk_from_thing(entry->mark_out),
                    279:                                        chunk_hash_inc(chunk_from_thing(entry->if_id_in),
                    280:                                                chunk_hash(chunk_from_thing(entry->if_id_out)))))));
                    281: }
                    282: 
                    283: /**
                    284:  * Compare two array with traffic selectors for equality
                    285:  */
                    286: static bool ts_array_equals(array_t *a, array_t *b)
                    287: {
                    288:        traffic_selector_t *tsa, *tsb;
                    289:        enumerator_t *ae, *be;
                    290:        bool equal = TRUE;
                    291: 
                    292:        if (array_count(a) != array_count(b))
                    293:        {
                    294:                return FALSE;
                    295:        }
                    296: 
                    297:        ae = array_create_enumerator(a);
                    298:        be = array_create_enumerator(b);
                    299:        while (equal && ae->enumerate(ae, &tsa) && be->enumerate(be, &tsb))
                    300:        {
                    301:                equal = tsa->equals(tsa, tsb);
                    302:        }
                    303:        ae->destroy(ae);
                    304:        be->destroy(be);
                    305: 
                    306:        return equal;
                    307: }
                    308: 
                    309: /**
                    310:  * Hashtable equals function for reqid entries using traffic selectors as key
                    311:  */
                    312: static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b)
                    313: {
                    314:        return ts_array_equals(a->local, b->local) &&
                    315:                   ts_array_equals(a->remote, b->remote) &&
                    316:                   a->mark_in.value == b->mark_in.value &&
                    317:                   a->mark_in.mask == b->mark_in.mask &&
                    318:                   a->mark_out.value == b->mark_out.value &&
                    319:                   a->mark_out.mask == b->mark_out.mask &&
                    320:                   a->if_id_in == b->if_id_in &&
                    321:                   a->if_id_out == b->if_id_out;
                    322: }
                    323: 
                    324: /**
                    325:  * Create an array from copied traffic selector list items
                    326:  */
                    327: static array_t *array_from_ts_list(linked_list_t *list)
                    328: {
                    329:        enumerator_t *enumerator;
                    330:        traffic_selector_t *ts;
                    331:        array_t *array;
                    332: 
                    333:        array = array_create(0, 0);
                    334: 
                    335:        enumerator = list->create_enumerator(list);
                    336:        while (enumerator->enumerate(enumerator, &ts))
                    337:        {
                    338:                array_insert(array, ARRAY_TAIL, ts->clone(ts));
                    339:        }
                    340:        enumerator->destroy(enumerator);
                    341: 
                    342:        return array;
                    343: }
                    344: 
                    345: METHOD(kernel_interface_t, alloc_reqid, status_t,
                    346:        private_kernel_interface_t *this,
                    347:        linked_list_t *local_ts, linked_list_t *remote_ts,
                    348:        mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out,
                    349:        uint32_t *reqid)
                    350: {
                    351:        static uint32_t counter = 0;
                    352:        reqid_entry_t *entry = NULL, *tmpl;
                    353:        status_t status = SUCCESS;
                    354: 
                    355:        INIT(tmpl,
                    356:                .local = array_from_ts_list(local_ts),
                    357:                .remote = array_from_ts_list(remote_ts),
                    358:                .mark_in = mark_in,
                    359:                .mark_out = mark_out,
                    360:                .if_id_in = if_id_in,
                    361:                .if_id_out = if_id_out,
                    362:                .reqid = *reqid,
                    363:        );
                    364: 
                    365:        this->mutex->lock(this->mutex);
                    366:        if (tmpl->reqid)
                    367:        {
                    368:                /* search by reqid if given */
                    369:                entry = this->reqids->get(this->reqids, tmpl);
                    370:        }
                    371:        if (entry)
                    372:        {
                    373:                /* we don't require a traffic selector match for explicit reqids,
                    374:                 * as we want to reuse a reqid for trap-triggered policies that
                    375:                 * got narrowed during negotiation. */
                    376:                reqid_entry_destroy(tmpl);
                    377:        }
                    378:        else
                    379:        {
                    380:                /* search by traffic selectors */
                    381:                entry = this->reqids_by_ts->get(this->reqids_by_ts, tmpl);
                    382:                if (entry)
                    383:                {
                    384:                        reqid_entry_destroy(tmpl);
                    385:                }
                    386:                else
                    387:                {
                    388:                        /* none found, create a new entry, allocating a reqid */
                    389:                        entry = tmpl;
                    390:                        if (!array_remove(this->released_reqids, ARRAY_HEAD, &entry->reqid))
                    391:                        {
                    392:                                entry->reqid = ++counter;
                    393:                        }
                    394:                        this->reqids_by_ts->put(this->reqids_by_ts, entry, entry);
                    395:                        this->reqids->put(this->reqids, entry, entry);
                    396:                }
                    397:                *reqid = entry->reqid;
                    398:        }
                    399:        entry->refs++;
                    400:        this->mutex->unlock(this->mutex);
                    401: 
                    402:        return status;
                    403: }
                    404: 
                    405: METHOD(kernel_interface_t, release_reqid, status_t,
                    406:        private_kernel_interface_t *this, uint32_t reqid,
                    407:        mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out)
                    408: {
                    409:        reqid_entry_t *entry, tmpl = {
                    410:                .reqid = reqid,
                    411:                .mark_in = mark_in,
                    412:                .mark_out = mark_out,
                    413:                .if_id_in = if_id_in,
                    414:                .if_id_out = if_id_out,
                    415:        };
                    416: 
                    417:        this->mutex->lock(this->mutex);
                    418:        entry = this->reqids->remove(this->reqids, &tmpl);
                    419:        if (entry)
                    420:        {
                    421:                if (--entry->refs == 0)
                    422:                {
                    423:                        array_insert_create_value(&this->released_reqids, sizeof(uint32_t),
                    424:                                                                          ARRAY_TAIL, &entry->reqid);
                    425:                        entry = this->reqids_by_ts->remove(this->reqids_by_ts, entry);
                    426:                        if (entry)
                    427:                        {
                    428:                                reqid_entry_destroy(entry);
                    429:                        }
                    430:                }
                    431:                else
                    432:                {
                    433:                        this->reqids->put(this->reqids, entry, entry);
                    434:                }
                    435:        }
                    436:        this->mutex->unlock(this->mutex);
                    437: 
                    438:        if (entry)
                    439:        {
                    440:                return SUCCESS;
                    441:        }
                    442:        return NOT_FOUND;
                    443: }
                    444: 
                    445: METHOD(kernel_interface_t, add_sa, status_t,
                    446:        private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
                    447:        kernel_ipsec_add_sa_t *data)
                    448: {
                    449:        if (!this->ipsec)
                    450:        {
                    451:                return NOT_SUPPORTED;
                    452:        }
                    453:        return this->ipsec->add_sa(this->ipsec, id, data);
                    454: }
                    455: 
                    456: METHOD(kernel_interface_t, update_sa, status_t,
                    457:        private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
                    458:        kernel_ipsec_update_sa_t *data)
                    459: {
                    460:        if (!this->ipsec)
                    461:        {
                    462:                return NOT_SUPPORTED;
                    463:        }
                    464:        return this->ipsec->update_sa(this->ipsec, id, data);
                    465: }
                    466: 
                    467: METHOD(kernel_interface_t, query_sa, status_t,
                    468:        private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
                    469:        kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
                    470:        time_t *time)
                    471: {
                    472:        if (!this->ipsec)
                    473:        {
                    474:                return NOT_SUPPORTED;
                    475:        }
                    476:        return this->ipsec->query_sa(this->ipsec, id, data, bytes, packets, time);
                    477: }
                    478: 
                    479: METHOD(kernel_interface_t, del_sa, status_t,
                    480:        private_kernel_interface_t *this, kernel_ipsec_sa_id_t *id,
                    481:        kernel_ipsec_del_sa_t *data)
                    482: {
                    483:        if (!this->ipsec)
                    484:        {
                    485:                return NOT_SUPPORTED;
                    486:        }
                    487:        return this->ipsec->del_sa(this->ipsec, id, data);
                    488: }
                    489: 
                    490: METHOD(kernel_interface_t, flush_sas, status_t,
                    491:        private_kernel_interface_t *this)
                    492: {
                    493:        if (!this->ipsec)
                    494:        {
                    495:                return NOT_SUPPORTED;
                    496:        }
                    497:        return this->ipsec->flush_sas(this->ipsec);
                    498: }
                    499: 
                    500: METHOD(kernel_interface_t, add_policy, status_t,
                    501:        private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
                    502:        kernel_ipsec_manage_policy_t *data)
                    503: {
                    504:        if (!this->ipsec)
                    505:        {
                    506:                return NOT_SUPPORTED;
                    507:        }
                    508:        return this->ipsec->add_policy(this->ipsec, id, data);
                    509: }
                    510: 
                    511: METHOD(kernel_interface_t, query_policy, status_t,
                    512:        private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
                    513:        kernel_ipsec_query_policy_t *data, time_t *use_time)
                    514: {
                    515:        if (!this->ipsec)
                    516:        {
                    517:                return NOT_SUPPORTED;
                    518:        }
                    519:        return this->ipsec->query_policy(this->ipsec, id, data, use_time);
                    520: }
                    521: 
                    522: METHOD(kernel_interface_t, del_policy, status_t,
                    523:        private_kernel_interface_t *this, kernel_ipsec_policy_id_t *id,
                    524:        kernel_ipsec_manage_policy_t *data)
                    525: {
                    526:        if (!this->ipsec)
                    527:        {
                    528:                return NOT_SUPPORTED;
                    529:        }
                    530:        return this->ipsec->del_policy(this->ipsec, id, data);
                    531: }
                    532: 
                    533: METHOD(kernel_interface_t, flush_policies, status_t,
                    534:        private_kernel_interface_t *this)
                    535: {
                    536:        if (!this->ipsec)
                    537:        {
                    538:                return NOT_SUPPORTED;
                    539:        }
                    540:        return this->ipsec->flush_policies(this->ipsec);
                    541: }
                    542: 
                    543: METHOD(kernel_interface_t, get_source_addr, host_t*,
                    544:        private_kernel_interface_t *this, host_t *dest, host_t *src)
                    545: {
                    546:        if (!this->net)
                    547:        {
                    548:                return NULL;
                    549:        }
                    550:        return this->net->get_source_addr(this->net, dest, src);
                    551: }
                    552: 
                    553: METHOD(kernel_interface_t, get_nexthop, host_t*,
                    554:        private_kernel_interface_t *this, host_t *dest, int prefix, host_t *src,
                    555:        char **iface)
                    556: {
                    557:        if (!this->net)
                    558:        {
                    559:                return NULL;
                    560:        }
                    561:        return this->net->get_nexthop(this->net, dest, prefix, src, iface);
                    562: }
                    563: 
                    564: METHOD(kernel_interface_t, get_interface, bool,
                    565:        private_kernel_interface_t *this, host_t *host, char **name)
                    566: {
                    567:        if (!this->net)
                    568:        {
                    569:                return NULL;
                    570:        }
                    571:        return this->net->get_interface(this->net, host, name);
                    572: }
                    573: 
                    574: METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
                    575:        private_kernel_interface_t *this, kernel_address_type_t which)
                    576: {
                    577:        if (!this->net)
                    578:        {
                    579:                return enumerator_create_empty();
                    580:        }
                    581:        return this->net->create_address_enumerator(this->net, which);
                    582: }
                    583: 
                    584: METHOD(kernel_interface_t, create_local_subnet_enumerator, enumerator_t*,
                    585:        private_kernel_interface_t *this)
                    586: {
                    587:        if (!this->net || !this->net->create_local_subnet_enumerator)
                    588:        {
                    589:                return enumerator_create_empty();
                    590:        }
                    591:        return this->net->create_local_subnet_enumerator(this->net);
                    592: }
                    593: 
                    594: METHOD(kernel_interface_t, add_ip, status_t,
                    595:        private_kernel_interface_t *this, host_t *virtual_ip, int prefix,
                    596:        char *iface)
                    597: {
                    598:        if (!this->net)
                    599:        {
                    600:                return NOT_SUPPORTED;
                    601:        }
                    602:        return this->net->add_ip(this->net, virtual_ip, prefix, iface);
                    603: }
                    604: 
                    605: METHOD(kernel_interface_t, del_ip, status_t,
                    606:        private_kernel_interface_t *this, host_t *virtual_ip, int prefix, bool wait)
                    607: {
                    608:        if (!this->net)
                    609:        {
                    610:                return NOT_SUPPORTED;
                    611:        }
                    612:        return this->net->del_ip(this->net, virtual_ip, prefix, wait);
                    613: }
                    614: 
                    615: METHOD(kernel_interface_t, add_route, status_t,
                    616:        private_kernel_interface_t *this, chunk_t dst_net,
                    617:        uint8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name,
                    618:        bool pass)
                    619: {
                    620:        if (!this->net)
                    621:        {
                    622:                return NOT_SUPPORTED;
                    623:        }
                    624:        return this->net->add_route(this->net, dst_net, prefixlen, gateway,
                    625:                                                                src_ip, if_name, pass);
                    626: }
                    627: 
                    628: METHOD(kernel_interface_t, del_route, status_t,
                    629:        private_kernel_interface_t *this, chunk_t dst_net,
                    630:        uint8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name,
                    631:        bool pass)
                    632: {
                    633:        if (!this->net)
                    634:        {
                    635:                return NOT_SUPPORTED;
                    636:        }
                    637:        return this->net->del_route(this->net, dst_net, prefixlen, gateway,
                    638:                                                                src_ip, if_name, pass);
                    639: }
                    640: 
                    641: METHOD(kernel_interface_t, bypass_socket, bool,
                    642:        private_kernel_interface_t *this, int fd, int family)
                    643: {
                    644:        if (!this->ipsec)
                    645:        {
                    646:                return FALSE;
                    647:        }
                    648:        return this->ipsec->bypass_socket(this->ipsec, fd, family);
                    649: }
                    650: 
                    651: METHOD(kernel_interface_t, enable_udp_decap, bool,
                    652:        private_kernel_interface_t *this, int fd, int family, uint16_t port)
                    653: {
                    654:        if (!this->ipsec)
                    655:        {
                    656:                return FALSE;
                    657:        }
                    658:        return this->ipsec->enable_udp_decap(this->ipsec, fd, family, port);
                    659: }
                    660: 
                    661: METHOD(kernel_interface_t, is_interface_usable, bool,
                    662:        private_kernel_interface_t *this, const char *iface)
                    663: {
                    664:        if (!this->ifaces_filter)
                    665:        {
                    666:                return TRUE;
                    667:        }
                    668:        return this->ifaces_filter->find_first(this->ifaces_filter,
                    669:                                        linked_list_match_str, NULL, iface) != this->ifaces_exclude;
                    670: }
                    671: 
                    672: METHOD(kernel_interface_t, all_interfaces_usable, bool,
                    673:        private_kernel_interface_t *this)
                    674: {
                    675:        return !this->ifaces_filter;
                    676: }
                    677: 
                    678: METHOD(kernel_interface_t, get_address_by_ts, status_t,
                    679:        private_kernel_interface_t *this, traffic_selector_t *ts,
                    680:        host_t **ip, bool *vip)
                    681: {
                    682:        enumerator_t *addrs;
                    683:        host_t *host;
                    684:        int family;
                    685:        bool found = FALSE;
                    686: 
                    687:        DBG2(DBG_KNL, "getting a local address in traffic selector %R", ts);
                    688: 
                    689:        /* if we have a family which includes localhost, we do not
                    690:         * search for an IP, we use the default */
                    691:        family = ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
                    692: 
                    693:        if (family == AF_INET)
                    694:        {
                    695:                host = host_create_from_string("127.0.0.1", 0);
                    696:        }
                    697:        else
                    698:        {
                    699:                host = host_create_from_string("::1", 0);
                    700:        }
                    701: 
                    702:        if (ts->includes(ts, host))
                    703:        {
                    704:                *ip = host_create_any(family);
                    705:                if (vip)
                    706:                {
                    707:                        *vip = FALSE;
                    708:                }
                    709:                host->destroy(host);
                    710:                DBG2(DBG_KNL, "using host %H", *ip);
                    711:                return SUCCESS;
                    712:        }
                    713:        host->destroy(host);
                    714: 
                    715:        /* try virtual IPs only first (on all interfaces) */
                    716:        addrs = create_address_enumerator(this,
                    717:                                                                          ADDR_TYPE_ALL ^ ADDR_TYPE_REGULAR);
                    718:        while (addrs->enumerate(addrs, (void**)&host))
                    719:        {
                    720:                if (ts->includes(ts, host))
                    721:                {
                    722:                        found = TRUE;
                    723:                        *ip = host->clone(host);
                    724:                        if (vip)
                    725:                        {
                    726:                                *vip = TRUE;
                    727:                        }
                    728:                        break;
                    729:                }
                    730:        }
                    731:        addrs->destroy(addrs);
                    732: 
                    733:        if (!found)
                    734:        {       /* then try the regular addresses (on all interfaces) */
                    735:                addrs = create_address_enumerator(this,
                    736:                                                                                  ADDR_TYPE_ALL ^ ADDR_TYPE_VIRTUAL);
                    737:                while (addrs->enumerate(addrs, (void**)&host))
                    738:                {
                    739:                        if (ts->includes(ts, host))
                    740:                        {
                    741:                                found = TRUE;
                    742:                                *ip = host->clone(host);
                    743:                                if (vip)
                    744:                                {
                    745:                                        *vip = FALSE;
                    746:                                }
                    747:                                break;
                    748:                        }
                    749:                }
                    750:                addrs->destroy(addrs);
                    751:        }
                    752: 
                    753:        if (!found)
                    754:        {
                    755:                DBG2(DBG_KNL, "no local address found in traffic selector %R", ts);
                    756:                return FAILED;
                    757:        }
                    758: 
                    759:        DBG2(DBG_KNL, "using host %H", *ip);
                    760:        return SUCCESS;
                    761: }
                    762: 
                    763: 
                    764: METHOD(kernel_interface_t, add_ipsec_interface, bool,
                    765:        private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
                    766: {
                    767:        if (!this->ipsec)
                    768:        {
                    769:                this->ipsec_constructor = constructor;
                    770:                this->ipsec = constructor();
                    771:                return this->ipsec != NULL;
                    772:        }
                    773:        return FALSE;
                    774: }
                    775: 
                    776: METHOD(kernel_interface_t, remove_ipsec_interface, bool,
                    777:        private_kernel_interface_t *this, kernel_ipsec_constructor_t constructor)
                    778: {
                    779:        if (constructor == this->ipsec_constructor && this->ipsec)
                    780:        {
                    781:                this->ipsec->destroy(this->ipsec);
                    782:                this->ipsec = NULL;
                    783:                return TRUE;
                    784:        }
                    785:        return FALSE;
                    786: }
                    787: 
                    788: METHOD(kernel_interface_t, add_net_interface, bool,
                    789:        private_kernel_interface_t *this, kernel_net_constructor_t constructor)
                    790: {
                    791:        if (!this->net)
                    792:        {
                    793:                this->net_constructor = constructor;
                    794:                this->net = constructor();
                    795:                return this->net != NULL;
                    796:        }
                    797:        return FALSE;
                    798: }
                    799: 
                    800: METHOD(kernel_interface_t, remove_net_interface, bool,
                    801:        private_kernel_interface_t *this, kernel_net_constructor_t constructor)
                    802: {
                    803:        if (constructor == this->net_constructor && this->net)
                    804:        {
                    805:                this->net->destroy(this->net);
                    806:                this->net = NULL;
                    807:                return TRUE;
                    808:        }
                    809:        return FALSE;
                    810: }
                    811: 
                    812: METHOD(kernel_interface_t, add_listener, void,
                    813:        private_kernel_interface_t *this, kernel_listener_t *listener)
                    814: {
                    815:        this->mutex->lock(this->mutex);
                    816:        this->listeners->insert_last(this->listeners, listener);
                    817:        this->mutex->unlock(this->mutex);
                    818: }
                    819: 
                    820: METHOD(kernel_interface_t, remove_listener, void,
                    821:        private_kernel_interface_t *this, kernel_listener_t *listener)
                    822: {
                    823:        this->mutex->lock(this->mutex);
                    824:        this->listeners->remove(this->listeners, listener, NULL);
                    825:        this->mutex->unlock(this->mutex);
                    826: }
                    827: 
                    828: METHOD(kernel_interface_t, acquire, void,
                    829:        private_kernel_interface_t *this, uint32_t reqid,
                    830:        traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
                    831: {
                    832:        kernel_listener_t *listener;
                    833:        enumerator_t *enumerator;
                    834:        this->mutex->lock(this->mutex);
                    835:        enumerator = this->listeners->create_enumerator(this->listeners);
                    836:        while (enumerator->enumerate(enumerator, &listener))
                    837:        {
                    838:                if (listener->acquire &&
                    839:                        !listener->acquire(listener, reqid, src_ts, dst_ts))
                    840:                {
                    841:                        this->listeners->remove_at(this->listeners, enumerator);
                    842:                }
                    843:        }
                    844:        enumerator->destroy(enumerator);
                    845:        this->mutex->unlock(this->mutex);
                    846: }
                    847: 
                    848: METHOD(kernel_interface_t, expire, void,
                    849:        private_kernel_interface_t *this, uint8_t protocol, uint32_t spi,
                    850:        host_t *dst, bool hard)
                    851: {
                    852:        kernel_listener_t *listener;
                    853:        enumerator_t *enumerator;
                    854: 
                    855:        this->mutex->lock(this->mutex);
                    856:        enumerator = this->listeners->create_enumerator(this->listeners);
                    857:        while (enumerator->enumerate(enumerator, &listener))
                    858:        {
                    859:                if (listener->expire &&
                    860:                        !listener->expire(listener, protocol, spi, dst, hard))
                    861:                {
                    862:                        this->listeners->remove_at(this->listeners, enumerator);
                    863:                }
                    864:        }
                    865:        enumerator->destroy(enumerator);
                    866:        this->mutex->unlock(this->mutex);
                    867: }
                    868: 
                    869: METHOD(kernel_interface_t, mapping, void,
                    870:        private_kernel_interface_t *this, uint8_t protocol, uint32_t spi,
                    871:        host_t *dst, host_t *remote)
                    872: {
                    873:        kernel_listener_t *listener;
                    874:        enumerator_t *enumerator;
                    875: 
                    876:        this->mutex->lock(this->mutex);
                    877:        enumerator = this->listeners->create_enumerator(this->listeners);
                    878:        while (enumerator->enumerate(enumerator, &listener))
                    879:        {
                    880:                if (listener->mapping &&
                    881:                        !listener->mapping(listener, protocol, spi, dst, remote))
                    882:                {
                    883:                        this->listeners->remove_at(this->listeners, enumerator);
                    884:                }
                    885:        }
                    886:        enumerator->destroy(enumerator);
                    887:        this->mutex->unlock(this->mutex);
                    888: }
                    889: 
                    890: METHOD(kernel_interface_t, migrate, void,
                    891:        private_kernel_interface_t *this, uint32_t reqid,
                    892:        traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
                    893:        policy_dir_t direction, host_t *local, host_t *remote)
                    894: {
                    895:        kernel_listener_t *listener;
                    896:        enumerator_t *enumerator;
                    897:        this->mutex->lock(this->mutex);
                    898:        enumerator = this->listeners->create_enumerator(this->listeners);
                    899:        while (enumerator->enumerate(enumerator, &listener))
                    900:        {
                    901:                if (listener->migrate &&
                    902:                        !listener->migrate(listener, reqid, src_ts, dst_ts, direction,
                    903:                                                           local, remote))
                    904:                {
                    905:                        this->listeners->remove_at(this->listeners, enumerator);
                    906:                }
                    907:        }
                    908:        enumerator->destroy(enumerator);
                    909:        this->mutex->unlock(this->mutex);
                    910: }
                    911: 
                    912: static bool call_roam(kernel_listener_t *listener, bool *roam)
                    913: {
                    914:        return listener->roam && !listener->roam(listener, *roam);
                    915: }
                    916: 
                    917: METHOD(kernel_interface_t, roam, void,
                    918:        private_kernel_interface_t *this, bool address)
                    919: {
                    920:        this->mutex->lock(this->mutex);
                    921:        this->listeners->remove(this->listeners, &address, (void*)call_roam);
                    922:        this->mutex->unlock(this->mutex);
                    923: }
                    924: 
                    925: METHOD(kernel_interface_t, tun, void,
                    926:        private_kernel_interface_t *this, tun_device_t *tun, bool created)
                    927: {
                    928:        kernel_listener_t *listener;
                    929:        enumerator_t *enumerator;
                    930:        this->mutex->lock(this->mutex);
                    931:        enumerator = this->listeners->create_enumerator(this->listeners);
                    932:        while (enumerator->enumerate(enumerator, &listener))
                    933:        {
                    934:                if (listener->tun &&
                    935:                        !listener->tun(listener, tun, created))
                    936:                {
                    937:                        this->listeners->remove_at(this->listeners, enumerator);
                    938:                }
                    939:        }
                    940:        enumerator->destroy(enumerator);
                    941:        this->mutex->unlock(this->mutex);
                    942: }
                    943: 
                    944: METHOD(kernel_interface_t, register_algorithm, void,
                    945:        private_kernel_interface_t *this, uint16_t alg_id, transform_type_t type,
                    946:        uint16_t kernel_id, char *kernel_name)
                    947: {
                    948:        kernel_algorithm_t *algorithm;
                    949: 
                    950:        INIT(algorithm,
                    951:                .type = type,
                    952:                .ike = alg_id,
                    953:                .kernel = kernel_id,
                    954:                .name = strdup(kernel_name),
                    955:        );
                    956: 
                    957:        this->mutex_algs->lock(this->mutex_algs);
                    958:        this->algorithms->insert_first(this->algorithms, algorithm);
                    959:        this->mutex_algs->unlock(this->mutex_algs);
                    960: }
                    961: 
                    962: METHOD(kernel_interface_t, lookup_algorithm, bool,
                    963:        private_kernel_interface_t *this, uint16_t alg_id, transform_type_t type,
                    964:        uint16_t *kernel_id, char **kernel_name)
                    965: {
                    966:        kernel_algorithm_t *algorithm;
                    967:        enumerator_t *enumerator;
                    968:        bool found = FALSE;
                    969: 
                    970:        this->mutex_algs->lock(this->mutex_algs);
                    971:        enumerator = this->algorithms->create_enumerator(this->algorithms);
                    972:        while (enumerator->enumerate(enumerator, &algorithm))
                    973:        {
                    974:                if (algorithm->type == type && algorithm->ike == alg_id)
                    975:                {
                    976:                        if (kernel_id)
                    977:                        {
                    978:                                *kernel_id = algorithm->kernel;
                    979:                        }
                    980:                        if (kernel_name)
                    981:                        {
                    982:                                *kernel_name = algorithm->name;
                    983:                        }
                    984:                        found = TRUE;
                    985:                        break;
                    986:                }
                    987:        }
                    988:        enumerator->destroy(enumerator);
                    989:        this->mutex_algs->unlock(this->mutex_algs);
                    990:        return found;
                    991: }
                    992: 
                    993: METHOD(kernel_interface_t, destroy, void,
                    994:        private_kernel_interface_t *this)
                    995: {
                    996:        kernel_algorithm_t *algorithm;
                    997: 
                    998:        while (this->algorithms->remove_first(this->algorithms,
                    999:                                                                                 (void**)&algorithm) == SUCCESS)
                   1000:        {
                   1001:                free(algorithm->name);
                   1002:                free(algorithm);
                   1003:        }
                   1004:        this->algorithms->destroy(this->algorithms);
                   1005:        this->mutex_algs->destroy(this->mutex_algs);
                   1006:        DESTROY_IF(this->ipsec);
                   1007:        DESTROY_IF(this->net);
                   1008:        DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
                   1009:        this->reqids->destroy(this->reqids);
                   1010:        this->reqids_by_ts->destroy(this->reqids_by_ts);
                   1011:        array_destroy(this->released_reqids);
                   1012:        this->listeners->destroy(this->listeners);
                   1013:        this->mutex->destroy(this->mutex);
                   1014:        free(this);
                   1015: }
                   1016: 
                   1017: /*
                   1018:  * Described in header-file
                   1019:  */
                   1020: kernel_interface_t *kernel_interface_create()
                   1021: {
                   1022:        private_kernel_interface_t *this;
                   1023:        char *ifaces;
                   1024: 
                   1025:        INIT(this,
                   1026:                .public = {
                   1027:                        .get_features = _get_features,
                   1028:                        .get_spi = _get_spi,
                   1029:                        .get_cpi = _get_cpi,
                   1030:                        .alloc_reqid = _alloc_reqid,
                   1031:                        .release_reqid = _release_reqid,
                   1032:                        .add_sa = _add_sa,
                   1033:                        .update_sa = _update_sa,
                   1034:                        .query_sa = _query_sa,
                   1035:                        .del_sa = _del_sa,
                   1036:                        .flush_sas = _flush_sas,
                   1037:                        .add_policy = _add_policy,
                   1038:                        .query_policy = _query_policy,
                   1039:                        .del_policy = _del_policy,
                   1040:                        .flush_policies = _flush_policies,
                   1041:                        .get_source_addr = _get_source_addr,
                   1042:                        .get_nexthop = _get_nexthop,
                   1043:                        .get_interface = _get_interface,
                   1044:                        .create_address_enumerator = _create_address_enumerator,
                   1045:                        .create_local_subnet_enumerator = _create_local_subnet_enumerator,
                   1046:                        .add_ip = _add_ip,
                   1047:                        .del_ip = _del_ip,
                   1048:                        .add_route = _add_route,
                   1049:                        .del_route = _del_route,
                   1050:                        .bypass_socket = _bypass_socket,
                   1051:                        .enable_udp_decap = _enable_udp_decap,
                   1052: 
                   1053:                        .is_interface_usable = _is_interface_usable,
                   1054:                        .all_interfaces_usable = _all_interfaces_usable,
                   1055:                        .get_address_by_ts = _get_address_by_ts,
                   1056:                        .add_ipsec_interface = _add_ipsec_interface,
                   1057:                        .remove_ipsec_interface = _remove_ipsec_interface,
                   1058:                        .add_net_interface = _add_net_interface,
                   1059:                        .remove_net_interface = _remove_net_interface,
                   1060: 
                   1061:                        .add_listener = _add_listener,
                   1062:                        .remove_listener = _remove_listener,
                   1063:                        .register_algorithm = _register_algorithm,
                   1064:                        .lookup_algorithm = _lookup_algorithm,
                   1065:                        .acquire = _acquire,
                   1066:                        .expire = _expire,
                   1067:                        .mapping = _mapping,
                   1068:                        .migrate = _migrate,
                   1069:                        .roam = _roam,
                   1070:                        .tun = _tun,
                   1071:                        .destroy = _destroy,
                   1072:                },
                   1073:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                   1074:                .listeners = linked_list_create(),
                   1075:                .mutex_algs = mutex_create(MUTEX_TYPE_DEFAULT),
                   1076:                .algorithms = linked_list_create(),
                   1077:                .reqids = hashtable_create((hashtable_hash_t)hash_reqid,
                   1078:                                                                   (hashtable_equals_t)equals_reqid, 8),
                   1079:                .reqids_by_ts = hashtable_create((hashtable_hash_t)hash_reqid_by_ts,
                   1080:                                                                   (hashtable_equals_t)equals_reqid_by_ts, 8),
                   1081:        );
                   1082: 
                   1083:        ifaces = lib->settings->get_str(lib->settings,
                   1084:                                                                        "%s.interfaces_use", NULL, lib->ns);
                   1085:        if (!ifaces)
                   1086:        {
                   1087:                this->ifaces_exclude = TRUE;
                   1088:                ifaces = lib->settings->get_str(lib->settings,
                   1089:                                                                        "%s.interfaces_ignore", NULL, lib->ns);
                   1090:        }
                   1091:        if (ifaces)
                   1092:        {
                   1093:                enumerator_t *enumerator;
                   1094:                char *iface;
                   1095: 
                   1096:                enumerator = enumerator_create_token(ifaces, ",", " ");
                   1097:                while (enumerator->enumerate(enumerator, &iface))
                   1098:                {
                   1099:                        if (!this->ifaces_filter)
                   1100:                        {
                   1101:                                this->ifaces_filter = linked_list_create();
                   1102:                        }
                   1103:                        this->ifaces_filter->insert_last(this->ifaces_filter,
                   1104:                                                                                         strdup(iface));
                   1105:                }
                   1106:                enumerator->destroy(enumerator);
                   1107:        }
                   1108: 
                   1109:        return &this->public;
                   1110: }

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