Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_control.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013-2015 Tobias Brunner
                      3:  * Copyright (C) 2008 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "stroke_control.h"
                     18: 
                     19: #include <daemon.h>
                     20: 
                     21: #include <processing/jobs/delete_ike_sa_job.h>
                     22: #include <processing/jobs/rekey_ike_sa_job.h>
                     23: #include <processing/jobs/rekey_child_sa_job.h>
                     24: 
                     25: typedef struct private_stroke_control_t private_stroke_control_t;
                     26: 
                     27: /**
                     28:  * private data of stroke_control
                     29:  */
                     30: struct private_stroke_control_t {
                     31: 
                     32:        /**
                     33:         * public functions
                     34:         */
                     35:        stroke_control_t public;
                     36: 
                     37:        /**
                     38:         * Timeout for stroke commands, im ms
                     39:         */
                     40:        u_int timeout;
                     41: };
                     42: 
                     43: 
                     44: typedef struct stroke_log_info_t stroke_log_info_t;
                     45: 
                     46: /**
                     47:  * helper struct to say what and where to log when using controller callback
                     48:  */
                     49: struct stroke_log_info_t {
                     50: 
                     51:        /**
                     52:         * level to log up to
                     53:         */
                     54:        level_t level;
                     55: 
                     56:        /**
                     57:         * where to write log
                     58:         */
                     59:        FILE* out;
                     60: };
                     61: 
                     62: /**
                     63:  * logging to the stroke interface
                     64:  */
                     65: static bool stroke_log(stroke_log_info_t *info, debug_t group, level_t level,
                     66:                                           ike_sa_t *ike_sa, char *message)
                     67: {
                     68:        if (level <= info->level)
                     69:        {
                     70:                if (fprintf(info->out, "%s", message) < 0 ||
                     71:                        fprintf(info->out, "\n") < 0 ||
                     72:                        fflush(info->out) != 0)
                     73:                {
                     74:                        return FALSE;
                     75:                }
                     76:        }
                     77:        return TRUE;
                     78: }
                     79: 
                     80: /**
                     81:  * get the child_cfg with the same name as the peer cfg
                     82:  */
                     83: static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
                     84: {
                     85:        child_cfg_t *current, *found = NULL;
                     86:        enumerator_t *enumerator;
                     87: 
                     88:        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                     89:        while (enumerator->enumerate(enumerator, &current))
                     90:        {
                     91:                if (streq(current->get_name(current), name))
                     92:                {
                     93:                        found = current;
                     94:                        found->get_ref(found);
                     95:                        break;
                     96:                }
                     97:        }
                     98:        enumerator->destroy(enumerator);
                     99:        return found;
                    100: }
                    101: 
                    102: /**
                    103:  * call the charon controller to initiate the connection
                    104:  */
                    105: static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg,
                    106:                                                        child_cfg_t *child_cfg, stroke_msg_t *msg, FILE *out)
                    107: {
                    108:        if (msg->output_verbosity < 0)
                    109:        {
                    110:                charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
                    111:                                                                         NULL, NULL, 0, FALSE);
                    112:        }
                    113:        else
                    114:        {
                    115:                stroke_log_info_t info = { msg->output_verbosity, out };
                    116:                status_t status;
                    117: 
                    118:                status = charon->controller->initiate(charon->controller,
                    119:                                                        peer_cfg, child_cfg, (controller_cb_t)stroke_log,
                    120:                                                        &info, this->timeout, FALSE);
                    121:                switch (status)
                    122:                {
                    123:                        case SUCCESS:
                    124:                                fprintf(out, "connection '%s' established successfully\n",
                    125:                                                msg->initiate.name);
                    126:                                break;
                    127:                        case OUT_OF_RES:
                    128:                                fprintf(out, "connection '%s' not established after %dms, "
                    129:                                                "detaching\n", msg->initiate.name, this->timeout);
                    130:                                break;
                    131:                        default:
                    132:                        case FAILED:
                    133:                                fprintf(out, "establishing connection '%s' failed\n",
                    134:                                                msg->initiate.name);
                    135:                                break;
                    136:                }
                    137:        }
                    138: }
                    139: 
                    140: METHOD(stroke_control_t, initiate, void,
                    141:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    142: {
                    143:        child_cfg_t *child_cfg = NULL;
                    144:        peer_cfg_t *peer_cfg;
                    145:        enumerator_t *enumerator;
                    146:        bool empty = TRUE;
                    147: 
                    148:        peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
                    149:                                                                                                          msg->initiate.name);
                    150:        if (peer_cfg)
                    151:        {
                    152:                child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
                    153:                if (child_cfg == NULL)
                    154:                {
                    155:                        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                    156:                        while (enumerator->enumerate(enumerator, &child_cfg))
                    157:                        {
                    158:                                empty = FALSE;
                    159:                                charon_initiate(this, peer_cfg->get_ref(peer_cfg),
                    160:                                                                child_cfg->get_ref(child_cfg), msg, out);
                    161:                        }
                    162:                        enumerator->destroy(enumerator);
                    163: 
                    164:                        if (empty)
                    165:                        {
                    166:                                DBG1(DBG_CFG, "no child config named '%s'", msg->initiate.name);
                    167:                                fprintf(out, "no child config named '%s'\n", msg->initiate.name);
                    168:                        }
                    169:                        peer_cfg->destroy(peer_cfg);
                    170:                        return;
                    171:                }
                    172:        }
                    173:        else
                    174:        {
                    175:                enumerator = charon->backends->create_peer_cfg_enumerator(
                    176:                                                        charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
                    177:                while (enumerator->enumerate(enumerator, &peer_cfg))
                    178:                {
                    179:                        child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
                    180:                        if (child_cfg)
                    181:                        {
                    182:                                peer_cfg->get_ref(peer_cfg);
                    183:                                break;
                    184:                        }
                    185:                }
                    186:                enumerator->destroy(enumerator);
                    187: 
                    188:                if (child_cfg == NULL)
                    189:                {
                    190:                        DBG1(DBG_CFG, "no config named '%s'", msg->initiate.name);
                    191:                        fprintf(out, "no config named '%s'\n", msg->initiate.name);
                    192:                        return;
                    193:                }
                    194:        }
                    195:        charon_initiate(this, peer_cfg, child_cfg, msg, out);
                    196: }
                    197: 
                    198: /**
                    199:  * Parse a terminate/rekey specifier
                    200:  */
                    201: static bool parse_specifier(char *string, uint32_t *id,
                    202:                                                        char **name, bool *child, bool *all)
                    203: {
                    204:        int len;
                    205:        char *pos = NULL;
                    206: 
                    207:        *id = 0;
                    208:        *name = NULL;
                    209:        *all = FALSE;
                    210: 
                    211:        len = strlen(string);
                    212:        if (len < 1)
                    213:        {
                    214:                return FALSE;
                    215:        }
                    216:        switch (string[len-1])
                    217:        {
                    218:                case '}':
                    219:                        *child = TRUE;
                    220:                        pos = strchr(string, '{');
                    221:                        break;
                    222:                case ']':
                    223:                        *child = FALSE;
                    224:                        pos = strchr(string, '[');
                    225:                        break;
                    226:                default:
                    227:                        *name = string;
                    228:                        *child = FALSE;
                    229:                        break;
                    230:        }
                    231: 
                    232:        if (*name)
                    233:        {
                    234:                /* is a single name */
                    235:        }
                    236:        else if (pos == string + len - 2)
                    237:        {       /* is name[] or name{} */
                    238:                string[len-2] = '\0';
                    239:                *name = string;
                    240:        }
                    241:        else
                    242:        {
                    243:                if (!pos)
                    244:                {
                    245:                        return FALSE;
                    246:                }
                    247:                if (*(pos + 1) == '*')
                    248:                {       /* is name[*] */
                    249:                        *all = TRUE;
                    250:                        *pos = '\0';
                    251:                        *name = string;
                    252:                }
                    253:                else
                    254:                {       /* is name[123] or name{23} */
                    255:                        *id = atoi(pos + 1);
                    256:                        if (*id == 0)
                    257:                        {
                    258:                                return FALSE;
                    259:                        }
                    260:                }
                    261:        }
                    262:        return TRUE;
                    263: }
                    264: 
                    265: /**
                    266:  * Report the result of a terminate() call to console
                    267:  */
                    268: static void report_terminate_status(private_stroke_control_t *this,
                    269:                                                status_t status, FILE *out, uint32_t id, bool child)
                    270: {
                    271:        char *prefix, *postfix;
                    272: 
                    273:        if (child)
                    274:        {
                    275:                prefix = "CHILD_SA {";
                    276:                postfix = "}";
                    277:        }
                    278:        else
                    279:        {
                    280:                prefix = "IKE_SA [";
                    281:                postfix = "]";
                    282:        }
                    283: 
                    284:        switch (status)
                    285:        {
                    286:                case SUCCESS:
                    287:                        fprintf(out, "%s%d%s closed successfully\n", prefix, id, postfix);
                    288:                        break;
                    289:                case OUT_OF_RES:
                    290:                        fprintf(out, "%s%d%s not closed after %dms, detaching\n",
                    291:                                        prefix, id, postfix, this->timeout);
                    292:                        break;
                    293:                default:
                    294:                case FAILED:
                    295:                        fprintf(out, "closing %s%d%s failed\n", prefix, id, postfix);
                    296:                        break;
                    297:        }
                    298: }
                    299: 
                    300: /**
                    301:  * Call the charon controller to terminate a CHILD_SA
                    302:  */
                    303: static void charon_terminate(private_stroke_control_t *this, uint32_t id,
                    304:                                                         stroke_msg_t *msg, FILE *out, bool child)
                    305: {
                    306:        if (msg->output_verbosity >= 0)
                    307:        {
                    308:                stroke_log_info_t info = { msg->output_verbosity, out };
                    309:                status_t status;
                    310: 
                    311:                if (child)
                    312:                {
                    313:                        status = charon->controller->terminate_child(charon->controller, id,
                    314:                                                        (controller_cb_t)stroke_log, &info, this->timeout);
                    315:                }
                    316:                else
                    317:                {
                    318:                        status = charon->controller->terminate_ike(charon->controller, id,
                    319:                                                        FALSE, (controller_cb_t)stroke_log, &info,
                    320:                                                        this->timeout);
                    321:                }
                    322:                report_terminate_status(this, status, out, id, child);
                    323:        }
                    324:        else if (child)
                    325:        {
                    326:                charon->controller->terminate_child(charon->controller, id,
                    327:                                                                                    NULL, NULL, 0);
                    328:        }
                    329:        else
                    330:        {
                    331:                charon->controller->terminate_ike(charon->controller, id, FALSE,
                    332:                                                                                  NULL, NULL, 0);
                    333:        }
                    334: }
                    335: 
                    336: METHOD(stroke_control_t, terminate, void,
                    337:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    338: {
                    339:        char *name;
                    340:        uint32_t id;
                    341:        bool child, all;
                    342:        ike_sa_t *ike_sa;
                    343:        enumerator_t *enumerator;
                    344:        linked_list_t *ike_list, *child_list;
                    345:        uintptr_t del;
                    346: 
                    347:        if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
                    348:        {
                    349:                DBG1(DBG_CFG, "error parsing specifier string");
                    350:                return;
                    351:        }
                    352: 
                    353:        if (id)
                    354:        {
                    355:                return charon_terminate(this, id, msg, out, child);
                    356:        }
                    357: 
                    358:        ike_list = linked_list_create();
                    359:        child_list = linked_list_create();
                    360:        enumerator = charon->controller->create_ike_sa_enumerator(
                    361:                                                                                                        charon->controller, TRUE);
                    362:        while (enumerator->enumerate(enumerator, &ike_sa))
                    363:        {
                    364:                child_sa_t *child_sa;
                    365:                enumerator_t *children;
                    366: 
                    367:                if (child)
                    368:                {
                    369:                        children = ike_sa->create_child_sa_enumerator(ike_sa);
                    370:                        while (children->enumerate(children, (void**)&child_sa))
                    371:                        {
                    372:                                if (streq(name, child_sa->get_name(child_sa)))
                    373:                                {
                    374:                                        child_list->insert_last(child_list,
                    375:                                                        (void*)(uintptr_t)child_sa->get_unique_id(child_sa));
                    376:                                        if (!all)
                    377:                                        {
                    378:                                                break;
                    379:                                        }
                    380:                                }
                    381:                        }
                    382:                        children->destroy(children);
                    383:                        if (child_list->get_count(child_list) && !all)
                    384:                        {
                    385:                                break;
                    386:                        }
                    387:                }
                    388:                else if (streq(name, ike_sa->get_name(ike_sa)))
                    389:                {
                    390:                        ike_list->insert_last(ike_list,
                    391:                                                (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa));
                    392:                        if (!all)
                    393:                        {
                    394:                                break;
                    395:                        }
                    396:                }
                    397:        }
                    398:        enumerator->destroy(enumerator);
                    399: 
                    400:        enumerator = child_list->create_enumerator(child_list);
                    401:        while (enumerator->enumerate(enumerator, &del))
                    402:        {
                    403:                charon_terminate(this, del, msg, out, TRUE);
                    404:        }
                    405:        enumerator->destroy(enumerator);
                    406: 
                    407:        enumerator = ike_list->create_enumerator(ike_list);
                    408:        while (enumerator->enumerate(enumerator, &del))
                    409:        {
                    410:                charon_terminate(this, del, msg, out, FALSE);
                    411:        }
                    412:        enumerator->destroy(enumerator);
                    413: 
                    414:        if (child_list->get_count(child_list) == 0 &&
                    415:                ike_list->get_count(ike_list) == 0)
                    416:        {
                    417:                DBG1(DBG_CFG, "no %s_SA named '%s' found",
                    418:                         child ? "CHILD" : "IKE", name);
                    419:        }
                    420:        ike_list->destroy(ike_list);
                    421:        child_list->destroy(child_list);
                    422: }
                    423: 
                    424: METHOD(stroke_control_t, rekey, void,
                    425:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    426: {
                    427:        char *name;
                    428:        uint32_t id;
                    429:        bool child, all, finished = FALSE;
                    430:        ike_sa_t *ike_sa;
                    431:        enumerator_t *enumerator;
                    432: 
                    433:        if (!parse_specifier(msg->terminate.name, &id, &name, &child, &all))
                    434:        {
                    435:                DBG1(DBG_CFG, "error parsing specifier string");
                    436:                return;
                    437:        }
                    438:        enumerator = charon->controller->create_ike_sa_enumerator(
                    439:                                                                                                        charon->controller, TRUE);
                    440:        while (enumerator->enumerate(enumerator, &ike_sa))
                    441:        {
                    442:                child_sa_t *child_sa;
                    443:                enumerator_t *children;
                    444: 
                    445:                if (child)
                    446:                {
                    447:                        children = ike_sa->create_child_sa_enumerator(ike_sa);
                    448:                        while (children->enumerate(children, (void**)&child_sa))
                    449:                        {
                    450:                                if ((name && streq(name, child_sa->get_name(child_sa))) ||
                    451:                                        (id && id == child_sa->get_unique_id(child_sa)))
                    452:                                {
                    453:                                        lib->processor->queue_job(lib->processor,
                    454:                                                (job_t*)rekey_child_sa_job_create(
                    455:                                                                child_sa->get_protocol(child_sa),
                    456:                                                                child_sa->get_spi(child_sa, TRUE),
                    457:                                                                ike_sa->get_my_host(ike_sa)));
                    458:                                        if (!all)
                    459:                                        {
                    460:                                                finished = TRUE;
                    461:                                                break;
                    462:                                        }
                    463:                                }
                    464:                        }
                    465:                        children->destroy(children);
                    466:                }
                    467:                else if ((name && streq(name, ike_sa->get_name(ike_sa))) ||
                    468:                                 (id && id == ike_sa->get_unique_id(ike_sa)))
                    469:                {
                    470:                        lib->processor->queue_job(lib->processor,
                    471:                                (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE));
                    472:                        if (!all)
                    473:                        {
                    474:                                finished = TRUE;
                    475:                        }
                    476:                }
                    477:                if (finished)
                    478:                {
                    479:                        break;
                    480:                }
                    481:        }
                    482:        enumerator->destroy(enumerator);
                    483: }
                    484: 
                    485: METHOD(stroke_control_t, terminate_srcip, void,
                    486:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    487: {
                    488:        enumerator_t *enumerator, *vips;
                    489:        ike_sa_t *ike_sa;
                    490:        host_t *start = NULL, *end = NULL, *vip;
                    491:        chunk_t chunk_start, chunk_end = chunk_empty, chunk;
                    492: 
                    493:        if (msg->terminate_srcip.start)
                    494:        {
                    495:                start = host_create_from_string(msg->terminate_srcip.start, 0);
                    496:        }
                    497:        if (!start)
                    498:        {
                    499:                DBG1(DBG_CFG, "invalid start address: %s", msg->terminate_srcip.start);
                    500:                return;
                    501:        }
                    502:        chunk_start = start->get_address(start);
                    503:        if (msg->terminate_srcip.end)
                    504:        {
                    505:                end = host_create_from_string(msg->terminate_srcip.end, 0);
                    506:                if (!end)
                    507:                {
                    508:                        DBG1(DBG_CFG, "invalid end address: %s", msg->terminate_srcip.end);
                    509:                        start->destroy(start);
                    510:                        return;
                    511:                }
                    512:                chunk_end = end->get_address(end);
                    513:        }
                    514: 
                    515:        enumerator = charon->controller->create_ike_sa_enumerator(
                    516:                                                                                                        charon->controller, TRUE);
                    517:        while (enumerator->enumerate(enumerator, &ike_sa))
                    518:        {
                    519:                bool match = FALSE;
                    520: 
                    521:                vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
                    522:                while (vips->enumerate(vips, &vip))
                    523:                {
                    524:                        if (!end)
                    525:                        {
                    526:                                if (vip->ip_equals(vip, start))
                    527:                                {
                    528:                                        match = TRUE;
                    529:                                        break;
                    530:                                }
                    531:                        }
                    532:                        else
                    533:                        {
                    534:                                chunk = vip->get_address(vip);
                    535:                                if (chunk.len == chunk_start.len &&
                    536:                                        chunk.len == chunk_end.len &&
                    537:                                        memcmp(chunk.ptr, chunk_start.ptr, chunk.len) >= 0 &&
                    538:                                        memcmp(chunk.ptr, chunk_end.ptr, chunk.len) <= 0)
                    539:                                {
                    540:                                        match = TRUE;
                    541:                                        break;
                    542:                                }
                    543:                        }
                    544:                }
                    545:                vips->destroy(vips);
                    546: 
                    547:                if (match)
                    548:                {
                    549:                        /* schedule delete asynchronously */
                    550:                        lib->processor->queue_job(lib->processor, (job_t*)
                    551:                                                delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
                    552:                }
                    553:        }
                    554:        enumerator->destroy(enumerator);
                    555:        start->destroy(start);
                    556:        DESTROY_IF(end);
                    557: }
                    558: 
                    559: METHOD(stroke_control_t, purge_ike, void,
                    560:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    561: {
                    562:        enumerator_t *enumerator, *children;
                    563:        ike_sa_t *ike_sa;
                    564:        child_sa_t *child_sa;
                    565:        linked_list_t *list;
                    566:        uintptr_t del;
                    567: 
                    568:        list = linked_list_create();
                    569:        enumerator = charon->controller->create_ike_sa_enumerator(
                    570:                                                                                                        charon->controller, TRUE);
                    571:        while (enumerator->enumerate(enumerator, &ike_sa))
                    572:        {
                    573:                children = ike_sa->create_child_sa_enumerator(ike_sa);
                    574:                if (!children->enumerate(children, (void**)&child_sa))
                    575:                {
                    576:                        list->insert_last(list,
                    577:                                                (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa));
                    578:                }
                    579:                children->destroy(children);
                    580:        }
                    581:        enumerator->destroy(enumerator);
                    582: 
                    583:        enumerator = list->create_enumerator(list);
                    584:        while (enumerator->enumerate(enumerator, &del))
                    585:        {
                    586:                charon_terminate(this, del, msg, out, FALSE);
                    587:        }
                    588:        enumerator->destroy(enumerator);
                    589:        list->destroy(list);
                    590: }
                    591: 
                    592: /**
                    593:  * call charon to install a shunt or trap
                    594:  */
                    595: static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
                    596:                                                 char *name, FILE *out)
                    597: {
                    598:        ipsec_mode_t mode;
                    599: 
                    600:        mode = child_cfg->get_mode(child_cfg);
                    601:        if (mode == MODE_PASS || mode == MODE_DROP)
                    602:        {
                    603:                if (charon->shunts->install(charon->shunts,
                    604:                                                                        peer_cfg->get_name(peer_cfg), child_cfg))
                    605:                {
                    606:                        fprintf(out, "'%s' shunt %N policy installed\n",
                    607:                                        name, ipsec_mode_names, mode);
                    608:                }
                    609:                else
                    610:                {
                    611:                        fprintf(out, "'%s' shunt %N policy installation failed\n",
                    612:                                        name, ipsec_mode_names, mode);
                    613:                }
                    614:        }
                    615:        else
                    616:        {
                    617:                if (charon->traps->install(charon->traps, peer_cfg, child_cfg))
                    618:                {
                    619:                        fprintf(out, "'%s' routed\n", name);
                    620:                }
                    621:                else
                    622:                {
                    623:                        fprintf(out, "routing '%s' failed\n", name);
                    624:                }
                    625:        }
                    626: }
                    627: 
                    628: METHOD(stroke_control_t, route, void,
                    629:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    630: {
                    631:        child_cfg_t *child_cfg = NULL;
                    632:        peer_cfg_t *peer_cfg;
                    633:        enumerator_t *enumerator;
                    634:        bool empty = TRUE;
                    635: 
                    636:        peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
                    637:                                                                                                          msg->route.name);
                    638:        if (peer_cfg)
                    639:        {
                    640:                child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
                    641:                if (child_cfg == NULL)
                    642:                {
                    643:                        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                    644:                        while (enumerator->enumerate(enumerator, &child_cfg))
                    645:                        {
                    646:                                empty = FALSE;
                    647:                                charon_route(peer_cfg, child_cfg, child_cfg->get_name(child_cfg),
                    648:                                                         out);
                    649:                        }
                    650:                        enumerator->destroy(enumerator);
                    651: 
                    652:                        if (empty)
                    653:                        {
                    654:                                DBG1(DBG_CFG, "no child config named '%s'", msg->route.name);
                    655:                                fprintf(out, "no child config named '%s'\n", msg->route.name);
                    656:                        }
                    657:                        peer_cfg->destroy(peer_cfg);
                    658:                        return;
                    659:                }
                    660:        }
                    661:        else
                    662:        {
                    663:                enumerator = charon->backends->create_peer_cfg_enumerator(
                    664:                                                        charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
                    665:                while (enumerator->enumerate(enumerator, &peer_cfg))
                    666:                {
                    667:                        child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
                    668:                        if (child_cfg)
                    669:                        {
                    670:                                peer_cfg->get_ref(peer_cfg);
                    671:                                break;
                    672:                        }
                    673:                }
                    674:                enumerator->destroy(enumerator);
                    675: 
                    676:                if (child_cfg == NULL)
                    677:                {
                    678:                        DBG1(DBG_CFG, "no config named '%s'", msg->route.name);
                    679:                        fprintf(out, "no config named '%s'\n", msg->route.name);
                    680:                        return;
                    681:                }
                    682:        }
                    683:        charon_route(peer_cfg, child_cfg, msg->route.name, out);
                    684:        peer_cfg->destroy(peer_cfg);
                    685:        child_cfg->destroy(child_cfg);
                    686: }
                    687: 
                    688: METHOD(stroke_control_t, unroute, void,
                    689:        private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
                    690: {
                    691:        if (charon->shunts->uninstall(charon->shunts, NULL, msg->unroute.name))
                    692:        {
                    693:                fprintf(out, "shunt policy '%s' uninstalled\n", msg->unroute.name);
                    694:        }
                    695:        else if (charon->traps->uninstall(charon->traps, NULL, msg->unroute.name))
                    696:        {
                    697:                fprintf(out, "trap policy '%s' unrouted\n", msg->unroute.name);
                    698:        }
                    699:        else
                    700:        {
                    701:                fprintf(out, "configuration '%s' not found\n", msg->unroute.name);
                    702:        }
                    703: }
                    704: 
                    705: METHOD(stroke_control_t, destroy, void,
                    706:        private_stroke_control_t *this)
                    707: {
                    708:        free(this);
                    709: }
                    710: 
                    711: /*
                    712:  * see header file
                    713:  */
                    714: stroke_control_t *stroke_control_create()
                    715: {
                    716:        private_stroke_control_t *this;
                    717: 
                    718:        INIT(this,
                    719:                .public = {
                    720:                        .initiate = _initiate,
                    721:                        .terminate = _terminate,
                    722:                        .terminate_srcip = _terminate_srcip,
                    723:                        .rekey = _rekey,
                    724:                        .purge_ike = _purge_ike,
                    725:                        .route = _route,
                    726:                        .unroute = _unroute,
                    727:                        .destroy = _destroy,
                    728:                },
                    729:                .timeout = lib->settings->get_int(lib->settings,
                    730:                                                                        "%s.plugins.stroke.timeout", 0, lib->ns),
                    731:        );
                    732: 
                    733:        return &this->public;
                    734: }

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