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>