swanctl: list EAP type in --list-conns
[strongswan.git] / src / swanctl / commands / list_conns.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
4 *
5 * Copyright (C) 2016 Andreas Steffen
6 * HSR Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #define _GNU_SOURCE
20 #include <stdio.h>
21 #include <errno.h>
22
23 #include "command.h"
24
25 #include <collections/hashtable.h>
26
27 /**
28 * Free hashtable with contained strings
29 */
30 static 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
45 CALLBACK(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
63 CALLBACK(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
82 CALLBACK(children_sn, int,
83 hashtable_t *ike, vici_res_t *res, char *name)
84 {
85 hashtable_t *child;
86 char *interface, *priority;
87 int ret;
88
89 child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
90 ret = vici_parse_cb(res, NULL, values, list, child);
91 if (ret == 0)
92 {
93 printf(" %s: %s\n", name, child->get(child, "mode"));
94 printf(" local: %s\n", child->get(child, "local-ts"));
95 printf(" remote: %s\n", child->get(child, "remote-ts"));
96
97 interface = child->get(child, "interface");
98 if (interface)
99 {
100 printf(" interface: %s\n", interface);
101 }
102
103 priority = child->get(child, "priority");
104 if (priority)
105 {
106 printf(" priority: %s\n", priority);
107 }
108 }
109 free_hashtable(child);
110 return ret;
111 }
112
113 CALLBACK(conn_sn, int,
114 hashtable_t *ike, vici_res_t *res, char *name)
115 {
116 int ret = 0;
117
118 if (streq(name, "children"))
119 {
120 return vici_parse_cb(res, children_sn, NULL, NULL, NULL);
121 }
122 if (strpfx(name, "local") || strpfx(name, "remote"))
123 {
124 hashtable_t *auth;
125 char *class;
126
127 auth = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
128 ret = vici_parse_cb(res, NULL, values, list, auth);
129 if (ret == 0)
130 {
131 class = auth->get(auth, "class") ?: "unspecified";
132 if (strcaseeq(class, "EAP"))
133 {
134 class = auth->get(auth, "eap-type") ?: class;
135 }
136 printf(" %s %s authentication:\n",
137 strpfx(name, "local") ? "local" : "remote", class);
138 {
139 printf(" id: %s\n", auth->get(auth, "id"));
140 }
141 if (auth->get(auth, "groups"))
142 {
143 printf(" groups: %s\n", auth->get(auth, "groups"));
144 }
145 if (auth->get(auth, "certs"))
146 {
147 printf(" certs: %s\n", auth->get(auth, "certs"));
148 }
149 if (auth->get(auth, "cacerts"))
150 {
151 printf(" cacerts: %s\n", auth->get(auth, "cacerts"));
152 }
153 }
154 free_hashtable(auth);
155 }
156 return ret;
157 }
158
159 CALLBACK(conn_list, int,
160 hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
161 {
162 if (chunk_printable(chunk_create(value, len), NULL, ' '))
163 {
164 if (streq(name, "local_addrs"))
165 {
166 printf(" local: %.*s\n", len, value);
167 }
168 if (streq(name, "remote_addrs"))
169 {
170 printf(" remote: %.*s\n", len, value);
171 }
172 }
173 return 0;
174 }
175
176 CALLBACK(conns, int,
177 void *null, vici_res_t *res, char *name)
178 {
179 printf("%s: %s\n", name, vici_find_str(res, "", "%s.version", name));
180
181 return vici_parse_cb(res, conn_sn, NULL, conn_list, NULL);
182 }
183
184 CALLBACK(list_cb, void,
185 command_format_options_t *format, char *name, vici_res_t *res)
186 {
187 if (*format & COMMAND_FORMAT_RAW)
188 {
189 vici_dump(res, "list-conn event", *format & COMMAND_FORMAT_PRETTY,
190 stdout);
191 }
192 else
193 {
194 if (vici_parse_cb(res, conns, NULL, NULL, NULL) != 0)
195 {
196 fprintf(stderr, "parsing conn event failed: %s\n", strerror(errno));
197 }
198 }
199 }
200
201 static int list_conns(vici_conn_t *conn)
202 {
203 vici_req_t *req;
204 vici_res_t *res;
205 command_format_options_t format = COMMAND_FORMAT_NONE;
206 char *arg;
207 int ret;
208
209 while (TRUE)
210 {
211 switch (command_getopt(&arg))
212 {
213 case 'h':
214 return command_usage(NULL);
215 case 'P':
216 format |= COMMAND_FORMAT_PRETTY;
217 /* fall through to raw */
218 case 'r':
219 format |= COMMAND_FORMAT_RAW;
220 continue;
221 case EOF:
222 break;
223 default:
224 return command_usage("invalid --list-conns option");
225 }
226 break;
227 }
228 if (vici_register(conn, "list-conn", list_cb, &format) != 0)
229 {
230 ret = errno;
231 fprintf(stderr, "registering for connections failed: %s\n",
232 strerror(errno));
233 return ret;
234 }
235 req = vici_begin("list-conns");
236 res = vici_submit(req, conn);
237 if (!res)
238 {
239 ret = errno;
240 fprintf(stderr, "list-conns request failed: %s\n", strerror(errno));
241 return ret;
242 }
243 if (format & COMMAND_FORMAT_RAW)
244 {
245 vici_dump(res, "list-conns reply", format & COMMAND_FORMAT_PRETTY,
246 stdout);
247 }
248 vici_free_res(res);
249 return 0;
250 }
251
252 /**
253 * Register the command.
254 */
255 static void __attribute__ ((constructor))reg()
256 {
257 command_register((command_t) {
258 list_conns, 'L', "list-conns", "list loaded configurations",
259 {"[--raw|--pretty]"},
260 {
261 {"help", 'h', 0, "show usage information"},
262 {"raw", 'r', 0, "dump raw response message"},
263 {"pretty", 'P', 0, "dump raw response message in pretty print"},
264 }
265 });
266 }