diff options
author | Martin Willi <martin@strongswan.org> | 2006-10-18 11:46:13 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2006-10-18 11:46:13 +0000 |
commit | 60356f3375da67375e48691bb1d732c02d1681a1 (patch) | |
tree | 1bfa3bd28d46c4211a17a831094e7fcbceea8bb6 /src/charon/daemon.c | |
parent | 8cdce67afa4bc4b4ff1a05e956db08cddc5dc48e (diff) | |
download | strongswan-60356f3375da67375e48691bb1d732c02d1681a1.tar.bz2 strongswan-60356f3375da67375e48691bb1d732c02d1681a1.tar.xz |
introduced new logging subsystem using bus:
passive listeners can register on the bus
active listeners wait for signals actively
multiplexing allows multiple listeners to receive debug signals
a lot more...
Diffstat (limited to 'src/charon/daemon.c')
-rw-r--r-- | src/charon/daemon.c | 214 |
1 files changed, 139 insertions, 75 deletions
diff --git a/src/charon/daemon.c b/src/charon/daemon.c index fee85dd05..602259b31 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -21,7 +21,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ - + #include <stdio.h> #include <signal.h> #include <pthread.h> @@ -34,7 +34,7 @@ #include <getopt.h> #include <errno.h> -#include "daemon.h" +#include "daemon.h" #include <types.h> #include <config/credentials/local_credential_store.h> @@ -54,11 +54,6 @@ struct private_daemon_t { daemon_t public; /** - * A logger_t object assigned for daemon things. - */ - logger_t *logger; - - /** * Signal set used for signal handling. */ sigset_t signal_set; @@ -75,6 +70,37 @@ struct private_daemon_t { daemon_t *charon; /** + * hook in library for debugging messages + */ +extern void (*dbg) (int level, char *fmt, ...); + +/** + * Logging hook for library logs, spreads debug message over bus + */ +static void dbg_bus(int level, char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + charon->bus->vsignal(charon->bus, SIG_DBG_LIB, level, fmt, args); + va_end(args); +} + +/** + * Logging hook for library logs, using stderr output + */ +static void dbg_stderr(int level, char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "00[LIB] "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); +} + +/** * Run the daemon and handle unix signals */ static void run(private_daemon_t *this) @@ -94,27 +120,27 @@ static void run(private_daemon_t *this) error = sigwait(&(this->signal_set), &signal_number); if(error) { - this->logger->log(this->logger, ERROR, "Error %d when waiting for signal", error); + DBG1(SIG_DBG_DMN, "error %d while waiting for a signal", error); return; } switch (signal_number) { case SIGHUP: { - this->logger->log(this->logger, CONTROL, "Signal of type SIGHUP received. Do nothing"); + DBG1(SIG_DBG_DMN, "signal of type SIGHUP received. Ignored"); break; } case SIGINT: { - this->logger->log(this->logger, CONTROL, "Signal of type SIGINT received. Exit main loop"); + DBG1(SIG_DBG_DMN, "signal of type SIGINT received. Shutting down"); return; } case SIGTERM: - this->logger->log(this->logger, CONTROL, "Signal of type SIGTERM received. Exit main loop"); + DBG1(SIG_DBG_DMN, "signal of type SIGTERM received. Shutting down"); return; default: { - this->logger->log(this->logger, CONTROL, "Unknown signal %d received. Do nothing", signal_number); + DBG1(SIG_DBG_DMN, "unknown signal %d received. Ignored", signal_number); break; } } @@ -144,20 +170,24 @@ static void destroy(private_daemon_t *this) /* all child SAs should be down now, so kill kernel interface */ DESTROY_IF(this->public.kernel_interface); /* destroy other infrastructure */ - DESTROY_IF(this->public.bus); - DESTROY_IF(this->public.outlog); - DESTROY_IF(this->public.syslog); DESTROY_IF(this->public.job_queue); DESTROY_IF(this->public.event_queue); DESTROY_IF(this->public.configuration); DESTROY_IF(this->public.credentials); DESTROY_IF(this->public.connections); DESTROY_IF(this->public.policies); + sched_yield(); /* we hope the sender could send the outstanding deletes, but - * we shut down here at any cost */ + * we shut down here at any cost */ DESTROY_IF(this->public.sender); DESTROY_IF(this->public.send_queue); DESTROY_IF(this->public.socket); + /* before destroying bus with its listeners, rehook library logs */ + dbg = dbg_stderr; + DESTROY_IF(this->public.bus); + DESTROY_IF(this->public.outlog); + DESTROY_IF(this->public.syslog); + DESTROY_IF(this->public.authlog); free(this); } @@ -167,7 +197,7 @@ static void destroy(private_daemon_t *this) static void kill_daemon(private_daemon_t *this, char *reason) { /* we send SIGTERM, so the daemon can cleanly shut down */ - this->logger->log(this->logger, CONTROL, "Killing daemon: %s", reason); + DBG1(SIG_DBG_DMN, "killing daemon: %s", reason); if (this->main_thread_id == pthread_self()) { /* initialization failed, terminate daemon */ @@ -177,7 +207,7 @@ static void kill_daemon(private_daemon_t *this, char *reason) } else { - this->logger->log(this->logger, CONTROL, "sending SIGTERM to ourself", reason); + DBG1(SIG_DBG_DMN, "sending SIGTERM to ourself"); raise(SIGTERM); /* thread must die, since he produced a ciritcal failure and can't continue */ pthread_exit(NULL); @@ -187,24 +217,50 @@ static void kill_daemon(private_daemon_t *this, char *reason) /** * Initialize the daemon, optional with a strict crl policy */ -static void initialize(private_daemon_t *this, bool strict) +static void initialize(private_daemon_t *this, bool strict, bool syslog, + level_t levels[]) { credential_store_t* credentials; + signal_t signal; /* for uncritical pseudo random numbers */ srandom(time(NULL) + getpid()); + /* setup bus and it's listeners first to enable log output */ + this->public.bus = bus_create(); + this->public.outlog = file_logger_create(stdout); + this->public.syslog = sys_logger_create(LOG_DAEMON); + this->public.authlog = sys_logger_create(LOG_AUTHPRIV); + this->public.bus->add_listener(this->public.bus, &this->public.syslog->listener); + this->public.bus->add_listener(this->public.bus, &this->public.outlog->listener); + this->public.bus->add_listener(this->public.bus, &this->public.authlog->listener); + this->public.authlog->set_level(this->public.authlog, SIG_ANY, LEVEL_AUDIT); + /* set up hook to log dbg message in library via charons message bus */ + dbg = dbg_bus; + + /* apply loglevels */ + for (signal = 0; signal < SIG_DBG_MAX; signal++) + { + if (syslog) + { + this->public.syslog->set_level(this->public.syslog, + signal, levels[signal]); + } + else + { + this->public.outlog->set_level(this->public.outlog, + signal, levels[signal]); + } + } + + DBG1(SIG_DBG_DMN, "starting charon (strongSwan Version %s)", VERSION); + this->public.configuration = configuration_create(); this->public.socket = socket_create(IKEV2_UDP_PORT, IKEV2_NATT_PORT); this->public.ike_sa_manager = ike_sa_manager_create(); this->public.job_queue = job_queue_create(); this->public.event_queue = event_queue_create(); this->public.send_queue = send_queue_create(); - this->public.bus = bus_create(); - this->public.outlog = file_logger_create(stdout); - this->public.bus->add_listener(this->public.bus, &this->public.outlog->listener); - this->public.syslog = sys_logger_create(LOG_DAEMON); - this->public.bus->add_listener(this->public.bus, &this->public.syslog->listener); this->public.connections = (connection_store_t*)local_connection_store_create(); this->public.policies = (policy_store_t*)local_policy_store_create(); this->public.credentials = (credential_store_t*)local_credential_store_create(strict); @@ -233,23 +289,19 @@ void signal_handler(int signal) size_t size; char **strings; size_t i; - logger_t *logger; size = backtrace(array, 20); strings = backtrace_symbols(array, size); - logger = logger_manager->get_logger(logger_manager, DAEMON); - logger->log(logger, ERROR, - "Thread %u received %s. Dumping %d frames from stack:", - signal == SIGSEGV ? "SIGSEGV" : "SIGILL", - pthread_self(), size); + DBG1(SIG_DBG_DMN, "thread %u received %s. Dumping %d frames from stack:", + signal == SIGSEGV ? "SIGSEGV" : "SIGILL", pthread_self(), size); for (i = 0; i < size; i++) { - logger->log(logger, ERROR, " %s", strings[i]); + DBG1(SIG_DBG_DMN, " %s", strings[i]); } free (strings); - logger->log(logger, ERROR, "Killing ourself hard after SIGSEGV"); + DBG1(SIG_DBG_DMN, "killing ourself hard after SIGSEGV"); raise(SIGKILL); } @@ -283,6 +335,7 @@ private_daemon_t *daemon_create(void) this->public.bus = NULL; this->public.outlog = NULL; this->public.syslog = NULL; + this->public.authlog = NULL; this->main_thread_id = pthread_self(); @@ -298,14 +351,8 @@ private_daemon_t *daemon_create(void) action.sa_handler = signal_handler; action.sa_mask = this->signal_set; action.sa_flags = 0; - if (sigaction(SIGSEGV, &action, NULL) == -1) - { - this->logger->log(this->logger, ERROR, "signal handler setup for SIGSEGV failed"); - } - if (sigaction(SIGILL, &action, NULL) == -1) - { - this->logger->log(this->logger, ERROR, "signal handler setup for SIGILL failed"); - } + sigaction(SIGSEGV, &action, NULL); + sigaction(SIGILL, &action, NULL); return this; } @@ -315,64 +362,90 @@ private_daemon_t *daemon_create(void) static void usage(const char *msg) { if (msg != NULL && *msg != '\0') + { fprintf(stderr, "%s\n", msg); - fprintf(stderr, "Usage: charon" - " [--help]" - " [--version]" - " [--use-syslog]" - " [--strictcrlpolicy]" - "\n" - ); - exit(msg == NULL? 0 : 1); + } + fprintf(stderr, "Usage: charon\n" + " [--help]\n" + " [--version]\n" + " [--strictcrlpolicy]\n" + " [--use-syslog]\n" + " [--debug-<type> <level>]\n" + " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|enc|lib)\n" + " <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n" + " 2 = controlmore, 3 = raw, 4 = private)\n" + "\n" + ); + exit(msg == NULL? 0 : 1); } - /** * Main function, manages the daemon. */ int main(int argc, char *argv[]) -{ +{ bool strict_crl_policy = FALSE; + bool use_syslog = FALSE; private_daemon_t *private_charon; FILE *pid_file; struct stat stb; linked_list_t *list; host_t *host; + level_t levels[SIG_DBG_MAX]; + int signal; + + /* use CTRL loglevel for default */ + for (signal = 0; signal < SIG_DBG_MAX; signal++) + { + levels[signal] = LEVEL_CTRL; + } - /* handle arguments */ - for (;;) - { - static const struct option long_opts[] = { + /* handle arguments */ + for (;;) + { + struct option long_opts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "use-syslog", no_argument, NULL, 'l' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, + { "debug-dmn", required_argument, &signal, SIG_DBG_DMN }, + { "debug-mgr", required_argument, &signal, SIG_DBG_MGR }, + { "debug-ike", required_argument, &signal, SIG_DBG_IKE }, + { "debug-chd", required_argument, &signal, SIG_DBG_CHD }, + { "debug-job", required_argument, &signal, SIG_DBG_JOB }, + { "debug-cfg", required_argument, &signal, SIG_DBG_CFG }, + { "debug-knl", required_argument, &signal, SIG_DBG_KNL }, + { "debug-net", required_argument, &signal, SIG_DBG_NET }, + { "debug-enc", required_argument, &signal, SIG_DBG_ENC }, + { "debug-lib", required_argument, &signal, SIG_DBG_LIB }, { 0,0,0,0 } }; - + int c = getopt_long(argc, argv, "", long_opts, NULL); - - /* Note: "breaking" from case terminates loop */ switch (c) { - case EOF: /* end of flags */ + case EOF: break; case 'h': usage(NULL); - break; /* not actually reached */ + break; case 'v': printf("Linux strongSwan %s\n", VERSION); exit(0); case 'l': - logger_manager->set_output(logger_manager, ALL_LOGGERS, NULL); + use_syslog = TRUE; continue; case 'r': strict_crl_policy = TRUE; continue; + case 0: + /* option is in signal */ + levels[signal] = atoi(optarg); + continue; default: usage(""); - break; /* not actually reached */ + break; } break; } @@ -380,19 +453,13 @@ int main(int argc, char *argv[]) private_charon = daemon_create(); charon = (daemon_t*)private_charon; - private_charon->logger = logger_manager->get_logger(logger_manager, DAEMON); - - private_charon->logger->log(private_charon->logger, CONTROL, - "Starting Charon (strongSwan Version %s)", VERSION); - /* initialize daemon */ - initialize(private_charon, strict_crl_policy); + initialize(private_charon, strict_crl_policy, use_syslog, levels); /* check/setup PID file */ if (stat(PID_FILE, &stb) == 0) { - private_charon->logger->log(private_charon->logger, ERROR, - "charon already running (\""PID_FILE"\" exists)"); + DBG1(SIG_DBG_DMN, "charon already running (\""PID_FILE"\" exists)"); destroy(private_charon); exit(-1); } @@ -404,13 +471,10 @@ int main(int argc, char *argv[]) } /* log socket info */ list = charon->socket->create_local_address_list(charon->socket); - private_charon->logger->log(private_charon->logger, CONTROL, - "listening on %d addresses:", - list->get_count(list)); + DBG1(SIG_DBG_NET, "listening on %d addresses:", list->get_count(list)); while (list->remove_first(list, (void**)&host) == SUCCESS) { - private_charon->logger->log(private_charon->logger, CONTROL, - " %H", host); + DBG1(SIG_DBG_NET, " %H", host); host->destroy(host); } list->destroy(list); @@ -421,6 +485,6 @@ int main(int argc, char *argv[]) /* normal termination, cleanup and exit */ destroy(private_charon); unlink(PID_FILE); - + return 0; } |