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
23 * Check if we should handle a key as a list of comma separated values
25 static bool is_list_key(char *key
)
39 for (i
= 0; i
< countof(keys
); i
++)
41 if (strcaseeq(keys
[i
], key
))
50 * Add a vici list from a comma separated string value
52 static void add_list_key(vici_req_t
*req
, char *key
, char *value
)
54 enumerator_t
*enumerator
;
57 vici_begin_list(req
, key
);
58 enumerator
= enumerator_create_token(value
, ",", " ");
59 while (enumerator
->enumerate(enumerator
, &token
))
61 vici_add_list_itemf(req
, "%s", token
);
63 enumerator
->destroy(enumerator
);
68 * Translate setting key/values from a section into vici key-values/lists
70 static void add_key_values(vici_req_t
*req
, settings_t
*cfg
, char *section
)
72 enumerator_t
*enumerator
;
75 enumerator
= cfg
->create_key_value_enumerator(cfg
, section
);
76 while (enumerator
->enumerate(enumerator
, &key
, &value
))
80 add_list_key(req
, key
, value
);
84 vici_add_key_valuef(req
, key
, "%s", value
);
87 enumerator
->destroy(enumerator
);
91 * Translate a settings section to a vici section
93 static void add_sections(vici_req_t
*req
, settings_t
*cfg
, char *section
)
95 enumerator_t
*enumerator
;
98 enumerator
= cfg
->create_section_enumerator(cfg
, section
);
99 while (enumerator
->enumerate(enumerator
, &name
))
101 vici_begin_section(req
, name
);
102 snprintf(buf
, sizeof(buf
), "%s.%s", section
, name
);
103 add_key_values(req
, cfg
, buf
);
104 add_sections(req
, cfg
, buf
);
105 vici_end_section(req
);
107 enumerator
->destroy(enumerator
);
111 * Load an IKE_SA config with CHILD_SA configs from a section
113 static bool load_conn(vici_conn_t
*conn
, settings_t
*cfg
,
114 char *section
, bool raw
)
121 snprintf(buf
, sizeof(buf
), "%s.%s", "connections", section
);
123 req
= vici_begin("load-conn");
125 vici_begin_section(req
, section
);
126 add_key_values(req
, cfg
, buf
);
127 add_sections(req
, cfg
, buf
);
128 vici_end_section(req
);
130 res
= vici_submit(req
, conn
);
133 fprintf(stderr
, "load-conn request failed: %s\n", strerror(errno
));
138 vici_dump(res
, "load-conn reply", stdout
);
140 else if (!streq(vici_find_str(res
, "no", "success"), "yes"))
142 fprintf(stderr
, "loading connection '%s' failed: %s\n",
143 section
, vici_find_str(res
, "", "errmsg"));
150 CALLBACK(list_conn
, int,
151 linked_list_t
*list
, vici_res_t
*res
, char *name
, void *value
, int len
)
153 if (streq(name
, "conns"))
157 if (asprintf(&str
, "%.*s", len
, value
) != -1)
159 list
->insert_last(list
, str
);
166 * Create a list of currently loaded connections
168 static linked_list_t
* list_conns(vici_conn_t
*conn
, bool raw
)
173 list
= linked_list_create();
175 res
= vici_submit(vici_begin("get-conns"), conn
);
180 vici_dump(res
, "get-conns reply", stdout
);
182 vici_parse_cb(res
, NULL
, NULL
, list_conn
, list
);
189 * Remove and free a string from a list
191 static void remove_from_list(linked_list_t
*list
, char *str
)
193 enumerator_t
*enumerator
;
196 enumerator
= list
->create_enumerator(list
);
197 while (enumerator
->enumerate(enumerator
, ¤t
))
199 if (streq(current
, str
))
201 list
->remove_at(list
, enumerator
);
205 enumerator
->destroy(enumerator
);
209 * Unload a connection by name
211 static bool unload_conn(vici_conn_t
*conn
, char *name
, bool raw
)
217 req
= vici_begin("unload-conn");
218 vici_add_key_valuef(req
, "name", "%s", name
);
219 res
= vici_submit(req
, conn
);
222 fprintf(stderr
, "unload-conn request failed: %s\n", strerror(errno
));
227 vici_dump(res
, "unload-conn reply", stdout
);
229 else if (!streq(vici_find_str(res
, "no", "success"), "yes"))
231 fprintf(stderr
, "unloading connection '%s' failed: %s\n",
232 name
, vici_find_str(res
, "", "errmsg"));
239 static int load_conns(vici_conn_t
*conn
)
242 u_int found
= 0, loaded
= 0, unloaded
= 0;
244 enumerator_t
*enumerator
;
245 linked_list_t
*conns
;
250 switch (command_getopt(&arg
))
253 return command_usage(NULL
);
260 return command_usage("invalid --load-conns option");
265 cfg
= settings_create(CONF_FILE
);
268 fprintf(stderr
, "parsing '%s' failed\n", CONF_FILE
);
272 conns
= list_conns(conn
, raw
);
274 enumerator
= cfg
->create_section_enumerator(cfg
, "connections");
275 while (enumerator
->enumerate(enumerator
, §ion
))
277 remove_from_list(conns
, section
);
279 if (load_conn(conn
, cfg
, section
, raw
))
284 enumerator
->destroy(enumerator
);
288 /* unload all connection in daemon, but not in file */
289 while (conns
->remove_first(conns
, (void**)§ion
) == SUCCESS
)
291 if (unload_conn(conn
, section
, raw
))
297 conns
->destroy(conns
);
305 printf("no connections found, %u unloaded\n", unloaded
);
310 printf("successfully loaded %u connections, %u unloaded\n",
314 fprintf(stderr
, "loaded %u of %u connections, %u failed to load, "
315 "%u unloaded\n", loaded
, found
, found
- loaded
, unloaded
);
320 * Register the command.
322 static void __attribute__ ((constructor
))reg()
324 command_register((command_t
) {
325 load_conns
, 'c', "load-conns", "(re-)load connection configuration",
328 {"help", 'h', 0, "show usage information"},
329 {"raw", 'r', 0, "dump raw response message"},