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/log.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)
59 char const *progname = NULL;
60 char const *radius_dir = NULL;
61 char const *radacct_dir = NULL;
62 char const *radlog_dir = NULL;
63 char const *radlib_dir = NULL;
64 int log_stripped_names;
65 log_debug_t debug_flag = 0;
66 int check_config = false;
67 int memory_report = false;
69 char const *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION_STRING
70 #ifdef RADIUSD_VERSION_COMMIT
71 " (git #" RADIUSD_VERSION_COMMIT ")"
73 ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
78 * Configuration items.
84 static void usage(int);
86 static void sig_fatal (int);
88 static void sig_hup (int);
91 #ifdef WITH_VERIFY_PTR
92 static void die_horribly(char const *reason)
94 ERROR("talloc abort: %s\n", reason);
102 int main(int argc, char *argv[])
104 int rcode = EXIT_SUCCESS;
107 int spawn_flag = true;
108 int dont_fork = false;
109 int write_pid = false;
112 #ifdef HAVE_SIGACTION
113 struct sigaction act;
117 set_auth_parameters(argc,argv);
120 if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL)
128 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
129 fprintf(stderr, "%s: Unable to initialize socket library.\n", progname);
137 radius_dir = talloc_strdup(NULL, RADIUS_DIR);
140 * Ensure that the configuration is initialized.
142 memset(&mainconfig, 0, sizeof(mainconfig));
143 mainconfig.myip.af = AF_UNSPEC;
144 mainconfig.port = -1;
145 mainconfig.name = "radiusd";
147 #ifdef HAVE_SIGACTION
148 memset(&act, 0, sizeof(act));
150 sigemptyset( &act.sa_mask ) ;
154 * Don't put output anywhere until we get told a little
157 default_log.dest = L_DST_NULL;
159 mainconfig.log_file = NULL;
161 /* Process the options. */
162 while ((argval = getopt(argc, argv, "Cd:D:fhi:l:mMn:p:PstvxX")) != EOF) {
173 rad_const_free(radius_dir);
175 radius_dir = talloc_strdup(NULL, optarg);
179 mainconfig.dictionary_dir = talloc_strdup(NULL, optarg);
191 if (strcmp(optarg, "stdout") == 0) {
194 mainconfig.log_file = strdup(optarg);
195 default_log.dest = L_DST_FILES;
196 default_log.fd = open(mainconfig.log_file,
197 O_WRONLY | O_APPEND | O_CREAT, 0640);
198 if (default_log.fd < 0) {
199 fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno));
202 fr_log_fp = fdopen(default_log.fd, "a");
206 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
207 fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
214 mainconfig.name = optarg;
218 mainconfig.debug_memory = 1;
223 mainconfig.debug_memory = 1;
227 mainconfig.port = atoi(optarg);
228 if ((mainconfig.port <= 0) ||
229 (mainconfig.port >= 65536)) {
230 fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
237 /* Force the PID to be written, even in -f mode */
241 case 's': /* Single process mode */
246 case 't': /* no child threads */
251 /* Don't print timestamps */
254 default_log.dest = L_DST_STDOUT;
255 default_log.fd = STDOUT_FILENO;
263 mainconfig.log_auth = true;
264 mainconfig.log_auth_badpass = true;
265 mainconfig.log_auth_goodpass = true;
268 default_log.dest = L_DST_STDOUT;
269 default_log.fd = STDOUT_FILENO;
283 talloc_enable_null_tracking();
284 talloc_set_log_fn(log_talloc);
285 #ifdef WITH_VERIFY_PTR
286 talloc_set_abort_fn(die_horribly);
292 * Mismatch between build time OpenSSL and linked SSL,
293 * better to die here than segfault later.
295 #ifdef HAVE_OPENSSL_CRYPTO_H
296 if (ssl_check_version() < 0) {
301 if (flag && (flag != 0x03)) {
302 fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
310 /* Read the configuration files, BEFORE doing anything else. */
311 if (read_mainconfig(0) < 0) {
317 * Disconnect from session
319 if (dont_fork == false) {
323 ERROR("Couldn't fork: %s", strerror(errno));
328 * The parent exits, so the child can run in the background.
340 * Ensure that we're using the CORRECT pid after forking,
341 * NOT the one we started with.
343 radius_pid = getpid();
346 * If we're running as a daemon, close the default file
347 * descriptors, AFTER forking.
352 devnull = open("/dev/null", O_RDWR);
354 ERROR("Failed opening /dev/null: %s\n",
358 dup2(devnull, STDIN_FILENO);
359 if (default_log.dest == L_DST_STDOUT) {
361 default_log.fd = STDOUT_FILENO;
363 dup2(devnull, STDOUT_FILENO);
365 if (default_log.dest == L_DST_STDERR) {
367 default_log.fd = STDERR_FILENO;
369 dup2(devnull, STDERR_FILENO);
374 setlinebuf(stdout); /* unbuffered output */
378 * Now we have logging check that the OpenSSL
382 * Initialize the event pool, including threads.
384 radius_event_init(mainconfig.config, spawn_flag);
387 * Now that we've set everything up, we can install the signal
388 * handlers. Before this, if we get any signal, we don't know
389 * what to do, so we might as well do the default, and die.
392 signal(SIGPIPE, SIG_IGN);
394 #ifdef HAVE_SIGACTION
395 act.sa_handler = sig_hup;
396 sigaction(SIGHUP, &act, NULL);
397 act.sa_handler = sig_fatal;
398 sigaction(SIGTERM, &act, NULL);
401 signal(SIGHUP, sig_hup);
403 signal(SIGTERM, sig_fatal);
406 * If we're debugging, then a CTRL-C will cause the
407 * server to die immediately. Use SIGTERM to shut down
408 * the server cleanly in that case.
410 if ((mainconfig.debug_memory == 1) || (debug_flag == 0)) {
411 #ifdef HAVE_SIGACTION
412 act.sa_handler = sig_fatal;
413 sigaction(SIGINT, &act, NULL);
414 sigaction(SIGQUIT, &act, NULL);
416 signal(SIGINT, sig_fatal);
418 signal(SIGQUIT, sig_fatal);
424 * Everything seems to have loaded OK, exit gracefully.
427 DEBUG("Configuration appears to be OK.");
430 if (mainconfig.debug_memory) {
438 radius_stats_init(0);
442 * Write out the PID anyway if were in foreground mode.
444 if (!dont_fork) write_pid = true;
447 * Only write the PID file if we're running as a daemon.
449 * And write it AFTER we've forked, so that we write the
455 fp = fopen(mainconfig.pid_file, "w");
458 * FIXME: What about following symlinks,
459 * and having it over-write a normal file?
461 fprintf(fp, "%d\n", (int) radius_pid);
464 ERROR("Failed creating PID file %s: %s\n",
465 mainconfig.pid_file, strerror(errno));
470 exec_trigger(NULL, NULL, "server.start", false);
473 * Process requests until HUP or exit.
475 while ((status = radius_event_process()) == 0x80) {
477 radius_stats_init(1);
482 ERROR("Exiting due to internal error: %s", fr_strerror());
483 rcode = EXIT_FAILURE;
485 INFO("Exiting normally.");
488 exec_trigger(NULL, NULL, "server.stop", false);
491 * Ignore the TERM signal: we're
494 signal(SIGTERM, SIG_IGN);
497 * Send a TERM signal to all
498 * associated processes
499 * (including us, which gets
503 if (spawn_flag) kill(-radius_pid, SIGTERM);
507 * We're exiting, so we can delete the PID
508 * file. (If it doesn't exist, we can ignore
509 * the error returned by unlink)
511 if (dont_fork == false) {
512 unlink(mainconfig.pid_file);
519 * Detach any modules.
523 xlat_free(); /* modules may have xlat's */
526 * Free the configuration items.
530 rad_const_free(radius_dir);
537 INFO("Allocated memory at time of report:");
538 log_talloc_report(NULL);
546 * Display the syntax for starting this program.
548 static void NEVER_RETURNS usage(int status)
550 FILE *output = status?stderr:stdout;
553 "Usage: %s [-d db_dir] [-l log_dir] [-i address] [-n name] [-fsvXx]\n", progname);
554 fprintf(output, "Options:\n\n");
555 fprintf(output, " -C Check configuration and exit.\n");
556 fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
557 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
558 fprintf(output, " -h Print this help message.\n");
559 fprintf(output, " -i ipaddr Listen on ipaddr ONLY.\n");
560 fprintf(output, " -l log_file Logging output will be written to this file.\n");
561 fprintf(output, " -m On SIGINT or SIGQUIT exit cleanly instead of immediately.\n");
562 fprintf(output, " -n name Read raddb/name.conf instead of raddb/radiusd.conf\n");
563 fprintf(output, " -p port Listen on port ONLY.\n");
564 fprintf(output, " -P Always write out PID, even with -f");
565 fprintf(output, " -s Do not spawn child processes to handle requests.\n");
566 fprintf(output, " -t Disable threads.\n");
567 fprintf(output, " -v Print server version information.\n");
568 fprintf(output, " -X Turn on full debugging.\n");
569 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
575 * We got a fatal signal.
577 static void sig_fatal(int sig)
579 if (getpid() != radius_pid) _exit(sig);
583 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
590 if (mainconfig.debug_memory || memory_report) {
591 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
603 * We got the hangup signal.
604 * Re-read the configuration files.
606 static void sig_hup(UNUSED int sig)
608 reset_signal(SIGHUP, sig_hup);
610 radius_signal_self(RADIUS_SIGNAL_SELF_HUP);