22a5633d5b7240655783b9f08022a130049696b4
[strongswan.git] / src / swanctl / commands / list_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 #define _GNU_SOURCE
17 #include <stdio.h>
18 #include <errno.h>
19
20 #include "command.h"
21
22 #include <collections/hashtable.h>
23
24 /**
25 * Free hashtable with contained strings
26 */
27 static void free_hashtable(hashtable_t *hashtable)
28 {
29 enumerator_t *enumerator;
30 char *str;
31
32 enumerator = hashtable->create_enumerator(hashtable);
33 while (enumerator->enumerate(enumerator, NULL, &str))
34 {
35 free(str);
36 }
37 enumerator->destroy(enumerator);
38
39 hashtable->destroy(hashtable);
40 }
41
42 CALLBACK(values, int,
43 hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
44 {
45 chunk_t chunk;
46 char *str;
47
48 chunk = chunk_create(value, len);
49 if (chunk_printable(chunk, NULL, ' '))
50 {
51 if (asprintf(&str, "%.*s", len, value) >= 0)
52 {
53 free(sa->put(sa, name, str));
54 }
55 }
56 return 0;
57 }
58
59
60 CALLBACK(list, int,
61 hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
62 {
63 chunk_t chunk;
64 char *str;
65
66 chunk = chunk_create(value, len);
67 if (chunk_printable(chunk, NULL, ' '))
68 {
69 str = sa->get(sa, name);
70 if (asprintf(&str, "%s%s%.*s",
71 str ?: "", str ? " " : "", len, value) >= 0)
72 {
73 free(sa->put(sa, name, str));
74 }
75 }
76 return 0;
77 }
78
79 CALLBACK(children_sn, int,
80 hashtable_t *ike, vici_res_t *res, char *name)
81 {
82 hashtable_t *child;
83 char *interface, *priority;
84 int ret;
85
86 child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
87 ret = vici_parse_cb(res, NULL, values, list, child);
88 if (ret == 0)
89 {
90 printf(" %s: %s\n", name, child->get(child, "mode"));
91 printf(" local: %s\n", child->get(child, "local-ts"));
92 printf(" remote: %s\n", child->get(child, "remote-ts"));
93
94 interface = child->get(child, "interface");
95 if (interface)
96 {
97 printf(" interface: %s\n", interface);
98 }
99
100 priority = child->get(child, "priority");
101 if (priority)
102 {
103 printf(" priority: %s\n", priority);
104 }
105 }
106 free_hashtable(child);
107 return ret;
108 }
109
110 CALLBACK(conn_sn, int,
111 hashtable_t *ike, vici_res_t *res, char *name)
112 {
113 int ret = 0;
114
115 if (streq(name, "children"))
116 {
117 return vici_parse_cb(res, children_sn, NULL, NULL, NULL);
118 }
119 if (strpfx(name, "local") || strpfx(name, "remote"))
120 {
121 hashtable_t *auth;
122
123 auth = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
124 ret = vici_parse_cb(res, NULL, values, list, auth);
125 if (ret == 0)
126 {
127 printf(" %s %s authentication:\n",
128 strpfx(name, "local") ? "local" : "remote",
129 auth->get(auth, "class") ?: "unspecified");
130 if (auth->get(auth, "id"))
131 {
132 printf(" id: %s\n", auth->get(auth, "id"));
133 }
134 if (auth->get(auth, "groups"))
135 {
136 printf(" groups: %s\n", auth->get(auth, "groups"));
137 }
138 if (auth->get(auth, "certs"))
139 {
140 printf(" certs: %s\n", auth->get(auth, "certs"));
141 }
142 if (auth->get(auth, "cacerts"))
143 {
144 printf(" cacerts: %s\n", auth->get(auth, "cacerts"));
145 }
146 }
147 free_hashtable(auth);
148 }
149 return ret;
150 }
151
152 CALLBACK(conn_list, int,
153 hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
154 {
155 if (chunk_printable(chunk_create(value, len), NULL, ' '))
156 {
157 if (streq(name, "local_addrs"))
158 {
159 printf(" local: %.*s\n", len, value);
160 }
161 if (streq(name, "remote_addrs"))
162 {
163 printf(" remote: %.*s\n", len, value);
164 }
165 }
166 return 0;
167 }
168
169 CALLBACK(conns, int,
170 void *null, vici_res_t *res, char *name)
171 {
172 printf("%s: %s\n", name, vici_find_str(res, "", "%s.version", name));
173
174 return vici_parse_cb(res, conn_sn, NULL, conn_list, NULL);
175 }
176
177 CALLBACK(list_cb, void,
178 command_format_options_t *format, char *name, vici_res_t *res)
179 {
180 if (*format & COMMAND_FORMAT_RAW)
181 {
182 vici_dump(res, "list-conn event", *format & COMMAND_FORMAT_PRETTY,
183 stdout);
184 }
185 else
186 {
187 if (vici_parse_cb(res, conns, NULL, NULL, NULL) != 0)
188 {
189 fprintf(stderr, "parsing conn event failed: %s\n", strerror(errno));
190 }
191 }
192 }
193
194 static int list_conns(vici_conn_t *conn)
195 {
196 vici_req_t *req;
197 vici_res_t *res;
198 command_format_options_t format = COMMAND_FORMAT_NONE;
199 char *arg;
200 int ret;
201
202 while (TRUE)
203 {
204 switch (command_getopt(&arg))
205 {
206 case 'h':
207 return command_usage(NULL);
208 case 'P':
209 format |= COMMAND_FORMAT_PRETTY;
210 /* fall through to raw */
211 case 'r':
212 format |= COMMAND_FORMAT_RAW;
213 continue;
214 case EOF:
215 break;
216 default:
217 return command_usage("invalid --list-conns option");
218 }
219 break;
220 }
221 if (vici_register(conn, "list-conn", list_cb, &format) != 0)
222 {
223 ret = errno;
224 fprintf(stderr, "registering for connections failed: %s\n",
225 strerror(errno));
226 return ret;
227 }
228 req = vici_begin("list-conns");
229 res = vici_submit(req, conn);
230 if (!res)
231 {
232 ret = errno;
233 fprintf(stderr, "list-conns request failed: %s\n", strerror(errno));
234 return ret;
235 }
236 if (format & COMMAND_FORMAT_RAW)
237 {
238 vici_dump(res, "list-conns reply", format & COMMAND_FORMAT_PRETTY,
239 stdout);
240 }
241 vici_free_res(res);
242 return 0;
243 }
244
245 /**
246 * Register the command.
247 */
248 static void __attribute__ ((constructor))reg()
249 {
250 command_register((command_t) {
251 list_conns, 'L', "list-conns", "list loaded configurations",
252 {"[--raw|--pretty]"},
253 {
254 {"help", 'h', 0, "show usage information"},
255 {"raw", 'r', 0, "dump raw response message"},
256 {"pretty", 'P', 0, "dump raw response message in pretty print"},
257 }
258 });
259 }