Annotation of embedaddon/strongswan/src/libcharon/plugins/dhcp/dhcp_provider.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "dhcp_provider.h"
                     17: 
                     18: #include <collections/hashtable.h>
                     19: #include <threading/mutex.h>
                     20: 
                     21: typedef struct private_dhcp_provider_t private_dhcp_provider_t;
                     22: 
                     23: /**
                     24:  * Private data of an dhcp_provider_t object.
                     25:  */
                     26: struct private_dhcp_provider_t {
                     27: 
                     28:        /**
                     29:         * Public dhcp_provider_t interface.
                     30:         */
                     31:        dhcp_provider_t public;
                     32: 
                     33:        /**
                     34:         * Completed DHCP transactions
                     35:         */
                     36:        hashtable_t *transactions;
                     37: 
                     38:        /**
                     39:         * Lock for transactions
                     40:         */
                     41:        mutex_t *mutex;
                     42: 
                     43:        /**
                     44:         * DHCP communication socket
                     45:         */
                     46:        dhcp_socket_t *socket;
                     47: };
                     48: 
                     49: /**
                     50:  * Hash ID and host to a key
                     51:  */
                     52: static uintptr_t hash_id_host(identification_t *id, host_t *host)
                     53: {
                     54:        return chunk_hash_inc(id->get_encoding(id),
                     55:                                                  chunk_hash(host->get_address(host)));
                     56: }
                     57: 
                     58: /**
                     59:  * Hash a DHCP transaction to a key, using address and id
                     60:  */
                     61: static uintptr_t hash_transaction(dhcp_transaction_t *transaction)
                     62: {
                     63:        return hash_id_host(transaction->get_identity(transaction),
                     64:                                                transaction->get_address(transaction));
                     65: }
                     66: 
                     67: METHOD(attribute_provider_t, acquire_address, host_t*,
                     68:        private_dhcp_provider_t *this, linked_list_t *pools,
                     69:        ike_sa_t *ike_sa, host_t *requested)
                     70: {
                     71:        dhcp_transaction_t *transaction, *old;
                     72:        enumerator_t *enumerator;
                     73:        identification_t *id;
                     74:        char *pool;
                     75:        host_t *vip = NULL;
                     76: 
                     77:        if (requested->get_family(requested) != AF_INET)
                     78:        {
                     79:                return NULL;
                     80:        }
                     81:        id = ike_sa->get_other_eap_id(ike_sa);
                     82:        enumerator = pools->create_enumerator(pools);
                     83:        while (enumerator->enumerate(enumerator, &pool))
                     84:        {
                     85:                if (!streq(pool, "dhcp"))
                     86:                {
                     87:                        continue;
                     88:                }
                     89:                transaction = this->socket->enroll(this->socket, id);
                     90:                if (!transaction)
                     91:                {
                     92:                        continue;
                     93:                }
                     94:                vip = transaction->get_address(transaction);
                     95:                vip = vip->clone(vip);
                     96:                this->mutex->lock(this->mutex);
                     97:                old = this->transactions->put(this->transactions,
                     98:                                                        (void*)hash_transaction(transaction), transaction);
                     99:                this->mutex->unlock(this->mutex);
                    100:                DESTROY_IF(old);
                    101:                break;
                    102:        }
                    103:        enumerator->destroy(enumerator);
                    104:        return vip;
                    105: }
                    106: 
                    107: METHOD(attribute_provider_t, release_address, bool,
                    108:        private_dhcp_provider_t *this, linked_list_t *pools,
                    109:        host_t *address, ike_sa_t *ike_sa)
                    110: {
                    111:        dhcp_transaction_t *transaction;
                    112:        enumerator_t *enumerator;
                    113:        identification_t *id;
                    114:        bool found = FALSE;
                    115:        char *pool;
                    116: 
                    117:        if (address->get_family(address) != AF_INET)
                    118:        {
                    119:                return FALSE;
                    120:        }
                    121:        id = ike_sa->get_other_eap_id(ike_sa);
                    122:        enumerator = pools->create_enumerator(pools);
                    123:        while (enumerator->enumerate(enumerator, &pool))
                    124:        {
                    125:                if (!streq(pool, "dhcp"))
                    126:                {
                    127:                        continue;
                    128:                }
                    129:                this->mutex->lock(this->mutex);
                    130:                transaction = this->transactions->remove(this->transactions,
                    131:                                                                                (void*)hash_id_host(id, address));
                    132:                this->mutex->unlock(this->mutex);
                    133:                if (transaction)
                    134:                {
                    135:                        this->socket->release(this->socket, transaction);
                    136:                        transaction->destroy(transaction);
                    137:                        found = TRUE;
                    138:                        break;
                    139:                }
                    140:        }
                    141:        enumerator->destroy(enumerator);
                    142:        return found;
                    143: }
                    144: 
                    145: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
                    146:        private_dhcp_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa,
                    147:        linked_list_t *vips)
                    148: {
                    149:        dhcp_transaction_t *transaction = NULL;
                    150:        enumerator_t *enumerator;
                    151:        identification_t *id;
                    152:        host_t *vip;
                    153: 
                    154:        if (!pools->find_first(pools, linked_list_match_str, NULL, "dhcp"))
                    155:        {
                    156:                return NULL;
                    157:        }
                    158: 
                    159:        id = ike_sa->get_other_eap_id(ike_sa);
                    160:        this->mutex->lock(this->mutex);
                    161:        enumerator = vips->create_enumerator(vips);
                    162:        while (enumerator->enumerate(enumerator, &vip))
                    163:        {
                    164:                transaction = this->transactions->get(this->transactions,
                    165:                                                                                          (void*)hash_id_host(id, vip));
                    166:                if (transaction)
                    167:                {
                    168:                        break;
                    169:                }
                    170:        }
                    171:        enumerator->destroy(enumerator);
                    172:        if (!transaction)
                    173:        {
                    174:                this->mutex->unlock(this->mutex);
                    175:                return NULL;
                    176:        }
                    177:        return enumerator_create_cleaner(
                    178:                                                transaction->create_attribute_enumerator(transaction),
                    179:                                                (void*)this->mutex->unlock, this->mutex);
                    180: }
                    181: 
                    182: METHOD(dhcp_provider_t, destroy, void,
                    183:        private_dhcp_provider_t *this)
                    184: {
                    185:        enumerator_t *enumerator;
                    186:        dhcp_transaction_t *value;
                    187:        void *key;
                    188: 
                    189:        enumerator = this->transactions->create_enumerator(this->transactions);
                    190:        while (enumerator->enumerate(enumerator, &key, &value))
                    191:        {
                    192:                value->destroy(value);
                    193:        }
                    194:        enumerator->destroy(enumerator);
                    195:        this->transactions->destroy(this->transactions);
                    196:        this->mutex->destroy(this->mutex);
                    197:        free(this);
                    198: }
                    199: 
                    200: /**
                    201:  * See header
                    202:  */
                    203: dhcp_provider_t *dhcp_provider_create(dhcp_socket_t *socket)
                    204: {
                    205:        private_dhcp_provider_t *this;
                    206: 
                    207:        INIT(this,
                    208:                .public = {
                    209:                        .provider = {
                    210:                                .acquire_address = _acquire_address,
                    211:                                .release_address = _release_address,
                    212:                                .create_attribute_enumerator = _create_attribute_enumerator,
                    213:                        },
                    214:                        .destroy = _destroy,
                    215:                },
                    216:                .socket = socket,
                    217:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    218:                .transactions = hashtable_create(hashtable_hash_ptr,
                    219:                                                                                 hashtable_equals_ptr, 8),
                    220:        );
                    221: 
                    222:        return &this->public;
                    223: }

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