b6842e00df5c4c9aa2ebe86eed560b4c11321445
[strongswan.git] / src / swanctl / commands / load_conns.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 #include "command.h"
17
18 #include <errno.h>
19
20 /**
21 * Check if we should handle a key as a list of comma separated values
22 */
23 static bool is_list_key(char *key)
24 {
25 char *keys[] = {
26 "local_addrs",
27 "remote_addrs",
28 "proposals",
29 "esp_proposals",
30 "ah_proposals",
31 "local_ts",
32 "remote_ts",
33 "vips",
34 };
35 int i;
36
37 for (i = 0; i < countof(keys); i++)
38 {
39 if (strcaseeq(keys[i], key))
40 {
41 return TRUE;
42 }
43 }
44 return FALSE;
45 }
46
47 /**
48 * Add a vici list from a comma separated string value
49 */
50 static void add_list_key(vici_req_t *req, char *key, char *value)
51 {
52 enumerator_t *enumerator;
53 char *token;
54
55 vici_begin_list(req, key);
56 enumerator = enumerator_create_token(value, ",", " ");
57 while (enumerator->enumerate(enumerator, &token))
58 {
59 vici_add_list_itemf(req, "%s", token);
60 }
61 enumerator->destroy(enumerator);
62 vici_end_list(req);
63 }
64
65 /**
66 * Translate setting key/values from a section into vici key-values/lists
67 */
68 static void add_key_values(vici_req_t *req, settings_t *cfg, char *section)
69 {
70 enumerator_t *enumerator;
71 char *key, *value;
72
73 enumerator = cfg->create_key_value_enumerator(cfg, section);
74 while (enumerator->enumerate(enumerator, &key, &value))
75 {
76 if (is_list_key(key))
77 {
78 add_list_key(req, key, value);
79 }
80 else
81 {
82 vici_add_key_valuef(req, key, "%s", value);
83 }
84 }
85 enumerator->destroy(enumerator);
86 }
87
88 /**
89 * Translate a settings section to a vici section
90 */
91 static void add_sections(vici_req_t *req, settings_t *cfg, char *section)
92 {
93 enumerator_t *enumerator;
94 char *name, buf[256];
95
96 enumerator = cfg->create_section_enumerator(cfg, section);
97 while (enumerator->enumerate(enumerator, &name))
98 {
99 vici_begin_section(req, name);
100 snprintf(buf, sizeof(buf), "%s.%s", section, name);
101 add_key_values(req, cfg, buf);
102 add_sections(req, cfg, buf);
103 vici_end_section(req);
104 }
105 enumerator->destroy(enumerator);
106 }
107
108 /**
109 * Load an IKE_SA config with CHILD_SA configs from a section
110 */
111 static bool load_conn(vici_conn_t *conn, settings_t *cfg,
112 char *section, bool raw)
113 {
114 vici_req_t *req;
115 vici_res_t *res;
116 bool ret = TRUE;
117 char buf[128];
118
119 snprintf(buf, sizeof(buf), "%s.%s", "connections", section);
120
121 req = vici_begin("load-conn");
122
123 vici_begin_section(req, section);
124 add_key_values(req, cfg, buf);
125 add_sections(req, cfg, buf);
126 vici_end_section(req);
127
128 res = vici_submit(req, conn);
129 if (!res)
130 {
131 fprintf(stderr, "load-conn request failed: %s\n", strerror(errno));
132 return FALSE;
133 }
134 if (raw)
135 {
136 vici_dump(res, "load-conn reply", stdout);
137 }
138 else if (!streq(vici_find_str(res, "no", "success"), "yes"))
139 {
140 fprintf(stderr, "loading connection '%s' failed: %s\n",
141 section, vici_find_str(res, "", "errmsg"));
142 ret = FALSE;
143 }
144 vici_free_res(res);
145 return ret;
146 }
147
148 static int load_conns(vici_conn_t *conn)
149 {
150 bool raw = FALSE;
151 u_int found = 0, loaded = 0;
152 char *arg, *section;
153 enumerator_t *enumerator;
154 settings_t *cfg;
155
156 while (TRUE)
157 {
158 switch (command_getopt(&arg))
159 {
160 case 'h':
161 return command_usage(NULL);
162 case 'r':
163 raw = TRUE;
164 continue;
165 case EOF:
166 break;
167 default:
168 return command_usage("invalid --load-conns option");
169 }
170 break;
171 }
172
173 cfg = settings_create(CONF_FILE);
174 if (!cfg)
175 {
176 fprintf(stderr, "parsing '%s' failed\n", CONF_FILE);
177 return EINVAL;
178 }
179
180 enumerator = cfg->create_section_enumerator(cfg, "connections");
181 while (enumerator->enumerate(enumerator, &section))
182 {
183 found++;
184 if (load_conn(conn, cfg, section, raw))
185 {
186 loaded++;
187 }
188 }
189 enumerator->destroy(enumerator);
190
191 cfg->destroy(cfg);
192
193 if (raw)
194 {
195 return 0;
196 }
197 if (found == 0)
198 {
199 printf("no connections found\n");
200 return 0;
201 }
202 if (loaded == found)
203 {
204 printf("successfully loaded %u connections\n", loaded);
205 return 0;
206 }
207 fprintf(stderr, "loaded %u of %u connections, %u failed to load\n",
208 loaded, found, found - loaded);
209 return EINVAL;
210 }
211
212 /**
213 * Register the command.
214 */
215 static void __attribute__ ((constructor))reg()
216 {
217 command_register((command_t) {
218 load_conns, 'c', "load-conns", "(re-)load connection configuration",
219 {"[--raw]"},
220 {
221 {"help", 'h', 0, "show usage information"},
222 {"raw", 'r', 0, "dump raw response message"},
223 }
224 });
225 }