#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/radius_snmp.h>
+#include <freeradius-devel/modules.h>
#include <freeradius-devel/rad_assert.h>
#include <sys/file.h>
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
+#ifndef HAVE_PTHREAD_H
+#define thread_pool_lock(_x)
+#define thread_pool_unlock(_x)
+#endif
+
/*
* Global variables.
*/
const char *radlib_dir = NULL;
int log_stripped_names;
int debug_flag = 0;
-int log_auth_detail = FALSE;
+int check_config = FALSE;
const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
static void usage(int);
static void sig_fatal (int);
+#ifdef SIGHUP
static void sig_hup (int);
+#endif
/*
* The main guy.
*/
int main(int argc, char *argv[])
{
- unsigned char buffer[4096];
+ int rcode;
int argval;
- pid_t pid;
int spawn_flag = TRUE;
int dont_fork = FALSE;
+ int flag = 0;
#ifdef HAVE_SIGACTION
struct sigaction act;
#endif
- rad_listen_t *listener;
#ifdef OSFC2
set_auth_parameters(argc,argv);
else
progname++;
+#ifdef WIN32
+ {
+ WSADATA wsaData;
+ if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
+ fprintf(stderr, "%s: Unable to initialize socket library.\n");
+ return 1;
+ }
+ }
+#endif
+
debug_flag = 0;
spawn_flag = TRUE;
radius_dir = strdup(RADIUS_DIR);
mainconfig.log_file = NULL;
/* Process the options. */
- while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mn:p:sSvxXyz")) != EOF) {
+ while ((argval = getopt(argc, argv, "Cd:fhi:mn:p:svxX")) != EOF) {
switch(argval) {
-
- case 'A':
- log_auth_detail = TRUE;
- break;
-
- case 'a':
- if (radacct_dir) free(radacct_dir);
- radacct_dir = strdup(optarg);
- break;
-
- case 'c':
- /* ignore for backwards compatibility with Cistron */
+ case 'C':
+ check_config = TRUE;
+ spawn_flag = FALSE;
+ dont_fork = TRUE;
break;
case 'd':
fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
exit(1);
}
- break;
-
- case 'l':
- if ((strcmp(optarg, "stdout") == 0) ||
- (strcmp(optarg, "stderr") == 0) ||
- (strcmp(optarg, "syslog") == 0)) {
- fprintf(stderr, "radiusd: -l %s is unsupported. Use log_destination in radiusd.conf\n", optarg);
- exit(1);
- }
- if (radlog_dir) free(radlog_dir);
- radlog_dir = strdup(optarg);
- break;
-
- case 'g':
- fprintf(stderr, "radiusd: -g is unsupported. Use log_destination in radiusd.conf.\n");
- exit(1);
+ flag |= 1;
break;
case 'm':
debug_memory = 1;
break;
- case 'n':
- if ((strchr(optarg, '/') != NULL) ||
- (strchr(optarg, '.') != NULL) ||
- (strlen(optarg) > 45)) usage(1);
-
- snprintf(buffer, sizeof(buffer), "%s.conf",
- optarg);
- if (mainconfig.radiusd_conf)
- free(mainconfig.radiusd_conf);
- mainconfig.radiusd_conf = strdup(buffer);
- break;
-
- case 'S':
- log_stripped_names++;
- break;
-
case 'p':
mainconfig.port = atoi(optarg);
if ((mainconfig.port <= 0) ||
fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
exit(1);
}
+ flag |= 2;
break;
case 's': /* Single process mode */
version();
break;
- /*
- * BIG debugging mode for users who are
- * TOO LAZY to type '-sfxxyz -l stdout' themselves.
- */
case 'X':
spawn_flag = FALSE;
dont_fork = TRUE;
debug_flag++;
break;
- case 'y':
- mainconfig.log_auth = TRUE;
- mainconfig.log_auth_badpass = TRUE;
- break;
-
- case 'z':
- mainconfig.log_auth_badpass = TRUE;
- mainconfig.log_auth_goodpass = TRUE;
- break;
-
default:
usage(1);
break;
}
}
+ if (flag && (flag != 0x03)) {
+ fprintf(stderr, "radiusd: The options -i and -p cannot be used individually.\n");
+ exit(1);
+ }
+
if (debug_flag) {
radlog(L_INFO, "%s", radiusd_version);
radlog(L_INFO, "Copyright (C) 2000-2007 The FreeRADIUS server project.\n");
exit(1);
}
+#ifndef __MINGW32__
/*
* Disconnect from session
*/
if (debug_flag == 0 && dont_fork == FALSE) {
- pid = fork();
- if(pid < 0) {
- radlog(L_ERR|L_CONS, "Couldn't fork");
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ radlog(L_ERR, "Couldn't fork: %s", strerror(errno));
exit(1);
}
setsid();
#endif
}
-
- /*
- * If we're NOT debugging, trap fatal signals, so we can
- * easily clean up after ourselves.
- *
- * If we ARE debugging, don't trap them, so we can
- * dump core.
- */
- if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
-#ifdef SIGSEGV
-#ifdef HAVE_SIGACTION
- act.sa_handler = sig_fatal;
- sigaction(SIGSEGV, &act, NULL);
-#else
- signal(SIGSEGV, sig_fatal);
#endif
-#endif
- }
/*
* Ensure that we're using the CORRECT pid after forking,
}
dup2(devnull, STDERR_FILENO);
close(devnull);
+
+ } else {
+ setlinebuf(stdout); /* unbuffered output */
}
/*
radius_event_init(mainconfig.config, spawn_flag);
/*
- * Use linebuffered or unbuffered stdout if
- * the debug flag is on.
- */
- if (debug_flag == TRUE)
- setlinebuf(stdout);
-
- /*
- * Print out which ports we're listening on.
- */
- for (listener = mainconfig.listen;
- listener != NULL;
- listener = listener->next) {
- listener->print(listener, buffer, sizeof(buffer));
- switch (listener->type) {
- case RAD_LISTEN_DETAIL:
- break;
-
- case RAD_LISTEN_SNMP:
- DEBUG("Listening on SNMP %s", buffer);
- break;
-
- default:
- break;
- }
-
- DEBUG("Listening on %s", buffer);
- }
-
- /*
* Now that we've set everything up, we can install the signal
* handlers. Before this, if we get any signal, we don't know
* what to do, so we might as well do the default, and die.
*/
+#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
+#endif
#ifdef HAVE_SIGACTION
act.sa_handler = sig_hup;
sigaction(SIGHUP, &act, NULL);
act.sa_handler = sig_fatal;
sigaction(SIGTERM, &act, NULL);
#else
+#ifdef SIGHUP
signal(SIGHUP, sig_hup);
+#endif
signal(SIGTERM, sig_fatal);
#endif
/*
sigaction(SIGQUIT, &act, NULL);
#else
signal(SIGINT, sig_fatal);
+#ifdef SIGQUIT
signal(SIGQUIT, sig_fatal);
#endif
+#endif
}
- radius_event_process();
+ /*
+ * Everything seems to have loaded OK, exit gracefully.
+ */
+ if (check_config) {
+ DEBUG("Configuration appears OK.");
+ exit(0);
+ }
+
+ /*
+ * Process requests until HUP or exit.
+ */
+ while ((rcode = radius_event_process()) == 0x80) {
+ module_hup(cf_section_sub_find(mainconfig.config, "modules"));
+ }
+
+ DEBUG("Exiting...");
+
+ /*
+ * Ignore the TERM signal: we're
+ * about to die.
+ */
+ signal(SIGTERM, SIG_IGN);
+
+ /*
+ * Send a TERM signal to all
+ * associated processes
+ * (including us, which gets
+ * ignored.)
+ */
+#ifndef __MINGW32__
+ kill(-radius_pid, SIGTERM);
+#endif
/*
* We're exiting, so we can delete the PID
*/
detach_modules();
+ xlat_free(); /* modules may have xlat's */
+
free(radius_dir);
- if (radius_pid < 0) return 1;
+#ifdef WIN32
+ WSACleanup();
+#endif
- return 0;
+ return (rcode - 1);
}
FILE *output = status?stderr:stdout;
fprintf(output,
- "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
+ "Usage: %s [-d db_dir] [-l log_dir] [-i address] [-fsvXx]\n", progname);
fprintf(output, "Options:\n\n");
- fprintf(output, " -a acct_dir use accounting directory 'acct_dir'.\n");
- fprintf(output, " -A Log auth detail.\n");
+ fprintf(output, " -C Check configuration and exit.\n");
fprintf(output, " -d raddb_dir Configuration files are in \"raddbdir/*\".\n");
fprintf(output, " -f Run as a foreground process, not a daemon.\n");
fprintf(output, " -h Print this help message.\n");
fprintf(output, " -i ipaddr Listen on ipaddr ONLY\n");
- fprintf(output, " -l log_dir Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
fprintf(output, " -p port Listen on port ONLY\n");
fprintf(output, " -s Do not spawn child processes to handle requests.\n");
- fprintf(output, " -S Log stripped names.\n");
fprintf(output, " -v Print server version information.\n");
fprintf(output, " -X Turn on full debugging.\n");
fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
- fprintf(output, " -y Log authentication failures, with password.\n");
- fprintf(output, " -z Log authentication successes, with password.\n");
exit(status);
}
break;
case SIGINT:
+#ifdef SIGQUIT
case SIGQUIT:
+#endif
if (debug_memory) {
radius_signal_self(RADIUS_SIGNAL_SELF_TERM);
break;
}
}
-
+#ifdef SIGHUP
/*
* We got the hangup signal.
* Re-read the configuration files.
reset_signal(SIGHUP, sig_hup);
- write(STDOUT_FILENO, "STUFF\n", 6);
-
radius_signal_self(RADIUS_SIGNAL_SELF_HUP);
}
+#endif