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

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:        /**
        !            45:         * virtual IP, if any
        !            46:         */
        !            47:        host_t *vip;
        !            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:        requested = host_create_any(AF_INET);
        !           637:        snprintf(buf, sizeof(buf), "ext-%d", num);
        !           638:        id = identification_create_from_string(buf);
        !           639:        enumerator = this->pools->create_enumerator(this->pools);
        !           640:        while (enumerator->enumerate(enumerator, &pool))
        !           641:        {
        !           642:                found = pool->acquire_address(pool, id, requested, MEM_POOL_NEW, NULL);
        !           643:                if (found)
        !           644:                {
        !           645:                        iface = (char*)pool->get_name(pool);
        !           646:                        break;
        !           647:                }
        !           648:        }
        !           649:        enumerator->destroy(enumerator);
        !           650:        requested->destroy(requested);
        !           651: 
        !           652:        if (!found)
        !           653:        {
        !           654:                DBG1(DBG_CFG, "no address found to install as load-tester external IP");
        !           655:                id->destroy(id);
        !           656:                return NULL;
        !           657:        }
        !           658:        if (charon->kernel->add_ip(charon->kernel, found, this->prefix,
        !           659:                                                           iface) != SUCCESS)
        !           660:        {
        !           661:                DBG1(DBG_CFG, "installing load-tester IP %H on %s failed", found, iface);
        !           662:                found->destroy(found);
        !           663:                id->destroy(id);
        !           664:                return NULL;
        !           665:        }
        !           666:        DBG1(DBG_CFG, "installed load-tester IP %H on %s", found, iface);
        !           667:        INIT(entry,
        !           668:                .host = found->clone(found),
        !           669:                .id = id,
        !           670:        );
        !           671:        this->mutex->lock(this->mutex);
        !           672:        entry = this->leases->put(this->leases, entry->host, entry);
        !           673:        this->mutex->unlock(this->mutex);
        !           674:        if (entry)
        !           675:        {       /* shouldn't actually happen */
        !           676:                entry_destroy(entry);
        !           677:        }
        !           678:        return found;
        !           679: }
        !           680: 
        !           681: /**
        !           682:  * Generate a new initiator config, num = 0 for responder config
        !           683:  */
        !           684: static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
        !           685: {
        !           686:        ike_cfg_t *ike_cfg;
        !           687:        child_cfg_t *child_cfg;
        !           688:        peer_cfg_t *peer_cfg;
        !           689:        char local[32];
        !           690:        host_t *addr;
        !           691:        ike_cfg_create_t ike = {
        !           692:                .version = this->version,
        !           693:                .remote_port = IKEV2_UDP_PORT,
        !           694:        };
        !           695:        peer_cfg_create_t peer = {
        !           696:                .cert_policy = CERT_SEND_IF_ASKED,
        !           697:                .unique = UNIQUE_NO,
        !           698:                .keyingtries = 1,
        !           699:                .rekey_time = this->ike_rekey,
        !           700:                .over_time = this->ike_rekey,
        !           701:                .no_mobike = TRUE,
        !           702:                .dpd = this->dpd_delay,
        !           703:                .dpd_timeout = this->dpd_timeout,
        !           704:        };
        !           705:        child_cfg_create_t child = {
        !           706:                .lifetime = {
        !           707:                        .time = {
        !           708:                                .life = this->child_rekey * 2,
        !           709:                                .rekey = this->child_rekey,
        !           710:                                .jitter = 0
        !           711:                        },
        !           712:                },
        !           713:                .mode = MODE_TUNNEL,
        !           714:        };
        !           715: 
        !           716:        if (num)
        !           717:        {       /* initiator */
        !           718:                if (this->pools->get_count(this->pools))
        !           719:                {       /* using dynamically installed external addresses */
        !           720:                        addr = allocate_addr(this, num);
        !           721:                        if (!addr)
        !           722:                        {
        !           723:                                DBG1(DBG_CFG, "allocating external address failed");
        !           724:                                return NULL;
        !           725:                        }
        !           726:                        snprintf(local, sizeof(local), "%H", addr);
        !           727:                        addr->destroy(addr);
        !           728:                }
        !           729:                else
        !           730:                {
        !           731:                        snprintf(local, sizeof(local), "%s", this->initiator);
        !           732:                }
        !           733:                ike.remote = this->responder;
        !           734:        }
        !           735:        else
        !           736:        {
        !           737:                snprintf(local, sizeof(local), "%s", this->responder);
        !           738:                ike.remote = this->initiator;
        !           739:        }
        !           740: 
        !           741:        ike.local = local;
        !           742:        if (this->port && num)
        !           743:        {
        !           744:                ike.local_port = this->port + num - 1;
        !           745:                ike.remote_port = IKEV2_NATT_PORT;
        !           746:        }
        !           747:        else
        !           748:        {
        !           749:                ike.local_port = charon->socket->get_port(charon->socket, FALSE);
        !           750:        }
        !           751:        ike_cfg = ike_cfg_create(&ike);
        !           752:        ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal, 0));
        !           753:        peer_cfg = peer_cfg_create("load-test", ike_cfg, &peer);
        !           754: 
        !           755:        if (this->vip)
        !           756:        {
        !           757:                peer_cfg->add_virtual_ip(peer_cfg, this->vip->clone(this->vip));
        !           758:        }
        !           759:        if (this->pool)
        !           760:        {
        !           761:                peer_cfg->add_pool(peer_cfg, this->pool);
        !           762:        }
        !           763:        if (num)
        !           764:        {       /* initiator */
        !           765:                generate_auth_cfg(this, this->initiator_auth, peer_cfg, TRUE, num);
        !           766:                generate_auth_cfg(this, this->responder_auth, peer_cfg, FALSE, num);
        !           767:        }
        !           768:        else
        !           769:        {       /* responder */
        !           770:                generate_auth_cfg(this, this->responder_auth, peer_cfg, TRUE, num);
        !           771:                generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num);
        !           772:        }
        !           773: 
        !           774:        if (this->mode)
        !           775:        {
        !           776:                if (streq(this->mode, "transport"))
        !           777:                {
        !           778:                        child.mode = MODE_TRANSPORT;
        !           779:                }
        !           780:                else if (streq(this->mode, "beet"))
        !           781:                {
        !           782:                        child.mode = MODE_BEET;
        !           783:                }
        !           784:        }
        !           785: 
        !           786:        child_cfg = child_cfg_create("load-test", &child);
        !           787:        child_cfg->add_proposal(child_cfg, this->esp->clone(this->esp, 0));
        !           788: 
        !           789:        if (num)
        !           790:        {       /* initiator */
        !           791:                if (this->vip)
        !           792:                {
        !           793:                        add_ts(this, NULL, child_cfg, TRUE, TRUE);
        !           794:                }
        !           795:                else
        !           796:                {
        !           797:                        add_ts(this, this->initiator_tsi, child_cfg, TRUE, TRUE);
        !           798:                }
        !           799:                add_ts(this, this->initiator_tsr, child_cfg, FALSE, TRUE);
        !           800:        }
        !           801:        else
        !           802:        {       /* responder */
        !           803:                add_ts(this, this->responder_tsr, child_cfg, TRUE, FALSE);
        !           804:                add_ts(this, this->responder_tsi, child_cfg, FALSE, FALSE);
        !           805:        }
        !           806:        peer_cfg->add_child_cfg(peer_cfg, child_cfg);
        !           807:        return peer_cfg;
        !           808: }
        !           809: 
        !           810: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
        !           811:        private_load_tester_config_t *this,
        !           812:        identification_t *me, identification_t *other)
        !           813: {
        !           814:        return enumerator_create_single(this->peer_cfg, NULL);
        !           815: }
        !           816: 
        !           817: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
        !           818:        private_load_tester_config_t *this, host_t *me, host_t *other)
        !           819: {
        !           820:        ike_cfg_t *ike_cfg;
        !           821: 
        !           822:        ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg);
        !           823:        return enumerator_create_single(ike_cfg, NULL);
        !           824: }
        !           825: 
        !           826: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
        !           827:        private_load_tester_config_t *this, char *name)
        !           828: {
        !           829:        if (streq(name, "load-test"))
        !           830:        {
        !           831:                return generate_config(this, (u_int)ref_get(&this->num));
        !           832:        }
        !           833:        return NULL;
        !           834: }
        !           835: 
        !           836: METHOD(load_tester_config_t, delete_ip, void,
        !           837:        private_load_tester_config_t *this, host_t *ip)
        !           838: {
        !           839:        enumerator_t *enumerator;
        !           840:        mem_pool_t *pool;
        !           841:        entry_t *entry;
        !           842: 
        !           843:        if (this->keep)
        !           844:        {
        !           845:                return;
        !           846:        }
        !           847: 
        !           848:        this->mutex->lock(this->mutex);
        !           849:        entry = this->leases->remove(this->leases, ip);
        !           850:        this->mutex->unlock(this->mutex);
        !           851: 
        !           852:        if (entry)
        !           853:        {
        !           854:                enumerator = this->pools->create_enumerator(this->pools);
        !           855:                while (enumerator->enumerate(enumerator, &pool))
        !           856:                {
        !           857:                        if (pool->release_address(pool, entry->host, entry->id))
        !           858:                        {
        !           859:                                charon->kernel->del_ip(charon->kernel, entry->host,
        !           860:                                                                           this->prefix, FALSE);
        !           861:                                break;
        !           862:                        }
        !           863:                }
        !           864:                enumerator->destroy(enumerator);
        !           865:                entry_destroy(entry);
        !           866:        }
        !           867: }
        !           868: 
        !           869: /**
        !           870:  * Clean up leases for allocated external addresses, if have been kept
        !           871:  */
        !           872: static void cleanup_leases(private_load_tester_config_t *this)
        !           873: {
        !           874:        enumerator_t *pools, *leases;
        !           875:        mem_pool_t *pool;
        !           876:        identification_t *id;
        !           877:        host_t *addr;
        !           878:        entry_t *entry;
        !           879:        bool online;
        !           880: 
        !           881:        pools = this->pools->create_enumerator(this->pools);
        !           882:        while (pools->enumerate(pools, &pool))
        !           883:        {
        !           884:                leases = pool->create_lease_enumerator(pool);
        !           885:                while (leases->enumerate(leases, &id, &addr, &online))
        !           886:                {
        !           887:                        if (online)
        !           888:                        {
        !           889:                                charon->kernel->del_ip(charon->kernel, addr, this->prefix,
        !           890:                                                                           FALSE);
        !           891:                                entry = this->leases->remove(this->leases, addr);
        !           892:                                if (entry)
        !           893:                                {
        !           894:                                        entry_destroy(entry);
        !           895:                                }
        !           896:                        }
        !           897:                }
        !           898:                leases->destroy(leases);
        !           899:        }
        !           900:        pools->destroy(pools);
        !           901: }
        !           902: 
        !           903: METHOD(load_tester_config_t, destroy, void,
        !           904:        private_load_tester_config_t *this)
        !           905: {
        !           906:        if (this->keep)
        !           907:        {
        !           908:                cleanup_leases(this);
        !           909:        }
        !           910:        this->mutex->destroy(this->mutex);
        !           911:        this->leases->destroy(this->leases);
        !           912:        this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
        !           913:        this->peer_cfg->destroy(this->peer_cfg);
        !           914:        DESTROY_IF(this->proposal);
        !           915:        DESTROY_IF(this->esp);
        !           916:        DESTROY_IF(this->vip);
        !           917:        free(this);
        !           918: }
        !           919: 
        !           920: /**
        !           921:  * Described in header.
        !           922:  */
        !           923: load_tester_config_t *load_tester_config_create()
        !           924: {
        !           925:        private_load_tester_config_t *this;
        !           926: 
        !           927:        INIT(this,
        !           928:                .public = {
        !           929:                        .backend = {
        !           930:                                .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
        !           931:                                .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
        !           932:                                .get_peer_cfg_by_name = _get_peer_cfg_by_name,
        !           933:                        },
        !           934:                        .delete_ip = _delete_ip,
        !           935:                        .destroy = _destroy,
        !           936:                },
        !           937:                .pools = linked_list_create(),
        !           938:                .leases = hashtable_create((hashtable_hash_t)hash,
        !           939:                                                                   (hashtable_equals_t)equals, 256),
        !           940:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
        !           941:                .unique_port = UNIQUE_PORT_START,
        !           942:        );
        !           943: 
        !           944:        if (lib->settings->get_bool(lib->settings,
        !           945:                                "%s.plugins.load-tester.request_virtual_ip", FALSE, lib->ns))
        !           946:        {
        !           947:                this->vip = host_create_from_string("0.0.0.0", 0);
        !           948:        }
        !           949:        this->pool = lib->settings->get_str(lib->settings,
        !           950:                                        "%s.plugins.load-tester.pool", NULL, lib->ns);
        !           951:        this->initiator = lib->settings->get_str(lib->settings,
        !           952:                                        "%s.plugins.load-tester.initiator", "0.0.0.0", lib->ns);
        !           953:        this->responder = lib->settings->get_str(lib->settings,
        !           954:                                        "%s.plugins.load-tester.responder", "127.0.0.1", lib->ns);
        !           955: 
        !           956:        this->proposal = proposal_create_from_string(PROTO_IKE,
        !           957:                                lib->settings->get_str(lib->settings,
        !           958:                                        "%s.plugins.load-tester.proposal", "aes128-sha1-modp768",
        !           959:                                        lib->ns));
        !           960:        if (!this->proposal)
        !           961:        {       /* fallback */
        !           962:                this->proposal = proposal_create_from_string(PROTO_IKE,
        !           963:                                                                                                         "aes128-sha1-modp768");
        !           964:        }
        !           965:        this->esp = proposal_create_from_string(PROTO_ESP,
        !           966:                                lib->settings->get_str(lib->settings,
        !           967:                                        "%s.plugins.load-tester.esp", "aes128-sha1", lib->ns));
        !           968:        if (!this->esp)
        !           969:        {       /* fallback */
        !           970:                this->esp = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
        !           971:        }
        !           972: 
        !           973:        this->ike_rekey = lib->settings->get_int(lib->settings,
        !           974:                                "%s.plugins.load-tester.ike_rekey", 0, lib->ns);
        !           975:        this->child_rekey = lib->settings->get_int(lib->settings,
        !           976:                                "%s.plugins.load-tester.child_rekey", 600, lib->ns);
        !           977:        this->dpd_delay = lib->settings->get_int(lib->settings,
        !           978:                                "%s.plugins.load-tester.dpd_delay", 0, lib->ns);
        !           979:        this->dpd_timeout = lib->settings->get_int(lib->settings,
        !           980:                                "%s.plugins.load-tester.dpd_timeout", 0, lib->ns);
        !           981: 
        !           982:        this->initiator_auth = lib->settings->get_str(lib->settings,
        !           983:                                "%s.plugins.load-tester.initiator_auth", "pubkey", lib->ns);
        !           984:        this->responder_auth = lib->settings->get_str(lib->settings,
        !           985:                                "%s.plugins.load-tester.responder_auth", "pubkey", lib->ns);
        !           986:        this->initiator_id = lib->settings->get_str(lib->settings,
        !           987:                                "%s.plugins.load-tester.initiator_id", NULL, lib->ns);
        !           988:        this->initiator_match = lib->settings->get_str(lib->settings,
        !           989:                                "%s.plugins.load-tester.initiator_match", NULL, lib->ns);
        !           990:        this->responder_id = lib->settings->get_str(lib->settings,
        !           991:                                "%s.plugins.load-tester.responder_id", NULL, lib->ns);
        !           992: 
        !           993:        this->mode = lib->settings->get_str(lib->settings,
        !           994:                                "%s.plugins.load-tester.mode", NULL, lib->ns);
        !           995:        this->initiator_tsi = lib->settings->get_str(lib->settings,
        !           996:                                "%s.plugins.load-tester.initiator_tsi", NULL, lib->ns);
        !           997:        this->responder_tsi =lib->settings->get_str(lib->settings,
        !           998:                                "%s.plugins.load-tester.responder_tsi",
        !           999:                                this->initiator_tsi, lib->ns);
        !          1000:        this->initiator_tsr = lib->settings->get_str(lib->settings,
        !          1001:                                "%s.plugins.load-tester.initiator_tsr", NULL, lib->ns);
        !          1002:        this->responder_tsr =lib->settings->get_str(lib->settings,
        !          1003:                                "%s.plugins.load-tester.responder_tsr",
        !          1004:                                this->initiator_tsr, lib->ns);
        !          1005: 
        !          1006:        this->port = lib->settings->get_int(lib->settings,
        !          1007:                                "%s.plugins.load-tester.dynamic_port", 0, lib->ns);
        !          1008:        this->version = lib->settings->get_int(lib->settings,
        !          1009:                                "%s.plugins.load-tester.version", IKE_ANY, lib->ns);
        !          1010: 
        !          1011:        load_addrs(this);
        !          1012: 
        !          1013:        this->peer_cfg = generate_config(this, 0);
        !          1014: 
        !          1015:        return &this->public;
        !          1016: }

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