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