Annotation of embedaddon/strongswan/src/libcharon/plugins/load_tester/load_tester_config.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Copyright (C) 2008 Martin Willi
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      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 "load_tester_config.h"
                     17: 
                     18: #include <netdb.h>
                     19: 
                     20: #include <daemon.h>
                     21: #include <attributes/mem_pool.h>
                     22: #include <collections/hashtable.h>
                     23: #include <threading/mutex.h>
                     24: 
                     25: #define UNIQUE_PORT_START 1025
                     26: 
                     27: typedef struct private_load_tester_config_t private_load_tester_config_t;
                     28: 
                     29: /**
                     30:  * Private data of an load_tester_config_t object
                     31:  */
                     32: struct private_load_tester_config_t {
                     33: 
                     34:        /**
                     35:         * Public part
                     36:         */
                     37:        load_tester_config_t public;
                     38: 
                     39:        /**
                     40:         * peer config
                     41:         */
                     42:        peer_cfg_t *peer_cfg;
                     43: 
                     44:        /**
1.1.1.2 ! misho      45:         * request virtual IPs
1.1       misho      46:         */
1.1.1.2 ! misho      47:        bool vips;
1.1       misho      48: 
                     49:        /**
                     50:         * Initiator address
                     51:         */
                     52:        char *initiator;
                     53: 
                     54:        /**
                     55:         * Responder address
                     56:         */
                     57:        char *responder;
                     58: 
                     59:        /**
                     60:         * IP address pool
                     61:         */
                     62:        char *pool;
                     63: 
                     64:        /**
                     65:         * IKE proposal
                     66:         */
                     67:        proposal_t *proposal;
                     68: 
                     69:        /**
                     70:         * ESP proposal
                     71:         */
                     72:        proposal_t *esp;
                     73: 
                     74:        /**
                     75:         * Authentication method(s) to use/expect from initiator
                     76:         */
                     77:        char *initiator_auth;
                     78: 
                     79:        /**
                     80:         * Authentication method(s) use/expected from responder
                     81:         */
                     82:        char *responder_auth;
                     83: 
                     84:        /**
                     85:         * Initiator ID to enforce
                     86:         */
                     87:        char *initiator_id;
                     88: 
                     89:        /**
                     90:         * Initiator ID to to match against as responder
                     91:         */
                     92:        char *initiator_match;
                     93: 
                     94:        /**
                     95:         * Responder ID to enforce
                     96:         */
                     97:        char *responder_id;
                     98: 
                     99:        /**
                    100:         * IPsec mode, tunnel|transport|beet
                    101:         */
                    102:        char *mode;
                    103: 
                    104:        /**
                    105:         * Traffic Selector on initiator side, as proposed from initiator
                    106:         */
                    107:        char *initiator_tsi;
                    108: 
                    109:        /**
                    110:         * Traffic Selector on responder side, as proposed from initiator
                    111:         */
                    112:        char *initiator_tsr;
                    113: 
                    114:        /**
                    115:         * Traffic Selector on initiator side, as narrowed by responder
                    116:         */
                    117:        char *responder_tsi;
                    118: 
                    119:        /**
                    120:         * Traffic Selector on responder side, as narrowed by responder
                    121:         */
                    122:        char *responder_tsr;
                    123: 
                    124:        /**
                    125:         * Current port for unique initiator ports
                    126:         */
                    127:        uint16_t unique_port;
                    128: 
                    129:        /**
                    130:         * IKE_SA rekeying delay
                    131:         */
                    132:        u_int ike_rekey;
                    133: 
                    134:        /**
                    135:         * CHILD_SA rekeying delay
                    136:         */
                    137:        u_int child_rekey;
                    138: 
                    139:        /**
                    140:         * DPD check delay
                    141:         */
                    142:        u_int dpd_delay;
                    143: 
                    144:        /**
                    145:         * DPD timeout (IKEv1 only)
                    146:         */
                    147:        u_int dpd_timeout;
                    148: 
                    149:        /**
                    150:         * incremental numbering of generated configs
                    151:         */
                    152:        refcount_t num;
                    153: 
                    154:        /**
                    155:         * Dynamic source port, if used
                    156:         */
                    157:        uint16_t port;
                    158: 
                    159:        /**
                    160:         * IKE version to use for load testing
                    161:         */
                    162:        ike_version_t version;
                    163: 
                    164:        /**
                    165:         * List of pools to allocate external addresses dynamically, as mem_pool_t
                    166:         */
                    167:        linked_list_t *pools;
                    168: 
                    169:        /**
                    170:         * Address prefix to use when installing dynamic addresses
                    171:         */
                    172:        int prefix;
                    173: 
                    174:        /**
                    175:         * Keep addresses until shutdown?
                    176:         */
                    177:        bool keep;
                    178: 
                    179:        /**
                    180:         * Hashtable with leases in "pools", host_t => entry_t
                    181:         */
                    182:        hashtable_t *leases;
                    183: 
                    184:        /**
                    185:         * Mutex for leases hashtable
                    186:         */
                    187:        mutex_t *mutex;
                    188: };
                    189: 
                    190: /**
                    191:  * Lease entry
                    192:  */
                    193: typedef struct {
                    194:        /** host reference, equal to key */
                    195:        host_t *host;
                    196:        /** associated identity */
                    197:        identification_t *id;
                    198: } entry_t;
                    199: 
                    200: /**
                    201:  * Destroy an entry_t
                    202:  */
                    203: static void entry_destroy(entry_t *this)
                    204: {
                    205:        this->host->destroy(this->host);
                    206:        this->id->destroy(this->id);
                    207:        free(this);
                    208: }
                    209: 
                    210: /**
                    211:  * Hashtable hash function
                    212:  */
                    213: static u_int hash(host_t *key)
                    214: {
                    215:        return chunk_hash(key->get_address(key));
                    216: }
                    217: 
                    218: /**
                    219:  * Hashtable equals function
                    220:  */
                    221: static bool equals(host_t *a, host_t *b)
                    222: {
                    223:        return a->ip_equals(a, b);
                    224: }
                    225: 
                    226: /**
                    227:  * Load external addresses to use, if any
                    228:  */
                    229: static void load_addrs(private_load_tester_config_t *this)
                    230: {
                    231:        enumerator_t *enumerator, *tokens;
                    232:        host_t *from, *to;
                    233:        int bits;
                    234:        char *iface, *token, *pos;
                    235:        mem_pool_t *pool;
                    236: 
                    237:        this->keep = lib->settings->get_bool(lib->settings,
                    238:                                                "%s.plugins.load-tester.addrs_keep", FALSE, lib->ns);
                    239:        this->prefix = lib->settings->get_int(lib->settings,
                    240:                                                "%s.plugins.load-tester.addrs_prefix", 16, lib->ns);
                    241:        enumerator = lib->settings->create_key_value_enumerator(lib->settings,
                    242:                                                "%s.plugins.load-tester.addrs", lib->ns);
                    243:        while (enumerator->enumerate(enumerator, &iface, &token))
                    244:        {
                    245:                tokens = enumerator_create_token(token, ",", " ");
                    246:                while (tokens->enumerate(tokens, &token))
                    247:                {
                    248:                        pos = strchr(token, '-');
                    249:                        if (pos)
                    250:                        {       /* range */
                    251:                                *(pos++) = '\0';
                    252:                                /* trim whitespace */
                    253:                                while (*pos == ' ')
                    254:                                {
                    255:                                        pos++;
                    256:                                }
                    257:                                while (token[strlen(token) - 1] == ' ')
                    258:                                {
                    259:                                        token[strlen(token) - 1] = '\0';
                    260:                                }
                    261:                                from = host_create_from_string(token, 0);
                    262:                                to = host_create_from_string(pos, 0);
                    263:                                if (from && to)
                    264:                                {
                    265:                                        pool = mem_pool_create_range(iface, from, to);
                    266:                                        if (pool)
                    267:                                        {
                    268:                                                DBG1(DBG_CFG, "loaded load-tester address range "
                    269:                                                         "%H-%H on %s", from, to, iface);
                    270:                                                this->pools->insert_last(this->pools, pool);
                    271:                                        }
                    272:                                        from->destroy(from);
                    273:                                        to->destroy(to);
                    274:                                }
                    275:                                else
                    276:                                {
                    277:                                        DBG1(DBG_CFG, "parsing load-tester address range %s-%s "
                    278:                                                 "failed, skipped", token, pos);
                    279:                                        DESTROY_IF(from);
                    280:                                        DESTROY_IF(to);
                    281:                                }
                    282:                        }
                    283:                        else
                    284:                        {       /* subnet */
                    285:                                from = host_create_from_subnet(token, &bits);
                    286:                                if (from)
                    287:                                {
                    288:                                        DBG1(DBG_CFG, "loaded load-tester address pool %H/%d on %s",
                    289:                                                 from, bits, iface);
                    290:                                        pool = mem_pool_create(iface, from, bits);
                    291:                                        from->destroy(from);
                    292:                                        this->pools->insert_last(this->pools, pool);
                    293:                                }
                    294:                                else
                    295:                                {
                    296:                                        DBG1(DBG_CFG, "parsing load-tester address %s failed, "
                    297:                                                 "skipped", token);
                    298:                                }
                    299:                        }
                    300:                }
                    301:                tokens->destroy(tokens);
                    302:        }
                    303:        enumerator->destroy(enumerator);
                    304: }
                    305: 
                    306: /**
                    307:  * Generate auth config from string
                    308:  */
                    309: static void generate_auth_cfg(private_load_tester_config_t *this, char *str,
                    310:                                                          peer_cfg_t *peer_cfg, bool local, int num)
                    311: {
                    312:        enumerator_t *enumerator;
                    313:        auth_cfg_t *auth;
                    314:        identification_t *id;
                    315:        auth_class_t class;
                    316:        eap_type_t type;
                    317:        char buf[128];
                    318:        int rnd = 0;
                    319: 
                    320:        enumerator = enumerator_create_token(str, "|", " ");
                    321:        while (enumerator->enumerate(enumerator, &str))
                    322:        {
                    323:                id = NULL;
                    324:                auth = auth_cfg_create();
                    325:                rnd++;
                    326: 
                    327:                if (this->initiator_id)
                    328:                {
                    329:                        if (this->initiator_match && (!local && !num))
                    330:                        {       /* as responder, use the specified identity that matches
                    331:                                 * all used initiator identities, if given. */
                    332:                                snprintf(buf, sizeof(buf), this->initiator_match, rnd);
                    333:                                id = identification_create_from_string(buf);
                    334:                        }
                    335:                        else if ((local && num) || (!local && !num))
                    336:                        {       /* as initiator, create peer specific identities */
                    337:                                snprintf(buf, sizeof(buf), this->initiator_id, num, rnd);
                    338:                                id = identification_create_from_string(buf);
                    339:                        }
                    340:                }
                    341:                if (this->responder_id)
                    342:                {
                    343:                        if ((local && !num) || (!local && num))
                    344:                        {
                    345:                                snprintf(buf, sizeof(buf), this->responder_id, num, rnd);
                    346:                                id = identification_create_from_string(buf);
                    347:                        }
                    348:                }
                    349: 
                    350:                if (streq(str, "psk"))
                    351:                {       /* PSK authentication, use FQDNs */
                    352:                        class = AUTH_CLASS_PSK;
                    353:                        if (!id)
                    354:                        {
                    355:                                if ((local && !num) || (!local && num))
                    356:                                {
                    357:                                        id = identification_create_from_string("srv.strongswan.org");
                    358:                                }
                    359:                                else if (local)
                    360:                                {
                    361:                                        snprintf(buf, sizeof(buf), "c%d-r%d.strongswan.org",
                    362:                                                         num, rnd);
                    363:                                        id = identification_create_from_string(buf);
                    364:                                }
                    365:                                else
                    366:                                {
                    367:                                        id = identification_create_from_string("*.strongswan.org");
                    368:                                }
                    369:                        }
                    370:                }
                    371:                else if (strpfx(str, "eap"))
                    372:                {       /* EAP authentication, use a NAI */
                    373:                        class = AUTH_CLASS_EAP;
                    374:                        if (*(str + strlen("eap")) == '-')
                    375:                        {
                    376:                                type = eap_type_from_string(str + strlen("eap-"));
                    377:                                if (type)
                    378:                                {
                    379:                                        auth->add(auth, AUTH_RULE_EAP_TYPE, type);
                    380:                                }
                    381:                        }
                    382:                        if (!id)
                    383:                        {
                    384:                                if (local && num)
                    385:                                {
                    386:                                        snprintf(buf, sizeof(buf), "1%.10d%.4d@strongswan.org",
                    387:                                                         num, rnd);
                    388:                                        id = identification_create_from_string(buf);
                    389:                                }
                    390:                                else
                    391:                                {
                    392:                                        id = identification_create_from_encoding(ID_ANY, chunk_empty);
                    393:                                }
                    394:                        }
                    395:                }
                    396:                else if (strpfx(str, "xauth"))
                    397:                {       /* XAuth, use a username */
                    398:                        class = AUTH_CLASS_XAUTH;
                    399:                        if (*(str + strlen("xauth")) == '-')
                    400:                        {
                    401:                                auth->add(auth, AUTH_RULE_XAUTH_BACKEND, str + strlen("xauth-"));
                    402:                        }
                    403:                        if (!id)
                    404:                        {
                    405:                                if (local && num)
                    406:                                {
                    407:                                        snprintf(buf, sizeof(buf), "cli-%.6d-%.2d", num, rnd);
                    408:                                        id = identification_create_from_string(buf);
                    409:                                }
                    410:                                else
                    411:                                {
                    412:                                        id = identification_create_from_encoding(ID_ANY, chunk_empty);
                    413:                                }
                    414:                        }
                    415:                        /* additionally set the ID as XAuth identity */
                    416:                        auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id));
                    417:                }
                    418:                else
                    419:                {
                    420:                        if (!streq(str, "pubkey"))
                    421:                        {
                    422:                                DBG1(DBG_CFG, "invalid authentication: '%s', fallback to pubkey",
                    423:                                         str);
                    424:                        }
                    425:                        /* certificate authentication, use distinguished names */
                    426:                        class = AUTH_CLASS_PUBKEY;
                    427:                        if (!id)
                    428:                        {
                    429:                                if ((local && !num) || (!local && num))
                    430:                                {
                    431:                                        id = identification_create_from_string(
                    432:                                                                "CN=srv, OU=load-test, O=strongSwan");
                    433:                                }
                    434:                                else if (local)
                    435:                                {
                    436:                                        snprintf(buf, sizeof(buf),
                    437:                                                         "CN=c%d-r%d, OU=load-test, O=strongSwan", num, rnd);
                    438:                                        id = identification_create_from_string(buf);
                    439:                                }
                    440:                                else
                    441:                                {
                    442:                                        id = identification_create_from_string(
                    443:                                                                        "CN=*, OU=load-test, O=strongSwan");
                    444:                                }
                    445:                        }
                    446:                }
                    447:                auth->add(auth, AUTH_RULE_AUTH_CLASS, class);
                    448:                auth->add(auth, AUTH_RULE_IDENTITY, id);
                    449:                peer_cfg->add_auth_cfg(peer_cfg, auth, local);
                    450:        }
                    451:        enumerator->destroy(enumerator);
                    452: }
                    453: 
                    454: /**
                    455:  * Parse a protoport specifier
                    456:  */
                    457: static bool parse_protoport(char *token, uint16_t *from_port,
                    458:                                                        uint16_t *to_port, uint8_t *protocol)
                    459: {
                    460:        char *sep, *port = "", *endptr;
                    461:        struct protoent *proto;
                    462:        struct servent *svc;
                    463:        long int p;
                    464: 
                    465:        sep = strrchr(token, ']');
                    466:        if (!sep)
                    467:        {
                    468:                return FALSE;
                    469:        }
                    470:        *sep = '\0';
                    471: 
                    472:        sep = strchr(token, '/');
                    473:        if (sep)
                    474:        {       /* protocol/port */
                    475:                *sep = '\0';
                    476:                port = sep + 1;
                    477:        }
                    478: 
                    479:        if (streq(token, "%any"))
                    480:        {
                    481:                *protocol = 0;
                    482:        }
                    483:        else
                    484:        {
                    485:                proto = getprotobyname(token);
                    486:                if (proto)
                    487:                {
                    488:                        *protocol = proto->p_proto;
                    489:                }
                    490:                else
                    491:                {
                    492:                        p = strtol(token, &endptr, 0);
                    493:                        if ((*token && *endptr) || p < 0 || p > 0xff)
                    494:                        {
                    495:                                return FALSE;
                    496:                        }
                    497:                        *protocol = (uint8_t)p;
                    498:                }
                    499:        }
                    500:        if (streq(port, "%any"))
                    501:        {
                    502:                *from_port = 0;
                    503:                *to_port = 0xffff;
                    504:        }
                    505:        else if (streq(port, "%opaque"))
                    506:        {
                    507:                *from_port = 0xffff;
                    508:                *to_port = 0;
                    509:        }
                    510:        else if (streq(port, "%unique"))
                    511:        {
                    512:                *from_port = *to_port = 0;
                    513:        }
                    514:        else if (*port)
                    515:        {
                    516:                svc = getservbyname(port, NULL);
                    517:                if (svc)
                    518:                {
                    519:                        *from_port = *to_port = ntohs(svc->s_port);
                    520:                }
                    521:                else
                    522:                {
                    523:                        p = strtol(port, &endptr, 0);
                    524:                        if (p < 0 || p > 0xffff)
                    525:                        {
                    526:                                return FALSE;
                    527:                        }
                    528:                        *from_port = p;
                    529:                        if (*endptr == '-')
                    530:                        {
                    531:                                port = endptr + 1;
                    532:                                p = strtol(port, &endptr, 0);
                    533:                                if (p < 0 || p > 0xffff)
                    534:                                {
                    535:                                        return FALSE;
                    536:                                }
                    537:                        }
                    538:                        *to_port = p;
                    539:                        if (*endptr)
                    540:                        {
                    541:                                return FALSE;
                    542:                        }
                    543:                }
                    544:        }
                    545:        return TRUE;
                    546: }
                    547: 
                    548: /**
                    549:  * Add a TS from a string to a child_cfg
                    550:  */
                    551: static void add_ts(private_load_tester_config_t *this,
                    552:                                   char *string, child_cfg_t *cfg, bool local, bool initiator)
                    553: {
                    554:        traffic_selector_t *ts;
                    555: 
                    556:        if (string)
                    557:        {
                    558:                enumerator_t *enumerator;
                    559:                char *subnet, *pos;
                    560:                uint16_t from_port, to_port;
                    561:                uint8_t proto;
                    562: 
                    563:                enumerator = enumerator_create_token(string, ",", " ");
                    564:                while (enumerator->enumerate(enumerator, &subnet))
                    565:                {
                    566:                        proto = 0;
                    567:                        from_port = 0;
                    568:                        to_port = 65535;
                    569: 
                    570:                        pos = strchr(subnet, '[');
                    571:                        if (pos)
                    572:                        {
                    573:                                *(pos++) = '\0';
                    574:                                if (!parse_protoport(pos, &from_port, &to_port, &proto))
                    575:                                {
                    576:                                        DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet",
                    577:                                                 pos);
                    578:                                        continue;
                    579:                                }
                    580:                        }
                    581:                        if (from_port == 0 && to_port == 0)
                    582:                        {       /* %unique */
                    583:                                if (initiator)
                    584:                                {
                    585:                                        from_port = this->unique_port++;
                    586:                                        from_port = to_port = max(from_port, UNIQUE_PORT_START);
                    587:                                }
                    588:                                else
                    589:                                {       /* not supported as responder, use %any */
                    590:                                        to_port = 65535;
                    591:                                }
                    592:                        }
                    593:                        if (streq(subnet, "%dynamic"))
                    594:                        {
                    595:                                ts = traffic_selector_create_dynamic(proto,
                    596:                                                                                                         from_port, to_port);
                    597:                        }
                    598:                        else
                    599:                        {
                    600:                                ts = traffic_selector_create_from_cidr(subnet, proto,
                    601:                                                                                                           from_port, to_port);
                    602:                        }
                    603:                        if (ts)
                    604:                        {
                    605:                                cfg->add_traffic_selector(cfg, local, ts);
                    606:                        }
                    607:                        else
                    608:                        {
                    609:                                DBG1(DBG_CFG, "invalid subnet: %s, skipped", subnet);
                    610:                        }
                    611:                }
                    612:                enumerator->destroy(enumerator);
                    613:        }
                    614:        else
                    615:        {
                    616:                ts = traffic_selector_create_dynamic(0, 0, 65535);
                    617:                if (ts)
                    618:                {
                    619:                        cfg->add_traffic_selector(cfg, local, ts);
                    620:                }
                    621:        }
                    622: }
                    623: 
                    624: /**
                    625:  * Allocate and install a dynamic external address to use
                    626:  */
                    627: static host_t *allocate_addr(private_load_tester_config_t *this, uint num)
                    628: {
                    629:        enumerator_t *enumerator;
                    630:        mem_pool_t *pool;
                    631:        host_t *found = NULL, *requested;
                    632:        identification_t *id;
                    633:        char *iface = NULL, buf[32];
                    634:        entry_t *entry;
                    635: 
                    636:        snprintf(buf, sizeof(buf), "ext-%d", num);
                    637:        id = identification_create_from_string(buf);
                    638:        enumerator = this->pools->create_enumerator(this->pools);
                    639:        while (enumerator->enumerate(enumerator, &pool))
                    640:        {
1.1.1.2 ! misho     641:                requested = pool->get_base(pool);
        !           642:                requested = host_create_any(requested->get_family(requested));
1.1       misho     643:                found = pool->acquire_address(pool, id, requested, MEM_POOL_NEW, NULL);
1.1.1.2 ! misho     644:                requested->destroy(requested);
1.1       misho     645:                if (found)
                    646:                {
                    647:                        iface = (char*)pool->get_name(pool);
                    648:                        break;
                    649:                }
                    650:        }
                    651:        enumerator->destroy(enumerator);
                    652: 
                    653:        if (!found)
                    654:        {
                    655:                DBG1(DBG_CFG, "no address found to install as load-tester external IP");
                    656:                id->destroy(id);
                    657:                return NULL;
                    658:        }
                    659:        if (charon->kernel->add_ip(charon->kernel, found, this->prefix,
                    660:                                                           iface) != SUCCESS)
                    661:        {
                    662:                DBG1(DBG_CFG, "installing load-tester IP %H on %s failed", found, iface);
                    663:                found->destroy(found);
                    664:                id->destroy(id);
                    665:                return NULL;
                    666:        }
                    667:        DBG1(DBG_CFG, "installed load-tester IP %H on %s", found, iface);
                    668:        INIT(entry,
                    669:                .host = found->clone(found),
                    670:                .id = id,
                    671:        );
                    672:        this->mutex->lock(this->mutex);
                    673:        entry = this->leases->put(this->leases, entry->host, entry);
                    674:        this->mutex->unlock(this->mutex);
                    675:        if (entry)
                    676:        {       /* shouldn't actually happen */
                    677:                entry_destroy(entry);
                    678:        }
                    679:        return found;
                    680: }
                    681: 
                    682: /**
                    683:  * Generate a new initiator config, num = 0 for responder config
                    684:  */
                    685: static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
                    686: {
                    687:        ike_cfg_t *ike_cfg;
                    688:        child_cfg_t *child_cfg;
                    689:        peer_cfg_t *peer_cfg;
                    690:        char local[32];
                    691:        host_t *addr;
                    692:        ike_cfg_create_t ike = {
                    693:                .version = this->version,
                    694:                .remote_port = IKEV2_UDP_PORT,
                    695:        };
                    696:        peer_cfg_create_t peer = {
                    697:                .cert_policy = CERT_SEND_IF_ASKED,
                    698:                .unique = UNIQUE_NO,
                    699:                .keyingtries = 1,
                    700:                .rekey_time = this->ike_rekey,
                    701:                .over_time = this->ike_rekey,
                    702:                .no_mobike = TRUE,
                    703:                .dpd = this->dpd_delay,
                    704:                .dpd_timeout = this->dpd_timeout,
                    705:        };
                    706:        child_cfg_create_t child = {
                    707:                .lifetime = {
                    708:                        .time = {
                    709:                                .life = this->child_rekey * 2,
                    710:                                .rekey = this->child_rekey,
                    711:                                .jitter = 0
                    712:                        },
                    713:                },
                    714:                .mode = MODE_TUNNEL,
                    715:        };
                    716: 
                    717:        if (num)
                    718:        {       /* initiator */
                    719:                if (this->pools->get_count(this->pools))
                    720:                {       /* using dynamically installed external addresses */
                    721:                        addr = allocate_addr(this, num);
                    722:                        if (!addr)
                    723:                        {
                    724:                                DBG1(DBG_CFG, "allocating external address failed");
                    725:                                return NULL;
                    726:                        }
                    727:                        snprintf(local, sizeof(local), "%H", addr);
                    728:                        addr->destroy(addr);
                    729:                }
                    730:                else
                    731:                {
                    732:                        snprintf(local, sizeof(local), "%s", this->initiator);
                    733:                }
                    734:                ike.remote = this->responder;
                    735:        }
                    736:        else
                    737:        {
                    738:                snprintf(local, sizeof(local), "%s", this->responder);
                    739:                ike.remote = this->initiator;
                    740:        }
                    741: 
                    742:        ike.local = local;
                    743:        if (this->port && num)
                    744:        {
                    745:                ike.local_port = this->port + num - 1;
                    746:                ike.remote_port = IKEV2_NATT_PORT;
                    747:        }
                    748:        else
                    749:        {
                    750:                ike.local_port = charon->socket->get_port(charon->socket, FALSE);
                    751:        }
                    752:        ike_cfg = ike_cfg_create(&ike);
                    753:        ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal, 0));
                    754:        peer_cfg = peer_cfg_create("load-test", ike_cfg, &peer);
                    755: 
