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