2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
5 * Copyright (C) 2015-2019 Tobias Brunner
6 * Copyright (C) 2015-2018 Andreas Steffen
7 * HSR Hochschule fuer Technik Rapperswil
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44 #include "vici_config.h"
45 #include "vici_builder.h"
48 #include <threading/rwlock.h>
49 #include <threading/rwlock_condvar.h>
50 #include <collections/array.h>
51 #include <collections/linked_list.h>
53 #include <pubkey_cert.h>
58 * Magic value for an undefined lifetime
60 #define LFT_UNDEFINED (~(uint64_t)0)
63 * Default IKE rekey time
65 #define LFT_DEFAULT_IKE_REKEY_TIME (4 * 60 * 60)
68 * Default CHILD rekey time
70 #define LFT_DEFAULT_CHILD_REKEY_TIME (1 * 60 * 60)
73 * Default CHILD rekey bytes
75 #define LFT_DEFAULT_CHILD_REKEY_BYTES 0
78 * Default CHILD rekey packets
80 #define LFT_DEFAULT_CHILD_REKEY_PACKETS 0
83 * Undefined replay window
85 #define REPLAY_UNDEFINED (~(uint32_t)0)
87 typedef struct private_vici_config_t private_vici_config_t
;
90 * Private data of an vici_config_t object.
92 struct private_vici_config_t
{
95 * Public vici_config_t interface.
102 vici_dispatcher_t
*dispatcher
;
105 * List of loaded connections, as peer_cfg_t
107 linked_list_t
*conns
;
110 * Lock for conns list
115 * Condvar used to sync running actions
117 rwlock_condvar_t
*condvar
;
120 * True while we run or undo a start action
122 bool handling_actions
;
125 * Credential backend managed by VICI used for our certificates
130 * Auxiliary certification authority information
132 vici_authority_t
*authority
;
136 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
137 private_vici_config_t
*this, identification_t
*me
, identification_t
*other
)
139 this->lock
->read_lock(this->lock
);
140 return enumerator_create_cleaner(this->conns
->create_enumerator(this->conns
),
141 (void*)this->lock
->unlock
, this->lock
);
144 CALLBACK(ike_filter
, bool,
145 void *data
, enumerator_t
*orig
, va_list args
)
150 VA_ARGS_VGET(args
, out
);
152 if (orig
->enumerate(orig
, &cfg
))
154 *out
= cfg
->get_ike_cfg(cfg
);
160 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
161 private_vici_config_t
*this, host_t
*me
, host_t
*other
)
163 this->lock
->read_lock(this->lock
);
164 return enumerator_create_filter(this->conns
->create_enumerator(this->conns
),
165 ike_filter
, this->lock
,
166 (void*)this->lock
->unlock
);
169 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
170 private_vici_config_t
*this, char *name
)
172 peer_cfg_t
*current
, *found
= NULL
;
173 enumerator_t
*enumerator
;
175 this->lock
->read_lock(this->lock
);
176 enumerator
= this->conns
->create_enumerator(this->conns
);
177 while (enumerator
->enumerate(enumerator
, ¤t
))
179 if (streq(current
->get_name(current
), name
))
182 found
->get_ref(found
);
186 enumerator
->destroy(enumerator
);
187 this->lock
->unlock(this->lock
);
193 * Create a (error) reply message
195 static vici_message_t
* create_reply(char *fmt
, ...)
197 vici_builder_t
*builder
;
200 builder
= vici_builder_create();
201 builder
->add_kv(builder
, "success", fmt
? "no" : "yes");
205 builder
->vadd_kv(builder
, "errmsg", fmt
, args
);
208 return builder
->finalize(builder
);
212 * A rule to parse a key/value or list item
215 /** name of the key/value or list */
217 /** function to parse value */
218 bool (*parse
)(void *out
, chunk_t value
);
219 /** result, passed to parse() */
224 * Parse key/values using a rule-set
226 static bool parse_rules(parse_rule_t
*rules
, int count
, char *name
,
227 chunk_t value
, vici_message_t
**reply
)
231 for (i
= 0; i
< count
; i
++)
233 if (streq(name
, rules
[i
].name
))
235 if (rules
[i
].parse(rules
[i
].out
, value
))
239 *reply
= create_reply("invalid value for: %s, config discarded",
244 *reply
= create_reply("unknown option: %s, config discarded", name
);
249 * Parse callback data, passed to each callback
252 private_vici_config_t
*this;
253 vici_message_t
*reply
;
260 request_data_t
*request
;
268 * Clean up certificate data
270 static void free_cert_data(cert_data_t
*data
)
282 request_data_t
*request
;
288 * Clean up auth config data
290 static void free_auth_data(auth_data_t
*data
)
292 DESTROY_IF(data
->cfg
);
297 * Data associated to a peer config
300 request_data_t
*request
;
307 identification_t
*ppk_id
;
309 cert_policy_t send_cert
;
311 uint64_t dpd_timeout
;
312 fragmentation_t fragmentation
;
313 unique_policy_t unique
;
314 uint32_t keyingtries
;
316 uint32_t remote_port
;
319 linked_list_t
*local
;
320 linked_list_t
*remote
;
321 linked_list_t
*proposals
;
322 linked_list_t
*children
;
325 uint64_t reauth_time
;
333 identification_t
*peer_id
;
338 * Log relevant auth config data
340 static void log_auth(auth_cfg_t
*auth
)
342 enumerator_t
*enumerator
;
346 identification_t
*id
;
350 enumerator
= auth
->create_enumerator(auth
);
351 while (enumerator
->enumerate(enumerator
, &rule
, &v
))
355 case AUTH_RULE_AUTH_CLASS
:
356 DBG2(DBG_CFG
, " class = %N", auth_class_names
, v
.u
);
358 case AUTH_RULE_EAP_TYPE
:
359 DBG2(DBG_CFG
, " eap-type = %N", eap_type_names
, v
.u
);
361 case AUTH_RULE_EAP_VENDOR
:
362 DBG2(DBG_CFG
, " eap-vendor = %u", v
.u
);
364 case AUTH_RULE_XAUTH_BACKEND
:
365 DBG2(DBG_CFG
, " xauth = %s", v
.str
);
367 case AUTH_RULE_CRL_VALIDATION
:
368 DBG2(DBG_CFG
, " revocation = %N", cert_validation_names
, v
.u
);
370 case AUTH_RULE_IDENTITY
:
371 DBG2(DBG_CFG
, " id = %Y", v
.id
);
373 case AUTH_RULE_AAA_IDENTITY
:
374 DBG2(DBG_CFG
, " aaa_id = %Y", v
.id
);
376 case AUTH_RULE_EAP_IDENTITY
:
377 DBG2(DBG_CFG
, " eap_id = %Y", v
.id
);
379 case AUTH_RULE_XAUTH_IDENTITY
:
380 DBG2(DBG_CFG
, " xauth_id = %Y", v
.id
);
382 case AUTH_RULE_GROUP
:
383 DBG2(DBG_CFG
, " group = %Y", v
.id
);
389 enumerator
->destroy(enumerator
);
393 * Log parsed peer data
395 static void log_peer_data(peer_data_t
*data
)
397 enumerator_t
*enumerator
;
401 DBG2(DBG_CFG
, " version = %u", data
->version
);
402 DBG2(DBG_CFG
, " local_addrs = %s", data
->local_addrs
);
403 DBG2(DBG_CFG
, " remote_addrs = %s", data
->remote_addrs
);
404 DBG2(DBG_CFG
, " local_port = %u", data
->local_port
);
405 DBG2(DBG_CFG
, " remote_port = %u", data
->remote_port
);
406 DBG2(DBG_CFG
, " send_certreq = %u", data
->send_certreq
);
407 DBG2(DBG_CFG
, " send_cert = %N", cert_policy_names
, data
->send_cert
);
408 DBG2(DBG_CFG
, " ppk_id = %Y", data
->ppk_id
);
409 DBG2(DBG_CFG
, " ppk_required = %u", data
->ppk_required
);
410 DBG2(DBG_CFG
, " mobike = %u", data
->mobike
);
411 DBG2(DBG_CFG
, " aggressive = %u", data
->aggressive
);
412 DBG2(DBG_CFG
, " dscp = 0x%.2x", data
->dscp
);
413 DBG2(DBG_CFG
, " encap = %u", data
->encap
);
414 DBG2(DBG_CFG
, " dpd_delay = %llu", data
->dpd_delay
);
415 DBG2(DBG_CFG
, " dpd_timeout = %llu", data
->dpd_timeout
);
416 DBG2(DBG_CFG
, " fragmentation = %u", data
->fragmentation
);
417 DBG2(DBG_CFG
, " unique = %N", unique_policy_names
, data
->unique
);
418 DBG2(DBG_CFG
, " keyingtries = %u", data
->keyingtries
);
419 DBG2(DBG_CFG
, " reauth_time = %llu", data
->reauth_time
);
420 DBG2(DBG_CFG
, " rekey_time = %llu", data
->rekey_time
);
421 DBG2(DBG_CFG
, " over_time = %llu", data
->over_time
);
422 DBG2(DBG_CFG
, " rand_time = %llu", data
->rand_time
);
423 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
425 DBG2(DBG_CFG
, " mediation = %u", data
->mediation
);
426 if (data
->mediated_by
)
428 DBG2(DBG_CFG
, " mediated_by = %s", data
->mediated_by
);
429 DBG2(DBG_CFG
, " mediation_peer = %Y", data
->peer_id
);
433 if (data
->vips
->get_count(data
->vips
))
435 DBG2(DBG_CFG
, " vips:");
437 enumerator
= data
->vips
->create_enumerator(data
->vips
);
438 while (enumerator
->enumerate(enumerator
, &host
))
440 DBG2(DBG_CFG
, " %H", host
);
442 enumerator
->destroy(enumerator
);
444 enumerator
= data
->local
->create_enumerator(data
->local
);
445 while (enumerator
->enumerate(enumerator
, &auth
))
447 DBG2(DBG_CFG
, " local:");
450 enumerator
->destroy(enumerator
);
452 enumerator
= data
->remote
->create_enumerator(data
->remote
);
453 while (enumerator
->enumerate(enumerator
, &auth
))
455 DBG2(DBG_CFG
, " remote:");
458 enumerator
->destroy(enumerator
);
462 * Clean up peer config data
464 static void free_peer_data(peer_data_t
*data
)
466 data
->local
->destroy_function(data
->local
, (void*)free_auth_data
);
467 data
->remote
->destroy_function(data
->remote
, (void*)free_auth_data
);
468 data
->children
->destroy_offset(data
->children
,
469 offsetof(child_cfg_t
, destroy
));
470 data
->proposals
->destroy_offset(data
->proposals
,
471 offsetof(proposal_t
, destroy
));
472 data
->vips
->destroy_offset(data
->vips
, offsetof(host_t
, destroy
));
474 free(data
->local_addrs
);
475 free(data
->remote_addrs
);
476 DESTROY_IF(data
->ppk_id
);
478 free(data
->mediated_by
);
479 DESTROY_IF(data
->peer_id
);
487 request_data_t
*request
;
488 linked_list_t
*proposals
;
489 linked_list_t
*local_ts
;
490 linked_list_t
*remote_ts
;
491 uint32_t replay_window
;
492 child_cfg_create_t cfg
;
496 * Log parsed CHILD config data
498 static void log_child_data(child_data_t
*data
, char *name
)
500 child_cfg_create_t
*cfg
= &data
->cfg
;
502 #define has_opt(opt) ({ (cfg->options & (opt)) == (opt); })
503 DBG2(DBG_CFG
, " child %s:", name
);
504 DBG2(DBG_CFG
, " rekey_time = %llu", cfg
->lifetime
.time
.rekey
);
505 DBG2(DBG_CFG
, " life_time = %llu", cfg
->lifetime
.time
.life
);
506 DBG2(DBG_CFG
, " rand_time = %llu", cfg
->lifetime
.time
.jitter
);
507 DBG2(DBG_CFG
, " rekey_bytes = %llu", cfg
->lifetime
.bytes
.rekey
);
508 DBG2(DBG_CFG
, " life_bytes = %llu", cfg
->lifetime
.bytes
.life
);
509 DBG2(DBG_CFG
, " rand_bytes = %llu", cfg
->lifetime
.bytes
.jitter
);
510 DBG2(DBG_CFG
, " rekey_packets = %llu", cfg
->lifetime
.packets
.rekey
);
511 DBG2(DBG_CFG
, " life_packets = %llu", cfg
->lifetime
.packets
.life
);
512 DBG2(DBG_CFG
, " rand_packets = %llu", cfg
->lifetime
.packets
.jitter
);
513 DBG2(DBG_CFG
, " updown = %s", cfg
->updown
);
514 DBG2(DBG_CFG
, " hostaccess = %u", has_opt(OPT_HOSTACCESS
));
515 DBG2(DBG_CFG
, " ipcomp = %u", has_opt(OPT_IPCOMP
));
516 DBG2(DBG_CFG
, " mode = %N%s", ipsec_mode_names
, cfg
->mode
,
517 has_opt(OPT_PROXY_MODE
) ? "_PROXY" : "");
518 DBG2(DBG_CFG
, " policies = %u", !has_opt(OPT_NO_POLICIES
));
519 DBG2(DBG_CFG
, " policies_fwd_out = %u", has_opt(OPT_FWD_OUT_POLICIES
));
520 if (data
->replay_window
!= REPLAY_UNDEFINED
)
522 DBG2(DBG_CFG
, " replay_window = %u", data
->replay_window
);
524 DBG2(DBG_CFG
, " dpd_action = %N", action_names
, cfg
->dpd_action
);
525 DBG2(DBG_CFG
, " start_action = %N", action_names
, cfg
->start_action
);
526 DBG2(DBG_CFG
, " close_action = %N", action_names
, cfg
->close_action
);
527 DBG2(DBG_CFG
, " reqid = %u", cfg
->reqid
);
528 DBG2(DBG_CFG
, " tfc = %d", cfg
->tfc
);
529 DBG2(DBG_CFG
, " priority = %d", cfg
->priority
);
530 DBG2(DBG_CFG
, " interface = %s", cfg
->interface
);
531 DBG2(DBG_CFG
, " mark_in = %u/%u",
532 cfg
->mark_in
.value
, cfg
->mark_in
.mask
);
533 DBG2(DBG_CFG
, " mark_in_sa = %u", has_opt(OPT_MARK_IN_SA
));
534 DBG2(DBG_CFG
, " mark_out = %u/%u",
535 cfg
->mark_out
.value
, cfg
->mark_out
.mask
);
536 DBG2(DBG_CFG
, " set_mark_in = %u/%u",
537 cfg
->set_mark_in
.value
, cfg
->set_mark_in
.mask
);
538 DBG2(DBG_CFG
, " set_mark_out = %u/%u",
539 cfg
->set_mark_out
.value
, cfg
->set_mark_out
.mask
);
540 DBG2(DBG_CFG
, " inactivity = %llu", cfg
->inactivity
);
541 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
542 DBG2(DBG_CFG
, " local_ts = %#R", data
->local_ts
);
543 DBG2(DBG_CFG
, " remote_ts = %#R", data
->remote_ts
);
544 DBG2(DBG_CFG
, " hw_offload = %N", hw_offload_names
, cfg
->hw_offload
);
545 DBG2(DBG_CFG
, " sha256_96 = %u", has_opt(OPT_SHA256_96
));
546 DBG2(DBG_CFG
, " copy_df = %u", !has_opt(OPT_NO_COPY_DF
));
547 DBG2(DBG_CFG
, " copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN
));
548 DBG2(DBG_CFG
, " copy_dscp = %N", dscp_copy_names
, cfg
->copy_dscp
);
552 * Clean up CHILD config data
554 static void free_child_data(child_data_t
*data
)
556 data
->proposals
->destroy_offset(data
->proposals
,
557 offsetof(proposal_t
, destroy
));
558 data
->local_ts
->destroy_offset(data
->local_ts
,
559 offsetof(traffic_selector_t
, destroy
));
560 data
->remote_ts
->destroy_offset(data
->remote_ts
,
561 offsetof(traffic_selector_t
, destroy
));
562 free(data
->cfg
.updown
);
563 free(data
->cfg
.interface
);
567 * Common proposal parsing
569 static bool parse_proposal(linked_list_t
*list
, protocol_id_t proto
, chunk_t v
)
572 proposal_t
*proposal
;
574 if (!vici_stringify(v
, buf
, sizeof(buf
)))
578 if (strcaseeq("default", buf
))
580 proposal
= proposal_create_default(proto
);
583 list
->insert_last(list
, proposal
);
585 proposal
= proposal_create_default_aead(proto
);
588 list
->insert_last(list
, proposal
);
592 proposal
= proposal_create_from_string(proto
, buf
);
595 list
->insert_last(list
, proposal
);
604 CALLBACK(parse_ike_proposal
, bool,
605 linked_list_t
*out
, chunk_t v
)
607 return parse_proposal(out
, PROTO_IKE
, v
);
613 CALLBACK(parse_esp_proposal
, bool,
614 linked_list_t
*out
, chunk_t v
)
616 return parse_proposal(out
, PROTO_ESP
, v
);
622 CALLBACK(parse_ah_proposal
, bool,
623 linked_list_t
*out
, chunk_t v
)
625 return parse_proposal(out
, PROTO_AH
, v
);
629 * Parse a traffic selector
631 CALLBACK(parse_ts
, bool,
632 linked_list_t
*out
, chunk_t v
)
634 char buf
[BUF_LEN
], *protoport
, *sep
, *port
= "", *end
;
635 traffic_selector_t
*ts
= NULL
;
636 struct protoent
*protoent
;
639 uint16_t from
= 0, to
= 0xffff;
642 if (!vici_stringify(v
, buf
, sizeof(buf
)))
647 protoport
= strchr(buf
, '[');
650 *(protoport
++) = '\0';
652 sep
= strrchr(protoport
, ']');
659 sep
= strchr(protoport
, '/');
661 { /* protocol/port */
666 if (streq(protoport
, "any"))
672 protoent
= getprotobyname(protoport
);
675 proto
= protoent
->p_proto
;
679 p
= strtol(protoport
, &end
, 0);
680 if ((*protoport
&& *end
) || p
< 0 || p
> 0xff)
687 if (streq(port
, "opaque"))
692 else if (*port
&& !streq(port
, "any"))
694 svc
= getservbyname(port
, NULL
);
697 from
= to
= ntohs(svc
->s_port
);
701 p
= strtol(port
, &end
, 0);
702 if (p
< 0 || p
> 0xffff)
710 p
= strtol(port
, &end
, 0);
711 if (p
< 0 || p
> 0xffff)
724 if (streq(buf
, "dynamic"))
726 ts
= traffic_selector_create_dynamic(proto
, from
, to
);
728 else if (strchr(buf
, '-'))
730 host_t
*lower
, *upper
;
733 if (host_create_from_range(buf
, &lower
, &upper
))
735 type
= (lower
->get_family(lower
) == AF_INET
) ?
736 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
;
737 ts
= traffic_selector_create_from_bytes(proto
, type
,
738 lower
->get_address(lower
), from
,
739 upper
->get_address(upper
), to
);
740 lower
->destroy(lower
);
741 upper
->destroy(upper
);
746 ts
= traffic_selector_create_from_cidr(buf
, proto
, from
, to
);
752 out
->insert_last(out
, ts
);
759 CALLBACK(parse_string
, bool,
760 char **out
, chunk_t v
)
762 if (!chunk_printable(v
, NULL
, ' '))
768 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
776 * Map a string to an integer
784 * Parse a string to an integer mapping
786 static bool parse_map(enum_map_t
*map
, int count
, int *out
, chunk_t v
)
791 if (!vici_stringify(v
, buf
, sizeof(buf
)))
795 for (i
= 0; i
< count
; i
++)
797 if (strcaseeq(map
[i
].str
, buf
))
809 CALLBACK(parse_bool
, bool,
810 bool *out
, chunk_t v
)
819 { "disabled", FALSE
},
824 if (parse_map(map
, countof(map
), &d
, v
))
833 * Parse a ipsec_mode_t
835 CALLBACK(parse_mode
, bool,
836 child_cfg_create_t
*cfg
, chunk_t v
)
839 { "tunnel", MODE_TUNNEL
},
840 { "transport", MODE_TRANSPORT
},
841 { "transport_proxy", MODE_TRANSPORT
},
842 { "beet", MODE_BEET
},
843 { "drop", MODE_DROP
},
844 { "pass", MODE_PASS
},
848 if (parse_map(map
, countof(map
), &d
, v
))
851 if ((d
== MODE_TRANSPORT
) && (v
.len
> 9))
853 cfg
->options
|= OPT_PROXY_MODE
;
861 * Enable a child_cfg_option_t, the flag controls whether the option is enabled
862 * if the parsed value is TRUE or FALSE.
864 static bool parse_option(child_cfg_option_t
*out
, child_cfg_option_t opt
,
865 chunk_t v
, bool add_if_true
)
869 if (parse_bool(&val
, v
))
871 if (val
== add_if_true
)
881 * Parse OPT_HOSTACCESS option
883 CALLBACK(parse_opt_haccess
, bool,
884 child_cfg_option_t
*out
, chunk_t v
)
886 return parse_option(out
, OPT_HOSTACCESS
, v
, TRUE
);
890 * Parse OPT_NO_POLICIES option
892 CALLBACK(parse_opt_policies
, bool,
893 child_cfg_option_t
*out
, chunk_t v
)
895 return parse_option(out
, OPT_NO_POLICIES
, v
, FALSE
);
899 * Parse OPT_FWD_OUT_POLICIES option
901 CALLBACK(parse_opt_fwd_out
, bool,
902 child_cfg_option_t
*out
, chunk_t v
)
904 return parse_option(out
, OPT_FWD_OUT_POLICIES
, v
, TRUE
);
908 * Parse OPT_IPCOMP option
910 CALLBACK(parse_opt_ipcomp
, bool,
911 child_cfg_option_t
*out
, chunk_t v
)
913 return parse_option(out
, OPT_IPCOMP
, v
, TRUE
);
917 * Parse OPT_SHA256_96 option
919 CALLBACK(parse_opt_sha256_96
, bool,
920 child_cfg_option_t
*out
, chunk_t v
)
922 return parse_option(out
, OPT_SHA256_96
, v
, TRUE
);
926 * Parse OPT_MARK_IN_SA option
928 CALLBACK(parse_opt_mark_in
, bool,
929 child_cfg_option_t
*out
, chunk_t v
)
931 return parse_option(out
, OPT_MARK_IN_SA
, v
, TRUE
);
935 * Parse OPT_NO_COPY_DF option
937 CALLBACK(parse_opt_copy_df
, bool,
938 child_cfg_option_t
*out
, chunk_t v
)
940 return parse_option(out
, OPT_NO_COPY_DF
, v
, FALSE
);
944 * Parse OPT_NO_COPY_ECN option
946 CALLBACK(parse_opt_copy_ecn
, bool,
947 child_cfg_option_t
*out
, chunk_t v
)
949 return parse_option(out
, OPT_NO_COPY_ECN
, v
, FALSE
);
953 * Parse a dscp_copy_t
955 CALLBACK(parse_copy_dscp
, bool,
956 dscp_copy_t
*out
, chunk_t v
)
959 { "no", DSCP_COPY_NO
},
960 { "in", DSCP_COPY_IN_ONLY
},
961 { "out", DSCP_COPY_OUT_ONLY
},
962 { "yes", DSCP_COPY_YES
},
966 if (parse_map(map
, countof(map
), &d
, v
))
977 CALLBACK(parse_action
, bool,
978 action_t
*out
, chunk_t v
)
981 { "start", ACTION_RESTART
},
982 { "restart", ACTION_RESTART
},
983 { "route", ACTION_ROUTE
},
984 { "trap", ACTION_ROUTE
},
985 { "none", ACTION_NONE
},
986 { "clear", ACTION_NONE
},
990 if (parse_map(map
, countof(map
), &d
, v
))
999 * Parse an hw_offload_t
1001 CALLBACK(parse_hw_offload
, bool,
1002 action_t
*out
, chunk_t v
)
1004 enum_map_t map
[] = {
1005 { "no", HW_OFFLOAD_NO
},
1006 { "yes", HW_OFFLOAD_YES
},
1007 { "auto", HW_OFFLOAD_AUTO
},
1011 if (parse_map(map
, countof(map
), &d
, v
))
1020 * Parse a uint32_t with the given base
1022 static bool parse_uint32_base(uint32_t *out
, chunk_t v
, int base
)
1027 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1031 l
= strtoul(buf
, &end
, base
);
1043 CALLBACK(parse_uint32
, bool,
1044 uint32_t *out
, chunk_t v
)
1046 return parse_uint32_base(out
, v
, 0);
1050 * Parse a uint32_t in binary encoding
1052 CALLBACK(parse_uint32_bin
, bool,
1053 uint32_t *out
, chunk_t v
)
1055 return parse_uint32_base(out
, v
, 2);
1061 CALLBACK(parse_uint64
, bool,
1062 uint64_t *out
, chunk_t v
)
1065 unsigned long long l
;
1067 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1071 l
= strtoull(buf
, &end
, 0);
1081 * Parse a relative time
1083 CALLBACK(parse_time
, bool,
1084 uint64_t *out
, chunk_t v
)
1089 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1094 l
= strtoul(buf
, &end
, 0);
1131 * Parse a relative time (32-bit)
1133 CALLBACK(parse_time32
, bool,
1134 uint32_t *out
, chunk_t v
)
1138 if (parse_time(&time
, v
))
1149 CALLBACK(parse_bytes
, bool,
1150 uint64_t *out
, chunk_t v
)
1153 unsigned long long l
;
1155 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1160 l
= strtoull(buf
, &end
, 0);
1196 CALLBACK(parse_mark
, bool,
1197 mark_t
*out
, chunk_t v
)
1201 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1205 return mark_from_string(buf
, MARK_OP_UNIQUE
, out
);
1209 * Parse a mark_t when using it as set_mark.
1211 CALLBACK(parse_set_mark
, bool,
1212 mark_t
*out
, chunk_t v
)
1216 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1220 return mark_from_string(buf
, MARK_OP_SAME
, out
);
1224 * Parse TFC padding option
1226 CALLBACK(parse_tfc
, bool,
1227 uint32_t *out
, chunk_t v
)
1229 if (chunk_equals(v
, chunk_from_str("mtu")))
1234 return parse_uint32(out
, v
);
1238 * Parse 6-bit DSCP value
1240 CALLBACK(parse_dscp
, bool,
1241 uint8_t *out
, chunk_t v
)
1243 if (parse_uint32_bin(out
, v
))
1252 * Parse authentication config
1254 CALLBACK(parse_auth
, bool,
1255 auth_cfg_t
*cfg
, chunk_t v
)
1258 eap_vendor_type_t
*type
;
1260 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1264 if (strpfx(buf
, "ike:") ||
1265 strpfx(buf
, "pubkey") ||
1266 strpfx(buf
, "rsa") ||
1267 strpfx(buf
, "ecdsa") ||
1268 strpfx(buf
, "bliss"))
1270 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
1271 cfg
->add_pubkey_constraints(cfg
, buf
, TRUE
);
1274 if (strcaseeq(buf
, "psk"))
1276 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
1279 if (strcasepfx(buf
, "xauth"))
1281 pos
= strchr(buf
, '-');
1284 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
1286 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
1289 if (strcasepfx(buf
, "eap"))
1293 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
1295 pos
= strchr(buf
, ':');
1299 cfg
->add_pubkey_constraints(cfg
, pos
+ 1, FALSE
);
1301 type
= eap_vendor_type_from_string(buf
);
1304 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
1307 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
1317 * Parse identity; add as auth rule to config
1319 static bool parse_id(auth_cfg_t
*cfg
, auth_rule_t rule
, chunk_t v
)
1323 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1327 cfg
->add(cfg
, rule
, identification_create_from_string(buf
));
1332 * Parse IKE identity
1334 CALLBACK(parse_ike_id
, bool,
1335 auth_cfg_t
*cfg
, chunk_t v
)
1337 return parse_id(cfg
, AUTH_RULE_IDENTITY
, v
);
1341 * Parse AAA identity
1343 CALLBACK(parse_aaa_id
, bool,
1344 auth_cfg_t
*cfg
, chunk_t v
)
1346 return parse_id(cfg
, AUTH_RULE_AAA_IDENTITY
, v
);
1350 * Parse EAP identity
1352 CALLBACK(parse_eap_id
, bool,
1353 auth_cfg_t
*cfg
, chunk_t v
)
1355 return parse_id(cfg
, AUTH_RULE_EAP_IDENTITY
, v
);
1359 * Parse XAuth identity
1361 CALLBACK(parse_xauth_id
, bool,
1362 auth_cfg_t
*cfg
, chunk_t v
)
1364 return parse_id(cfg
, AUTH_RULE_XAUTH_IDENTITY
, v
);
1368 * Parse group membership
1370 CALLBACK(parse_group
, bool,
1371 auth_cfg_t
*cfg
, chunk_t v
)
1373 return parse_id(cfg
, AUTH_RULE_GROUP
, v
);
1377 * Parse certificate policy
1379 CALLBACK(parse_cert_policy
, bool,
1380 auth_cfg_t
*cfg
, chunk_t v
)
1384 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1388 cfg
->add(cfg
, AUTH_RULE_CERT_POLICY
, strdup(buf
));
1393 * Add a certificate as auth rule to config
1395 static bool add_cert(auth_data_t
*auth
, auth_rule_t rule
, certificate_t
*cert
)
1397 vici_authority_t
*authority
;
1400 if (rule
== AUTH_RULE_SUBJECT_CERT
)
1402 authority
= auth
->request
->this->authority
;
1403 authority
->check_for_hash_and_url(authority
, cert
);
1405 cred
= auth
->request
->this->cred
;
1406 cert
= cred
->add_cert(cred
, cert
);
1407 auth
->cfg
->add(auth
->cfg
, rule
, cert
);
1412 * Parse a certificate; add as auth rule to config
1414 static bool parse_cert(auth_data_t
*auth
, auth_rule_t rule
, chunk_t v
)
1416 certificate_t
*cert
;
1418 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
1419 BUILD_BLOB_PEM
, v
, BUILD_END
);
1422 return add_cert(auth
, rule
, cert
);
1428 * Parse subject certificates
1430 CALLBACK(parse_certs
, bool,
1431 auth_data_t
*auth
, chunk_t v
)
1433 return parse_cert(auth
, AUTH_RULE_SUBJECT_CERT
, v
);
1437 * Parse CA certificates
1439 CALLBACK(parse_cacerts
, bool,
1440 auth_data_t
*auth
, chunk_t v
)
1442 return parse_cert(auth
, AUTH_RULE_CA_CERT
, v
);
1446 * Parse raw public keys
1448 CALLBACK(parse_pubkeys
, bool,
1449 auth_data_t
*auth
, chunk_t v
)
1452 certificate_t
*cert
;
1454 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_TRUSTED_PUBKEY
,
1455 BUILD_BLOB_PEM
, v
, BUILD_END
);
1458 cred
= auth
->request
->this->cred
;
1459 cert
= cred
->add_cert(cred
, cert
);
1460 auth
->cfg
->add(auth
->cfg
, AUTH_RULE_SUBJECT_CERT
, cert
);
1467 * Parse revocation status
1469 CALLBACK(parse_revocation
, bool,
1470 auth_cfg_t
*cfg
, chunk_t v
)
1472 enum_map_t map
[] = {
1473 { "strict", VALIDATION_GOOD
},
1474 { "ifuri", VALIDATION_SKIPPED
},
1475 { "relaxed", VALIDATION_FAILED
},
1479 if (parse_map(map
, countof(map
), &d
, v
))
1481 if (d
!= VALIDATION_FAILED
)
1483 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, d
);
1491 * Parse list items to comma separated strings
1493 CALLBACK(parse_stringlist
, bool,
1494 char **out
, chunk_t v
)
1498 if (!chunk_printable(v
, NULL
, ' '))
1505 if (asprintf(out
, "%s, %.*s", current
, (int)v
.len
, v
.ptr
) == -1)
1513 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
1522 * Parse an fragmentation_t
1524 CALLBACK(parse_frag
, bool,
1525 fragmentation_t
*out
, chunk_t v
)
1527 enum_map_t map
[] = {
1528 { "yes", FRAGMENTATION_YES
},
1529 { "accept", FRAGMENTATION_ACCEPT
},
1530 { "no", FRAGMENTATION_NO
},
1531 { "force", FRAGMENTATION_FORCE
},
1535 if (parse_map(map
, countof(map
), &d
, v
))
1544 * Parse a cert_policy_t
1546 CALLBACK(parse_send_cert
, bool,
1547 cert_policy_t
*out
, chunk_t v
)
1549 enum_map_t map
[] = {
1550 { "ifasked", CERT_SEND_IF_ASKED
},
1551 { "always", CERT_ALWAYS_SEND
},
1552 { "never", CERT_NEVER_SEND
},
1556 if (parse_map(map
, countof(map
), &d
, v
))
1565 * Parse a unique_policy_t
1567 CALLBACK(parse_unique
, bool,
1568 unique_policy_t
*out
, chunk_t v
)
1570 enum_map_t map
[] = {
1571 { "never", UNIQUE_NEVER
},
1572 { "no", UNIQUE_NO
},
1573 { "replace", UNIQUE_REPLACE
},
1574 { "keep", UNIQUE_KEEP
},
1578 if (parse_map(map
, countof(map
), &d
, v
))
1587 * Parse host_t into a list
1589 CALLBACK(parse_hosts
, bool,
1590 linked_list_t
*list
, chunk_t v
)
1595 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1599 host
= host_create_from_string(buf
, 0);
1604 list
->insert_last(list
, host
);
1611 CALLBACK(parse_peer_id
, bool,
1612 identification_t
**out
, chunk_t v
)
1616 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1620 *out
= identification_create_from_string(buf
);
1625 CALLBACK(cert_kv
, bool,
1626 cert_data_t
*cert
, vici_message_t
*message
, char *name
, chunk_t value
)
1628 parse_rule_t rules
[] = {
1629 { "handle", parse_string
, &cert
->handle
},
1630 { "slot", parse_uint32
, &cert
->slot
},
1631 { "module", parse_string
, &cert
->module
},
1632 { "file", parse_string
, &cert
->file
},
1635 return parse_rules(rules
, countof(rules
), name
, value
,
1636 &cert
->request
->reply
);
1639 CALLBACK(child_li
, bool,
1640 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1642 parse_rule_t rules
[] = {
1643 { "ah_proposals", parse_ah_proposal
, child
->proposals
},
1644 { "esp_proposals", parse_esp_proposal
, child
->proposals
},
1645 { "local_ts", parse_ts
, child
->local_ts
},
1646 { "remote_ts", parse_ts
, child
->remote_ts
},
1649 return parse_rules(rules
, countof(rules
), name
, value
,
1650 &child
->request
->reply
);
1653 CALLBACK(child_kv
, bool,
1654 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1656 parse_rule_t rules
[] = {
1657 { "updown", parse_string
, &child
->cfg
.updown
},
1658 { "hostaccess", parse_opt_haccess
, &child
->cfg
.options
},
1659 { "mode", parse_mode
, &child
->cfg
},
1660 { "policies", parse_opt_policies
, &child
->cfg
.options
},
1661 { "policies_fwd_out", parse_opt_fwd_out
, &child
->cfg
.options
},
1662 { "replay_window", parse_uint32
, &child
->replay_window
},
1663 { "rekey_time", parse_time
, &child
->cfg
.lifetime
.time
.rekey
},
1664 { "life_time", parse_time
, &child
->cfg
.lifetime
.time
.life
},
1665 { "rand_time", parse_time
, &child
->cfg
.lifetime
.time
.jitter
},
1666 { "rekey_bytes", parse_bytes
, &child
->cfg
.lifetime
.bytes
.rekey
},
1667 { "life_bytes", parse_bytes
, &child
->cfg
.lifetime
.bytes
.life
},
1668 { "rand_bytes", parse_bytes
, &child
->cfg
.lifetime
.bytes
.jitter
},
1669 { "rekey_packets", parse_uint64
, &child
->cfg
.lifetime
.packets
.rekey
},
1670 { "life_packets", parse_uint64
, &child
->cfg
.lifetime
.packets
.life
},
1671 { "rand_packets", parse_uint64
, &child
->cfg
.lifetime
.packets
.jitter
},
1672 { "dpd_action", parse_action
, &child
->cfg
.dpd_action
},
1673 { "start_action", parse_action
, &child
->cfg
.start_action
},
1674 { "close_action", parse_action
, &child
->cfg
.close_action
},
1675 { "ipcomp", parse_opt_ipcomp
, &child
->cfg
.options
},
1676 { "inactivity", parse_time32
, &child
->cfg
.inactivity
},
1677 { "reqid", parse_uint32
, &child
->cfg
.reqid
},
1678 { "mark_in", parse_mark
, &child
->cfg
.mark_in
},
1679 { "mark_in_sa", parse_opt_mark_in
, &child
->cfg
.options
},
1680 { "mark_out", parse_mark
, &child
->cfg
.mark_out
},
1681 { "set_mark_in", parse_set_mark
, &child
->cfg
.set_mark_in
},
1682 { "set_mark_out", parse_set_mark
, &child
->cfg
.set_mark_out
},
1683 { "tfc_padding", parse_tfc
, &child
->cfg
.tfc
},
1684 { "priority", parse_uint32
, &child
->cfg
.priority
},
1685 { "interface", parse_string
, &child
->cfg
.interface
},
1686 { "hw_offload", parse_hw_offload
, &child
->cfg
.hw_offload
},
1687 { "sha256_96", parse_opt_sha256_96
,&child
->cfg
.options
},
1688 { "copy_df", parse_opt_copy_df
, &child
->cfg
.options
},
1689 { "copy_ecn", parse_opt_copy_ecn
, &child
->cfg
.options
},
1690 { "copy_dscp", parse_copy_dscp
, &child
->cfg
.copy_dscp
},
1693 return parse_rules(rules
, countof(rules
), name
, value
,
1694 &child
->request
->reply
);
1697 CALLBACK(auth_li
, bool,
1698 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1700 parse_rule_t rules
[] = {
1701 { "groups", parse_group
, auth
->cfg
},
1702 { "cert_policy", parse_cert_policy
, auth
->cfg
},
1703 { "certs", parse_certs
, auth
},
1704 { "cacerts", parse_cacerts
, auth
},
1705 { "pubkeys", parse_pubkeys
, auth
},
1708 return parse_rules(rules
, countof(rules
), name
, value
,
1709 &auth
->request
->reply
);
1712 CALLBACK(auth_kv
, bool,
1713 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1715 parse_rule_t rules
[] = {
1716 { "auth", parse_auth
, auth
->cfg
},
1717 { "id", parse_ike_id
, auth
->cfg
},
1718 { "aaa_id", parse_aaa_id
, auth
->cfg
},
1719 { "eap_id", parse_eap_id
, auth
->cfg
},
1720 { "xauth_id", parse_xauth_id
, auth
->cfg
},
1721 { "revocation", parse_revocation
, auth
->cfg
},
1722 { "round", parse_uint32
, &auth
->round
},
1725 return parse_rules(rules
, countof(rules
), name
, value
,
1726 &auth
->request
->reply
);
1729 CALLBACK(peer_li
, bool,
1730 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1732 parse_rule_t rules
[] = {
1733 { "local_addrs", parse_stringlist
, &peer
->local_addrs
},
1734 { "remote_addrs", parse_stringlist
, &peer
->remote_addrs
},
1735 { "proposals", parse_ike_proposal
, peer
->proposals
},
1736 { "vips", parse_hosts
, peer
->vips
},
1737 { "pools", parse_stringlist
, &peer
->pools
},
1740 return parse_rules(rules
, countof(rules
), name
, value
,
1741 &peer
->request
->reply
);
1744 CALLBACK(peer_kv
, bool,
1745 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1747 parse_rule_t rules
[] = {
1748 { "version", parse_uint32
, &peer
->version
},
1749 { "aggressive", parse_bool
, &peer
->aggressive
},
1750 { "pull", parse_bool
, &peer
->pull
},
1751 { "dscp", parse_dscp
, &peer
->dscp
},
1752 { "encap", parse_bool
, &peer
->encap
},
1753 { "mobike", parse_bool
, &peer
->mobike
},
1754 { "dpd_delay", parse_time
, &peer
->dpd_delay
},
1755 { "dpd_timeout", parse_time
, &peer
->dpd_timeout
},
1756 { "fragmentation", parse_frag
, &peer
->fragmentation
},
1757 { "send_certreq", parse_bool
, &peer
->send_certreq
},
1758 { "send_cert", parse_send_cert
, &peer
->send_cert
},
1759 { "keyingtries", parse_uint32
, &peer
->keyingtries
},
1760 { "unique", parse_unique
, &peer
->unique
},
1761 { "local_port", parse_uint32
, &peer
->local_port
},
1762 { "remote_port", parse_uint32
, &peer
->remote_port
},
1763 { "reauth_time", parse_time
, &peer
->reauth_time
},
1764 { "rekey_time", parse_time
, &peer
->rekey_time
},
1765 { "over_time", parse_time
, &peer
->over_time
},
1766 { "rand_time", parse_time
, &peer
->rand_time
},
1767 { "ppk_id", parse_peer_id
, &peer
->ppk_id
},
1768 { "ppk_required", parse_bool
, &peer
->ppk_required
},
1770 { "mediation", parse_bool
, &peer
->mediation
},
1771 { "mediated_by", parse_string
, &peer
->mediated_by
},
1772 { "mediation_peer", parse_peer_id
, &peer
->peer_id
},
1776 return parse_rules(rules
, countof(rules
), name
, value
,
1777 &peer
->request
->reply
);
1780 CALLBACK(auth_sn
, bool,
1781 auth_data_t
*auth
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1784 if (strcasepfx(name
, "cert") ||
1785 strcasepfx(name
, "cacert"))
1789 certificate_t
*cert
;
1793 .request
= auth
->request
,
1797 if (!message
->parse(message
, ctx
, NULL
, cert_kv
, NULL
, data
))
1799 free_cert_data(data
);
1802 if (!data
->handle
&& !data
->file
)
1804 auth
->request
->reply
= create_reply("handle or file path missing: "
1806 free_cert_data(data
);
1809 else if (data
->handle
&& data
->file
)
1811 auth
->request
->reply
= create_reply("handle and file path given: "
1813 free_cert_data(data
);
1819 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
1820 BUILD_FROM_FILE
, data
->file
, BUILD_END
);
1824 handle
= chunk_from_hex(chunk_from_str(data
->handle
), NULL
);
1825 if (data
->slot
!= -1)
1827 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
1828 CERT_X509
, BUILD_PKCS11_KEYID
, handle
,
1829 BUILD_PKCS11_SLOT
, data
->slot
,
1830 data
->module
? BUILD_PKCS11_MODULE
: BUILD_END
,
1831 data
->module
, BUILD_END
);
1835 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
1836 CERT_X509
, BUILD_PKCS11_KEYID
, handle
,
1837 data
->module
? BUILD_PKCS11_MODULE
: BUILD_END
,
1838 data
->module
, BUILD_END
);
1840 chunk_free(&handle
);
1842 free_cert_data(data
);
1845 auth
->request
->reply
= create_reply("unable to load certificate: "
1849 rule
= strcasepfx(name
, "cert") ? AUTH_RULE_SUBJECT_CERT
1850 : AUTH_RULE_CA_CERT
;
1851 return add_cert(auth
, rule
, cert
);
1853 auth
->request
->reply
= create_reply("invalid section: %s", name
);
1858 * Check and update lifetimes
1860 static void check_lifetimes(lifetime_cfg_t
*lft
)
1862 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1863 if (lft
->time
.life
== LFT_UNDEFINED
)
1865 lft
->time
.life
= lft
->time
.rekey
* 110 / 100;
1867 if (lft
->bytes
.life
== LFT_UNDEFINED
)
1869 lft
->bytes
.life
= lft
->bytes
.rekey
* 110 / 100;
1871 if (lft
->packets
.life
== LFT_UNDEFINED
)
1873 lft
->packets
.life
= lft
->packets
.rekey
* 110 / 100;
1875 /* if no rand time defined, use difference of hard and soft */
1876 if (lft
->time
.jitter
== LFT_UNDEFINED
)
1878 lft
->time
.jitter
= lft
->time
.life
-
1879 min(lft
->time
.life
, lft
->time
.rekey
);
1881 if (lft
->bytes
.jitter
== LFT_UNDEFINED
)
1883 lft
->bytes
.jitter
= lft
->bytes
.life
-
1884 min(lft
->bytes
.life
, lft
->bytes
.rekey
);
1886 if (lft
->packets
.jitter
== LFT_UNDEFINED
)
1888 lft
->packets
.jitter
= lft
->packets
.life
-
1889 min(lft
->packets
.life
, lft
->packets
.rekey
);
1893 CALLBACK(children_sn
, bool,
1894 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1897 child_data_t child
= {
1898 .request
= peer
->request
,
1899 .proposals
= linked_list_create(),
1900 .local_ts
= linked_list_create(),
1901 .remote_ts
= linked_list_create(),
1902 .replay_window
= REPLAY_UNDEFINED
,
1904 .mode
= MODE_TUNNEL
,
1907 .rekey
= LFT_DEFAULT_CHILD_REKEY_TIME
,
1908 .life
= LFT_UNDEFINED
,
1909 .jitter
= LFT_UNDEFINED
,
1912 .rekey
= LFT_DEFAULT_CHILD_REKEY_BYTES
,
1913 .life
= LFT_UNDEFINED
,
1914 .jitter
= LFT_UNDEFINED
,
1917 .rekey
= LFT_DEFAULT_CHILD_REKEY_PACKETS
,
1918 .life
= LFT_UNDEFINED
,
1919 .jitter
= LFT_UNDEFINED
,
1925 proposal_t
*proposal
;
1926 traffic_selector_t
*ts
;
1928 if (!message
->parse(message
, ctx
, NULL
, child_kv
, child_li
, &child
))
1930 free_child_data(&child
);
1934 if (child
.local_ts
->get_count(child
.local_ts
) == 0)
1936 child
.local_ts
->insert_last(child
.local_ts
,
1937 traffic_selector_create_dynamic(0, 0, 65535));
1939 if (child
.remote_ts
->get_count(child
.remote_ts
) == 0)
1941 child
.remote_ts
->insert_last(child
.remote_ts
,
1942 traffic_selector_create_dynamic(0, 0, 65535));
1944 if (child
.proposals
->get_count(child
.proposals
) == 0)
1946 proposal
= proposal_create_default(PROTO_ESP
);
1949 child
.proposals
->insert_last(child
.proposals
, proposal
);
1951 proposal
= proposal_create_default_aead(PROTO_ESP
);
1954 child
.proposals
->insert_last(child
.proposals
, proposal
);
1958 check_lifetimes(&child
.cfg
.lifetime
);
1960 log_child_data(&child
, name
);
1962 cfg
= child_cfg_create(name
, &child
.cfg
);
1964 if (child
.replay_window
!= REPLAY_UNDEFINED
)
1966 cfg
->set_replay_window(cfg
, child
.replay_window
);
1968 while (child
.local_ts
->remove_first(child
.local_ts
,
1969 (void**)&ts
) == SUCCESS
)
1971 cfg
->add_traffic_selector(cfg
, TRUE
, ts
);
1973 while (child
.remote_ts
->remove_first(child
.remote_ts
,
1974 (void**)&ts
) == SUCCESS
)
1976 cfg
->add_traffic_selector(cfg
, FALSE
, ts
);
1978 while (child
.proposals
->remove_first(child
.proposals
,
1979 (void**)&proposal
) == SUCCESS
)
1981 cfg
->add_proposal(cfg
, proposal
);
1984 peer
->children
->insert_last(peer
->children
, cfg
);
1986 free_child_data(&child
);
1991 CALLBACK(peer_sn
, bool,
1992 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1995 if (strcaseeq(name
, "children"))
1997 return message
->parse(message
, ctx
, children_sn
, NULL
, NULL
, peer
);
1999 if (strcasepfx(name
, "local") ||
2000 strcasepfx(name
, "remote"))
2002 enumerator_t
*enumerator
;
2003 linked_list_t
*auths
;
2004 auth_data_t
*auth
, *current
;
2006 certificate_t
*cert
;
2007 pubkey_cert_t
*pubkey_cert
;
2008 identification_t
*id
;
2009 bool default_id
= FALSE
;
2012 .request
= peer
->request
,
2013 .cfg
= auth_cfg_create(),
2016 if (!message
->parse(message
, ctx
, auth_sn
, auth_kv
, auth_li
, auth
))
2018 free_auth_data(auth
);
2021 id
= auth
->cfg
->get(auth
->cfg
, AUTH_RULE_IDENTITY
);
2023 enumerator
= auth
->cfg
->create_enumerator(auth
->cfg
);
2024 while (enumerator
->enumerate(enumerator
, &rule
, &cert
))
2026 if (rule
== AUTH_RULE_SUBJECT_CERT
&& !default_id
)
2030 id
= cert
->get_subject(cert
);
2031 DBG1(DBG_CFG
, " id not specified, defaulting to"
2032 " cert subject '%Y'", id
);
2033 auth
->cfg
->add(auth
->cfg
, AUTH_RULE_IDENTITY
, id
->clone(id
));
2036 else if (cert
->get_type(cert
) == CERT_TRUSTED_PUBKEY
&&
2037 id
->get_type
!= ID_ANY
)
2039 /* set the subject of all raw public keys to the id */
2040 pubkey_cert
= (pubkey_cert_t
*)cert
;
2041 pubkey_cert
->set_subject(pubkey_cert
, id
);
2045 enumerator
->destroy(enumerator
);
2047 auths
= strcasepfx(name
, "local") ? peer
->local
: peer
->remote
;
2048 enumerator
= auths
->create_enumerator(auths
);
2049 while (enumerator
->enumerate(enumerator
, ¤t
))
2051 if (auth
->round
< current
->round
)
2056 auths
->insert_before(auths
, enumerator
, auth
);
2057 enumerator
->destroy(enumerator
);
2060 peer
->request
->reply
= create_reply("invalid section: %s", name
);
2065 * Perform start actions associated with a child config
2067 static void run_start_action(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
,
2068 child_cfg_t
*child_cfg
)
2070 switch (child_cfg
->get_start_action(child_cfg
))
2072 case ACTION_RESTART
:
2073 DBG1(DBG_CFG
, "initiating '%s'", child_cfg
->get_name(child_cfg
));
2074 charon
->controller
->initiate(charon
->controller
,
2075 peer_cfg
->get_ref(peer_cfg
), child_cfg
->get_ref(child_cfg
),
2076 NULL
, NULL
, 0, FALSE
);
2079 DBG1(DBG_CFG
, "installing '%s'", child_cfg
->get_name(child_cfg
));
2080 switch (child_cfg
->get_mode(child_cfg
))
2084 charon
->shunts
->install(charon
->shunts
,
2085 peer_cfg
->get_name(peer_cfg
), child_cfg
);
2088 charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
);
2098 * Undo start actions associated with a child config
2100 static void clear_start_action(private_vici_config_t
*this, char *peer_name
,
2101 child_cfg_t
*child_cfg
)
2103 enumerator_t
*enumerator
, *children
;
2104 child_sa_t
*child_sa
;
2106 uint32_t id
= 0, others
;
2107 array_t
*ids
= NULL
, *ikeids
= NULL
;
2110 name
= child_cfg
->get_name(child_cfg
);
2112 switch (child_cfg
->get_start_action(child_cfg
))
2114 case ACTION_RESTART
:
2115 enumerator
= charon
->controller
->create_ike_sa_enumerator(
2116 charon
->controller
, TRUE
);
2117 while (enumerator
->enumerate(enumerator
, &ike_sa
))
2119 if (!streq(ike_sa
->get_name(ike_sa
), peer_name
))
2124 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
2125 while (children
->enumerate(children
, &child_sa
))
2127 if (child_sa
->get_state(child_sa
) != CHILD_DELETING
&&
2128 child_sa
->get_state(child_sa
) != CHILD_DELETED
)
2130 if (streq(name
, child_sa
->get_name(child_sa
)))
2132 id
= child_sa
->get_unique_id(child_sa
);
2140 children
->destroy(children
);
2144 /* found matching children only, delete full IKE_SA */
2145 id
= ike_sa
->get_unique_id(ike_sa
);
2146 array_insert_create_value(&ikeids
, sizeof(id
),
2151 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
2152 while (children
->enumerate(children
, &child_sa
))
2154 if (streq(name
, child_sa
->get_name(child_sa
)))
2156 id
= child_sa
->get_unique_id(child_sa
);
2157 array_insert_create_value(&ids
, sizeof(id
),
2161 children
->destroy(children
);
2164 enumerator
->destroy(enumerator
);
2166 if (array_count(ids
))
2168 while (array_remove(ids
, ARRAY_HEAD
, &id
))
2170 DBG1(DBG_CFG
, "closing '%s' #%u", name
, id
);
2171 charon
->controller
->terminate_child(charon
->controller
,
2176 if (array_count(ikeids
))
2178 while (array_remove(ikeids
, ARRAY_HEAD
, &id
))
2180 DBG1(DBG_CFG
, "closing IKE_SA #%u", id
);
2181 charon
->controller
->terminate_ike(charon
->controller
, id
,
2182 FALSE
, NULL
, NULL
, 0);
2184 array_destroy(ikeids
);
2188 DBG1(DBG_CFG
, "uninstalling '%s'", name
);
2189 switch (child_cfg
->get_mode(child_cfg
))
2193 charon
->shunts
->uninstall(charon
->shunts
, peer_name
, name
);
2196 charon
->traps
->uninstall(charon
->traps
, peer_name
, name
);
2206 * Run or undo a start actions associated with a child config
2208 static void handle_start_action(private_vici_config_t
*this,
2209 peer_cfg_t
*peer_cfg
, child_cfg_t
*child_cfg
,
2212 this->handling_actions
= TRUE
;
2213 this->lock
->unlock(this->lock
);
2217 clear_start_action(this, peer_cfg
->get_name(peer_cfg
), child_cfg
);
2221 run_start_action(this, peer_cfg
, child_cfg
);
2224 this->lock
->write_lock(this->lock
);
2225 this->handling_actions
= FALSE
;
2229 * Run or undo start actions associated with all child configs of a peer config
2231 static void handle_start_actions(private_vici_config_t
*this,
2232 peer_cfg_t
*peer_cfg
, bool undo
)
2234 enumerator_t
*enumerator
;
2235 child_cfg_t
*child_cfg
;
2237 this->handling_actions
= TRUE
;
2238 this->lock
->unlock(this->lock
);
2240 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
2241 while (enumerator
->enumerate(enumerator
, &child_cfg
))
2245 clear_start_action(this, peer_cfg
->get_name(peer_cfg
), child_cfg
);
2249 run_start_action(this, peer_cfg
, child_cfg
);
2252 enumerator
->destroy(enumerator
);
2254 this->lock
->write_lock(this->lock
);
2255 this->handling_actions
= FALSE
;
2259 * Replace children of a peer config by a new config
2261 static void replace_children(private_vici_config_t
*this,
2262 peer_cfg_t
*from
, peer_cfg_t
*to
)
2264 enumerator_t
*enumerator
;
2268 enumerator
= to
->replace_child_cfgs(to
, from
);
2269 while (enumerator
->enumerate(enumerator
, &child
, &added
))
2271 handle_start_action(this, to
, child
, !added
);
2273 enumerator
->destroy(enumerator
);
2277 * Merge/replace a peer config with existing configs
2279 static void merge_config(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
2281 enumerator_t
*enumerator
;
2282 peer_cfg_t
*current
;
2284 bool merged
= FALSE
;
2286 this->lock
->write_lock(this->lock
);
2287 while (this->handling_actions
)
2289 this->condvar
->wait(this->condvar
, this->lock
);
2292 enumerator
= this->conns
->create_enumerator(this->conns
);
2293 while (enumerator
->enumerate(enumerator
, ¤t
))
2295 if (streq(peer_cfg
->get_name(peer_cfg
), current
->get_name(current
)))
2297 ike_cfg
= current
->get_ike_cfg(current
);
2298 if (peer_cfg
->equals(peer_cfg
, current
) &&
2299 ike_cfg
->equals(ike_cfg
, peer_cfg
->get_ike_cfg(peer_cfg
)))
2301 DBG1(DBG_CFG
, "updated vici connection: %s",
2302 peer_cfg
->get_name(peer_cfg
));
2303 replace_children(this, peer_cfg
, current
);
2304 peer_cfg
->destroy(peer_cfg
);
2308 DBG1(DBG_CFG
, "replaced vici connection: %s",
2309 peer_cfg
->get_name(peer_cfg
));
2310 this->conns
->insert_before(this->conns
, enumerator
, peer_cfg
);
2311 this->conns
->remove_at(this->conns
, enumerator
);
2312 handle_start_actions(this, current
, TRUE
);
2313 handle_start_actions(this, peer_cfg
, FALSE
);
2314 current
->destroy(current
);
2320 enumerator
->destroy(enumerator
);
2324 DBG1(DBG_CFG
, "added vici connection: %s", peer_cfg
->get_name(peer_cfg
));
2325 this->conns
->insert_last(this->conns
, peer_cfg
);
2326 handle_start_actions(this, peer_cfg
, FALSE
);
2328 this->condvar
->signal(this->condvar
);
2329 this->lock
->unlock(this->lock
);
2332 CALLBACK(config_sn
, bool,
2333 request_data_t
*request
, vici_message_t
*message
,
2334 vici_parse_context_t
*ctx
, char *name
)
2336 peer_data_t peer
= {
2338 .local
= linked_list_create(),
2339 .remote
= linked_list_create(),
2340 .vips
= linked_list_create(),
2341 .children
= linked_list_create(),
2342 .proposals
= linked_list_create(),
2344 .send_certreq
= TRUE
,
2346 .send_cert
= CERT_SEND_IF_ASKED
,
2348 .remote_port
= IKEV2_UDP_PORT
,
2349 .fragmentation
= FRAGMENTATION_YES
,
2350 .unique
= UNIQUE_NO
,
2352 .rekey_time
= LFT_UNDEFINED
,
2353 .reauth_time
= LFT_UNDEFINED
,
2354 .over_time
= LFT_UNDEFINED
,
2355 .rand_time
= LFT_UNDEFINED
,
2357 enumerator_t
*enumerator
;
2358 peer_cfg_create_t cfg
;
2359 peer_cfg_t
*peer_cfg
;
2361 child_cfg_t
*child_cfg
;
2363 proposal_t
*proposal
;
2367 DBG2(DBG_CFG
, " conn %s:", name
);
2369 if (!message
->parse(message
, ctx
, peer_sn
, peer_kv
, peer_li
, &peer
))
2371 free_peer_data(&peer
);
2375 if (peer
.local
->get_count(peer
.local
) == 0)
2378 .cfg
= auth_cfg_create(),
2380 peer
.local
->insert_last(peer
.local
, auth
);
2382 if (peer
.remote
->get_count(peer
.remote
) == 0)
2385 .cfg
= auth_cfg_create(),
2387 peer
.remote
->insert_last(peer
.remote
, auth
);
2389 if (peer
.proposals
->get_count(peer
.proposals
) == 0)
2391 proposal
= proposal_create_default(PROTO_IKE
);
2394 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
2396 proposal
= proposal_create_default_aead(PROTO_IKE
);
2399 peer
.proposals
->insert_last(peer
.proposals
, proposal
);
2402 if (!peer
.local_addrs
)
2404 peer
.local_addrs
= strdup("%any");
2406 if (!peer
.remote_addrs
)
2408 peer
.remote_addrs
= strdup("%any");
2410 if (!peer
.local_port
)
2412 peer
.local_port
= charon
->socket
->get_port(charon
->socket
, FALSE
);
2415 if (peer
.rekey_time
== LFT_UNDEFINED
&& peer
.reauth_time
== LFT_UNDEFINED
)
2417 /* apply a default rekey time if no rekey/reauth time set */
2418 peer
.rekey_time
= LFT_DEFAULT_IKE_REKEY_TIME
;
2419 peer
.reauth_time
= 0;
2421 if (peer
.rekey_time
== LFT_UNDEFINED
)
2423 peer
.rekey_time
= 0;
2425 if (peer
.reauth_time
== LFT_UNDEFINED
)
2427 peer
.reauth_time
= 0;
2429 if (peer
.over_time
== LFT_UNDEFINED
)
2431 /* default over_time to 10% of rekey/reauth time if not given */
2432 peer
.over_time
= max(peer
.rekey_time
, peer
.reauth_time
) / 10;
2434 if (peer
.rand_time
== LFT_UNDEFINED
)
2436 /* default rand_time to over_time if not given, but don't make it
2437 * longer than half of rekey/rauth time */
2438 if (peer
.rekey_time
&& peer
.reauth_time
)
2440 peer
.rand_time
= min(peer
.rekey_time
, peer
.reauth_time
);
2444 peer
.rand_time
= max(peer
.rekey_time
, peer
.reauth_time
);
2446 peer
.rand_time
= min(peer
.over_time
, peer
.rand_time
/ 2);
2450 if (peer
.mediation
&& peer
.mediated_by
)
2452 DBG1(DBG_CFG
, "a mediation connection cannot be a mediated connection "
2453 "at the same time, config discarded");
2454 free_peer_data(&peer
);
2458 { /* force unique connections for mediation connections */
2459 peer
.unique
= UNIQUE_REPLACE
;
2461 else if (peer
.mediated_by
)
2462 { /* fallback to remote identity of first auth round if peer_id is not
2463 * given explicitly */
2466 if (!peer
.peer_id
&&
2467 peer
.remote
->get_first(peer
.remote
, (void**)&cfg
) == SUCCESS
)
2469 peer
.peer_id
= cfg
->get(cfg
, AUTH_RULE_IDENTITY
);
2472 peer
.peer_id
= peer
.peer_id
->clone(peer
.peer_id
);
2476 DBG1(DBG_CFG
, "mediation peer missing for mediated connection, "
2477 "config discarded");
2478 free_peer_data(&peer
);
2485 log_peer_data(&peer
);
2487 ike_cfg
= ike_cfg_create(peer
.version
, peer
.send_certreq
, peer
.encap
,
2488 peer
.local_addrs
, peer
.local_port
,
2489 peer
.remote_addrs
, peer
.remote_port
,
2490 peer
.fragmentation
, peer
.dscp
);
2492 cfg
= (peer_cfg_create_t
){
2493 .cert_policy
= peer
.send_cert
,
2494 .unique
= peer
.unique
,
2495 .keyingtries
= peer
.keyingtries
,
2496 .rekey_time
= peer
.rekey_time
,
2497 .reauth_time
= peer
.reauth_time
,
2498 .jitter_time
= peer
.rand_time
,
2499 .over_time
= peer
.over_time
,
2500 .no_mobike
= !peer
.mobike
,
2501 .aggressive
= peer
.aggressive
,
2502 .push_mode
= !peer
.pull
,
2503 .dpd
= peer
.dpd_delay
,
2504 .dpd_timeout
= peer
.dpd_timeout
,
2505 .ppk_id
= peer
.ppk_id
? peer
.ppk_id
->clone(peer
.ppk_id
) : NULL
,
2506 .ppk_required
= peer
.ppk_required
,
2509 cfg
.mediation
= peer
.mediation
;
2510 if (peer
.mediated_by
)
2512 cfg
.mediated_by
= peer
.mediated_by
;
2515 cfg
.peer_id
= peer
.peer_id
->clone(peer
.peer_id
);
2519 peer_cfg
= peer_cfg_create(name
, ike_cfg
, &cfg
);
2521 while (peer
.local
->remove_first(peer
.local
,
2522 (void**)&auth
) == SUCCESS
)
2524 peer_cfg
->add_auth_cfg(peer_cfg
, auth
->cfg
, TRUE
);
2526 free_auth_data(auth
);
2528 while (peer
.remote
->remove_first(peer
.remote
,
2529 (void**)&auth
) == SUCCESS
)
2531 peer_cfg
->add_auth_cfg(peer_cfg
, auth
->cfg
, FALSE
);
2533 free_auth_data(auth
);
2535 while (peer
.children
->remove_first(peer
.children
,
2536 (void**)&child_cfg
) == SUCCESS
)
2538 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
2540 while (peer
.proposals
->remove_first(peer
.proposals
,
2541 (void**)&proposal
) == SUCCESS
)
2543 ike_cfg
->add_proposal(ike_cfg
, proposal
);
2545 while (peer
.vips
->remove_first(peer
.vips
, (void**)&host
) == SUCCESS
)
2547 peer_cfg
->add_virtual_ip(peer_cfg
, host
);
2551 enumerator
= enumerator_create_token(peer
.pools
, ",", " ");
2552 while (enumerator
->enumerate(enumerator
, &str
))
2554 peer_cfg
->add_pool(peer_cfg
, str
);
2556 enumerator
->destroy(enumerator
);
2559 free_peer_data(&peer
);
2561 merge_config(request
->this, peer_cfg
);
2566 CALLBACK(load_conn
, vici_message_t
*,
2567 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2569 request_data_t request
= {
2573 if (!message
->parse(message
, NULL
, config_sn
, NULL
, NULL
, &request
))
2577 return request
.reply
;
2579 return create_reply("parsing request failed");
2581 return create_reply(NULL
);
2584 CALLBACK(unload_conn
, vici_message_t
*,
2585 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2587 enumerator_t
*enumerator
;
2592 conn_name
= message
->get_str(message
, NULL
, "name");
2595 return create_reply("unload: missing connection name");
2598 this->lock
->write_lock(this->lock
);
2599 while (this->handling_actions
)
2601 this->condvar
->wait(this->condvar
, this->lock
);
2603 enumerator
= this->conns
->create_enumerator(this->conns
);
2604 while (enumerator
->enumerate(enumerator
, &cfg
))
2606 if (streq(cfg
->get_name(cfg
), conn_name
))
2608 this->conns
->remove_at(this->conns
, enumerator
);
2609 handle_start_actions(this, cfg
, TRUE
);
2615 enumerator
->destroy(enumerator
);
2616 this->condvar
->signal(this->condvar
);
2617 this->lock
->unlock(this->lock
);
2621 return create_reply("unload: connection '%s' not found", conn_name
);
2623 return create_reply(NULL
);
2626 CALLBACK(get_conns
, vici_message_t
*,
2627 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
2629 vici_builder_t
*builder
;
2630 enumerator_t
*enumerator
;
2633 builder
= vici_builder_create();
2634 builder
->begin_list(builder
, "conns");
2636 this->lock
->read_lock(this->lock
);
2637 enumerator
= this->conns
->create_enumerator(this->conns
);
2638 while (enumerator
->enumerate(enumerator
, &cfg
))
2640 builder
->add_li(builder
, "%s", cfg
->get_name(cfg
));
2642 enumerator
->destroy(enumerator
);
2643 this->lock
->unlock(this->lock
);
2645 builder
->end_list(builder
);
2647 return builder
->finalize(builder
);
2650 static void manage_command(private_vici_config_t
*this,
2651 char *name
, vici_command_cb_t cb
, bool reg
)
2653 this->dispatcher
->manage_command(this->dispatcher
, name
,
2654 reg
? cb
: NULL
, this);
2658 * (Un-)register dispatcher functions
2660 static void manage_commands(private_vici_config_t
*this, bool reg
)
2662 manage_command(this, "load-conn", load_conn
, reg
);
2663 manage_command(this, "unload-conn", unload_conn
, reg
);
2664 manage_command(this, "get-conns", get_conns
, reg
);
2667 METHOD(vici_config_t
, destroy
, void,
2668 private_vici_config_t
*this)
2670 manage_commands(this, FALSE
);
2671 this->conns
->destroy_offset(this->conns
, offsetof(peer_cfg_t
, destroy
));
2672 this->condvar
->destroy(this->condvar
);
2673 this->lock
->destroy(this->lock
);
2680 vici_config_t
*vici_config_create(vici_dispatcher_t
*dispatcher
,
2681 vici_authority_t
*authority
,
2684 private_vici_config_t
*this;
2689 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
2690 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
2691 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
2693 .destroy
= _destroy
,
2695 .dispatcher
= dispatcher
,
2696 .conns
= linked_list_create(),
2697 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
2698 .condvar
= rwlock_condvar_create(),
2699 .authority
= authority
,
2703 manage_commands(this, TRUE
);
2705 return &this->public;