X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmain%2Fradiusd.c;h=20ad58e57c019968ae3e359115d97330c083d681;hb=1147ab4f2843e6deee5fd07f2b716de7cbb1675b;hp=aa39c968907abec9bb030521854dcb448d340cbd;hpb=73e197cdd04d0a69da8d173aa3be7b295baa113b;p=freeradius.git diff --git a/src/main/radiusd.c b/src/main/radiusd.c index aa39c96..20ad58e 100644 --- a/src/main/radiusd.c +++ b/src/main/radiusd.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * - * Copyright 2000,2001,2002,2003,2004 The FreeRADIUS server project + * Copyright 2000-2004,2006 The FreeRADIUS server project * Copyright 1999,2000 Miquel van Smoorenburg * Copyright 2000 Alan DeKok * Copyright 2000 Alan Curry @@ -25,37 +25,24 @@ * Copyright 2000 Chad Miller */ -/* don't look here for the version, run radiusd -v or look in version.c */ -static const char rcsid[] = -"$Id$"; +#include +RCSID("$Id$") -#include +#include +#include +#include #include -#ifdef HAVE_NETINET_IN_H -# include -#endif - -#include -#include #include #include -#ifdef HAVE_UNISTD_H -# include -#endif - #include #ifdef HAVE_GETOPT_H # include #endif -#ifdef HAVE_SYS_SELECT_H -# include -#endif - #ifdef HAVE_SYS_WAIT_H # include #endif @@ -66,15 +53,6 @@ static const char rcsid[] = # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif -#include -#include -#include -#include -#include -#include - -#define SLEEP_FOREVER (65536) - /* * Global variables. */ @@ -85,18 +63,17 @@ const char *radlog_dir = NULL; const char *radlib_dir = NULL; int log_stripped_names; int debug_flag = 0; -int log_auth_detail = FALSE; -int need_reload = FALSE; +int check_config = FALSE; const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__; -time_t time_now; -static pid_t radius_pid; +pid_t radius_pid; + +static int debug_memory = 0; /* * Configuration items. */ -static int do_exit = 0; /* * Static functions. @@ -104,40 +81,44 @@ static int do_exit = 0; 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[]) { - REQUEST *request; - unsigned char buffer[4096]; - fd_set readfds; + int rcode; int argval; - int pid; - int max_fd; - int status; - int sleep_time = SLEEP_FOREVER; int spawn_flag = TRUE; int dont_fork = FALSE; - int sig_hup_block = FALSE; - time_t last_cleaned_lists = 0; + int flag = 0; #ifdef HAVE_SIGACTION struct sigaction act; #endif - rad_listen_t *listener; #ifdef OSFC2 set_auth_parameters(argc,argv); #endif - if ((progname = strrchr(argv[0], '/')) == NULL) + if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) progname = argv[0]; 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); @@ -148,7 +129,7 @@ int main(int argc, char *argv[]) memset(&mainconfig, 0, sizeof(mainconfig)); mainconfig.myip.af = AF_UNSPEC; mainconfig.port = -1; - mainconfig.radiusd_conf = strdup("radiusd.conf"); + mainconfig.name = "radiusd"; #ifdef HAVE_SIGACTION memset(&act, 0, sizeof(act)); @@ -156,22 +137,22 @@ int main(int argc, char *argv[]) sigemptyset( &act.sa_mask ) ; #endif + /* + * Don't put output anywhere until we get told a little + * more. + */ + mainconfig.radlog_dest = RADLOG_NULL; + mainconfig.radlog_fd = -1; + mainconfig.log_file = NULL; + /* Process the options. */ - while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:n:p:sSvxXyz")) != EOF) { + while ((argval = getopt(argc, argv, "Cd:fhi:l:mn:p:stvxX")) != 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': @@ -187,43 +168,34 @@ int main(int argc, char *argv[]) usage(0); break; - case 'i': - if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) { - fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg); + case 'l': + if (strcmp(optarg, "stdout") == 0) { + goto do_stdout; + } + mainconfig.log_file = strdup(optarg); + mainconfig.radlog_dest = RADLOG_FILES; + mainconfig.radlog_fd = open(mainconfig.log_file, + O_WRONLY | O_APPEND | O_CREAT, 0640); + if (mainconfig.radlog_fd < 0) { + fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno)); exit(1); } - break; + 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); + case 'i': + if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) { + fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\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 '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); + mainconfig.name = optarg; break; - case 'S': - log_stripped_names++; + case 'm': + debug_memory = 1; break; case 'p': @@ -233,6 +205,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "radiusd: Invalid port number %s\n", optarg); exit(1); } + flag |= 2; break; case 's': /* Single process mode */ @@ -240,14 +213,14 @@ int main(int argc, char *argv[]) dont_fork = TRUE; break; + case 't': /* no child threads */ + spawn_flag = FALSE; + break; + case 'v': 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; @@ -255,41 +228,51 @@ int main(int argc, char *argv[]) mainconfig.log_auth = TRUE; mainconfig.log_auth_badpass = TRUE; mainconfig.log_auth_goodpass = TRUE; + do_stdout: mainconfig.radlog_dest = RADLOG_STDOUT; + mainconfig.radlog_fd = STDOUT_FILENO; + fr_log_fp = stdout; break; case 'x': 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) 1999-2009 The FreeRADIUS server project and contributors.\n"); + radlog(L_INFO, "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n"); + radlog(L_INFO, "PARTICULAR PURPOSE.\n"); + radlog(L_INFO, "You may redistribute copies of FreeRADIUS under the terms of the\n"); + radlog(L_INFO, "GNU General Public License v2.\n"); + fflush(NULL); + } + /* Read the configuration files, BEFORE doing anything else. */ if (read_mainconfig(0) < 0) { 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"); + if (dont_fork == FALSE) { + pid_t pid = fork(); + + if (pid < 0) { + radlog(L_ERR, "Couldn't fork: %s", strerror(errno)); exit(1); } @@ -303,27 +286,6 @@ int main(int argc, char *argv[]) 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 - } - -#ifdef WITH_SNMP - if (mainconfig.do_snmp) radius_snmp_init(); #endif /* @@ -332,39 +294,11 @@ int main(int argc, char *argv[]) */ radius_pid = getpid(); - - /* - * Only write the PID file if we're running as a daemon. - * - * And write it AFTER we've forked, so that we write the - * correct PID. - */ - if (dont_fork == FALSE) { - FILE *fp; - - fp = fopen(mainconfig.pid_file, "w"); - if (fp != NULL) { - /* - * FIXME: What about following symlinks, - * and having it over-write a normal file? - */ - fprintf(fp, "%d\n", (int) radius_pid); - fclose(fp); - } else { - radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n", - mainconfig.pid_file, strerror(errno)); - exit(1); - } - } - /* * If we're running as a daemon, close the default file * descriptors, AFTER forking. */ - mainconfig.radlog_fd = -1; - if (debug_flag) { - mainconfig.radlog_fd = STDOUT_FILENO; - } else { + if (!debug_flag) { int devnull; devnull = open("/dev/null", O_RDWR); @@ -376,70 +310,42 @@ int main(int argc, char *argv[]) dup2(devnull, STDIN_FILENO); if (mainconfig.radlog_dest == RADLOG_STDOUT) { mainconfig.radlog_fd = dup(STDOUT_FILENO); + setlinebuf(stdout); } dup2(devnull, STDOUT_FILENO); if (mainconfig.radlog_dest == RADLOG_STDERR) { mainconfig.radlog_fd = dup(STDERR_FILENO); + setlinebuf(stdout); } dup2(devnull, STDERR_FILENO); close(devnull); - } - /* - * It's called the thread pool, but it does a little - * more than that. - */ - thread_pool_init(spawn_flag); - - /* - * Use linebuffered or unbuffered stdout if - * the debug flag is on. - */ - if (debug_flag == TRUE) - setlinebuf(stdout); + } else { + setlinebuf(stdout); /* unbuffered output */ + } /* - * Print out which ports we're listening on. + * Initialize the event pool, including threads. */ - for (listener = mainconfig.listen; - listener != NULL; - listener = listener->next) { - listener->print(listener, buffer, sizeof(buffer)); - switch (listener->type) { - case RAD_LISTEN_AUTH: - DEBUG("Listening on authentication address %s", buffer); - break; - - case RAD_LISTEN_ACCT: - DEBUG("Listening on accounting address %s", buffer); - break; - - case RAD_LISTEN_PROXY: - DEBUG("Listening on proxy address %s", buffer); - break; - - case RAD_LISTEN_DETAIL: - DEBUG("Listening on detail file %s", buffer); - break; - - default: - break; - } - } + radius_event_init(mainconfig.config, spawn_flag); /* * 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 /* @@ -447,294 +353,111 @@ int main(int argc, char *argv[]) * server to die immediately. Use SIGTERM to shut down * the server cleanly in that case. */ - if (debug_flag == 0) { + if ((debug_memory == 1) || (debug_flag == 0)) { #ifdef HAVE_SIGACTION act.sa_handler = sig_fatal; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); #else signal(SIGINT, sig_fatal); +#ifdef SIGQUIT signal(SIGQUIT, sig_fatal); #endif +#endif } - radlog(L_INFO, "Ready to process requests."); - /* - * Receive user requests + * Everything seems to have loaded OK, exit gracefully. */ - for (;;) { - /* - * If we've been told to exit, then do so, - * even if we have data waiting. - */ - if (do_exit) { - 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.) - */ - kill(-radius_pid, SIGTERM); - - /* - * FIXME: Kill child threads, and - * clean up? - */ - - /* - * Detach any modules. - */ - detach_modules(); - - /* - * FIXME: clean up any active REQUEST - * handles. - */ - - /* - * We're exiting, so we can delete the PID - * file. (If it doesn't exist, we can ignore - * the error returned by unlink) - */ - if (dont_fork == FALSE) { - unlink(mainconfig.pid_file); - } - - /* - * Free the configuration items. - */ - free_mainconfig(); - - /* - * SIGTERM gets do_exit=0, - * and we want to exit cleanly. - * - * Other signals make us exit - * with an error status. - */ - exit(do_exit - 1); - } - - if (need_reload) { -#ifdef HAVE_PTHREAD_H - /* - * Threads: wait for all threads to stop - * processing before re-loading the - * config, so we don't pull the rug out - * from under them. - */ - int max_wait = 0; - if (spawn_flag) for(;;) { - /* - * Block until there are '0' threads - * with a REQUEST handle. - */ - sig_hup_block = TRUE; - if( (total_active_threads() == 0) || - (max_wait >= 5) ) { - sig_hup_block = FALSE; - break; - } - sleep(1); - max_wait++; - } -#endif - if (read_mainconfig(TRUE) < 0) { - exit(1); - } - - need_reload = FALSE; - radlog(L_INFO, "Ready to process requests."); - } - - FD_ZERO(&readfds); - max_fd = 0; - - /* - * Loop over all the listening FD's. - */ - for (listener = mainconfig.listen; - listener != NULL; - listener = listener->next) { - if (listener->fd < 0) continue; - - FD_SET(listener->fd, &readfds); - if (listener->fd > max_fd) max_fd = listener->fd; - } + if (check_config) { + DEBUG("Configuration appears to be OK."); + exit(0); + } -#ifdef WITH_SNMP - if (mainconfig.do_snmp && - (rad_snmp.smux_fd >= 0)) { - FD_SET(rad_snmp.smux_fd, &readfds); - if (rad_snmp.smux_fd > max_fd) max_fd = rad_snmp.smux_fd; - } +#ifdef WITH_STATS + radius_stats_init(0); #endif - if (sleep_time == SLEEP_FOREVER) { - DEBUG2("Nothing to do. Sleeping until we see a request."); - status = select(max_fd + 1, &readfds, NULL, NULL, NULL); - } else { - struct timeval tv; - - DEBUG2("Waking up in %d seconds...", sleep_time); + /* + * Only write the PID file if we're running as a daemon. + * + * And write it AFTER we've forked, so that we write the + * correct PID. + */ + if (dont_fork == FALSE) { + FILE *fp; - tv.tv_sec = sleep_time; - tv.tv_usec = 0; - status = select(max_fd + 1, &readfds, NULL, NULL, &tv); - } - if (status == -1) { + fp = fopen(mainconfig.pid_file, "w"); + if (fp != NULL) { /* - * On interrupts, we clean up the request - * list. We then continue with the loop, - * so that if we're supposed to exit, - * then the code at the start of the loop - * catches that, and exits. + * FIXME: What about following symlinks, + * and having it over-write a normal file? */ - if (errno == EINTR) { -#ifdef MEMORY_USE_DEBUGGING - /* - * Run the server in debugging mode, - * without threads, and give it a - * SIGHUP. It will clean up after - * itself, and any memory left over - * should be allocated by C libraries, - * and the like. - */ - detach_modules(); - free_mainconfig(); - xlat_free(); - dict_free(); - exit(1); -#endif - continue; - } - radlog(L_ERR, "Unexpected error in select(): %s", - strerror(errno)); + fprintf(fp, "%d\n", (int) radius_pid); + fclose(fp); + } else { + radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n", + mainconfig.pid_file, strerror(errno)); exit(1); } + } - time_now = time(NULL); -#ifndef HAVE_PTHREAD_H - /* - * If there are no child threads, then there may - * be child processes. In that case, wait for - * their exit status, and throw that exit status - * away. This helps get rid of zxombie children. - */ - while (waitpid(-1, &argval, WNOHANG) > 0) { - /* do nothing */ - } + /* + * Process requests until HUP or exit. + */ + while ((rcode = radius_event_process()) == 0x80) { + radius_stats_init(1); + hup_mainconfig(); + } + + radlog(L_INFO, "Exiting normally."); + + /* + * 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__ + if (spawn_flag) kill(-radius_pid, SIGTERM); #endif - - /* - * Loop over the open socket FD's, reading any data. - */ - for (listener = mainconfig.listen; - listener != NULL; - listener = listener->next) { - RAD_REQUEST_FUNP fun; - - if ((listener->fd >= 0) && - !FD_ISSET(listener->fd, &readfds)) - continue; - - /* - * Receive the packet. - */ - if (sig_hup_block != FALSE) { - continue; - } - - /* - * Do per-socket receive processing of the - * packet. - */ - if (!listener->recv(listener, &fun, &request)) { - continue; - } - - /* - * Drop the request into the thread pool, - * and let the thread pool take care of - * doing something with it. - */ - if (!thread_pool_addrequest(request, fun)) { - /* - * FIXME: Maybe just drop - * the packet on the floor? - */ - request_reject(request, REQUEST_FAIL_NO_THREADS); - request->finished = TRUE; - } - } /* loop over listening sockets*/ - -#ifdef WITH_SNMP - if (mainconfig.do_snmp) { - /* - * After handling all authentication/accounting - * requests, THEN process any pending SMUX/SNMP - * queries. - * - * Note that the handling is done in the main server, - * which probably isn't a Good Thing. It really - * should be wrapped, and handled in a thread pool. - */ - if ((rad_snmp.smux_fd >= 0) && - FD_ISSET(rad_snmp.smux_fd, &readfds) && - (rad_snmp.smux_event == SMUX_READ)) { - smux_read(); - } - - /* - * If we've got to re-connect, then do so now, - * before calling select again. - */ - if (rad_snmp.smux_event == SMUX_CONNECT) { - smux_connect(); - } - } + + /* + * We're exiting, so we can delete the PID + * file. (If it doesn't exist, we can ignore + * the error returned by unlink) + */ + if (dont_fork == FALSE) { + unlink(mainconfig.pid_file); + } + + radius_event_free(); + + /* + * Free the configuration items. + */ + free_mainconfig(); + + /* + * Detach any modules. + */ + detach_modules(); + + xlat_free(); /* modules may have xlat's */ + + free(radius_dir); + +#ifdef WIN32 + WSACleanup(); #endif - /* - * Loop through the request lists once per - * second, to clean up old requests. - */ - if (last_cleaned_lists != time_now) { - last_cleaned_lists = time_now; - - DEBUG2("--- Walking the entire request list ---"); - sleep_time = SLEEP_FOREVER; - for (listener = mainconfig.listen; - listener != NULL; - listener = listener->next) { - int next; - - next = listener->update(listener, time_now); - if (next < sleep_time) { - sleep_time = next; - } - } - } - -#ifdef HAVE_PTHREAD_H - - /* - * Only clean the thread pool if we're spawning - * child threads. - */ - if (spawn_flag) { - thread_pool_clean(time_now); - } -#endif - } /* loop forever */ + return (rcode - 1); } @@ -746,23 +469,19 @@ static void NEVER_RETURNS usage(int status) 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] [-n name] [-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, " -n name Read raddb/name.conf instead of raddb/radiusd.conf\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); } @@ -773,41 +492,36 @@ static void NEVER_RETURNS usage(int status) static void sig_fatal(int sig) { switch(sig) { - case SIGSEGV: - /* We can't really do anything intelligent here so just die */ - _exit(1); case SIGTERM: - do_exit = 1; + radius_signal_self(RADIUS_SIGNAL_SELF_TERM); break; + + case SIGINT: +#ifdef SIGQUIT + case SIGQUIT: +#endif + if (debug_memory) { + radius_signal_self(RADIUS_SIGNAL_SELF_TERM); + break; + } + /* FALL-THROUGH */ + default: - do_exit = 2; - break; + _exit(sig); } } - +#ifdef SIGHUP /* * We got the hangup signal. * Re-read the configuration files. */ -/*ARGSUSED*/ static void sig_hup(int sig) { sig = sig; /* -Wunused */ reset_signal(SIGHUP, sig_hup); - /* - * Only do the reload if we're the main server, both - * for processes, and for threads. - */ - if (getpid() == radius_pid) { - need_reload = TRUE; - } -#ifdef WITH_SNMP - if (mainconfig.do_snmp) { - rad_snmp.smux_failures = 0; - rad_snmp.smux_event = SMUX_CONNECT; - } -#endif + radius_signal_self(RADIUS_SIGNAL_SELF_HUP); } +#endif