123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- /*
- * Copyright (C) 2012 Tobias Brunner
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
- #include <stdio.h>
- #include <syslog.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <errno.h>
- #include <daemon.h>
- #include <library.h>
- #include <utils/backtrace.h>
- #include <threading/thread.h>
- #include <nm/nm_backend.h>
- /**
- * Default user and group
- */
- #ifndef IPSEC_USER
- #define IPSEC_USER NULL
- #endif
- #ifndef IPSEC_GROUP
- #define IPSEC_GROUP NULL
- #endif
- /**
- * Hook in library for debugging messages
- */
- extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
- /**
- * Simple logging hook for library logs, using syslog output
- */
- static void dbg_syslog(debug_t group, level_t level, char *fmt, ...)
- {
- if (level <= 1)
- {
- char buffer[8192], groupstr[4];
- va_list args;
- va_start(args, fmt);
- /* write in memory buffer first */
- vsnprintf(buffer, sizeof(buffer), fmt, args);
- /* cache group name */
- snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group);
- syslog(LOG_DAEMON|LOG_INFO, "00[%s] %s", groupstr, buffer);
- va_end(args);
- }
- }
- /**
- * Run the daemon and handle unix signals
- */
- static void run()
- {
- sigset_t set;
- /* handle SIGINT and SIGTERM in this handler */
- sigemptyset(&set);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGTERM);
- sigprocmask(SIG_BLOCK, &set, NULL);
- while (TRUE)
- {
- int sig;
- sig = sigwaitinfo(&set, NULL);
- if (sig == -1)
- {
- if (errno == EINTR)
- { /* ignore signals we didn't wait for */
- continue;
- }
- DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno));
- return;
- }
- switch (sig)
- {
- case SIGINT:
- {
- DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
- charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
- return;
- }
- case SIGTERM:
- {
- DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
- charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
- return;
- }
- }
- }
- }
- #ifndef DISABLE_SIGNAL_HANDLER
- /**
- * Handle SIGSEGV/SIGILL signals raised by threads
- */
- static void segv_handler(int signal)
- {
- backtrace_t *backtrace;
- DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
- backtrace = backtrace_create(2);
- backtrace->log(backtrace, stderr, TRUE);
- backtrace->destroy(backtrace);
- DBG1(DBG_DMN, "killing ourself, received critical signal");
- abort();
- }
- #endif /* DISABLE_SIGNAL_HANDLER */
- /**
- * Lookup UID and GID
- */
- static bool lookup_uid_gid()
- {
- char *name;
- name = lib->settings->get_str(lib->settings, "charon-nm.user",
- IPSEC_USER);
- if (name && !lib->caps->resolve_uid(lib->caps, name))
- {
- return FALSE;
- }
- name = lib->settings->get_str(lib->settings, "charon-nm.group",
- IPSEC_GROUP);
- if (name && !lib->caps->resolve_gid(lib->caps, name))
- {
- return FALSE;
- }
- return TRUE;
- }
- /**
- * Main function, starts NetworkManager backend.
- */
- int main(int argc, char *argv[])
- {
- struct sigaction action;
- int status = SS_RC_INITIALIZATION_FAILED;
- /* logging for library during initialization, as we have no bus yet */
- dbg = dbg_syslog;
- /* LD causes a crash probably due to Glib */
- setenv("LEAK_DETECTIVE_DISABLE", "1", 1);
- /* initialize library */
- if (!library_init(NULL, "charon-nm"))
- {
- library_deinit();
- exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
- }
- if (lib->integrity &&
- !lib->integrity->check_file(lib->integrity, "charon-nm", argv[0]))
- {
- dbg_syslog(DBG_DMN, 1, "integrity check of charon-nm failed");
- library_deinit();
- exit(SS_RC_DAEMON_INTEGRITY);
- }
- if (!libcharon_init())
- {
- dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
- goto deinit;
- }
- if (!lookup_uid_gid())
- {
- dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting charon-nm");
- goto deinit;
- }
- /* make sure we log to the DAEMON facility by default */
- lib->settings->set_int(lib->settings, "charon-nm.syslog.daemon.default",
- lib->settings->get_int(lib->settings,
- "charon-nm.syslog.daemon.default", 1));
- charon->load_loggers(charon);
- /* use random ports to avoid conflicts with regular charon */
- lib->settings->set_int(lib->settings, "charon-nm.port", 0);
- lib->settings->set_int(lib->settings, "charon-nm.port_nat_t", 0);
- DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")");
- if (lib->integrity)
- {
- DBG1(DBG_DMN, "integrity tests enabled:");
- DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests");
- DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests");
- DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test");
- }
- /* register NM backend to be loaded with plugins */
- nm_backend_register();
- /* initialize daemon */
- if (!charon->initialize(charon,
- lib->settings->get_str(lib->settings, "charon-nm.load", PLUGINS)))
- {
- DBG1(DBG_DMN, "initialization failed - aborting charon-nm");
- goto deinit;
- }
- lib->plugins->status(lib->plugins, LEVEL_CTRL);
- if (!lib->caps->drop(lib->caps))
- {
- DBG1(DBG_DMN, "capability dropping failed - aborting charon-nm");
- goto deinit;
- }
- /* add handler for fatal signals,
- * INT and TERM are handled by sigwaitinfo() in run() */
- action.sa_flags = 0;
- sigemptyset(&action.sa_mask);
- sigaddset(&action.sa_mask, SIGINT);
- sigaddset(&action.sa_mask, SIGTERM);
- /* optionally let the external system handle fatal signals */
- #ifndef DISABLE_SIGNAL_HANDLER
- action.sa_handler = segv_handler;
- sigaction(SIGSEGV, &action, NULL);
- sigaction(SIGILL, &action, NULL);
- sigaction(SIGBUS, &action, NULL);
- #endif /* DISABLE_SIGNAL_HANDLER */
- action.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &action, NULL);
- pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
- /* start daemon (i.e. the threads in the thread-pool) */
- charon->start(charon);
- /* main thread goes to run loop */
- run();
- status = 0;
- deinit:
- libcharon_deinit();
- library_deinit();
- return status;
- }
|