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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000,2001,2002,2003,2004 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 /* don't look here for the version, run radiusd -v or look in version.c */
29 static const char rcsid[] =
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
55 #ifdef HAVE_SYS_SELECT_H
56 # include <sys/select.h>
59 #ifdef HAVE_SYS_WAIT_H
60 # include <sys/wait.h>
63 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
66 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
70 #include "rad_assert.h"
73 #include "request_list.h"
74 #include "radius_snmp.h"
76 #define SLEEP_FOREVER (65536)
81 const char *progname = NULL;
82 const char *radius_dir = NULL;
83 const char *radacct_dir = NULL;
84 const char *radlog_dir = NULL;
85 const char *radlib_dir = NULL;
86 int log_stripped_names;
88 int log_auth_detail = FALSE;
89 int need_reload = FALSE;
90 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
93 static pid_t radius_pid;
96 * Configuration items.
98 static int do_exit = 0;
103 static void usage(int);
105 static void sig_fatal (int);
106 static void sig_hup (int);
111 int main(int argc, char *argv[])
114 unsigned char buffer[4096];
120 int sleep_time = SLEEP_FOREVER;
121 int spawn_flag = TRUE;
122 int dont_fork = FALSE;
123 int sig_hup_block = FALSE;
124 time_t last_cleaned_lists = 0;
126 #ifdef HAVE_SIGACTION
127 struct sigaction act;
129 rad_listen_t *listener;
132 set_auth_parameters(argc,argv);
135 if ((progname = strrchr(argv[0], '/')) == NULL)
142 radius_dir = strdup(RADIUS_DIR);
145 * Ensure that the configuration is initialized.
147 memset(&mainconfig, 0, sizeof(mainconfig));
148 mainconfig.myip.af = AF_UNSPEC;
149 mainconfig.port = -1;
150 mainconfig.radiusd_conf = "radiusd.conf";
152 #ifdef HAVE_SIGACTION
153 memset(&act, 0, sizeof(act));
155 sigemptyset( &act.sa_mask ) ;
158 /* Process the options. */
159 while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:n:p:sSvxXyz")) != EOF) {
164 log_auth_detail = TRUE;
168 if (radacct_dir) free(radacct_dir);
169 radacct_dir = strdup(optarg);
173 /* ignore for backwards compatibility with Cistron */
177 if (radius_dir) free(radius_dir);
178 radius_dir = strdup(optarg);
190 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
191 fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
197 if ((strcmp(optarg, "stdout") == 0) ||
198 (strcmp(optarg, "stderr") == 0) ||
199 (strcmp(optarg, "syslog") == 0)) {
200 fprintf(stderr, "radiusd: -l %s is unsupported. Use log_destination in radiusd.conf\n", optarg);
203 radlog_dir = strdup(optarg);
207 fprintf(stderr, "radiusd: -g is unsupported. Use log_destination in radiusd.conf.\n");
212 if ((strchr(optarg, '/') != NULL) ||
213 (strchr(optarg, '.') != NULL) ||
214 (strlen(optarg) > 256)) usage(1);
216 snprintf(buffer, sizeof(buffer), "%s.conf",
218 mainconfig.radiusd_conf = strdup(buffer);
222 log_stripped_names++;
226 mainconfig.port = atoi(optarg);
227 if ((mainconfig.port <= 0) ||
228 (mainconfig.port >= 65536)) {
229 fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
234 case 's': /* Single process mode */
244 * BIG debugging mode for users who are
245 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
251 mainconfig.log_auth = TRUE;
252 mainconfig.log_auth_badpass = TRUE;
253 mainconfig.log_auth_goodpass = TRUE;
254 mainconfig.radlog_dest = RADLOG_STDOUT;
262 mainconfig.log_auth = TRUE;
263 mainconfig.log_auth_badpass = TRUE;
267 mainconfig.log_auth_badpass = TRUE;
268 mainconfig.log_auth_goodpass = TRUE;
280 radius_pid = getpid();
282 /* Read the configuration files, BEFORE doing anything else. */
283 if (read_mainconfig(0) < 0) {
288 * If we're NOT debugging, trap fatal signals, so we can
289 * easily clean up after ourselves.
291 * If we ARE debugging, don't trap them, so we can
294 if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
296 #ifdef HAVE_SIGACTION
297 act.sa_handler = sig_fatal;
298 sigaction(SIGSEGV, &act, NULL);
300 signal(SIGSEGV, sig_fatal);
305 /* Reload the modules. */
306 DEBUG2("radiusd: entering modules setup");
307 if (setup_modules(1) < 0) {
308 radlog(L_ERR|L_CONS, "Errors setting up modules");
313 if (mainconfig.do_snmp) radius_snmp_init();
317 * Disconnect from session
319 if (debug_flag == 0 && dont_fork == FALSE) {
322 radlog(L_ERR|L_CONS, "Couldn't fork");
327 * The parent exits, so the child can run in the background.
338 * Ensure that we're using the CORRECT pid after forking,
339 * NOT the one we started with.
341 radius_pid = getpid();
345 * Only write the PID file if we're running as a daemon.
347 * And write it AFTER we've forked, so that we write the
350 if (dont_fork == FALSE) {
353 fp = fopen(mainconfig.pid_file, "w");
356 * FIXME: What about following symlinks,
357 * and having it over-write a normal file?
359 fprintf(fp, "%d\n", (int) radius_pid);
362 radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
363 mainconfig.pid_file, strerror(errno));
369 * If we're running as a daemon, close the default file
370 * descriptors, AFTER forking.
372 mainconfig.radlog_fd = -1;
374 mainconfig.radlog_fd = STDOUT_FILENO;
378 devnull = open("/dev/null", O_RDWR);
380 radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
384 dup2(devnull, STDIN_FILENO);
385 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
386 mainconfig.radlog_fd = dup(STDOUT_FILENO);
388 dup2(devnull, STDOUT_FILENO);
389 if (mainconfig.radlog_dest == RADLOG_STDERR) {
390 mainconfig.radlog_fd = dup(STDERR_FILENO);
392 dup2(devnull, STDERR_FILENO);
397 * It's called the thread pool, but it does a little
400 thread_pool_init(spawn_flag);
403 * Use linebuffered or unbuffered stdout if
404 * the debug flag is on.
406 if (debug_flag == TRUE)
410 * Print out which ports we're listening on.
412 for (listener = mainconfig.listen;
414 listener = listener->next) {
415 if ((listener->ipaddr.af == AF_INET) &&
416 (listener->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
419 ip_ntoh(&listener->ipaddr, buffer, sizeof(buffer));
422 switch (listener->type) {
423 case RAD_LISTEN_AUTH:
424 DEBUG("Listening on authentication address %s port %d",
425 buffer, listener->port);
428 case RAD_LISTEN_ACCT:
429 DEBUG("Listening on accounting address %s port %d",
430 buffer, listener->port);
433 case RAD_LISTEN_PROXY:
434 DEBUG("Listening on proxy address %s port %d",
435 buffer, listener->port);
438 case RAD_LISTEN_DETAIL:
439 DEBUG("Listening on detail file %s", listener->detail);
448 * Now that we've set everything up, we can install the signal
449 * handlers. Before this, if we get any signal, we don't know
450 * what to do, so we might as well do the default, and die.
452 signal(SIGPIPE, SIG_IGN);
453 #ifdef HAVE_SIGACTION
454 act.sa_handler = sig_hup;
455 sigaction(SIGHUP, &act, NULL);
456 act.sa_handler = sig_fatal;
457 sigaction(SIGTERM, &act, NULL);
459 signal(SIGHUP, sig_hup);
460 signal(SIGTERM, sig_fatal);
463 * If we're debugging, then a CTRL-C will cause the
464 * server to die immediately. Use SIGTERM to shut down
465 * the server cleanly in that case.
467 if (debug_flag == 0) {
468 #ifdef HAVE_SIGACTION
469 act.sa_handler = sig_fatal;
470 sigaction(SIGINT, &act, NULL);
471 sigaction(SIGQUIT, &act, NULL);
473 signal(SIGINT, sig_fatal);
474 signal(SIGQUIT, sig_fatal);
478 radlog(L_INFO, "Ready to process requests.");
481 * Receive user requests
485 * If we've been told to exit, then do so,
486 * even if we have data waiting.
492 * Ignore the TERM signal: we're about
495 signal(SIGTERM, SIG_IGN);
498 * Send a TERM signal to all associated
499 * processes (including us, which gets
502 kill(-radius_pid, SIGTERM);
505 * FIXME: Kill child threads, and
510 * Detach any modules.
515 * FIXME: clean up any active REQUEST
520 * We're exiting, so we can delete the PID
521 * file. (If it doesn't exist, we can ignore
522 * the error returned by unlink)
524 if (dont_fork == FALSE) {
525 unlink(mainconfig.pid_file);
529 * Free the configuration items.
534 * SIGTERM gets do_exit=0,
535 * and we want to exit cleanly.
537 * Other signals make us exit
538 * with an error status.
544 #ifdef HAVE_PTHREAD_H
546 * Threads: wait for all threads to stop
547 * processing before re-loading the
548 * config, so we don't pull the rug out
552 if (!spawn_flag) for(;;) {
554 * Block until there are '0' threads
555 * with a REQUEST handle.
557 sig_hup_block = TRUE;
558 if( (total_active_threads() == 0) ||
560 sig_hup_block = FALSE;
567 if (read_mainconfig(TRUE) < 0) {
571 /* Reload the modules. */
572 DEBUG2("radiusd: entering modules setup");
573 if (setup_modules(0) < 0) {
574 radlog(L_ERR|L_CONS, "Errors setting up modules");
579 radlog(L_INFO, "Ready to process requests.");
586 * Loop over all the listening FD's.
588 for (listener = mainconfig.listen;
590 listener = listener->next) {
591 if (listener->fd < 0) continue;
593 FD_SET(listener->fd, &readfds);
594 if (listener->fd > max_fd) max_fd = listener->fd;
598 if (mainconfig.do_snmp &&
599 (rad_snmp.smux_fd >= 0)) {
600 FD_SET(rad_snmp.smux_fd, &readfds);
601 if (rad_snmp.smux_fd > max_fd) max_fd = rad_snmp.smux_fd;
605 if (sleep_time == SLEEP_FOREVER) {
606 DEBUG2("Nothing to do. Sleeping until we see a request.");
607 status = select(max_fd + 1, &readfds, NULL, NULL, NULL);
611 DEBUG2("Waking up in %d seconds...", sleep_time);
613 tv.tv_sec = sleep_time;
615 status = select(max_fd + 1, &readfds, NULL, NULL, &tv);
619 * On interrupts, we clean up the request
620 * list. We then continue with the loop,
621 * so that if we're supposed to exit,
622 * then the code at the start of the loop
623 * catches that, and exits.
625 if (errno == EINTR) {
626 #ifdef MEMORY_USE_DEBUGGING
628 * Run the server in debugging mode,
629 * without threads, and give it a
630 * SIGHUP. It will clean up after
631 * itself, and any memory left over
632 * should be allocated by C libraries,
643 radlog(L_ERR, "Unexpected error in select(): %s",
648 time_now = time(NULL);
649 #ifndef HAVE_PTHREAD_H
651 * If there are no child threads, then there may
652 * be child processes. In that case, wait for
653 * their exit status, and throw that exit status
654 * away. This helps get rid of zxombie children.
656 while (waitpid(-1, &argval, WNOHANG) > 0) {
662 * Loop over the open socket FD's, reading any data.
664 for (listener = mainconfig.listen;
666 listener = listener->next) {
667 RAD_REQUEST_FUNP fun;
669 if ((listener->fd >= 0) &&
670 !FD_ISSET(listener->fd, &readfds))
674 * Receive the packet.
676 if (sig_hup_block != FALSE) {
681 * Do per-socket receive processing of the
684 if (!listener->recv(listener, &fun, &request)) {
689 * Drop the request into the thread pool,
690 * and let the thread pool take care of
691 * doing something with it.
693 if (!thread_pool_addrequest(request, fun)) {
695 * FIXME: Maybe just drop
696 * the packet on the floor?
698 request_reject(request, REQUEST_FAIL_NO_THREADS);
699 request->finished = TRUE;
701 } /* loop over listening sockets*/
704 if (mainconfig.do_snmp) {
706 * After handling all authentication/accounting
707 * requests, THEN process any pending SMUX/SNMP
710 * Note that the handling is done in the main server,
711 * which probably isn't a Good Thing. It really
712 * should be wrapped, and handled in a thread pool.
714 if ((rad_snmp.smux_fd >= 0) &&
715 FD_ISSET(rad_snmp.smux_fd, &readfds) &&
716 (rad_snmp.smux_event == SMUX_READ)) {
721 * If we've got to re-connect, then do so now,
722 * before calling select again.
724 if (rad_snmp.smux_event == SMUX_CONNECT) {
731 * Loop through the request lists once per
732 * second, to clean up old requests.
734 if (last_cleaned_lists != time_now) {
735 last_cleaned_lists = time_now;
737 DEBUG2("--- Walking the entire request list ---");
738 sleep_time = SLEEP_FOREVER;
739 for (listener = mainconfig.listen;
741 listener = listener->next) {
744 next = listener->update(listener, time_now);
745 if (next < sleep_time) {
751 #ifdef HAVE_PTHREAD_H
754 * Only clean the thread pool if we're spawning
758 thread_pool_clean(time_now);
766 * Display the syntax for starting this program.
768 static void usage(int status)
770 FILE *output = status?stderr:stdout;
773 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
774 fprintf(output, "Options:\n\n");
775 fprintf(output, " -a acct_dir use accounting directory 'acct_dir'.\n");
776 fprintf(output, " -A Log auth detail.\n");
777 fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
778 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
779 fprintf(output, " -h Print this help message.\n");
780 fprintf(output, " -i ipaddr Listen on ipaddr ONLY\n");
781 fprintf(output, " -l log_dir Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
782 fprintf(output, " -p port Listen on port ONLY\n");
783 fprintf(output, " -s Do not spawn child processes to handle requests.\n");
784 fprintf(output, " -S Log stripped names.\n");
785 fprintf(output, " -v Print server version information.\n");
786 fprintf(output, " -X Turn on full debugging.\n");
787 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
788 fprintf(output, " -y Log authentication failures, with password.\n");
789 fprintf(output, " -z Log authentication successes, with password.\n");
795 * We got a fatal signal.
797 static void sig_fatal(int sig)
801 /* We can't really do anything intelligent here so just die */
814 * We got the hangup signal.
815 * Re-read the configuration files.
818 static void sig_hup(int sig)
820 sig = sig; /* -Wunused */
822 reset_signal(SIGHUP, sig_hup);
825 * Only do the reload if we're the main server, both
826 * for processes, and for threads.
828 if (getpid() == radius_pid) {
832 if (mainconfig.do_snmp) {
833 rad_snmp.smux_failures = 0;
834 rad_snmp.smux_event = SMUX_CONNECT;