filtering out IKEv1 configurations for manager
[strongswan.git] / src / charon / control / interfaces / xml_interface.c
1 /**
2 * @file xml_interface.c
3 *
4 * @brief Implementation of xml_interface_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23 #include <stdlib.h>
24
25 #include "xml_interface.h"
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <pthread.h>
34 #include <signal.h>
35 #include <libxml/xmlreader.h>
36 #include <libxml/xmlwriter.h>
37
38 #include <library.h>
39 #include <daemon.h>
40 #include <processing/jobs/callback_job.h>
41
42
43 typedef struct private_xml_interface_t private_xml_interface_t;
44
45 /**
46 * Private data of an xml_interface_t object.
47 */
48 struct private_xml_interface_t {
49
50 /**
51 * Public part of xml_t object.
52 */
53 xml_interface_t public;
54
55 /**
56 * XML unix socket fd
57 */
58 int socket;
59
60 /**
61 * job accepting stroke messages
62 */
63 callback_job_t *job;
64 };
65
66 ENUM(ike_sa_state_lower_names, IKE_CREATED, IKE_DELETING,
67 "created",
68 "connecting",
69 "established",
70 "rekeying",
71 "deleting",
72 );
73
74 /**
75 * write a bool into element
76 */
77 static void write_bool(xmlTextWriterPtr writer, char *element, bool val)
78 {
79 xmlTextWriterWriteElement(writer, element, val ? "true" : "false");
80 }
81
82 /**
83 * write a identification_t into element
84 */
85 static void write_id(xmlTextWriterPtr writer, char *element, identification_t *id)
86 {
87 xmlTextWriterStartElement(writer, element);
88 switch (id->get_type(id))
89 {
90 {
91 char *type = "";
92 while (TRUE)
93 {
94 case ID_IPV4_ADDR:
95 type = "ipv4";
96 break;
97 case ID_IPV6_ADDR:
98 type = "ipv6";
99 break;
100 case ID_FQDN:
101 type = "fqdn";
102 break;
103 case ID_RFC822_ADDR:
104 type = "email";
105 break;
106 case ID_DER_ASN1_DN:
107 type = "asn1dn";
108 break;
109 case ID_DER_ASN1_GN:
110 type = "asn1gn";
111 break;
112 }
113 xmlTextWriterWriteAttribute(writer, "type", type);
114 xmlTextWriterWriteFormatString(writer, "%D", id);
115 break;
116 }
117 case ID_ANY:
118 xmlTextWriterWriteAttribute(writer, "type", "any");
119 break;
120 default:
121 /* TODO: base64 keyid */
122 xmlTextWriterWriteAttribute(writer, "type", "keyid");
123 break;
124 }
125 xmlTextWriterEndElement(writer);
126 }
127
128 /**
129 * write a host_t address into an element
130 */
131 static void write_address(xmlTextWriterPtr writer, char *element, host_t *host)
132 {
133 xmlTextWriterStartElement(writer, element);
134 xmlTextWriterWriteAttribute(writer, "type",
135 host->get_family(host) == AF_INET ? "ipv4" : "ipv6");
136 if (host->is_anyaddr(host))
137 { /* do not use %any for XML */
138 xmlTextWriterWriteFormatString(writer, "%s",
139 host->get_family(host) == AF_INET ? "0.0.0.0" : "::");
140 }
141 else
142 {
143 xmlTextWriterWriteFormatString(writer, "%H", host);
144 }
145 xmlTextWriterEndElement(writer);
146 }
147
148 /**
149 * write networks element
150 */
151 static void write_networks(xmlTextWriterPtr writer, char *element,
152 linked_list_t *list)
153 {
154 iterator_t *iterator;
155 traffic_selector_t *ts;
156
157 xmlTextWriterStartElement(writer, element);
158 iterator = list->create_iterator(list, TRUE);
159 while (iterator->iterate(iterator, (void**)&ts))
160 {
161 xmlTextWriterStartElement(writer, "network");
162 xmlTextWriterWriteAttribute(writer, "type",
163 ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? "ipv4" : "ipv6");
164 xmlTextWriterWriteFormatString(writer, "%R", ts);
165 xmlTextWriterEndElement(writer);
166 }
167 iterator->destroy(iterator);
168 xmlTextWriterEndElement(writer);
169 }
170
171 /**
172 * write a childEnd
173 */
174 static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool local)
175 {
176 linked_list_t *list;
177
178 xmlTextWriterWriteFormatElement(writer, "spi", "%lx",
179 htonl(child->get_spi(child, local)));
180 list = child->get_traffic_selectors(child, local);
181 write_networks(writer, "networks", list);
182 }
183
184 /**
185 * write a child_sa_t
186 */
187 static void write_child(xmlTextWriterPtr writer, child_sa_t *child)
188 {
189 mode_t mode;
190 encryption_algorithm_t encr;
191 integrity_algorithm_t int_algo;
192 size_t encr_len, int_len;
193 u_int32_t rekey, use_in, use_out, use_fwd;
194 child_cfg_t *config;
195
196 config = child->get_config(child);
197 child->get_stats(child, &mode, &encr, &encr_len, &int_algo, &int_len,
198 &rekey, &use_in, &use_out, &use_fwd);
199
200 xmlTextWriterStartElement(writer, "childsa");
201 xmlTextWriterWriteFormatElement(writer, "reqid", "%d", child->get_reqid(child));
202 xmlTextWriterWriteFormatElement(writer, "childconfig", "%s",
203 config->get_name(config));
204 xmlTextWriterStartElement(writer, "local");
205 write_childend(writer, child, TRUE);
206 xmlTextWriterEndElement(writer);
207 xmlTextWriterStartElement(writer, "remote");
208 write_childend(writer, child, FALSE);
209 xmlTextWriterEndElement(writer);
210 xmlTextWriterEndElement(writer);
211 }
212
213 /**
214 * process a ikesalist query request message
215 */
216 static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
217 {
218 iterator_t *iterator;
219 ike_sa_t *ike_sa;
220
221 /* <ikesalist> */
222 xmlTextWriterStartElement(writer, "ikesalist");
223
224 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
225 while (iterator->iterate(iterator, (void**)&ike_sa))
226 {
227 ike_sa_id_t *id;
228 host_t *local, *remote;
229 iterator_t *children;
230 child_sa_t *child_sa;
231
232 id = ike_sa->get_id(ike_sa);
233
234 xmlTextWriterStartElement(writer, "ikesa");
235 xmlTextWriterWriteFormatElement(writer, "id", "%d",
236 ike_sa->get_unique_id(ike_sa));
237 xmlTextWriterWriteFormatElement(writer, "status", "%N",
238 ike_sa_state_lower_names, ike_sa->get_state(ike_sa));
239 xmlTextWriterWriteElement(writer, "role",
240 id->is_initiator(id) ? "initiator" : "responder");
241 xmlTextWriterWriteElement(writer, "peerconfig", ike_sa->get_name(ike_sa));
242
243 /* <local> */
244 local = ike_sa->get_my_host(ike_sa);
245 xmlTextWriterStartElement(writer, "local");
246 xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
247 id->is_initiator(id) ? id->get_initiator_spi(id)
248 : id->get_responder_spi(id));
249 write_id(writer, "identification", ike_sa->get_my_id(ike_sa));
250 write_address(writer, "address", local);
251 xmlTextWriterWriteFormatElement(writer, "port", "%d",
252 local->get_port(local));
253 if (ike_sa->supports_extension(ike_sa, EXT_NATT))
254 {
255 write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_HERE));
256 }
257 xmlTextWriterEndElement(writer);
258 /* </local> */
259
260 /* <remote> */
261 remote = ike_sa->get_other_host(ike_sa);
262 xmlTextWriterStartElement(writer, "remote");
263 xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
264 id->is_initiator(id) ? id->get_responder_spi(id)
265 : id->get_initiator_spi(id));
266 write_id(writer, "identification", ike_sa->get_other_id(ike_sa));
267 write_address(writer, "address", remote);
268 xmlTextWriterWriteFormatElement(writer, "port", "%d",
269 remote->get_port(remote));
270 if (ike_sa->supports_extension(ike_sa, EXT_NATT))
271 {
272 write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_THERE));
273 }
274 xmlTextWriterEndElement(writer);
275 /* </remote> */
276
277 /* <childsalist> */
278 xmlTextWriterStartElement(writer, "childsalist");
279 children = ike_sa->create_child_sa_iterator(ike_sa);
280 while (children->iterate(children, (void**)&child_sa))
281 {
282 write_child(writer, child_sa);
283 }
284 children->destroy(children);
285 /* </childsalist> */
286 xmlTextWriterEndElement(writer);
287
288 /* </ikesa> */
289 xmlTextWriterEndElement(writer);
290 }
291 iterator->destroy(iterator);
292
293 /* </ikesalist> */
294 xmlTextWriterEndElement(writer);
295 }
296
297 /**
298 * process a configlist query request message
299 */
300 static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
301 {
302 iterator_t *iterator;
303 peer_cfg_t *peer_cfg;
304
305 /* <configlist> */
306 xmlTextWriterStartElement(writer, "configlist");
307
308 iterator = charon->backends->create_iterator(charon->backends);
309 while (iterator->iterate(iterator, (void**)&peer_cfg))
310 {
311 iterator_t *children;
312 child_cfg_t *child_cfg;
313 ike_cfg_t *ike_cfg;
314 linked_list_t *list;
315
316 if (peer_cfg->get_ike_version(peer_cfg) != 2)
317 { /* only IKEv2 connections yet */
318 continue;
319 }
320
321 /* <peerconfig> */
322 xmlTextWriterStartElement(writer, "peerconfig");
323 xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
324 write_id(writer, "local", peer_cfg->get_my_id(peer_cfg));
325 write_id(writer, "remote", peer_cfg->get_other_id(peer_cfg));
326
327 /* <ikeconfig> */
328 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
329 xmlTextWriterStartElement(writer, "ikeconfig");
330 write_address(writer, "local", ike_cfg->get_my_host(ike_cfg));
331 write_address(writer, "remote", ike_cfg->get_other_host(ike_cfg));
332 xmlTextWriterEndElement(writer);
333 /* </ikeconfig> */
334
335 /* <childconfiglist> */
336 xmlTextWriterStartElement(writer, "childconfiglist");
337 children = peer_cfg->create_child_cfg_iterator(peer_cfg);
338 while (children->iterate(children, (void**)&child_cfg))
339 {
340 /* <childconfig> */
341 xmlTextWriterStartElement(writer, "childconfig");
342 xmlTextWriterWriteElement(writer, "name",
343 child_cfg->get_name(child_cfg));
344 list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
345 write_networks(writer, "local", list);
346 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
347 list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
348 write_networks(writer, "remote", list);
349 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
350 xmlTextWriterEndElement(writer);
351 /* </childconfig> */
352 }
353 children->destroy(children);
354 /* </childconfiglist> */
355 xmlTextWriterEndElement(writer);
356 /* </peerconfig> */
357 xmlTextWriterEndElement(writer);
358 }
359 iterator->destroy(iterator);
360 /* </configlist> */
361 xmlTextWriterEndElement(writer);
362 }
363
364 /**
365 * callback which logs to a XML writer
366 */
367 static bool xml_callback(xmlTextWriterPtr writer, signal_t signal, level_t level,
368 ike_sa_t* ike_sa, char* format, va_list args)
369 {
370 if (level <= 1)
371 {
372 /* <item> */
373 xmlTextWriterStartElement(writer, "item");
374 xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level);
375 xmlTextWriterWriteFormatAttribute(writer, "source", "%N", signal_names, signal);
376 xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", pthread_self());
377 xmlTextWriterWriteVFormatString(writer, format, args);
378 xmlTextWriterEndElement(writer);
379 /* </item> */
380 }
381 return TRUE;
382 }
383
384 /**
385 * process a *terminate control request message
386 */
387 static void request_control_terminate(xmlTextReaderPtr reader,
388 xmlTextWriterPtr writer, bool ike)
389 {
390 if (xmlTextReaderRead(reader) &&
391 xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
392 {
393 const char *str;
394 u_int32_t id;
395 status_t status;
396
397 str = xmlTextReaderConstValue(reader);
398 if (str == NULL || !(id = atoi(str)))
399 {
400 DBG1(DBG_CFG, "error parsing XML id string");
401 return;
402 }
403 DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id);
404
405 /* <log> */
406 xmlTextWriterStartElement(writer, "log");
407 if (ike)
408 {
409 status = charon->interfaces->terminate_ike(
410 charon->interfaces, id,
411 (interface_manager_cb_t)xml_callback, writer);
412 }
413 else
414 {
415 status = charon->interfaces->terminate_child(
416 charon->interfaces, id,
417 (interface_manager_cb_t)xml_callback, writer);
418 }
419 /* </log> */
420 xmlTextWriterEndElement(writer);
421 xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
422 }
423 }
424
425 /**
426 * process a *initiate control request message
427 */
428 static void request_control_initiate(xmlTextReaderPtr reader,
429 xmlTextWriterPtr writer, bool ike)
430 {
431 if (xmlTextReaderRead(reader) &&
432 xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
433 {
434 const char *str;
435 status_t status = FAILED;
436 peer_cfg_t *peer;
437 child_cfg_t *child = NULL;
438 iterator_t *iterator;
439
440 str = xmlTextReaderConstValue(reader);
441 if (str == NULL)
442 {
443 DBG1(DBG_CFG, "error parsing XML config name string");
444 return;
445 }
446 DBG1(DBG_CFG, "initiating %s_SA %s", ike ? "IKE" : "CHILD", str);
447
448 /* <log> */
449 xmlTextWriterStartElement(writer, "log");
450 peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str);
451 if (peer)
452 {
453 iterator = peer->create_child_cfg_iterator(peer);
454 if (ike)
455 {
456 if (!iterator->iterate(iterator, (void**)&child))
457 {
458 child = NULL;
459 }
460 child->get_ref(child);
461 }
462 else
463 {
464 while (iterator->iterate(iterator, (void**)&child))
465 {
466 if (streq(child->get_name(child), str))
467 {
468 child->get_ref(child);
469 break;
470 }
471 child = NULL;
472 }
473 }
474 iterator->destroy(iterator);
475 if (child)
476 {
477 status = charon->interfaces->initiate(charon->interfaces,
478 peer, child, (interface_manager_cb_t)xml_callback,
479 writer);
480 }
481 else
482 {
483 peer->destroy(peer);
484 }
485 }
486 /* </log> */
487 xmlTextWriterEndElement(writer);
488 xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
489 }
490 }
491
492 /**
493 * process a query request
494 */
495 static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
496 {
497 /* <query> */
498 xmlTextWriterStartElement(writer, "query");
499 while (xmlTextReaderRead(reader))
500 {
501 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
502 {
503 if (streq(xmlTextReaderConstName(reader), "ikesalist"))
504 {
505 request_query_ikesa(reader, writer);
506 break;
507 }
508 if (streq(xmlTextReaderConstName(reader), "configlist"))
509 {
510 request_query_config(reader, writer);
511 break;
512 }
513 }
514 }
515 /* </query> */
516 xmlTextWriterEndElement(writer);
517 }
518
519 /**
520 * process a control request
521 */
522 static void request_control(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
523 {
524 /* <control> */
525 xmlTextWriterStartElement(writer, "control");
526 while (xmlTextReaderRead(reader))
527 {
528 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
529 {
530 if (streq(xmlTextReaderConstName(reader), "ikesaterminate"))
531 {
532 request_control_terminate(reader, writer, TRUE);
533 break;
534 }
535 if (streq(xmlTextReaderConstName(reader), "childsaterminate"))
536 {
537 request_control_terminate(reader, writer, FALSE);
538 break;
539 }
540 if (streq(xmlTextReaderConstName(reader), "ikesainitiate"))
541 {
542 request_control_initiate(reader, writer, TRUE);
543 break;
544 }
545 if (streq(xmlTextReaderConstName(reader), "childsainitiate"))
546 {
547 request_control_initiate(reader, writer, FALSE);
548 break;
549 }
550 }
551 }
552 /* </control> */
553 xmlTextWriterEndElement(writer);
554 }
555
556 /**
557 * process a request message
558 */
559 static void request(xmlTextReaderPtr reader, char *id, int fd)
560 {
561 xmlTextWriterPtr writer;
562
563 writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL));
564 if (writer == NULL)
565 {
566 DBG1(DBG_CFG, "opening SMP XML writer failed");
567 return;
568 }
569
570 xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
571 /* <message xmlns="http://www.strongswan.org/smp/1.0"
572 id="id" type="response"> */
573 xmlTextWriterStartElement(writer, "message");
574 xmlTextWriterWriteAttribute(writer, "xmlns",
575 "http://www.strongswan.org/smp/1.0");
576 xmlTextWriterWriteAttribute(writer, "id", id);
577 xmlTextWriterWriteAttribute(writer, "type", "response");
578
579 while (xmlTextReaderRead(reader))
580 {
581 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
582 {
583 if (streq(xmlTextReaderConstName(reader), "query"))
584 {
585 request_query(reader, writer);
586 break;
587 }
588 if (streq(xmlTextReaderConstName(reader), "control"))
589 {
590 request_control(reader, writer);
591 break;
592 }
593 }
594 }
595 /* </message> and close document */
596 xmlTextWriterEndDocument(writer);
597 xmlFreeTextWriter(writer);
598 }
599
600 /**
601 * cleanup helper function for open file descriptors
602 */
603 static void closefdp(int *fd)
604 {
605 close(*fd);
606 }
607
608 /**
609 * read from a opened connection and process it
610 */
611 static job_requeue_t process(int *fdp)
612 {
613 int oldstate, fd = *fdp;
614 char buffer[4096];
615 size_t len;
616 xmlTextReaderPtr reader;
617 char *id = NULL, *type = NULL;
618
619 pthread_cleanup_push((void*)closefdp, (void*)&fd);
620 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
621 len = read(fd, buffer, sizeof(buffer));
622 pthread_setcancelstate(oldstate, NULL);
623 pthread_cleanup_pop(0);
624 if (len <= 0)
625 {
626 close(fd);
627 DBG2(DBG_CFG, "SMP XML connection closed");
628 return JOB_REQUEUE_NONE;
629 }
630 DBG3(DBG_CFG, "got XML request: %b", buffer, len);
631
632 reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
633 if (reader == NULL)
634 {
635 DBG1(DBG_CFG, "opening SMP XML reader failed");
636 return JOB_REQUEUE_FAIR;;
637 }
638
639 /* read message type and id */
640 while (xmlTextReaderRead(reader))
641 {
642 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT &&
643 streq(xmlTextReaderConstName(reader), "message"))
644 {
645 id = xmlTextReaderGetAttribute(reader, "id");
646 type = xmlTextReaderGetAttribute(reader, "type");
647 break;
648 }
649 }
650
651 /* process message */
652 if (id && type)
653 {
654 if (streq(type, "request"))
655 {
656 request(reader, id, fd);
657 }
658 else
659 {
660 /* response(reader, id) */
661 }
662 }
663 xmlFreeTextReader(reader);
664 return JOB_REQUEUE_FAIR;;
665 }
666
667 /**
668 * accept from XML socket and create jobs to process connections
669 */
670 static job_requeue_t dispatch(private_xml_interface_t *this)
671 {
672 struct sockaddr_un strokeaddr;
673 int oldstate, fd, *fdp, strokeaddrlen = sizeof(strokeaddr);
674 callback_job_t *job;
675
676 /* wait for connections, but allow thread to terminate */
677 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
678 fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
679 pthread_setcancelstate(oldstate, NULL);
680
681 if (fd < 0)
682 {
683 DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno));
684 sleep(1);
685 return JOB_REQUEUE_FAIR;;
686 }
687
688 fdp = malloc_thing(int);
689 *fdp = fd;
690 job = callback_job_create((callback_job_cb_t)process, fdp, free, this->job);
691 charon->processor->queue_job(charon->processor, (job_t*)job);
692
693 return JOB_REQUEUE_DIRECT;
694 }
695
696 /**
697 * Implementation of itnerface_t.destroy.
698 */
699 static void destroy(private_xml_interface_t *this)
700 {
701 this->job->cancel(this->job);
702 close(this->socket);
703 free(this);
704 }
705
706 /*
707 * Described in header file
708 */
709 interface_t *interface_create()
710 {
711 struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"};
712 private_xml_interface_t *this = malloc_thing(private_xml_interface_t);
713 mode_t old;
714
715 this->public.interface.destroy = (void (*)(interface_t*))destroy;
716
717 /* set up unix socket */
718 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
719 if (this->socket == -1)
720 {
721 DBG1(DBG_CFG, "could not create XML socket");
722 free(this);
723 return NULL;
724 }
725
726 unlink(unix_addr.sun_path);
727 old = umask(~(S_IRWXU | S_IRWXG));
728 if (bind(this->socket, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0)
729 {
730 DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno));
731 close(this->socket);
732 free(this);
733 return NULL;
734 }
735 umask(old);
736 if (chown(unix_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0)
737 {
738 DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
739 }
740
741 if (listen(this->socket, 5) < 0)
742 {
743 DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno));
744 close(this->socket);
745 free(this);
746 return NULL;
747 }
748
749 this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
750 charon->processor->queue_job(charon->processor, (job_t*)this->job);
751
752 return &this->public.interface;
753 }
754