Return to daemon.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon |
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: }