Annotation of embedaddon/strongswan/src/libcharon/plugins/attr/attr_provider.c, revision 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>