2 * radiusd.c Main loop of the radius server.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000-2012 The FreeRADIUS server project
21 * Copyright 1999,2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
23 * Copyright 2000 Alan Curry <pacman-radius@cqc.com>
24 * Copyright 2000 Jeff Carneal <jeff@apex.net>
25 * Copyright 2000 Chad Miller <cmiller@surfsouth.com>
30 #include <freeradius-devel/radiusd.h>
31 #include <freeradius-devel/modules.h>
32 #include <freeradius-devel/state.h>
33 #include <freeradius-devel/rad_assert.h>
44 #ifdef HAVE_SYS_WAIT_H
45 # include <sys/wait.h>
48 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
51 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
57 char const *radacct_dir = NULL;
58 char const *radlog_dir = NULL;
60 bool log_stripped_names;
62 char const *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
63 #ifdef RADIUSD_VERSION_COMMIT
64 " (git #" STRINGIFY(RADIUSD_VERSION_COMMIT) ")"
66 ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
68 static pid_t radius_pid;
71 * Configuration items.
77 static void usage(int);
79 static void sig_fatal (int);
81 static void sig_hup (int);
87 int main(int argc, char *argv[])
89 int rcode = EXIT_SUCCESS;
92 bool spawn_flag = true;
93 bool display_version = false;
95 int from_child[2] = {-1, -1};
97 fr_state_t *state = NULL;
100 * We probably don't want to free the talloc autofree context
101 * directly, so we'll allocate a new context beneath it, and
102 * free that before any leak reports.
104 TALLOC_CTX *autofree = talloc_init("main");
107 set_auth_parameters(argc, argv);
110 p = strrchr(argv[0], FR_DIR_SEP);
112 main_config.name = argv[0];
114 main_config.name = p + 1;
120 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
121 fprintf(stderr, "%s: Unable to initialize socket library.\n",
129 set_radius_dir(autofree, RADIUS_DIR);
132 * Ensure that the configuration is initialized.
134 memset(&main_config, 0, sizeof(main_config));
135 main_config.myip.af = AF_UNSPEC;
136 main_config.port = 0;
137 main_config.name = "radiusd";
138 main_config.daemonize = true;
141 * Don't put output anywhere until we get told a little
144 default_log.dst = L_DST_NULL;
146 main_config.log_file = NULL;
148 /* Process the options. */
149 while ((argval = getopt(argc, argv, "Cd:D:fhi:l:mMn:p:PstvxX")) != EOF) {
155 main_config.daemonize = false;
159 set_radius_dir(autofree, optarg);
163 main_config.dictionary_dir = talloc_typed_strdup(autofree, optarg);
167 main_config.daemonize = false;
175 if (strcmp(optarg, "stdout") == 0) {
178 main_config.log_file = strdup(optarg);
179 default_log.dst = L_DST_FILES;
180 default_log.fd = open(main_config.log_file,
181 O_WRONLY | O_APPEND | O_CREAT, 0640);
182 if (default_log.fd < 0) {
183 fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno));
186 fr_log_fp = fdopen(default_log.fd, "a");
190 if (ip_hton(&main_config.myip, AF_UNSPEC, optarg, false) < 0) {
191 fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
198 main_config.name = optarg;
202 main_config.debug_memory = true;
206 main_config.memory_report = true;
207 main_config.debug_memory = true;
214 port = strtoul(optarg, 0, 10);
215 if ((port == 0) || (port > UINT16_MAX)) {
216 fprintf(stderr, "radiusd: Invalid port number \"%s\"\n", optarg);
220 main_config.port = (uint16_t) port;
226 /* Force the PID to be written, even in -f mode */
227 main_config.write_pid = true;
230 case 's': /* Single process mode */
232 main_config.daemonize = false;
235 case 't': /* no child threads */
240 display_version = true;
245 main_config.daemonize = false;
247 main_config.log_auth = true;
248 main_config.log_auth_badpass = true;
249 main_config.log_auth_goodpass = true;
252 default_log.dst = L_DST_STDOUT;
253 default_log.fd = STDOUT_FILENO;
267 * Mismatch between the binary and the libraries it depends on.
269 if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
270 fr_perror("radiusd");
274 if (rad_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) exit(EXIT_FAILURE);
277 * Mismatch between build time OpenSSL and linked SSL, better to die
278 * here than segfault later.
280 #ifdef HAVE_OPENSSL_CRYPTO_H
281 if (ssl_check_consistency() < 0) exit(EXIT_FAILURE);
284 if (flag && (flag != 0x03)) {
285 fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
290 * According to the talloc peeps, no two threads may modify any part of
291 * a ctx tree with a common root without synchronisation.
293 * So we can't run with a null context and threads.
295 if (main_config.memory_report) {
297 fprintf(stderr, "radiusd: The server cannot produce memory reports (-M) in threaded mode\n");
300 talloc_enable_null_tracking();
302 talloc_disable_null_tracking();
306 * Better here, so it doesn't matter whether we get passed -xv or -vx.
308 if (display_version) {
309 /* Don't print timestamps */
312 default_log.dst = L_DST_STDOUT;
313 default_log.fd = STDOUT_FILENO;
315 INFO("%s: %s", main_config.name, radiusd_version);
320 if (rad_debug_lvl) version_print();
323 * Under linux CAP_SYS_PTRACE is usually only available before setuid/setguid,
324 * so we need to check whether we can attach before calling those functions
325 * (in main_config_init()).
327 fr_store_debug_state();
330 * Initialising OpenSSL once, here, is safer than having individual modules do it.
332 #ifdef HAVE_OPENSSL_CRYPTO_H
337 * Write the PID always if we're running as a daemon.
339 if (main_config.daemonize) main_config.write_pid = true;
342 * Read the configuration files, BEFORE doing anything else.
344 if (main_config_init() < 0) exit(EXIT_FAILURE);
347 * This is very useful in figuring out why the panic_action didn't fire.
349 INFO("%s", fr_debug_state_to_msg(fr_debug_state));
352 * Check for vulnerabilities in the version of libssl were linked against.
354 #if defined(HAVE_OPENSSL_CRYPTO_H) && defined(ENABLE_OPENSSL_VERSION_CHECK)
355 if (tls_global_version_check(main_config.allow_vulnerable_openssl) < 0) exit(EXIT_FAILURE);
358 fr_talloc_fault_setup();
361 * Set the panic action (if required)
364 char const *panic_action = NULL;
366 panic_action = getenv("PANIC_ACTION");
367 if (!panic_action) panic_action = main_config.panic_action;
369 if (panic_action && (fr_fault_setup(panic_action, argv[0]) < 0)) {
370 fr_perror("radiusd");
377 * Disconnect from session
379 if (main_config.daemonize) {
384 * Really weird things happen if we leave stdin open and call things like
387 devnull = open("/dev/null", O_RDWR);
389 ERROR("Failed opening /dev/null: %s", fr_syserror(errno));
392 dup2(devnull, STDIN_FILENO);
396 if (pipe(from_child) != 0) {
397 ERROR("Couldn't open pipe for child status: %s", fr_syserror(errno));
403 ERROR("Couldn't fork: %s", fr_syserror(errno));
408 * The parent exits, so the child can run in the background.
410 * As the child can still encounter an error during initialisation
411 * we do a blocking read on a pipe between it and the parent.
413 * Just before entering the event loop the child will send a success
414 * or failure message to the parent, via the pipe.
420 /* So the pipe is correctly widowed if the child exits */
421 close(from_child[1]);
424 * The child writes a 0x01 byte on success, and closes
427 if ((read(from_child[0], &ret, 1) < 0)) {
431 /* For cleanliness... */
432 close(from_child[0]);
434 /* Don't turn children into zombies */
436 waitpid(pid, &stat_loc, WNOHANG);
443 /* so the pipe is correctly widowed if the parent exits?! */
444 close(from_child[0]);
452 * Ensure that we're using the CORRECT pid after forking, NOT the one
455 radius_pid = getpid();
458 * Initialize any event loops just enough so module instantiations can
459 * add fd/event to them, but do not start them yet.
461 * This has to be done post-fork in case we're using kqueue, where the
462 * queue isn't inherited by the child process.
464 if (!radius_event_init(autofree)) exit(EXIT_FAILURE);
469 if (modules_init(main_config.config) < 0) exit(EXIT_FAILURE);
472 * Redirect stderr/stdout as appropriate.
474 if (radlog_init(&default_log, main_config.daemonize) < 0) {
475 ERROR("%s", fr_strerror());
479 event_loop_started = true;
482 * Start the event loop(s) and threads.
484 radius_event_start(main_config.config, spawn_flag);
487 * Now that we've set everything up, we can install the signal
488 * handlers. Before this, if we get any signal, we don't know
489 * what to do, so we might as well do the default, and die.
492 signal(SIGPIPE, SIG_IGN);
495 if ((fr_set_signal(SIGHUP, sig_hup) < 0) ||
496 (fr_set_signal(SIGTERM, sig_fatal) < 0)) {
497 ERROR("%s", fr_strerror());
502 * If we're debugging, then a CTRL-C will cause the server to die
503 * immediately. Use SIGTERM to shut down the server cleanly in
506 if (main_config.debug_memory || (rad_debug_lvl == 0)) {
507 if ((fr_set_signal(SIGINT, sig_fatal) < 0)
509 || (fr_set_signal(SIGQUIT, sig_fatal) < 0)
512 ERROR("%s", fr_strerror());
518 * Everything seems to have loaded OK, exit gracefully.
521 DEBUG("Configuration appears to be OK");
524 if (main_config.debug_memory) goto cleanup;
530 radius_stats_init(0);
534 * Write the PID after we've forked, so that we write the correct one.
536 if (main_config.write_pid) {
539 fp = fopen(main_config.pid_file, "w");
542 * @fixme What about following symlinks,
543 * and having it over-write a normal file?
545 fprintf(fp, "%d\n", (int) radius_pid);
548 ERROR("Failed creating PID file %s: %s", main_config.pid_file, fr_syserror(errno));
553 exec_trigger(NULL, NULL, "server.start", false);
556 * Inform the parent (who should still be waiting) that the rest of
557 * initialisation went OK, and that it should exit with a 0 status.
558 * If we don't get this far, then we just close the pipe on exit, and the
559 * parent gets a read failure.
561 if (main_config.daemonize) {
562 if (write(from_child[1], "\001", 1) < 0) {
563 WARN("Failed informing parent of successful start: %s",
566 close(from_child[1]);
570 * Clear the libfreeradius error buffer.
575 * Initialise the state rbtree (used to link multiple rounds of challenges).
577 state = fr_state_init(NULL);
580 * Process requests until HUP or exit.
582 while ((status = radius_event_process()) == 0x80) {
584 radius_stats_init(1);
589 ERROR("Exiting due to internal error: %s", fr_strerror());
590 rcode = EXIT_FAILURE;
592 INFO("Exiting normally");
596 * Ignore the TERM signal: we're about to die.
598 signal(SIGTERM, SIG_IGN);
601 * Fire signal and stop triggers after ignoring SIGTERM, so handlers are
602 * not killed with the rest of the process group, below.
604 if (status == 2) exec_trigger(NULL, NULL, "server.signal.term", true);
605 exec_trigger(NULL, NULL, "server.stop", false);
608 * Send a TERM signal to all associated processes
609 * (including us, which gets ignored.)
612 if (spawn_flag) kill(-radius_pid, SIGTERM);
616 * We're exiting, so we can delete the PID file.
617 * (If it doesn't exist, we can ignore the error returned by unlink)
619 if (main_config.daemonize) unlink(main_config.pid_file);
625 * Detach any modules.
629 xlat_free(); /* modules may have xlat's */
631 fr_state_delete(state);
634 * Free the configuration items.
642 #ifdef HAVE_OPENSSL_CRYPTO_H
643 tls_global_cleanup();
647 * So we don't see autofreed memory in the talloc report
649 talloc_free(autofree);
651 if (main_config.memory_report) {
652 INFO("Allocated memory at time of report:");
653 fr_log_talloc_report(NULL);
661 * Display the syntax for starting this program.
663 static void NEVER_RETURNS usage(int status)
665 FILE *output = status?stderr:stdout;
667 fprintf(output, "Usage: %s [options]\n", main_config.name);
668 fprintf(output, "Options:\n");
669 fprintf(output, " -C Check configuration and exit.\n");
670 fprintf(stderr, " -d <raddb> Set configuration directory (defaults to " RADDBDIR ").\n");
671 fprintf(stderr, " -D <dictdir> Set main dictionary directory (defaults to " DICTDIR ").\n");
672 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
673 fprintf(output, " -h Print this help message.\n");
674 fprintf(output, " -i <ipaddr> Listen on ipaddr ONLY.\n");
675 fprintf(output, " -l <log_file> Logging output will be written to this file.\n");
676 fprintf(output, " -m On SIGINT or SIGQUIT clean up all used memory instead of just exiting.\n");
677 fprintf(output, " -n <name> Read raddb/name.conf instead of raddb/radiusd.conf.\n");
678 fprintf(output, " -p <port> Listen on port ONLY.\n");
679 fprintf(output, " -P Always write out PID, even with -f.\n");
680 fprintf(output, " -s Do not spawn child processes to handle requests (same as -ft).\n");
681 fprintf(output, " -t Disable threads.\n");
682 fprintf(output, " -v Print server version information.\n");
683 fprintf(output, " -X Turn on full debugging (similar to -tfxxl stdout).\n");
684 fprintf(output, " -x Turn on additional debugging (-xx gives more debugging).\n");
690 * We got a fatal signal.
692 static void sig_fatal(int sig)
694 if (getpid() != radius_pid) _exit(sig);
698 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
705 if (main_config.debug_memory || main_config.memory_report) {
706 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
718 * We got the hangup signal.
719 * Re-read the configuration files.
721 static void sig_hup(UNUSED int sig)
723 reset_signal(SIGHUP, sig_hup);
725 radius_signal_self(RADIUS_SIGNAL_SELF_HUP);