f861460dba38856d84dc7488b4c7d1bcee37e25d
[strongswan.git] / src / libcharon / daemon.c
1 /*
2 * Copyright (C) 2006-2015 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * Copyright (C) 2006 Daniel Roethlisberger
5 * Copyright (C) 2005 Jan Hutter
6 * 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 <config/proposal.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 * Identifier used for syslog (in the openlog call)
90 */
91 char *syslog_identifier;
92
93 /**
94 * Mutex for configured loggers
95 */
96 mutex_t *mutex;
97
98 /**
99 * Integrity check failed?
100 */
101 bool integrity_failed;
102
103 /**
104 * Number of times we have been initialized
105 */
106 refcount_t ref;
107 };
108
109 /**
110 * One and only instance of the daemon.
111 */
112 daemon_t *charon;
113
114 /**
115 * hook in library for debugging messages
116 */
117 extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
118
119 /**
120 * we store the previous debug function so we can reset it
121 */
122 static void (*dbg_old) (debug_t group, level_t level, char *fmt, ...);
123
124 /**
125 * Logging hook for library logs, spreads debug message over bus
126 */
127 static void dbg_bus(debug_t group, level_t level, char *fmt, ...)
128 {
129 va_list args;
130
131 va_start(args, fmt);
132 charon->bus->vlog(charon->bus, group, level, fmt, args);
133 va_end(args);
134 }
135
136 /**
137 * Data for registered custom loggers
138 */
139 typedef struct {
140 /**
141 * Name of the custom logger (also used for loglevel configuration)
142 */
143 char *name;
144
145 /**
146 * Constructor to be called for custom logger creation
147 */
148 custom_logger_constructor_t constructor;
149
150 } custom_logger_entry_t;
151
152 #define MAX_CUSTOM_LOGGERS 10
153
154 /**
155 * Static array for logger registration using __attribute__((constructor))
156 */
157 static custom_logger_entry_t custom_loggers[MAX_CUSTOM_LOGGERS];
158 static int custom_logger_count;
159
160 /**
161 * Described in header
162 */
163 void register_custom_logger(char *name,
164 custom_logger_constructor_t constructor)
165 {
166 if (custom_logger_count < MAX_CUSTOM_LOGGERS - 1)
167 {
168 custom_loggers[custom_logger_count].name = name;
169 custom_loggers[custom_logger_count].constructor = constructor;
170 custom_logger_count++;
171 }
172 else
173 {
174 fprintf(stderr, "failed to register custom logger, please increase "
175 "MAX_CUSTOM_LOGGERS");
176 }
177 }
178
179 /**
180 * Types of supported loggers
181 */
182 typedef enum {
183 /**
184 * Syslog logger instance
185 */
186 SYS_LOGGER,
187
188 /**
189 * File logger instance
190 */
191 FILE_LOGGER,
192
193 /**
194 * Custom logger instance
195 */
196 CUSTOM_LOGGER,
197
198 } logger_type_t;
199
200 /**
201 * Some metadata about configured loggers
202 */
203 typedef struct {
204 /**
205 * Target of the logger (syslog facility or filename)
206 */
207 char *target;
208
209 /**
210 * Type of logger
211 */
212 logger_type_t type;
213
214 /**
215 * The actual logger
216 */
217 union {
218 sys_logger_t *sys;
219 file_logger_t *file;
220 custom_logger_t *custom;
221 } logger;
222
223 } logger_entry_t;
224
225 /**
226 * Destroy a logger entry
227 */
228 static void logger_entry_destroy(logger_entry_t *this)
229 {
230 switch (this->type)
231 {
232 case FILE_LOGGER:
233 DESTROY_IF(this->logger.file);
234 break;
235 case SYS_LOGGER:
236 DESTROY_IF(this->logger.sys);
237 break;
238 case CUSTOM_LOGGER:
239 DESTROY_IF(this->logger.custom);
240 break;
241 }
242 free(this->target);
243 free(this);
244 }
245
246 /**
247 * Unregister and destroy a logger entry
248 */
249 static void logger_entry_unregister_destroy(logger_entry_t *this)
250 {
251 switch (this->type)
252 {
253 case FILE_LOGGER:
254 charon->bus->remove_logger(charon->bus, &this->logger.file->logger);
255 break;
256 case SYS_LOGGER:
257 charon->bus->remove_logger(charon->bus, &this->logger.sys->logger);
258 break;
259 case CUSTOM_LOGGER:
260 charon->bus->remove_logger(charon->bus,
261 &this->logger.custom->logger);
262 break;
263 }
264 logger_entry_destroy(this);
265 }
266
267 /**
268 * Match a logger entry by target and whether it is a file or syslog logger
269 */
270 static bool logger_entry_match(logger_entry_t *this, char *target,
271 logger_type_t *type)
272 {
273 return this->type == *type && streq(this->target, target);
274 }
275
276 /**
277 * Handle configured syslog identifier
278 *
279 * mutex must be locked when calling this function
280 */
281 static void handle_syslog_identifier(private_daemon_t *this)
282 {
283 #ifdef HAVE_SYSLOG
284 char *identifier;
285
286 identifier = lib->settings->get_str(lib->settings, "%s.syslog.identifier",
287 NULL, lib->ns);
288 if (identifier)
289 { /* set identifier, which is prepended to each log line */
290 if (!this->syslog_identifier ||
291 !streq(identifier, this->syslog_identifier))
292 {
293 closelog();
294 this->syslog_identifier = identifier;
295 openlog(this->syslog_identifier, 0, 0);
296 }
297 }
298 else if (this->syslog_identifier)
299 {
300 closelog();
301 this->syslog_identifier = NULL;
302 }
303 #endif /* HAVE_SYSLOG */
304 }
305
306 /**
307 * Convert the given string into a syslog facility, returns -1 if the facility
308 * is not supported
309 */
310 static int get_syslog_facility(char *facility)
311 {
312 #ifdef HAVE_SYSLOG
313 if (streq(facility, "daemon"))
314 {
315 return LOG_DAEMON;
316 }
317 else if (streq(facility, "auth"))
318 {
319 return LOG_AUTHPRIV;
320 }
321 #endif /* HAVE_SYSLOG */
322 return -1;
323 }
324
325 /**
326 * Returns an existing or newly created logger entry (if found, it is removed
327 * from the given linked list of existing loggers)
328 */
329 static logger_entry_t *get_logger_entry(char *target, logger_type_t type,
330 linked_list_t *existing,
331 custom_logger_constructor_t constructor)
332 {
333 logger_entry_t *entry;
334
335 if (existing->find_first(existing, (void*)logger_entry_match,
336 (void**)&entry, target, &type) != SUCCESS)
337 {
338 INIT(entry,
339 .target = strdup(target),
340 .type = type,
341 );
342 switch (type)
343 {
344 case FILE_LOGGER:
345 entry->logger.file = file_logger_create(target);
346 break;
347 case SYS_LOGGER:
348 #ifdef HAVE_SYSLOG
349 entry->logger.sys = sys_logger_create(
350 get_syslog_facility(target));
351 break;
352 #else
353 free(entry);
354 return NULL;
355 #endif /* HAVE_SYSLOG */
356 case CUSTOM_LOGGER:
357 if (constructor)
358 {
359 entry->logger.custom = constructor(target);
360 }
361 if (!entry->logger.custom)
362 {
363 free(entry);
364 return NULL;
365 }
366 break;
367 }
368 }
369 else
370 {
371 existing->remove(existing, entry, NULL);
372 }
373 return entry;
374 }
375
376 /**
377 * Create or reuse a syslog logger
378 */
379 static sys_logger_t *add_sys_logger(private_daemon_t *this, char *facility,
380 linked_list_t *current_loggers)
381 {
382 logger_entry_t *entry;
383
384 entry = get_logger_entry(facility, SYS_LOGGER, current_loggers, NULL);
385 if (entry)
386 {
387 this->loggers->insert_last(this->loggers, entry);
388 }
389 return entry ? entry->logger.sys : NULL;
390 }
391
392 /**
393 * Create or reuse a file logger
394 */
395 static file_logger_t *add_file_logger(private_daemon_t *this, char *filename,
396 linked_list_t *current_loggers)
397 {
398 logger_entry_t *entry;
399
400 entry = get_logger_entry(filename, FILE_LOGGER, current_loggers, NULL);
401 if (entry)
402 {
403 this->loggers->insert_last(this->loggers, entry);
404 }
405 return entry ? entry->logger.file : NULL;
406 }
407
408 /**
409 * Create or reuse a custom logger
410 */
411 static custom_logger_t *add_custom_logger(private_daemon_t *this,
412 custom_logger_entry_t *custom,
413 linked_list_t *current_loggers)
414 {
415 logger_entry_t *entry;
416
417 entry = get_logger_entry(custom->name, CUSTOM_LOGGER, current_loggers,
418 custom->constructor);
419 if (entry)
420 {
421 this->loggers->insert_last(this->loggers, entry);
422 }
423 return entry ? entry->logger.custom : NULL;
424 }
425
426 /**
427 * Load the given syslog logger configured in strongswan.conf
428 */
429 static void load_sys_logger(private_daemon_t *this, char *facility,
430 linked_list_t *current_loggers)
431 {
432 sys_logger_t *sys_logger;
433 debug_t group;
434 level_t def;
435
436 if (get_syslog_facility(facility) == -1)
437 {
438 return;
439 }
440
441 sys_logger = add_sys_logger(this, facility, current_loggers);
442 if (!sys_logger)
443 {
444 return;
445 }
446
447 sys_logger->set_options(sys_logger,
448 lib->settings->get_bool(lib->settings, "%s.syslog.%s.ike_name",
449 FALSE, lib->ns, facility));
450
451 def = lib->settings->get_int(lib->settings, "%s.syslog.%s.default", 1,
452 lib->ns, facility);
453 for (group = 0; group < DBG_MAX; group++)
454 {
455 sys_logger->set_level(sys_logger, group,
456 lib->settings->get_int(lib->settings, "%s.syslog.%s.%N", def,
457 lib->ns, facility, debug_lower_names, group));
458 }
459 charon->bus->add_logger(charon->bus, &sys_logger->logger);
460 }
461
462 /**
463 * Load the given file logger configured in strongswan.conf
464 */
465 static void load_file_logger(private_daemon_t *this, char *filename,
466 linked_list_t *current_loggers)
467 {
468 file_logger_t *file_logger;
469 debug_t group;
470 level_t def;
471 bool add_ms, ike_name, flush_line, append;
472 char *time_format;
473
474 time_format = lib->settings->get_str(lib->settings,
475 "%s.filelog.%s.time_format", NULL, lib->ns, filename);
476 add_ms = lib->settings->get_bool(lib->settings,
477 "%s.filelog.%s.time_add_ms", FALSE, lib->ns, filename);
478 ike_name = lib->settings->get_bool(lib->settings,
479 "%s.filelog.%s.ike_name", FALSE, lib->ns, filename);
480 flush_line = lib->settings->get_bool(lib->settings,
481 "%s.filelog.%s.flush_line", FALSE, lib->ns, filename);
482 append = lib->settings->get_bool(lib->settings,
483 "%s.filelog.%s.append", TRUE, lib->ns, filename);
484
485 file_logger = add_file_logger(this, filename, current_loggers);
486 if (!file_logger)
487 {
488 return;
489 }
490
491 file_logger->set_options(file_logger, time_format, add_ms, ike_name);
492 file_logger->open(file_logger, flush_line, append);
493
494 def = lib->settings->get_int(lib->settings, "%s.filelog.%s.default", 1,
495 lib->ns, filename);
496 for (group = 0; group < DBG_MAX; group++)
497 {
498 file_logger->set_level(file_logger, group,
499 lib->settings->get_int(lib->settings, "%s.filelog.%s.%N", def,
500 lib->ns, filename, debug_lower_names, group));
501 }
502 charon->bus->add_logger(charon->bus, &file_logger->logger);
503 }
504
505 /**
506 * Load the given custom logger configured in strongswan.conf
507 */
508 static void load_custom_logger(private_daemon_t *this,
509 custom_logger_entry_t *entry,
510 linked_list_t *current_loggers)
511 {
512 custom_logger_t *custom_logger;
513 debug_t group;
514 level_t def;
515
516 custom_logger = add_custom_logger(this, entry, current_loggers);
517 if (!custom_logger)
518 {
519 return;
520 }
521
522 def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
523 lib->ns, entry->name);
524 for (group = 0; group < DBG_MAX; group++)
525 {
526 custom_logger->set_level(custom_logger, group,
527 lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
528 lib->ns, entry->name, debug_lower_names, group));
529 }
530 charon->bus->add_logger(charon->bus, &custom_logger->logger);
531 }
532
533 METHOD(daemon_t, load_loggers, void,
534 private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
535 {
536 enumerator_t *enumerator;
537 linked_list_t *current_loggers;
538 char *target;
539 int i;
540
541 this->mutex->lock(this->mutex);
542 handle_syslog_identifier(this);
543 current_loggers = this->loggers;
544 this->loggers = linked_list_create();
545 enumerator = lib->settings->create_section_enumerator(lib->settings,
546 "%s.syslog", lib->ns);
547 while (enumerator->enumerate(enumerator, &target))
548 {
549 load_sys_logger(this, target, current_loggers);
550 }
551 enumerator->destroy(enumerator);
552
553 enumerator = lib->settings->create_section_enumerator(lib->settings,
554 "%s.filelog", lib->ns);
555 while (enumerator->enumerate(enumerator, &target))
556 {
557 load_file_logger(this, target, current_loggers);
558 }
559 enumerator->destroy(enumerator);
560
561 for (i = 0; i < custom_logger_count; ++i)
562 {
563 load_custom_logger(this, &custom_loggers[i], current_loggers);
564 }
565
566 if (!this->loggers->get_count(this->loggers) && levels)
567 { /* setup legacy style default loggers configured via command-line */
568 file_logger_t *file_logger;
569 sys_logger_t *sys_logger;
570 debug_t group;
571
572 sys_logger = add_sys_logger(this, "daemon", current_loggers);
573 file_logger = add_file_logger(this, "stdout", current_loggers);
574 file_logger->open(file_logger, FALSE, FALSE);
575
576 for (group = 0; group < DBG_MAX; group++)
577 {
578 if (sys_logger)
579 {
580 sys_logger->set_level(sys_logger, group, levels[group]);
581 }
582 if (to_stderr)
583 {
584 file_logger->set_level(file_logger, group, levels[group]);
585 }
586 }
587 if (sys_logger)
588 {
589 charon->bus->add_logger(charon->bus, &sys_logger->logger);
590 }
591 charon->bus->add_logger(charon->bus, &file_logger->logger);
592
593 sys_logger = add_sys_logger(this, "auth", current_loggers);
594 if (sys_logger)
595 {
596 sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
597 charon->bus->add_logger(charon->bus, &sys_logger->logger);
598 }
599 }
600 /* unregister and destroy any unused remaining loggers */
601 current_loggers->destroy_function(current_loggers,
602 (void*)logger_entry_unregister_destroy);
603 this->mutex->unlock(this->mutex);
604 }
605
606 METHOD(daemon_t, set_level, void,
607 private_daemon_t *this, debug_t group, level_t level)
608 {
609 enumerator_t *enumerator;
610 logger_entry_t *entry;
611
612 /* we set the loglevel on ALL sys- and file-loggers */
613 this->mutex->lock(this->mutex);
614 enumerator = this->loggers->create_enumerator(this->loggers);
615 while (enumerator->enumerate(enumerator, &entry))
616 {
617 switch (entry->type)
618 {
619 case FILE_LOGGER:
620 entry->logger.file->set_level(entry->logger.file, group, level);
621 charon->bus->add_logger(charon->bus,
622 &entry->logger.file->logger);
623 break;
624 case SYS_LOGGER:
625 entry->logger.sys->set_level(entry->logger.sys, group, level);
626 charon->bus->add_logger(charon->bus,
627 &entry->logger.sys->logger);
628 break;
629 case CUSTOM_LOGGER:
630 entry->logger.custom->set_level(entry->logger.custom, group,
631 level);
632 charon->bus->add_logger(charon->bus,
633 &entry->logger.sys->logger);
634 break;
635 }
636 }
637 enumerator->destroy(enumerator);
638 this->mutex->unlock(this->mutex);
639 }
640
641 /**
642 * Clean up all daemon resources
643 */
644 static void destroy(private_daemon_t *this)
645 {
646 /* terminate all idle threads */
647 lib->processor->set_threads(lib->processor, 0);
648 /* make sure nobody waits for a DNS query */
649 lib->hosts->flush(lib->hosts);
650 /* close all IKE_SAs */
651 if (this->public.ike_sa_manager)
652 {
653 this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
654 }
655 if (this->public.traps)
656 {
657 this->public.traps->flush(this->public.traps);
658 }
659 if (this->public.shunts)
660 {
661 this->public.shunts->flush(this->public.shunts);
662 }
663 if (this->public.sender)
664 {
665 this->public.sender->flush(this->public.sender);
666 }
667
668 /* cancel all threads and wait for their termination */
669 lib->processor->cancel(lib->processor);
670
671 #ifdef ME
672 DESTROY_IF(this->public.connect_manager);
673 DESTROY_IF(this->public.mediation_manager);
674 #endif /* ME */
675 /* make sure the cache and scheduler are clear before unloading plugins */
676 lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
677 lib->scheduler->flush(lib->scheduler);
678 lib->plugins->unload(lib->plugins);
679 DESTROY_IF(this->public.attributes);
680 DESTROY_IF(this->kernel_handler);
681 DESTROY_IF(this->public.traps);
682 DESTROY_IF(this->public.shunts);
683 DESTROY_IF(this->public.controller);
684 DESTROY_IF(this->public.eap);
685 DESTROY_IF(this->public.xauth);
686 DESTROY_IF(this->public.backends);
687 DESTROY_IF(this->public.socket);
688
689 /* rehook library logging, shutdown logging */
690 dbg = dbg_old;
691 DESTROY_IF(this->public.bus);
692 this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
693 this->mutex->destroy(this->mutex);
694 free(this);
695 }
696
697 /**
698 * Run a set of configured scripts
699 */
700 static void run_scripts(private_daemon_t *this, char *verb)
701 {
702 enumerator_t *enumerator;
703 char *key, *value, *pos, buf[1024];
704 FILE *cmd;
705
706 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
707 "%s.%s-scripts", lib->ns, verb);
708 while (enumerator->enumerate(enumerator, &key, &value))
709 {
710 DBG1(DBG_DMN, "executing %s script '%s' (%s):", verb, key, value);
711 cmd = popen(value, "r");
712 if (!cmd)
713 {
714 DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
715 verb, key, value, strerror(errno));
716 continue;
717 }
718 while (TRUE)
719 {
720 if (!fgets(buf, sizeof(buf), cmd))
721 {
722 if (ferror(cmd))
723 {
724 DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
725 verb, key, value);
726 }
727 break;
728 }
729 else
730 {
731 pos = buf + strlen(buf);
732 if (pos > buf && pos[-1] == '\n')
733 {
734 pos[-1] = '\0';
735 }
736 DBG1(DBG_DMN, "%s: %s", key, buf);
737 }
738 }
739 pclose(cmd);
740 }
741 enumerator->destroy(enumerator);
742 }
743
744 METHOD(daemon_t, start, void,
745 private_daemon_t *this)
746 {
747 /* start the engine, go multithreaded */
748 lib->processor->set_threads(lib->processor,
749 lib->settings->get_int(lib->settings, "%s.threads",
750 DEFAULT_THREADS, lib->ns));
751
752 run_scripts(this, "start");
753 }
754
755 /**
756 * Initialize/deinitialize sender and receiver
757 */
758 static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
759 bool reg, private_daemon_t *this)
760 {
761 if (reg)
762 {
763 this->public.receiver = receiver_create();
764 if (!this->public.receiver)
765 {
766 return FALSE;
767 }
768 this->public.sender = sender_create();
769 }
770 else
771 {
772 DESTROY_IF(this->public.receiver);
773 DESTROY_IF(this->public.sender);
774 }
775 return TRUE;
776 }
777
778 /**
779 * Initialize/deinitialize IKE_SA/CHILD_SA managers
780 */
781 static bool sa_managers_cb(void *plugin, plugin_feature_t *feature,
782 bool reg, private_daemon_t *this)
783 {
784 if (reg)
785 {
786 this->public.ike_sa_manager = ike_sa_manager_create();
787 if (!this->public.ike_sa_manager)
788 {
789 return FALSE;
790 }
791 this->public.child_sa_manager = child_sa_manager_create();
792 }
793 else
794 {
795 DESTROY_IF(this->public.ike_sa_manager);
796 DESTROY_IF(this->public.child_sa_manager);
797 }
798 return TRUE;
799 }
800
801 METHOD(daemon_t, initialize, bool,
802 private_daemon_t *this, char *plugins)
803 {
804 plugin_feature_t features[] = {
805 PLUGIN_PROVIDE(CUSTOM, "libcharon"),
806 PLUGIN_DEPENDS(NONCE_GEN),
807 PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
808 PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
809 PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
810 PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
811 PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
812 PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
813 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
814 PLUGIN_DEPENDS(RNG, RNG_STRONG),
815 PLUGIN_DEPENDS(CUSTOM, "socket"),
816 PLUGIN_CALLBACK((plugin_feature_callback_t)sa_managers_cb, this),
817 PLUGIN_PROVIDE(CUSTOM, "libcharon-sa-managers"),
818 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
819 PLUGIN_DEPENDS(RNG, RNG_WEAK),
820 };
821 lib->plugins->add_static_features(lib->plugins, lib->ns, features,
822 countof(features), TRUE, NULL, NULL);
823
824 /* load plugins, further infrastructure may need it */
825 if (!lib->plugins->load(lib->plugins, plugins))
826 {
827 return FALSE;
828 }
829
830 /* Queue start_action job */
831 lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
832
833 #ifdef ME
834 this->public.connect_manager = connect_manager_create();
835 if (this->public.connect_manager == NULL)
836 {
837 return FALSE;
838 }
839 this->public.mediation_manager = mediation_manager_create();
840 #endif /* ME */
841
842 return TRUE;
843 }
844
845 /**
846 * Create the daemon.
847 */
848 private_daemon_t *daemon_create()
849 {
850 private_daemon_t *this;
851
852 INIT(this,
853 .public = {
854 .initialize = _initialize,
855 .start = _start,
856 .load_loggers = _load_loggers,
857 .set_level = _set_level,
858 .bus = bus_create(),
859 },
860 .loggers = linked_list_create(),
861 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
862 .ref = 1,
863 );
864 charon = &this->public;
865 this->public.attributes = attribute_manager_create();
866 this->public.controller = controller_create();
867 this->public.eap = eap_manager_create();
868 this->public.xauth = xauth_manager_create();
869 this->public.backends = backend_manager_create();
870 this->public.socket = socket_manager_create();
871 this->public.traps = trap_manager_create();
872 this->public.shunts = shunt_manager_create();
873 this->kernel_handler = kernel_handler_create();
874
875 return this;
876 }
877
878 /**
879 * Described in header.
880 */
881 void libcharon_deinit()
882 {
883 private_daemon_t *this = (private_daemon_t*)charon;
884
885 if (!this || !ref_put(&this->ref))
886 { /* have more users */
887 return;
888 }
889
890 run_scripts(this, "stop");
891
892 destroy(this);
893 charon = NULL;
894 }
895
896 /**
897 * Described in header.
898 */
899 bool libcharon_init()
900 {
901 private_daemon_t *this;
902
903 if (charon)
904 { /* already initialized, increase refcount */
905 this = (private_daemon_t*)charon;
906 ref_get(&this->ref);
907 return !this->integrity_failed;
908 }
909
910 this = daemon_create();
911
912 /* for uncritical pseudo random numbers */
913 srandom(time(NULL) + getpid());
914
915 /* set up hook to log dbg message in library via charons message bus */
916 dbg_old = dbg;
917 dbg = dbg_bus;
918
919 lib->printf_hook->add_handler(lib->printf_hook, 'P',
920 proposal_printf_hook,
921 PRINTF_HOOK_ARGTYPE_POINTER,
922 PRINTF_HOOK_ARGTYPE_END);
923
924 if (lib->integrity &&
925 !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
926 {
927 dbg(DBG_DMN, 1, "integrity check of libcharon failed");
928 this->integrity_failed = TRUE;
929 }
930 return !this->integrity_failed;
931 }