Add plugin constructor registration for all libraries that provide plugins
[strongswan.git] / src / libcharon / daemon.c
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 <config/proposal.h>
59 #include <plugins/plugin_feature.h>
60 #include <kernel/kernel_handler.h>
61 #include <processing/jobs/start_action_job.h>
62 #include <threading/mutex.h>
63
64 #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
65 #define LOG_AUTHPRIV LOG_AUTH
66 #endif
67
68 typedef struct private_daemon_t private_daemon_t;
69
70 /**
71 * Private additions to daemon_t, contains threads and internal functions.
72 */
73 struct private_daemon_t {
74 /**
75 * Public members of daemon_t.
76 */
77 daemon_t public;
78
79 /**
80 * Handler for kernel events
81 */
82 kernel_handler_t *kernel_handler;
83
84 /**
85 * A list of installed loggers (as logger_entry_t*)
86 */
87 linked_list_t *loggers;
88
89 /**
90 * Cached log levels for default loggers
91 */
92 level_t *levels;
93
94 /**
95 * Whether to log to stdout/err by default
96 */
97 bool to_stderr;
98
99 /**
100 * Identifier used for syslog (in the openlog call)
101 */
102 char *syslog_identifier;
103
104 /**
105 * Mutex for configured loggers
106 */
107 mutex_t *mutex;
108
109 /**
110 * Integrity check failed?
111 */
112 bool integrity_failed;
113
114 /**
115 * Number of times we have been initialized
116 */
117 refcount_t ref;
118 };
119
120 /**
121 * Register plugins if built statically
122 */
123 #ifdef STATIC_PLUGIN_CONSTRUCTORS
124 #include "plugin_constructors.c"
125 #endif
126
127 /**
128 * One and only instance of the daemon.
129 */
130 daemon_t *charon;
131
132 /**
133 * hook in library for debugging messages
134 */
135 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
136
137 /**
138 * we store the previous debug function so we can reset it
139 */
140 static void (*dbg_old) (debug_t group, level_t level, char *fmt, ...);
141
142 /**
143 * Logging hook for library logs, spreads debug message over bus
144 */
145 static void dbg_bus(debug_t group, level_t level, char *fmt, ...)
146 {
147 va_list args;
148
149 va_start(args, fmt);
150 charon->bus->vlog(charon->bus, group, level, fmt, args);
151 va_end(args);
152 }
153
154 /**
155 * Data for registered custom loggers
156 */
157 typedef struct {
158 /**
159 * Name of the custom logger (also used for loglevel configuration)
160 */
161 char *name;
162
163 /**
164 * Constructor to be called for custom logger creation
165 */
166 custom_logger_constructor_t constructor;
167
168 } custom_logger_entry_t;
169
170 #define MAX_CUSTOM_LOGGERS 10
171
172 /**
173 * Static array for logger registration using __attribute__((constructor))
174 */
175 static custom_logger_entry_t custom_loggers[MAX_CUSTOM_LOGGERS];
176 static int custom_logger_count;
177
178 /**
179 * Described in header
180 */
181 void register_custom_logger(char *name,
182 custom_logger_constructor_t constructor)
183 {
184 if (custom_logger_count < MAX_CUSTOM_LOGGERS - 1)
185 {
186 custom_loggers[custom_logger_count].name = name;
187 custom_loggers[custom_logger_count].constructor = constructor;
188 custom_logger_count++;
189 }
190 else
191 {
192 fprintf(stderr, "failed to register custom logger, please increase "
193 "MAX_CUSTOM_LOGGERS");
194 }
195 }
196
197 /**
198 * Types of supported loggers
199 */
200 typedef enum {
201 /**
202 * Syslog logger instance
203 */
204 SYS_LOGGER,
205
206 /**
207 * File logger instance
208 */
209 FILE_LOGGER,
210
211 /**
212 * Custom logger instance
213 */
214 CUSTOM_LOGGER,
215
216 } logger_type_t;
217
218 /**
219 * Some metadata about configured loggers
220 */
221 typedef struct {
222 /**
223 * Target of the logger (syslog facility or filename)
224 */
225 char *target;
226
227 /**
228 * Type of logger
229 */
230 logger_type_t type;
231
232 /**
233 * The actual logger
234 */
235 union {
236 sys_logger_t *sys;
237 file_logger_t *file;
238 custom_logger_t *custom;
239 } logger;
240
241 } logger_entry_t;
242
243 /**
244 * Destroy a logger entry
245 */
246 static void logger_entry_destroy(logger_entry_t *this)
247 {
248 switch (this->type)
249 {
250 case FILE_LOGGER:
251 DESTROY_IF(this->logger.file);
252 break;
253 case SYS_LOGGER:
254 DESTROY_IF(this->logger.sys);
255 break;
256 case CUSTOM_LOGGER:
257 DESTROY_IF(this->logger.custom);
258 break;
259 }
260 free(this->target);
261 free(this);
262 }
263
264 /**
265 * Unregister and destroy a logger entry
266 */
267 static void logger_entry_unregister_destroy(logger_entry_t *this)
268 {
269 switch (this->type)
270 {
271 case FILE_LOGGER:
272 charon->bus->remove_logger(charon->bus, &this->logger.file->logger);
273 break;
274 case SYS_LOGGER:
275 charon->bus->remove_logger(charon->bus, &this->logger.sys->logger);
276 break;
277 case CUSTOM_LOGGER:
278 charon->bus->remove_logger(charon->bus,
279 &this->logger.custom->logger);
280 break;
281 }
282 logger_entry_destroy(this);
283 }
284
285 /**
286 * Match a logger entry by target and whether it is a file or syslog logger
287 */
288 static bool logger_entry_match(logger_entry_t *this, char *target,
289 logger_type_t *type)
290 {
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, (void*)logger_entry_match,
354 (void**)&entry, target, &type) != SUCCESS)
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 *filename,
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;
491
492 time_format = lib->settings->get_str(lib->settings,
493 "%s.filelog.%s.time_format", NULL, lib->ns, filename);
494 add_ms = lib->settings->get_bool(lib->settings,
495 "%s.filelog.%s.time_add_ms", FALSE, lib->ns, filename);
496 ike_name = lib->settings->get_bool(lib->settings,
497 "%s.filelog.%s.ike_name", FALSE, lib->ns, filename);
498 flush_line = lib->settings->get_bool(lib->settings,
499 "%s.filelog.%s.flush_line", FALSE, lib->ns, filename);
500 append = lib->settings->get_bool(lib->settings,
501 "%s.filelog.%s.append", TRUE, lib->ns, filename);
502
503 file_logger = add_file_logger(this, filename, current_loggers);
504 if (!file_logger)
505 {
506 return;
507 }
508
509 file_logger->set_options(file_logger, time_format, add_ms, ike_name);
510 file_logger->open(file_logger, flush_line, append);
511
512 def = lib->settings->get_int(lib->settings, "%s.filelog.%s.default", 1,
513 lib->ns, filename);
514 for (group = 0; group < DBG_MAX; group++)
515 {
516 file_logger->set_level(file_logger, group,
517 lib->settings->get_int(lib->settings, "%s.filelog.%s.%N", def,
518 lib->ns, filename, debug_lower_names, group));
519 }
520 charon->bus->add_logger(charon->bus, &file_logger->logger);
521 }
522
523 /**
524 * Load the given custom logger configured in strongswan.conf
525 */
526 static void load_custom_logger(private_daemon_t *this,
527 custom_logger_entry_t *entry,
528 linked_list_t *current_loggers)
529 {
530 custom_logger_t *custom_logger;
531 debug_t group;
532 level_t def;
533
534 custom_logger = add_custom_logger(this, entry, current_loggers);
535 if (!custom_logger)
536 {
537 return;
538 }
539
540 def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
541 lib->ns, entry->name);
542 for (group = 0; group < DBG_MAX; group++)
543 {
544 custom_logger->set_level(custom_logger, group,
545 lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
546 lib->ns, entry->name, debug_lower_names, group));
547 }
548 charon->bus->add_logger(charon->bus, &custom_logger->logger);
549 }
550
551 METHOD(daemon_t, load_loggers, void,
552 private_daemon_t *this)
553 {
554 enumerator_t *enumerator;
555 linked_list_t *current_loggers;
556 char *target;
557 int i;
558
559 this->mutex->lock(this->mutex);
560 handle_syslog_identifier(this);
561 current_loggers = this->loggers;
562 this->loggers = linked_list_create();
563 enumerator = lib->settings->create_section_enumerator(lib->settings,
564 "%s.syslog", lib->ns);
565 while (enumerator->enumerate(enumerator, &target))
566 {
567 load_sys_logger(this, target, current_loggers);
568 }
569 enumerator->destroy(enumerator);
570
571 enumerator = lib->settings->create_section_enumerator(lib->settings,
572 "%s.filelog", lib->ns);
573 while (enumerator->enumerate(enumerator, &target))
574 {
575 load_file_logger(this, target, current_loggers);
576 }
577 enumerator->destroy(enumerator);
578
579 for (i = 0; i < custom_logger_count; ++i)
580 {
581 load_custom_logger(this, &custom_loggers[i], current_loggers);
582 }
583
584 if (!this->loggers->get_count(this->loggers) && this->levels)
585 { /* setup legacy style default loggers configured via command-line */
586 file_logger_t *file_logger;
587 sys_logger_t *sys_logger;
588 debug_t group;
589
590 sys_logger = add_sys_logger(this, "daemon", current_loggers);
591 file_logger = add_file_logger(this, "stdout", current_loggers);
592 file_logger->open(file_logger, FALSE, FALSE);
593
594 for (group = 0; group < DBG_MAX; group++)
595 {
596 if (sys_logger)
597 {
598 sys_logger->set_level(sys_logger, group, this->levels[group]);
599 }
600 if (this->to_stderr)
601 {
602 file_logger->set_level(file_logger, group, this->levels[group]);
603 }
604 }
605 if (sys_logger)
606 {
607 charon->bus->add_logger(charon->bus, &sys_logger->logger);
608 }
609 charon->bus->add_logger(charon->bus, &file_logger->logger);
610
611 sys_logger = add_sys_logger(this, "auth", current_loggers);
612 if (sys_logger)
613 {
614 sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
615 charon->bus->add_logger(charon->bus, &sys_logger->logger);
616 }
617 }
618 /* unregister and destroy any unused remaining loggers */
619 current_loggers->destroy_function(current_loggers,
620 (void*)logger_entry_unregister_destroy);
621 this->mutex->unlock(this->mutex);
622 }
623
624 METHOD(daemon_t, set_default_loggers, void,
625 private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
626 {
627 debug_t group;
628
629 this->mutex->lock(this->mutex);
630 if (!levels)
631 {
632 free(this->levels);
633 this->levels = NULL;
634 }
635 else
636 {
637 if (!this->levels)
638 {
639 this->levels = calloc(sizeof(level_t), DBG_MAX);
640 }
641 for (group = 0; group < DBG_MAX; group++)
642 {
643 this->levels[group] = levels[group];
644 }
645 this->to_stderr = to_stderr;
646 }
647 this->mutex->unlock(this->mutex);
648 }
649
650 METHOD(daemon_t, set_level, void,
651 private_daemon_t *this, debug_t group, level_t level)
652 {
653 enumerator_t *enumerator;
654 logger_entry_t *entry;
655
656 /* we set the loglevel on ALL loggers */
657 this->mutex->lock(this->mutex);
658 enumerator = this->loggers->create_enumerator(this->loggers);
659 while (enumerator->enumerate(enumerator, &entry))
660 {
661 switch (entry->type)
662 {
663 case FILE_LOGGER:
664 entry->logger.file->set_level(entry->logger.file, group, level);
665 charon->bus->add_logger(charon->bus,
666 &entry->logger.file->logger);
667 break;
668 case SYS_LOGGER:
669 entry->logger.sys->set_level(entry->logger.sys, group, level);
670 charon->bus->add_logger(charon->bus,
671 &entry->logger.sys->logger);
672 break;
673 case CUSTOM_LOGGER:
674 entry->logger.custom->set_level(entry->logger.custom, group,
675 level);
676 charon->bus->add_logger(charon->bus,
677 &entry->logger.sys->logger);
678 break;
679 }
680 }
681 enumerator->destroy(enumerator);
682 this->mutex->unlock(this->mutex);
683 }
684
685 /**
686 * Clean up all daemon resources
687 */
688 static void destroy(private_daemon_t *this)
689 {
690 /* terminate all idle threads */
691 lib->processor->set_threads(lib->processor, 0);
692 /* make sure nobody waits for a DNS query */
693 lib->hosts->flush(lib->hosts);
694 /* close all IKE_SAs */
695 if (this->public.ike_sa_manager)
696 {
697 this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
698 }
699 if (this->public.traps)
700 {
701 this->public.traps->flush(this->public.traps);
702 }
703 if (this->public.shunts)
704 {
705 this->public.shunts->flush(this->public.shunts);
706 }
707 if (this->public.sender)
708 {
709 this->public.sender->flush(this->public.sender);
710 }
711
712 /* cancel all threads and wait for their termination */
713 lib->processor->cancel(lib->processor);
714
715 #ifdef ME
716 DESTROY_IF(this->public.connect_manager);
717 DESTROY_IF(this->public.mediation_manager);
718 #endif /* ME */
719 /* make sure the cache and scheduler are clear before unloading plugins */
720 lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
721 lib->scheduler->flush(lib->scheduler);
722 lib->plugins->unload(lib->plugins);
723 DESTROY_IF(this->public.attributes);
724 DESTROY_IF(this->kernel_handler);
725 DESTROY_IF(this->public.traps);
726 DESTROY_IF(this->public.shunts);
727 DESTROY_IF(this->public.redirect);
728 DESTROY_IF(this->public.controller);
729 DESTROY_IF(this->public.eap);
730 DESTROY_IF(this->public.xauth);
731 DESTROY_IF(this->public.backends);
732 DESTROY_IF(this->public.socket);
733 DESTROY_IF(this->public.kernel);
734
735 /* rehook library logging, shutdown logging */
736 dbg = dbg_old;
737 DESTROY_IF(this->public.bus);
738 this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
739 this->mutex->destroy(this->mutex);
740 free(this->levels);
741 free(this);
742 }
743
744 /**
745 * Run a set of configured scripts
746 */
747 static void run_scripts(private_daemon_t *this, char *verb)
748 {
749 struct {
750 char *name;
751 char *path;
752 } *script;
753 array_t *scripts = NULL;
754 enumerator_t *enumerator;
755 char *key, *value, *pos, buf[1024];
756 FILE *cmd;
757
758 /* copy the scripts so we don't hold any locks while executing them */
759 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
760 "%s.%s-scripts", lib->ns, verb);
761 while (enumerator->enumerate(enumerator, &key, &value))
762 {
763 INIT(script,
764 .name = key,
765 .path = value,
766 );
767 array_insert_create(&scripts, ARRAY_TAIL, script);
768 }
769 enumerator->destroy(enumerator);
770
771 enumerator = array_create_enumerator(scripts);
772 while (enumerator->enumerate(enumerator, &script))
773 {
774 DBG1(DBG_DMN, "executing %s script '%s' (%s)", verb, script->name,
775 script->path);
776 cmd = popen(script->path, "r");
777 if (!cmd)
778 {
779 DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
780 verb, script->name, script->path, strerror(errno));
781 }
782 else
783 {
784 while (TRUE)
785 {
786 if (!fgets(buf, sizeof(buf), cmd))
787 {
788 if (ferror(cmd))
789 {
790 DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
791 verb, script->name, script->path);
792 }
793 break;
794 }
795 else
796 {
797 pos = buf + strlen(buf);
798 if (pos > buf && pos[-1] == '\n')
799 {
800 pos[-1] = '\0';
801 }
802 DBG1(DBG_DMN, "%s: %s", script->name, buf);
803 }
804 }
805 pclose(cmd);
806 }
807 free(script);
808 }
809 enumerator->destroy(enumerator);
810 array_destroy(scripts);
811 }
812
813 METHOD(daemon_t, start, void,
814 private_daemon_t *this)
815 {
816 /* start the engine, go multithreaded */
817 lib->processor->set_threads(lib->processor,
818 lib->settings->get_int(lib->settings, "%s.threads",
819 DEFAULT_THREADS, lib->ns));
820
821 run_scripts(this, "start");
822 }
823
824 /**
825 * Initialize/deinitialize sender and receiver
826 */
827 static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
828 bool reg, private_daemon_t *this)
829 {
830 if (reg)
831 {
832 this->public.receiver = receiver_create();
833 if (!this->public.receiver)
834 {
835 return FALSE;
836 }
837 this->public.sender = sender_create();
838 }
839 else
840 {
841 DESTROY_IF(this->public.receiver);
842 DESTROY_IF(this->public.sender);
843 }
844 return TRUE;
845 }
846
847 /**
848 * Initialize/deinitialize IKE_SA/CHILD_SA managers
849 */
850 static bool sa_managers_cb(void *plugin, plugin_feature_t *feature,
851 bool reg, private_daemon_t *this)
852 {
853 if (reg)
854 {
855 this->public.ike_sa_manager = ike_sa_manager_create();
856 if (!this->public.ike_sa_manager)
857 {
858 return FALSE;
859 }
860 this->public.child_sa_manager = child_sa_manager_create();
861 }
862 else
863 {
864 DESTROY_IF(this->public.ike_sa_manager);
865 DESTROY_IF(this->public.child_sa_manager);
866 }
867 return TRUE;
868 }
869
870 METHOD(daemon_t, initialize, bool,
871 private_daemon_t *this, char *plugins)
872 {
873 plugin_feature_t features[] = {
874 PLUGIN_PROVIDE(CUSTOM, "libcharon"),
875 PLUGIN_DEPENDS(NONCE_GEN),
876 PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
877 PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
878 PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
879 PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
880 PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
881 PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
882 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
883 PLUGIN_DEPENDS(RNG, RNG_STRONG),
884 PLUGIN_DEPENDS(CUSTOM, "socket"),
885 PLUGIN_CALLBACK((plugin_feature_callback_t)sa_managers_cb, this),
886 PLUGIN_PROVIDE(CUSTOM, "libcharon-sa-managers"),
887 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
888 PLUGIN_DEPENDS(RNG, RNG_WEAK),
889 };
890 lib->plugins->add_static_features(lib->plugins, lib->ns, features,
891 countof(features), TRUE, NULL, NULL);
892
893 /* load plugins, further infrastructure may need it */
894 if (!lib->plugins->load(lib->plugins, plugins))
895 {
896 return FALSE;
897 }
898
899 /* Queue start_action job */
900 lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
901
902 #ifdef ME
903 this->public.connect_manager = connect_manager_create();
904 if (this->public.connect_manager == NULL)
905 {
906 return FALSE;
907 }
908 this->public.mediation_manager = mediation_manager_create();
909 #endif /* ME */
910
911 return TRUE;
912 }
913
914 /**
915 * Create the daemon.
916 */
917 private_daemon_t *daemon_create()
918 {
919 private_daemon_t *this;
920
921 INIT(this,
922 .public = {
923 .initialize = _initialize,
924 .start = _start,
925 .load_loggers = _load_loggers,
926 .set_default_loggers = _set_default_loggers,
927 .set_level = _set_level,
928 .bus = bus_create(),
929 },
930 .loggers = linked_list_create(),
931 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
932 .ref = 1,
933 );
934 charon = &this->public;
935 this->public.kernel = kernel_interface_create();
936 this->public.attributes = attribute_manager_create();
937 this->public.controller = controller_create();
938 this->public.eap = eap_manager_create();
939 this->public.xauth = xauth_manager_create();
940 this->public.backends = backend_manager_create();
941 this->public.socket = socket_manager_create();
942 this->public.traps = trap_manager_create();
943 this->public.shunts = shunt_manager_create();
944 this->public.redirect = redirect_manager_create();
945 this->kernel_handler = kernel_handler_create();
946
947 return this;
948 }
949
950 /**
951 * Described in header.
952 */
953 void libcharon_deinit()
954 {
955 private_daemon_t *this = (private_daemon_t*)charon;
956
957 if (!this || !ref_put(&this->ref))
958 { /* have more users */
959 return;
960 }
961
962 run_scripts(this, "stop");
963
964 destroy(this);
965 charon = NULL;
966 }
967
968 /**
969 * Described in header.
970 */
971 bool libcharon_init()
972 {
973 private_daemon_t *this;
974
975 if (charon)
976 { /* already initialized, increase refcount */
977 this = (private_daemon_t*)charon;
978 ref_get(&this->ref);
979 return !this->integrity_failed;
980 }
981
982 this = daemon_create();
983
984 /* for uncritical pseudo random numbers */
985 srandom(time(NULL) + getpid());
986
987 /* set up hook to log dbg message in library via charons message bus */
988 dbg_old = dbg;
989 dbg = dbg_bus;
990
991 lib->printf_hook->add_handler(lib->printf_hook, 'P',
992 proposal_printf_hook,
993 PRINTF_HOOK_ARGTYPE_POINTER,
994 PRINTF_HOOK_ARGTYPE_END);
995
996 if (lib->integrity &&
997 !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
998 {
999 dbg(DBG_DMN, 1, "integrity check of libcharon failed");
1000 this->integrity_failed = TRUE;
1001 }
1002 return !this->integrity_failed;
1003 }