Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_control.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2015-2017 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2014 Martin Willi
                      6:  * Copyright (C) 2014 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "vici_control.h"
                     20: #include "vici_builder.h"
                     21: 
                     22: #include <inttypes.h>
                     23: 
                     24: #include <daemon.h>
                     25: #include <collections/array.h>
                     26: #include <processing/jobs/rekey_ike_sa_job.h>
                     27: #include <processing/jobs/rekey_child_sa_job.h>
                     28: #include <processing/jobs/redirect_job.h>
                     29: 
                     30: typedef struct private_vici_control_t private_vici_control_t;
                     31: 
                     32: /**
                     33:  * Private data of an vici_control_t object.
                     34:  */
                     35: struct private_vici_control_t {
                     36: 
                     37:        /**
                     38:         * Public vici_control_t interface.
                     39:         */
                     40:        vici_control_t public;
                     41: 
                     42:        /**
                     43:         * Dispatcher
                     44:         */
                     45:        vici_dispatcher_t *dispatcher;
                     46: };
                     47: 
                     48: /**
                     49:  * Log callback helper data
                     50:  */
                     51: typedef struct {
                     52:        /** dispatcher to send log messages over */
                     53:        vici_dispatcher_t *dispatcher;
                     54:        /** connection ID to send messages to */
                     55:        u_int id;
                     56:        /** loglevel */
                     57:        level_t level;
                     58:        /** prevent recursive log */
                     59:        u_int recursive;
                     60: } log_info_t;
                     61: 
                     62: /**
                     63:  * Log using vici event messages
                     64:  */
                     65: static bool log_vici(log_info_t *info, debug_t group, level_t level,
                     66:                                         ike_sa_t *ike_sa, char *text)
                     67: {
                     68:        if (level <= info->level)
                     69:        {
                     70:                if (info->recursive++ == 0)
                     71:                {
                     72:                        vici_message_t *message;
                     73:                        vici_builder_t *builder;
                     74: 
                     75:                        builder = vici_builder_create();
                     76:                        builder->add_kv(builder, "group", "%N", debug_names, group);
                     77:                        builder->add_kv(builder, "level", "%d", level);
                     78:                        if (ike_sa)
                     79:                        {
                     80:                                builder->add_kv(builder, "ikesa-name", "%s",
                     81:                                                                ike_sa->get_name(ike_sa));
                     82:                                builder->add_kv(builder, "ikesa-uniqueid", "%u",
                     83:                                                                ike_sa->get_unique_id(ike_sa));
                     84:                        }
                     85:                        builder->add_kv(builder, "msg", "%s", text);
                     86: 
                     87:                        message = builder->finalize(builder);
                     88:                        if (message)
                     89:                        {
                     90:                                info->dispatcher->raise_event(info->dispatcher, "control-log",
                     91:                                                                                          info->id, message);
                     92:                        }
                     93:                }
                     94:                info->recursive--;
                     95:        }
                     96:        return TRUE;
                     97: }
                     98: 
                     99: /**
                    100:  * Send a (error) reply message
                    101:  */
                    102: static vici_message_t* send_reply(private_vici_control_t *this, char *fmt, ...)
                    103: {
                    104:        vici_builder_t *builder;
                    105:        va_list args;
                    106: 
                    107:        builder = vici_builder_create();
                    108:        builder->add_kv(builder, "success", fmt ? "no" : "yes");
                    109:        if (fmt)
                    110:        {
                    111:                va_start(args, fmt);
                    112:                builder->vadd_kv(builder, "errmsg", fmt, args);
                    113:                va_end(args);
                    114:        }
                    115:        return builder->finalize(builder);
                    116: }
                    117: 
                    118: /**
                    119:  * Get the child_cfg having name from peer_cfg
                    120:  */
                    121: static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
                    122: {
                    123:        child_cfg_t *current, *found = NULL;
                    124:        enumerator_t *enumerator;
                    125: 
                    126:        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                    127:        while (enumerator->enumerate(enumerator, &current))
                    128:        {
                    129:                if (streq(current->get_name(current), name))
                    130:                {
                    131:                        found = current;
                    132:                        found->get_ref(found);
                    133:                        break;
                    134:                }
                    135:        }
                    136:        enumerator->destroy(enumerator);
                    137:        return found;
                    138: }
                    139: 
                    140: /**
                    141:  * Find a peer/child config from a config name
                    142:  */
                    143: static child_cfg_t* find_child_cfg(char *name, char *pname, peer_cfg_t **out)
                    144: {
                    145:        enumerator_t *enumerator;
                    146:        peer_cfg_t *peer_cfg;
                    147:        child_cfg_t *child_cfg = NULL;
                    148: 
                    149:        enumerator = charon->backends->create_peer_cfg_enumerator(
                    150:                                                        charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
                    151:        while (enumerator->enumerate(enumerator, &peer_cfg))
                    152:        {
                    153:                if (pname && !streq(pname, peer_cfg->get_name(peer_cfg)))
                    154:                {
                    155:                        continue;
                    156:                }
                    157:                if (!name)
                    158:                {
                    159:                        *out = peer_cfg->get_ref(peer_cfg);
                    160:                        break;
                    161:                }
                    162:                child_cfg = get_child_from_peer(peer_cfg, name);
                    163:                if (child_cfg)
                    164:                {
                    165:                        *out = peer_cfg->get_ref(peer_cfg);
                    166:                        break;
                    167:                }
                    168:        }
                    169:        enumerator->destroy(enumerator);
                    170: 
                    171:        return child_cfg;
                    172: }
                    173: 
                    174: CALLBACK(initiate, vici_message_t*,
                    175:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    176: {
                    177:        peer_cfg_t *peer_cfg = NULL;
                    178:        child_cfg_t *child_cfg;
                    179:        char *child, *ike, *type, *sa;
                    180:        int timeout;
                    181:        bool limits;
                    182:        controller_cb_t log_cb = NULL;
                    183:        log_info_t log = {
                    184:                .dispatcher = this->dispatcher,
                    185:                .id = id,
                    186:        };
                    187: 
                    188:        child = request->get_str(request, NULL, "child");
                    189:        ike = request->get_str(request, NULL, "ike");
                    190:        timeout = request->get_int(request, 0, "timeout");
                    191:        limits = request->get_bool(request, FALSE, "init-limits");
                    192:        log.level = request->get_int(request, 1, "loglevel");
                    193: 
                    194:        if (!child && !ike)
                    195:        {
                    196:                return send_reply(this, "missing configuration name");
                    197:        }
                    198:        if (timeout >= 0)
                    199:        {
                    200:                log_cb = (controller_cb_t)log_vici;
                    201:        }
                    202: 
                    203:        type = child ? "CHILD_SA" : "IKE_SA";
                    204:        sa = child ?: ike;
                    205: 
                    206:        child_cfg = find_child_cfg(child, ike, &peer_cfg);
                    207: 
                    208:        DBG1(DBG_CFG, "vici initiate %s '%s'", type, sa);
                    209:        if (!peer_cfg)
                    210:        {
                    211:                return send_reply(this, "%s config '%s' not found", type, sa);
                    212:        }
                    213:        switch (charon->controller->initiate(charon->controller, peer_cfg,
                    214:                                                                        child_cfg, log_cb, &log, timeout, limits))
                    215:        {
                    216:                case SUCCESS:
                    217:                        return send_reply(this, NULL);
                    218:                case OUT_OF_RES:
                    219:                        return send_reply(this, "%s '%s' not established after %dms", type,
                    220:                                                          sa, timeout);
                    221:                case INVALID_STATE:
                    222:                        return send_reply(this, "establishing %s '%s' not possible at the "
                    223:                                                          "moment due to limits", type, sa);
                    224:                case FAILED:
                    225:                default:
                    226:                        return send_reply(this, "establishing %s '%s' failed", type, sa);
                    227:        }
                    228: }
                    229: 
                    230: CALLBACK(terminate, vici_message_t*,
                    231:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    232: {
                    233:        enumerator_t *enumerator, *isas, *csas;
                    234:        char *child, *ike, *errmsg = NULL;
                    235:        u_int child_id, ike_id, current, *del, done = 0;
                    236:        bool force;
                    237:        int timeout;
                    238:        ike_sa_t *ike_sa;
                    239:        child_sa_t *child_sa;
                    240:        array_t *ids;
                    241:        vici_builder_t *builder;
                    242:        controller_cb_t log_cb = NULL;
                    243:        log_info_t log = {
                    244:                .dispatcher = this->dispatcher,
                    245:                .id = id,
                    246:        };
                    247: 
                    248:        child = request->get_str(request, NULL, "child");
                    249:        ike = request->get_str(request, NULL, "ike");
                    250:        child_id = request->get_int(request, 0, "child-id");
                    251:        ike_id = request->get_int(request, 0, "ike-id");
                    252:        force = request->get_bool(request, FALSE, "force");
                    253:        timeout = request->get_int(request, 0, "timeout");
                    254:        log.level = request->get_int(request, 1, "loglevel");
                    255: 
                    256:        if (!child && !ike && !ike_id && !child_id)
                    257:        {
                    258:                return send_reply(this, "missing terminate selector");
                    259:        }
                    260: 
                    261:        if (ike_id)
                    262:        {
                    263:                DBG1(DBG_CFG, "vici terminate IKE_SA #%d", ike_id);
                    264:        }
                    265:        if (child_id)
                    266:        {
                    267:                DBG1(DBG_CFG, "vici terminate CHILD_SA #%d", child_id);
                    268:        }
                    269:        if (ike)
                    270:        {
                    271:                DBG1(DBG_CFG, "vici terminate IKE_SA '%s'", ike);
                    272:        }
                    273:        if (child)
                    274:        {
                    275:                DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
                    276:        }
                    277: 
                    278:        if (timeout >= 0)
                    279:        {
                    280:                log_cb = (controller_cb_t)log_vici;
                    281:        }
                    282: 
                    283:        ids = array_create(sizeof(u_int), 0);
                    284: 
                    285:        isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
                    286:        while (isas->enumerate(isas, &ike_sa))
                    287:        {
                    288:                if (child || child_id)
                    289:                {
                    290:                        if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
                    291:                        {
                    292:                                continue;
                    293:                        }
                    294:                        if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
                    295:                        {
                    296:                                continue;
                    297:                        }
                    298:                        csas = ike_sa->create_child_sa_enumerator(ike_sa);
                    299:                        while (csas->enumerate(csas, &child_sa))
                    300:                        {
                    301:                                if (child && !streq(child, child_sa->get_name(child_sa)))
                    302:                                {
                    303:                                        continue;
                    304:                                }
                    305:                                if (child_id && child_sa->get_unique_id(child_sa) != child_id)
                    306:                                {
                    307:                                        continue;
                    308:                                }
                    309:                                current = child_sa->get_unique_id(child_sa);
                    310:                                array_insert(ids, ARRAY_TAIL, &current);
                    311:                        }
                    312:                        csas->destroy(csas);
                    313:                }
                    314:                else if (ike && streq(ike, ike_sa->get_name(ike_sa)))
                    315:                {
                    316:                        current = ike_sa->get_unique_id(ike_sa);
                    317:                        array_insert(ids, ARRAY_TAIL, &current);
                    318:                }
                    319:                else if (ike_id && ike_id == ike_sa->get_unique_id(ike_sa))
                    320:                {
                    321:                        array_insert(ids, ARRAY_TAIL, &ike_id);
                    322:                }
                    323:        }
                    324:        isas->destroy(isas);
                    325: 
                    326:        enumerator = array_create_enumerator(ids);
                    327:        while (enumerator->enumerate(enumerator, &del))
                    328:        {
                    329:                if (child || child_id)
                    330:                {
                    331:                        if (charon->controller->terminate_child(charon->controller, *del,
                    332:                                                                                        log_cb, &log, timeout) == SUCCESS)
                    333:                        {
                    334:                                done++;
                    335:                        }
                    336:                }
                    337:                else
                    338:                {
                    339:                        if (charon->controller->terminate_ike(charon->controller, *del, force,
                    340:                                                                                        log_cb, &log, timeout) == SUCCESS)
                    341:                        {
                    342:                                done++;
                    343:                        }
                    344:                }
                    345:        }
                    346:        enumerator->destroy(enumerator);
                    347: 
                    348:        builder = vici_builder_create();
                    349:        if (array_count(ids) == 0)
                    350:        {
                    351:                errmsg = "no matching SAs to terminate found";
                    352:        }
                    353:        else if (done < array_count(ids))
                    354:        {
                    355:                if (array_count(ids) == 1)
                    356:                {
                    357:                        errmsg = "terminating SA failed";
                    358:                }
                    359:                else
                    360:                {
                    361:                        errmsg = "not all matching SAs could be terminated";
                    362:                }
                    363:        }
                    364:        builder->add_kv(builder, "success", errmsg ? "no" : "yes");
                    365:        builder->add_kv(builder, "matches", "%u", array_count(ids));
                    366:        builder->add_kv(builder, "terminated", "%u", done);
                    367:        if (errmsg)
                    368:        {
                    369:                builder->add_kv(builder, "errmsg", "%s", errmsg);
                    370:        }
                    371:        array_destroy(ids);
                    372:        return builder->finalize(builder);
                    373: }
                    374: 
                    375: CALLBACK(rekey, vici_message_t*,
                    376:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    377: {
                    378:        enumerator_t *isas, *csas;
                    379:        char *child, *ike, *errmsg = NULL;
                    380:        u_int child_id, ike_id, found = 0;
                    381:        ike_sa_t *ike_sa;
                    382:        child_sa_t *child_sa;
                    383:        vici_builder_t *builder;
                    384:        bool reauth;
                    385: 
                    386:        child = request->get_str(request, NULL, "child");
                    387:        ike = request->get_str(request, NULL, "ike");
                    388:        child_id = request->get_int(request, 0, "child-id");
                    389:        ike_id = request->get_int(request, 0, "ike-id");
                    390:        reauth = request->get_bool(request, FALSE, "reauth");
                    391: 
                    392:        if (!child && !ike && !ike_id && !child_id)
                    393:        {
                    394:                return send_reply(this, "missing rekey selector");
                    395:        }
                    396: 
                    397:        if (ike_id)
                    398:        {
                    399:                DBG1(DBG_CFG, "vici rekey IKE_SA #%d", ike_id);
                    400:        }
                    401:        if (child_id)
                    402:        {
                    403:                DBG1(DBG_CFG, "vici rekey CHILD_SA #%d", child_id);
                    404:        }
                    405:        if (ike)
                    406:        {
                    407:                DBG1(DBG_CFG, "vici rekey IKE_SA '%s'", ike);
                    408:        }
                    409:        if (child)
                    410:        {
                    411:                DBG1(DBG_CFG, "vici rekey CHILD_SA '%s'", child);
                    412:        }
                    413: 
                    414:        isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
                    415:        while (isas->enumerate(isas, &ike_sa))
                    416:        {
                    417:                if (child || child_id)
                    418:                {
                    419:                        if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
                    420:                        {
                    421:                                continue;
                    422:                        }
                    423:                        if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
                    424:                        {
                    425:                                continue;
                    426:                        }
                    427:                        csas = ike_sa->create_child_sa_enumerator(ike_sa);
                    428:                        while (csas->enumerate(csas, &child_sa))
                    429:                        {
                    430:                                if (child && !streq(child, child_sa->get_name(child_sa)))
                    431:                                {
                    432:                                        continue;
                    433:                                }
                    434:                                if (child_id && child_sa->get_unique_id(child_sa) != child_id)
                    435:                                {
                    436:                                        continue;
                    437:                                }
                    438:                                lib->processor->queue_job(lib->processor,
                    439:                                                (job_t*)rekey_child_sa_job_create(
                    440:                                                                                        child_sa->get_protocol(child_sa),
                    441:                                                                                        child_sa->get_spi(child_sa, TRUE),
                    442:                                                                                        ike_sa->get_my_host(ike_sa)));
                    443:                                found++;
                    444:                        }
                    445:                        csas->destroy(csas);
                    446:                }
                    447:                else if ((ike && streq(ike, ike_sa->get_name(ike_sa))) ||
                    448:                                 (ike_id && ike_id == ike_sa->get_unique_id(ike_sa)))
                    449:                {
                    450:                        lib->processor->queue_job(lib->processor,
                    451:                                (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), reauth));
                    452:                        found++;
                    453:                }
                    454:        }
                    455:        isas->destroy(isas);
                    456: 
                    457:        builder = vici_builder_create();
                    458:        if (!found)
                    459:        {
                    460:                errmsg = "no matching SAs to rekey found";
                    461:        }
                    462:        builder->add_kv(builder, "success", errmsg ? "no" : "yes");
                    463:        builder->add_kv(builder, "matches", "%u", found);
                    464:        if (errmsg)
                    465:        {
                    466:                builder->add_kv(builder, "errmsg", "%s", errmsg);
                    467:        }
                    468:        return builder->finalize(builder);
                    469: }
                    470: 
                    471: /**
                    472:  * Parse a peer-ip specified, which can be a subnet in CIDR notation, a range
                    473:  * or a single IP address.
                    474:  */
                    475: static traffic_selector_t *parse_peer_ip(char *ip)
                    476: {
                    477:        traffic_selector_t *ts;
                    478:        host_t *from, *to;
                    479:        ts_type_t type;
                    480: 
                    481:        if (host_create_from_range(ip, &from, &to))
                    482:        {
                    483:                if (to->get_family(to) == AF_INET)
                    484:                {
                    485:                        type = TS_IPV4_ADDR_RANGE;
                    486:                }
                    487:                else
                    488:                {
                    489:                        type = TS_IPV6_ADDR_RANGE;
                    490:                }
                    491:                ts = traffic_selector_create_from_bytes(0, type,
                    492:                                                                                                from->get_address(from), 0,
                    493:                                                                                                to->get_address(to), 0xFFFF);
                    494:                from->destroy(from);
                    495:                to->destroy(to);
                    496:                return ts;
                    497:        }
                    498:        return traffic_selector_create_from_cidr(ip, 0, 0, 0xFFFF);
                    499: }
                    500: 
                    501: CALLBACK(redirect, vici_message_t*,
                    502:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    503: {
                    504:        enumerator_t *sas;
                    505:        char *ike, *peer_ip, *peer_id, *gw, *errmsg = NULL;
                    506:        u_int ike_id, current, found = 0;
                    507:        identification_t *gateway, *identity = NULL, *other_id;
                    508:        traffic_selector_t *ts = NULL;
                    509:        ike_sa_t *ike_sa;
                    510:        vici_builder_t *builder;
                    511: 
                    512:        ike = request->get_str(request, NULL, "ike");
                    513:        ike_id = request->get_int(request, 0, "ike-id");
                    514:        peer_ip = request->get_str(request, NULL, "peer-ip");
                    515:        peer_id = request->get_str(request, NULL, "peer-id");
                    516:        gw = request->get_str(request, NULL, "gateway");
                    517: 
                    518:        if (!gw || !(gateway = identification_create_from_string(gw)))
                    519:        {
                    520:                return send_reply(this, "missing target gateway");
                    521:        }
                    522:        switch (gateway->get_type(gateway))
                    523:        {
                    524:                case ID_IPV4_ADDR:
                    525:                case ID_IPV6_ADDR:
                    526:                case ID_FQDN:
                    527:                        break;
                    528:                default:
                    529:                        return send_reply(this, "unsupported gateway identity");
                    530:        }
                    531:        if (peer_ip)
                    532:        {
                    533:                ts = parse_peer_ip(peer_ip);
                    534:                if (!ts)
                    535:                {
                    536:                        return send_reply(this, "invalid peer IP selector");
                    537:                }
                    538:                DBG1(DBG_CFG, "vici redirect IKE_SAs with src %R to %Y", ts,
                    539:                         gateway);
                    540:        }
                    541:        if (peer_id)
                    542:        {
                    543:                identity = identification_create_from_string(peer_id);
                    544:                if (!identity)
                    545:                {
                    546:                        DESTROY_IF(ts);
                    547:                        return send_reply(this, "invalid peer identity selector");
                    548:                }
                    549:                DBG1(DBG_CFG, "vici redirect IKE_SAs with ID '%Y' to %Y", identity,
                    550:                         gateway);
                    551:        }
                    552:        if (ike_id)
                    553:        {
                    554:                DBG1(DBG_CFG, "vici redirect IKE_SA #%d to '%Y'", ike_id, gateway);
                    555:        }
                    556:        if (ike)
                    557:        {
                    558:                DBG1(DBG_CFG, "vici redirect IKE_SA '%s' to '%Y'", ike, gateway);
                    559:        }
                    560:        if (!peer_ip && !peer_id && !ike && !ike_id)
                    561:        {
                    562:                return send_reply(this, "missing redirect selector");
                    563:        }
                    564: 
                    565:        sas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
                    566:        while (sas->enumerate(sas, &ike_sa))
                    567:        {
                    568:                if (ike_sa->get_version(ike_sa) != IKEV2)
                    569:                {
                    570:                        continue;
                    571:                }
                    572:                current = ike_sa->get_unique_id(ike_sa);
                    573:                if (ike_id && ike_id != current)
                    574:                {
                    575:                        continue;
                    576:                }
                    577:                if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
                    578:                {
                    579:                        continue;
                    580:                }
                    581:                if (ts && !ts->includes(ts, ike_sa->get_other_host(ike_sa)))
                    582:                {
                    583:                        continue;
                    584:                }
                    585:                if (identity)
                    586:                {
                    587:                        other_id = ike_sa->get_other_eap_id(ike_sa);
                    588:                        if (!other_id->matches(other_id, identity))
                    589:                        {
                    590:                                continue;
                    591:                        }
                    592:                }
                    593:                lib->processor->queue_job(lib->processor,
                    594:                                (job_t*)redirect_job_create(ike_sa->get_id(ike_sa), gateway));
                    595:                found++;
                    596:        }
                    597:        sas->destroy(sas);
                    598: 
                    599:        builder = vici_builder_create();
                    600:        if (!found)
                    601:        {
                    602:                errmsg = "no matching SAs to redirect found";
                    603:        }
                    604:        builder->add_kv(builder, "success", errmsg ? "no" : "yes");
                    605:        builder->add_kv(builder, "matches", "%u", found);
                    606:        if (errmsg)
                    607:        {
                    608:                builder->add_kv(builder, "errmsg", "%s", errmsg);
                    609:        }
                    610:        gateway->destroy(gateway);
                    611:        DESTROY_IF(identity);
                    612:        DESTROY_IF(ts);
                    613:        return builder->finalize(builder);
                    614: }
                    615: 
                    616: CALLBACK(install, vici_message_t*,
                    617:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    618: {
                    619:        child_cfg_t *child_cfg = NULL;
                    620:        peer_cfg_t *peer_cfg;
                    621:        char *child, *ike;
                    622:        bool ok;
                    623: 
                    624:        child = request->get_str(request, NULL, "child");
                    625:        ike = request->get_str(request, NULL, "ike");
                    626:        if (!child)
                    627:        {
                    628:                return send_reply(this, "missing configuration name");
                    629:        }
                    630: 
                    631:        DBG1(DBG_CFG, "vici install '%s'", child);
                    632: 
                    633:        child_cfg = find_child_cfg(child, ike, &peer_cfg);
                    634:        if (!child_cfg)
                    635:        {
                    636:                return send_reply(this, "configuration name not found");
                    637:        }
                    638:        switch (child_cfg->get_mode(child_cfg))
                    639:        {
                    640:                case MODE_PASS:
                    641:                case MODE_DROP:
                    642:                        ok = charon->shunts->install(charon->shunts,
                    643:                                                                        peer_cfg->get_name(peer_cfg), child_cfg);
                    644:                        break;
                    645:                default:
                    646:                        ok = charon->traps->install(charon->traps, peer_cfg, child_cfg);
                    647:                        break;
                    648:        }
                    649:        peer_cfg->destroy(peer_cfg);
                    650:        child_cfg->destroy(child_cfg);
                    651: 
                    652:        return send_reply(this, ok ? NULL : "installing policy '%s' failed", child);
                    653: }
                    654: 
                    655: CALLBACK(uninstall, vici_message_t*,
                    656:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    657: {
                    658:        char *child, *ike;
                    659: 
                    660:        child = request->get_str(request, NULL, "child");
                    661:        ike = request->get_str(request, NULL, "ike");
                    662:        if (!child)
                    663:        {
                    664:                return send_reply(this, "missing configuration name");
                    665:        }
                    666: 
                    667:        DBG1(DBG_CFG, "vici uninstall '%s'", child);
                    668: 
                    669:        if (charon->shunts->uninstall(charon->shunts, ike, child))
                    670:        {
                    671:                return send_reply(this, NULL);
                    672:        }
                    673:        else if (charon->traps->uninstall(charon->traps, ike, child))
                    674:        {
                    675:                return send_reply(this, NULL);
                    676:        }
                    677:        return send_reply(this, "policy '%s' not found", child);
                    678: }
                    679: 
                    680: CALLBACK(reload_settings, vici_message_t*,
                    681:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
                    682: {
                    683:        if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
                    684:        {
                    685:                charon->load_loggers(charon);
                    686:                lib->plugins->reload(lib->plugins, NULL);
                    687:                return send_reply(this, NULL);
                    688:        }
                    689:        return send_reply(this, "reloading '%s' failed", lib->conf);
                    690: }
                    691: 
                    692: static void manage_command(private_vici_control_t *this,
                    693:                                                   char *name, vici_command_cb_t cb, bool reg)
                    694: {
                    695:        this->dispatcher->manage_command(this->dispatcher, name,
                    696:                                                                         reg ? cb : NULL, this);
                    697: }
                    698: 
                    699: /**
                    700:  * (Un-)register dispatcher functions
                    701:  */
                    702: static void manage_commands(private_vici_control_t *this, bool reg)
                    703: {
                    704:        manage_command(this, "initiate", initiate, reg);
                    705:        manage_command(this, "terminate", terminate, reg);
                    706:        manage_command(this, "rekey", rekey, reg);
                    707:        manage_command(this, "redirect", redirect, reg);
                    708:        manage_command(this, "install", install, reg);
                    709:        manage_command(this, "uninstall", uninstall, reg);
                    710:        manage_command(this, "reload-settings", reload_settings, reg);
                    711:        this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
                    712: }
                    713: 
                    714: METHOD(vici_control_t, destroy, void,
                    715:        private_vici_control_t *this)
                    716: {
                    717:        manage_commands(this, FALSE);
                    718:        free(this);
                    719: }
                    720: 
                    721: /**
                    722:  * See header
                    723:  */
                    724: vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher)
                    725: {
                    726:        private_vici_control_t *this;
                    727: 
                    728:        INIT(this,
                    729:                .public = {
                    730:                        .destroy = _destroy,
                    731:                },
                    732:                .dispatcher = dispatcher,
                    733:        );
                    734: 
                    735:        manage_commands(this, TRUE);
                    736: 
                    737:        return &this->public;
                    738: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>