Annotation of embedaddon/strongswan/src/libcharon/plugins/smp/smp.c, revision 1.1.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>