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>