store ESP keys in CHILD_SA
[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 ipsec_mode_t mode;
185 encryption_algorithm_t encr;
186 integrity_algorithm_t int_algo;
187 chunk_t encr_key, int_key;
188 u_int32_t rekey, use_in, use_out, use_fwd;
189 child_cfg_t *config;
190
191 config = child->get_config(child);
192 child->get_stats(child, &mode, &encr, &encr_key, &int_algo, &int_key,
193 &rekey, &use_in, &use_out, &use_fwd);
194
195 xmlTextWriterStartElement(writer, "childsa");
196 xmlTextWriterWriteFormatElement(writer, "reqid", "%d", child->get_reqid(child));
197 xmlTextWriterWriteFormatElement(writer, "childconfig", "%s",
198 config->get_name(config));
199 xmlTextWriterStartElement(writer, "local");
200 write_childend(writer, child, TRUE);
201 xmlTextWriterEndElement(writer);
202 xmlTextWriterStartElement(writer, "remote");
203 write_childend(writer, child, FALSE);
204 xmlTextWriterEndElement(writer);
205 xmlTextWriterEndElement(writer);
206 }
207
208 /**
209 * process a ikesalist query request message
210 */
211 static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
212 {
213 enumerator_t *enumerator;
214 ike_sa_t *ike_sa;
215
216 /* <ikesalist> */
217 xmlTextWriterStartElement(writer, "ikesalist");
218
219 enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
220 while (enumerator->enumerate(enumerator, &ike_sa))
221 {
222 ike_sa_id_t *id;
223 host_t *local, *remote;
224 iterator_t *children;
225 child_sa_t *child_sa;
226
227 id = ike_sa->get_id(ike_sa);
228
229 xmlTextWriterStartElement(writer, "ikesa");
230 xmlTextWriterWriteFormatElement(writer, "id", "%d",
231 ike_sa->get_unique_id(ike_sa));
232 xmlTextWriterWriteFormatElement(writer, "status", "%N",
233 ike_sa_state_lower_names, ike_sa->get_state(ike_sa));
234 xmlTextWriterWriteElement(writer, "role",
235 id->is_initiator(id) ? "initiator" : "responder");
236 xmlTextWriterWriteElement(writer, "peerconfig", ike_sa->get_name(ike_sa));
237
238 /* <local> */
239 local = ike_sa->get_my_host(ike_sa);
240 xmlTextWriterStartElement(writer, "local");
241 xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
242 id->is_initiator(id) ? id->get_initiator_spi(id)
243 : id->get_responder_spi(id));
244 write_id(writer, "identification", ike_sa->get_my_id(ike_sa));
245 write_address(writer, "address", local);
246 xmlTextWriterWriteFormatElement(writer, "port", "%d",
247 local->get_port(local));
248 if (ike_sa->supports_extension(ike_sa, EXT_NATT))
249 {
250 write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_HERE));
251 }
252 xmlTextWriterEndElement(writer);
253 /* </local> */
254
255 /* <remote> */
256 remote = ike_sa->get_other_host(ike_sa);
257 xmlTextWriterStartElement(writer, "remote");
258 xmlTextWriterWriteFormatElement(writer, "spi", "%.16llx",
259 id->is_initiator(id) ? id->get_responder_spi(id)
260 : id->get_initiator_spi(id));
261 write_id(writer, "identification", ike_sa->get_other_id(ike_sa));
262 write_address(writer, "address", remote);
263 xmlTextWriterWriteFormatElement(writer, "port", "%d",
264 remote->get_port(remote));
265 if (ike_sa->supports_extension(ike_sa, EXT_NATT))
266 {
267 write_bool(writer, "nat", ike_sa->has_condition(ike_sa, COND_NAT_THERE));
268 }
269 xmlTextWriterEndElement(writer);
270 /* </remote> */
271
272 /* <childsalist> */
273 xmlTextWriterStartElement(writer, "childsalist");
274 children = ike_sa->create_child_sa_iterator(ike_sa);
275 while (children->iterate(children, (void**)&child_sa))
276 {
277 write_child(writer, child_sa);
278 }
279 children->destroy(children);
280 /* </childsalist> */
281 xmlTextWriterEndElement(writer);
282
283 /* </ikesa> */
284 xmlTextWriterEndElement(writer);
285 }
286 enumerator->destroy(enumerator);
287
288 /* </ikesalist> */
289 xmlTextWriterEndElement(writer);
290 }
291
292 /**
293 * process a configlist query request message
294 */
295 static void request_query_config(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
296 {
297 enumerator_t *enumerator;
298 peer_cfg_t *peer_cfg;
299
300 /* <configlist> */
301 xmlTextWriterStartElement(writer, "configlist");
302
303 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
304 while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
305 {
306 enumerator_t *children;
307 child_cfg_t *child_cfg;
308 ike_cfg_t *ike_cfg;
309 linked_list_t *list;
310
311 if (peer_cfg->get_ike_version(peer_cfg) != 2)
312 { /* only IKEv2 connections yet */
313 continue;
314 }
315
316 /* <peerconfig> */
317 xmlTextWriterStartElement(writer, "peerconfig");
318 xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg));
319 write_id(writer, "local", peer_cfg->get_my_id(peer_cfg));
320 write_id(writer, "remote", peer_cfg->get_other_id(peer_cfg));
321
322 /* <ikeconfig> */
323 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
324 xmlTextWriterStartElement(writer, "ikeconfig");
325 xmlTextWriterWriteElement(writer, "local", ike_cfg->get_my_addr(ike_cfg));
326 xmlTextWriterWriteElement(writer, "remote", ike_cfg->get_other_addr(ike_cfg));
327 xmlTextWriterEndElement(writer);
328 /* </ikeconfig> */
329
330 /* <childconfiglist> */
331 xmlTextWriterStartElement(writer, "childconfiglist");
332 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
333 while (children->enumerate(children, &child_cfg))
334 {
335 /* <childconfig> */
336 xmlTextWriterStartElement(writer, "childconfig");
337 xmlTextWriterWriteElement(writer, "name",
338 child_cfg->get_name(child_cfg));
339 list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
340 write_networks(writer, "local", list);
341 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
342 list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
343 write_networks(writer, "remote", list);
344 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
345 xmlTextWriterEndElement(writer);
346 /* </childconfig> */
347 }
348 children->destroy(children);
349 /* </childconfiglist> */
350 xmlTextWriterEndElement(writer);
351 /* </peerconfig> */
352 xmlTextWriterEndElement(writer);
353 }
354 enumerator->destroy(enumerator);
355 /* </configlist> */
356 xmlTextWriterEndElement(writer);
357 }
358
359 /**
360 * callback which logs to a XML writer
361 */
362 static bool xml_callback(xmlTextWriterPtr writer, debug_t group, level_t level,
363 ike_sa_t* ike_sa, char* format, va_list args)
364 {
365 if (level <= 1)
366 {
367 /* <item> */
368 xmlTextWriterStartElement(writer, "item");
369 xmlTextWriterWriteFormatAttribute(writer, "level", "%d", level);
370 xmlTextWriterWriteFormatAttribute(writer, "source", "%N", debug_names, group);
371 xmlTextWriterWriteFormatAttribute(writer, "thread", "%u", pthread_self());
372 xmlTextWriterWriteVFormatString(writer, format, args);
373 xmlTextWriterEndElement(writer);
374 /* </item> */
375 }
376 return TRUE;
377 }
378
379 /**
380 * process a *terminate control request message
381 */
382 static void request_control_terminate(xmlTextReaderPtr reader,
383 xmlTextWriterPtr writer, bool ike)
384 {
385 if (xmlTextReaderRead(reader) &&
386 xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
387 {
388 const char *str;
389 u_int32_t id;
390 status_t status;
391
392 str = xmlTextReaderConstValue(reader);
393 if (str == NULL)
394 {
395 DBG1(DBG_CFG, "error parsing XML id string");
396 return;
397 }
398 id = atoi(str);
399 if (!id)
400 {
401 enumerator_t *enumerator;
402 ike_sa_t *ike_sa;
403
404 enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
405 while (enumerator->enumerate(enumerator, &ike_sa))
406 {
407 if (streq(str, ike_sa->get_name(ike_sa)))
408 {
409 ike = TRUE;
410 id = ike_sa->get_unique_id(ike_sa);
411 break;
412 }
413 }
414 enumerator->destroy(enumerator);
415 }
416 if (!id)
417 {
418 DBG1(DBG_CFG, "error parsing XML id string");
419 return;
420 }
421
422 DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id);
423
424 /* <log> */
425 xmlTextWriterStartElement(writer, "log");
426 if (ike)
427 {
428 status = charon->controller->terminate_ike(
429 charon->controller, id,
430 (controller_cb_t)xml_callback, writer);
431 }
432 else
433 {
434 status = charon->controller->terminate_child(
435 charon->controller, id,
436 (controller_cb_t)xml_callback, writer);
437 }
438 /* </log> */
439 xmlTextWriterEndElement(writer);
440 xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
441 }
442 }
443
444 /**
445 * process a *initiate control request message
446 */
447 static void request_control_initiate(xmlTextReaderPtr reader,
448 xmlTextWriterPtr writer, bool ike)
449 {
450 if (xmlTextReaderRead(reader) &&
451 xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT)
452 {
453 const char *str;
454 status_t status = FAILED;
455 peer_cfg_t *peer;
456 child_cfg_t *child = NULL;
457 enumerator_t *enumerator;
458
459 str = xmlTextReaderConstValue(reader);
460 if (str == NULL)
461 {
462 DBG1(DBG_CFG, "error parsing XML config name string");
463 return;
464 }
465 DBG1(DBG_CFG, "initiating %s_SA %s", ike ? "IKE" : "CHILD", str);
466
467 /* <log> */
468 xmlTextWriterStartElement(writer, "log");
469 peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str);
470 if (peer)
471 {
472 enumerator = peer->create_child_cfg_enumerator(peer);
473 if (ike)
474 {
475 if (!enumerator->enumerate(enumerator, &child))
476 {
477 child = NULL;
478 }
479 child->get_ref(child);
480 }
481 else
482 {
483 while (enumerator->enumerate(enumerator, &child))
484 {
485 if (streq(child->get_name(child), str))
486 {
487 child->get_ref(child);
488 break;
489 }
490 child = NULL;
491 }
492 }
493 enumerator->destroy(enumerator);
494 if (child)
495 {
496 status = charon->controller->initiate(charon->controller,
497 peer, child, (controller_cb_t)xml_callback,
498 writer);
499 }
500 else
501 {
502 peer->destroy(peer);
503 }
504 }
505 /* </log> */
506 xmlTextWriterEndElement(writer);
507 xmlTextWriterWriteFormatElement(writer, "status", "%d", status);
508 }
509 }
510
511 /**
512 * process a query request
513 */
514 static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
515 {
516 /* <query> */
517 xmlTextWriterStartElement(writer, "query");
518 while (xmlTextReaderRead(reader))
519 {
520 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
521 {
522 if (streq(xmlTextReaderConstName(reader), "ikesalist"))
523 {
524 request_query_ikesa(reader, writer);
525 break;
526 }
527 if (streq(xmlTextReaderConstName(reader), "configlist"))
528 {
529 request_query_config(reader, writer);
530 break;
531 }
532 }
533 }
534 /* </query> */
535 xmlTextWriterEndElement(writer);
536 }
537
538 /**
539 * process a control request
540 */
541 static void request_control(xmlTextReaderPtr reader, xmlTextWriterPtr writer)
542 {
543 /* <control> */
544 xmlTextWriterStartElement(writer, "control");
545 while (xmlTextReaderRead(reader))
546 {
547 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
548 {
549 if (streq(xmlTextReaderConstName(reader), "ikesaterminate"))
550 {
551 request_control_terminate(reader, writer, TRUE);
552 break;
553 }
554 if (streq(xmlTextReaderConstName(reader), "childsaterminate"))
555 {
556 request_control_terminate(reader, writer, FALSE);
557 break;
558 }
559 if (streq(xmlTextReaderConstName(reader), "ikesainitiate"))
560 {
561 request_control_initiate(reader, writer, TRUE);
562 break;
563 }
564 if (streq(xmlTextReaderConstName(reader), "childsainitiate"))
565 {
566 request_control_initiate(reader, writer, FALSE);
567 break;
568 }
569 }
570 }
571 /* </control> */
572 xmlTextWriterEndElement(writer);
573 }
574
575 /**
576 * process a request message
577 */
578 static void request(xmlTextReaderPtr reader, char *id, int fd)
579 {
580 xmlTextWriterPtr writer;
581
582 writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL));
583 if (writer == NULL)
584 {
585 DBG1(DBG_CFG, "opening SMP XML writer failed");
586 return;
587 }
588
589 xmlTextWriterStartDocument(writer, NULL, NULL, NULL);
590 /* <message xmlns="http://www.strongswan.org/smp/1.0"
591 id="id" type="response"> */
592 xmlTextWriterStartElement(writer, "message");
593 xmlTextWriterWriteAttribute(writer, "xmlns",
594 "http://www.strongswan.org/smp/1.0");
595 xmlTextWriterWriteAttribute(writer, "id", id);
596 xmlTextWriterWriteAttribute(writer, "type", "response");
597
598 while (xmlTextReaderRead(reader))
599 {
600 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT)
601 {
602 if (streq(xmlTextReaderConstName(reader), "query"))
603 {
604 request_query(reader, writer);
605 break;
606 }
607 if (streq(xmlTextReaderConstName(reader), "control"))
608 {
609 request_control(reader, writer);
610 break;
611 }
612 }
613 }
614 /* </message> and close document */
615 xmlTextWriterEndDocument(writer);
616 xmlFreeTextWriter(writer);
617 }
618
619 /**
620 * cleanup helper function for open file descriptors
621 */
622 static void closefdp(int *fd)
623 {
624 close(*fd);
625 }
626
627 /**
628 * read from a opened connection and process it
629 */
630 static job_requeue_t process(int *fdp)
631 {
632 int oldstate, fd = *fdp;
633 char buffer[4096];
634 size_t len;
635 xmlTextReaderPtr reader;
636 char *id = NULL, *type = NULL;
637
638 pthread_cleanup_push((void*)closefdp, (void*)&fd);
639 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
640 len = read(fd, buffer, sizeof(buffer));
641 pthread_setcancelstate(oldstate, NULL);
642 pthread_cleanup_pop(0);
643 if (len <= 0)
644 {
645 close(fd);
646 DBG2(DBG_CFG, "SMP XML connection closed");
647 return JOB_REQUEUE_NONE;
648 }
649 DBG3(DBG_CFG, "got XML request: %b", buffer, len);
650
651 reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
652 if (reader == NULL)
653 {
654 DBG1(DBG_CFG, "opening SMP XML reader failed");
655 return JOB_REQUEUE_FAIR;;
656 }
657
658 /* read message type and id */
659 while (xmlTextReaderRead(reader))
660 {
661 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT &&
662 streq(xmlTextReaderConstName(reader), "message"))
663 {
664 id = xmlTextReaderGetAttribute(reader, "id");
665 type = xmlTextReaderGetAttribute(reader, "type");
666 break;
667 }
668 }
669
670 /* process message */
671 if (id && type)
672 {
673 if (streq(type, "request"))
674 {
675 request(reader, id, fd);
676 }
677 else
678 {
679 /* response(reader, id) */
680 }
681 }
682 xmlFreeTextReader(reader);
683 return JOB_REQUEUE_FAIR;;
684 }
685
686 /**
687 * accept from XML socket and create jobs to process connections
688 */
689 static job_requeue_t dispatch(private_smp_t *this)
690 {
691 struct sockaddr_un strokeaddr;
692 int oldstate, fd, *fdp, strokeaddrlen = sizeof(strokeaddr);
693 callback_job_t *job;
694
695 /* wait for connections, but allow thread to terminate */
696 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
697 fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
698 pthread_setcancelstate(oldstate, NULL);
699
700 if (fd < 0)
701 {
702 DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno));
703 sleep(1);
704 return JOB_REQUEUE_FAIR;;
705 }
706
707 fdp = malloc_thing(int);
708 *fdp = fd;
709 job = callback_job_create((callback_job_cb_t)process, fdp, free, this->job);
710 charon->processor->queue_job(charon->processor, (job_t*)job);
711
712 return JOB_REQUEUE_DIRECT;
713 }
714
715 /**
716 * Implementation of itnerface_t.destroy.
717 */
718 static void destroy(private_smp_t *this)
719 {
720 this->job->cancel(this->job);
721 close(this->socket);
722 free(this);
723 }
724
725 /*
726 * Described in header file
727 */
728 plugin_t *plugin_create()
729 {
730 struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"};
731 private_smp_t *this = malloc_thing(private_smp_t);
732 mode_t old;
733
734 this->public.plugin.destroy = (void (*)(plugin_t*))destroy;
735
736 /* set up unix socket */
737 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
738 if (this->socket == -1)
739 {
740 DBG1(DBG_CFG, "could not create XML socket");
741 free(this);
742 return NULL;
743 }
744
745 unlink(unix_addr.sun_path);
746 old = umask(~(S_IRWXU | S_IRWXG));
747 if (bind(this->socket, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0)
748 {
749 DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno));
750 close(this->socket);
751 free(this);
752 return NULL;
753 }
754 umask(old);
755 if (chown(unix_addr.sun_path, charon->uid, charon->gid) != 0)
756 {
757 DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
758 }
759
760 if (listen(this->socket, 5) < 0)
761 {
762 DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno));
763 close(this->socket);
764 free(this);
765 return NULL;
766 }
767
768 this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL);
769 charon->processor->queue_job(charon->processor, (job_t*)this->job);
770
771 return &this->public.plugin;
772 }
773