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