Annotation of embedaddon/strongswan/src/libcharon/plugins/smp/smp.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>