Removed strayed code fragment
[strongswan.git] / src / charon / plugins / uci / uci_control.c
1 /*
2 * Copyright (C) 2008 Thomas Kallenberg
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #define _GNU_SOURCE
18 #include <string.h>
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <errno.h>
24
25 #include "uci_control.h"
26
27 #include <daemon.h>
28 #include <threading/thread.h>
29 #include <processing/jobs/callback_job.h>
30
31 #define FIFO_FILE "/var/run/charon.fifo"
32
33
34 typedef struct private_uci_control_t private_uci_control_t;
35
36 /**
37 * private data of uci_control_t
38 */
39 struct private_uci_control_t {
40
41 /**
42 * Public part
43 */
44 uci_control_t public;
45
46 /**
47 * Job
48 */
49 callback_job_t *job;
50 };
51
52 /**
53 * write answer to fifo
54 */
55 static void write_fifo(private_uci_control_t *this, char *format, ...)
56 {
57 va_list args;
58 FILE *out;
59
60 out = fopen(FIFO_FILE, "w");
61 if (out)
62 {
63 va_start(args, format);
64 vfprintf(out, format, args);
65 va_end(args);
66 fclose(out);
67 }
68 else
69 {
70 DBG1(DBG_CFG, "writing to UCI fifo failed: %s", strerror(errno));
71 }
72 }
73
74 /**
75 * print IKE_SA status information
76 */
77 static void status(private_uci_control_t *this, char *name)
78 {
79 enumerator_t *configs, *sas;
80 iterator_t *children;
81 ike_sa_t *ike_sa;
82 child_sa_t *child_sa;
83 peer_cfg_t *peer_cfg;
84 char buf[2048];
85 FILE *out = NULL;
86
87 configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
88 NULL, NULL, NULL, NULL);
89 while (configs->enumerate(configs, &peer_cfg))
90 {
91 if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
92 {
93 continue;
94 }
95 sas = charon->controller->create_ike_sa_enumerator(charon->controller);
96 while (sas->enumerate(sas, &ike_sa))
97 {
98 if (!streq(ike_sa->get_name(ike_sa), peer_cfg->get_name(peer_cfg)))
99 {
100 continue;
101 }
102 if (!out)
103 {
104 out = fmemopen(buf, sizeof(buf), "w");
105 if (!out)
106 {
107 continue;
108 }
109 }
110 fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
111 ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
112
113 children = ike_sa->create_child_sa_iterator(ike_sa);
114 while (children->iterate(children, (void**)&child_sa))
115 {
116 fprintf(out, "%#R",
117 child_sa->get_traffic_selectors(child_sa, FALSE));
118 }
119 children->destroy(children);
120 fprintf(out, "\n");
121 }
122 sas->destroy(sas);
123 }
124 configs->destroy(configs);
125 if (out)
126 {
127 fclose(out);
128 write_fifo(this, "%s", buf);
129 }
130 else
131 {
132 write_fifo(this, "");
133 }
134 }
135
136 /**
137 * Initiate an IKE_SA
138 */
139 static void initiate(private_uci_control_t *this, char *name)
140 {
141 peer_cfg_t *peer_cfg;
142 child_cfg_t *child_cfg;
143 enumerator_t *enumerator;
144
145 peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
146 if (peer_cfg)
147 {
148 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
149 if (enumerator->enumerate(enumerator, &child_cfg) &&
150 charon->controller->initiate(charon->controller, peer_cfg,
151 child_cfg->get_ref(child_cfg),
152 controller_cb_empty, NULL) == SUCCESS)
153 {
154 write_fifo(this, "connection '%s' established\n", name);
155 }
156 else
157 {
158 write_fifo(this, "establishing connection '%s' failed\n", name);
159 }
160 enumerator->destroy(enumerator);
161 }
162 else
163 {
164 write_fifo(this, "no connection named '%s' found\n", name);
165 }
166 }
167
168 /**
169 * terminate an IKE_SA
170 */
171 static void terminate(private_uci_control_t *this, char *name)
172 {
173 enumerator_t *enumerator;
174 ike_sa_t *ike_sa;
175 u_int id;
176
177 enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
178 while (enumerator->enumerate(enumerator, &ike_sa))
179 {
180 if (streq(name, ike_sa->get_name(ike_sa)))
181 {
182 id = ike_sa->get_unique_id(ike_sa);
183 enumerator->destroy(enumerator);
184 charon->controller->terminate_ike(charon->controller, id,
185 controller_cb_empty, NULL);
186 write_fifo(this, "connection '%s' terminated\n", name);
187 return;
188 }
189 }
190 enumerator->destroy(enumerator);
191 write_fifo(this, "no active connection named '%s'\n", name);
192 }
193
194 /**
195 * dispatch control request
196 */
197 static void process(private_uci_control_t *this, char *message)
198 {
199 enumerator_t* enumerator;
200
201 enumerator = enumerator_create_token(message, " \n", "");
202 if (enumerator->enumerate(enumerator, &message))
203 {
204 if (streq(message, "status"))
205 {
206 if (enumerator->enumerate(enumerator, &message))
207 {
208 status(this, message);
209 }
210 else
211 {
212 status(this, NULL);
213 }
214 }
215 else if (streq(message, "up") &&
216 enumerator->enumerate(enumerator, &message))
217 {
218 initiate(this, message);
219 }
220 else if (streq(message, "down") &&
221 enumerator->enumerate(enumerator, &message))
222 {
223 terminate(this, message);
224 }
225 else
226 {
227 write_fifo(this, "usage: status [<name>] | up <name> | down <name>\n"
228 " status format: name peer-id peer-addr tunnel(s)\n");
229 }
230 }
231 enumerator->destroy(enumerator);
232 }
233
234 /**
235 * read from fifo
236 */
237 static job_requeue_t receive(private_uci_control_t *this)
238 {
239 char message[128];
240 int len;
241 bool oldstate;
242 FILE *in;
243
244 memset(message, 0, sizeof(message));
245 oldstate = thread_cancelability(TRUE);
246 in = fopen(FIFO_FILE, "r");
247 thread_cancelability(oldstate);
248 if (in)
249 {
250 len = fread(message, 1, sizeof(message) - 1, in);
251 fclose(in);
252 if (len > 0)
253 {
254 process(this, message);
255 }
256 else
257 {
258 DBG1(DBG_DMN, "reading from UCI fifo failed: %s", strerror(errno));
259 }
260 }
261 else
262 {
263 DBG1(DBG_DMN, "opening UCI fifo failed: %s", strerror(errno));
264 }
265 return JOB_REQUEUE_FAIR;
266 }
267
268 /**
269 * Implementation of uci_control_t.destroy
270 */
271 static void destroy(private_uci_control_t *this)
272 {
273 this->job->cancel(this->job);
274 unlink(FIFO_FILE);
275 free(this);
276 }
277
278 /**
279 * Described in header.
280 */
281 uci_control_t *uci_control_create()
282 {
283 private_uci_control_t *this = malloc_thing(private_uci_control_t);
284
285 this->public.destroy = (void(*)(uci_control_t*))destroy;
286
287 unlink(FIFO_FILE);
288 if (mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0)
289 {
290 DBG1(DBG_CFG, "creating UCI control fifo '%s' failed: %s",
291 FIFO_FILE, strerror(errno));
292 }
293 else
294 {
295 this->job = callback_job_create((callback_job_cb_t)receive,
296 this, NULL, NULL);
297 charon->processor->queue_job(charon->processor, (job_t*)this->job);
298 }
299 return &this->public;
300 }
301