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