File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / daemon.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:20:08 2021 UTC (3 years, 8 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, HEAD
strongswan 5.9.2

    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: 	bool ike_name, log_level;
  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: 
  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);
  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;
  493: 	bool add_ms, ike_name, log_level, flush_line, append;
  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);
  502: 	log_level = lib->settings->get_bool(lib->settings,
  503: 						"%s.filelog.%s.log_level", FALSE, lib->ns, section);
  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: 
  517: 	file_logger->set_options(file_logger, time_format, add_ms, ike_name,
  518: 							 log_level);
  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>