]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/swanctl/commands/list_conns.c
github: Use latest SonarQube action
[thirdparty/strongswan.git] / src / swanctl / commands / list_conns.c
CommitLineData
51bdc1f3 1/*
19ef2aec 2 * Copyright (C) 2016-2018 Andreas Steffen
51bdc1f3 3 * Copyright (C) 2014 Martin Willi
51bdc1f3 4 *
19ef2aec 5 * Copyright (C) secunet Security Networks AG
afcd4661 6 *
51bdc1f3
MW
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18#define _GNU_SOURCE
19#include <stdio.h>
20#include <errno.h>
21
b67f7fb8 22#include "swanctl.h"
51bdc1f3
MW
23#include "command.h"
24
25#include <collections/hashtable.h>
26
27/**
28 * Free hashtable with contained strings
29 */
30static void free_hashtable(hashtable_t *hashtable)
31{
32 enumerator_t *enumerator;
33 char *str;
34
35 enumerator = hashtable->create_enumerator(hashtable);
36 while (enumerator->enumerate(enumerator, NULL, &str))
37 {
38 free(str);
39 }
40 enumerator->destroy(enumerator);
41
42 hashtable->destroy(hashtable);
43}
44
45CALLBACK(values, int,
46 hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
47{
48 chunk_t chunk;
49 char *str;
50
51 chunk = chunk_create(value, len);
52 if (chunk_printable(chunk, NULL, ' '))
53 {
54 if (asprintf(&str, "%.*s", len, value) >= 0)
55 {
56 free(sa->put(sa, name, str));
57 }
58 }
59 return 0;
60}
61
62
63CALLBACK(list, int,
64 hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
65{
66 chunk_t chunk;
67 char *str;
68
69 chunk = chunk_create(value, len);
70 if (chunk_printable(chunk, NULL, ' '))
71 {
72 str = sa->get(sa, name);
73 if (asprintf(&str, "%s%s%.*s",
74 str ?: "", str ? " " : "", len, value) >= 0)
75 {
76 free(sa->put(sa, name, str));
77 }
78 }
79 return 0;
80}
81
82CALLBACK(children_sn, int,
83 hashtable_t *ike, vici_res_t *res, char *name)
84{
85 hashtable_t *child;
b9522f9d 86 char *mode, *interface, *priority;
4eaf08c3
AS
87 char *rekey_time, *rekey_bytes, *rekey_packets, *dpd_action, *dpd_delay;
88 bool no_time, no_bytes, no_packets, no_dpd, or = FALSE;
51bdc1f3
MW
89 int ret;
90
91 child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
92 ret = vici_parse_cb(res, NULL, values, list, child);
93 if (ret == 0)
94 {
b9522f9d
AS
95 mode = child->get(child, "mode");
96 printf(" %s: %s, ", name, mode);
b1df6312
AS
97
98 rekey_time = child->get(child, "rekey_time");
99 rekey_bytes = child->get(child, "rekey_bytes");
100 rekey_packets = child->get(child, "rekey_packets");
4eaf08c3
AS
101 dpd_action = child->get(child, "dpd_action");
102 dpd_delay = ike->get(ike, "dpd_delay");
103
b1df6312
AS
104 no_time = streq(rekey_time, "0");
105 no_bytes = streq(rekey_bytes, "0");
106 no_packets = streq(rekey_packets, "0");
4eaf08c3 107 no_dpd = streq(dpd_delay, "0");
b1df6312 108
b9522f9d
AS
109 if (strcaseeq(mode, "PASS") || strcaseeq(mode, "DROP") ||
110 (no_time && no_bytes && no_packets))
b1df6312 111 {
4eaf08c3 112 printf("no rekeying");
b1df6312
AS
113 }
114 else
115 {
116 printf("rekeying every");
117 if (!no_time)
118 {
119 printf(" %ss", rekey_time);
120 or = TRUE;
121 }
122 if (!no_bytes)
123 {
124 printf("%s %s bytes", or ? " or" : "", rekey_bytes);
125 or = TRUE;
126 }
127 if (!no_packets)
128 {
129 printf("%s %s packets", or ? " or" : "", rekey_packets);
130 }
b1df6312 131 }
4eaf08c3
AS
132 if (!no_dpd)
133 {
134 printf(", dpd action is %s", dpd_action);
135 }
136 printf("\n");
b1df6312 137
b67f7fb8 138 print_label(" label: ", child->get(child, "label"));
51bdc1f3
MW
139 printf(" local: %s\n", child->get(child, "local-ts"));
140 printf(" remote: %s\n", child->get(child, "remote-ts"));
e9704e90
AS
141
142 interface = child->get(child, "interface");
143 if (interface)
144 {
145 printf(" interface: %s\n", interface);
146 }
147
148 priority = child->get(child, "priority");
149 if (priority)
150 {
151 printf(" priority: %s\n", priority);
152 }
51bdc1f3
MW
153 }
154 free_hashtable(child);
155 return ret;
156}
157
158CALLBACK(conn_sn, int,
159 hashtable_t *ike, vici_res_t *res, char *name)
160{
161 int ret = 0;
162
163 if (streq(name, "children"))
164 {
4eaf08c3 165 return vici_parse_cb(res, children_sn, NULL, NULL, ike);
51bdc1f3 166 }
94bb26fa 167 if (strpfx(name, "local") || strpfx(name, "remote"))
51bdc1f3
MW
168 {
169 hashtable_t *auth;
afcd4661 170 char *class;
51bdc1f3
MW
171
172 auth = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
173 ret = vici_parse_cb(res, NULL, values, list, auth);
174 if (ret == 0)
175 {
afcd4661
AS
176 class = auth->get(auth, "class") ?: "unspecified";
177 if (strcaseeq(class, "EAP"))
178 {
179 class = auth->get(auth, "eap-type") ?: class;
180 }
51bdc1f3 181 printf(" %s %s authentication:\n",
afcd4661 182 strpfx(name, "local") ? "local" : "remote", class);
e88f21cf 183 if (auth->get(auth, "id"))
51bdc1f3
MW
184 {
185 printf(" id: %s\n", auth->get(auth, "id"));
186 }
026024bc
MW
187 if (auth->get(auth, "ca_id"))
188 {
189 printf(" ca_id: %s\n", auth->get(auth, "ca_id"));
190 }
e88f21cf
AS
191 if (auth->get(auth, "eap_id"))
192 {
193 printf(" eap_id: %s\n", auth->get(auth, "eap_id"));
194 }
195 if (auth->get(auth, "xauth_id"))
196 {
197 printf(" xauth_id: %s\n", auth->get(auth, "xauth_id"));
198 }
199 if (auth->get(auth, "aaa_id"))
200 {
201 printf(" aaa_id: %s\n", auth->get(auth, "aaa_id"));
202 }
51bdc1f3
MW
203 if (auth->get(auth, "groups"))
204 {
205 printf(" groups: %s\n", auth->get(auth, "groups"));
206 }
ef4a6352
AS
207 if (auth->get(auth, "cert_policy"))
208 {
209 printf(" cert policy: %s\n", auth->get(auth, "cert_policy"));
210 }
51bdc1f3
MW
211 if (auth->get(auth, "certs"))
212 {
213 printf(" certs: %s\n", auth->get(auth, "certs"));
214 }
215 if (auth->get(auth, "cacerts"))
216 {
217 printf(" cacerts: %s\n", auth->get(auth, "cacerts"));
218 }
219 }
220 free_hashtable(auth);
221 }
222 return ret;
223}
224
a2875525 225CALLBACK(conn_list, int,
a24dc2e9 226 hashtable_t *ike, vici_res_t *res, char *name, void *value, int len)
a2875525
MW
227{
228 if (chunk_printable(chunk_create(value, len), NULL, ' '))
229 {
230 if (streq(name, "local_addrs"))
231 {
a24dc2e9
MA
232 printf(" local: %.*s[%s]\n", len, value,
233 ike->get(ike, "local_port"));
a2875525
MW
234 }
235 if (streq(name, "remote_addrs"))
236 {
a24dc2e9
MA
237 printf(" remote: %.*s[%s]\n", len, value,
238 ike->get(ike, "remote_port"));
a2875525
MW
239 }
240 }
241 return 0;
242}
243
51bdc1f3
MW
244CALLBACK(conns, int,
245 void *null, vici_res_t *res, char *name)
246{
4eaf08c3 247 int ret;
1fb46f71 248 char *version, *reauth_time, *rekey_time, *dpd_delay, *ppk_id, *ppk_req;
a24dc2e9 249 char *local_port, *remote_port;
4eaf08c3 250 hashtable_t *ike;
b1df6312
AS
251
252 version = vici_find_str(res, "", "%s.version", name);
4eaf08c3
AS
253 reauth_time = vici_find_str(res, "0", "%s.reauth_time", name);
254 rekey_time = vici_find_str(res, "0", "%s.rekey_time", name);
255 dpd_delay = vici_find_str(res, "0", "%s.dpd_delay", name);
a24dc2e9
MA
256 local_port = vici_find_str(res, "0", "%s.local_port", name);
257 remote_port = vici_find_str(res, "0", "%s.remote_port", name);
4eaf08c3
AS
258
259 ike = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
260 free(ike->put(ike,"dpd_delay", strdup(dpd_delay)));
a24dc2e9
MA
261 free(ike->put(ike,"local_port", strdup(local_port)));
262 free(ike->put(ike,"remote_port", strdup(remote_port)));
51bdc1f3 263
b1df6312
AS
264 printf("%s: %s, ", name, version);
265 if (streq(version, "IKEv1"))
266 {
267 if (streq(reauth_time, "0"))
268 {
269 reauth_time = rekey_time;
270 }
271 }
272 if (streq(reauth_time, "0"))
273 {
274 printf("no reauthentication");
275 }
276 else
277 {
278 printf("reauthentication every %ss", reauth_time);
279 }
4eaf08c3 280 if (!streq(version, "IKEv1"))
b1df6312
AS
281 {
282 if (streq(rekey_time, "0"))
283 {
4eaf08c3 284 printf(", no rekeying");
b1df6312
AS
285 }
286 else
287 {
4eaf08c3 288 printf(", rekeying every %ss", rekey_time);
b1df6312
AS
289 }
290 }
4eaf08c3
AS
291 if (!streq(dpd_delay, "0"))
292 {
293 printf(", dpd delay %ss", dpd_delay);
294 }
295 printf("\n");
296
1fb46f71
TB
297 ppk_id = vici_find_str(res, NULL, "%s.ppk_id", name);
298 ppk_req = vici_find_str(res, NULL, "%s.ppk_required", name);
299 if (ppk_id || ppk_req)
300 {
301 printf(" ppk: %s%s%srequired\n", ppk_id ?: "", ppk_id ? ", " : "",
302 !ppk_req || !streq(ppk_req, "yes") ? "not " : "");
303 }
304
4eaf08c3
AS
305 ret = vici_parse_cb(res, conn_sn, NULL, conn_list, ike);
306 free_hashtable(ike);
307 return ret;
51bdc1f3
MW
308}
309
310CALLBACK(list_cb, void,
dacb75f5 311 command_format_options_t *format, char *name, vici_res_t *res)
51bdc1f3 312{
dacb75f5 313 if (*format & COMMAND_FORMAT_RAW)
51bdc1f3 314 {
dacb75f5
AS
315 vici_dump(res, "list-conn event", *format & COMMAND_FORMAT_PRETTY,
316 stdout);
51bdc1f3
MW
317 }
318 else
319 {
320 if (vici_parse_cb(res, conns, NULL, NULL, NULL) != 0)
321 {
322 fprintf(stderr, "parsing conn event failed: %s\n", strerror(errno));
323 }
324 }
325}
326
327static int list_conns(vici_conn_t *conn)
328{
329 vici_req_t *req;
330 vici_res_t *res;
dacb75f5 331 command_format_options_t format = COMMAND_FORMAT_NONE;
51bdc1f3 332 char *arg;
67f9f09d 333 int ret;
51bdc1f3
MW
334
335 while (TRUE)
336 {
337 switch (command_getopt(&arg))
338 {
339 case 'h':
340 return command_usage(NULL);
dacb75f5
AS
341 case 'P':
342 format |= COMMAND_FORMAT_PRETTY;
343 /* fall through to raw */
51bdc1f3 344 case 'r':
dacb75f5 345 format |= COMMAND_FORMAT_RAW;
51bdc1f3
MW
346 continue;
347 case EOF:
348 break;
349 default:
350 return command_usage("invalid --list-conns option");
351 }
352 break;
353 }
dacb75f5 354 if (vici_register(conn, "list-conn", list_cb, &format) != 0)
51bdc1f3 355 {
67f9f09d 356 ret = errno;
51bdc1f3
MW
357 fprintf(stderr, "registering for connections failed: %s\n",
358 strerror(errno));
67f9f09d 359 return ret;
51bdc1f3
MW
360 }
361 req = vici_begin("list-conns");
362 res = vici_submit(req, conn);
363 if (!res)
364 {
67f9f09d 365 ret = errno;
51bdc1f3 366 fprintf(stderr, "list-conns request failed: %s\n", strerror(errno));
67f9f09d 367 return ret;
51bdc1f3 368 }
dacb75f5 369 if (format & COMMAND_FORMAT_RAW)
51bdc1f3 370 {
dacb75f5
AS
371 vici_dump(res, "list-conns reply", format & COMMAND_FORMAT_PRETTY,
372 stdout);
51bdc1f3
MW
373 }
374 vici_free_res(res);
375 return 0;
376}
377
378/**
379 * Register the command.
380 */
381static void __attribute__ ((constructor))reg()
382{
383 command_register((command_t) {
384 list_conns, 'L', "list-conns", "list loaded configurations",
dacb75f5 385 {"[--raw|--pretty]"},
51bdc1f3
MW
386 {
387 {"help", 'h', 0, "show usage information"},
388 {"raw", 'r', 0, "dump raw response message"},
dacb75f5 389 {"pretty", 'P', 0, "dump raw response message in pretty print"},
51bdc1f3
MW
390 }
391 });
392}