]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/config/peer_cfg.c
e7dfb5f62296bd0483d9a13d4b031a4cd0216e89
[thirdparty/strongswan.git] / src / libcharon / config / peer_cfg.c
1 /*
2 * Copyright (C) 2007-2018 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <string.h>
19
20 #include "peer_cfg.h"
21
22 #include <daemon.h>
23
24 #include <threading/rwlock.h>
25 #include <collections/linked_list.h>
26 #include <utils/identification.h>
27
28 ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
29 "CERT_ALWAYS_SEND",
30 "CERT_SEND_IF_ASKED",
31 "CERT_NEVER_SEND",
32 );
33
34 ENUM(unique_policy_names, UNIQUE_NEVER, UNIQUE_KEEP,
35 "UNIQUE_NEVER",
36 "UNIQUE_NO",
37 "UNIQUE_REPLACE",
38 "UNIQUE_KEEP",
39 );
40
41 typedef struct private_peer_cfg_t private_peer_cfg_t;
42
43 /**
44 * Private data of an peer_cfg_t object
45 */
46 struct private_peer_cfg_t {
47
48 /**
49 * Public part
50 */
51 peer_cfg_t public;
52
53 /**
54 * Number of references hold by others to this peer_cfg
55 */
56 refcount_t refcount;
57
58 /**
59 * Name of the peer_cfg, used to query it
60 */
61 char *name;
62
63 /**
64 * IKE config associated to this peer config
65 */
66 ike_cfg_t *ike_cfg;
67
68 /**
69 * list of child configs associated to this peer config
70 */
71 linked_list_t *child_cfgs;
72
73 /**
74 * lock to access list of child_cfgs
75 */
76 rwlock_t *lock;
77
78 /**
79 * should we send a certificate
80 */
81 cert_policy_t cert_policy;
82
83 /**
84 * uniqueness of an IKE_SA
85 */
86 unique_policy_t unique;
87
88 /**
89 * number of tries after giving up if peer does not respond
90 */
91 uint32_t keyingtries;
92
93 /**
94 * enable support for MOBIKE
95 */
96 bool use_mobike;
97
98 /**
99 * Use aggressive mode?
100 */
101 bool aggressive;
102
103 /**
104 * Use pull or push in mode config?
105 */
106 bool pull_mode;
107
108 /**
109 * Time before starting rekeying
110 */
111 uint32_t rekey_time;
112
113 /**
114 * Time before starting reauthentication
115 */
116 uint32_t reauth_time;
117
118 /**
119 * Time, which specifies the range of a random value subtracted from above.
120 */
121 uint32_t jitter_time;
122
123 /**
124 * Delay before deleting a rekeying/reauthenticating SA
125 */
126 uint32_t over_time;
127
128 /**
129 * DPD check interval
130 */
131 uint32_t dpd;
132
133 /**
134 * DPD timeout interval (used for IKEv1 only)
135 */
136 uint32_t dpd_timeout;
137
138 /**
139 * List of virtual IPs (host_t*) to request
140 */
141 linked_list_t *vips;
142
143 /**
144 * List of pool names to use for virtual IP lookup
145 */
146 linked_list_t *pools;
147
148 /**
149 * local authentication configs (rulesets)
150 */
151 linked_list_t *local_auth;
152
153 /**
154 * remote authentication configs (constraints)
155 */
156 linked_list_t *remote_auth;
157
158 /**
159 * PPK ID
160 */
161 identification_t *ppk_id;
162
163 /**
164 * Whether a PPK is required
165 */
166 bool ppk_required;
167
168 #ifdef ME
169 /**
170 * Is this a mediation connection?
171 */
172 bool mediation;
173
174 /**
175 * Name of the mediation connection to mediate through
176 */
177 char *mediated_by;
178
179 /**
180 * ID of our peer at the mediation server (= leftid of the peer's conn with
181 * the mediation server)
182 */
183 identification_t *peer_id;
184 #endif /* ME */
185 };
186
187 METHOD(peer_cfg_t, get_name, char*,
188 private_peer_cfg_t *this)
189 {
190 return this->name;
191 }
192
193 METHOD(peer_cfg_t, get_ike_version, ike_version_t,
194 private_peer_cfg_t *this)
195 {
196 return this->ike_cfg->get_version(this->ike_cfg);
197 }
198
199 METHOD(peer_cfg_t, get_ike_cfg, ike_cfg_t*,
200 private_peer_cfg_t *this)
201 {
202 return this->ike_cfg;
203 }
204
205 METHOD(peer_cfg_t, add_child_cfg, void,
206 private_peer_cfg_t *this, child_cfg_t *child_cfg)
207 {
208 this->lock->write_lock(this->lock);
209 this->child_cfgs->insert_last(this->child_cfgs, child_cfg);
210 this->lock->unlock(this->lock);
211 }
212
213 typedef struct {
214 enumerator_t public;
215 linked_list_t *removed;
216 linked_list_t *added;
217 enumerator_t *wrapped;
218 bool add;
219 } child_cfgs_replace_enumerator_t;
220
221 METHOD(enumerator_t, child_cfgs_replace_enumerate, bool,
222 child_cfgs_replace_enumerator_t *this, va_list args)
223 {
224 child_cfg_t *child_cfg, **chd;
225 bool *added;
226
227 VA_ARGS_VGET(args, chd, added);
228
229 if (!this->wrapped)
230 {
231 this->wrapped = this->removed->create_enumerator(this->removed);
232 }
233 while (TRUE)
234 {
235 if (this->wrapped->enumerate(this->wrapped, &child_cfg))
236 {
237 if (chd)
238 {
239 *chd = child_cfg;
240 }
241 if (added)
242 {
243 *added = this->add;
244 }
245 return TRUE;
246 }
247 if (this->add)
248 {
249 break;
250 }
251 this->wrapped->destroy(this->wrapped);
252 this->wrapped = this->added->create_enumerator(this->added);
253 this->add = TRUE;
254 }
255 return FALSE;
256 }
257
258 METHOD(enumerator_t, child_cfgs_replace_enumerator_destroy, void,
259 child_cfgs_replace_enumerator_t *this)
260 {
261 DESTROY_IF(this->wrapped);
262 this->removed->destroy_offset(this->removed, offsetof(child_cfg_t, destroy));
263 this->added->destroy_offset(this->added, offsetof(child_cfg_t, destroy));
264 free(this);
265 }
266
267 METHOD(peer_cfg_t, replace_child_cfgs, enumerator_t*,
268 private_peer_cfg_t *this, peer_cfg_t *other_pub)
269 {
270 private_peer_cfg_t *other = (private_peer_cfg_t*)other_pub;
271 linked_list_t *new_cfgs, *removed, *added;
272 enumerator_t *mine, *others;
273 child_cfg_t *my_cfg, *other_cfg;
274 child_cfgs_replace_enumerator_t *enumerator;
275 bool found;
276
277 added = linked_list_create();
278
279 other->lock->read_lock(other->lock);
280 new_cfgs = linked_list_create_from_enumerator(
281 other->child_cfgs->create_enumerator(other->child_cfgs));
282 new_cfgs->invoke_offset(new_cfgs, offsetof(child_cfg_t, get_ref));
283 other->lock->unlock(other->lock);
284
285 this->lock->write_lock(this->lock);
286 removed = this->child_cfgs;
287 this->child_cfgs = new_cfgs;
288 others = new_cfgs->create_enumerator(new_cfgs);
289 mine = removed->create_enumerator(removed);
290 while (others->enumerate(others, &other_cfg))
291 {
292 found = FALSE;
293 while (mine->enumerate(mine, &my_cfg))
294 {
295 if (my_cfg->equals(my_cfg, other_cfg))
296 {
297 removed->remove_at(removed, mine);
298 my_cfg->destroy(my_cfg);
299 found = TRUE;
300 break;
301 }
302 }
303 removed->reset_enumerator(removed, mine);
304 if (!found)
305 {
306 added->insert_last(added, other_cfg->get_ref(other_cfg));
307 }
308 }
309 others->destroy(others);
310 mine->destroy(mine);
311 this->lock->unlock(this->lock);
312
313 INIT(enumerator,
314 .public = {
315 .enumerate = enumerator_enumerate_default,
316 .venumerate = _child_cfgs_replace_enumerate,
317 .destroy = _child_cfgs_replace_enumerator_destroy,
318 },
319 .removed = removed,
320 .added = added,
321 );
322 return &enumerator->public;
323 }
324
325 /**
326 * child_cfg enumerator
327 */
328 typedef struct {
329 enumerator_t public;
330 enumerator_t *wrapped;
331 rwlock_t *lock;
332 } child_cfg_enumerator_t;
333
334 METHOD(peer_cfg_t, remove_child_cfg, void,
335 private_peer_cfg_t *this, child_cfg_enumerator_t *enumerator)
336 {
337 this->child_cfgs->remove_at(this->child_cfgs, enumerator->wrapped);
338 }
339
340 METHOD(enumerator_t, child_cfg_enumerator_destroy, void,
341 child_cfg_enumerator_t *this)
342 {
343 this->lock->unlock(this->lock);
344 this->wrapped->destroy(this->wrapped);
345 free(this);
346 }
347
348 METHOD(enumerator_t, child_cfg_enumerate, bool,
349 child_cfg_enumerator_t *this, va_list args)
350 {
351 child_cfg_t **chd;
352
353 VA_ARGS_VGET(args, chd);
354 return this->wrapped->enumerate(this->wrapped, chd);
355 }
356
357 METHOD(peer_cfg_t, create_child_cfg_enumerator, enumerator_t*,
358 private_peer_cfg_t *this)
359 {
360 child_cfg_enumerator_t *enumerator;
361
362 INIT(enumerator,
363 .public = {
364 .enumerate = enumerator_enumerate_default,
365 .venumerate = _child_cfg_enumerate,
366 .destroy = _child_cfg_enumerator_destroy,
367 },
368 .lock = this->lock,
369 .wrapped = this->child_cfgs->create_enumerator(this->child_cfgs),
370 );
371
372 this->lock->read_lock(this->lock);
373 return &enumerator->public;
374 }
375
376 /**
377 * Check how good a list of TS matches a given child config
378 */
379 static int get_ts_match(child_cfg_t *cfg, bool local,
380 linked_list_t *sup_list, linked_list_t *hosts)
381 {
382 linked_list_t *cfg_list;
383 enumerator_t *sup_enum, *cfg_enum;
384 traffic_selector_t *sup_ts, *cfg_ts, *subset;
385 int match = 0, round;
386
387 /* fetch configured TS list, narrowing dynamic TS */
388 cfg_list = cfg->get_traffic_selectors(cfg, local, NULL, hosts, TRUE);
389
390 /* use a round counter to rate leading TS with higher priority */
391 round = sup_list->get_count(sup_list);
392
393 sup_enum = sup_list->create_enumerator(sup_list);
394 while (sup_enum->enumerate(sup_enum, &sup_ts))
395 {
396 cfg_enum = cfg_list->create_enumerator(cfg_list);
397 while (cfg_enum->enumerate(cfg_enum, &cfg_ts))
398 {
399 if (cfg_ts->equals(cfg_ts, sup_ts))
400 { /* equality is honored better than matches */
401 match += round * 5;
402 }
403 else
404 {
405 subset = cfg_ts->get_subset(cfg_ts, sup_ts);
406 if (subset)
407 {
408 subset->destroy(subset);
409 match += round * 1;
410 }
411 }
412 }
413 cfg_enum->destroy(cfg_enum);
414 round--;
415 }
416 sup_enum->destroy(sup_enum);
417
418 cfg_list->destroy_offset(cfg_list, offsetof(traffic_selector_t, destroy));
419
420 return match;
421 }
422
423 METHOD(peer_cfg_t, select_child_cfg, child_cfg_t*,
424 private_peer_cfg_t *this, linked_list_t *my_ts, linked_list_t *other_ts,
425 linked_list_t *my_hosts, linked_list_t *other_hosts)
426 {
427 child_cfg_t *current, *found = NULL;
428 enumerator_t *enumerator;
429 int best = 0;
430
431 DBG2(DBG_CFG, "looking for a child config for %#R === %#R", my_ts, other_ts);
432 enumerator = create_child_cfg_enumerator(this);
433 while (enumerator->enumerate(enumerator, &current))
434 {
435 int my_prio, other_prio;
436
437 my_prio = get_ts_match(current, TRUE, my_ts, my_hosts);
438 other_prio = get_ts_match(current, FALSE, other_ts, other_hosts);
439
440 if (my_prio && other_prio)
441 {
442 DBG2(DBG_CFG, " candidate \"%s\" with prio %d+%d",
443 current->get_name(current), my_prio, other_prio);
444 if (my_prio + other_prio > best)
445 {
446 best = my_prio + other_prio;
447 DESTROY_IF(found);
448 found = current->get_ref(current);
449 }
450 }
451 }
452 enumerator->destroy(enumerator);
453 if (found)
454 {
455 DBG2(DBG_CFG, "found matching child config \"%s\" with prio %d",
456 found->get_name(found), best);
457 }
458 return found;
459 }
460
461 METHOD(peer_cfg_t, get_cert_policy, cert_policy_t,
462 private_peer_cfg_t *this)
463 {
464 return this->cert_policy;
465 }
466
467 METHOD(peer_cfg_t, get_unique_policy, unique_policy_t,
468 private_peer_cfg_t *this)
469 {
470 return this->unique;
471 }
472
473 METHOD(peer_cfg_t, get_keyingtries, uint32_t,
474 private_peer_cfg_t *this)
475 {
476 return this->keyingtries;
477 }
478
479 METHOD(peer_cfg_t, get_rekey_time, uint32_t,
480 private_peer_cfg_t *this, bool jitter)
481 {
482 if (this->rekey_time == 0)
483 {
484 return 0;
485 }
486 if (this->jitter_time == 0 || !jitter)
487 {
488 return this->rekey_time;
489 }
490 return this->rekey_time - (random() % this->jitter_time);
491 }
492
493 METHOD(peer_cfg_t, get_reauth_time, uint32_t,
494 private_peer_cfg_t *this, bool jitter)
495 {
496 if (this->reauth_time == 0)
497 {
498 return 0;
499 }
500 if (this->jitter_time == 0 || !jitter)
501 {
502 return this->reauth_time;
503 }
504 return this->reauth_time - (random() % this->jitter_time);
505 }
506
507 METHOD(peer_cfg_t, get_over_time, uint32_t,
508 private_peer_cfg_t *this)
509 {
510 return this->over_time;
511 }
512
513 METHOD(peer_cfg_t, use_mobike, bool,
514 private_peer_cfg_t *this)
515 {
516 return this->use_mobike;
517 }
518
519 METHOD(peer_cfg_t, use_aggressive, bool,
520 private_peer_cfg_t *this)
521 {
522 return this->aggressive;
523 }
524
525 METHOD(peer_cfg_t, use_pull_mode, bool,
526 private_peer_cfg_t *this)
527 {
528 return this->pull_mode;
529 }
530
531 METHOD(peer_cfg_t, get_dpd, uint32_t,
532 private_peer_cfg_t *this)
533 {
534 return this->dpd;
535 }
536
537 METHOD(peer_cfg_t, get_dpd_timeout, uint32_t,
538 private_peer_cfg_t *this)
539 {
540 return this->dpd_timeout;
541 }
542
543 METHOD(peer_cfg_t, add_virtual_ip, void,
544 private_peer_cfg_t *this, host_t *vip)
545 {
546 this->vips->insert_last(this->vips, vip);
547 }
548
549 METHOD(peer_cfg_t, create_virtual_ip_enumerator, enumerator_t*,
550 private_peer_cfg_t *this)
551 {
552 return this->vips->create_enumerator(this->vips);
553 }
554
555 METHOD(peer_cfg_t, add_pool, void,
556 private_peer_cfg_t *this, char *name)
557 {
558 this->pools->insert_last(this->pools, strdup(name));
559 }
560
561 METHOD(peer_cfg_t, create_pool_enumerator, enumerator_t*,
562 private_peer_cfg_t *this)
563 {
564 return this->pools->create_enumerator(this->pools);
565 }
566
567 METHOD(peer_cfg_t, add_auth_cfg, void,
568 private_peer_cfg_t *this, auth_cfg_t *cfg, bool local)
569 {
570 if (local)
571 {
572 this->local_auth->insert_last(this->local_auth, cfg);
573 }
574 else
575 {
576 this->remote_auth->insert_last(this->remote_auth, cfg);
577 }
578 }
579
580 METHOD(peer_cfg_t, create_auth_cfg_enumerator, enumerator_t*,
581 private_peer_cfg_t *this, bool local)
582 {
583 if (local)
584 {
585 return this->local_auth->create_enumerator(this->local_auth);
586 }
587 return this->remote_auth->create_enumerator(this->remote_auth);
588 }
589
590 METHOD(peer_cfg_t, get_ppk_id, identification_t*,
591 private_peer_cfg_t *this)
592 {
593 return this->ppk_id;
594 }
595
596 METHOD(peer_cfg_t, ppk_required, bool,
597 private_peer_cfg_t *this)
598 {
599 return this->ppk_required;
600 }
601
602 #ifdef ME
603 METHOD(peer_cfg_t, is_mediation, bool,
604 private_peer_cfg_t *this)
605 {
606 return this->mediation;
607 }
608
609 METHOD(peer_cfg_t, get_mediated_by, char*,
610 private_peer_cfg_t *this)
611 {
612 return this->mediated_by;
613 }
614
615 METHOD(peer_cfg_t, get_peer_id, identification_t*,
616 private_peer_cfg_t *this)
617 {
618 return this->peer_id;
619 }
620 #endif /* ME */
621
622 /**
623 * check auth configs for equality
624 */
625 static bool auth_cfg_equal(private_peer_cfg_t *this, private_peer_cfg_t *other)
626 {
627 enumerator_t *e1, *e2;
628 auth_cfg_t *cfg1, *cfg2;
629 bool equal = TRUE;
630
631 if (this->local_auth->get_count(this->local_auth) !=
632 other->local_auth->get_count(other->local_auth))
633 {
634 return FALSE;
635 }
636 if (this->remote_auth->get_count(this->remote_auth) !=
637 other->remote_auth->get_count(other->remote_auth))
638 {
639 return FALSE;
640 }
641
642 e1 = this->local_auth->create_enumerator(this->local_auth);
643 e2 = other->local_auth->create_enumerator(other->local_auth);
644 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
645 {
646 if (!cfg1->equals(cfg1, cfg2))
647 {
648 equal = FALSE;
649 break;
650 }
651 }
652 e1->destroy(e1);
653 e2->destroy(e2);
654
655 if (!equal)
656 {
657 return FALSE;
658 }
659
660 e1 = this->remote_auth->create_enumerator(this->remote_auth);
661 e2 = other->remote_auth->create_enumerator(other->remote_auth);
662 while (e1->enumerate(e1, &cfg1) && e2->enumerate(e2, &cfg2))
663 {
664 if (!cfg1->equals(cfg1, cfg2))
665 {
666 equal = FALSE;
667 break;
668 }
669 }
670 e1->destroy(e1);
671 e2->destroy(e2);
672
673 return equal;
674 }
675
676 /**
677 * Check if two identities are equal, or both are not set
678 */
679 static bool id_equal(identification_t *this, identification_t *other)
680 {
681 return this == other || (this && other && this->equals(this, other));
682 }
683
684 METHOD(peer_cfg_t, equals, bool,
685 private_peer_cfg_t *this, private_peer_cfg_t *other)
686 {
687 if (this == other)
688 {
689 return TRUE;
690 }
691 if (this->public.equals != other->public.equals)
692 {
693 return FALSE;
694 }
695 if (!this->vips->equals_offset(this->vips, other->vips,
696 offsetof(host_t, ip_equals)))
697 {
698 return FALSE;
699 }
700 if (!this->pools->equals_function(this->pools, other->pools, (void*)streq))
701 {
702 return FALSE;
703 }
704 return (
705 get_ike_version(this) == get_ike_version(other) &&
706 this->cert_policy == other->cert_policy &&
707 this->unique == other->unique &&
708 this->keyingtries == other->keyingtries &&
709 this->use_mobike == other->use_mobike &&
710 this->rekey_time == other->rekey_time &&
711 this->reauth_time == other->reauth_time &&
712 this->jitter_time == other->jitter_time &&
713 this->over_time == other->over_time &&
714 this->dpd == other->dpd &&
715 this->aggressive == other->aggressive &&
716 this->pull_mode == other->pull_mode &&
717 auth_cfg_equal(this, other) &&
718 this->ppk_required == other->ppk_required &&
719 id_equal(this->ppk_id, other->ppk_id)
720 #ifdef ME
721 && this->mediation == other->mediation &&
722 streq(this->mediated_by, other->mediated_by) &&
723 id_equal(this->peer_id, other->peer_id)
724 #endif /* ME */
725 );
726 }
727
728 METHOD(peer_cfg_t, get_ref, peer_cfg_t*,
729 private_peer_cfg_t *this)
730 {
731 ref_get(&this->refcount);
732 return &this->public;
733 }
734
735 METHOD(peer_cfg_t, destroy, void,
736 private_peer_cfg_t *this)
737 {
738 if (ref_put(&this->refcount))
739 {
740 this->ike_cfg->destroy(this->ike_cfg);
741 this->child_cfgs->destroy_offset(this->child_cfgs,
742 offsetof(child_cfg_t, destroy));
743 this->local_auth->destroy_offset(this->local_auth,
744 offsetof(auth_cfg_t, destroy));
745 this->remote_auth->destroy_offset(this->remote_auth,
746 offsetof(auth_cfg_t, destroy));
747 this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
748 this->pools->destroy_function(this->pools, free);
749 #ifdef ME
750 DESTROY_IF(this->peer_id);
751 free(this->mediated_by);
752 #endif /* ME */
753 DESTROY_IF(this->ppk_id);
754 this->lock->destroy(this->lock);
755 free(this->name);
756 free(this);
757 }
758 }
759
760 /*
761 * Described in header-file
762 */
763 peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
764 peer_cfg_create_t *data)
765 {
766 private_peer_cfg_t *this;
767
768 if (data->rekey_time && data->jitter_time > data->rekey_time)
769 {
770 data->jitter_time = data->rekey_time;
771 }
772 if (data->reauth_time && data->jitter_time > data->reauth_time)
773 {
774 data->jitter_time = data->reauth_time;
775 }
776 if (data->dpd && data->dpd_timeout && data->dpd > data->dpd_timeout)
777 {
778 data->dpd_timeout = data->dpd;
779 }
780
781 INIT(this,
782 .public = {
783 .get_name = _get_name,
784 .get_ike_version = _get_ike_version,
785 .get_ike_cfg = _get_ike_cfg,
786 .add_child_cfg = _add_child_cfg,
787 .remove_child_cfg = (void*)_remove_child_cfg,
788 .replace_child_cfgs = _replace_child_cfgs,
789 .create_child_cfg_enumerator = _create_child_cfg_enumerator,
790 .select_child_cfg = _select_child_cfg,
791 .get_cert_policy = _get_cert_policy,
792 .get_unique_policy = _get_unique_policy,
793 .get_keyingtries = _get_keyingtries,
794 .get_rekey_time = _get_rekey_time,
795 .get_reauth_time = _get_reauth_time,
796 .get_over_time = _get_over_time,
797 .use_mobike = _use_mobike,
798 .use_aggressive = _use_aggressive,
799 .use_pull_mode = _use_pull_mode,
800 .get_dpd = _get_dpd,
801 .get_dpd_timeout = _get_dpd_timeout,
802 .add_virtual_ip = _add_virtual_ip,
803 .create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
804 .add_pool = _add_pool,
805 .create_pool_enumerator = _create_pool_enumerator,
806 .add_auth_cfg = _add_auth_cfg,
807 .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
808 .get_ppk_id = _get_ppk_id,
809 .ppk_required = _ppk_required,
810 .equals = (void*)_equals,
811 .get_ref = _get_ref,
812 .destroy = _destroy,
813 #ifdef ME
814 .is_mediation = _is_mediation,
815 .get_mediated_by = _get_mediated_by,
816 .get_peer_id = _get_peer_id,
817 #endif /* ME */
818 },
819 .name = strdup(name),
820 .ike_cfg = ike_cfg,
821 .child_cfgs = linked_list_create(),
822 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
823 .cert_policy = data->cert_policy,
824 .unique = data->unique,
825 .keyingtries = data->keyingtries,
826 .rekey_time = data->rekey_time,
827 .reauth_time = data->reauth_time,
828 .jitter_time = data->jitter_time,
829 .over_time = data->over_time,
830 .use_mobike = !data->no_mobike,
831 .aggressive = data->aggressive,
832 .pull_mode = !data->push_mode,
833 .dpd = data->dpd,
834 .dpd_timeout = data->dpd_timeout,
835 .ppk_id = data->ppk_id,
836 .ppk_required = data->ppk_required,
837 .vips = linked_list_create(),
838 .pools = linked_list_create(),
839 .local_auth = linked_list_create(),
840 .remote_auth = linked_list_create(),
841 .refcount = 1,
842 #ifdef ME
843 .mediation = data->mediation,
844 .mediated_by = strdupnull(data->mediated_by),
845 .peer_id = data->peer_id,
846 #endif /* ME */
847 );
848
849 return &this->public;
850 }