summaryrefslogtreecommitdiff
path: root/src/charon/control
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2007-07-05 00:05:56 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2007-07-05 00:05:56 +0000
commit5db544cc26db378616a46dfa22138f0008cf2930 (patch)
treeff9254d87967bb6f703a5ab5e63edcde2e8a6c17 /src/charon/control
parent3d44c2edf1a3663c7d4acc4434bc8a3abace1ebf (diff)
downloadvyos-strongswan-5db544cc26db378616a46dfa22138f0008cf2930.tar.gz
vyos-strongswan-5db544cc26db378616a46dfa22138f0008cf2930.zip
- Updated to new upstream release.
Diffstat (limited to 'src/charon/control')
-rw-r--r--src/charon/control/interfaces/dbus_interface.c23
-rwxr-xr-xsrc/charon/control/interfaces/stroke_interface.c204
-rw-r--r--src/charon/control/interfaces/xml_interface.c200
3 files changed, 300 insertions, 127 deletions
diff --git a/src/charon/control/interfaces/dbus_interface.c b/src/charon/control/interfaces/dbus_interface.c
index 443df635c..d93a5d048 100644
--- a/src/charon/control/interfaces/dbus_interface.c
+++ b/src/charon/control/interfaces/dbus_interface.c
@@ -30,6 +30,7 @@
#include <library.h>
#include <daemon.h>
+#include <processing/jobs/callback_job.h>
#define NM_DBUS_SERVICE_STRONG "org.freedesktop.NetworkManager.strongswan"
@@ -64,9 +65,9 @@ struct private_dbus_interface_t {
NMVPNState state;
/**
- * dispatcher thread for DBUS messages
+ * job accepting stroke messages
*/
- pthread_t thread;
+ callback_job_t *job;
/**
* name of the currently active connection
@@ -392,14 +393,13 @@ static DBusHandlerResult signal_handler(DBusConnection *con, DBusMessage *msg,
/**
* dispatcher function processed by a seperate thread
*/
-static void dispatch(private_dbus_interface_t *this)
+static job_requeue_t dispatch(private_dbus_interface_t *this)
{
- charon->drop_capabilities(charon, TRUE);
-
- while (dbus_connection_read_write_dispatch(this->conn, -1))
+ if (dbus_connection_read_write_dispatch(this->conn, -1))
{
- /* nothing */
+ return JOB_REQUEUE_DIRECT;
}
+ return JOB_REQUEUE_NONE;
}
/**
@@ -407,8 +407,7 @@ static void dispatch(private_dbus_interface_t *this)
*/
static void destroy(private_dbus_interface_t *this)
{
- pthread_cancel(this->thread);
- pthread_join(this->thread, NULL);
+ this->job->cancel(this->job);
dbus_connection_close(this->conn);
dbus_error_free(&this->err);
dbus_shutdown();
@@ -469,10 +468,8 @@ interface_t *interface_create()
this->state = NM_VPN_STATE_INIT;
set_state(this, NM_VPN_STATE_STOPPED);
- if (pthread_create(&this->thread, NULL, (void*(*)(void*))dispatch, this) != 0)
- {
- charon->kill(charon, "unable to create stroke thread");
- }
+ this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
return &this->public.interface;
}
diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c
index 6e3427e8e..7885fc2e6 100755
--- a/src/charon/control/interfaces/stroke_interface.c
+++ b/src/charon/control/interfaces/stroke_interface.c
@@ -43,6 +43,7 @@
#include <control/interface_manager.h>
#include <control/interfaces/interface.h>
#include <utils/leak_detective.h>
+#include <processing/jobs/callback_job.h>
#define IKE_PORT 500
#define PATH_BUF 256
@@ -69,9 +70,9 @@ struct private_stroke_interface_t {
int socket;
/**
- * Thread which reads from the Socket
+ * job accepting stroke messages
*/
- pthread_t threads[STROKE_THREADS];
+ callback_job_t *job;
};
typedef struct stroke_log_info_t stroke_log_info_t;
@@ -224,8 +225,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
/**
* Add a connection to the configuration list
*/
-static void stroke_add_conn(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
{
ike_cfg_t *ike_cfg;
peer_cfg_t *peer_cfg;
@@ -288,16 +288,18 @@ static void stroke_add_conn(private_stroke_interface_t *this,
msg->add_conn.other = tmp_end;
free(interface);
}
- if (!interface)
+ else
{
interface = charon->kernel_interface->get_interface(
charon->kernel_interface, my_host);
if (!interface)
{
- DBG1(DBG_CFG, "left nor right host is our side, aborting\n");
- goto destroy_hosts;
+ DBG1(DBG_CFG, "left nor right host is our side, assuming left=local");
+ }
+ else
+ {
+ free(interface);
}
- free(interface);
}
my_id = identification_create_from_string(msg->add_conn.me.id ?
@@ -628,8 +630,7 @@ destroy_hosts:
/**
* Delete a connection from the list
*/
-static void stroke_del_conn(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_del_conn(stroke_msg_t *msg, FILE *out)
{
iterator_t *peer_iter, *child_iter;
peer_cfg_t *peer, *child;
@@ -747,8 +748,7 @@ static peer_cfg_t *get_peer_cfg_by_name(char *name)
/**
* initiate a connection by name
*/
-static void stroke_initiate(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_initiate(stroke_msg_t *msg, FILE *out)
{
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
@@ -781,7 +781,6 @@ static void stroke_initiate(private_stroke_interface_t *this,
info.out = out;
info.level = msg->output_verbosity;
-
charon->interfaces->initiate(charon->interfaces, peer_cfg, child_cfg,
(interface_manager_cb_t)stroke_log, &info);
}
@@ -789,8 +788,7 @@ static void stroke_initiate(private_stroke_interface_t *this,
/**
* route a policy (install SPD entries)
*/
-static void stroke_route(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_route(stroke_msg_t *msg, FILE *out)
{
peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
@@ -830,8 +828,7 @@ static void stroke_route(private_stroke_interface_t *this,
/**
* unroute a policy
*/
-static void stroke_unroute(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_unroute(stroke_msg_t *msg, FILE *out)
{
char *name;
ike_sa_t *ike_sa;
@@ -874,8 +871,7 @@ static void stroke_unroute(private_stroke_interface_t *this,
/**
* terminate a connection by name
*/
-static void stroke_terminate(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_terminate(stroke_msg_t *msg, FILE *out)
{
char *string, *pos = NULL, *name = NULL;
u_int32_t id = 0;
@@ -979,8 +975,7 @@ static void stroke_terminate(private_stroke_interface_t *this,
/**
* Add a ca information record to the cainfo list
*/
-static void stroke_add_ca(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_add_ca(stroke_msg_t *msg, FILE *out)
{
x509_t *cacert;
ca_info_t *ca_info;
@@ -1047,8 +1042,7 @@ static void stroke_add_ca(private_stroke_interface_t *this,
/**
* Delete a ca information record from the cainfo list
*/
-static void stroke_del_ca(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_del_ca(stroke_msg_t *msg, FILE *out)
{
status_t status;
@@ -1194,11 +1188,9 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
/**
* show status of daemon
*/
-static void stroke_status(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out, bool all)
+static void stroke_status(stroke_msg_t *msg, FILE *out, bool all)
{
iterator_t *iterator, *children;
- linked_list_t *list;
host_t *host;
peer_cfg_t *peer_cfg;
ike_cfg_t *ike_cfg;
@@ -1218,21 +1210,20 @@ static void stroke_status(private_stroke_interface_t *this,
fprintf(out, "Performance:\n");
fprintf(out, " worker threads: %d idle of %d,",
- charon->thread_pool->get_idle_threads(charon->thread_pool),
- charon->thread_pool->get_pool_size(charon->thread_pool));
+ charon->processor->get_idle_threads(charon->processor),
+ charon->processor->get_total_threads(charon->processor));
fprintf(out, " job queue load: %d,",
- charon->job_queue->get_count(charon->job_queue));
+ charon->processor->get_job_load(charon->processor));
fprintf(out, " scheduled events: %d\n",
- charon->event_queue->get_count(charon->event_queue));
- list = charon->kernel_interface->create_address_list(charon->kernel_interface);
-
- fprintf(out, "Listening on %d IP addresses:\n", list->get_count(list));
- while (list->remove_first(list, (void**)&host) == SUCCESS)
+ charon->scheduler->get_job_load(charon->scheduler));
+ iterator = charon->kernel_interface->create_address_iterator(
+ charon->kernel_interface);
+ fprintf(out, "Listening IP addresses:\n");
+ while (iterator->iterate(iterator, (void**)&host))
{
fprintf(out, " %H\n", host);
- host->destroy(host);
}
- list->destroy(list);
+ iterator->destroy(iterator);
fprintf(out, "Connections:\n");
iterator = charon->backends->create_iterator(charon->backends);
@@ -1312,8 +1303,8 @@ static void stroke_status(private_stroke_interface_t *this,
/**
* list all authority certificates matching a specified flag
*/
-static void list_auth_certificates(private_stroke_interface_t *this, u_int flag,
- const char *label, bool utc, FILE *out)
+static void list_auth_certificates(u_int flag, const char *label,
+ bool utc, FILE *out)
{
bool first = TRUE;
x509_t *cert;
@@ -1341,8 +1332,7 @@ static void list_auth_certificates(private_stroke_interface_t *this, u_int flag
/**
* list various information
*/
-static void stroke_list(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_list(stroke_msg_t *msg, FILE *out)
{
iterator_t *iterator;
@@ -1372,15 +1362,15 @@ static void stroke_list(private_stroke_interface_t *this,
}
if (msg->list.flags & LIST_CACERTS)
{
- list_auth_certificates(this, AUTH_CA, "CA", msg->list.utc, out);
+ list_auth_certificates(AUTH_CA, "CA", msg->list.utc, out);
}
if (msg->list.flags & LIST_OCSPCERTS)
{
- list_auth_certificates(this, AUTH_OCSP, "OCSP", msg->list.utc, out);
+ list_auth_certificates(AUTH_OCSP, "OCSP", msg->list.utc, out);
}
if (msg->list.flags & LIST_AACERTS)
{
- list_auth_certificates(this, AUTH_AA, "AA", msg->list.utc, out);
+ list_auth_certificates(AUTH_AA, "AA", msg->list.utc, out);
}
if (msg->list.flags & LIST_CAINFOS)
{
@@ -1453,8 +1443,7 @@ static void stroke_list(private_stroke_interface_t *this,
/**
* reread various information
*/
-static void stroke_reread(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_reread(stroke_msg_t *msg, FILE *out)
{
if (msg->reread.flags & REREAD_CACERTS)
{
@@ -1473,8 +1462,7 @@ static void stroke_reread(private_stroke_interface_t *this,
/**
* purge various information
*/
-static void stroke_purge(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_purge(stroke_msg_t *msg, FILE *out)
{
if (msg->purge.flags & PURGE_OCSP)
{
@@ -1510,8 +1498,7 @@ signal_t get_signal_from_logtype(char *type)
/**
* set the verbosity debug output
*/
-static void stroke_loglevel(private_stroke_interface_t *this,
- stroke_msg_t *msg, FILE *out)
+static void stroke_loglevel(stroke_msg_t *msg, FILE *out)
{
signal_t signal;
@@ -1533,20 +1520,22 @@ static void stroke_loglevel(private_stroke_interface_t *this,
/**
* process a stroke request from the socket pointed by "fd"
*/
-static void stroke_process(private_stroke_interface_t *this, int strokefd)
+static job_requeue_t stroke_process(int *fdp)
{
stroke_msg_t *msg;
u_int16_t msg_length;
ssize_t bytes_read;
FILE *out;
+ int strokefd = *fdp;
/* peek the length */
bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
if (bytes_read != sizeof(msg_length))
{
- DBG1(DBG_CFG, "reading length of stroke message failed");
+ DBG1(DBG_CFG, "reading length of stroke message failed: %s",
+ strerror(errno));
close(strokefd);
- return;
+ return JOB_REQUEUE_NONE;
}
/* read message */
@@ -1556,105 +1545,107 @@ static void stroke_process(private_stroke_interface_t *this, int strokefd)
{
DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
close(strokefd);
- return;
+ return JOB_REQUEUE_NONE;
}
- out = fdopen(dup(strokefd), "w");
+ out = fdopen(strokefd, "w");
if (out == NULL)
{
DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno));
close(strokefd);
free(msg);
- return;
+ return JOB_REQUEUE_NONE;
}
DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
+ /* the stroke_* functions are blocking, as they listen on the bus. Add
+ * cancellation handlers. */
+ pthread_cleanup_push((void*)fclose, out);
+ pthread_cleanup_push(free, msg);
+
switch (msg->type)
{
case STR_INITIATE:
- stroke_initiate(this, msg, out);
+ stroke_initiate(msg, out);
break;
case STR_ROUTE:
- stroke_route(this, msg, out);
+ stroke_route(msg, out);
break;
case STR_UNROUTE:
- stroke_unroute(this, msg, out);
+ stroke_unroute(msg, out);
break;
case STR_TERMINATE:
- stroke_terminate(this, msg, out);
+ stroke_terminate(msg, out);
break;
case STR_STATUS:
- stroke_status(this, msg, out, FALSE);
+ stroke_status(msg, out, FALSE);
break;
case STR_STATUS_ALL:
- stroke_status(this, msg, out, TRUE);
+ stroke_status(msg, out, TRUE);
break;
case STR_ADD_CONN:
- stroke_add_conn(this, msg, out);
+ stroke_add_conn(msg, out);
break;
case STR_DEL_CONN:
- stroke_del_conn(this, msg, out);
+ stroke_del_conn(msg, out);
break;
case STR_ADD_CA:
- stroke_add_ca(this, msg, out);
+ stroke_add_ca(msg, out);
break;
case STR_DEL_CA:
- stroke_del_ca(this, msg, out);
+ stroke_del_ca(msg, out);
break;
case STR_LOGLEVEL:
- stroke_loglevel(this, msg, out);
+ stroke_loglevel(msg, out);
break;
case STR_LIST:
- stroke_list(this, msg, out);
+ stroke_list(msg, out);
break;
case STR_REREAD:
- stroke_reread(this, msg, out);
+ stroke_reread(msg, out);
break;
case STR_PURGE:
- stroke_purge(this, msg, out);
+ stroke_purge(msg, out);
break;
default:
DBG1(DBG_CFG, "received unknown stroke");
}
- fclose(out);
- close(strokefd);
- free(msg);
+ /* remove and execute cancellation handlers */
+ pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
+
+ return JOB_REQUEUE_NONE;
}
+
/**
* Implementation of private_stroke_interface_t.stroke_receive.
*/
-static void stroke_receive(private_stroke_interface_t *this)
+static job_requeue_t stroke_receive(private_stroke_interface_t *this)
{
struct sockaddr_un strokeaddr;
int strokeaddrlen = sizeof(strokeaddr);
+ int strokefd, *fdp;
int oldstate;
- int strokefd;
-
- charon->drop_capabilities(charon, TRUE);
+ callback_job_t *job;
- /* ignore sigpipe. writing over the pipe back to the console
- * only fails if SIGPIPE is ignored. */
- signal(SIGPIPE, SIG_IGN);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
+ pthread_setcancelstate(oldstate, NULL);
- /* disable cancellation by default */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-
- while (TRUE)
+ if (strokefd < 0)
{
- /* wait for connections, but allow thread to terminate */
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
- strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
- pthread_setcancelstate(oldstate, NULL);
-
- if (strokefd < 0)
- {
- DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno));
- continue;
- }
- stroke_process(this, strokefd);
+ DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno));
+ return JOB_REQUEUE_FAIR;
}
+
+ fdp = malloc_thing(int);
+ *fdp = strokefd;
+ job = callback_job_create((callback_job_cb_t)stroke_process, fdp, free, this->job);
+ charon->processor->queue_job(charon->processor, (job_t*)job);
+
+ return JOB_REQUEUE_FAIR;
}
/**
@@ -1662,17 +1653,9 @@ static void stroke_receive(private_stroke_interface_t *this)
*/
static void destroy(private_stroke_interface_t *this)
{
- int i;
-
- for (i = 0; i < STROKE_THREADS; i++)
- {
- pthread_cancel(this->threads[i]);
- pthread_join(this->threads[i], NULL);
- }
-
- close(this->socket);
- unlink(socket_addr.sun_path);
+ this->job->cancel(this->job);
free(this);
+ unlink(socket_addr.sun_path);
}
/*
@@ -1682,7 +1665,6 @@ interface_t *interface_create()
{
private_stroke_interface_t *this = malloc_thing(private_stroke_interface_t);
mode_t old;
- int i;
/* public functions */
this->public.interface.destroy = (void (*)(interface_t*))destroy;
@@ -1715,14 +1697,10 @@ interface_t *interface_create()
return NULL;
}
- /* start threads reading from the socket */
- for (i = 0; i < STROKE_THREADS; i++)
- {
- if (pthread_create(&this->threads[i], NULL, (void*(*)(void*))stroke_receive, this) != 0)
- {
- charon->kill(charon, "unable to create stroke thread");
- }
- }
+ this->job = callback_job_create((callback_job_cb_t)stroke_receive,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
return &this->public.interface;
}
+
diff --git a/src/charon/control/interfaces/xml_interface.c b/src/charon/control/interfaces/xml_interface.c
index e570f2543..992377436 100644
--- a/src/charon/control/interfaces/xml_interface.c
+++ b/src/charon/control/interfaces/xml_interface.c
@@ -24,8 +24,22 @@
#include "xml_interface.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlwriter.h>
+
#include <library.h>
#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+static struct sockaddr_un socket_addr = { AF_UNIX, "/var/run/charon.xml"};
typedef struct private_xml_interface_t private_xml_interface_t;
@@ -39,14 +53,166 @@ struct private_xml_interface_t {
* Public part of xml_t object.
*/
xml_interface_t public;
+
+ /**
+ * XML unix socket fd
+ */
+ int socket;
+
+ /**
+ * job accepting stroke messages
+ */
+ callback_job_t *job;
};
+/**
+ * process a getRequest message
+ */
+static void process_get(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
+{
+ if (/* <GetResponse> */
+ xmlTextWriterStartElement(writer, "GetResponse") < 0 ||
+ /* <Status Code="200"><Message/></Status> */
+ xmlTextWriterStartElement(writer, "Status") < 0 ||
+ xmlTextWriterWriteAttribute(writer, "Code", "200") < 0 ||
+ xmlTextWriterStartElement(writer, "Message") < 0 ||
+ xmlTextWriterEndElement(writer) < 0 ||
+ xmlTextWriterEndElement(writer) < 0 ||
+ /* <ConnectionList/> */
+ xmlTextWriterStartElement(writer, "ConnectionList") < 0 ||
+ xmlTextWriterEndElement(writer) < 0 ||
+ /* </GetResponse> */
+ xmlTextWriterEndElement(writer) < 0)
+ {
+ DBG1(DBG_CFG, "error writing XML document (GetResponse)");
+ }
+}
+
+/**
+ * read from a opened connection and process it
+ */
+static job_requeue_t process(int *fdp)
+{
+ int oldstate, fd = *fdp;
+ char buffer[4096];
+ size_t len;
+ xmlTextReaderPtr reader;
+ xmlTextWriterPtr writer;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ len = read(fd, buffer, sizeof(buffer));
+ pthread_setcancelstate(oldstate, NULL);
+ if (len <= 0)
+ {
+ close(fd);
+ DBG2(DBG_CFG, "SMP XML connection closed");
+ return JOB_REQUEUE_NONE;
+ }
+
+ reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
+ if (reader == NULL)
+ {
+ DBG1(DBG_CFG, "opening SMP XML reader failed");
+ return JOB_REQUEUE_FAIR;;
+ }
+
+ writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL));
+ if (writer == NULL)
+ {
+ xmlFreeTextReader(reader);
+ DBG1(DBG_CFG, "opening SMP XML writer failed");
+ return JOB_REQUEUE_FAIR;;
+ }
+
+ /* create the standard message parts */
+ if (xmlTextWriterStartDocument(writer, NULL, NULL, NULL) < 0 ||
+ /* <SMPMessage xmlns="http://www.strongswan.org/smp/1.0"> */
+ xmlTextWriterStartElement(writer, "SMPMessage") < 0 ||
+ xmlTextWriterWriteAttribute(writer, "xmlns",
+ "http://www.strongswan.org/smp/1.0") < 0 ||
+ /* <Body> */
+ xmlTextWriterStartElement(writer, "Body") < 0)
+ {
+ xmlFreeTextReader(reader);
+ xmlFreeTextWriter(writer);
+ DBG1(DBG_CFG, "creating SMP XML message failed");
+ return JOB_REQUEUE_FAIR;;
+ }
+
+ while (TRUE)
+ {
+ switch (xmlTextReaderRead(reader))
+ {
+ case 1:
+ {
+ if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
+ {
+ if (streq(xmlTextReaderConstName(reader), "GetRequest"))
+ {
+ process_get(reader, writer);
+ break;
+ }
+ }
+ continue;
+ }
+ case 0:
+ /* end of XML */
+ break;
+ default:
+ DBG1(DBG_CFG, "parsing SMP XML message failed");
+ break;
+ }
+ xmlFreeTextReader(reader);
+ break;
+ }
+ /* write </Body></SMPMessage> and close document */
+ if (xmlTextWriterEndDocument(writer) < 0)
+ {
+ DBG1(DBG_CFG, "completing SMP XML message failed");
+ }
+ xmlFreeTextWriter(writer);
+
+ /* write a newline to indicate end of xml */
+ write(fd, "\n", 1);
+ return JOB_REQUEUE_FAIR;;
+}
+
+/**
+ * accept from XML socket and create jobs to process connections
+ */
+static job_requeue_t dispatch(private_xml_interface_t *this)
+{
+ struct sockaddr_un strokeaddr;
+ int oldstate, fd, *fdp, strokeaddrlen = sizeof(strokeaddr);
+ callback_job_t *job;
+
+ /* wait for connections, but allow thread to terminate */
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
+ pthread_setcancelstate(oldstate, NULL);
+
+ if (fd < 0)
+ {
+ DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno));
+ sleep(1);
+ return JOB_REQUEUE_FAIR;;
+ }
+
+ fdp = malloc_thing(int);
+ *fdp = fd;
+ job = callback_job_create((callback_job_cb_t)process, fdp, free, this->job);
+ charon->processor->queue_job(charon->processor, (job_t*)job);
+
+ return JOB_REQUEUE_DIRECT;
+}
/**
* Implementation of itnerface_t.destroy.
*/
static void destroy(private_xml_interface_t *this)
{
+ this->job->cancel(this->job);
+ unlink(socket_addr.sun_path);
free(this);
}
@@ -56,8 +222,40 @@ static void destroy(private_xml_interface_t *this)
interface_t *interface_create()
{
private_xml_interface_t *this = malloc_thing(private_xml_interface_t);
+ mode_t old;
- this->public.interface.destroy = (void (*)(xml_interface_t*))destroy;
+ this->public.interface.destroy = (void (*)(interface_t*))destroy;
+
+ /* set up unix socket */
+ this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (this->socket == -1)
+ {
+ DBG1(DBG_CFG, "could not create XML socket");
+ free(this);
+ return NULL;
+ }
+
+ old = umask(~S_IRWXU);
+ if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
+ {
+ DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno));
+ close(this->socket);
+ free(this);
+ return NULL;
+ }
+ umask(old);
+
+ if (listen(this->socket, 0) < 0)
+ {
+ DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno));
+ close(this->socket);
+ free(this);
+ return NULL;
+ }
+
+ this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
return &this->public.interface;
}
+