Annotation of embedaddon/strongswan/src/libcharon/daemon.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2006-2017 Tobias Brunner
                      3:  * Copyright (C) 2005-2009 Martin Willi
                      4:  * Copyright (C) 2006 Daniel Roethlisberger
                      5:  * Copyright (C) 2005 Jan Hutter
                      6:  * HSR Hochschule fuer Technik Rapperswil
                      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: /*
                     20:  * Copyright (C) 2016 secunet Security Networks AG
                     21:  * Copyright (C) 2016 Thomas Egerer
                     22:  *
                     23:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     24:  * of this software and associated documentation files (the "Software"), to deal
                     25:  * in the Software without restriction, including without limitation the rights
                     26:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     27:  * copies of the Software, and to permit persons to whom the Software is
                     28:  * furnished to do so, subject to the following conditions:
                     29:  *
                     30:  * The above copyright notice and this permission notice shall be included in
                     31:  * all copies or substantial portions of the Software.
                     32:  *
                     33:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     34:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     35:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     36:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     37:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     38:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     39:  * THE SOFTWARE.
                     40:  */
                     41: 
                     42: #include <stdio.h>
                     43: #include <sys/types.h>
                     44: #include <unistd.h>
                     45: #include <time.h>
                     46: #include <errno.h>
                     47: 
                     48: #ifdef HAVE_SYSLOG
                     49: #include <syslog.h>
                     50: #endif
                     51: 
                     52: #include "daemon.h"
                     53: 
                     54: #include <library.h>
                     55: #include <bus/listeners/sys_logger.h>
                     56: #include <bus/listeners/file_logger.h>
                     57: #include <collections/array.h>
                     58: #include <plugins/plugin_feature.h>
                     59: #include <kernel/kernel_handler.h>
                     60: #include <processing/jobs/start_action_job.h>
                     61: #include <threading/mutex.h>
                     62: 
                     63: #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
                     64: #define LOG_AUTHPRIV LOG_AUTH
                     65: #endif
                     66: 
                     67: typedef struct private_daemon_t private_daemon_t;
                     68: 
                     69: /**
                     70:  * Private additions to daemon_t, contains threads and internal functions.
                     71:  */
                     72: struct private_daemon_t {
                     73:        /**
                     74:         * Public members of daemon_t.
                     75:         */
                     76:        daemon_t public;
                     77: 
                     78:        /**
                     79:         * Handler for kernel events
                     80:         */
                     81:        kernel_handler_t *kernel_handler;
                     82: 
                     83:        /**
                     84:         * A list of installed loggers (as logger_entry_t*)
                     85:         */
                     86:        linked_list_t *loggers;
                     87: 
                     88:        /**
                     89:         * Cached log levels for default loggers
                     90:         */
                     91:        level_t *levels;
                     92: 
                     93:        /**
                     94:         * Whether to log to stdout/err by default
                     95:         */
                     96:        bool to_stderr;
                     97: 
                     98:        /**
                     99:         * Identifier used for syslog (in the openlog call)
                    100:         */
                    101:        char *syslog_identifier;
                    102: 
                    103:        /**
                    104:         * Mutex for configured loggers
                    105:         */
                    106:        mutex_t *mutex;
                    107: 
                    108:        /**
                    109:         * Integrity check failed?
                    110:         */
                    111:        bool integrity_failed;
                    112: 
                    113:        /**
                    114:         * Number of times we have been initialized
                    115:         */
                    116:        refcount_t ref;
                    117: };
                    118: 
                    119: /**
                    120:  * Register plugins if built statically
                    121:  */
                    122: #ifdef STATIC_PLUGIN_CONSTRUCTORS
                    123: #include "plugin_constructors.c"
                    124: #endif
                    125: 
                    126: /**
                    127:  * One and only instance of the daemon.
                    128:  */
                    129: daemon_t *charon;
                    130: 
                    131: /**
                    132:  * hook in library for debugging messages
                    133:  */
                    134: extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
                    135: 
                    136: /**
                    137:  * we store the previous debug function so we can reset it
                    138:  */
                    139: static void (*dbg_old) (debug_t group, level_t level, char *fmt, ...);
                    140: 
                    141: /**
                    142:  * Logging hook for library logs, spreads debug message over bus
                    143:  */
                    144: static void dbg_bus(debug_t group, level_t level, char *fmt, ...)
                    145: {
                    146:        va_list args;
                    147: 
                    148:        va_start(args, fmt);
                    149:        charon->bus->vlog(charon->bus, group, level, fmt, args);
                    150:        va_end(args);
                    151: }
                    152: 
                    153: /**
                    154:  * Data for registered custom loggers
                    155:  */
                    156: typedef struct {
                    157:        /**
                    158:         * Name of the custom logger (also used for loglevel configuration)
                    159:         */
                    160:        char *name;
                    161: 
                    162:        /**
                    163:         * Constructor to be called for custom logger creation
                    164:         */
                    165:        custom_logger_constructor_t constructor;
                    166: 
                    167: } custom_logger_entry_t;
                    168: 
                    169: #define MAX_CUSTOM_LOGGERS 10
                    170: 
                    171: /**
                    172:  * Static array for logger registration using __attribute__((constructor))
                    173:  */
                    174: static custom_logger_entry_t custom_loggers[MAX_CUSTOM_LOGGERS];
                    175: static int custom_logger_count;
                    176: 
                    177: /**
                    178:  * Described in header
                    179:  */
                    180: void register_custom_logger(char *name,
                    181:                                                        custom_logger_constructor_t constructor)
                    182: {
                    183:        if (custom_logger_count < MAX_CUSTOM_LOGGERS - 1)
                    184:        {
                    185:                custom_loggers[custom_logger_count].name = name;
                    186:                custom_loggers[custom_logger_count].constructor = constructor;
                    187:                custom_logger_count++;
                    188:        }
                    189:        else
                    190:        {
                    191:                fprintf(stderr, "failed to register custom logger, please increase "
                    192:                                "MAX_CUSTOM_LOGGERS");
                    193:        }
                    194: }
                    195: 
                    196: /**
                    197:  * Types of supported loggers
                    198:  */
                    199: typedef enum {
                    200:        /**
                    201:         * Syslog logger instance
                    202:         */
                    203:        SYS_LOGGER,
                    204: 
                    205:        /**
                    206:         * File logger instance
                    207:         */
                    208:        FILE_LOGGER,
                    209: 
                    210:        /**
                    211:         * Custom logger instance
                    212:         */
                    213:        CUSTOM_LOGGER,
                    214: 
                    215: } logger_type_t;
                    216: 
                    217: /**
                    218:  * Some metadata about configured loggers
                    219:  */
                    220: typedef struct {
                    221:        /**
                    222:         * Target of the logger (syslog facility or filename)
                    223:         */
                    224:        char *target;
                    225: 
                    226:        /**
                    227:         * Type of logger
                    228:         */
                    229:        logger_type_t type;
                    230: 
                    231:        /**
                    232:         * The actual logger
                    233:         */
                    234:        union {
                    235:                sys_logger_t *sys;
                    236:                file_logger_t *file;
                    237:                custom_logger_t *custom;
                    238:        } logger;
                    239: 
                    240: } logger_entry_t;
                    241: 
                    242: /**
                    243:  * Destroy a logger entry
                    244:  */
                    245: static void logger_entry_destroy(logger_entry_t *this)
                    246: {
                    247:        switch (this->type)
                    248:        {
                    249:                case FILE_LOGGER:
                    250:                        DESTROY_IF(this->logger.file);
                    251:                        break;
                    252:                case SYS_LOGGER:
                    253:                        DESTROY_IF(this->logger.sys);
                    254:                        break;
                    255:                case CUSTOM_LOGGER:
                    256:                        DESTROY_IF(this->logger.custom);
                    257:                        break;
                    258:        }
                    259:        free(this->target);
                    260:        free(this);
                    261: }
                    262: 
                    263: /**
                    264:  * Unregister and destroy a logger entry
                    265:  */
                    266: static void logger_entry_unregister_destroy(logger_entry_t *this)
                    267: {
                    268:        switch (this->type)
                    269:        {
                    270:                case FILE_LOGGER:
                    271:                        charon->bus->remove_logger(charon->bus, &this->logger.file->logger);
                    272:                        break;
                    273:                case SYS_LOGGER:
                    274:                        charon->bus->remove_logger(charon->bus, &this->logger.sys->logger);
                    275:                        break;
                    276:                case CUSTOM_LOGGER:
                    277:                        charon->bus->remove_logger(charon->bus,
                    278:                                                                           &this->logger.custom->logger);
                    279:                        break;
                    280:        }
                    281:        logger_entry_destroy(this);
                    282: }
                    283: 
                    284: CALLBACK(logger_entry_match, bool,
                    285:        logger_entry_t *this, va_list args)
                    286: {
                    287:        logger_type_t type;
                    288:        char *target;
                    289: 
                    290:        VA_ARGS_VGET(args, target, type);
                    291:        return this->type == type && streq(this->target, target);
                    292: }
                    293: 
                    294: /**
                    295:  * Handle configured syslog identifier
                    296:  *
                    297:  * mutex must be locked when calling this function
                    298:  */
                    299: static void handle_syslog_identifier(private_daemon_t *this)
                    300: {
                    301: #ifdef HAVE_SYSLOG
                    302:        char *identifier;
                    303: 
                    304:        identifier = lib->settings->get_str(lib->settings, "%s.syslog.identifier",
                    305:                                                                                NULL, lib->ns);
                    306:        if (identifier)
                    307:        {       /* set identifier, which is prepended to each log line */
                    308:                if (!this->syslog_identifier ||
                    309:                        !streq(identifier, this->syslog_identifier))
                    310:                {
                    311:                        closelog();
                    312:                        this->syslog_identifier = identifier;
                    313:                        openlog(this->syslog_identifier, 0, 0);
                    314:                }
                    315:        }
                    316:        else if (this->syslog_identifier)
                    317:        {
                    318:                closelog();
                    319:                this->syslog_identifier = NULL;
                    320:        }
                    321: #endif /* HAVE_SYSLOG */
                    322: }
                    323: 
                    324: /**
                    325:  * Convert the given string into a syslog facility, returns -1 if the facility
                    326:  * is not supported
                    327:  */
                    328: static int get_syslog_facility(char *facility)
                    329: {
                    330: #ifdef HAVE_SYSLOG
                    331:        if (streq(facility, "daemon"))
                    332:        {
                    333:                return LOG_DAEMON;
                    334:        }
                    335:        else if (streq(facility, "auth"))
                    336:        {
                    337:                return LOG_AUTHPRIV;
                    338:        }
                    339: #endif /* HAVE_SYSLOG */
                    340:        return -1;
                    341: }
                    342: 
                    343: /**
                    344:  * Returns an existing or newly created logger entry (if found, it is removed
                    345:  * from the given linked list of existing loggers)
                    346:  */
                    347: static logger_entry_t *get_logger_entry(char *target, logger_type_t type,
                    348:                                                                                linked_list_t *existing,
                    349:                                                                                custom_logger_constructor_t constructor)
                    350: {
                    351:        logger_entry_t *entry;
                    352: 
                    353:        if (!existing->find_first(existing, logger_entry_match, (void**)&entry,
                    354:                                                          target, type))
                    355:        {
                    356:                INIT(entry,
                    357:                        .target = strdup(target),
                    358:                        .type = type,
                    359:                );
                    360:                switch (type)
                    361:                {
                    362:                        case FILE_LOGGER:
                    363:                                entry->logger.file = file_logger_create(target);
                    364:                                break;
                    365:                        case SYS_LOGGER:
                    366: #ifdef HAVE_SYSLOG
                    367:                                entry->logger.sys = sys_logger_create(
                    368:                                                                                                get_syslog_facility(target));
                    369:                                break;
                    370: #else
                    371:                                free(entry);
                    372:                                return NULL;
                    373: #endif /* HAVE_SYSLOG */
                    374:                        case CUSTOM_LOGGER:
                    375:                                if (constructor)
                    376:                                {
                    377:                                        entry->logger.custom = constructor(target);
                    378:                                }
                    379:                                if (!entry->logger.custom)
                    380:                                {
                    381:                                        free(entry);
                    382:                                        return NULL;
                    383:                                }
                    384:                                break;
                    385:                }
                    386:        }
                    387:        else
                    388:        {
                    389:                existing->remove(existing, entry, NULL);
                    390:        }
                    391:        return entry;
                    392: }
                    393: 
                    394: /**
                    395:  * Create or reuse a syslog logger
                    396:  */
                    397: static sys_logger_t *add_sys_logger(private_daemon_t *this, char *facility,
                    398:                                                                        linked_list_t *current_loggers)
                    399: {
                    400:        logger_entry_t *entry;
                    401: 
                    402:        entry = get_logger_entry(facility, SYS_LOGGER, current_loggers, NULL);
                    403:        if (entry)
                    404:        {
                    405:                this->loggers->insert_last(this->loggers, entry);
                    406:        }
                    407:        return entry ? entry->logger.sys : NULL;
                    408: }
                    409: 
                    410: /**
                    411:  * Create or reuse a file logger
                    412:  */
                    413: static file_logger_t *add_file_logger(private_daemon_t *this, char *filename,
                    414:                                                                          linked_list_t *current_loggers)
                    415: {
                    416:        logger_entry_t *entry;
                    417: 
                    418:        entry = get_logger_entry(filename, FILE_LOGGER, current_loggers, NULL);
                    419:        if (entry)
                    420:        {
                    421:                this->loggers->insert_last(this->loggers, entry);
                    422:        }
                    423:        return entry ? entry->logger.file : NULL;
                    424: }
                    425: 
                    426:  /**
                    427:  * Create or reuse a custom logger
                    428:  */
                    429: static custom_logger_t *add_custom_logger(private_daemon_t *this,
                    430:                                                                                  custom_logger_entry_t *custom,
                    431:                                                                                  linked_list_t *current_loggers)
                    432: {
                    433:        logger_entry_t *entry;
                    434: 
                    435:        entry = get_logger_entry(custom->name, CUSTOM_LOGGER, current_loggers,
                    436:                                                         custom->constructor);
                    437:        if (entry)
                    438:        {
                    439:                this->loggers->insert_last(this->loggers, entry);
                    440:        }
                    441:        return entry ? entry->logger.custom : NULL;
                    442: }
                    443: 
                    444: /**
                    445:  * Load the given syslog logger configured in strongswan.conf
                    446:  */
                    447: static void load_sys_logger(private_daemon_t *this, char *facility,
                    448:                                                        linked_list_t *current_loggers)
                    449: {
                    450:        sys_logger_t *sys_logger;
                    451:        debug_t group;
                    452:        level_t def;
                    453: 
                    454:        if (get_syslog_facility(facility) == -1)
                    455:        {
                    456:                return;
                    457:        }
                    458: 
                    459:        sys_logger = add_sys_logger(this, facility, current_loggers);
                    460:        if (!sys_logger)
                    461:        {
                    462:                return;
                    463:        }
                    464: 
                    465:        sys_logger->set_options(sys_logger,
                    466:                                lib->settings->get_bool(lib->settings, "%s.syslog.%s.ike_name",
                    467:                                                                                FALSE, lib->ns, facility));
                    468: 
                    469:        def = lib->settings->get_int(lib->settings, "%s.syslog.%s.default", 1,
                    470:                                                                 lib->ns, facility);
                    471:        for (group = 0; group < DBG_MAX; group++)
                    472:        {
                    473:                sys_logger->set_level(sys_logger, group,
                    474:                                lib->settings->get_int(lib->settings, "%s.syslog.%s.%N", def,
                    475:                                                        lib->ns, facility, debug_lower_names, group));
                    476:        }
                    477:        charon->bus->add_logger(charon->bus, &sys_logger->logger);
                    478: }
                    479: 
                    480: /**
                    481:  * Load the given file logger configured in strongswan.conf
                    482:  */
                    483: static void load_file_logger(private_daemon_t *this, char *section,
                    484:                                                         linked_list_t *current_loggers)
                    485: {
                    486:        file_logger_t *file_logger;
                    487:        debug_t group;
                    488:        level_t def;
                    489:        bool add_ms, ike_name, flush_line, append;
                    490:        char *time_format, *filename;
                    491: 
                    492:        time_format = lib->settings->get_str(lib->settings,
                    493:                                                "%s.filelog.%s.time_format", NULL, lib->ns, section);
                    494:        add_ms = lib->settings->get_bool(lib->settings,
                    495:                                                "%s.filelog.%s.time_add_ms", FALSE, lib->ns, section);
                    496:        ike_name = lib->settings->get_bool(lib->settings,
                    497:                                                "%s.filelog.%s.ike_name", FALSE, lib->ns, section);
                    498:        flush_line = lib->settings->get_bool(lib->settings,
                    499:                                                "%s.filelog.%s.flush_line", FALSE, lib->ns, section);
                    500:        append = lib->settings->get_bool(lib->settings,
                    501:                                                "%s.filelog.%s.append", TRUE, lib->ns, section);
                    502:        filename = lib->settings->get_str(lib->settings,
                    503:                                                "%s.filelog.%s.path", section, lib->ns, section);
                    504: 
                    505:        file_logger = add_file_logger(this, filename, current_loggers);
                    506:        if (!file_logger)
                    507:        {
                    508:                return;
                    509:        }
                    510: 
                    511:        file_logger->set_options(file_logger, time_format, add_ms, ike_name);
                    512:        file_logger->open(file_logger, flush_line, append);
                    513: 
                    514:        def = lib->settings->get_int(lib->settings, "%s.filelog.%s.default", 1,
                    515:                                                                 lib->ns, section);
                    516:        for (group = 0; group < DBG_MAX; group++)
                    517:        {
                    518:                file_logger->set_level(file_logger, group,
                    519:                                lib->settings->get_int(lib->settings, "%s.filelog.%s.%N", def,
                    520:                                                        lib->ns, section, debug_lower_names, group));
                    521:        }
                    522:        charon->bus->add_logger(charon->bus, &file_logger->logger);
                    523: }
                    524: 
                    525: /**
                    526:  * Load the given custom logger configured in strongswan.conf
                    527:  */
                    528: static void load_custom_logger(private_daemon_t *this,
                    529:                                                           custom_logger_entry_t *entry,
                    530:                                                           linked_list_t *current_loggers)
                    531: {
                    532:        custom_logger_t *custom_logger;
                    533:        debug_t group;
                    534:        level_t def;
                    535: 
                    536:        custom_logger = add_custom_logger(this, entry, current_loggers);
                    537:        if (!custom_logger)
                    538:        {
                    539:                return;
                    540:        }
                    541: 
                    542:        def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
                    543:                                                                 lib->ns, entry->name);
                    544:        for (group = 0; group < DBG_MAX; group++)
                    545:        {
                    546:                custom_logger->set_level(custom_logger, group,
                    547:                                lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
                    548:                                                        lib->ns, entry->name, debug_lower_names, group));
                    549:        }
                    550:        if (custom_logger->reload)
                    551:        {
                    552:                custom_logger->reload(custom_logger);
                    553:        }
                    554:        charon->bus->add_logger(charon->bus, &custom_logger->logger);
                    555: }
                    556: 
                    557: METHOD(daemon_t, load_loggers, void,
                    558:        private_daemon_t *this)
                    559: {
                    560:        enumerator_t *enumerator;
                    561:        linked_list_t *current_loggers;
                    562:        char *target;
                    563:        int i;
                    564: 
                    565:        this->mutex->lock(this->mutex);
                    566:        handle_syslog_identifier(this);
                    567:        current_loggers = this->loggers;
                    568:        this->loggers = linked_list_create();
                    569:        enumerator = lib->settings->create_section_enumerator(lib->settings,
                    570:                                                                                                                "%s.syslog", lib->ns);
                    571:        while (enumerator->enumerate(enumerator, &target))
                    572:        {
                    573:                load_sys_logger(this, target, current_loggers);
                    574:        }
                    575:        enumerator->destroy(enumerator);
                    576: 
                    577:        enumerator = lib->settings->create_section_enumerator(lib->settings,
                    578:                                                                                                                "%s.filelog", lib->ns);
                    579:        while (enumerator->enumerate(enumerator, &target))
                    580:        {
                    581:                load_file_logger(this, target, current_loggers);
                    582:        }
                    583:        enumerator->destroy(enumerator);
                    584: 
                    585:        for (i = 0; i < custom_logger_count; ++i)
                    586:        {
                    587:                load_custom_logger(this, &custom_loggers[i], current_loggers);
                    588:        }
                    589: 
                    590:        if (!this->loggers->get_count(this->loggers) && this->levels)
                    591:        {       /* setup legacy style default loggers configured via command-line */
                    592:                file_logger_t *file_logger;
                    593:                sys_logger_t *sys_logger;
                    594:                debug_t group;
                    595: 
                    596:                sys_logger = add_sys_logger(this, "daemon", current_loggers);
                    597:                file_logger = add_file_logger(this, "stdout", current_loggers);
                    598:                file_logger->open(file_logger, FALSE, FALSE);
                    599: 
                    600:                for (group = 0; group < DBG_MAX; group++)
                    601:                {
                    602:                        if (sys_logger)
                    603:                        {
                    604:                                sys_logger->set_level(sys_logger, group, this->levels[group]);
                    605:                        }
                    606:                        if (this->to_stderr)
                    607:                        {
                    608:                                file_logger->set_level(file_logger, group, this->levels[group]);
                    609:                        }
                    610:                }
                    611:                if (sys_logger)
                    612:                {
                    613:                        charon->bus->add_logger(charon->bus, &sys_logger->logger);
                    614:                }
                    615:                charon->bus->add_logger(charon->bus, &file_logger->logger);
                    616: 
                    617:                sys_logger = add_sys_logger(this, "auth", current_loggers);
                    618:                if (sys_logger)
                    619:                {
                    620:                        sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
                    621:                        charon->bus->add_logger(charon->bus, &sys_logger->logger);
                    622:                }
                    623:        }
                    624:        /* unregister and destroy any unused remaining loggers */
                    625:        current_loggers->destroy_function(current_loggers,
                    626:                                                                         (void*)logger_entry_unregister_destroy);
                    627:        this->mutex->unlock(this->mutex);
                    628: }
                    629: 
                    630: METHOD(daemon_t, set_default_loggers, void,
                    631:        private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
                    632: {
                    633:        debug_t group;
                    634: 
                    635:        this->mutex->lock(this->mutex);
                    636:        if (!levels)
                    637:        {
                    638:                free(this->levels);
                    639:                this->levels = NULL;
                    640:        }
                    641:        else
                    642:        {
                    643:                if (!this->levels)
                    644:                {
                    645:                        this->levels = calloc(sizeof(level_t), DBG_MAX);
                    646:                }
                    647:                for (group = 0; group < DBG_MAX; group++)
                    648:                {
                    649:                        this->levels[group] = levels[group];
                    650:                }
                    651:                this->to_stderr = to_stderr;
                    652:        }
                    653:        this->mutex->unlock(this->mutex);
                    654: }
                    655: 
                    656: METHOD(daemon_t, set_level, void,
                    657:        private_daemon_t *this, debug_t group, level_t level)
                    658: {
                    659:        enumerator_t *enumerator;
                    660:        logger_entry_t *entry;
                    661: 
                    662:        /* we set the loglevel on ALL loggers */
                    663:        this->mutex->lock(this->mutex);
                    664:        enumerator = this->loggers->create_enumerator(this->loggers);
                    665:        while (enumerator->enumerate(enumerator, &entry))
                    666:        {
                    667:                switch (entry->type)
                    668:                {
                    669:                        case FILE_LOGGER:
                    670:                                entry->logger.file->set_level(entry->logger.file, group, level);
                    671:                                charon->bus->add_logger(charon->bus,
                    672:                                                                                &entry->logger.file->logger);
                    673:                                break;
                    674:                        case SYS_LOGGER:
                    675:                                entry->logger.sys->set_level(entry->logger.sys, group, level);
                    676:                                charon->bus->add_logger(charon->bus,
                    677:                                                                                &entry->logger.sys->logger);
                    678:                                break;
                    679:                        case CUSTOM_LOGGER:
                    680:                                entry->logger.custom->set_level(entry->logger.custom, group,
                    681:                                                                                                level);
                    682:                                charon->bus->add_logger(charon->bus,
                    683:                                                                                &entry->logger.custom->logger);
                    684:                                break;
                    685:                }
                    686:        }
                    687:        enumerator->destroy(enumerator);
                    688:        this->mutex->unlock(this->mutex);
                    689: }
                    690: 
                    691: /**
                    692:  * Clean up all daemon resources
                    693:  */
                    694: static void destroy(private_daemon_t *this)
                    695: {
                    696:        /* terminate all idle threads */
                    697:        lib->processor->set_threads(lib->processor, 0);
                    698:        /* make sure nobody waits for a DNS query */
                    699:        lib->hosts->flush(lib->hosts);
                    700:        /* close all IKE_SAs */
                    701:        if (this->public.ike_sa_manager)
                    702:        {
                    703:                this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
                    704:        }
                    705:        if (this->public.traps)
                    706:        {
                    707:                this->public.traps->flush(this->public.traps);
                    708:        }
                    709:        if (this->public.shunts)
                    710:        {
                    711:                this->public.shunts->flush(this->public.shunts);
                    712:        }
                    713:        if (this->public.sender)
                    714:        {
                    715:                this->public.sender->flush(this->public.sender);
                    716:        }
                    717: 
                    718:        /* cancel all threads and wait for their termination */
                    719:        lib->processor->cancel(lib->processor);
                    720: 
                    721: #ifdef ME
                    722:        DESTROY_IF(this->public.connect_manager);
                    723:        DESTROY_IF(this->public.mediation_manager);
                    724: #endif /* ME */
                    725:        /* make sure the cache and scheduler are clear before unloading plugins */
                    726:        lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
                    727:        lib->scheduler->flush(lib->scheduler);
                    728:        lib->plugins->unload(lib->plugins);
                    729:        DESTROY_IF(this->public.attributes);
                    730:        DESTROY_IF(this->kernel_handler);
                    731:        DESTROY_IF(this->public.traps);
                    732:        DESTROY_IF(this->public.shunts);
                    733:        DESTROY_IF(this->public.redirect);
                    734:        DESTROY_IF(this->public.controller);
                    735:        DESTROY_IF(this->public.eap);
                    736:        DESTROY_IF(this->public.xauth);
                    737:        DESTROY_IF(this->public.backends);
                    738:        DESTROY_IF(this->public.socket);
                    739:        DESTROY_IF(this->public.kernel);
                    740: 
                    741:        /* rehook library logging, shutdown logging */
                    742:        dbg = dbg_old;
                    743:        DESTROY_IF(this->public.bus);
                    744:        this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
                    745:        this->mutex->destroy(this->mutex);
                    746:        free(this->levels);
                    747:        free(this);
                    748: }
                    749: 
                    750: /**
                    751:  * Run a set of configured scripts
                    752:  */
                    753: static void run_scripts(private_daemon_t *this, char *verb)
                    754: {
                    755:        struct {
                    756:                char *name;
                    757:                char *path;
                    758:        } *script;
                    759:        array_t *scripts = NULL;
                    760:        enumerator_t *enumerator;
                    761:        char *key, *value, *pos, buf[1024];
                    762:        FILE *cmd;
                    763: 
                    764:        /* copy the scripts so we don't hold any locks while executing them */
                    765:        enumerator = lib->settings->create_key_value_enumerator(lib->settings,
                    766:                                                                                                "%s.%s-scripts", lib->ns, verb);
                    767:        while (enumerator->enumerate(enumerator, &key, &value))
                    768:        {
                    769:                INIT(script,
                    770:                        .name = key,
                    771:                        .path = value,
                    772:                );
                    773:                array_insert_create(&scripts, ARRAY_TAIL, script);
                    774:        }
                    775:        enumerator->destroy(enumerator);
                    776: 
                    777:        enumerator = array_create_enumerator(scripts);
                    778:        while (enumerator->enumerate(enumerator, &script))
                    779:        {
                    780:                DBG1(DBG_DMN, "executing %s script '%s' (%s)", verb, script->name,
                    781:                         script->path);
                    782:                cmd = popen(script->path, "r");
                    783:                if (!cmd)
                    784:                {
                    785:                        DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
                    786:                                 verb, script->name, script->path, strerror(errno));
                    787:                }
                    788:                else
                    789:                {
                    790:                        while (TRUE)
                    791:                        {
                    792:                                if (!fgets(buf, sizeof(buf), cmd))
                    793:                                {
                    794:                                        if (ferror(cmd))
                    795:                                        {
                    796:                                                DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
                    797:                                                         verb, script->name, script->path);
                    798:                                        }
                    799:                                        break;
                    800:                                }
                    801:                                else
                    802:                                {
                    803:                                        pos = buf + strlen(buf);
                    804:                                        if (pos > buf && pos[-1] == '\n')
                    805:                                        {
                    806:                                                pos[-1] = '\0';
                    807:                                        }
                    808:                                        DBG1(DBG_DMN, "%s: %s", script->name, buf);
                    809:                                }
                    810:                        }
                    811:                        pclose(cmd);
                    812:                }
                    813:                free(script);
                    814:        }
                    815:        enumerator->destroy(enumerator);
                    816:        array_destroy(scripts);
                    817: }
                    818: 
                    819: METHOD(daemon_t, start, void,
                    820:           private_daemon_t *this)
                    821: {
                    822:        /* start the engine, go multithreaded */
                    823:        lib->processor->set_threads(lib->processor,
                    824:                                                lib->settings->get_int(lib->settings, "%s.threads",
                    825:                                                                                           DEFAULT_THREADS, lib->ns));
                    826: 
                    827:        run_scripts(this, "start");
                    828: }
                    829: 
                    830: /**
                    831:  * Initialize/deinitialize sender and receiver
                    832:  */
                    833: static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
                    834:                                                           bool reg, private_daemon_t *this)
                    835: {
                    836:        if (reg)
                    837:        {
                    838:                this->public.receiver = receiver_create();
                    839:                if (!this->public.receiver)
                    840:                {
                    841:                        return FALSE;
                    842:                }
                    843:                this->public.sender = sender_create();
                    844:        }
                    845:        else
                    846:        {
                    847:                DESTROY_IF(this->public.receiver);
                    848:                DESTROY_IF(this->public.sender);
                    849:        }
                    850:        return TRUE;
                    851: }
                    852: 
                    853: /**
                    854:  * Initialize/deinitialize IKE_SA/CHILD_SA managers
                    855:  */
                    856: static bool sa_managers_cb(void *plugin, plugin_feature_t *feature,
                    857:                                                   bool reg, private_daemon_t *this)
                    858: {
                    859:        if (reg)
                    860:        {
                    861:                this->public.ike_sa_manager = ike_sa_manager_create();
                    862:                if (!this->public.ike_sa_manager)
                    863:                {
                    864:                        return FALSE;
                    865:                }
                    866:                this->public.child_sa_manager = child_sa_manager_create();
                    867:        }
                    868:        else
                    869:        {
                    870:                DESTROY_IF(this->public.ike_sa_manager);
                    871:                DESTROY_IF(this->public.child_sa_manager);
                    872:        }
                    873:        return TRUE;
                    874: }
                    875: 
                    876: METHOD(daemon_t, initialize, bool,
                    877:        private_daemon_t *this, char *plugins)
                    878: {
                    879:        plugin_feature_t features[] = {
                    880:                PLUGIN_PROVIDE(CUSTOM, "libcharon"),
                    881:                        PLUGIN_DEPENDS(NONCE_GEN),
                    882:                        PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
                    883:                        PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
                    884:                        PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
                    885:                        PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
                    886:                PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
                    887:                        PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
                    888:                                PLUGIN_DEPENDS(HASHER, HASH_SHA1),
                    889:                                PLUGIN_DEPENDS(RNG, RNG_STRONG),
                    890:                                PLUGIN_DEPENDS(CUSTOM, "socket"),
                    891:                PLUGIN_CALLBACK((plugin_feature_callback_t)sa_managers_cb, this),
                    892:                        PLUGIN_PROVIDE(CUSTOM, "libcharon-sa-managers"),
                    893:                                PLUGIN_DEPENDS(HASHER, HASH_SHA1),
                    894:                                PLUGIN_DEPENDS(RNG, RNG_WEAK),
                    895:        };
                    896:        lib->plugins->add_static_features(lib->plugins, lib->ns, features,
                    897:                                                                          countof(features), TRUE, NULL, NULL);
                    898: 
                    899:        /* load plugins, further infrastructure may need it */
                    900:        if (!lib->plugins->load(lib->plugins, plugins))
                    901:        {
                    902:                return FALSE;
                    903:        }
                    904: 
                    905:        /* Queue start_action job */
                    906:        lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
                    907: 
                    908: #ifdef ME
                    909:        this->public.connect_manager = connect_manager_create();
                    910:        if (this->public.connect_manager == NULL)
                    911:        {
                    912:                return FALSE;
                    913:        }
                    914:        this->public.mediation_manager = mediation_manager_create();
                    915: #endif /* ME */
                    916: 
                    917:        return TRUE;
                    918: }
                    919: 
                    920: /**
                    921:  * Create the daemon.
                    922:  */
                    923: private_daemon_t *daemon_create()
                    924: {
                    925:        private_daemon_t *this;
                    926: 
                    927:        INIT(this,
                    928:                .public = {
                    929:                        .initialize = _initialize,
                    930:                        .start = _start,
                    931:                        .load_loggers = _load_loggers,
                    932:                        .set_default_loggers = _set_default_loggers,
                    933:                        .set_level = _set_level,
                    934:                        .bus = bus_create(),
                    935:                },
                    936:                .loggers = linked_list_create(),
                    937:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    938:                .ref = 1,
                    939:        );
                    940:        charon = &this->public;
                    941:        this->public.kernel = kernel_interface_create();
                    942:        this->public.attributes = attribute_manager_create();
                    943:        this->public.controller = controller_create();
                    944:        this->public.eap = eap_manager_create();
                    945:        this->public.xauth = xauth_manager_create();
                    946:        this->public.backends = backend_manager_create();
                    947:        this->public.socket = socket_manager_create();
                    948:        this->public.traps = trap_manager_create();
                    949:        this->public.shunts = shunt_manager_create();
                    950:        this->public.redirect = redirect_manager_create();
                    951:        this->kernel_handler = kernel_handler_create();
                    952: 
                    953:        return this;
                    954: }
                    955: 
                    956: /**
                    957:  * Described in header.
                    958:  */
                    959: void libcharon_deinit()
                    960: {
                    961:        private_daemon_t *this = (private_daemon_t*)charon;
                    962: 
                    963:        if (!this || !ref_put(&this->ref))
                    964:        {       /* have more users */
                    965:                return;
                    966:        }
                    967: 
                    968:        run_scripts(this, "stop");
                    969: 
                    970:        destroy(this);
                    971:        charon = NULL;
                    972: }
                    973: 
                    974: /**
                    975:  * Described in header.
                    976:  */
                    977: bool libcharon_init()
                    978: {
                    979:        private_daemon_t *this;
                    980: 
                    981:        if (charon)
                    982:        {       /* already initialized, increase refcount */
                    983:                this = (private_daemon_t*)charon;
                    984:                ref_get(&this->ref);
                    985:                return !this->integrity_failed;
                    986:        }
                    987: 
                    988:        this = daemon_create();
                    989: 
                    990:        /* for uncritical pseudo random numbers */
                    991:        srandom(time(NULL) + getpid());
                    992: 
                    993:        /* set up hook to log dbg message in library via charons message bus */
                    994:        dbg_old = dbg;
                    995:        dbg = dbg_bus;
                    996: 
                    997:        if (lib->integrity &&
                    998:                !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
                    999:        {
                   1000:                dbg(DBG_DMN, 1, "integrity check of libcharon failed");
                   1001:                this->integrity_failed = TRUE;
                   1002:        }
                   1003:        return !this->integrity_failed;
                   1004: }

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