swanctl: Stop logging with Ctrl+C on Windows as well
[strongswan.git] / src / swanctl / commands / load_pools.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #define _GNU_SOURCE
17 #include <stdio.h>
18 #include <errno.h>
19 #include <limits.h>
20
21 #include "command.h"
22 #include "swanctl.h"
23
24 /**
25 * Add a vici list from a comma separated string value
26 */
27 static void add_list_key(vici_req_t *req, char *key, char *value)
28 {
29 enumerator_t *enumerator;
30 char *token;
31
32 vici_begin_list(req, key);
33 enumerator = enumerator_create_token(value, ",", " ");
34 while (enumerator->enumerate(enumerator, &token))
35 {
36 vici_add_list_itemf(req, "%s", token);
37 }
38 enumerator->destroy(enumerator);
39 vici_end_list(req);
40 }
41
42 /**
43 * Translate setting key/values from a section into vici key-values/lists
44 */
45 static void add_key_values(vici_req_t *req, settings_t *cfg, char *section)
46 {
47 enumerator_t *enumerator;
48 char *key, *value;
49
50 enumerator = cfg->create_key_value_enumerator(cfg, section);
51 while (enumerator->enumerate(enumerator, &key, &value))
52 {
53 /* pool subnet is encoded as key/value, all other attributes as list */
54 if (streq(key, "addrs"))
55 {
56 vici_add_key_valuef(req, key, "%s", value);
57 }
58 else
59 {
60 add_list_key(req, key, value);
61 }
62 }
63 enumerator->destroy(enumerator);
64 }
65
66 /**
67 * Load a pool configuration
68 */
69 static bool load_pool(vici_conn_t *conn, settings_t *cfg,
70 char *section, bool raw)
71 {
72 vici_req_t *req;
73 vici_res_t *res;
74 bool ret = TRUE;
75 char buf[128];
76
77 snprintf(buf, sizeof(buf), "%s.%s", "pools", section);
78
79 req = vici_begin("load-pool");
80
81 vici_begin_section(req, section);
82 add_key_values(req, cfg, buf);
83 vici_end_section(req);
84
85 res = vici_submit(req, conn);
86 if (!res)
87 {
88 fprintf(stderr, "load-pool request failed: %s\n", strerror(errno));
89 return FALSE;
90 }
91 if (raw)
92 {
93 vici_dump(res, "load-pool reply", stdout);
94 }
95 else if (!streq(vici_find_str(res, "no", "success"), "yes"))
96 {
97 fprintf(stderr, "loading pool '%s' failed: %s\n",
98 section, vici_find_str(res, "", "errmsg"));
99 ret = FALSE;
100 }
101 else
102 {
103 printf("loaded pool '%s'\n", section);
104 }
105 vici_free_res(res);
106 return ret;
107 }
108
109 CALLBACK(list_pool, int,
110 linked_list_t *list, vici_res_t *res, char *name)
111 {
112 list->insert_last(list, strdup(name));
113 return 0;
114 }
115
116 /**
117 * Create a list of currently loaded pools
118 */
119 static linked_list_t* list_pools(vici_conn_t *conn, bool raw)
120 {
121 linked_list_t *list;
122 vici_res_t *res;
123
124 list = linked_list_create();
125
126 res = vici_submit(vici_begin("get-pools"), conn);
127 if (res)
128 {
129 if (raw)
130 {
131 vici_dump(res, "get-pools reply", stdout);
132 }
133 vici_parse_cb(res, list_pool, NULL, NULL, list);
134 vici_free_res(res);
135 }
136 return list;
137 }
138
139 /**
140 * Remove and free a string from a list
141 */
142 static void remove_from_list(linked_list_t *list, char *str)
143 {
144 enumerator_t *enumerator;
145 char *current;
146
147 enumerator = list->create_enumerator(list);
148 while (enumerator->enumerate(enumerator, &current))
149 {
150 if (streq(current, str))
151 {
152 list->remove_at(list, enumerator);
153 free(current);
154 }
155 }
156 enumerator->destroy(enumerator);
157 }
158
159 /**
160 * Unload a pool by name
161 */
162 static bool unload_pool(vici_conn_t *conn, char *name, bool raw)
163 {
164 vici_req_t *req;
165 vici_res_t *res;
166 bool ret = TRUE;
167
168 req = vici_begin("unload-pool");
169 vici_add_key_valuef(req, "name", "%s", name);
170 res = vici_submit(req, conn);
171 if (!res)
172 {
173 fprintf(stderr, "unload-pool request failed: %s\n", strerror(errno));
174 return FALSE;
175 }
176 if (raw)
177 {
178 vici_dump(res, "unload-pool reply", stdout);
179 }
180 else if (!streq(vici_find_str(res, "no", "success"), "yes"))
181 {
182 fprintf(stderr, "unloading pool '%s' failed: %s\n",
183 name, vici_find_str(res, "", "errmsg"));
184 ret = FALSE;
185 }
186 vici_free_res(res);
187 return ret;
188 }
189
190 static int load_pools(vici_conn_t *conn)
191 {
192 bool raw = FALSE;
193 u_int found = 0, loaded = 0, unloaded = 0;
194 char *arg, *section;
195 enumerator_t *enumerator;
196 linked_list_t *pools;
197 settings_t *cfg;
198
199 while (TRUE)
200 {
201 switch (command_getopt(&arg))
202 {
203 case 'h':
204 return command_usage(NULL);
205 case 'r':
206 raw = TRUE;
207 continue;
208 case EOF:
209 break;
210 default:
211 return command_usage("invalid --load-pools option");
212 }
213 break;
214 }
215
216 cfg = settings_create(SWANCTL_CONF);
217 if (!cfg)
218 {
219 fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF);
220 return EINVAL;
221 }
222
223 pools = list_pools(conn, raw);
224
225 enumerator = cfg->create_section_enumerator(cfg, "pools");
226 while (enumerator->enumerate(enumerator, &section))
227 {
228 remove_from_list(pools, section);
229 found++;
230 if (load_pool(conn, cfg, section, raw))
231 {
232 loaded++;
233 }
234 }
235 enumerator->destroy(enumerator);
236
237 cfg->destroy(cfg);
238
239 /* unload all pools in daemon, but not in file */
240 while (pools->remove_first(pools, (void**)&section) == SUCCESS)
241 {
242 if (unload_pool(conn, section, raw))
243 {
244 unloaded++;
245 }
246 free(section);
247 }
248 pools->destroy(pools);
249
250 if (raw)
251 {
252 return 0;
253 }
254 if (found == 0)
255 {
256 printf("no pools found, %u unloaded\n", unloaded);
257 return 0;
258 }
259 if (loaded == found)
260 {
261 printf("successfully loaded %u pools, %u unloaded\n",
262 loaded, unloaded);
263 return 0;
264 }
265 fprintf(stderr, "loaded %u of %u pools, %u failed to load, "
266 "%u unloaded\n", loaded, found, found - loaded, unloaded);
267 return EINVAL;
268 }
269
270 /**
271 * Register the command.
272 */
273 static void __attribute__ ((constructor))reg()
274 {
275 command_register((command_t) {
276 load_pools, 'a', "load-pools", "(re-)load pool configuration",
277 {"[--raw]"},
278 {
279 {"help", 'h', 0, "show usage information"},
280 {"raw", 'r', 0, "dump raw response message"},
281 }
282 });
283 }