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-2004,2006 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>
28 #include <freeradius-devel/ident.h>
31 #include <freeradius-devel/radiusd.h>
32 #include <freeradius-devel/modules.h>
33 #include <freeradius-devel/rad_assert.h>
46 #ifdef HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
50 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
53 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
56 #ifdef HAVE_OPENSSL_CRYPTO_H
57 #include <openssl/ssl.h>
63 const char *progname = NULL;
64 const char *radius_dir = NULL;
65 const char *radacct_dir = NULL;
66 const char *radlog_dir = NULL;
67 const char *radlib_dir = NULL;
68 int log_stripped_names;
70 int check_config = FALSE;
72 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
73 #ifdef RADIUSD_VERSION_COMMIT
74 " (git #" RADIUSD_VERSION_COMMIT ")"
76 ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
81 * Configuration items.
87 static void usage(int);
89 static void sig_fatal (int);
91 static void sig_hup (int);
97 int main(int argc, char *argv[])
101 int spawn_flag = TRUE;
102 int dont_fork = FALSE;
104 int from_child[2] = {-1, -1};
109 * If the server was built with debugging enabled always install
110 * the basic fatal signal handlers.
113 fr_fault_setup(getenv("PANIC_ACTION"), argv[0]);
116 #ifdef HAVE_SIGACTION
117 struct sigaction act;
121 set_auth_parameters(argc,argv);
124 if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
132 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
133 fprintf(stderr, "%s: Unable to initialize socket library.\n");
141 radius_dir = strdup(RADIUS_DIR);
144 * Ensure that the configuration is initialized.
146 memset(&mainconfig, 0, sizeof(mainconfig));
147 mainconfig.myip.af = AF_UNSPEC;
148 mainconfig.port = -1;
149 mainconfig.name = "radiusd";
151 #ifdef HAVE_SIGACTION
152 memset(&act, 0, sizeof(act));
154 sigemptyset( &act.sa_mask ) ;
158 * Don't put output anywhere until we get told a little
161 mainconfig.radlog_dest = RADLOG_NULL;
162 mainconfig.radlog_fd = -1;
163 mainconfig.log_file = NULL;
165 /* Process the options. */
166 while ((argval = getopt(argc, argv, "Cd:fhi:l:mn:p:stvxX")) != EOF) {
176 if (radius_dir) free(radius_dir);
177 radius_dir = strdup(optarg);
189 if (strcmp(optarg, "stdout") == 0) {
192 mainconfig.log_file = strdup(optarg);
193 mainconfig.radlog_dest = RADLOG_FILES;
194 mainconfig.radlog_fd = open(mainconfig.log_file,
195 O_WRONLY | O_APPEND | O_CREAT, 0640);
196 if (mainconfig.radlog_fd < 0) {
197 fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno));
200 fr_log_fp = fdopen(mainconfig.radlog_fd, "a");
204 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
205 fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
212 mainconfig.name = optarg;
216 mainconfig.debug_memory = 1;
220 mainconfig.port = atoi(optarg);
221 if ((mainconfig.port <= 0) ||
222 (mainconfig.port >= 65536)) {
223 fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
229 case 's': /* Single process mode */
234 case 't': /* no child threads */
239 /* Don't print timestamps */
242 mainconfig.radlog_dest = RADLOG_STDOUT;
243 mainconfig.radlog_fd = STDOUT_FILENO;
251 mainconfig.log_auth = TRUE;
252 mainconfig.log_auth_badpass = TRUE;
253 mainconfig.log_auth_goodpass = TRUE;
256 mainconfig.radlog_dest = RADLOG_STDOUT;
257 mainconfig.radlog_fd = STDOUT_FILENO;
270 if (flag && (flag != 0x03)) {
271 fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
279 /* Read the configuration files, BEFORE doing anything else. */
280 if (read_mainconfig(0) < 0) {
284 #ifdef HAVE_OPENSSL_CRYPTO_H
286 * Initialize the OpenSSL library before calling any of its
290 SSL_load_error_strings();
293 * Mismatch between build time OpenSSL and linked SSL,
294 * better to die here than segfault later.
296 if (ssl_check_version() < 0) {
301 * Check for known vulnerabilities that compromise the
302 * security of the server.
304 # ifdef ENABLE_OPENSSL_VERSION_CHECK
305 if (!mainconfig.allow_vulnerable_openssl) {
306 if (ssl_check_vulnerable() < 0) {
314 /* Load the modules AFTER doing SSL checks */
315 if (setup_modules(FALSE, mainconfig.config) < 0) {
319 /* Set the panic action (if required) */
320 if (mainconfig.panic_action &&
322 !getenv("PANIC_ACTION") &&
324 (fr_fault_setup(mainconfig.panic_action, argv[0]) < 0)) {
330 devnull = open("/dev/null", O_RDWR);
332 radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n", strerror(errno));
337 * Disconnect from session
339 if (dont_fork == FALSE) {
343 * Really weird things happen if we leave stdin open and call
344 * things like system() later.
346 if (dont_fork == 0) {
347 dup2(devnull, STDIN_FILENO);
350 if (pipe(from_child) != 0) {
351 radlog(L_ERR, "Couldn't open pipe for child status: %s", strerror(errno));
357 radlog(L_ERR, "Couldn't fork: %s", strerror(errno));
362 * The parent exits, so the child can run in the background.
364 * As the child can still encounter an error during initialisation
365 * we do a blocking read on a pipe between it and the parent.
367 * Just before entering the event loop the child will
373 /* So the pipe is correctly widowed if the child exits */
374 close(from_child[1]);
376 if ((read(from_child[0], &ret, 1) < 0)) {
380 /* For cleanliness... */
381 close(from_child[0]);
383 /* Don't turn children into zombies */
385 waitpid(pid, &stat_loc, WNOHANG);
392 /* so the pipe is correctly widowed if the parent exits?! */
393 close(from_child[0]);
401 * Ensure that we're using the CORRECT pid after forking,
402 * NOT the one we started with.
404 radius_pid = getpid();
407 * STDOUT & STDERR go to /dev/null, unless we have "-x",
408 * then STDOUT & STDERR go to the "-l log" destination.
410 * The complexity here is because "-l log" can go to
411 * STDOUT or STDERR, too.
413 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
415 mainconfig.radlog_fd = STDOUT_FILENO;
418 * If we're debugging, allow STDERR to go to
419 * STDOUT too, for executed programs,
422 dup2(STDOUT_FILENO, STDERR_FILENO);
424 dup2(devnull, STDERR_FILENO);
427 } else if (mainconfig.radlog_dest == RADLOG_STDERR) {
429 mainconfig.radlog_fd = STDERR_FILENO;
432 * If we're debugging, allow STDOUT to go to
433 * STDERR too, for executed programs,
436 dup2(STDERR_FILENO, STDOUT_FILENO);
438 dup2(devnull, STDOUT_FILENO);
441 } else if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
443 * Discard STDOUT and STDERR no matter what the
444 * status of debugging. Syslog isn't a file
445 * descriptor, so we can't use it.
447 dup2(devnull, STDOUT_FILENO);
448 dup2(devnull, STDERR_FILENO);
450 } else if (debug_flag) {
452 * If we're debugging, allow STDOUT and STDERR to
453 * go to the log file.
455 dup2(mainconfig.radlog_fd, STDOUT_FILENO);
456 dup2(mainconfig.radlog_fd, STDERR_FILENO);
460 * Not debugging, and the log isn't STDOUT or
461 * STDERR. Ensure that we move both of them to
462 * /dev/null, so that the calling terminal can
463 * exit, and the output from executed programs
464 * doesn't pollute STDOUT / STDERR.
466 dup2(devnull, STDOUT_FILENO);
467 dup2(devnull, STDERR_FILENO);
473 * Now we have logging check that the OpenSSL
477 * Initialize the event pool, including threads.
479 radius_event_init(mainconfig.config, spawn_flag);
482 * Now that we've set everything up, we can install the signal
483 * handlers. Before this, if we get any signal, we don't know
484 * what to do, so we might as well do the default, and die.
487 signal(SIGPIPE, SIG_IGN);
489 #ifdef HAVE_SIGACTION
490 act.sa_handler = sig_hup;
491 sigaction(SIGHUP, &act, NULL);
492 act.sa_handler = sig_fatal;
493 sigaction(SIGTERM, &act, NULL);
496 signal(SIGHUP, sig_hup);
498 signal(SIGTERM, sig_fatal);
501 * If we're debugging, then a CTRL-C will cause the
502 * server to die immediately. Use SIGTERM to shut down
503 * the server cleanly in that case.
505 if ((mainconfig.debug_memory == 1) || (debug_flag == 0)) {
506 #ifdef HAVE_SIGACTION
507 act.sa_handler = sig_fatal;
508 sigaction(SIGINT, &act, NULL);
509 sigaction(SIGQUIT, &act, NULL);
511 signal(SIGINT, sig_fatal);
513 signal(SIGQUIT, sig_fatal);
519 * Everything seems to have loaded OK, exit gracefully.
522 DEBUG("Configuration appears to be OK.");
526 radius_stats_init(0);
529 * Only write the PID file if we're running as a daemon.
531 * And write it AFTER we've forked, so that we write the
534 if (dont_fork == FALSE) {
537 fp = fopen(mainconfig.pid_file, "w");
540 * FIXME: What about following symlinks,
541 * and having it over-write a normal file?
543 fprintf(fp, "%d\n", (int) radius_pid);
546 radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
547 mainconfig.pid_file, strerror(errno));
552 * Inform parent (who should still be waiting) that
553 * the rest of initialisation went OK, and that it
554 * should exit with a 0 status.
556 write(from_child[1], "\001", 1);
557 close(from_child[1]);
561 * Process requests until HUP or exit.
563 while ((rcode = radius_event_process()) == 0x80) {
564 radius_stats_init(1);
569 radlog(L_ERR, "Exiting due to internal error: %s",
573 radlog(L_INFO, "Exiting normally.");
578 * Ignore the TERM signal: we're
581 signal(SIGTERM, SIG_IGN);
584 * Send a TERM signal to all
585 * associated processes
586 * (including us, which gets
590 if (spawn_flag) kill(-radius_pid, SIGTERM);
594 * We're exiting, so we can delete the PID
595 * file. (If it doesn't exist, we can ignore
596 * the error returned by unlink)
598 if (dont_fork == FALSE) {
599 unlink(mainconfig.pid_file);
605 * Detach any modules.
609 xlat_free(); /* modules may have xlat's */
612 * Free the configuration items.
627 * Display the syntax for starting this program.
629 static void NEVER_RETURNS usage(int status)
631 FILE *output = status?stderr:stdout;
634 "Usage: %s [-d db_dir] [-l log_dir] [-i address] [-n name] [-fsvXx]\n", progname);
635 fprintf(output, "Options:\n\n");
636 fprintf(output, " -C Check configuration and exit.\n");
637 fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
638 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
639 fprintf(output, " -h Print this help message.\n");
640 fprintf(output, " -i ipaddr Listen on ipaddr ONLY.\n");
641 fprintf(output, " -l log_file Logging output will be written to this file.\n");
642 fprintf(output, " -m On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
643 fprintf(output, " -n name Read raddb/name.conf instead of raddb/radiusd.conf\n");
644 fprintf(output, " -p port Listen on port ONLY.\n");
645 fprintf(output, " -s Do not spawn child processes to handle requests.\n");
646 fprintf(output, " -t Disable threads.\n");
647 fprintf(output, " -v Print server version information.\n");
648 fprintf(output, " -X Turn on full debugging.\n");
649 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
655 * We got a fatal signal.
657 static void sig_fatal(int sig)
659 if (getpid() != radius_pid) _exit(sig);
663 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
670 if (mainconfig.debug_memory) {
671 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
683 * We got the hangup signal.
684 * Re-read the configuration files.
686 static void sig_hup(int sig)
688 sig = sig; /* -Wunused */
690 reset_signal(SIGHUP, sig_hup);
692 radius_signal_self(RADIUS_SIGNAL_SELF_HUP);