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

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;
1.1.1.2 ! misho     453:        bool ike_name, log_level;
1.1       misho     454: 
                    455:        if (get_syslog_facility(facility) == -1)
                    456:        {
                    457:                return;
                    458:        }
                    459: 
                    460:        sys_logger = add_sys_logger(this, facility, current_loggers);
                    461:        if (!sys_logger)
                    462:        {
                    463:                return;
                    464:        }
                    465: 
1.1.1.2 ! misho     466:        ike_name = lib->settings->get_bool(lib->settings, "%s.syslog.%s.ike_name",
        !           467:                                                                           FALSE, lib->ns, facility);
        !           468:        log_level = lib->settings->get_bool(lib->settings, "%s.syslog.%s.log_level",
        !           469:                                                                           FALSE, lib->ns, facility);
        !           470: 
        !           471:        sys_logger->set_options(sys_logger, ike_name, log_level);
1.1       misho     472: 
                    473:        def = lib->settings->get_int(lib->settings, "%s.syslog.%s.default", 1,
                    474:                                                                 lib->ns, facility);
                    475:        for (group = 0; group < DBG_MAX; group++)
                    476:        {
                    477:                sys_logger->set_level(sys_logger, group,
                    478:                                lib->settings->get_int(lib->settings, "%s.syslog.%s.%N", def,
                    479:                                                        lib->ns, facility, debug_lower_names, group));
                    480:        }
                    481:        charon->bus->add_logger(charon->bus, &sys_logger->logger);
                    482: }
                    483: 
                    484: /**
                    485:  * Load the given file logger configured in strongswan.conf
                    486:  */
                    487: static void load_file_logger(private_daemon_t *this, char *section,
                    488:                                                         linked_list_t *current_loggers)
                    489: {
                    490:        file_logger_t *file_logger;
                    491:        debug_t group;
                    492:        level_t def;
1.1.1.2 ! misho     493:        bool add_ms, ike_name, log_level, flush_line, append;
1.1       misho     494:        char *time_format, *filename;
                    495: 
                    496:        time_format = lib->settings->get_str(lib->settings,
                    497:                                                "%s.filelog.%s.time_format", NULL, lib->ns, section);
                    498:        add_ms = lib->settings->get_bool(lib->settings,
                    499:                                                "%s.filelog.%s.time_add_ms", FALSE, lib->ns, section);
                    500:        ike_name = lib->settings->get_bool(lib->settings,
                    501:                                                "%s.filelog.%s.ike_name", FALSE, lib->ns, section);
1.1.1.2 ! misho     502:        log_level = lib->settings->get_bool(lib->settings,
        !           503:                                                "%s.filelog.%s.log_level", FALSE, lib->ns, section);
1.1       misho     504:        flush_line = lib->settings->get_bool(lib->settings,
                    505:                                                "%s.filelog.%s.flush_line", FALSE, lib->ns, section);
                    506:        append = lib->settings->get_bool(lib->settings,
                    507:                                                "%s.filelog.%s.append", TRUE, lib->ns, section);
                    508:        filename = lib->settings->get_str(lib->settings,
                    509:                                                "%s.filelog.%s.path", section, lib->ns, section);
                    510: 
                    511:        file_logger = add_file_logger(this, filename, current_loggers);
                    512:        if (!file_logger)
                    513:        {
                    514:                return;
                    515:        }
                    516: 
1.1.1.2 ! misho     517:        file_logger->set_options(file_logger, time_format, add_ms, ike_name,
        !           518:                                                         log_level);
1.1       misho     519:        file_logger->open(file_logger, flush_line, append);
                    520: 
                    521:        def = lib->settings->get_int(lib->settings, "%s.filelog.%s.default", 1,
                    522:                                                                 lib->ns, section);
                    523:        for (group = 0; group < DBG_MAX; group++)
                    524:        {
                    525:                file_logger->set_level(file_logger, group,
                    526:                                lib->settings->get_int(lib->settings, "%s.filelog.%s.%N", def,
                    527:                                                        lib->ns, section, debug_lower_names, group));
                    528:        }
                    529:        charon->bus->add_logger(charon->bus, &file_logger->logger);
                    530: }
                    531: 
                    532: /**
                    533:  * Load the given custom logger configured in strongswan.conf
                    534:  */
                    535: static void load_custom_logger(private_daemon_t *this,
                    536:                                                           custom_logger_entry_t *entry,
                    537:                                                           linked_list_t *current_loggers)
                    538: {
                    539:        custom_logger_t *custom_logger;
                    540:        debug_t group;
                    541:        level_t def;
                    542: 
                    543:        custom_logger = add_custom_logger(this, entry, current_loggers);
                    544:        if (!custom_logger)
                    545:        {
                    546:                return;
                    547:        }
                    548: 
                    549:        def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
                    550:                                                                 lib->ns, entry->name);
                    551:        for (group = 0; group < DBG_MAX; group++)
                    552:        {
                    553:                custom_logger->set_level(custom_logger, group,
                    554:                                lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
                    555:                                                        lib->ns, entry->name, debug_lower_names, group));
                    556:        }
                    557:        if (custom_logger->reload)
                    558:        {
                    559:                custom_logger->reload(custom_logger);
                    560:        }
                    561:        charon->bus->add_logger(charon->bus, &custom_logger->logger);
                    562: }
                    563: 
                    564: METHOD(daemon_t, load_loggers, void,
                    565:        private_daemon_t *this)
                    566: {
                    567:        enumerator_t *enumerator;
                    568:        linked_list_t *current_loggers;
                    569:        char *target;
                    570:        int i;
                    571: 
                    572:        this->mutex->lock(this->mutex);
                    573:        handle_syslog_identifier(this);
                    574:        current_loggers = this->loggers;
                    575:        this->loggers = linked_list_create();
                    576:        enumerator = lib->settings->create_section_enumerator(lib->settings,
                    577:                                                                                                                "%s.syslog", lib->ns);
                    578:        while (enumerator->enumerate(enumerator, &target))
                    579:        {
                    580:                load_sys_logger(this, target, current_loggers);
                    581:        }
                    582:        enumerator->destroy(enumerator);
                    583: 
                    584:        enumerator = lib->settings->create_section_enumerator(lib->settings,
                    585:                                                                                                                "%s.filelog", lib->ns);
                    586:        while (enumerator->enumerate(enumerator, &target))
                    587:        {
                    588:                load_file_logger(this, target, current_loggers);
                    589:        }
                    590:        enumerator->destroy(enumerator);
                    591: 
                    592:        for (i = 0; i < custom_logger_count; ++i)
                    593:        {
                    594:                load_custom_logger(this, &custom_loggers[i], current_loggers);
                    595:        }
                    596: 
                    597:        if (!this->loggers->get_count(this->loggers) && this->levels)
                    598:        {       /* setup legacy style default loggers configured via command-line */
                    599:                file_logger_t *file_logger;
                    600:                sys_logger_t *sys_logger;
                    601:                debug_t group;
                    602: 
                    603:                sys_logger = add_sys_logger(this, "daemon", current_loggers);
                    604:                file_logger = add_file_logger(this, "stdout", current_loggers);
                    605:                file_logger->open(file_logger, FALSE, FALSE);
                    606: 
                    607:                for (group = 0; group < DBG_MAX; group++)
                    608:                {
                    609:                        if (sys_logger)
                    610:                        {
                    611:                                sys_logger->set_level(sys_logger, group, this->levels[group]);
                    612:                        }
                    613:                        if (this->to_stderr)
                    614:                        {
                    615:                                file_logger->set_level(file_logger, group, this->levels[group]);
                    616:                        }
                    617:                }
                    618:                if (sys_logger)
                    619:                {
                    620:                        charon->bus->add_logger(charon->bus, &sys_logger->logger);
                    621:                }
                    622:                charon->bus->add_logger(charon->bus, &file_logger->logger);
                    623: 
                    624:                sys_logger = add_sys_logger(this, "auth", current_loggers);
                    625:                if (sys_logger)
                    626:                {
                    627:                        sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
                    628:                        charon->bus->add_logger(charon->bus, &sys_logger->logger);
                    629:                }
                    630:        }
                    631:        /* unregister and destroy any unused remaining loggers */
                    632:        current_loggers->destroy_function(current_loggers,
                    633:                                                                         (void*)logger_entry_unregister_destroy);
                    634:        this->mutex->unlock(this->mutex);
                    635: }
                    636: 
                    637: METHOD(daemon_t, set_default_loggers, void,
                    638:        private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
                    639: {
                    640:        debug_t group;
                    641: 
                    642:        this->mutex->lock(this->mutex);
                    643:        if (!levels)
                    644:        {
                    645:                free(this->levels);
                    646:                this->levels = NULL;
                    647:        }
                    648:        else
                    649:        {
                    650:                if (!this->levels)
                    651:                {
                    652:                        this->levels = calloc(sizeof(level_t), DBG_MAX);
                    653:                }
                    654:                for (group = 0; group < DBG_MAX; group++)
                    655:                {
                    656:                        this->levels[group] = levels[group];
                    657:                }
                    658:                this->to_stderr = to_stderr;
                    659:        }
                    660:        this->mutex->unlock(this->mutex);
                    661: }
                    662: 
                    663: METHOD(daemon_t, set_level, void,
                    664:        private_daemon_t *this, debug_t group, level_t level)
                    665: {
                    666:        enumerator_t *enumerator;
                    667:        logger_entry_t *entry;
                    668: 
                    669:        /* we set the loglevel on ALL loggers */
                    670:        this->mutex->lock(this->mutex);
                    671:        enumerator = this->loggers->create_enumerator(this->loggers);
                    672:        while (enumerator->enumerate(enumerator, &entry))
                    673:        {
                    674:                switch (entry->type)
                    675:                {
                    676:                        case FILE_LOGGER:
                    677:                                entry->logger.file->set_level(entry->logger.file, group, level);
                    678:                                charon->bus->add_logger(charon->bus,
                    679:                                                                                &entry->logger.file->logger);
                    680:                                break;
                    681:                        case SYS_LOGGER:
                    682:                                entry->logger.sys->set_level(entry->logger.sys, group, level);
                    683:                                charon->bus->add_logger(charon->bus,
                    684:                                                                                &entry->logger.sys->logger);
                    685:                                break;
                    686:                        case CUSTOM_LOGGER:
                    687:                                entry->logger.custom->set_level(entry->logger.custom, group,
                    688:                                                                                                level);
                    689:                                charon->bus->add_logger(charon->bus,
                    690:                                                                                &entry->logger.custom->logger);
                    691:                                break;
                    692:                }
                    693:        }
                    694:        enumerator->destroy(enumerator);
                    695:        this->mutex->unlock(this->mutex);
                    696: }
                    697: 
                    698: /**
                    699:  * Clean up all daemon resources
                    700:  */
                    701: static void destroy(private_daemon_t *this)
                    702: {
                    703:        /* terminate all idle threads */
                    704:        lib->processor->set_threads(lib->processor, 0);
                    705:        /* make sure nobody waits for a DNS query */
                    706:        lib->hosts->flush(lib->hosts);
                    707:        /* close all IKE_SAs */
                    708:        if (this->public.ike_sa_manager)
                    709:        {
                    710:                this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
                    711:        }
                    712:        if (this->public.traps)
                    713:        {
                    714:                this->public.traps->flush(this->public.traps);
                    715:        }
                    716:        if (this->public.shunts)
                    717:        {
                    718:                this->public.shunts->flush(this->public.shunts);
                    719:        }
                    720:        if (this->public.sender)
                    721:        {
                    722:                this->public.sender->flush(this->public.sender);
                    723:        }
                    724: 
                    725:        /* cancel all threads and wait for their termination */
                    726:        lib->processor->cancel(lib->processor);
                    727: 
                    728: #ifdef ME
                    729:        DESTROY_IF(this->public.connect_manager);
                    730:        DESTROY_IF(this->public.mediation_manager);
                    731: #endif /* ME */
                    732:        /* make sure the cache and scheduler are clear before unloading plugins */
                    733:        lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
                    734:        lib->scheduler->flush(lib->scheduler);
                    735:        lib->plugins->unload(lib->plugins);
                    736:        DESTROY_IF(this->public.attributes);
                    737:        DESTROY_IF(this->kernel_handler);
                    738:        DESTROY_IF(this->public.traps);
                    739:        DESTROY_IF(this->public.shunts);
                    740:        DESTROY_IF(this->public.redirect);
                    741:        DESTROY_IF(this->public.controller);
                    742:        DESTROY_IF(this->public.eap);
                    743:        DESTROY_IF(this->public.xauth);
                    744:        DESTROY_IF(this->public.backends);
                    745:        DESTROY_IF(this->public.socket);
                    746:        DESTROY_IF(this->public.kernel);
                    747: 
                    748:        /* rehook library logging, shutdown logging */
                    749:        dbg = dbg_old;
                    750:        DESTROY_IF(this->public.bus);
                    751:        this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
                    752:        this->mutex->destroy(this->mutex);
                    753:        free(this->levels);
                    754:        free(this);
                    755: }
                    756: 
                    757: /**
                    758:  * Run a set of configured scripts
                    759:  */
                    760: static void run_scripts(private_daemon_t *this, char *verb)
                    761: {
                    762:        struct {
                    763:                char *name;
                    764:                char *path;
                    765:        } *script;
                    766:        array_t *scripts = NULL;
                    767:        enumerator_t *enumerator;
                    768:        char *key, *value, *pos, buf[1024];
                    769:        FILE *cmd;
                    770: 
                    771:        /* copy the scripts so we don't hold any locks while executing them */
                    772:        enumerator = lib->settings->create_key_value_enumerator(lib->settings,
                    773:                                                                                                "%s.%s-scripts", lib->ns, verb);
                    774:        while (enumerator->enumerate(enumerator, &key, &value))
                    775:        {
                    776:                INIT(script,
                    777:                        .name = key,
                    778:                        .path = value,
                    779:                );
                    780:                array_insert_create(&scripts, ARRAY_TAIL, script);
                    781:        }
                    782:        enumerator->destroy(enumerator);
                    783: 
                    784:        enumerator = array_create_enumerator(scripts);
                    785:        while (enumerator->enumerate(enumerator, &script))
                    786:        {
                    787:                DBG1(DBG_DMN, "executing %s script '%s' (%s)", verb, script->name,
                    788:                         script->path);
                    789:                cmd = popen(script->path, "r");
                    790:                if (!cmd)
                    791:                {
                    792:                        DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
                    793:                                 verb, script->name, script->path, strerror(errno));
                    794:                }
                    795:                else
                    796:                {
                    797:                        while (TRUE)
                    798:                        {
                    799:                                if (!fgets(buf, sizeof(buf), cmd))
                    800:                                {
                    801:                                        if (ferror(cmd))
                    802:                                        {
                    803:                                                DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
                    804:                                                         verb, script->name, script->path);
                    805:                                        }
                    806:                                        break;
                    807:                                }
                    808:                                else
                    809:                                {
                    810:                                        pos = buf + strlen(buf);
                    811:                                        if (pos > buf && pos[-1] == '\n')
                    812:                                        {
                    813:                                                pos[-1] = '\0';
                    814:                                        }
                    815:                                        DBG1(DBG_DMN, "%s: %s", script->name, buf);
                    816:                                }
                    817:                        }
                    818:                        pclose(cmd);
                    819:                }
                    820:                free(script);
                    821:        }
                    822:        enumerator->destroy(enumerator);
                    823:        array_destroy(scripts);
                    824: }
                    825: 
                    826: METHOD(daemon_t, start, void,
                    827:           private_daemon_t *this)
                    828: {
                    829:        /* start the engine, go multithreaded */
                    830:        lib->processor->set_threads(lib->processor,
                    831:                                                lib->settings->get_int(lib->settings, "%s.threads",
                    832:                                                                                           DEFAULT_THREADS, lib->ns));
                    833: 
                    834:        run_scripts(this, "start");
                    835: }
                    836: 
                    837: /**
                    838:  * Initialize/deinitialize sender and receiver
                    839:  */
                    840: static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
                    841:                                                           bool reg, private_daemon_t *this)
                    842: {
                    843:        if (reg)
                    844:        {
                    845:                this->public.receiver = receiver_create();
                    846:                if (!this->public.receiver)
                    847:                {
                    848:                        return FALSE;
                    849:                }
                    850:                this->public.sender = sender_create();
                    851:        }
                    852:        else
                    853:        {
                    854:                DESTROY_IF(this->public.receiver);
                    855:                DESTROY_IF(this->public.sender);
                    856:        }
                    857:        return TRUE;
                    858: }
                    859: 
                    860: /**
                    861:  * Initialize/deinitialize IKE_SA/CHILD_SA managers
                    862:  */
                    863: static bool sa_managers_cb(void *plugin, plugin_feature_t *feature,
                    864:                                                   bool reg, private_daemon_t *this)
                    865: {
                    866:        if (reg)
                    867:        {
                    868:                this->public.ike_sa_manager = ike_sa_manager_create();
                    869:                if (!this->public.ike_sa_manager)
                    870:                {
                    871:                        return FALSE;
                    872:                }
                    873:                this->public.child_sa_manager = child_sa_manager_create();
                    874:        }
                    875:        else
                    876:        {
                    877:                DESTROY_IF(this->public.ike_sa_manager);
                    878:                DESTROY_IF(this->public.child_sa_manager);
                    879:        }
                    880:        return TRUE;
                    881: }
                    882: 
                    883: METHOD(daemon_t, initialize, bool,
                    884:        private_daemon_t *this, char *plugins)
                    885: {
                    886:        plugin_feature_t features[] = {
                    887:                PLUGIN_PROVIDE(CUSTOM, "libcharon"),
                    888:                        PLUGIN_DEPENDS(NONCE_GEN),
                    889:                        PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
                    890:                        PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
                    891:                        PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
                    892:                        PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
                    893:                PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
                    894:                        PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
                    895:                                PLUGIN_DEPENDS(HASHER, HASH_SHA1),
                    896:                                PLUGIN_DEPENDS(RNG, RNG_STRONG),
                    897:                                PLUGIN_DEPENDS(CUSTOM, "socket"),
                    898:                PLUGIN_CALLBACK((plugin_feature_callback_t)sa_managers_cb, this),
                    899:                        PLUGIN_PROVIDE(CUSTOM, "libcharon-sa-managers"),
                    900:                                PLUGIN_DEPENDS(HASHER, HASH_SHA1),
                    901:                                PLUGIN_DEPENDS(RNG, RNG_WEAK),
                    902:        };
                    903:        lib->plugins->add_static_features(lib->plugins, lib->ns, features,
                    904:                                                                          countof(features), TRUE, NULL, NULL);
                    905: 
                    906:        /* load plugins, further infrastructure may need it */
                    907:        if (!lib->plugins->load(lib->plugins, plugins))
                    908:        {
                    909:                return FALSE;
                    910:        }
                    911: 
                    912:        /* Queue start_action job */
                    913:        lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
                    914: 
                    915: #ifdef ME
                    916:        this->public.connect_manager = connect_manager_create();
                    917:        if (this->public.connect_manager == NULL)
                    918:        {
                    919:                return FALSE;
                    920:        }
                    921:        this->public.mediation_manager = mediation_manager_create();
                    922: #endif /* ME */
                    923: 
                    924:        return TRUE;
                    925: }
                    926: 
                    927: /**
                    928:  * Create the daemon.
                    929:  */
                    930: private_daemon_t *daemon_create()
                    931: {
                    932:        private_daemon_t *this;
                    933: 
                    934:        INIT(this,
                    935:                .public = {
                    936:                        .initialize = _initialize,
                    937:                        .start = _start,
                    938:                        .load_loggers = _load_loggers,
                    939:                        .set_default_loggers = _set_default_loggers,
                    940:                        .set_level = _set_level,
                    941:                        .bus = bus_create(),
                    942:                },
                    943:                .loggers = linked_list_create(),
                    944:                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
                    945:                .ref = 1,
                    946:        );
                    947:        charon = &this->public;
                    948:        this->public.kernel = kernel_interface_create();
                    949:        this->public.attributes = attribute_manager_create();
                    950:        this->public.controller = controller_create();
                    951:        this->public.eap = eap_manager_create();
                    952:        this->public.xauth = xauth_manager_create();
                    953:        this->public.backends = backend_manager_create();
                    954:        this->public.socket = socket_manager_create();
                    955:        this->public.traps = trap_manager_create();
                    956:        this->public.shunts = shunt_manager_create();
                    957:        this->public.redirect = redirect_manager_create();
                    958:        this->kernel_handler = kernel_handler_create();
                    959: 
                    960:        return this;
                    961: }
                    962: 
                    963: /**
                    964:  * Described in header.
                    965:  */
                    966: void libcharon_deinit()
                    967: {
                    968:        private_daemon_t *this = (private_daemon_t*)charon;
                    969: 
                    970:        if (!this || !ref_put(&this->ref))
                    971:        {       /* have more users */
                    972:                return;
                    973:        }
                    974: 
                    975:        run_scripts(this, "stop");
                    976: 
                    977:        destroy(this);
                    978:        charon = NULL;
                    979: }
                    980: 
                    981: /**
                    982:  * Described in header.
                    983:  */
                    984: bool libcharon_init()
                    985: {
                    986:        private_daemon_t *this;
                    987: 
                    988:        if (charon)
                    989:        {       /* already initialized, increase refcount */
                    990:                this = (private_daemon_t*)charon;
                    991:                ref_get(&this->ref);
                    992:                return !this->integrity_failed;
                    993:        }
                    994: 
                    995:        this = daemon_create();
                    996: 
                    997:        /* for uncritical pseudo random numbers */
                    998:        srandom(time(NULL) + getpid());
                    999: 
                   1000:        /* set up hook to log dbg message in library via charons message bus */
                   1001:        dbg_old = dbg;
                   1002:        dbg = dbg_bus;
                   1003: 
                   1004:        if (lib->integrity &&
                   1005:                !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
                   1006:        {
                   1007:                dbg(DBG_DMN, 1, "integrity check of libcharon failed");
                   1008:                this->integrity_failed = TRUE;
                   1009:        }
                   1010:        return !this->integrity_failed;
                   1011: }

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