Return to smp.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / smp |
1.1 misho 1: /* 2: * Copyright (C) 2007 Martin Willi 3: * HSR 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 <inttypes.h> 28: #include <libxml/xmlreader.h> 29: #include <libxml/xmlwriter.h> 30: 31: #include <library.h> 32: #include <daemon.h> 33: #include <threading/thread.h> 34: #include <processing/jobs/callback_job.h> 35: 36: 37: typedef struct private_smp_t private_smp_t; 38: 39: /** 40: * Private data of an smp_t object. 41: */ 42: struct private_smp_t { 43: 44: /** 45: * Public part of smp_t object. 46: */ 47: smp_t public; 48: 49: /** 50: * XML unix socket fd 51: */ 52: int socket; 53: }; 54: 55: ENUM(ike_sa_state_lower_names, IKE_CREATED, IKE_DELETING, 56: "created", 57: "connecting", 58: "established", 59: "passive", 60: "rekeying", 61: "rekeyed", 62: "deleting", 63: ); 64: 65: /** 66: * write a bool into element 67: */ 68: static void write_bool(xmlTextWriterPtr writer, char *element, bool val) 69: { 70: xmlTextWriterWriteElement(writer, element, val ? "true" : "false"); 71: } 72: 73: /** 74: * write a identification_t into element 75: */ 76: static void write_id(xmlTextWriterPtr writer, char *element, identification_t *id) 77: { 78: xmlTextWriterStartElement(writer, element); 79: switch (id->get_type(id)) 80: { 81: { 82: char *type; 83: 84: while (TRUE) 85: { 86: case ID_ANY: 87: type = "any"; 88: break; 89: case ID_IPV4_ADDR: 90: type = "ipv4"; 91: break; 92: case ID_IPV6_ADDR: 93: type = "ipv6"; 94: break; 95: case ID_FQDN: 96: type = "fqdn"; 97: break; 98: case ID_RFC822_ADDR: 99: type = "email"; 100: break; 101: case ID_DER_ASN1_DN: 102: type = "asn1dn"; 103: break; 104: case ID_DER_ASN1_GN: 105: type = "asn1gn"; 106: break; 107: } 108: xmlTextWriterWriteAttribute(writer, "type", type); 109: xmlTextWriterWriteFormatString(writer, "%Y", id); 110: break; 111: } 112: default: 113: /* TODO: base64 keyid */ 114: xmlTextWriterWriteAttribute(writer, "type", "keyid"); 115: break; 116: } 117: xmlTextWriterEndElement(writer); 118: } 119: 120: /** 121: * write a host_t address into an element 122: */ 123: static void write_address(xmlTextWriterPtr writer, char *element, host_t *host) 124: { 125: xmlTextWriterStartElement(writer, element); 126: xmlTextWriterWriteAttribute(writer, "type", 127: host->get_family(host) == AF_INET ? "ipv4" : "ipv6"); 128: if (host->is_anyaddr(host)) 129: { /* do not use %any for XML */ 130: xmlTextWriterWriteFormatString(writer, "%s", 131: host->get_family(host) == AF_INET ? "0.0.0.0" : "::"); 132: } 133: else 134: { 135: xmlTextWriterWriteFormatString(writer, "%H", host); 136: } 137: xmlTextWriterEndElement(writer); 138: } 139: 140: /** 141: * write networks element 142: */ 143: static void write_networks(xmlTextWriterPtr writer, char *element, 144: linked_list_t *list) 145: { 146: enumerator_t *enumerator; 147: traffic_selector_t *ts; 148: 149: xmlTextWriterStartElement(writer, element); 150: enumerator = list->create_enumerator(list); 151: while (enumerator->enumerate(enumerator, (void**)&ts)) 152: { 153: xmlTextWriterStartElement(writer, "network"); 154: xmlTextWriterWriteAttribute(writer, "type", 155: ts->get_type(ts) == TS_IPV4_ADDR_RANGE ? "ipv4" : "ipv6"); 156: xmlTextWriterWriteFormatString(writer, "%R", ts); 157: xmlTextWriterEndElement(writer); 158: } 159: enumerator->destroy(enumerator); 160: xmlTextWriterEndElement(writer); 161: } 162: 163: /** 164: * write a childEnd 165: */ 166: static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool local) 167: { 168: linked_list_t *list; 169: 170: xmlTextWriterWriteFormatElement(writer, "spi", "%x", 171: htonl(child->get_spi(child, local))); 172: list = linked_list_create_from_enumerator( 173: child->create_ts_enumerator(child, local)); 174: write_networks(writer, "networks", list); 175: list->destroy(list); 176: } 177: 178: /** 179: * write a child_sa_t 180: */ 181: static void write_child(xmlTextWriterPtr writer, child_sa_t *child) 182: { 183: child_cfg_t *config; 184: 185: config = child->get_config(child); 186: 187: xmlTextWriterStartElement(writer, "childsa"); 188: xmlTextWriterWriteFormatElement(writer, "reqid", "%d", 189: child->get_reqid(child)); 190: xmlTextWriterWriteFormatElement(writer, "childconfig", "%s", 191: config->get_name(config)); 192: xmlTextWriterStartElement(writer, "local"); 193: write_childend(writer, child, TRUE); 194: xmlTextWriterEndElement(writer); 195: xmlTextWriterStartElement(writer, "remote"); 196: write_childend(writer, child, FALSE); 197: xmlTextWriterEndElement(writer); 198: xmlTextWriterEndElement(writer); 199: } 200: 201: /** 202: * process a ikesalist query request message 203: */ 204: static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer) 205: { 206: enumerator_t *enumerator; 207: ike_sa_t *ike_sa; 208: 209: /* <ikesalist> */ 210: xmlTextWriterStartElement(writer, "ikesalist"); 211: 212: enumerator = charon->controller->create_ike_sa_enumerator( 213: charon->controller, TRUE); 214: while (enumerator->enumerate(enumerator, &ike_sa)) 215: { 216: ike_sa_id_t *id; 217: host_t *local, *remote; 218: enumerator_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", "%.16"PRIx64, 236: be64toh(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", "%.16"PRIx64, 253: be64toh(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_enumerator(ike_sa); 269: while (children->enumerate(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: NULL, NULL, NULL, NULL, IKE_ANY); 299: while (enumerator->enumerate(enumerator, &peer_cfg)) 300: { 301: enumerator_t *children; 302: child_cfg_t *child_cfg; 303: ike_cfg_t *ike_cfg; 304: linked_list_t *list; 305: 306: /* <peerconfig> */ 307: xmlTextWriterStartElement(writer, "peerconfig"); 308: xmlTextWriterWriteElement(writer, "name", peer_cfg->get_name(peer_cfg)); 309: 310: /* TODO: write auth_cfgs */ 311: 312: /* <ikeconfig> */ 313: ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); 314: xmlTextWriterStartElement(writer, "ikeconfig"); 315: xmlTextWriterWriteElement(writer, "local", 316: ike_cfg->get_my_addr(ike_cfg)); 317: xmlTextWriterWriteElement(writer, "remote", 318: ike_cfg->get_other_addr(ike_cfg)); 319: xmlTextWriterEndElement(writer); 320: /* </ikeconfig> */ 321: 322: /* <childconfiglist> */ 323: xmlTextWriterStartElement(writer, "childconfiglist"); 324: children = peer_cfg->create_child_cfg_enumerator(peer_cfg); 325: while (children->enumerate(children, &child_cfg)) 326: { 327: /* <childconfig> */ 328: xmlTextWriterStartElement(writer, "childconfig"); 329: xmlTextWriterWriteElement(writer, "name", 330: child_cfg->get_name(child_cfg)); 331: list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, 332: NULL, FALSE); 333: write_networks(writer, "local", list); 334: list->destroy_offset(list, offsetof(traffic_selector_t, destroy)); 335: list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, 336: NULL, FALSE); 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* message) 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", thread_current_id()); 366: xmlTextWriterWriteString(writer, message); 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: uint32_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( 399: charon->controller, TRUE); 400: while (enumerator->enumerate(enumerator, &ike_sa)) 401: { 402: if (streq(str, ike_sa->get_name(ike_sa))) 403: { 404: ike = TRUE; 405: id = ike_sa->get_unique_id(ike_sa); 406: break; 407: } 408: } 409: enumerator->destroy(enumerator); 410: } 411: if (!id) 412: { 413: DBG1(DBG_CFG, "error parsing XML id string"); 414: return; 415: } 416: 417: DBG1(DBG_CFG, "terminating %s_SA %d", ike ? "IKE" : "CHILD", id); 418: 419: /* <log> */ 420: xmlTextWriterStartElement(writer, "log"); 421: if (ike) 422: { 423: status = charon->controller->terminate_ike( 424: charon->controller, id, FALSE, 425: (controller_cb_t)xml_callback, writer, 0); 426: } 427: else 428: { 429: status = charon->controller->terminate_child( 430: charon->controller, id, 431: (controller_cb_t)xml_callback, writer, 0); 432: } 433: /* </log> */ 434: xmlTextWriterEndElement(writer); 435: xmlTextWriterWriteFormatElement(writer, "status", "%d", status); 436: } 437: } 438: 439: /** 440: * process a *initiate control request message 441: */ 442: static void request_control_initiate(xmlTextReaderPtr reader, 443: xmlTextWriterPtr writer, bool ike) 444: { 445: if (xmlTextReaderRead(reader) && 446: xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) 447: { 448: const char *str; 449: status_t status = FAILED; 450: peer_cfg_t *peer; 451: child_cfg_t *child = NULL; 452: enumerator_t *enumerator; 453: 454: str = xmlTextReaderConstValue(reader); 455: if (str == NULL) 456: { 457: DBG1(DBG_CFG, "error parsing XML config name string"); 458: return; 459: } 460: DBG1(DBG_CFG, "initiating %s_SA %s", ike ? "IKE" : "CHILD", str); 461: 462: /* <log> */ 463: xmlTextWriterStartElement(writer, "log"); 464: peer = charon->backends->get_peer_cfg_by_name(charon->backends, 465: (char*)str); 466: if (peer) 467: { 468: enumerator = peer->create_child_cfg_enumerator(peer); 469: if (ike) 470: { 471: if (enumerator->enumerate(enumerator, &child)) 472: { 473: child->get_ref(child); 474: } 475: else 476: { 477: child = NULL; 478: } 479: } 480: else 481: { 482: while (enumerator->enumerate(enumerator, &child)) 483: { 484: if (streq(child->get_name(child), str)) 485: { 486: child->get_ref(child); 487: break; 488: } 489: child = NULL; 490: } 491: } 492: enumerator->destroy(enumerator); 493: if (child) 494: { 495: status = charon->controller->initiate(charon->controller, 496: peer, child, (controller_cb_t)xml_callback, 497: writer, 0, FALSE); 498: } 499: else 500: { 501: peer->destroy(peer); 502: } 503: } 504: /* </log> */ 505: xmlTextWriterEndElement(writer); 506: xmlTextWriterWriteFormatElement(writer, "status", "%d", status); 507: } 508: } 509: 510: /** 511: * process a query request 512: */ 513: static void request_query(xmlTextReaderPtr reader, xmlTextWriterPtr writer) 514: { 515: /* <query> */ 516: xmlTextWriterStartElement(writer, "query"); 517: while (xmlTextReaderRead(reader)) 518: { 519: if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) 520: { 521: if (streq(xmlTextReaderConstName(reader), "ikesalist")) 522: { 523: request_query_ikesa(reader, writer); 524: break; 525: } 526: if (streq(xmlTextReaderConstName(reader), "configlist")) 527: { 528: request_query_config(reader, writer); 529: break; 530: } 531: } 532: } 533: /* </query> */ 534: xmlTextWriterEndElement(writer); 535: } 536: 537: /** 538: * process a control request 539: */ 540: static void request_control(xmlTextReaderPtr reader, xmlTextWriterPtr writer) 541: { 542: /* <control> */ 543: xmlTextWriterStartElement(writer, "control"); 544: while (xmlTextReaderRead(reader)) 545: { 546: if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) 547: { 548: if (streq(xmlTextReaderConstName(reader), "ikesaterminate")) 549: { 550: request_control_terminate(reader, writer, TRUE); 551: break; 552: } 553: if (streq(xmlTextReaderConstName(reader), "childsaterminate")) 554: { 555: request_control_terminate(reader, writer, FALSE); 556: break; 557: } 558: if (streq(xmlTextReaderConstName(reader), "ikesainitiate")) 559: { 560: request_control_initiate(reader, writer, TRUE); 561: break; 562: } 563: if (streq(xmlTextReaderConstName(reader), "childsainitiate")) 564: { 565: request_control_initiate(reader, writer, FALSE); 566: break; 567: } 568: } 569: } 570: /* </control> */ 571: xmlTextWriterEndElement(writer); 572: } 573: 574: /** 575: * process a request message 576: */ 577: static void request(xmlTextReaderPtr reader, char *id, int fd) 578: { 579: xmlTextWriterPtr writer; 580: 581: writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL)); 582: if (writer == NULL) 583: { 584: DBG1(DBG_CFG, "opening SMP XML writer failed"); 585: return; 586: } 587: 588: xmlTextWriterStartDocument(writer, NULL, NULL, NULL); 589: /* <message xmlns="http://www.strongswan.org/smp/1.0" 590: id="id" type="response"> */ 591: xmlTextWriterStartElement(writer, "message"); 592: xmlTextWriterWriteAttribute(writer, "xmlns", 593: "http://www.strongswan.org/smp/1.0"); 594: xmlTextWriterWriteAttribute(writer, "id", id); 595: xmlTextWriterWriteAttribute(writer, "type", "response"); 596: 597: while (xmlTextReaderRead(reader)) 598: { 599: if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) 600: { 601: if (streq(xmlTextReaderConstName(reader), "query")) 602: { 603: request_query(reader, writer); 604: break; 605: } 606: if (streq(xmlTextReaderConstName(reader), "control")) 607: { 608: request_control(reader, writer); 609: break; 610: } 611: } 612: } 613: /* </message> and close document */ 614: xmlTextWriterEndDocument(writer); 615: xmlFreeTextWriter(writer); 616: } 617: 618: /** 619: * cleanup helper function for open file descriptors 620: */ 621: static void closefdp(int *fd) 622: { 623: close(*fd); 624: } 625: 626: /** 627: * read from a opened connection and process it 628: */ 629: static job_requeue_t process(int *fdp) 630: { 631: int fd = *fdp; 632: bool oldstate; 633: char buffer[4096]; 634: ssize_t len; 635: xmlTextReaderPtr reader; 636: char *id = NULL, *type = NULL; 637: 638: thread_cleanup_push((thread_cleanup_t)closefdp, (void*)&fd); 639: oldstate = thread_cancelability(TRUE); 640: len = read(fd, buffer, sizeof(buffer)); 641: thread_cancelability(oldstate); 642: thread_cleanup_pop(FALSE); 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, (u_int)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 fd, *fdp, strokeaddrlen = sizeof(strokeaddr); 693: callback_job_t *job; 694: bool oldstate; 695: 696: /* wait for connections, but allow thread to terminate */ 697: oldstate = thread_cancelability(TRUE); 698: fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen); 699: thread_cancelability(oldstate); 700: 701: if (fd < 0) 702: { 703: DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno)); 704: sleep(1); 705: return JOB_REQUEUE_FAIR;; 706: } 707: 708: fdp = malloc_thing(int); 709: *fdp = fd; 710: job = callback_job_create((callback_job_cb_t)process, fdp, free, 711: (callback_job_cancel_t)return_false); 712: lib->processor->queue_job(lib->processor, (job_t*)job); 713: 714: return JOB_REQUEUE_DIRECT; 715: } 716: 717: METHOD(plugin_t, get_name, char*, 718: private_smp_t *this) 719: { 720: return "smp"; 721: } 722: 723: METHOD(plugin_t, get_features, int, 724: private_smp_t *this, plugin_feature_t *features[]) 725: { 726: static plugin_feature_t f[] = { 727: PLUGIN_NOOP, 728: PLUGIN_PROVIDE(CUSTOM, "smp"), 729: }; 730: *features = f; 731: return countof(f); 732: } 733: 734: METHOD(plugin_t, destroy, void, 735: private_smp_t *this) 736: { 737: close(this->socket); 738: free(this); 739: } 740: 741: /* 742: * Described in header file 743: */ 744: plugin_t *smp_plugin_create() 745: { 746: struct sockaddr_un unix_addr; 747: private_smp_t *this; 748: mode_t old; 749: 750: if (!lib->caps->check(lib->caps, CAP_CHOWN)) 751: { /* required to chown(2) control socket */ 752: DBG1(DBG_CFG, "smp plugin requires CAP_CHOWN capability"); 753: return NULL; 754: } 755: 756: INIT(this, 757: .public = { 758: .plugin = { 759: .get_name = _get_name, 760: .get_features = _get_features, 761: .destroy = _destroy, 762: }, 763: }, 764: ); 765: 766: /* set up unix socket */ 767: this->socket = socket(AF_UNIX, SOCK_STREAM, 0); 768: if (this->socket == -1) 769: { 770: DBG1(DBG_CFG, "could not create XML socket"); 771: free(this); 772: return NULL; 773: } 774: 775: strlcpy(unix_addr.sun_path, IPSEC_PIDDIR "/charon.xml", 776: sizeof(unix_addr.sun_path)); 777: unix_addr.sun_len = sizeof(unix_addr); 778: unix_addr.sun_family = PF_LOCAL; 779: 780: unlink(unix_addr.sun_path); 781: old = umask(S_IRWXO); 782: if (bind(this->socket, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) 783: { 784: DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno)); 785: close(this->socket); 786: free(this); 787: return NULL; 788: } 789: umask(old); 790: if (chown(unix_addr.sun_path, lib->caps->get_uid(lib->caps), 791: lib->caps->get_gid(lib->caps)) != 0) 792: { 793: DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno)); 794: } 795: 796: if (listen(this->socket, 5) < 0) 797: { 798: DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno)); 799: close(this->socket); 800: free(this); 801: return NULL; 802: } 803: 804: lib->processor->queue_job(lib->processor, 805: (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this, 806: NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); 807: 808: return &this->public.plugin; 809: }