ikev2: Return to the original host if connection fails after redirection
[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 <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
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 *section,
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, *filename;
491
492 time_format = lib->settings->get_str(lib->settings,
493 "%s.filelog.%s.time_format", NULL, lib->ns, section);
494 add_ms = lib->settings->get_bool(lib->settings,
495 "%s.filelog.%s.time_add_ms", FALSE, lib->ns, section);
496 ike_name = lib->settings->get_bool(lib->settings,
497 "%s.filelog.%s.ike_name", FALSE, lib->ns, section);
498 flush_line = lib->settings->get_bool(lib->settings,
499 "%s.filelog.%s.flush_line", FALSE, lib->ns, section);
500 append = lib->settings->get_bool(lib->settings,
501 "%s.filelog.%s.append", TRUE, lib->ns, section);
502 filename = lib->settings->get_str(lib->settings,
503 "%s.filelog.%s.path", section, lib->ns, section);
504
505 file_logger = add_file_logger(this, filename, current_loggers);
506 if (!file_logger)
507 {
508 return;
509 }
510
511 file_logger->set_options(file_logger, time_format, add_ms, ike_name);
512 file_logger->open(file_logger, flush_line, append);
513
514 def = lib->settings->get_int(lib->settings, "%s.filelog.%s.default", 1,
515 lib->ns, section);
516 for (group = 0; group < DBG_MAX; group++)
517 {
518 file_logger->set_level(file_logger, group,
519 lib->settings->get_int(lib->settings, "%s.filelog.%s.%N", def,
520 lib->ns, section, debug_lower_names, group));
521 }
522 charon->bus->add_logger(charon->bus, &file_logger->logger);
523 }
524
525 /**
526 * Load the given custom logger configured in strongswan.conf
527 */
528 static void load_custom_logger(private_daemon_t *this,
529 custom_logger_entry_t *entry,
530 linked_list_t *current_loggers)
531 {
532 custom_logger_t *custom_logger;
533 debug_t group;
534 level_t def;
535
536 custom_logger = add_custom_logger(this, entry, current_loggers);
537 if (!custom_logger)
538 {
539 return;
540 }
541
542 def = lib->settings->get_int(lib->settings, "%s.customlog.%s.default", 1,
543 lib->ns, entry->name);
544 for (group = 0; group < DBG_MAX; group++)
545 {
546 custom_logger->set_level(custom_logger, group,
547 lib->settings->get_int(lib->settings, "%s.customlog.%s.%N", def,
548 lib->ns, entry->name, debug_lower_names, group));
549 }
550 if (custom_logger->reload)
551 {
552 custom_logger->reload(custom_logger);
553 }
554 charon->bus->add_logger(charon->bus, &custom_logger->logger);
555 }
556
557 METHOD(daemon_t, load_loggers, void,
558 private_daemon_t *this)
559 {
560 enumerator_t *enumerator;
561 linked_list_t *current_loggers;
562 char *target;
563 int i;
564
565 this->mutex->lock(this->mutex);
566 handle_syslog_identifier(this);
567 current_loggers = this->loggers;
568 this->loggers = linked_list_create();
569 enumerator = lib->settings->create_section_enumerator(lib->settings,
570 "%s.syslog", lib->ns);
571 while (enumerator->enumerate(enumerator, &target))
572 {
573 load_sys_logger(this, target, current_loggers);
574 }
575 enumerator->destroy(enumerator);
576
577 enumerator = lib->settings->create_section_enumerator(lib->settings,
578 "%s.filelog", lib->ns);
579 while (enumerator->enumerate(enumerator, &target))
580 {
581 load_file_logger(this, target, current_loggers);
582 }
583 enumerator->destroy(enumerator);
584
585 for (i = 0; i < custom_logger_count; ++i)
586 {
587 load_custom_logger(this, &custom_loggers[i], current_loggers);
588 }
589
590 if (!this->loggers->get_count(this->loggers) && this->levels)
591 { /* setup legacy style default loggers configured via command-line */
592 file_logger_t *file_logger;
593 sys_logger_t *sys_logger;
594 debug_t group;
595
596 sys_logger = add_sys_logger(this, "daemon", current_loggers);
597 file_logger = add_file_logger(this, "stdout", current_loggers);
598 file_logger->open(file_logger, FALSE, FALSE);
599
600 for (group = 0; group < DBG_MAX; group++)
601 {
602 if (sys_logger)
603 {
604 sys_logger->set_level(sys_logger, group, this->levels[group]);
605 }
606 if (this->to_stderr)
607 {
608 file_logger->set_level(file_logger, group, this->levels[group]);
609 }
610 }
611 if (sys_logger)
612 {
613 charon->bus->add_logger(charon->bus, &sys_logger->logger);
614 }
615 charon->bus->add_logger(charon->bus, &file_logger->logger);
616
617 sys_logger = add_sys_logger(this, "auth", current_loggers);
618 if (sys_logger)
619 {
620 sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
621 charon->bus->add_logger(charon->bus, &sys_logger->logger);
622 }
623 }
624 /* unregister and destroy any unused remaining loggers */
625 current_loggers->destroy_function(current_loggers,
626 (void*)logger_entry_unregister_destroy);
627 this->mutex->unlock(this->mutex);
628 }
629
630 METHOD(daemon_t, set_default_loggers, void,
631 private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
632 {
633 debug_t group;
634
635 this->mutex->lock(this->mutex);
636 if (!levels)
637 {
638 free(this->levels);
639 this->levels = NULL;
640 }
641 else
642 {
643 if (!this->levels)
644 {
645 this->levels = calloc(sizeof(level_t), DBG_MAX);
646 }
647 for (group = 0; group < DBG_MAX; group++)
648 {
649 this->levels[group] = levels[group];
650 }
651 this->to_stderr = to_stderr;
652 }
653 this->mutex->unlock(this->mutex);
654 }
655
656 METHOD(daemon_t, set_level, void,
657 private_daemon_t *this, debug_t group, level_t level)
658 {
659 enumerator_t *enumerator;
660 logger_entry_t *entry;
661
662 /* we set the loglevel on ALL loggers */
663 this->mutex->lock(this->mutex);
664 enumerator = this->loggers->create_enumerator(this->loggers);
665 while (enumerator->enumerate(enumerator, &entry))
666 {
667 switch (entry->type)
668 {
669 case FILE_LOGGER:
670 entry->logger.file->set_level(entry->logger.file, group, level);
671 charon->bus->add_logger(charon->bus,
672 &entry->logger.file->logger);
673 break;
674 case SYS_LOGGER:
675 entry->logger.sys->set_level(entry->logger.sys, group, level);
676 charon->bus->add_logger(charon->bus,
677 &entry->logger.sys->logger);
678 break;
679 case CUSTOM_LOGGER:
680 entry->logger.custom->set_level(entry->logger.custom, group,
681 level);
682 charon->bus->add_logger(charon->bus,
683 &entry->logger.custom->logger);
684 break;
685 }
686 }
687 enumerator->destroy(enumerator);
688 this->mutex->unlock(this->mutex);
689 }
690
691 /**
692 * Clean up all daemon resources
693 */
694 static void destroy(private_daemon_t *this)
695 {
696 /* terminate all idle threads */
697 lib->processor->set_threads(lib->processor, 0);
698 /* make sure nobody waits for a DNS query */
699 lib->hosts->flush(lib->hosts);
700 /* close all IKE_SAs */
701 if (this->public.ike_sa_manager)
702 {
703 this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
704 }
705 if (this->public.traps)
706 {
707 this->public.traps->flush(this->public.traps);
708 }
709 if (this->public.shunts)
710 {
711 this->public.shunts->flush(this->public.shunts);
712 }
713 if (this->public.sender)
714 {
715 this->public.sender->flush(this->public.sender);
716 }
717
718 /* cancel all threads and wait for their termination */
719 lib->processor->cancel(lib->processor);
720
721 #ifdef ME
722 DESTROY_IF(this->public.connect_manager);
723 DESTROY_IF(this->public.mediation_manager);
724 #endif /* ME */
725 /* make sure the cache and scheduler are clear before unloading plugins */
726 lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
727 lib->scheduler->flush(lib->scheduler);
728 lib->plugins->unload(lib->plugins);
729 DESTROY_IF(this->public.attributes);
730 DESTROY_IF(this->kernel_handler);
731 DESTROY_IF(this->public.traps);
732 DESTROY_IF(this->public.shunts);
733 DESTROY_IF(this->public.redirect);
734 DESTROY_IF(this->public.controller);
735 DESTROY_IF(this->public.eap);
736 DESTROY_IF(this->public.xauth);
737 DESTROY_IF(this->public.backends);
738 DESTROY_IF(this->public.socket);
739 DESTROY_IF(this->public.kernel);
740
741 /* rehook library logging, shutdown logging */
742 dbg = dbg_old;
743 DESTROY_IF(this->public.bus);
744 this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
745 this->mutex->destroy(this->mutex);
746 free(this->levels);
747 free(this);
748 }
749
750 /**
751 * Run a set of configured scripts
752 */
753 static void run_scripts(private_daemon_t *this, char *verb)
754 {
755 struct {
756 char *name;
757 char *path;
758 } *script;
759 array_t *scripts = NULL;
760 enumerator_t *enumerator;
761 char *key, *value, *pos, buf[1024];
762 FILE *cmd;
763
764 /* copy the scripts so we don't hold any locks while executing them */
765 enumerator = lib->settings->create_key_value_enumerator(lib->settings,
766 "%s.%s-scripts", lib->ns, verb);
767 while (enumerator->enumerate(enumerator, &key, &value))
768 {
769 INIT(script,
770 .name = key,
771 .path = value,
772 );
773 array_insert_create(&scripts, ARRAY_TAIL, script);
774 }
775 enumerator->destroy(enumerator);
776
777 enumerator = array_create_enumerator(scripts);
778 while (enumerator->enumerate(enumerator, &script))
779 {
780 DBG1(DBG_DMN, "executing %s script '%s' (%s)", verb, script->name,
781 script->path);
782 cmd = popen(script->path, "r");
783 if (!cmd)
784 {
785 DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
786 verb, script->name, script->path, strerror(errno));
787 }
788 else
789 {
790 while (TRUE)
791 {
792 if (!fgets(buf, sizeof(buf), cmd))
793 {
794 if (ferror(cmd))
795 {
796 DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
797 verb, script->name, script->path);
798 }
799 break;
800 }
801 else
802 {
803 pos = buf + strlen(buf);
804 if (pos > buf && pos[-1] == '\n')
805 {
806 pos[-1] = '\0';
807 }
808 DBG1(DBG_DMN, "%s: %s", script->name, buf);
809 }
810 }
811 pclose(cmd);
812 }
813 free(script);
814 }
815 enumerator->destroy(enumerator);
816 array_destroy(scripts);
817 }
818
819 METHOD(daemon_t, start, void,
820 private_daemon_t *this)
821 {
822 /* start the engine, go multithreaded */
823 lib->processor->set_threads(lib->processor,
824 lib->settings->get_int(lib->settings, "%s.threads",
825 DEFAULT_THREADS, lib->ns));
826
827 run_scripts(this, "start");
828 }
829
830 /**
831 * Initialize/deinitialize sender and receiver
832 */
833 static bool sender_receiver_cb(void *plugin, plugin_feature_t *feature,
834 bool reg, private_daemon_t *this)
835 {
836 if (reg)
837 {
838 this->public.receiver = receiver_create();
839 if (!this->public.receiver)
840 {
841 return FALSE;
842 }
843 this->public.sender = sender_create();
844 }
845 else
846 {
847 DESTROY_IF(this->public.receiver);
848 DESTROY_IF(this->public.sender);
849 }
850 return TRUE;
851 }
852
853 /**
854 * Initialize/deinitialize IKE_SA/CHILD_SA managers
855 */
856 static bool sa_managers_cb(void *plugin, plugin_feature_t *feature,
857 bool reg, private_daemon_t *this)
858 {
859 if (reg)
860 {
861 this->public.ike_sa_manager = ike_sa_manager_create();
862 if (!this->public.ike_sa_manager)
863 {
864 return FALSE;
865 }
866 this->public.child_sa_manager = child_sa_manager_create();
867 }
868 else
869 {
870 DESTROY_IF(this->public.ike_sa_manager);
871 DESTROY_IF(this->public.child_sa_manager);
872 }
873 return TRUE;
874 }
875
876 METHOD(daemon_t, initialize, bool,
877 private_daemon_t *this, char *plugins)
878 {
879 plugin_feature_t features[] = {
880 PLUGIN_PROVIDE(CUSTOM, "libcharon"),
881 PLUGIN_DEPENDS(NONCE_GEN),
882 PLUGIN_DEPENDS(CUSTOM, "libcharon-sa-managers"),
883 PLUGIN_DEPENDS(CUSTOM, "libcharon-receiver"),
884 PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
885 PLUGIN_DEPENDS(CUSTOM, "kernel-net"),
886 PLUGIN_CALLBACK((plugin_feature_callback_t)sender_receiver_cb, this),
887 PLUGIN_PROVIDE(CUSTOM, "libcharon-receiver"),
888 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
889 PLUGIN_DEPENDS(RNG, RNG_STRONG),
890 PLUGIN_DEPENDS(CUSTOM, "socket"),
891 PLUGIN_CALLBACK((plugin_feature_callback_t)sa_managers_cb, this),
892 PLUGIN_PROVIDE(CUSTOM, "libcharon-sa-managers"),
893 PLUGIN_DEPENDS(HASHER, HASH_SHA1),
894 PLUGIN_DEPENDS(RNG, RNG_WEAK),
895 };
896 lib->plugins->add_static_features(lib->plugins, lib->ns, features,
897 countof(features), TRUE, NULL, NULL);
898
899 /* load plugins, further infrastructure may need it */
900 if (!lib->plugins->load(lib->plugins, plugins))
901 {
902 return FALSE;
903 }
904
905 /* Queue start_action job */
906 lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create());
907
908 #ifdef ME
909 this->public.connect_manager = connect_manager_create();
910 if (this->public.connect_manager == NULL)
911 {
912 return FALSE;
913 }
914 this->public.mediation_manager = mediation_manager_create();
915 #endif /* ME */
916
917 return TRUE;
918 }
919
920 /**
921 * Create the daemon.
922 */
923 private_daemon_t *daemon_create()
924 {
925 private_daemon_t *this;
926
927 INIT(this,
928 .public = {
929 .initialize = _initialize,
930 .start = _start,
931 .load_loggers = _load_loggers,
932 .set_default_loggers = _set_default_loggers,
933 .set_level = _set_level,
934 .bus = bus_create(),
935 },
936 .loggers = linked_list_create(),
937 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
938 .ref = 1,
939 );
940 charon = &this->public;
941 this->public.kernel = kernel_interface_create();
942 this->public.attributes = attribute_manager_create();
943 this->public.controller = controller_create();
944 this->public.eap = eap_manager_create();
945 this->public.xauth = xauth_manager_create();
946 this->public.backends = backend_manager_create();
947 this->public.socket = socket_manager_create();
948 this->public.traps = trap_manager_create();
949 this->public.shunts = shunt_manager_create();
950 this->public.redirect = redirect_manager_create();
951 this->kernel_handler = kernel_handler_create();
952
953 return this;
954 }
955
956 /**
957 * Described in header.
958 */
959 void libcharon_deinit()
960 {
961 private_daemon_t *this = (private_daemon_t*)charon;
962
963 if (!this || !ref_put(&this->ref))
964 { /* have more users */
965 return;
966 }
967
968 run_scripts(this, "stop");
969
970 destroy(this);
971 charon = NULL;
972 }
973
974 /**
975 * Described in header.
976 */
977 bool libcharon_init()
978 {
979 private_daemon_t *this;
980
981 if (charon)
982 { /* already initialized, increase refcount */
983 this = (private_daemon_t*)charon;
984 ref_get(&this->ref);
985 return !this->integrity_failed;
986 }
987
988 this = daemon_create();
989
990 /* for uncritical pseudo random numbers */
991 srandom(time(NULL) + getpid());
992
993 /* set up hook to log dbg message in library via charons message bus */
994 dbg_old = dbg;
995 dbg = dbg_bus;
996
997 if (lib->integrity &&
998 !lib->integrity->check(lib->integrity, "libcharon", libcharon_init))
999 {
1000 dbg(DBG_DMN, 1, "integrity check of libcharon failed");
1001 this->integrity_failed = TRUE;
1002 }
1003 return !this->integrity_failed;
1004 }