1.1.1.2 ! misho     756:        if (this->vips)
1.1       misho     757:        {
1.1.1.2 ! misho     758:                peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET));
        !           759:                peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET6));
1.1       misho     760:        }
                    761:        if (this->pool)
                    762:        {
                    763:                peer_cfg->add_pool(peer_cfg, this->pool);
                    764:        }
                    765:        if (num)
                    766:        {       /* initiator */
                    767:                generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
                    768:                generate_auth_cfg(this, this->responder_auth, peer_cfg, FALSE, num);
                    769:        }
                    770:        else
                    771:        {       /* responder */
                    772:                generate_auth_cfg(this, this->responder_auth, peer_cfg, TRUE, num);
                    773:                generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num);
                    774:        }
                    775: 
                    776:        if (this->mode)
                    777:        {
                    778:                if (streq(this->mode, "transport"))
                    779:                {
                    780:                        child.mode = MODE_TRANSPORT;
                    781:                }
                    782:                else if (streq(this->mode, "beet"))
                    783:                {
                    784:                        child.mode = MODE_BEET;
                    785:                }
                    786:        }
                    787: 
                    788:        child_cfg = child_cfg_create("load-test", &child);
                    789:        child_cfg->add_proposal(child_cfg, this->esp->clone(this->esp, 0));
                    790: 
                    791:        if (num)
                    792:        {       /* initiator */
1.1.1.2 ! misho     793:                if (this->vips)
1.1       misho     794:                {
                    795:                        add_ts(this, NULL, child_cfg, TRUE, TRUE);
                    796:                }
                    797:                else
                    798:                {
                    799:                        add_ts(this, this->initiator_tsi, child_cfg, TRUE, TRUE);
                    800:                }
                    801:                add_ts(this, this->initiator_tsr, child_cfg, FALSE, TRUE);
                    802:        }
                    803:        else
                    804:        {       /* responder */
                    805:                add_ts(this, this->responder_tsr, child_cfg, TRUE, FALSE);
                    806:                add_ts(this, this->responder_tsi, child_cfg, FALSE, FALSE);
                    807:        }
                    808:        peer_cfg->add_child_cfg(peer_cfg, child_cfg);
                    809:        return peer_cfg;
                    810: }
                    811: 
                    812: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
                    813:        private_load_tester_config_t *this,
                    814:        identification_t *me, identification_t *other)
                    815: {
                    816:        return enumerator_create_single(this->peer_cfg, NULL);
                    817: }
                    818: 
                    819: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
                    820:        private_load_tester_config_t *this, host_t *me, host_t *other)
                    821: {
                    822:        ike_cfg_t *ike_cfg;
                    823: 
                    824:        ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
                    825:        return enumerator_create_single(ike_cfg, NULL);
                    826: }
                    827: 
                    828: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
                    829:        private_load_tester_config_t *this, char *name)
                    830: {
                    831:        if (streq(name, "load-test"))
                    832:        {
                    833:                return generate_config(this, (u_int)ref_get(&this->num));
                    834:        }
                    835:        return NULL;
                    836: }
                    837: 
                    838: METHOD(load_tester_config_t, delete_ip, void,
                    839:        private_load_tester_config_t *this, host_t *ip)
                    840: {
                    841:        enumerator_t *enumerator;
                    842:        mem_pool_t *pool;
                    843:        entry_t *entry;
                    844: 
                    845:        if (this->keep)
                    846:        {
                    847:                return;
                    848:        }
                    849: 
                    850:        this->mutex->lock(this->mutex);
                    851:        entry = this->leases->remove(this->leases, ip);
                    852:        this->mutex->unlock(this->mutex);
                    853: 
                    854:        if (entry)
                    855:        {
                    856:                enumerator = this->pools->create_enumerator(this->pools);
                    857:                while (enumerator->enumerate(enumerator, &pool))
                    858:                {
                    859:                        if (pool->release_address(pool, entry->host, entry->id))
                    860:                        {
                    861:                                charon->kernel->del_ip(charon->kernel, entry->host,
                    862:                                                                           this->prefix, FALSE);
                    863:                                break;
                    864:                        }
                    865:                }
                    866:                enumerator->destroy(enumerator);
                    867:                entry_destroy(entry);
                    868:        }
                    869: }
                    870: 
                    871: /**
                    872:  * Clean up leases for allocated external addresses, if have been kept
                    873:  */
                    874: static void cleanup_leases(private_load_tester_config_t *this)
                    875: {
                    876:        enumerator_t *pools, *leases;
                    877:        mem_pool_t *pool;
                    878:        identification_t *id;
                    879:        host_t *addr;
                    880:        entry_t *entry;
                    881:        bool online;
                    882: 
                    883:        pools = this->pools->create_enumerator(this->pools);
                    884:        while (pools->enumerate(pools, &pool))
                    885:        {
                    886:                leases = pool->create_lease_enumerator(pool);
                    887:                while (leases->enumerate(leases, &id, &addr, &online))
                    888:                {
                    889:                        if (online)
                    890:                        {
                    891:                                charon->kernel->del_ip(charon->kernel, addr, this->prefix,
                    892:                                                                           FALSE);
                    893:                                entry = this->leases->remove(this->leases, addr);
                    894:                                if (entry)
                    895:                                {
                    896:                                        entry_destroy(entry);
                    897:                                }
                    898:                        }
                    899:                }
                    900:                leases->destroy(leases);
                    901:        }
                    902:        pools->destroy(pools);
                    903: }
                    904: 
                    905: METHOD(load_tester_config_t, destroy, void,
                    906:        private_load_tester_config_t *this)
                    907: {
                    908:        if (this->keep)
                    909:        {
                    910:                cleanup_leases(this);
                    911:        }
                    912:        this->mutex->destroy(this->mutex);
                    913:        this->leases->destroy(this->leases);
                    914:        this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
                    915:        this->peer_cfg->destroy(this->peer_cfg);
                    916:        DESTROY_IF(this->proposal);
                    917:        DESTROY_IF(this->esp);
                    918:        free(this);
                    919: }
                    920: 
                    921: /**
                    922:  * Described in header.
                    923:  */
                    924: load_tester_config_t *load_tester_config_create()
                    925: {
                    926:        private_load_tester_config_t *this;
                    927: 
                    928:        INIT(this,
                    929:                .public = {
                    930:                        .backend = {
                    931:                                .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
                    932:                                .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
                    933:                                .get_peer_cfg_by_name = _get_peer_cfg_by_name,
                    934:                        },
                    935:                        .delete_ip = _delete_ip,
                    936:                        .destroy = _destroy,
                    937:                },
                    938:                .pools = linked_list_create(),
                    939:                .leases = hashtable_create((hashtable_hash_t)hash,
                    940:                                                                   (hashtable_equals_t)equals, 256),
                    941:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    942:                .unique_port = UNIQUE_PORT_START,
                    943:        );
                    944: 
1.1.1.2 ! misho     945:        this->vips = lib->settings->get_bool(lib->settings,
        !           946:                                        "%s.plugins.load-tester.request_virtual_ip", FALSE, lib->ns);
1.1       misho     947:        this->pool = lib->settings->get_str(lib->settings,
                    948:                                        "%s.plugins.load-tester.pool", NULL, lib->ns);
                    949:        this->initiator = lib->settings->get_str(lib->settings,
                    950:                                        "%s.plugins.load-tester.initiator", "0.0.0.0", lib->ns);
                    951:        this->responder = lib->settings->get_str(lib->settings,
                    952:                                        "%s.plugins.load-tester.responder", "127.0.0.1", lib->ns);
                    953: 
                    954:        this->proposal = proposal_create_from_string(PROTO_IKE,
                    955:                                lib->settings->get_str(lib->settings,
                    956:                                        "%s.plugins.load-tester.proposal", "aes128-sha1-modp768",
                    957:                                        lib->ns));
                    958:        if (!this->proposal)
                    959:        {       /* fallback */
                    960:                this->proposal = proposal_create_from_string(PROTO_IKE,
                    961:                                                                                                         "aes128-sha1-modp768");
                    962:        }
                    963:        this->esp = proposal_create_from_string(PROTO_ESP,
                    964:                                lib->settings->get_str(lib->settings,
                    965:                                        "%s.plugins.load-tester.esp", "aes128-sha1", lib->ns));
                    966:        if (!this->esp)
                    967:        {       /* fallback */
                    968:                this->esp = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
                    969:        }
                    970: 
                    971:        this->ike_rekey = lib->settings->get_int(lib->settings,
                    972:                                "%s.plugins.load-tester.ike_rekey", 0, lib->ns);
                    973:        this->child_rekey = lib->settings->get_int(lib->settings,
                    974:                                "%s.plugins.load-tester.child_rekey", 600, lib->ns);
                    975:        this->dpd_delay = lib->settings->get_int(lib->settings,
                    976:                                "%s.plugins.load-tester.dpd_delay", 0, lib->ns);
                    977:        this->dpd_timeout = lib->settings->get_int(lib->settings,
                    978:                                "%s.plugins.load-tester.dpd_timeout", 0, lib->ns);
                    979: 
                    980:        this->initiator_auth = lib->settings->get_str(lib->settings,
                    981:                                "%s.plugins.load-tester.initiator_auth", "pubkey", lib->ns);
                    982:        this->responder_auth = lib->settings->get_str(lib->settings,
                    983:                                "%s.plugins.load-tester.responder_auth", "pubkey", lib->ns);
                    984:        this->initiator_id = lib->settings->get_str(lib->settings,
                    985:                                "%s.plugins.load-tester.initiator_id", NULL, lib->ns);
                    986:        this->initiator_match = lib->settings->get_str(lib->settings,
                    987:                                "%s.plugins.load-tester.initiator_match", NULL, lib->ns);
                    988:        this->responder_id = lib->settings->get_str(lib->settings,
                    989:                                "%s.plugins.load-tester.responder_id", NULL, lib->ns);
                    990: 
                    991:        this->mode = lib->settings->get_str(lib->settings,
                    992:                                "%s.plugins.load-tester.mode", NULL, lib->ns);
                    993:        this->initiator_tsi = lib->settings->get_str(lib->settings,
                    994:                                "%s.plugins.load-tester.initiator_tsi", NULL, lib->ns);
                    995:        this->responder_tsi =lib->settings->get_str(lib->settings,
                    996:                                "%s.plugins.load-tester.responder_tsi",
                    997:                                this->initiator_tsi, lib->ns);
                    998:        this->initiator_tsr = lib->settings->get_str(lib->settings,
                    999:                                "%s.plugins.load-tester.initiator_tsr", NULL, lib->ns);
                   1000:        this->responder_tsr =lib->settings->get_str(lib->settings,
                   1001:                                "%s.plugins.load-tester.responder_tsr",
                   1002:                                this->initiator_tsr, lib->ns);
                   1003: 
                   1004:        this->port = lib->settings->get_int(lib->settings,
                   1005:                                "%s.plugins.load-tester.dynamic_port", 0, lib->ns);
                   1006:        this->version = lib->settings->get_int(lib->settings,
                   1007:                                "%s.plugins.load-tester.version", IKE_ANY, lib->ns);
                   1008: 
                   1009:        load_addrs(this);
                   1010: 
                   1011:        this->peer_cfg = generate_config(this, 0);
                   1012: 
                   1013:        return &this->public;
                   1014: }

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