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
, *children
;
86 configs
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
87 NULL
, NULL
, NULL
, NULL
);
88 while (configs
->enumerate(configs
, &peer_cfg
))
90 if (name
&& !streq(name
, peer_cfg
->get_name(peer_cfg
)))
94 sas
= charon
->controller
->create_ike_sa_enumerator(
95 charon
->controller
, TRUE
);
96 while (sas
->enumerate(sas
, &ike_sa
))
98 if (!streq(ike_sa
->get_name(ike_sa
), peer_cfg
->get_name(peer_cfg
)))
104 out
= fmemopen(buf
, sizeof(buf
), "w");
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
));
113 children
= ike_sa
->create_child_sa_enumerator(ike_sa
);
114 while (children
->enumerate(children
, (void**)&child_sa
))
117 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
119 children
->destroy(children
);
124 configs
->destroy(configs
);
128 write_fifo(this, "%s", buf
);
132 write_fifo(this, "");
139 static void initiate(private_uci_control_t
*this, char *name
)
141 peer_cfg_t
*peer_cfg
;
142 child_cfg_t
*child_cfg
;
143 enumerator_t
*enumerator
;
145 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(charon
->backends
, name
);
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
, 0) == SUCCESS
)
154 write_fifo(this, "connection '%s' established\n", name
);
158 write_fifo(this, "establishing connection '%s' failed\n", name
);
160 enumerator
->destroy(enumerator
);
164 write_fifo(this, "no connection named '%s' found\n", name
);
169 * terminate an IKE_SA
171 static void terminate(private_uci_control_t
*this, char *name
)
173 enumerator_t
*enumerator
;
177 enumerator
= charon
->controller
->create_ike_sa_enumerator(
178 charon
->controller
, TRUE
);
179 while (enumerator
->enumerate(enumerator
, &ike_sa
))
181 if (streq(name
, ike_sa
->get_name(ike_sa
)))
183 id
= ike_sa
->get_unique_id(ike_sa
);
184 enumerator
->destroy(enumerator
);
185 charon
->controller
->terminate_ike(charon
->controller
, id
,
186 controller_cb_empty
, NULL
, 0);
187 write_fifo(this, "connection '%s' terminated\n", name
);
191 enumerator
->destroy(enumerator
);
192 write_fifo(this, "no active connection named '%s'\n", name
);
196 * dispatch control request
198 static void process(private_uci_control_t
*this, char *message
)
200 enumerator_t
* enumerator
;
202 enumerator
= enumerator_create_token(message
, " \n", "");
203 if (enumerator
->enumerate(enumerator
, &message
))
205 if (streq(message
, "status"))
207 if (enumerator
->enumerate(enumerator
, &message
))
209 status(this, message
);
216 else if (streq(message
, "up") &&
217 enumerator
->enumerate(enumerator
, &message
))
219 initiate(this, message
);
221 else if (streq(message
, "down") &&
222 enumerator
->enumerate(enumerator
, &message
))
224 terminate(this, message
);
228 write_fifo(this, "usage: status [<name>] | up <name> | down <name>\n"
229 " status format: name peer-id peer-addr tunnel(s)\n");
232 enumerator
->destroy(enumerator
);
238 static job_requeue_t
receive(private_uci_control_t
*this)
245 memset(message
, 0, sizeof(message
));
246 oldstate
= thread_cancelability(TRUE
);
247 in
= fopen(FIFO_FILE
, "r");
248 thread_cancelability(oldstate
);
251 len
= fread(message
, 1, sizeof(message
) - 1, in
);
255 process(this, message
);
259 DBG1(DBG_DMN
, "reading from UCI fifo failed: %s", strerror(errno
));
264 DBG1(DBG_DMN
, "opening UCI fifo failed: %s", strerror(errno
));
266 return JOB_REQUEUE_FAIR
;
270 * Implementation of uci_control_t.destroy
272 static void destroy(private_uci_control_t
*this)
274 this->job
->cancel(this->job
);
280 * Described in header.
282 uci_control_t
*uci_control_create()
284 private_uci_control_t
*this = malloc_thing(private_uci_control_t
);
286 this->public.destroy
= (void(*)(uci_control_t
*))destroy
;
289 if (mkfifo(FIFO_FILE
, S_IRUSR
|S_IWUSR
) != 0)
291 DBG1(DBG_CFG
, "creating UCI control fifo '%s' failed: %s",
292 FIFO_FILE
, strerror(errno
));
296 this->job
= callback_job_create_with_prio((callback_job_cb_t
)receive
,
297 this, NULL
, NULL
, JOB_PRIO_CRITICAL
);
298 lib
->processor
->queue_job(lib
->processor
, (job_t
*)this->job
);
300 return &this->public;