vici: Match identity with wildcards against remote ID in redirect command
[strongswan.git] / src / swanctl / commands / list_pols.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(policy_values, int,
43 hashtable_t *pol, 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(pol->put(pol, name, str));
54 }
55 }
56 return 0;
57 }
58
59 CALLBACK(policy_list, int,
60 hashtable_t *pol, vici_res_t *res, char *name, void *value, int len)
61 {
62 chunk_t chunk;
63 char *str;
64
65 chunk = chunk_create(value, len);
66 if (chunk_printable(chunk, NULL, ' '))
67 {
68 str = pol->get(pol, name);
69 if (asprintf(&str, "%s%s%.*s",
70 str ?: "", str ? " " : "", len, value) >= 0)
71 {
72 free(pol->put(pol, name, str));
73 }
74 }
75 return 0;
76 }
77
78 CALLBACK(policies, int,
79 void *null, vici_res_t *res, char *name)
80 {
81 hashtable_t *pol;
82 int ret;
83
84 pol = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
85 ret = vici_parse_cb(res, NULL, policy_values, policy_list, pol);
86
87 printf("%s, %s\n", name, pol->get(pol, "mode"));
88 printf(" local: %s\n", pol->get(pol, "local-ts"));
89 printf(" remote: %s\n", pol->get(pol, "remote-ts"));
90
91 free_hashtable(pol);
92 return ret;
93 }
94
95 CALLBACK(list_cb, void,
96 command_format_options_t *format, char *name, vici_res_t *res)
97 {
98 if (*format & COMMAND_FORMAT_RAW)
99 {
100 vici_dump(res, "list-policy event", *format & COMMAND_FORMAT_PRETTY,
101 stdout);
102 }
103 else
104 {
105 if (vici_parse_cb(res, policies, NULL, NULL, NULL) != 0)
106 {
107 fprintf(stderr, "parsing policy event failed: %s\n", strerror(errno));
108 }
109 }
110 }
111
112 static int list_pols(vici_conn_t *conn)
113 {
114 vici_req_t *req;
115 vici_res_t *res;
116 bool trap = FALSE, drop = FALSE, pass = FALSE;
117 command_format_options_t format = COMMAND_FORMAT_NONE;
118 char *arg, *child = NULL;
119 int ret;
120
121 while (TRUE)
122 {
123 switch (command_getopt(&arg))
124 {
125 case 'h':
126 return command_usage(NULL);
127 case 'c':
128 child = arg;
129 continue;
130 case 't':
131 trap = TRUE;
132 continue;
133 case 'd':
134 drop = TRUE;
135 continue;
136 case 'p':
137 pass = TRUE;
138 continue;
139 case 'P':
140 format |= COMMAND_FORMAT_PRETTY;
141 /* fall through to raw */
142 case 'r':
143 format |= COMMAND_FORMAT_RAW;
144 continue;
145 case EOF:
146 break;
147 default:
148 return command_usage("invalid --list-pols option");
149 }
150 break;
151 }
152 if (!trap && !drop && !pass)
153 {
154 trap = drop = pass = TRUE;
155 }
156 if (vici_register(conn, "list-policy", list_cb, &format) != 0)
157 {
158 ret = errno;
159 fprintf(stderr, "registering for policies failed: %s\n",
160 strerror(errno));
161 return ret;
162 }
163 req = vici_begin("list-policies");
164 if (child)
165 {
166 vici_add_key_valuef(req, "child", "%s", child);
167 }
168 if (trap)
169 {
170 vici_add_key_valuef(req, "trap", "yes");
171 }
172 if (drop)
173 {
174 vici_add_key_valuef(req, "drop", "yes");
175 }
176 if (pass)
177 {
178 vici_add_key_valuef(req, "pass", "yes");
179 }
180 res = vici_submit(req, conn);
181 if (!res)
182 {
183 ret = errno;
184 fprintf(stderr, "list-policies request failed: %s\n", strerror(errno));
185 return ret;
186 }
187 if (format & COMMAND_FORMAT_RAW)
188 {
189 vici_dump(res, "list-policies reply", format & COMMAND_FORMAT_PRETTY, stdout);
190 }
191 vici_free_res(res);
192 return 0;
193 }
194
195 /**
196 * Register the command.
197 */
198 static void __attribute__ ((constructor))reg()
199 {
200 command_register((command_t) {
201 list_pols, 'P', "list-pols", "list currently installed policies",
202 {"[--child <name>] [--trap] [--drop] [--pass] [--raw|--pretty]"},
203 {
204 {"help", 'h', 0, "show usage information"},
205 {"child", 'c', 1, "filter policies by CHILD_SA config name"},
206 {"trap", 't', 0, "list trap policies"},
207 {"drop", 'd', 0, "list drop policies"},
208 {"pass", 'p', 0, "list bypass policies"},
209 {"raw", 'r', 0, "dump raw response message"},
210 {"pretty", 'P', 0, "dump raw response message in pretty print"},
211 }
212 });
213 }