2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
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>.
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
18 #include "vici_config.h"
19 #include "vici_builder.h"
22 #include <threading/rwlock.h>
23 #include <collections/array.h>
24 #include <collections/linked_list.h>
30 * Magic value for an undefined lifetime
32 #define LFT_UNDEFINED (~(u_int64_t)0)
35 * Default IKE rekey time
37 #define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
40 * Default CHILD rekey time
42 #define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
44 typedef struct private_vici_config_t private_vici_config_t
;
47 * Private data of an vici_config_t object.
49 struct private_vici_config_t
{
52 * Public vici_config_t interface.
59 vici_dispatcher_t
*dispatcher
;
62 * List of loaded connections, as peer_cfg_t
72 METHOD(backend_t
, create_peer_cfg_enumerator
, enumerator_t
*,
73 private_vici_config_t
*this, identification_t
*me
, identification_t
*other
)
75 this->lock
->read_lock(this->lock
);
76 return enumerator_create_cleaner(this->conns
->create_enumerator(this->conns
),
77 (void*)this->lock
->unlock
, this->lock
);
81 * Enumerator filter function for ike configs
83 static bool ike_filter(void *data
, peer_cfg_t
**in
, ike_cfg_t
**out
)
85 *out
= (*in
)->get_ike_cfg(*in
);
89 METHOD(backend_t
, create_ike_cfg_enumerator
, enumerator_t
*,
90 private_vici_config_t
*this, host_t
*me
, host_t
*other
)
92 this->lock
->read_lock(this->lock
);
93 return enumerator_create_filter(this->conns
->create_enumerator(this->conns
),
94 (void*)ike_filter
, this->lock
,
95 (void*)this->lock
->unlock
);
98 METHOD(backend_t
, get_peer_cfg_by_name
, peer_cfg_t
*,
99 private_vici_config_t
*this, char *name
)
101 peer_cfg_t
*current
, *found
= NULL
;
102 enumerator_t
*enumerator
;
104 this->lock
->read_lock(this->lock
);
105 enumerator
= this->conns
->create_enumerator(this->conns
);
106 while (enumerator
->enumerate(enumerator
, ¤t
))
108 if (streq(current
->get_name(current
), name
))
111 found
->get_ref(found
);
115 enumerator
->destroy(enumerator
);
116 this->lock
->unlock(this->lock
);
122 * Create a (error) reply message
124 static vici_message_t
* create_reply(char *fmt
, ...)
126 vici_builder_t
*builder
;
129 builder
= vici_builder_create();
130 builder
->add_kv(builder
, "success", fmt ?
"no" : "yes");
134 builder
->vadd_kv(builder
, "errmsg", fmt
, args
);
137 return builder
->finalize(builder
);
141 * A rule to parse a key/value or list item
144 /** name of the key/value or list */
146 /** function to parse value */
147 bool (*parse
)(void *out
, chunk_t value
);
148 /** result, passed to parse() */
153 * Parse key/values using a rule-set
155 static bool parse_rules(parse_rule_t
*rules
, int count
, char *name
,
156 chunk_t value
, vici_message_t
**reply
)
160 for (i
= 0; i
< count
; i
++)
162 if (streq(name
, rules
[i
].name
))
164 if (rules
[i
].parse(rules
[i
].out
, value
))
168 *reply
= create_reply("invalid value for: %s, config discarded",
173 *reply
= create_reply("unknown option: %s, config discarded", name
);
178 * Parse callback data, passed to each callback
181 private_vici_config_t
*this;
182 vici_message_t
*reply
;
186 * Data associated to a peer config
189 request_data_t
*request
;
196 cert_policy_t send_cert
;
198 u_int64_t dpd_timeout
;
199 fragmentation_t fragmentation
;
200 unique_policy_t unique
;
201 u_int32_t keyingtries
;
202 u_int32_t local_port
;
203 u_int32_t remote_port
;
206 linked_list_t
*local
;
207 linked_list_t
*remote
;
208 linked_list_t
*proposals
;
209 linked_list_t
*children
;
212 u_int64_t reauth_time
;
213 u_int64_t rekey_time
;
219 * Log relevant auth config data
221 static void log_auth(auth_cfg_t
*auth
)
223 enumerator_t
*enumerator
;
227 identification_t
*id
;
231 enumerator
= auth
->create_enumerator(auth
);
232 while (enumerator
->enumerate(enumerator
, &rule
, &v
))
236 case AUTH_RULE_AUTH_CLASS
:
237 DBG2(DBG_CFG
, " class = %N", auth_class_names
, v
.u
);
239 case AUTH_RULE_EAP_TYPE
:
240 DBG2(DBG_CFG
, " eap-type = %N", eap_type_names
, v
.u
);
242 case AUTH_RULE_EAP_VENDOR
:
243 DBG2(DBG_CFG
, " eap-vendor = %u", v
.u
);
245 case AUTH_RULE_XAUTH_BACKEND
:
246 DBG2(DBG_CFG
, " xauth = %s", v
.str
);
248 case AUTH_RULE_CRL_VALIDATION
:
249 DBG2(DBG_CFG
, " revocation = %N", cert_validation_names
, v
.u
);
251 case AUTH_RULE_IDENTITY
:
252 DBG2(DBG_CFG
, " id = %Y", v
.id
);
254 case AUTH_RULE_AAA_IDENTITY
:
255 DBG2(DBG_CFG
, " aaa_id = %Y", v
.id
);
257 case AUTH_RULE_EAP_IDENTITY
:
258 DBG2(DBG_CFG
, " eap_id = %Y", v
.id
);
260 case AUTH_RULE_XAUTH_IDENTITY
:
261 DBG2(DBG_CFG
, " xauth_id = %Y", v
.id
);
263 case AUTH_RULE_GROUP
:
264 DBG2(DBG_CFG
, " group = %Y", v
.id
);
270 enumerator
->destroy(enumerator
);
274 * Log parsed peer data
276 static void log_peer_data(peer_data_t
*data
)
278 enumerator_t
*enumerator
;
282 DBG2(DBG_CFG
, " version = %u", data
->version
);
283 DBG2(DBG_CFG
, " local_addrs = %s", data
->local_addrs
);
284 DBG2(DBG_CFG
, " remote_addrs = %s", data
->remote_addrs
);
285 DBG2(DBG_CFG
, " local_port = %u", data
->local_port
);
286 DBG2(DBG_CFG
, " remote_port = %u", data
->remote_port
);
287 DBG2(DBG_CFG
, " send_certreq = %u", data
->send_certreq
);
288 DBG2(DBG_CFG
, " send_cert = %N", cert_policy_names
, data
->send_cert
);
289 DBG2(DBG_CFG
, " mobike = %u", data
->mobike
);
290 DBG2(DBG_CFG
, " aggressive = %u", data
->aggressive
);
291 DBG2(DBG_CFG
, " encap = %u", data
->encap
);
292 DBG2(DBG_CFG
, " dpd_delay = %llu", data
->dpd_delay
);
293 DBG2(DBG_CFG
, " dpd_timeout = %llu", data
->dpd_timeout
);
294 DBG2(DBG_CFG
, " fragmentation = %u", data
->fragmentation
);
295 DBG2(DBG_CFG
, " unique = %N", unique_policy_names
, data
->unique
);
296 DBG2(DBG_CFG
, " keyingtries = %u", data
->keyingtries
);
297 DBG2(DBG_CFG
, " reauth_time = %llu", data
->reauth_time
);
298 DBG2(DBG_CFG
, " rekey_time = %llu", data
->rekey_time
);
299 DBG2(DBG_CFG
, " over_time = %llu", data
->over_time
);
300 DBG2(DBG_CFG
, " rand_time = %llu", data
->rand_time
);
301 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
303 if (data
->vips
->get_count(data
->vips
))
305 DBG2(DBG_CFG
, " vips:");
307 enumerator
= data
->vips
->create_enumerator(data
->vips
);
308 while (enumerator
->enumerate(enumerator
, &host
))
310 DBG2(DBG_CFG
, " %H", host
);
312 enumerator
->destroy(enumerator
);
314 enumerator
= data
->local
->create_enumerator(data
->local
);
315 while (enumerator
->enumerate(enumerator
, &auth
))
317 DBG2(DBG_CFG
, " local:");
320 enumerator
->destroy(enumerator
);
322 enumerator
= data
->remote
->create_enumerator(data
->remote
);
323 while (enumerator
->enumerate(enumerator
, &auth
))
325 DBG2(DBG_CFG
, " remote:");
328 enumerator
->destroy(enumerator
);
332 * Clean up peer config data
334 static void free_peer_data(peer_data_t
*data
)
336 data
->local
->destroy_offset(data
->local
,
337 offsetof(auth_cfg_t
, destroy
));
338 data
->remote
->destroy_offset(data
->remote
,
339 offsetof(auth_cfg_t
, destroy
));
340 data
->children
->destroy_offset(data
->children
,
341 offsetof(child_cfg_t
, destroy
));
342 data
->proposals
->destroy_offset(data
->proposals
,
343 offsetof(proposal_t
, destroy
));
344 data
->vips
->destroy_offset(data
->vips
, offsetof(host_t
, destroy
));
346 free(data
->local_addrs
);
347 free(data
->remote_addrs
);
354 request_data_t
*request
;
362 action_t start_action
;
367 u_int64_t inactivity
;
368 linked_list_t
*proposals
;
369 linked_list_t
*local_ts
;
370 linked_list_t
*remote_ts
;
374 * Log parsed CHILD config data
376 static void log_child_data(child_data_t
*data
, char *name
)
378 DBG2(DBG_CFG
, " child %s:", name
);
379 DBG2(DBG_CFG
, " rekey_time = %llu", data
->lft
.time
.rekey
);
380 DBG2(DBG_CFG
, " life_time = %llu", data
->lft
.time
.life
);
381 DBG2(DBG_CFG
, " rand_time = %llu", data
->lft
.time
.jitter
);
382 DBG2(DBG_CFG
, " rekey_bytes = %llu", data
->lft
.bytes
.rekey
);
383 DBG2(DBG_CFG
, " life_bytes = %llu", data
->lft
.bytes
.life
);
384 DBG2(DBG_CFG
, " rand_bytes = %llu", data
->lft
.bytes
.jitter
);
385 DBG2(DBG_CFG
, " rekey_packets = %llu", data
->lft
.packets
.rekey
);
386 DBG2(DBG_CFG
, " life_packets = %llu", data
->lft
.packets
.life
);
387 DBG2(DBG_CFG
, " rand_packets = %llu", data
->lft
.packets
.jitter
);
388 DBG2(DBG_CFG
, " updown = %s", data
->updown
);
389 DBG2(DBG_CFG
, " hostaccess = %u", data
->hostaccess
);
390 DBG2(DBG_CFG
, " ipcomp = %u", data
->ipcomp
);
391 DBG2(DBG_CFG
, " mode = %N", ipsec_mode_names
, data
->mode
);
392 DBG2(DBG_CFG
, " dpd_action = %N", action_names
, data
->dpd_action
);
393 DBG2(DBG_CFG
, " reqid = %u", data
->reqid
);
394 DBG2(DBG_CFG
, " tfc = %u", data
->tfc
);
395 DBG2(DBG_CFG
, " mark_in = %u/%u",
396 data
->mark_in
.value
, data
->mark_in
.mask
);
397 DBG2(DBG_CFG
, " mark_out = %u/%u",
398 data
->mark_out
.value
, data
->mark_out
.mask
);
399 DBG2(DBG_CFG
, " inactivity = %llu", data
->inactivity
);
400 DBG2(DBG_CFG
, " proposals = %#P", data
->proposals
);
401 DBG2(DBG_CFG
, " local_ts = %#R", data
->local_ts
);
402 DBG2(DBG_CFG
, " remote_ts = %#R", data
->remote_ts
);
406 * Clean up CHILD config data
408 static void free_child_data(child_data_t
*data
)
410 data
->proposals
->destroy_offset(data
->proposals
,
411 offsetof(proposal_t
, destroy
));
412 data
->local_ts
->destroy_offset(data
->local_ts
,
413 offsetof(traffic_selector_t
, destroy
));
414 data
->remote_ts
->destroy_offset(data
->remote_ts
,
415 offsetof(traffic_selector_t
, destroy
));
423 request_data_t
*request
;
428 * Common proposal parsing
430 static bool parse_proposal(linked_list_t
*list
, protocol_id_t proto
, chunk_t v
)
433 proposal_t
*proposal
;
435 if (!vici_stringify(v
, buf
, sizeof(buf
)))
439 if (strcaseeq("default", buf
))
441 proposal
= proposal_create_default(proto
);
445 proposal
= proposal_create_from_string(proto
, buf
);
451 list
->insert_last(list
, proposal
);
458 CALLBACK(parse_ike_proposal
, bool,
459 linked_list_t
*out
, chunk_t v
)
461 return parse_proposal(out
, PROTO_IKE
, v
);
467 CALLBACK(parse_esp_proposal
, bool,
468 linked_list_t
*out
, chunk_t v
)
470 return parse_proposal(out
, PROTO_ESP
, v
);
476 CALLBACK(parse_ah_proposal
, bool,
477 linked_list_t
*out
, chunk_t v
)
479 return parse_proposal(out
, PROTO_AH
, v
);
483 * Parse a traffic selector
485 CALLBACK(parse_ts
, bool,
486 linked_list_t
*out
, chunk_t v
)
488 char buf
[128], *protoport
, *sep
, *port
= "", *end
;
489 traffic_selector_t
*ts
;
490 struct protoent
*protoent
;
493 u_int16_t from
= 0, to
= 0xffff;
496 if (!vici_stringify(v
, buf
, sizeof(buf
)))
501 protoport
= strchr(buf
, '[');
504 *(protoport
++) = '\0';
506 sep
= strrchr(protoport
, ']');
513 sep
= strchr(protoport
, '/');
515 { /* protocol/port */
520 if (streq(protoport
, "any"))
526 protoent
= getprotobyname(protoport
);
529 proto
= protoent
->p_proto
;
533 p
= strtol(protoport
, &end
, 0);
534 if ((*protoport
&& *end
) || p
< 0 || p
> 0xff)
541 if (streq(port
, "opaque"))
546 else if (*port
&& !streq(port
, "any"))
548 svc
= getservbyname(port
, NULL
);
551 from
= to
= ntohs(svc
->s_port
);
555 p
= strtol(port
, &end
, 0);
556 if (p
< 0 || p
> 0xffff)
564 p
= strtol(port
, &end
, 0);
565 if (p
< 0 || p
> 0xffff)
578 if (streq(buf
, "dynamic"))
580 ts
= traffic_selector_create_dynamic(proto
, from
, to
);
584 ts
= traffic_selector_create_from_cidr(buf
, proto
, from
, to
);
590 out
->insert_last(out
, ts
);
597 CALLBACK(parse_string
, bool,
598 char **out
, chunk_t v
)
600 if (!chunk_printable(v
, NULL
, ' '))
606 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
614 * Map a string to an integer
622 * Parse a string to an integer mapping
624 static bool parse_map(enum_map_t
*map
, int count
, int *out
, chunk_t v
)
629 if (!vici_stringify(v
, buf
, sizeof(buf
)))
633 for (i
= 0; i
< count
; i
++)
635 if (strcaseeq(map
[i
].str
, buf
))
647 CALLBACK(parse_bool
, bool,
648 bool *out
, chunk_t v
)
657 { "disabled", FALSE
},
662 if (parse_map(map
, countof(map
), &d
, v
))
671 * Parse a ipsec_mode_t
673 CALLBACK(parse_mode
, bool,
674 ipsec_mode_t
*out
, chunk_t v
)
677 { "tunnel", MODE_TUNNEL
},
678 { "transport", MODE_TRANSPORT
},
679 { "beet", MODE_BEET
},
680 { "drop", MODE_DROP
},
681 { "pass", MODE_PASS
},
685 if (parse_map(map
, countof(map
), &d
, v
))
696 CALLBACK(parse_action
, bool,
697 action_t
*out
, chunk_t v
)
700 { "start", ACTION_RESTART
},
701 { "restart", ACTION_RESTART
},
702 { "route", ACTION_ROUTE
},
703 { "none", ACTION_NONE
},
704 { "clear", ACTION_NONE
},
708 if (parse_map(map
, countof(map
), &d
, v
))
719 CALLBACK(parse_uint32
, bool,
720 u_int32_t
*out
, chunk_t v
)
725 if (!vici_stringify(v
, buf
, sizeof(buf
)))
729 l
= strtoul(buf
, &end
, 0);
741 CALLBACK(parse_uint64
, bool,
742 u_int64_t
*out
, chunk_t v
)
745 unsigned long long l
;
747 if (!vici_stringify(v
, buf
, sizeof(buf
)))
751 l
= strtoull(buf
, &end
, 0);
761 * Parse a relative time
763 CALLBACK(parse_time
, bool,
764 u_int64_t
*out
, chunk_t v
)
769 if (!vici_stringify(v
, buf
, sizeof(buf
)))
774 l
= strtoul(buf
, &end
, 0);
813 CALLBACK(parse_bytes
, bool,
814 u_int64_t
*out
, chunk_t v
)
817 unsigned long long l
;
819 if (!vici_stringify(v
, buf
, sizeof(buf
)))
824 l
= strtoull(buf
, &end
, 0);
860 CALLBACK(parse_mark
, bool,
861 mark_t
*out
, chunk_t v
)
865 if (!vici_stringify(v
, buf
, sizeof(buf
)))
869 return mark_from_string(buf
, out
);
873 * Parse authentication config
875 CALLBACK(parse_auth
, bool,
876 auth_cfg_t
*cfg
, chunk_t v
)
879 eap_vendor_type_t
*type
;
881 if (!vici_stringify(v
, buf
, sizeof(buf
)))
885 if (strcaseeq(buf
, "pubkey"))
887 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PUBKEY
);
890 if (strcaseeq(buf
, "psk"))
892 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_PSK
);
895 if (strcasepfx(buf
, "xauth"))
897 pos
= strchr(buf
, '-');
900 cfg
->add(cfg
, AUTH_RULE_XAUTH_BACKEND
, strdup(++pos
));
902 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_XAUTH
);
905 if (strcasepfx(buf
, "eap"))
907 cfg
->add(cfg
, AUTH_RULE_AUTH_CLASS
, AUTH_CLASS_EAP
);
909 type
= eap_vendor_type_from_string(buf
);
912 cfg
->add(cfg
, AUTH_RULE_EAP_TYPE
, type
->type
);
915 cfg
->add(cfg
, AUTH_RULE_EAP_VENDOR
, type
->vendor
);
925 * Parse identity; add as auth rule to config
927 static bool parse_id(auth_cfg_t
*cfg
, auth_rule_t rule
, chunk_t v
)
931 if (!vici_stringify(v
, buf
, sizeof(buf
)))
935 cfg
->add(cfg
, rule
, identification_create_from_string(buf
));
942 CALLBACK(parse_ike_id
, bool,
943 auth_cfg_t
*cfg
, chunk_t v
)
945 return parse_id(cfg
, AUTH_RULE_IDENTITY
, v
);
951 CALLBACK(parse_aaa_id
, bool,
952 auth_cfg_t
*cfg
, chunk_t v
)
954 return parse_id(cfg
, AUTH_RULE_AAA_IDENTITY
, v
);
960 CALLBACK(parse_eap_id
, bool,
961 auth_cfg_t
*cfg
, chunk_t v
)
963 return parse_id(cfg
, AUTH_RULE_EAP_IDENTITY
, v
);
967 * Parse XAuth identity
969 CALLBACK(parse_xauth_id
, bool,
970 auth_cfg_t
*cfg
, chunk_t v
)
972 return parse_id(cfg
, AUTH_RULE_XAUTH_IDENTITY
, v
);
976 * Parse group membership
978 CALLBACK(parse_group
, bool,
979 auth_cfg_t
*cfg
, chunk_t v
)
981 return parse_id(cfg
, AUTH_RULE_GROUP
, v
);
985 * Parse a certificate; add as auth rule to config
987 static bool parse_cert(auth_cfg_t
*cfg
, auth_rule_t rule
, chunk_t v
)
991 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
992 BUILD_BLOB_PEM
, v
, BUILD_END
);
995 cfg
->add(cfg
, rule
, cert
);
1002 * Parse subject certificates
1004 CALLBACK(parse_certs
, bool,
1005 auth_cfg_t
*cfg
, chunk_t v
)
1007 return parse_cert(cfg
, AUTH_RULE_SUBJECT_CERT
, v
);
1011 * Parse CA certificates
1013 CALLBACK(parse_cacerts
, bool,
1014 auth_cfg_t
*cfg
, chunk_t v
)
1016 return parse_cert(cfg
, AUTH_RULE_CA_CERT
, v
);
1020 * Parse revocation status
1022 CALLBACK(parse_revocation
, bool,
1023 auth_cfg_t
*cfg
, chunk_t v
)
1025 enum_map_t map
[] = {
1026 { "strict", VALIDATION_GOOD
},
1027 { "ifuri", VALIDATION_SKIPPED
},
1031 if (parse_map(map
, countof(map
), &d
, v
))
1033 cfg
->add(cfg
, AUTH_RULE_CRL_VALIDATION
, d
);
1040 * Parse list items to comma separated strings
1042 CALLBACK(parse_stringlist
, bool,
1043 char **out
, chunk_t v
)
1047 if (!chunk_printable(v
, NULL
, ' '))
1054 if (asprintf(out
, "%s, %.*s", current
, (int)v
.len
, v
.ptr
) == -1)
1062 if (asprintf(out
, "%.*s", (int)v
.len
, v
.ptr
) == -1)
1071 * Parse an fragmentation_t
1073 CALLBACK(parse_frag
, bool,
1074 fragmentation_t
*out
, chunk_t v
)
1076 enum_map_t map
[] = {
1077 { "yes", FRAGMENTATION_YES
},
1078 { "no", FRAGMENTATION_NO
},
1079 { "force", FRAGMENTATION_FORCE
},
1083 if (parse_map(map
, countof(map
), &d
, v
))
1092 * Parse a cert_policy_t
1094 CALLBACK(parse_send_cert
, bool,
1095 cert_policy_t
*out
, chunk_t v
)
1097 enum_map_t map
[] = {
1098 { "ifasked", CERT_SEND_IF_ASKED
},
1099 { "always", CERT_ALWAYS_SEND
},
1100 { "never", CERT_NEVER_SEND
},
1104 if (parse_map(map
, countof(map
), &d
, v
))
1113 * Parse a unique_policy_t
1115 CALLBACK(parse_unique
, bool,
1116 unique_policy_t
*out
, chunk_t v
)
1118 enum_map_t map
[] = {
1119 { "never", UNIQUE_NEVER
},
1120 { "no", UNIQUE_NO
},
1121 { "replace", UNIQUE_REPLACE
},
1122 { "keep", UNIQUE_KEEP
},
1126 if (parse_map(map
, countof(map
), &d
, v
))
1135 * Parse host_t into a list
1137 CALLBACK(parse_hosts
, bool,
1138 linked_list_t
*list
, chunk_t v
)
1143 if (!vici_stringify(v
, buf
, sizeof(buf
)))
1147 host
= host_create_from_string(buf
, 0);
1152 list
->insert_last(list
, host
);
1156 CALLBACK(child_li
, bool,
1157 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1159 parse_rule_t rules
[] = {
1160 { "ah_proposals", parse_ah_proposal
, child
->proposals
},
1161 { "esp_proposals", parse_esp_proposal
, child
->proposals
},
1162 { "local_ts", parse_ts
, child
->local_ts
},
1163 { "remote_ts", parse_ts
, child
->remote_ts
},
1166 return parse_rules(rules
, countof(rules
), name
, value
,
1167 &child
->request
->reply
);
1170 CALLBACK(child_kv
, bool,
1171 child_data_t
*child
, vici_message_t
*message
, char *name
, chunk_t value
)
1173 parse_rule_t rules
[] = {
1174 { "updown", parse_string
, &child
->updown
},
1175 { "hostaccess", parse_bool
, &child
->hostaccess
},
1176 { "mode", parse_mode
, &child
->mode
},
1177 { "rekey_time", parse_time
, &child
->lft
.time
.rekey
},
1178 { "life_time", parse_time
, &child
->lft
.time
.life
},
1179 { "rand_time", parse_time
, &child
->lft
.time
.jitter
},
1180 { "rekey_bytes", parse_bytes
, &child
->lft
.bytes
.rekey
},
1181 { "life_bytes", parse_bytes
, &child
->lft
.bytes
.life
},
1182 { "rand_bytes", parse_bytes
, &child
->lft
.bytes
.jitter
},
1183 { "rekey_packets", parse_uint64
, &child
->lft
.packets
.rekey
},
1184 { "life_packets", parse_uint64
, &child
->lft
.packets
.life
},
1185 { "rand_packets", parse_uint64
, &child
->lft
.packets
.jitter
},
1186 { "dpd_action", parse_action
, &child
->dpd_action
},
1187 { "start_action", parse_action
, &child
->start_action
},
1188 { "ipcomp", parse_bool
, &child
->ipcomp
},
1189 { "inactivity", parse_time
, &child
->inactivity
},
1190 { "reqid", parse_uint32
, &child
->reqid
},
1191 { "mark_in", parse_mark
, &child
->mark_in
},
1192 { "mark_out", parse_mark
, &child
->mark_out
},
1193 { "tfc_padding", parse_uint32
, &child
->tfc
},
1196 return parse_rules(rules
, countof(rules
), name
, value
,
1197 &child
->request
->reply
);
1200 CALLBACK(auth_li
, bool,
1201 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1203 parse_rule_t rules
[] = {
1204 { "groups", parse_group
, auth
->cfg
},
1205 { "certs", parse_certs
, auth
->cfg
},
1206 { "cacerts", parse_cacerts
, auth
->cfg
},
1209 return parse_rules(rules
, countof(rules
), name
, value
,
1210 &auth
->request
->reply
);
1213 CALLBACK(auth_kv
, bool,
1214 auth_data_t
*auth
, vici_message_t
*message
, char *name
, chunk_t value
)
1216 parse_rule_t rules
[] = {
1217 { "auth", parse_auth
, auth
->cfg
},
1218 { "id", parse_ike_id
, auth
->cfg
},
1219 { "aaa_id", parse_aaa_id
, auth
->cfg
},
1220 { "eap_id", parse_eap_id
, auth
->cfg
},
1221 { "xauth_id", parse_xauth_id
, auth
->cfg
},
1222 { "revocation", parse_revocation
, auth
->cfg
},
1225 return parse_rules(rules
, countof(rules
), name
, value
,
1226 &auth
->request
->reply
);
1229 CALLBACK(peer_li
, bool,
1230 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1232 parse_rule_t rules
[] = {
1233 { "local_addrs", parse_stringlist
, &peer
->local_addrs
},
1234 { "remote_addrs", parse_stringlist
, &peer
->remote_addrs
},
1235 { "proposals", parse_ike_proposal
, peer
->proposals
},
1236 { "vips", parse_hosts
, peer
->vips
},
1237 { "pools", parse_stringlist
, &peer
->pools
},
1240 return parse_rules(rules
, countof(rules
), name
, value
,
1241 &peer
->request
->reply
);
1244 CALLBACK(peer_kv
, bool,
1245 peer_data_t
*peer
, vici_message_t
*message
, char *name
, chunk_t value
)
1247 parse_rule_t rules
[] = {
1248 { "version", parse_uint32
, &peer
->version
},
1249 { "aggressive", parse_bool
, &peer
->aggressive
},
1250 { "pull", parse_bool
, &peer
->pull
},
1251 { "encap", parse_bool
, &peer
->encap
},
1252 { "mobike", parse_bool
, &peer
->mobike
},
1253 { "dpd_delay", parse_time
, &peer
->dpd_delay
},
1254 { "dpd_timeout", parse_time
, &peer
->dpd_timeout
},
1255 { "fragmentation", parse_frag
, &peer
->fragmentation
},
1256 { "send_certreq", parse_bool
, &peer
->send_certreq
},
1257 { "send_cert", parse_send_cert
, &peer
->send_cert
},
1258 { "keyingtries", parse_uint32
, &peer
->keyingtries
},
1259 { "unique", parse_unique
, &peer
->unique
},
1260 { "local_port", parse_uint32
, &peer
->local_port
},
1261 { "remote_port", parse_uint32
, &peer
->remote_port
},
1262 { "reauth_time", parse_time
, &peer
->reauth_time
},
1263 { "rekey_time", parse_time
, &peer
->rekey_time
},
1264 { "over_time", parse_time
, &peer
->over_time
},
1265 { "rand_time", parse_time
, &peer
->rand_time
},
1268 return parse_rules(rules
, countof(rules
), name
, value
,
1269 &peer
->request
->reply
);
1272 CALLBACK(children_sn
, bool,
1273 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1276 child_data_t child
= {
1277 .request
= peer
->request
,
1278 .proposals
= linked_list_create(),
1279 .local_ts
= linked_list_create(),
1280 .remote_ts
= linked_list_create(),
1281 .mode
= MODE_TUNNEL
,
1282 .dpd_action
= ACTION_NONE
,
1283 .start_action
= ACTION_NONE
,
1286 .rekey
= LFT_DEFAULT_CHILD_REKEY
,
1287 .life
= LFT_UNDEFINED
,
1288 .jitter
= LFT_UNDEFINED
,
1291 .life
= LFT_UNDEFINED
,
1292 .jitter
= LFT_UNDEFINED
,
1295 .life
= LFT_UNDEFINED
,
1296 .jitter
= LFT_UNDEFINED
,
1301 proposal_t
*proposal
;
1302 traffic_selector_t
*ts
;
1304 if (!message
->parse(message
, ctx
, NULL
, child_kv
, child_li
, &child
))
1306 free_child_data(&child
);
1310 if (child
.local_ts
->get_count(child
.local_ts
) == 0)
1312 child
.local_ts
->insert_last(child
.local_ts
,
1313 traffic_selector_create_dynamic(0, 0, 65535));
1315 if (child
.remote_ts
->get_count(child
.remote_ts
) == 0)
1317 child
.remote_ts
->insert_last(child
.remote_ts
,
1318 traffic_selector_create_dynamic(0, 0, 65535));
1320 if (child
.proposals
->get_count(child
.proposals
) == 0)
1322 child
.proposals
->insert_last(child
.proposals
,
1323 proposal_create_default(PROTO_ESP
));
1326 /* if no hard lifetime specified, add one at soft lifetime + 10% */
1327 if (child
.lft
.time
.life
== LFT_UNDEFINED
)
1329 child
.lft
.time
.life
= child
.lft
.time
.rekey
* 110 / 100;
1331 if (child
.lft
.bytes
.life
== LFT_UNDEFINED
)
1333 child
.lft
.bytes
.life
= child
.lft
.bytes
.rekey
* 110 / 100;
1335 if (child
.lft
.packets
.life
== LFT_UNDEFINED
)
1337 child
.lft
.packets
.life
= child
.lft
.packets
.rekey
* 110 / 100;
1339 /* if no rand time defined, use difference of hard and soft */
1340 if (child
.lft
.time
.jitter
== LFT_UNDEFINED
)
1342 child
.lft
.time
.jitter
= child
.lft
.time
.life
-
1343 min(child
.lft
.time
.life
, child
.lft
.time
.rekey
);
1345 if (child
.lft
.bytes
.jitter
== LFT_UNDEFINED
)
1347 child
.lft
.bytes
.jitter
= child
.lft
.bytes
.life
-
1348 min(child
.lft
.bytes
.life
, child
.lft
.bytes
.rekey
);
1350 if (child
.lft
.packets
.jitter
== LFT_UNDEFINED
)
1352 child
.lft
.packets
.jitter
= child
.lft
.packets
.life
-
1353 min(child
.lft
.packets
.life
, child
.lft
.packets
.rekey
);
1356 log_child_data(&child
, name
);
1358 cfg
= child_cfg_create(name
, &child
.lft
, child
.updown
,
1359 child
.hostaccess
, child
.mode
, child
.start_action
,
1360 child
.dpd_action
, ACTION_NONE
, child
.ipcomp
,
1361 child
.inactivity
, child
.reqid
, &child
.mark_in
,
1362 &child
.mark_out
, child
.tfc
);
1364 while (child
.local_ts
->remove_first(child
.local_ts
,
1365 (void**)&ts
) == SUCCESS
)
1367 cfg
->add_traffic_selector(cfg
, TRUE
, ts
);
1369 while (child
.remote_ts
->remove_first(child
.remote_ts
,
1370 (void**)&ts
) == SUCCESS
)
1372 cfg
->add_traffic_selector(cfg
, FALSE
, ts
);
1374 while (child
.proposals
->remove_first(child
.proposals
,
1375 (void**)&proposal
) == SUCCESS
)
1377 cfg
->add_proposal(cfg
, proposal
);
1380 peer
->children
->insert_last(peer
->children
, cfg
);
1382 free_child_data(&child
);
1387 CALLBACK(peer_sn
, bool,
1388 peer_data_t
*peer
, vici_message_t
*message
, vici_parse_context_t
*ctx
,
1391 if (strcaseeq(name
, "children"))
1393 return message
->parse(message
, ctx
, children_sn
, NULL
, NULL
, peer
);
1395 if (strcasepfx(name
, "local") ||
1396 strcasepfx(name
, "remote"))
1398 auth_data_t auth
= {
1399 .request
= peer
->request
,
1400 .cfg
= auth_cfg_create(),
1403 if (!message
->parse(message
, ctx
, NULL
, auth_kv
, auth_li
, &auth
))
1405 auth
.cfg
->destroy(auth
.cfg
);
1409 if (strcasepfx(name
, "local"))
1411 peer
->local
->insert_last(peer
->local
, auth
.cfg
);
1415 peer
->remote
->insert_last(peer
->remote
, auth
.cfg
);
1419 peer
->request
->reply
= create_reply("invalid section: %s", name
);
1424 * Find reqid of an existing CHILD_SA
1426 static u_int32_t
find_reqid(child_cfg_t
*cfg
)
1428 enumerator_t
*enumerator
, *children
;
1429 child_sa_t
*child_sa
;
1433 reqid
= charon
->traps
->find_reqid(charon
->traps
, cfg
);
1435 { /* already trapped */
1439 enumerator
= charon
->controller
->create_ike_sa_enumerator(
1440 charon
->controller
, TRUE
);
1441 while (!reqid
&& enumerator
->enumerate(enumerator
, &ike_sa
))
1443 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1444 while (children
->enumerate(children
, &child_sa
))
1446 if (streq(cfg
->get_name(cfg
), child_sa
->get_name(child_sa
)))
1448 reqid
= child_sa
->get_reqid(child_sa
);
1452 children
->destroy(children
);
1454 enumerator
->destroy(enumerator
);
1459 * Perform start actions associated to a child config
1461 static void run_start_action(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
,
1462 child_cfg_t
*child_cfg
)
1464 switch (child_cfg
->get_start_action(child_cfg
))
1466 case ACTION_RESTART
:
1467 DBG1(DBG_CFG
, "initiating '%s'", child_cfg
->get_name(child_cfg
));
1468 charon
->controller
->initiate(charon
->controller
,
1469 peer_cfg
->get_ref(peer_cfg
), child_cfg
->get_ref(child_cfg
),
1473 DBG1(DBG_CFG
, "installing '%s'", child_cfg
->get_name(child_cfg
));
1474 switch (child_cfg
->get_mode(child_cfg
))
1478 charon
->shunts
->install(charon
->shunts
, child_cfg
);
1481 charon
->traps
->install(charon
->traps
, peer_cfg
, child_cfg
,
1482 find_reqid(child_cfg
));
1492 * Undo start actions associated to a child config
1494 static void clear_start_action(private_vici_config_t
*this,
1495 child_cfg_t
*child_cfg
)
1497 enumerator_t
*enumerator
, *children
;
1498 child_sa_t
*child_sa
;
1500 u_int32_t reqid
= 0, *del
;
1501 array_t
*reqids
= NULL
;
1504 name
= child_cfg
->get_name(child_cfg
);
1505 switch (child_cfg
->get_start_action(child_cfg
))
1507 case ACTION_RESTART
:
1508 enumerator
= charon
->controller
->create_ike_sa_enumerator(
1509 charon
->controller
, TRUE
);
1510 while (enumerator
->enumerate(enumerator
, &ike_sa
))
1512 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
1513 while (children
->enumerate(children
, &child_sa
))
1515 reqid
= child_sa
->get_reqid(child_sa
);
1516 array_insert_create(&reqids
, ARRAY_TAIL
, &reqid
);
1518 children
->destroy(children
);
1520 enumerator
->destroy(enumerator
);
1522 if (array_count(reqids
))
1524 while (array_remove(reqids
, ARRAY_HEAD
, &del
))
1526 DBG1(DBG_CFG
, "closing '%s' #%u", name
, *del
);
1527 charon
->controller
->terminate_child(charon
->controller
,
1528 *del
, NULL
, NULL
, 0);
1530 array_destroy(reqids
);
1534 DBG1(DBG_CFG
, "uninstalling '%s'", name
);
1535 switch (child_cfg
->get_mode(child_cfg
))
1539 charon
->shunts
->uninstall(charon
->shunts
, name
);
1542 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
1543 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
1545 if (streq(name
, child_sa
->get_name(child_sa
)))
1547 reqid
= child_sa
->get_reqid(child_sa
);
1551 enumerator
->destroy(enumerator
);
1554 charon
->traps
->uninstall(charon
->traps
, reqid
);
1565 * Run start actions associated to all child configs of a peer config
1567 static void run_start_actions(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
1569 enumerator_t
*enumerator
;
1570 child_cfg_t
*child_cfg
;
1572 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
1573 while (enumerator
->enumerate(enumerator
, &child_cfg
))
1575 run_start_action(this, peer_cfg
, child_cfg
);
1577 enumerator
->destroy(enumerator
);
1581 * Undo start actions associated to all child configs of a peer config
1583 static void clear_start_actions(private_vici_config_t
*this,
1584 peer_cfg_t
*peer_cfg
)
1586 enumerator_t
*enumerator
;
1587 child_cfg_t
*child_cfg
;
1589 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
1590 while (enumerator
->enumerate(enumerator
, &child_cfg
))
1592 clear_start_action(this, child_cfg
);
1594 enumerator
->destroy(enumerator
);
1598 * Replace children of a peer config by a new config
1600 static void replace_children(private_vici_config_t
*this,
1601 peer_cfg_t
*from
, peer_cfg_t
*to
)
1603 enumerator_t
*enumerator
;
1606 enumerator
= to
->create_child_cfg_enumerator(to
);
1607 while (enumerator
->enumerate(enumerator
, &child
))
1609 to
->remove_child_cfg(to
, enumerator
);
1610 clear_start_action(this, child
);
1611 child
->destroy(child
);
1613 enumerator
->destroy(enumerator
);
1615 enumerator
= from
->create_child_cfg_enumerator(from
);
1616 while (enumerator
->enumerate(enumerator
, &child
))
1618 from
->remove_child_cfg(from
, enumerator
);
1619 to
->add_child_cfg(to
, child
);
1620 run_start_action(this, to
, child
);
1622 enumerator
->destroy(enumerator
);
1626 * Merge/replace a peer config with existing configs
1628 static void merge_config(private_vici_config_t
*this, peer_cfg_t
*peer_cfg
)
1630 enumerator_t
*enumerator
;
1631 peer_cfg_t
*current
;
1633 bool merged
= FALSE
;
1635 this->lock
->write_lock(this->lock
);
1637 enumerator
= this->conns
->create_enumerator(this->conns
);
1638 while (enumerator
->enumerate(enumerator
, ¤t
))
1640 if (streq(peer_cfg
->get_name(peer_cfg
), current
->get_name(current
)))
1642 ike_cfg
= current
->get_ike_cfg(current
);
1643 if (peer_cfg
->equals(peer_cfg
, current
) &&
1644 ike_cfg
->equals(ike_cfg
, peer_cfg
->get_ike_cfg(peer_cfg
)))
1646 DBG1(DBG_CFG
, "updated vici connection: %s",
1647 peer_cfg
->get_name(peer_cfg
));
1648 replace_children(this, peer_cfg
, current
);
1649 peer_cfg
->destroy(peer_cfg
);
1653 DBG1(DBG_CFG
, "replaced vici connection: %s",
1654 peer_cfg
->get_name(peer_cfg
));
1655 this->conns
->remove_at(this->conns
, enumerator
);
1656 clear_start_actions(this, current
);
1657 current
->destroy(current
);
1658 this->conns
->insert_last(this->conns
, peer_cfg
);
1659 run_start_actions(this, peer_cfg
);
1665 enumerator
->destroy(enumerator
);
1669 DBG1(DBG_CFG
, "added vici connection: %s", peer_cfg
->get_name(peer_cfg
));
1670 this->conns
->insert_last(this->conns
, peer_cfg
);
1671 run_start_actions(this, peer_cfg
);
1674 this->lock
->unlock(this->lock
);
1677 CALLBACK(config_sn
, bool,
1678 request_data_t
*request
, vici_message_t
*message
,
1679 vici_parse_context_t
*ctx
, char *name
)
1681 peer_data_t peer
= {
1683 .local
= linked_list_create(),
1684 .remote
= linked_list_create(),
1685 .vips
= linked_list_create(),
1686 .children
= linked_list_create(),
1687 .proposals
= linked_list_create(),
1689 .send_certreq
= TRUE
,
1691 .send_cert
= CERT_SEND_IF_ASKED
,
1693 .local_port
= IKEV2_UDP_PORT
,
1694 .remote_port
= IKEV2_UDP_PORT
,
1695 .fragmentation
= FRAGMENTATION_NO
,
1696 .unique
= UNIQUE_NO
,
1698 .rekey_time
= LFT_DEFAULT_IKE_REKEY
,
1699 .over_time
= LFT_UNDEFINED
,
1700 .rand_time
= LFT_UNDEFINED
,
1702 enumerator_t
*enumerator
;
1703 peer_cfg_t
*peer_cfg
;
1705 child_cfg_t
*child_cfg
;
1706 auth_cfg_t
*auth_cfg
;
1707 proposal_t
*proposal
;
1711 DBG2(DBG_CFG
, " conn %s:", name
);
1713 if (!message
->parse(message
, ctx
, peer_sn
, peer_kv
, peer_li
, &peer
))
1715 free_peer_data(&peer
);
1719 if (peer
.local
->get_count(peer
.local
) == 0)
1721 free_peer_data(&peer
);
1722 peer
.request
->reply
= create_reply("missing local auth config");
1725 if (peer
.remote
->get_count(peer
.remote
) == 0)
1727 auth_cfg
= auth_cfg_create();
1728 peer
.remote
->insert_last(peer
.remote
, auth_cfg
);
1730 if (peer
.proposals
->get_count(peer
.proposals
) == 0)
1732 peer
.proposals
->insert_last(peer
.proposals
,
1733 proposal_create_default(PROTO_IKE
));
1735 if (!peer
.local_addrs
)
1737 peer
.local_addrs
= strdup("%any");
1739 if (!peer
.remote_addrs
)
1741 peer
.remote_addrs
= strdup("%any");
1744 if (peer
.over_time
== LFT_UNDEFINED
)
1746 /* default over_time to 10% of rekey/reauth time if not given */
1747 peer
.over_time
= max(peer
.rekey_time
, peer
.reauth_time
) / 10;
1749 if (peer
.rand_time
== LFT_UNDEFINED
)
1751 /* default rand_time to over_time if not given */
1752 peer
.rand_time
= min(peer
.over_time
,
1753 max(peer
.rekey_time
, peer
.reauth_time
) / 2);
1756 log_peer_data(&peer
);
1758 ike_cfg
= ike_cfg_create(peer
.version
, peer
.send_certreq
, peer
.encap
,
1759 peer
.local_addrs
, peer
.local_port
,
1760 peer
.remote_addrs
, peer
.remote_port
,
1761 peer
.fragmentation
, 0);
1762 peer_cfg
= peer_cfg_create(name
, ike_cfg
, peer
.send_cert
, peer
.unique
,
1763 peer
.keyingtries
, peer
.rekey_time
, peer
.reauth_time
,
1764 peer
.rand_time
, peer
.over_time
, peer
.mobike
,
1765 peer
.aggressive
, peer
.pull
,
1766 peer
.dpd_delay
, peer
.dpd_timeout
,
1769 while (peer
.local
->remove_first(peer
.local
,
1770 (void**)&auth_cfg
) == SUCCESS
)
1772 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, TRUE
);
1774 while (peer
.remote
->remove_first(peer
.remote
,
1775 (void**)&auth_cfg
) == SUCCESS
)
1777 peer_cfg
->add_auth_cfg(peer_cfg
, auth_cfg
, FALSE
);
1779 while (peer
.children
->remove_first(peer
.children
,
1780 (void**)&child_cfg
) == SUCCESS
)
1782 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
1784 while (peer
.proposals
->remove_first(peer
.proposals
,
1785 (void**)&proposal
) == SUCCESS
)
1787 ike_cfg
->add_proposal(ike_cfg
, proposal
);
1789 while (peer
.vips
->remove_first(peer
.vips
, (void**)&host
) == SUCCESS
)
1791 peer_cfg
->add_virtual_ip(peer_cfg
, host
);
1795 enumerator
= enumerator_create_token(peer
.pools
, ",", " ");
1796 while (enumerator
->enumerate(enumerator
, &str
))
1798 peer_cfg
->add_pool(peer_cfg
, str
);
1800 enumerator
->destroy(enumerator
);
1803 free_peer_data(&peer
);
1805 merge_config(request
->this, peer_cfg
);
1810 CALLBACK(load_conn
, vici_message_t
*,
1811 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
1813 request_data_t request
= {
1817 if (!message
->parse(message
, NULL
, config_sn
, NULL
, NULL
, &request
))
1821 return request
.reply
;
1823 return create_reply("parsing request failed");
1825 return create_reply(NULL
);
1828 CALLBACK(unload_conn
, vici_message_t
*,
1829 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
1831 enumerator_t
*enumerator
;
1836 conn
= message
->get_str(message
, NULL
, "name");
1839 return create_reply("missing connection name to unload");
1842 this->lock
->write_lock(this->lock
);
1843 enumerator
= this->conns
->create_enumerator(this->conns
);
1844 while (enumerator
->enumerate(enumerator
, &cfg
))
1846 if (streq(cfg
->get_name(cfg
), conn
))
1848 this->conns
->remove_at(this->conns
, enumerator
);
1854 enumerator
->destroy(enumerator
);
1855 this->lock
->unlock(this->lock
);
1859 return create_reply("connection '%s' not found for unloading", conn
);
1861 return create_reply(NULL
);
1864 CALLBACK(get_conns
, vici_message_t
*,
1865 private_vici_config_t
*this, char *name
, u_int id
, vici_message_t
*message
)
1867 vici_builder_t
*builder
;
1868 enumerator_t
*enumerator
;
1871 builder
= vici_builder_create();
1872 builder
->begin_list(builder
, "conns");
1874 this->lock
->read_lock(this->lock
);
1875 enumerator
= this->conns
->create_enumerator(this->conns
);
1876 while (enumerator
->enumerate(enumerator
, &cfg
))
1878 builder
->add_li(builder
, "%s", cfg
->get_name(cfg
));
1880 enumerator
->destroy(enumerator
);
1881 this->lock
->unlock(this->lock
);
1883 builder
->end_list(builder
);
1885 return builder
->finalize(builder
);
1888 static void manage_command(private_vici_config_t
*this,
1889 char *name
, vici_command_cb_t cb
, bool reg
)
1891 this->dispatcher
->manage_command(this->dispatcher
, name
,
1892 reg ? cb
: NULL
, this);
1896 * (Un-)register dispatcher functions
1898 static void manage_commands(private_vici_config_t
*this, bool reg
)
1900 manage_command(this, "load-conn", load_conn
, reg
);
1901 manage_command(this, "unload-conn", unload_conn
, reg
);
1902 manage_command(this, "get-conns", get_conns
, reg
);
1905 METHOD(vici_config_t
, destroy
, void,
1906 private_vici_config_t
*this)
1908 manage_commands(this, FALSE
);
1909 this->conns
->destroy_offset(this->conns
, offsetof(peer_cfg_t
, destroy
));
1910 this->lock
->destroy(this->lock
);
1917 vici_config_t
*vici_config_create(vici_dispatcher_t
*dispatcher
)
1919 private_vici_config_t
*this;
1924 .create_peer_cfg_enumerator
= _create_peer_cfg_enumerator
,
1925 .create_ike_cfg_enumerator
= _create_ike_cfg_enumerator
,
1926 .get_peer_cfg_by_name
= _get_peer_cfg_by_name
,
1928 .destroy
= _destroy
,
1930 .dispatcher
= dispatcher
,
1931 .conns
= linked_list_create(),
1932 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
1935 manage_commands(this, TRUE
);
1937 return &this->public;