Annotation of embedaddon/strongswan/src/libcharon/plugins/uci/uci_control.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Thomas Kallenberg
3: * Copyright (C) 2008 Martin Willi
4: * HSR 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: /**
48: * write answer to fifo
49: */
50: static void write_fifo(private_uci_control_t *this, char *format, ...)
51: {
52: va_list args;
53: FILE *out;
54:
55: out = fopen(FIFO_FILE, "w");
56: if (out)
57: {
58: va_start(args, format);
59: vfprintf(out, format, args);
60: va_end(args);
61: fclose(out);
62: }
63: else
64: {
65: DBG1(DBG_CFG, "writing to UCI fifo failed: %s", strerror(errno));
66: }
67: }
68:
69: /**
70: * print IKE_SA status information
71: */
72: static void status(private_uci_control_t *this, char *name)
73: {
74: enumerator_t *configs, *sas, *children;
75: linked_list_t *list;
76: ike_sa_t *ike_sa;
77: child_sa_t *child_sa;
78: peer_cfg_t *peer_cfg;
79: char buf[2048];
80: FILE *out = NULL;
81:
82: configs = charon->backends->create_peer_cfg_enumerator(charon->backends,
83: NULL, NULL, NULL, NULL, IKE_ANY);
84: while (configs->enumerate(configs, &peer_cfg))
85: {
86: if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
87: {
88: continue;
89: }
90: sas = charon->controller->create_ike_sa_enumerator(
91: charon->controller, TRUE);
92: while (sas->enumerate(sas, &ike_sa))
93: {
94: if (!streq(ike_sa->get_name(ike_sa), peer_cfg->get_name(peer_cfg)))
95: {
96: continue;
97: }
98: if (!out)
99: {
100: out = fmemopen(buf, sizeof(buf), "w");
101: if (!out)
102: {
103: continue;
104: }
105: }
106: fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
107: ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
108:
109: children = ike_sa->create_child_sa_enumerator(ike_sa);
110: while (children->enumerate(children, (void**)&child_sa))
111: {
112: list = linked_list_create_from_enumerator(
113: child_sa->create_ts_enumerator(child_sa, FALSE));
114: fprintf(out, "%#R", list);
115: list->destroy(list);
116: }
117: children->destroy(children);
118: fprintf(out, "\n");
119: }
120: sas->destroy(sas);
121: }
122: configs->destroy(configs);
123: if (out)
124: {
125: fclose(out);
126: write_fifo(this, "%s", buf);
127: }
128: else
129: {
130: write_fifo(this, "");
131: }
132: }
133:
134: /**
135: * Initiate an IKE_SA
136: */
137: static void initiate(private_uci_control_t *this, char *name)
138: {
139: peer_cfg_t *peer_cfg;
140: child_cfg_t *child_cfg;
141: enumerator_t *enumerator;
142:
143: peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
144: if (peer_cfg)
145: {
146: enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
147: if (enumerator->enumerate(enumerator, &child_cfg) &&
148: charon->controller->initiate(charon->controller, peer_cfg,
149: child_cfg->get_ref(child_cfg),
150: controller_cb_empty, NULL, 0, FALSE) == SUCCESS)
151: {
152: write_fifo(this, "connection '%s' established\n", name);
153: }
154: else
155: {
156: write_fifo(this, "establishing connection '%s' failed\n", name);
157: }
158: enumerator->destroy(enumerator);
159: }
160: else
161: {
162: write_fifo(this, "no connection named '%s' found\n", name);
163: }
164: }
165:
166: /**
167: * terminate an IKE_SA
168: */
169: static void terminate(private_uci_control_t *this, char *name)
170: {
171: enumerator_t *enumerator;
172: ike_sa_t *ike_sa;
173: u_int id;
174:
175: enumerator = charon->controller->create_ike_sa_enumerator(
176: charon->controller, TRUE);
177: while (enumerator->enumerate(enumerator, &ike_sa))
178: {
179: if (streq(name, ike_sa->get_name(ike_sa)))
180: {
181: id = ike_sa->get_unique_id(ike_sa);
182: enumerator->destroy(enumerator);
183: charon->controller->terminate_ike(charon->controller, id, FALSE,
184: controller_cb_empty, NULL, 0);
185: write_fifo(this, "connection '%s' terminated\n", name);
186: return;
187: }
188: }
189: enumerator->destroy(enumerator);
190: write_fifo(this, "no active connection named '%s'\n", name);
191: }
192:
193: /**
194: * dispatch control request
195: */
196: static void process(private_uci_control_t *this, char *message)
197: {
198: enumerator_t* enumerator;
199:
200: enumerator = enumerator_create_token(message, " \n", "");
201: if (enumerator->enumerate(enumerator, &message))
202: {
203: if (streq(message, "status"))
204: {
205: if (enumerator->enumerate(enumerator, &message))
206: {
207: status(this, message);
208: }
209: else
210: {
211: status(this, NULL);
212: }
213: }
214: else if (streq(message, "up") &&
215: enumerator->enumerate(enumerator, &message))
216: {
217: initiate(this, message);
218: }
219: else if (streq(message, "down") &&
220: enumerator->enumerate(enumerator, &message))
221: {
222: terminate(this, message);
223: }
224: else
225: {
226: write_fifo(this, "usage: status [<name>] | up <name> | down <name>\n"
227: " status format: name peer-id peer-addr tunnel(s)\n");
228: }
229: }
230: enumerator->destroy(enumerator);
231: }
232:
233: /**
234: * read from fifo
235: */
236: static job_requeue_t receive(private_uci_control_t *this)
237: {
238: char message[128];
239: int len;
240: bool oldstate;
241: FILE *in;
242:
243: memset(message, 0, sizeof(message));
244: oldstate = thread_cancelability(TRUE);
245: in = fopen(FIFO_FILE, "r");
246: thread_cancelability(oldstate);
247: if (in)
248: {
249: len = fread(message, 1, sizeof(message) - 1, in);
250: fclose(in);
251: if (len > 0)
252: {
253: process(this, message);
254: }
255: else
256: {
257: DBG1(DBG_DMN, "reading from UCI fifo failed: %s", strerror(errno));
258: }
259: }
260: else
261: {
262: DBG1(DBG_DMN, "opening UCI fifo failed: %s", strerror(errno));
263: }
264: return JOB_REQUEUE_FAIR;
265: }
266:
267: METHOD(uci_control_t, destroy, void,
268: private_uci_control_t *this)
269: {
270: unlink(FIFO_FILE);
271: free(this);
272: }
273:
274: /**
275: * Described in header.
276: */
277: uci_control_t *uci_control_create()
278: {
279: private_uci_control_t *this;
280:
281: INIT(this,
282: .public = {
283: .destroy = _destroy,
284: },
285: );
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: lib->processor->queue_job(lib->processor,
296: (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive,
297: this, NULL, (callback_job_cancel_t)return_false,
298: JOB_PRIO_CRITICAL));
299: }
300: return &this->public;
301: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>