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/radius_snmp.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 const char *progname = NULL;
60 const char *radius_dir = NULL;
61 const char *radacct_dir = NULL;
62 const char *radlog_dir = NULL;
63 const char *radlib_dir = NULL;
64 int log_stripped_names;
66 int log_auth_detail = FALSE;
67 int need_reload = FALSE;
69 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
72 static pid_t radius_pid;
73 static int debug_memory = 0;
76 * Configuration items.
78 static int do_exit = 0;
83 static void usage(int);
85 static void sig_fatal (int);
86 static void sig_hup (int);
91 int main(int argc, char *argv[])
94 unsigned char buffer[4096];
100 int spawn_flag = TRUE;
101 int dont_fork = FALSE;
102 int sig_hup_block = FALSE;
103 struct timeval tv, *ptv = NULL;
105 #ifdef HAVE_SIGACTION
106 struct sigaction act;
108 rad_listen_t *listener;
111 set_auth_parameters(argc,argv);
114 if ((progname = strrchr(argv[0], '/')) == NULL)
121 radius_dir = strdup(RADIUS_DIR);
124 * Ensure that the configuration is initialized.
126 memset(&mainconfig, 0, sizeof(mainconfig));
127 mainconfig.myip.af = AF_UNSPEC;
128 mainconfig.port = -1;
129 mainconfig.radiusd_conf = strdup("radiusd.conf");
131 #ifdef HAVE_SIGACTION
132 memset(&act, 0, sizeof(act));
134 sigemptyset( &act.sa_mask ) ;
138 * Don't put output anywhere until we get told a little
141 mainconfig.radlog_fd = -1;
142 mainconfig.log_file = NULL;
144 /* Process the options. */
145 while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mn:p:sSvxXyz")) != EOF) {
150 log_auth_detail = TRUE;
154 if (radacct_dir) free(radacct_dir);
155 radacct_dir = strdup(optarg);
159 /* ignore for backwards compatibility with Cistron */
163 if (radius_dir) free(radius_dir);
164 radius_dir = strdup(optarg);
176 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
177 fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
183 if ((strcmp(optarg, "stdout") == 0) ||
184 (strcmp(optarg, "stderr") == 0) ||
185 (strcmp(optarg, "syslog") == 0)) {
186 fprintf(stderr, "radiusd: -l %s is unsupported. Use log_destination in radiusd.conf\n", optarg);
189 if (radlog_dir) free(radlog_dir);
190 radlog_dir = strdup(optarg);
194 fprintf(stderr, "radiusd: -g is unsupported. Use log_destination in radiusd.conf.\n");
203 if ((strchr(optarg, '/') != NULL) ||
204 (strchr(optarg, '.') != NULL) ||
205 (strlen(optarg) > 45)) usage(1);
207 snprintf(buffer, sizeof(buffer), "%s.conf",
209 if (mainconfig.radiusd_conf)
210 free(mainconfig.radiusd_conf);
211 mainconfig.radiusd_conf = strdup(buffer);
215 log_stripped_names++;
219 mainconfig.port = atoi(optarg);
220 if ((mainconfig.port <= 0) ||
221 (mainconfig.port >= 65536)) {
222 fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
227 case 's': /* Single process mode */
237 * BIG debugging mode for users who are
238 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
244 mainconfig.log_auth = TRUE;
245 mainconfig.log_auth_badpass = TRUE;
246 mainconfig.log_auth_goodpass = TRUE;
247 mainconfig.radlog_dest = RADLOG_STDOUT;
248 mainconfig.radlog_fd = STDOUT_FILENO;
256 mainconfig.log_auth = TRUE;
257 mainconfig.log_auth_badpass = TRUE;
261 mainconfig.log_auth_badpass = TRUE;
262 mainconfig.log_auth_goodpass = TRUE;
271 /* Read the configuration files, BEFORE doing anything else. */
272 if (read_mainconfig(0) < 0) {
277 * Disconnect from session
279 if (debug_flag == 0 && dont_fork == FALSE) {
282 radlog(L_ERR|L_CONS, "Couldn't fork");
287 * The parent exits, so the child can run in the background.
298 * If we're NOT debugging, trap fatal signals, so we can
299 * easily clean up after ourselves.
301 * If we ARE debugging, don't trap them, so we can
304 if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
306 #ifdef HAVE_SIGACTION
307 act.sa_handler = sig_fatal;
308 sigaction(SIGSEGV, &act, NULL);
310 signal(SIGSEGV, sig_fatal);
316 if (mainconfig.do_snmp) radius_snmp_init();
320 * Ensure that we're using the CORRECT pid after forking,
321 * NOT the one we started with.
323 radius_pid = getpid();
327 * Only write the PID file if we're running as a daemon.
329 * And write it AFTER we've forked, so that we write the
332 if (dont_fork == FALSE) {
335 fp = fopen(mainconfig.pid_file, "w");
338 * FIXME: What about following symlinks,
339 * and having it over-write a normal file?
341 fprintf(fp, "%d\n", (int) radius_pid);
344 radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
345 mainconfig.pid_file, strerror(errno));
351 * If we're running as a daemon, close the default file
352 * descriptors, AFTER forking.
357 devnull = open("/dev/null", O_RDWR);
359 radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
363 dup2(devnull, STDIN_FILENO);
364 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
365 mainconfig.radlog_fd = dup(STDOUT_FILENO);
367 dup2(devnull, STDOUT_FILENO);
368 if (mainconfig.radlog_dest == RADLOG_STDERR) {
369 mainconfig.radlog_fd = dup(STDERR_FILENO);
371 dup2(devnull, STDERR_FILENO);
376 * It's called the thread pool, but it does a little
379 radius_event_init(spawn_flag);
382 * Use linebuffered or unbuffered stdout if
383 * the debug flag is on.
385 if (debug_flag == TRUE)
389 * Print out which ports we're listening on.
391 for (listener = mainconfig.listen;
393 listener = listener->next) {
394 listener->print(listener, buffer, sizeof(buffer));
395 switch (listener->type) {
396 case RAD_LISTEN_AUTH:
397 DEBUG("Listening on authentication address %s", buffer);
400 case RAD_LISTEN_ACCT:
401 DEBUG("Listening on accounting address %s", buffer);
404 case RAD_LISTEN_PROXY:
405 DEBUG("Listening on proxy address %s", buffer);
408 case RAD_LISTEN_DETAIL:
409 DEBUG("Listening on detail file %s", buffer);
418 * Now that we've set everything up, we can install the signal
419 * handlers. Before this, if we get any signal, we don't know
420 * what to do, so we might as well do the default, and die.
422 signal(SIGPIPE, SIG_IGN);
423 #ifdef HAVE_SIGACTION
424 act.sa_handler = sig_hup;
425 sigaction(SIGHUP, &act, NULL);
426 act.sa_handler = sig_fatal;
427 sigaction(SIGTERM, &act, NULL);
429 signal(SIGHUP, sig_hup);
430 signal(SIGTERM, sig_fatal);
433 * If we're debugging, then a CTRL-C will cause the
434 * server to die immediately. Use SIGTERM to shut down
435 * the server cleanly in that case.
437 if ((debug_memory == 1) || (debug_flag == 0)) {
438 #ifdef HAVE_SIGACTION
439 act.sa_handler = sig_fatal;
440 sigaction(SIGINT, &act, NULL);
441 sigaction(SIGQUIT, &act, NULL);
443 signal(SIGINT, sig_fatal);
444 signal(SIGQUIT, sig_fatal);
448 radlog(L_INFO, "Ready to process requests.");
451 * Receive user requests
455 * If we've been told to exit, then do so,
456 * even if we have data waiting.
462 * Ignore the TERM signal: we're about
465 signal(SIGTERM, SIG_IGN);
468 * Send a TERM signal to all associated
469 * processes (including us, which gets
472 kill(-radius_pid, SIGTERM);
475 * FIXME: Kill child threads, and
480 * FIXME: clean up any active REQUEST
485 * We're exiting, so we can delete the PID
486 * file. (If it doesn't exist, we can ignore
487 * the error returned by unlink)
489 if (dont_fork == FALSE) {
490 unlink(mainconfig.pid_file);
494 * Free the configuration items.
499 * Detach any modules.
508 * SIGTERM gets do_exit=0,
509 * and we want to exit cleanly.
511 * Other signals make us exit
512 * with an error status.
518 #ifdef HAVE_PTHREAD_H
520 * Threads: wait for all threads to stop
521 * processing before re-loading the
522 * config, so we don't pull the rug out
526 if (spawn_flag) for(;;) {
528 * Block until there are '0' threads
529 * with a REQUEST handle.
531 sig_hup_block = TRUE;
532 if( (total_active_threads() == 0) ||
534 sig_hup_block = FALSE;
541 if (read_mainconfig(TRUE) < 0) {
546 radlog(L_INFO, "Ready to process requests.");
553 * Loop over all the listening FD's.
555 for (listener = mainconfig.listen;
557 listener = listener->next) {
558 if (listener->fd < 0) continue;
560 FD_SET(listener->fd, &readfds);
561 if (listener->fd > max_fd) max_fd = listener->fd;
565 if (mainconfig.do_snmp &&
566 (rad_snmp.smux_fd >= 0)) {
567 FD_SET(rad_snmp.smux_fd, &readfds);
568 if (rad_snmp.smux_fd > max_fd) max_fd = rad_snmp.smux_fd;
573 DEBUG2("Nothing to do. Sleeping until we see a request.");
574 } else if (tv.tv_sec) {
576 DEBUG2("Waking up in %d.%06d seconds...",
577 (int) tv.tv_sec, (int) tv.tv_usec);
579 DEBUG2("Waking up in %d seconds...",
583 status = select(max_fd + 1, &readfds, NULL, NULL, ptv);
586 * On interrupts, we clean up the request
587 * list. We then continue with the loop,
588 * so that if we're supposed to exit,
589 * then the code at the start of the loop
590 * catches that, and exits.
592 if (errno == EINTR) {
593 #ifdef MEMORY_USE_DEBUGGING
595 * Run the server in debugging mode,
596 * without threads, and give it a
597 * SIGHUP. It will clean up after
598 * itself, and any memory left over
599 * should be allocated by C libraries,
608 radlog(L_ERR, "Unexpected error in select(): %s",
613 time_now = time(NULL);
614 #ifndef HAVE_PTHREAD_H
616 * If there are no child threads, then there may
617 * be child processes. In that case, wait for
618 * their exit status, and throw that exit status
619 * away. This helps get rid of zxombie children.
621 while (waitpid(-1, &argval, WNOHANG) > 0) {
627 * Loop over the open socket FD's, reading any data.
629 for (listener = mainconfig.listen;
631 listener = listener->next) {
632 RAD_REQUEST_FUNP fun;
634 if ((listener->fd >= 0) &&
635 !FD_ISSET(listener->fd, &readfds))
639 * Receive the packet.
641 if (sig_hup_block != FALSE) {
646 * Do per-socket receive processing of
647 * the packet. This also takes care of
648 * inserting the request into the event
649 * tree, and adding it to the queue for
652 if (!listener->recv(listener, &fun, &request)) {
656 // EVENT FIX FIXME! Nuke this!
659 * Drop the request into the thread pool,
660 * and let the thread pool take care of
661 * doing something with it.
663 if (!thread_pool_addrequest(request, fun)) {
664 request->child_state = REQUEST_DONE;
666 } /* loop over listening sockets*/
669 if (mainconfig.do_snmp) {
671 * After handling all authentication/accounting
672 * requests, THEN process any pending SMUX/SNMP
675 * Note that the handling is done in the main server,
676 * which probably isn't a Good Thing. It really
677 * should be wrapped, and handled in a thread pool.
679 if ((rad_snmp.smux_fd >= 0) &&
680 FD_ISSET(rad_snmp.smux_fd, &readfds) &&
681 (rad_snmp.smux_event == SMUX_READ)) {
686 * If we've got to re-connect, then do so now,
687 * before calling select again.
689 if (rad_snmp.smux_event == SMUX_CONNECT) {
696 radius_event_process(&ptv);
698 #ifdef HAVE_PTHREAD_H
701 * Only clean the thread pool if we're spawning
705 thread_pool_clean(time_now);
713 * Display the syntax for starting this program.
715 static void NEVER_RETURNS usage(int status)
717 FILE *output = status?stderr:stdout;
720 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
721 fprintf(output, "Options:\n\n");
722 fprintf(output, " -a acct_dir use accounting directory 'acct_dir'.\n");
723 fprintf(output, " -A Log auth detail.\n");
724 fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
725 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
726 fprintf(output, " -h Print this help message.\n");
727 fprintf(output, " -i ipaddr Listen on ipaddr ONLY\n");
728 fprintf(output, " -l log_dir Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
729 fprintf(output, " -p port Listen on port ONLY\n");
730 fprintf(output, " -s Do not spawn child processes to handle requests.\n");
731 fprintf(output, " -S Log stripped names.\n");
732 fprintf(output, " -v Print server version information.\n");
733 fprintf(output, " -X Turn on full debugging.\n");
734 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
735 fprintf(output, " -y Log authentication failures, with password.\n");
736 fprintf(output, " -z Log authentication successes, with password.\n");
742 * We got a fatal signal.
744 static void sig_fatal(int sig)
748 /* We can't really do anything intelligent here so just die */
768 * We got the hangup signal.
769 * Re-read the configuration files.
772 static void sig_hup(int sig)
774 sig = sig; /* -Wunused */
776 reset_signal(SIGHUP, sig_hup);
779 * Only do the reload if we're the main server, both
780 * for processes, and for threads.
782 if (getpid() == radius_pid) {
786 if (mainconfig.do_snmp) {
787 rad_snmp.smux_failures = 0;
788 rad_snmp.smux_event = SMUX_CONNECT;