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