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;
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;
74 static int has_detail_listener = FALSE;
76 static int radius_self_pipe[2];
79 * Configuration items.
85 static void usage(int);
87 static void sig_fatal (int);
88 static void sig_hup (int);
93 int main(int argc, char *argv[])
96 unsigned char buffer[4096];
102 int dont_fork = FALSE;
103 int spawn_flag = TRUE;
104 int sig_hup_block = FALSE;
105 struct timeval tv, *ptv = NULL;
106 int read_from_detail = FALSE;
109 #ifdef HAVE_SIGACTION
110 struct sigaction act;
112 rad_listen_t *listener;
115 set_auth_parameters(argc,argv);
118 if ((progname = strrchr(argv[0], '/')) == NULL)
125 radius_dir = strdup(RADIUS_DIR);
128 * Ensure that the configuration is initialized.
130 memset(&mainconfig, 0, sizeof(mainconfig));
131 mainconfig.myip.af = AF_UNSPEC;
132 mainconfig.port = -1;
133 mainconfig.radiusd_conf = strdup("radiusd.conf");
135 #ifdef HAVE_SIGACTION
136 memset(&act, 0, sizeof(act));
138 sigemptyset( &act.sa_mask ) ;
142 * Don't put output anywhere until we get told a little
145 mainconfig.radlog_fd = -1;
146 mainconfig.log_file = NULL;
148 /* Process the options. */
149 while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mn:p:sSvxXyz")) != EOF) {
154 log_auth_detail = TRUE;
158 if (radacct_dir) free(radacct_dir);
159 radacct_dir = strdup(optarg);
163 /* ignore for backwards compatibility with Cistron */
167 if (radius_dir) free(radius_dir);
168 radius_dir = strdup(optarg);
180 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
181 fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
187 if ((strcmp(optarg, "stdout") == 0) ||
188 (strcmp(optarg, "stderr") == 0) ||
189 (strcmp(optarg, "syslog") == 0)) {
190 fprintf(stderr, "radiusd: -l %s is unsupported. Use log_destination in radiusd.conf\n", optarg);
193 if (radlog_dir) free(radlog_dir);
194 radlog_dir = strdup(optarg);
198 fprintf(stderr, "radiusd: -g is unsupported. Use log_destination in radiusd.conf.\n");
207 if ((strchr(optarg, '/') != NULL) ||
208 (strchr(optarg, '.') != NULL) ||
209 (strlen(optarg) > 45)) usage(1);
211 snprintf(buffer, sizeof(buffer), "%s.conf",
213 if (mainconfig.radiusd_conf)
214 free(mainconfig.radiusd_conf);
215 mainconfig.radiusd_conf = strdup(buffer);
219 log_stripped_names++;
223 mainconfig.port = atoi(optarg);
224 if ((mainconfig.port <= 0) ||
225 (mainconfig.port >= 65536)) {
226 fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
231 case 's': /* Single process mode */
241 * BIG debugging mode for users who are
242 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
248 mainconfig.log_auth = TRUE;
249 mainconfig.log_auth_badpass = TRUE;
250 mainconfig.log_auth_goodpass = TRUE;
251 mainconfig.radlog_dest = RADLOG_STDOUT;
252 mainconfig.radlog_fd = STDOUT_FILENO;
260 mainconfig.log_auth = TRUE;
261 mainconfig.log_auth_badpass = TRUE;
265 mainconfig.log_auth_badpass = TRUE;
266 mainconfig.log_auth_goodpass = TRUE;
276 radlog(L_INFO, "%s", radiusd_version);
277 radlog(L_INFO, "Copyright (C) 2000-2007 The FreeRADIUS server project.\n");
278 radlog(L_INFO, "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
279 radlog(L_INFO, "PARTICULAR PURPOSE.\n");
280 radlog(L_INFO, "You may redistribute copies of FreeRADIUS under the terms of the\n");
281 radlog(L_INFO, "GNU General Public License.\n");
285 /* Read the configuration files, BEFORE doing anything else. */
286 if (read_mainconfig(0) < 0) {
291 * Disconnect from session
293 if (debug_flag == 0 && dont_fork == FALSE) {
296 radlog(L_ERR|L_CONS, "Couldn't fork");
301 * The parent exits, so the child can run in the background.
312 * If we're NOT debugging, trap fatal signals, so we can
313 * easily clean up after ourselves.
315 * If we ARE debugging, don't trap them, so we can
318 if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
320 #ifdef HAVE_SIGACTION
321 act.sa_handler = sig_fatal;
322 sigaction(SIGSEGV, &act, NULL);
324 signal(SIGSEGV, sig_fatal);
330 * Ensure that we're using the CORRECT pid after forking,
331 * NOT the one we started with.
333 radius_pid = getpid();
336 * Only write the PID file if we're running as a daemon.
338 * And write it AFTER we've forked, so that we write the
341 if (dont_fork == FALSE) {
344 fp = fopen(mainconfig.pid_file, "w");
347 * FIXME: What about following symlinks,
348 * and having it over-write a normal file?
350 fprintf(fp, "%d\n", (int) radius_pid);
353 radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
354 mainconfig.pid_file, strerror(errno));
360 * Child threads need a pipe to signal us, as do the
363 if (pipe(radius_self_pipe) < 0) {
364 radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
368 if (fcntl(radius_self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
369 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
373 if (fcntl(radius_self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
374 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
380 * If we're running as a daemon, close the default file
381 * descriptors, AFTER forking.
386 devnull = open("/dev/null", O_RDWR);
388 radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
392 dup2(devnull, STDIN_FILENO);
393 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
394 mainconfig.radlog_fd = dup(STDOUT_FILENO);
396 dup2(devnull, STDOUT_FILENO);
397 if (mainconfig.radlog_dest == RADLOG_STDERR) {
398 mainconfig.radlog_fd = dup(STDERR_FILENO);
400 dup2(devnull, STDERR_FILENO);
405 * It's called the thread pool, but it does a little
408 radius_event_init(spawn_flag);
411 * Use linebuffered or unbuffered stdout if
412 * the debug flag is on.
414 if (debug_flag == TRUE)
418 * Print out which ports we're listening on.
420 for (listener = mainconfig.listen;
422 listener = listener->next) {
423 listener->print(listener, buffer, sizeof(buffer));
424 switch (listener->type) {
425 case RAD_LISTEN_AUTH:
426 DEBUG("Listening on authentication address %s", buffer);
429 case RAD_LISTEN_ACCT:
430 DEBUG("Listening on accounting address %s", buffer);
433 case RAD_LISTEN_PROXY:
434 DEBUG("Listening on proxy address %s", buffer);
437 case RAD_LISTEN_DETAIL:
438 has_detail_listener = TRUE;
439 read_from_detail = TRUE;
440 DEBUG("Listening on detail file %s", buffer);
443 case RAD_LISTEN_SNMP:
444 DEBUG("Listening on SNMP %s", buffer);
449 DEBUG("Listening on vmps %s", buffer);
459 * Now that we've set everything up, we can install the signal
460 * handlers. Before this, if we get any signal, we don't know
461 * what to do, so we might as well do the default, and die.
463 signal(SIGPIPE, SIG_IGN);
464 #ifdef HAVE_SIGACTION
465 act.sa_handler = sig_hup;
466 sigaction(SIGHUP, &act, NULL);
467 act.sa_handler = sig_fatal;
468 sigaction(SIGTERM, &act, NULL);
470 signal(SIGHUP, sig_hup);
471 signal(SIGTERM, sig_fatal);
474 * If we're debugging, then a CTRL-C will cause the
475 * server to die immediately. Use SIGTERM to shut down
476 * the server cleanly in that case.
478 if ((debug_memory == 1) || (debug_flag == 0)) {
479 #ifdef HAVE_SIGACTION
480 act.sa_handler = sig_fatal;
481 sigaction(SIGINT, &act, NULL);
482 sigaction(SIGQUIT, &act, NULL);
484 signal(SIGINT, sig_fatal);
485 signal(SIGQUIT, sig_fatal);
490 radlog(L_INFO, "Ready to process requests.");
493 * Receive user requests
502 * Loop over all the listening FD's.
504 for (listener = mainconfig.listen;
506 listener = listener->next) {
507 if (listener->fd < 0) continue;
509 if (!read_from_detail &&
510 (listener->type == RAD_LISTEN_DETAIL)) continue;
512 FD_SET(listener->fd, &readfds);
513 if (listener->fd > max_fd) max_fd = listener->fd;
517 * Add in the self pipe FD, for signals or
518 * notices from the child threads.
520 FD_SET(radius_self_pipe[0], &readfds);
521 if (radius_self_pipe[0] > max_fd) {
522 max_fd = radius_self_pipe[0];
526 DEBUG2("Nothing to do. Sleeping until we see a request.");
527 } else if (tv.tv_sec) {
528 DEBUG2("Waking up in %d seconds...",
532 status = select(max_fd + 1, &readfds, NULL, NULL, ptv);
533 if ((status < 0) && (errno != EINTR)) {
534 radlog(L_ERR, "Unexpected error in select(): %s",
538 time_now = time(NULL);
540 #ifndef HAVE_PTHREAD_H
542 * If there are no child threads, then there may
543 * be child processes. In that case, wait for
544 * their exit status, and throw that exit status
545 * away. This helps get rid of zxombie children.
547 while (waitpid(-1, &argval, WNOHANG) > 0) {
553 * Before doing anything else, check the self pipe.
555 if (FD_ISSET(radius_self_pipe[0], &readfds) &&
556 (rcode = read(radius_self_pipe[0], buffer, sizeof(buffer))) > 0) {
559 for (i = 1; i < rcode; i++) {
560 buffer[0] |= buffer[i];
563 if ((buffer[0] & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
567 * Ignore the TERM signal: we're
570 signal(SIGTERM, SIG_IGN);
573 * Send a TERM signal to all
574 * associated processes
575 * (including us, which gets
578 kill(-radius_pid, SIGTERM);
581 * FIXME: Kill child threads, and
586 * FIXME: clean up any active REQUEST
591 * We're exiting, so we can delete the PID
592 * file. (If it doesn't exist, we can ignore
593 * the error returned by unlink)
595 if (dont_fork == FALSE) {
596 unlink(mainconfig.pid_file);
602 * Free the configuration items.
607 * Detach any modules.
614 * SIGTERM gets do_exit=0,
615 * and we want to exit cleanly.
617 * Other signals make us exit
618 * with an error status.
620 if ((buffer[0] & RADIUS_SIGNAL_SELF_EXIT) != 0) {
624 } /* else exit/term flags weren't set */
626 if ((buffer[0] & RADIUS_SIGNAL_SELF_HUP) != 0) {
627 DEBUG("Received HUP signal");
628 #ifdef HAVE_PTHREAD_H
630 * Threads: wait for all threads to stop
631 * processing before re-loading the
632 * config, so we don't pull the rug out
636 if (spawn_flag) for(;;) {
638 * Block until there are
639 * zero threads with a
643 * threads to send us a
644 * signal in the pipe?
646 sig_hup_block = TRUE;
648 if( (total_active_threads() == 0) ||
650 sig_hup_block = FALSE;
659 if (mainconfig.do_snmp) {
660 rad_snmp.smux_failures = 0;
661 rad_snmp.smux_event = SMUX_CONNECT;
664 if (read_mainconfig(TRUE) < 0) {
672 * Check if we can read from the detail file
674 if (has_detail_listener &&
675 (buffer[0] & RADIUS_SIGNAL_SELF_DETAIL) != 0) {
676 DEBUG3("Can now read from detail file(s)");
677 read_from_detail = TRUE;
679 } /* else the self pipe didn't have data ready */
682 * Loop over the open socket FD's, reading any data.
684 for (listener = mainconfig.listen;
686 listener = listener->next) {
687 RAD_REQUEST_FUNP fun;
689 if ((listener->fd >= 0) &&
690 !FD_ISSET(listener->fd, &readfds))
694 * Receive the packet.
696 if (sig_hup_block != FALSE) {
701 * Do per-socket receive processing of
702 * the packet. This also takes care of
703 * inserting the request into the event
704 * tree, and adding it to the queue for
707 if (!listener->recv(listener, &fun, &request)) {
712 * Drop the request into the thread pool,
713 * and let the thread pool take care of
714 * doing something with it.
716 if (!thread_pool_addrequest(request, fun)) {
717 request->child_state = REQUEST_DONE;
721 * If we've read a packet from a socket
722 * OTHER than the detail file, we start
723 * ignoring the detail file.
725 * When the child thread pulls the
726 * request off of the queues, it will
727 * check if the queues are empty. Once
728 * all queues are empty, it will signal
729 * us to read the detail file again.
732 (listener->type != RAD_LISTEN_DETAIL)) {
733 read_from_detail = FALSE;
735 } /* loop over listening sockets*/
738 radius_event_process(&ptv);
740 #ifdef HAVE_PTHREAD_H
743 * Only clean the thread pool if we're spawning
746 * FIXME: Move this to the event handler!
749 thread_pool_clean(time_now);
757 * Display the syntax for starting this program.
759 static void NEVER_RETURNS usage(int status)
761 FILE *output = status?stderr:stdout;
764 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
765 fprintf(output, "Options:\n\n");
766 fprintf(output, " -a acct_dir use accounting directory 'acct_dir'.\n");
767 fprintf(output, " -A Log auth detail.\n");
768 fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
769 fprintf(output, " -f Run as a foreground process, not a daemon.\n");
770 fprintf(output, " -h Print this help message.\n");
771 fprintf(output, " -i ipaddr Listen on ipaddr ONLY\n");
772 fprintf(output, " -l log_dir Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
773 fprintf(output, " -p port Listen on port ONLY\n");
774 fprintf(output, " -s Do not spawn child processes to handle requests.\n");
775 fprintf(output, " -S Log stripped names.\n");
776 fprintf(output, " -v Print server version information.\n");
777 fprintf(output, " -X Turn on full debugging.\n");
778 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
779 fprintf(output, " -y Log authentication failures, with password.\n");
780 fprintf(output, " -z Log authentication successes, with password.\n");
786 * We got a fatal signal.
788 static void sig_fatal(int sig)
793 * We can't really do anything
794 * intelligent here so just die
799 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
805 radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
811 radius_signal_self(RADIUS_SIGNAL_SELF_EXIT);
818 * We got the hangup signal.
819 * Re-read the configuration files.
821 static void sig_hup(int sig)
823 sig = sig; /* -Wunused */
825 reset_signal(SIGHUP, sig_hup);
827 write(STDOUT_FILENO, "STUFF\n", 6);
829 radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
832 void radius_signal_self(int flag)
838 * The caller is telling us it's OK to read from the
839 * detail files. However, we're not even listening on
840 * the detail files. Therefore, suppress the flag to
841 * avoid bothering the mail worker thread.
843 if ((flag == RADIUS_SIGNAL_SELF_DETAIL) &&
844 !has_detail_listener) {
849 * The read MUST be non-blocking for this to work.
851 rcode = read(radius_self_pipe[0], buffer, sizeof(buffer));
855 for (i = 1; i < rcode; i++) {
856 buffer[0] |= buffer[i];
861 memset(buffer + 1, 0, sizeof(buffer) - 1);
867 write(radius_self_pipe[1], buffer, 1);