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