Annotation of embedaddon/strongswan/src/libcharon/plugins/attr/attr_provider.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Tobias Brunner
                      3:  * Copyright (C) 2009 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "attr_provider.h"
                     18: 
                     19: #include <time.h>
                     20: 
                     21: #include <daemon.h>
                     22: #include <utils/debug.h>
                     23: #include <collections/linked_list.h>
                     24: #include <threading/rwlock.h>
                     25: 
                     26: #define SERVER_MAX             2
                     27: 
                     28: typedef struct private_attr_provider_t private_attr_provider_t;
                     29: typedef struct attribute_entry_t attribute_entry_t;
                     30: 
                     31: /**
                     32:  * private data of attr_provider
                     33:  */
                     34: struct private_attr_provider_t {
                     35: 
                     36:        /**
                     37:         * public functions
                     38:         */
                     39:        attr_provider_t public;
                     40: 
                     41:        /**
                     42:         * List of attributes, attribute_entry_t
                     43:         */
                     44:        linked_list_t *attributes;
                     45: 
                     46:        /**
                     47:         * Lock for attribute list
                     48:         */
                     49:        rwlock_t *lock;
                     50: };
                     51: 
                     52: struct attribute_entry_t {
                     53:        /** type of attribute */
                     54:        configuration_attribute_type_t type;
                     55:        /** attribute value */
                     56:        chunk_t value;
                     57:        /** associated IKE version */
                     58:        ike_version_t ike;
                     59: };
                     60: 
                     61: /**
                     62:  * Destroy an entry
                     63:  */
                     64: static void attribute_destroy(attribute_entry_t *this)
                     65: {
                     66:        free(this->value.ptr);
                     67:        free(this);
                     68: }
                     69: 
                     70: /**
                     71:  * Data for attribute enumerator
                     72:  */
                     73: typedef struct {
                     74:        rwlock_t *lock;
                     75:        ike_version_t ike;
                     76: } enumerator_data_t;
                     77: 
                     78: CALLBACK(attr_enum_filter, bool,
                     79:        enumerator_data_t *data, enumerator_t *orig, va_list args)
                     80: {
                     81:        configuration_attribute_type_t *type;
                     82:        attribute_entry_t *entry;
                     83:        chunk_t *value;
                     84: 
                     85:        VA_ARGS_VGET(args, type, value);
                     86: 
                     87:        while (orig->enumerate(orig, &entry))
                     88:        {
                     89:                if (entry->ike == IKE_ANY || entry->ike == data->ike)
                     90:                {
                     91:                        *type = entry->type;
                     92:                        *value = entry->value;
                     93:                        return TRUE;
                     94:                }
                     95:        }
                     96:        return FALSE;
                     97: }
                     98: 
                     99: CALLBACK(attr_enum_destroy, void,
                    100:        enumerator_data_t *data)
                    101: {
                    102:        data->lock->unlock(data->lock);
                    103:        free(data);
                    104: }
                    105: 
                    106: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
                    107:        private_attr_provider_t *this, linked_list_t *pools,
                    108:        ike_sa_t *ike_sa, linked_list_t *vips)
                    109: {
                    110:        enumerator_data_t *data;
                    111: 
                    112:        if (vips->get_count(vips))
                    113:        {
                    114:                INIT(data,
                    115:                        .lock = this->lock,
                    116:                        .ike = ike_sa->get_version(ike_sa),
                    117:                );
                    118:                this->lock->read_lock(this->lock);
                    119:                return enumerator_create_filter(
                    120:                                this->attributes->create_enumerator(this->attributes),
                    121:                                attr_enum_filter, data, attr_enum_destroy);
                    122:        }
                    123:        return enumerator_create_empty();
                    124: }
                    125: 
                    126: METHOD(attr_provider_t, destroy, void,
                    127:        private_attr_provider_t *this)
                    128: {
                    129:        this->attributes->destroy_function(this->attributes,
                    130:                                                                           (void*)attribute_destroy);
                    131:        this->lock->destroy(this->lock);
                    132:        free(this);
                    133: }
                    134: 
                    135: /**
                    136:  * Add an attribute entry to the list
                    137:  */
                    138: static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
                    139:                                                         configuration_attribute_type_t type)
                    140: {
                    141:        attribute_entry_t *entry;
                    142:        host_t *host;
                    143:        char *str;
                    144: 
                    145:        str = lib->settings->get_str(lib->settings, "%s.%s%d", NULL, lib->ns,
                    146:                                                                 key, nr);
                    147:        if (str)
                    148:        {
                    149:                host = host_create_from_string(str, 0);
                    150:                if (host)
                    151:                {
                    152:                        if (host->get_family(host) == AF_INET6)
                    153:                        {
                    154:                                switch (type)
                    155:                                {
                    156:                                        case INTERNAL_IP4_DNS:
                    157:                                                type = INTERNAL_IP6_DNS;
                    158:                                                break;
                    159:                                        case INTERNAL_IP4_NBNS:
                    160:                                                type = INTERNAL_IP6_NBNS;
                    161:                                                break;
                    162:                                        default:
                    163:                                                break;
                    164:                                }
                    165:                        }
                    166:                        INIT(entry,
                    167:                                .type = type,
                    168:                                .value = chunk_clone(host->get_address(host)),
                    169:                                .ike = IKE_ANY,
                    170:                        );
                    171:                        host->destroy(host);
                    172:                        DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B",
                    173:                                 configuration_attribute_type_names, entry->type, &entry->value);
                    174:                        this->attributes->insert_last(this->attributes, entry);
                    175:                }
                    176:        }
                    177: }
                    178: 
                    179: /**
                    180:  * Key to attribute type mappings, for v4 and v6 attributes
                    181:  */
                    182: typedef struct {
                    183:        char *name;
                    184:        configuration_attribute_type_t v4;
                    185:        configuration_attribute_type_t v6;
                    186:        ike_version_t ike;
                    187: } attribute_type_key_t;
                    188: 
                    189: static attribute_type_key_t keys[] = {
                    190:        {"address",                     INTERNAL_IP4_ADDRESS,   INTERNAL_IP6_ADDRESS,   IKE_ANY},
                    191:        {"dns",                         INTERNAL_IP4_DNS,               INTERNAL_IP6_DNS,               IKE_ANY},
                    192:        {"nbns",                        INTERNAL_IP4_NBNS,              INTERNAL_IP6_NBNS,              IKE_ANY},
                    193:        {"dhcp",                        INTERNAL_IP4_DHCP,              INTERNAL_IP6_DHCP,              IKE_ANY},
                    194:        {"netmask",                     INTERNAL_IP4_NETMASK,   INTERNAL_IP6_NETMASK,   IKE_ANY},
                    195:        {"server",                      INTERNAL_IP4_SERVER,    INTERNAL_IP6_SERVER,    IKE_ANY},
                    196:        {"subnet",                      INTERNAL_IP4_SUBNET,    INTERNAL_IP6_SUBNET,    IKE_ANY},
                    197:        {"p-cscf",                      P_CSCF_IP4_ADDRESS,             P_CSCF_IP6_ADDRESS,             IKEV2},
                    198:        {"split-include",       UNITY_SPLIT_INCLUDE,    UNITY_SPLIT_INCLUDE,    IKEV1},
                    199:        {"split-exclude",       UNITY_LOCAL_LAN,                UNITY_LOCAL_LAN,                IKEV1},
                    200: };
                    201: 
                    202: /**
                    203:  * Load (numerical) entries from the plugins.attr namespace
                    204:  */
                    205: static void load_entries(private_attr_provider_t *this)
                    206: {
                    207:        enumerator_t *enumerator, *tokens;
                    208:        char *key, *value, *token;
                    209:        int i;
                    210: 
                    211:        for (i = 1; i <= SERVER_MAX; i++)
                    212:        {
                    213:                add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS);
                    214:                add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS);
                    215:        }
                    216: 
                    217:        enumerator = lib->settings->create_key_value_enumerator(lib->settings,
                    218:                                                                                                        "%s.plugins.attr", lib->ns);
                    219:        while (enumerator->enumerate(enumerator, &key, &value))
                    220:        {
                    221:                configuration_attribute_type_t type;
                    222:                attribute_type_key_t *mapped = NULL;
                    223:                attribute_entry_t *entry;
                    224:                chunk_t data;
                    225:                host_t *host;
                    226:                char *pos;
                    227:                int i, mask = -1, family;
                    228: 
                    229:                if (streq(key, "load"))
                    230:                {
                    231:                        continue;
                    232:                }
                    233:                type = atoi(key);
                    234:                if (!type)
                    235:                {
                    236:                        for (i = 0; i < countof(keys); i++)
                    237:                        {
                    238:                                if (streq(key, keys[i].name))
                    239:                                {
                    240:                                        mapped = &keys[i];
                    241:                                        break;
                    242:                                }
                    243:                        }
                    244:                        if (!mapped)
                    245:                        {
                    246:                                DBG1(DBG_CFG, "mapping attribute type %s failed", key);
                    247:                                continue;
                    248:                        }
                    249:                }
                    250:                tokens = enumerator_create_token(value, ",", " ");
                    251:                while (tokens->enumerate(tokens, &token))
                    252:                {
                    253:                        pos = strchr(token, '/');
                    254:                        if (pos)
                    255:                        {
                    256:                                *(pos++) = '\0';
                    257:                                mask = atoi(pos);
                    258:                        }
                    259:                        host = host_create_from_string(token, 0);
                    260:                        if (!host)
                    261:                        {
                    262:                                if (mapped)
                    263:                                {
                    264:                                        DBG1(DBG_CFG, "invalid host in key %s: %s", key, token);
                    265:                                        continue;
                    266:                                }
                    267:                                /* store numeric attributes that are no IP addresses as strings */
                    268:                                data = chunk_clone(chunk_from_str(token));
                    269:                        }
                    270:                        else
                    271:                        {
                    272:                                family = host->get_family(host);
                    273:                                if (mask == -1)
                    274:                                {
                    275:                                        data = chunk_clone(host->get_address(host));
                    276:                                }
                    277:                                else
                    278:                                {
                    279:                                        if (family == AF_INET)
                    280:                                        {       /* IPv4 attributes contain a subnet mask */
                    281:                                                uint32_t netmask = 0;
                    282: 
                    283:                                                if (mask)
                    284:                                                {       /* shifting uint32_t by 32 or more is undefined */
                    285:                                                        mask = 32 - mask;
                    286:                                                        netmask = htonl((0xFFFFFFFF >> mask) << mask);
                    287:                                                }
                    288:                                                data = chunk_cat("cc", host->get_address(host),
                    289:                                                                                 chunk_from_thing(netmask));
                    290:                                        }
                    291:                                        else
                    292:                                        {       /* IPv6 addresses the prefix only */
                    293:                                                data = chunk_cat("cc", host->get_address(host),
                    294:                                                                                 chunk_from_chars(mask));
                    295:                                        }
                    296:                                }
                    297:                                host->destroy(host);
                    298:                                if (mapped)
                    299:                                {
                    300:                                        switch (family)
                    301:                                        {
                    302:                                                case AF_INET:
                    303:                                                        type = mapped->v4;
                    304:                                                        break;
                    305:                                                case AF_INET6:
                    306:                                                        type = mapped->v6;
                    307:                                                        break;
                    308:                                        }
                    309:                                }
                    310:                        }
                    311:                        INIT(entry,
                    312:                                .type = type,
                    313:                                .value = data,
                    314:                                .ike = mapped ? mapped->ike : IKE_ANY,
                    315:                        );
                    316:                        DBG2(DBG_CFG, "loaded attribute %N: %#B",
                    317:                                 configuration_attribute_type_names, entry->type, &entry->value);
                    318:                        this->attributes->insert_last(this->attributes, entry);
                    319:                }
                    320:                tokens->destroy(tokens);
                    321:        }
                    322:        enumerator->destroy(enumerator);
                    323: }
                    324: 
                    325: METHOD(attr_provider_t, reload, void,
                    326:        private_attr_provider_t *this)
                    327: {
                    328:        this->lock->write_lock(this->lock);
                    329: 
                    330:        this->attributes->destroy_function(this->attributes, (void*)attribute_destroy);
                    331:        this->attributes = linked_list_create();
                    332: 
                    333:        load_entries(this);
                    334: 
                    335:        DBG1(DBG_CFG, "loaded %d entr%s for attr plugin configuration",
                    336:                 this->attributes->get_count(this->attributes),
                    337:                 this->attributes->get_count(this->attributes) == 1 ? "y" : "ies");
                    338: 
                    339:        this->lock->unlock(this->lock);
                    340: }
                    341: 
                    342: /*
                    343:  * see header file
                    344:  */
                    345: attr_provider_t *attr_provider_create()
                    346: {
                    347:        private_attr_provider_t *this;
                    348: 
                    349:        INIT(this,
                    350:                .public = {
                    351:                        .provider = {
                    352:                                .acquire_address = (void*)return_null,
                    353:                                .release_address = (void*)return_false,
                    354:                                .create_attribute_enumerator = _create_attribute_enumerator,
                    355:                        },
                    356:                        .reload = _reload,
                    357:                        .destroy = _destroy,
                    358:                },
                    359:                .attributes = linked_list_create(),
                    360:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    361:        );
                    362: 
                    363:        load_entries(this);
                    364: 
                    365:        return &this->public;
                    366: }

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