2 * Copyright (C) 2006-2012 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
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>.
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
20 #define _POSIX_PTHREAD_SEMANTICS /* for two param sigwait on OpenSolaris */
22 #undef _POSIX_PTHREAD_SEMANTICS
25 #include <sys/types.h>
26 #include <sys/utsname.h>
36 #include <utils/backtrace.h>
37 #include <threading/thread.h>
40 #include <private/android_filesystem_config.h> /* for AID_VPN */
43 #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
44 #define LOG_AUTHPRIV LOG_AUTH
48 * PID file, in which charon stores its process id
50 #define PID_FILE IPSEC_PIDDIR "/charon.pid"
53 * Global reference to PID file (required to truncate, if undeletable)
55 static FILE *pidfile
= NULL
;
58 * hook in library for debugging messages
60 extern void (*dbg
) (debug_t group
, level_t level
, char *fmt
, ...);
63 * Logging hook for library logs, using stderr output
65 static void dbg_stderr(debug_t group
, level_t level
, char *fmt
, ...)
72 fprintf(stderr
, "00[%N] ", debug_names
, group
);
73 vfprintf(stderr
, fmt
, args
);
74 fprintf(stderr
, "\n");
80 * Run the daemon and handle unix signals
86 /* handle SIGINT, SIGHUP ans SIGTERM in this handler */
88 sigaddset(&set
, SIGINT
);
89 sigaddset(&set
, SIGHUP
);
90 sigaddset(&set
, SIGTERM
);
91 sigprocmask(SIG_BLOCK
, &set
, NULL
);
98 error
= sigwait(&set
, &sig
);
101 DBG1(DBG_DMN
, "error %d while waiting for a signal", error
);
108 DBG1(DBG_DMN
, "signal of type SIGHUP received. Reloading "
110 if (lib
->settings
->load_files(lib
->settings
, NULL
, FALSE
))
112 lib
->plugins
->reload(lib
->plugins
, NULL
);
116 DBG1(DBG_DMN
, "reloading config failed, keeping old");
122 DBG1(DBG_DMN
, "signal of type SIGINT received. Shutting down");
123 charon
->bus
->alert(charon
->bus
, ALERT_SHUTDOWN_SIGNAL
, sig
);
128 DBG1(DBG_DMN
, "signal of type SIGTERM received. Shutting down");
129 charon
->bus
->alert(charon
->bus
, ALERT_SHUTDOWN_SIGNAL
, sig
);
134 DBG1(DBG_DMN
, "unknown signal %d received. Ignored", sig
);
144 static bool lookup_uid_gid()
147 if (!charon
->caps
->resolve_uid(charon
->caps
, IPSEC_USER
))
153 if (!charon
->caps
->resolve_gid(charon
->caps
, IPSEC_GROUP
))
159 charon
->caps
->set_uid(charon
->caps
, AID_VPN
);
165 * Handle SIGSEGV/SIGILL signals raised by threads
167 static void segv_handler(int signal
)
169 backtrace_t
*backtrace
;
171 DBG1(DBG_DMN
, "thread %u received %d", thread_current_id(), signal
);
172 backtrace
= backtrace_create(2);
173 backtrace
->log(backtrace
, stderr
, TRUE
);
174 backtrace
->destroy(backtrace
);
176 DBG1(DBG_DMN
, "killing ourself, received critical signal");
181 * Check/create PID file, return TRUE if already running
183 static bool check_pidfile()
187 if (stat(PID_FILE
, &stb
) == 0)
189 pidfile
= fopen(PID_FILE
, "r");
195 memset(buf
, 0, sizeof(buf
));
196 if (fread(buf
, 1, sizeof(buf
), pidfile
))
198 buf
[sizeof(buf
) - 1] = '\0';
202 if (pid
&& kill(pid
, 0) == 0)
203 { /* such a process is running */
207 DBG1(DBG_DMN
, "removing pidfile '"PID_FILE
"', process not running");
211 /* create new pidfile */
212 pidfile
= fopen(PID_FILE
, "w");
215 ignore_result(fchown(fileno(pidfile
),
216 charon
->caps
->get_uid(charon
->caps
),
217 charon
->caps
->get_gid(charon
->caps
)));
218 fprintf(pidfile
, "%d\n", getpid());
225 * Delete/truncate the PID file
227 static void unlink_pidfile()
229 /* because unlinking the PID file may fail, we truncate it to ensure the
230 * daemon can be properly restarted. one probable cause for this is the
231 * combination of not running as root and the effective user lacking
232 * permissions on the parent dir(s) of the PID file */
235 ignore_result(ftruncate(fileno(pidfile
), 0));
244 static void initialize_loggers(bool use_stderr
, level_t levels
[])
246 sys_logger_t
*sys_logger
;
247 file_logger_t
*file_logger
;
248 enumerator_t
*enumerator
;
249 char *identifier
, *facility
, *filename
;
250 int loggers_defined
= 0;
253 bool append
, ike_name
;
256 /* setup sysloggers */
257 identifier
= lib
->settings
->get_str(lib
->settings
,
258 "charon.syslog.identifier", NULL
);
260 { /* set identifier, which is prepended to each log line */
261 openlog(identifier
, 0, 0);
263 enumerator
= lib
->settings
->create_section_enumerator(lib
->settings
,
265 while (enumerator
->enumerate(enumerator
, &facility
))
269 ike_name
= lib
->settings
->get_bool(lib
->settings
,
270 "charon.syslog.%s.ike_name", FALSE
, facility
);
271 if (streq(facility
, "daemon"))
273 sys_logger
= sys_logger_create(LOG_DAEMON
, ike_name
);
275 else if (streq(facility
, "auth"))
277 sys_logger
= sys_logger_create(LOG_AUTHPRIV
, ike_name
);
283 def
= lib
->settings
->get_int(lib
->settings
,
284 "charon.syslog.%s.default", 1, facility
);
285 for (group
= 0; group
< DBG_MAX
; group
++)
287 sys_logger
->set_level(sys_logger
, group
,
288 lib
->settings
->get_int(lib
->settings
,
289 "charon.syslog.%s.%N", def
,
290 facility
, debug_lower_names
, group
));
292 charon
->sys_loggers
->insert_last(charon
->sys_loggers
, sys_logger
);
293 charon
->bus
->add_logger(charon
->bus
, &sys_logger
->logger
);
295 enumerator
->destroy(enumerator
);
297 /* and file loggers */
298 enumerator
= lib
->settings
->create_section_enumerator(lib
->settings
,
300 while (enumerator
->enumerate(enumerator
, &filename
))
303 if (streq(filename
, "stderr"))
307 else if (streq(filename
, "stdout"))
313 append
= lib
->settings
->get_bool(lib
->settings
,
314 "charon.filelog.%s.append", TRUE
, filename
);
315 file
= fopen(filename
, append ?
"a" : "w");
318 DBG1(DBG_DMN
, "opening file %s for logging failed: %s",
319 filename
, strerror(errno
));
322 if (lib
->settings
->get_bool(lib
->settings
,
323 "charon.filelog.%s.flush_line", FALSE
, filename
))
328 file_logger
= file_logger_create(file
,
329 lib
->settings
->get_str(lib
->settings
,
330 "charon.filelog.%s.time_format", NULL
, filename
),
331 lib
->settings
->get_bool(lib
->settings
,
332 "charon.filelog.%s.ike_name", FALSE
, filename
));
333 def
= lib
->settings
->get_int(lib
->settings
,
334 "charon.filelog.%s.default", 1, filename
);
335 for (group
= 0; group
< DBG_MAX
; group
++)
337 file_logger
->set_level(file_logger
, group
,
338 lib
->settings
->get_int(lib
->settings
,
339 "charon.filelog.%s.%N", def
,
340 filename
, debug_lower_names
, group
));
342 charon
->file_loggers
->insert_last(charon
->file_loggers
, file_logger
);
343 charon
->bus
->add_logger(charon
->bus
, &file_logger
->logger
);
346 enumerator
->destroy(enumerator
);
348 /* set up legacy style default loggers provided via command-line */
349 if (!loggers_defined
)
351 /* set up default stdout file_logger */
352 file_logger
= file_logger_create(stdout
, NULL
, FALSE
);
353 charon
->file_loggers
->insert_last(charon
->file_loggers
, file_logger
);
354 /* set up default daemon sys_logger */
355 sys_logger
= sys_logger_create(LOG_DAEMON
, FALSE
);
356 charon
->sys_loggers
->insert_last(charon
->sys_loggers
, sys_logger
);
357 for (group
= 0; group
< DBG_MAX
; group
++)
359 sys_logger
->set_level(sys_logger
, group
, levels
[group
]);
362 file_logger
->set_level(file_logger
, group
, levels
[group
]);
365 charon
->bus
->add_logger(charon
->bus
, &file_logger
->logger
);
366 charon
->bus
->add_logger(charon
->bus
, &sys_logger
->logger
);
368 /* set up default auth sys_logger */
369 sys_logger
= sys_logger_create(LOG_AUTHPRIV
, FALSE
);
370 sys_logger
->set_level(sys_logger
, DBG_ANY
, LEVEL_AUDIT
);
371 charon
->sys_loggers
->insert_last(charon
->sys_loggers
, sys_logger
);
372 charon
->bus
->add_logger(charon
->bus
, &sys_logger
->logger
);
377 * print command line usage and exit
379 static void usage(const char *msg
)
381 if (msg
!= NULL
&& *msg
!= '\0')
383 fprintf(stderr
, "%s\n", msg
);
385 fprintf(stderr
, "Usage: charon\n"
389 " [--debug-<type> <level>]\n"
390 " <type>: log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n"
391 " <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
392 " 2 = controlmore, 3 = raw, 4 = private)\n"
398 * Main function, starts the daemon.
400 int main(int argc
, char *argv
[])
402 struct sigaction action
;
403 bool use_syslog
= FALSE
;
404 level_t levels
[DBG_MAX
];
405 int group
, status
= SS_RC_INITIALIZATION_FAILED
;
406 struct utsname utsname
;
408 /* logging for library during initialization, as we have no bus yet */
411 /* initialize library */
412 if (!library_init(NULL
))
415 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY
);
418 if (lib
->integrity
&&
419 !lib
->integrity
->check_file(lib
->integrity
, "charon", argv
[0]))
421 dbg_stderr(DBG_DMN
, 1, "integrity check of charon failed");
423 exit(SS_RC_DAEMON_INTEGRITY
);
426 if (!libhydra_init("charon"))
428 dbg_stderr(DBG_DMN
, 1, "initialization failed - aborting charon");
431 exit(SS_RC_INITIALIZATION_FAILED
);
434 if (!libcharon_init("charon"))
436 dbg_stderr(DBG_DMN
, 1, "initialization failed - aborting charon");
440 /* use CTRL loglevel for default */
441 for (group
= 0; group
< DBG_MAX
; group
++)
443 levels
[group
] = LEVEL_CTRL
;
446 /* handle arguments */
449 struct option long_opts
[] = {
450 { "help", no_argument
, NULL
, 'h' },
451 { "version", no_argument
, NULL
, 'v' },
452 { "use-syslog", no_argument
, NULL
, 'l' },
453 /* TODO: handle "debug-all" */
454 { "debug-dmn", required_argument
, &group
, DBG_DMN
},
455 { "debug-mgr", required_argument
, &group
, DBG_MGR
},
456 { "debug-ike", required_argument
, &group
, DBG_IKE
},
457 { "debug-chd", required_argument
, &group
, DBG_CHD
},
458 { "debug-job", required_argument
, &group
, DBG_JOB
},
459 { "debug-cfg", required_argument
, &group
, DBG_CFG
},
460 { "debug-knl", required_argument
, &group
, DBG_KNL
},
461 { "debug-net", required_argument
, &group
, DBG_NET
},
462 { "debug-asn", required_argument
, &group
, DBG_ASN
},
463 { "debug-enc", required_argument
, &group
, DBG_ENC
},
464 { "debug-tnc", required_argument
, &group
, DBG_TNC
},
465 { "debug-imc", required_argument
, &group
, DBG_IMC
},
466 { "debug-imv", required_argument
, &group
, DBG_IMV
},
467 { "debug-pts", required_argument
, &group
, DBG_PTS
},
468 { "debug-tls", required_argument
, &group
, DBG_TLS
},
469 { "debug-esp", required_argument
, &group
, DBG_ESP
},
470 { "debug-lib", required_argument
, &group
, DBG_LIB
},
474 int c
= getopt_long(argc
, argv
, "", long_opts
, NULL
);
484 printf("Linux strongSwan %s\n", VERSION
);
491 /* option is in group */
492 levels
[group
] = atoi(optarg
);
502 if (!lookup_uid_gid())
504 dbg_stderr(DBG_DMN
, 1, "invalid uid/gid - aborting charon");
508 initialize_loggers(!use_syslog
, levels
);
510 if (uname(&utsname
) != 0)
512 memset(&utsname
, 0, sizeof(utsname
));
514 DBG1(DBG_DMN
, "Starting IKE charon daemon (strongSwan "VERSION
", %s %s, %s)",
515 utsname
.sysname
, utsname
.release
, utsname
.machine
);
518 DBG1(DBG_DMN
, "integrity tests enabled:");
519 DBG1(DBG_DMN
, "lib 'libstrongswan': passed file and segment integrity tests");
520 DBG1(DBG_DMN
, "lib 'libhydra': passed file and segment integrity tests");
521 DBG1(DBG_DMN
, "lib 'libcharon': passed file and segment integrity tests");
522 DBG1(DBG_DMN
, "daemon 'charon': passed file integrity test");
525 /* initialize daemon */
526 if (!charon
->initialize(charon
,
527 lib
->settings
->get_str(lib
->settings
, "charon.load", PLUGINS
)))
529 DBG1(DBG_DMN
, "initialization failed - aborting charon");
535 DBG1(DBG_DMN
, "charon already running (\""PID_FILE
"\" exists)");
540 if (!charon
->caps
->drop(charon
->caps
))
542 DBG1(DBG_DMN
, "capability dropping failed - aborting charon");
546 /* add handler for SEGV and ILL,
547 * INT, TERM and HUP are handled by sigwait() in run() */
548 action
.sa_handler
= segv_handler
;
550 sigemptyset(&action
.sa_mask
);
551 sigaddset(&action
.sa_mask
, SIGINT
);
552 sigaddset(&action
.sa_mask
, SIGTERM
);
553 sigaddset(&action
.sa_mask
, SIGHUP
);
554 sigaction(SIGSEGV
, &action
, NULL
);
555 sigaction(SIGILL
, &action
, NULL
);
556 sigaction(SIGBUS
, &action
, NULL
);
557 action
.sa_handler
= SIG_IGN
;
558 sigaction(SIGPIPE
, &action
, NULL
);
560 pthread_sigmask(SIG_SETMASK
, &action
.sa_mask
, NULL
);
562 /* start daemon (i.e. the threads in the thread-pool) */
563 charon
->start(charon
);
565 /* main thread goes to run loop */
568 /* normal termination, cleanup and exit */