2 * @file xml_interface.c
4 * @brief Implementation of xml_interface_t.
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "xml_interface.h"
27 #include <sys/types.h>
29 #include <sys/socket.h>
35 #include <libxml/xmlreader.h>
36 #include <libxml/xmlwriter.h>
42 static struct sockaddr_un socket_addr
= { AF_UNIX
, "/var/run/charon.xml"};
45 typedef struct private_xml_interface_t private_xml_interface_t
;
48 * Private data of an xml_interface_t object.
50 struct private_xml_interface_t
{
53 * Public part of xml_t object.
55 xml_interface_t
public;
63 * thread receiving messages
68 static void get(private_xml_interface_t
*this,
69 xmlTextReaderPtr reader
, xmlTextWriterPtr writer
)
72 if (/* <GetResponse> */
73 xmlTextWriterStartElement(writer
, "GetResponse") < 0 ||
74 /* <Status Code="200"><Message/></Status> */
75 xmlTextWriterStartElement(writer
, "Status") < 0 ||
76 xmlTextWriterWriteAttribute(writer
, "Code", "200") < 0 ||
77 xmlTextWriterStartElement(writer
, "Message") < 0 ||
78 xmlTextWriterEndElement(writer
) < 0 ||
79 xmlTextWriterEndElement(writer
) < 0 ||
80 /* <ConnectionList/> */
81 xmlTextWriterStartElement(writer
, "ConnectionList") < 0 ||
82 xmlTextWriterEndElement(writer
) < 0 ||
84 xmlTextWriterEndElement(writer
) < 0)
86 DBG1(DBG_CFG
, "error writing XML document (GetResponse)");
91 DBG1(DBG_CFG, "%d %d %s %d %d %s",
92 xmlTextReaderDepth(reader),
94 xmlTextReaderConstName(reader),
95 xmlTextReaderIsEmptyElement(reader),
96 xmlTextReaderHasValue(reader),
97 xmlTextReaderConstValue(reader));
101 static void receive(private_xml_interface_t
*this)
103 charon
->drop_capabilities(charon
, TRUE
);
105 /* disable cancellation by default */
106 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
110 struct sockaddr_un strokeaddr
;
111 int strokeaddrlen
= sizeof(strokeaddr
);
117 /* wait for connections, but allow thread to terminate */
118 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
119 fd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
120 pthread_setcancelstate(oldstate
, NULL
);
124 DBG1(DBG_CFG
, "accepting SMP XML socket failed: %s", strerror(errno
));
127 DBG2(DBG_CFG
, "SMP XML connection opened");
130 xmlTextReaderPtr reader
;
131 xmlTextWriterPtr writer
;
133 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
134 len
= read(fd
, buffer
, sizeof(buffer
));
135 pthread_setcancelstate(oldstate
, NULL
);
139 DBG2(DBG_CFG
, "SMP XML connection closed");
143 reader
= xmlReaderForMemory(buffer
, len
, NULL
, NULL
, 0);
146 DBG1(DBG_CFG
, "opening SMP XML reader failed");
150 writer
= xmlNewTextWriter(xmlOutputBufferCreateFd(fd
, NULL
));
153 xmlFreeTextReader(reader
);
154 DBG1(DBG_CFG
, "opening SMP XML writer failed");
158 /* create the standard message parts */
159 if (xmlTextWriterStartDocument(writer
, NULL
, NULL
, NULL
) < 0 ||
160 /* <SMPMessage xmlns="http://www.strongswan.org/smp/1.0"> */
161 xmlTextWriterStartElement(writer
, "SMPMessage") < 0 ||
162 xmlTextWriterWriteAttribute(writer
, "xmlns",
163 "http://www.strongswan.org/smp/1.0") < 0 ||
165 xmlTextWriterStartElement(writer
, "Body") < 0)
167 xmlFreeTextReader(reader
);
168 xmlFreeTextWriter(writer
);
169 DBG1(DBG_CFG
, "creating SMP XML message failed");
175 switch (xmlTextReaderRead(reader
))
179 if (xmlTextReaderNodeType(reader
) ==
180 XML_READER_TYPE_ELEMENT
)
182 if (streq(xmlTextReaderConstName(reader
), "GetRequest"))
184 get(this, reader
, writer
);
194 DBG1(DBG_CFG
, "parsing SMP XML message failed");
197 xmlFreeTextReader(reader
);
200 /* write </Body></SMPMessage> and close document */
201 if (xmlTextWriterEndDocument(writer
) < 0)
203 DBG1(DBG_CFG
, "completing SMP XML message failed");
205 xmlFreeTextWriter(writer
);
206 /* write a newline to indicate end of xml */
213 * Implementation of itnerface_t.destroy.
215 static void destroy(private_xml_interface_t
*this)
217 pthread_cancel(this->thread
);
218 pthread_join(this->thread
, NULL
);
220 unlink(socket_addr
.sun_path
);
225 * Described in header file
227 interface_t
*interface_create()
229 private_xml_interface_t
*this = malloc_thing(private_xml_interface_t
);
232 this->public.interface
.destroy
= (void (*)(interface_t
*))destroy
;
234 /* set up unix socket */
235 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
236 if (this->socket
== -1)
238 DBG1(DBG_CFG
, "could not create XML socket");
243 old
= umask(~S_IRWXU
);
244 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
246 DBG1(DBG_CFG
, "could not bind XML socket: %s", strerror(errno
));
253 if (listen(this->socket
, 0) < 0)
255 DBG1(DBG_CFG
, "could not listen on XML socket: %s", strerror(errno
));
261 if (pthread_create(&this->thread
, NULL
, (void*(*)(void*))receive
, this) != 0)
263 DBG1(DBG_CFG
, "could not create XML socket thread: %s", strerror(errno
));
265 unlink(socket_addr
.sun_path
);
270 return &this->public.interface
;