Annotation of embedaddon/strongswan/src/libcharon/plugins/unity/unity_provider.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2012 Martin Willi
                      6:  * Copyright (C) 2012 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: #include "unity_provider.h"
                     20: 
                     21: #include <daemon.h>
                     22: #include <bio/bio_writer.h>
                     23: 
                     24: typedef struct private_unity_provider_t private_unity_provider_t;
                     25: 
                     26: /**
                     27:  * Private data of an unity_provider_t object.
                     28:  */
                     29: struct private_unity_provider_t {
                     30: 
                     31:        /**
                     32:         * Public unity_provider_t interface.
                     33:         */
                     34:        unity_provider_t public;
                     35: };
                     36: 
                     37: /**
                     38:  * Attribute enumerator for UNITY_SPLIT_INCLUDE attribute
                     39:  */
                     40: typedef struct {
                     41:        /** Implements enumerator_t */
                     42:        enumerator_t public;
                     43:        /** list of traffic selectors to enumerate */
                     44:        linked_list_t *list;
                     45:        /** attribute value */
                     46:        chunk_t attr;
                     47: } attribute_enumerator_t;
                     48: 
                     49: /**
                     50:  * Append data from the given traffic selector to the attribute data
                     51:  */
                     52: static void append_ts(bio_writer_t *writer, traffic_selector_t *ts)
                     53: {
                     54:        host_t *net, *mask;
                     55:        chunk_t padding;
                     56:        uint8_t bits;
                     57: 
                     58:        if (!ts->to_subnet(ts, &net, &bits))
                     59:        {
                     60:                return;
                     61:        }
                     62:        mask = host_create_netmask(AF_INET, bits);
                     63:        if (!mask)
                     64:        {
                     65:                net->destroy(net);
                     66:                return;
                     67:        }
                     68:        writer->write_data(writer, net->get_address(net));
                     69:        writer->write_data(writer, mask->get_address(mask));
                     70:        /* the Cisco client parses the "padding" as protocol, src and dst port, the
                     71:         * first two in network order the last in host order - no other clients seem
                     72:         * to support these fields so we don't use them either */
                     73:        padding = writer->skip(writer, 6);
                     74:        memset(padding.ptr, 0, padding.len);
                     75:        mask->destroy(mask);
                     76:        net->destroy(net);
                     77: }
                     78: 
                     79: METHOD(enumerator_t, attribute_enumerate, bool,
                     80:        attribute_enumerator_t *this, va_list args)
                     81: {
                     82:        configuration_attribute_type_t *type;
                     83:        chunk_t *attr;
                     84:        traffic_selector_t *ts;
                     85:        bio_writer_t *writer;
                     86: 
                     87:        VA_ARGS_VGET(args, type, attr);
                     88: 
                     89:        if (this->list->get_count(this->list) == 0)
                     90:        {
                     91:                return FALSE;
                     92:        }
                     93: 
                     94:        writer = bio_writer_create(14);
                     95:        while (this->list->remove_first(this->list, (void**)&ts) == SUCCESS)
                     96:        {
                     97:                append_ts(writer, ts);
                     98:                ts->destroy(ts);
                     99:        }
                    100: 
                    101:        *type = UNITY_SPLIT_INCLUDE;
                    102:        *attr = this->attr = writer->extract_buf(writer);
                    103: 
                    104:        writer->destroy(writer);
                    105:        return TRUE;
                    106: }
                    107: 
                    108: METHOD(enumerator_t, attribute_destroy, void,
                    109:        attribute_enumerator_t *this)
                    110: {
                    111:        this->list->destroy_offset(this->list, offsetof(traffic_selector_t, destroy));
                    112:        chunk_free(&this->attr);
                    113:        free(this);
                    114: }
                    115: 
                    116: /**
                    117:  * Check if we should send a configured TS as Split-Include attribute
                    118:  */
                    119: static bool use_ts(traffic_selector_t *ts)
                    120: {
                    121:        uint8_t mask;
                    122:        host_t *net;
                    123: 
                    124:        if (ts->get_type(ts) != TS_IPV4_ADDR_RANGE)
                    125:        {
                    126:                return FALSE;
                    127:        }
                    128:        if (ts->is_dynamic(ts))
                    129:        {
                    130:                return FALSE;
                    131:        }
                    132:        if (!ts->to_subnet(ts, &net, &mask))
                    133:        {
                    134:                return FALSE;
                    135:        }
                    136:        net->destroy(net);
                    137:        return mask > 0;
                    138: }
                    139: 
                    140: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
                    141:        private_unity_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa,
                    142:        linked_list_t *vips)
                    143: {
                    144:        attribute_enumerator_t *attr_enum;
                    145:        enumerator_t *enumerator;
                    146:        linked_list_t *list, *current;
                    147:        traffic_selector_t *ts;
                    148:        peer_cfg_t *peer_cfg;
                    149:        child_cfg_t *child_cfg;
                    150: 
                    151:        if (ike_sa->get_version(ike_sa) != IKEV1 ||
                    152:                !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY) ||
                    153:                !vips->get_count(vips))
                    154:        {
                    155:                return NULL;
                    156:        }
                    157: 
                    158:        list = linked_list_create();
                    159:        peer_cfg = ike_sa->get_peer_cfg(ike_sa);
                    160:        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                    161:        while (enumerator->enumerate(enumerator, &child_cfg))
                    162:        {
                    163:                current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL,
                    164:                                                                                                   FALSE);
                    165:                while (current->remove_first(current, (void**)&ts) == SUCCESS)
                    166:                {
                    167:                        if (use_ts(ts))
                    168:                        {
                    169:                                list->insert_last(list, ts);
                    170:                        }
                    171:                        else
                    172:                        {
                    173:                                ts->destroy(ts);
                    174:                        }
                    175:                }
                    176:                current->destroy(current);
                    177:        }
                    178:        enumerator->destroy(enumerator);
                    179: 
                    180:        if (list->get_count(list) == 0)
                    181:        {
                    182:                list->destroy(list);
                    183:                return NULL;
                    184:        }
                    185:        DBG1(DBG_CFG, "sending %N: %#R",
                    186:                 configuration_attribute_type_names, UNITY_SPLIT_INCLUDE, list);
                    187: 
                    188:        INIT(attr_enum,
                    189:                .public = {
                    190:                        .enumerate = enumerator_enumerate_default,
                    191:                        .venumerate = _attribute_enumerate,
                    192:                        .destroy = _attribute_destroy,
                    193:                },
                    194:                .list = list,
                    195:        );
                    196: 
                    197:        return &attr_enum->public;
                    198: }
                    199: 
                    200: METHOD(unity_provider_t, destroy, void,
                    201:        private_unity_provider_t *this)
                    202: {
                    203:        free(this);
                    204: }
                    205: 
                    206: /**
                    207:  * See header
                    208:  */
                    209: unity_provider_t *unity_provider_create()
                    210: {
                    211:        private_unity_provider_t *this;
                    212: 
                    213:        INIT(this,
                    214:                .public = {
                    215:                        .provider = {
                    216:                                .acquire_address = (void*)return_null,
                    217:                                .release_address = (void*)return_false,
                    218:                                .create_attribute_enumerator = _create_attribute_enumerator,
                    219:                        },
                    220:                        .destroy = _destroy,
                    221:                },
                    222:        );
                    223: 
                    224:        return &this->public;
                    225: }

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