2 * Copyright (C) 2008 Thomas Kallenberg
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
21 #include <sys/types.h>
25 #include "uci_control.h"
28 #include <threading/thread.h>
29 #include <processing/jobs/callback_job.h>
31 #define FIFO_FILE "/var/run/charon.fifo"
34 typedef struct private_uci_control_t private_uci_control_t
;
37 * private data of uci_control_t
39 struct private_uci_control_t
{
53 * write answer to fifo
55 static void write_fifo(private_uci_control_t
*this, char *format
, ...)
60 out
= fopen(FIFO_FILE
, "w");
63 va_start(args
, format
);
64 vfprintf(out
, format
, args
);
70 DBG1(DBG_CFG
, "writing to UCI fifo failed: %s", strerror(errno
));
75 * print IKE_SA status information
77 static void status(private_uci_control_t
*this, char *name
)
79 enumerator_t
*configs
, *sas
;
87 configs
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
88 NULL
, NULL
, NULL
, NULL
);
89 while (configs
->enumerate(configs
, &peer_cfg
))
91 if (name
&& !streq(name
, peer_cfg
->get_name(peer_cfg
)))
95 sas
= charon
->controller
->create_ike_sa_enumerator(
96 charon
->controller
, TRUE
);
97 while (sas
->enumerate(sas
, &ike_sa
))
99 if (!streq(ike_sa
->get_name(ike_sa
), peer_cfg
->get_name(peer_cfg
)))
105 out
= fmemopen(buf
, sizeof(buf
), "w");
111 fprintf(out
, "%-8s %-20D %-16H ", ike_sa
->get_name(ike_sa
),
112 ike_sa
->get_other_id(ike_sa
), ike_sa
->get_other_host(ike_sa
));
114 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
115 while (children
->iterate(children
, (void**)&child_sa
))
118 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
120 children
->destroy(children
);
125 configs
->destroy(configs
);
129 write_fifo(this, "%s", buf
);
133 write_fifo(this, "");
140 static void initiate(private_uci_control_t
*this, char *name
)
142 peer_cfg_t
*peer_cfg
;
143 child_cfg_t
*child_cfg
;
144 enumerator_t
*enumerator
;
146 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
, name
);
149 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
150 if (enumerator
->enumerate(enumerator
, &child_cfg
) &&
151 charon
->controller
->initiate(charon
->controller
, peer_cfg
,
152 child_cfg
->get_ref(child_cfg
),
153 controller_cb_empty
, NULL
) == SUCCESS
)
155 write_fifo(this, "connection '%s' established\n", name
);
159 write_fifo(this, "establishing connection '%s' failed\n", name
);
161 enumerator
->destroy(enumerator
);
165 write_fifo(this, "no connection named '%s' found\n", name
);
170 * terminate an IKE_SA
172 static void terminate(private_uci_control_t
*this, char *name
)
174 enumerator_t
*enumerator
;
178 enumerator
= charon
->controller
->create_ike_sa_enumerator(
179 charon
->controller
, TRUE
);
180 while (enumerator
->enumerate(enumerator
, &ike_sa
))
182 if (streq(name
, ike_sa
->get_name(ike_sa
)))
184 id
= ike_sa
->get_unique_id(ike_sa
);
185 enumerator
->destroy(enumerator
);
186 charon
->controller
->terminate_ike(charon
->controller
, id
,
187 controller_cb_empty
, NULL
);
188 write_fifo(this, "connection '%s' terminated\n", name
);
192 enumerator
->destroy(enumerator
);
193 write_fifo(this, "no active connection named '%s'\n", name
);
197 * dispatch control request
199 static void process(private_uci_control_t
*this, char *message
)
201 enumerator_t
* enumerator
;
203 enumerator
= enumerator_create_token(message
, " \n", "");
204 if (enumerator
->enumerate(enumerator
, &message
))
206 if (streq(message
, "status"))
208 if (enumerator
->enumerate(enumerator
, &message
))
210 status(this, message
);
217 else if (streq(message
, "up") &&
218 enumerator
->enumerate(enumerator
, &message
))
220 initiate(this, message
);
222 else if (streq(message
, "down") &&
223 enumerator
->enumerate(enumerator
, &message
))
225 terminate(this, message
);
229 write_fifo(this, "usage: status [<name>] | up <name> | down <name>\n"
230 " status format: name peer-id peer-addr tunnel(s)\n");
233 enumerator
->destroy(enumerator
);
239 static job_requeue_t
receive(private_uci_control_t
*this)
246 memset(message
, 0, sizeof(message
));
247 oldstate
= thread_cancelability(TRUE
);
248 in
= fopen(FIFO_FILE
, "r");
249 thread_cancelability(oldstate
);
252 len
= fread(message
, 1, sizeof(message
) - 1, in
);
256 process(this, message
);
260 DBG1(DBG_DMN
, "reading from UCI fifo failed: %s", strerror(errno
));
265 DBG1(DBG_DMN
, "opening UCI fifo failed: %s", strerror(errno
));
267 return JOB_REQUEUE_FAIR
;
271 * Implementation of uci_control_t.destroy
273 static void destroy(private_uci_control_t
*this)
275 this->job
->cancel(this->job
);
281 * Described in header.
283 uci_control_t
*uci_control_create()
285 private_uci_control_t
*this = malloc_thing(private_uci_control_t
);
287 this->public.destroy
= (void(*)(uci_control_t
*))destroy
;
290 if (mkfifo(FIFO_FILE
, S_IRUSR
|S_IWUSR
) != 0)
292 DBG1(DBG_CFG
, "creating UCI control fifo '%s' failed: %s",
293 FIFO_FILE
, strerror(errno
));
297 this->job
= callback_job_create_with_prio((callback_job_cb_t
)receive
,
298 this, NULL
, NULL
, JOB_PRIO_CRITICAL
);
299 lib
->processor
->queue_job(lib
->processor
, (job_t
*)this->job
);
301 return &this->public;