Make new request_list_t structure, and return it from rl_init(),
[freeradius.git] / src / main / radiusd.c
1 /*
2  * radiusd.c    Main loop of the radius server.
3  *
4  * Version:     $Id$
5  *
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.
10  *
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.
15  *
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
19  *
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>
26  */
27
28 /* don't look here for the version, run radiusd -v or look in version.c */
29 static const char rcsid[] =
30 "$Id$";
31
32 #include "autoconf.h"
33
34 #include <sys/file.h>
35
36 #ifdef HAVE_NETINET_IN_H
37 #       include <netinet/in.h>
38 #endif
39
40 #include <stdlib.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <ctype.h>
44
45 #ifdef HAVE_UNISTD_H
46 #       include <unistd.h>
47 #endif
48
49 #include <signal.h>
50
51 #ifdef HAVE_GETOPT_H
52 #       include <getopt.h>
53 #endif
54
55 #ifdef HAVE_SYS_SELECT_H
56 #       include <sys/select.h>
57 #endif
58
59 #ifdef HAVE_SYS_WAIT_H
60 #       include <sys/wait.h>
61 #endif
62 #ifndef WEXITSTATUS
63 #       define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
64 #endif
65 #ifndef WIFEXITED
66 #       define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
67 #endif
68
69 #include "radiusd.h"
70 #include "rad_assert.h"
71 #include "conffile.h"
72 #include "modules.h"
73 #include "request_list.h"
74 #include "radius_snmp.h"
75
76 #define SLEEP_FOREVER (65536)
77
78 /*
79  *  Global variables.
80  */
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;
87 int debug_flag = 0;
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__;
91
92 time_t time_now;
93 static pid_t radius_pid;
94
95 /*
96  *  Configuration items.
97  */
98 static int do_exit = 0;
99
100 /*
101  *      Static functions.
102  */
103 static void usage(int);
104
105 static void sig_fatal (int);
106 static void sig_hup (int);
107
108 /*
109  *      The main guy.
110  */
111 int main(int argc, char *argv[])
112 {
113         REQUEST *request;
114         unsigned char buffer[4096];
115         fd_set readfds;
116         int argval;
117         int pid;
118         int max_fd;
119         int status;
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;
125
126 #ifdef HAVE_SIGACTION
127         struct sigaction act;
128 #endif
129         rad_listen_t *listener;
130
131 #ifdef OSFC2
132         set_auth_parameters(argc,argv);
133 #endif
134
135         if ((progname = strrchr(argv[0], '/')) == NULL)
136                 progname = argv[0];
137         else
138                 progname++;
139
140         debug_flag = 0;
141         spawn_flag = TRUE;
142         radius_dir = strdup(RADIUS_DIR);
143
144         /*
145          *      Ensure that the configuration is initialized.
146          */
147         memset(&mainconfig, 0, sizeof(mainconfig));
148         mainconfig.myip.af = AF_UNSPEC;
149         mainconfig.port = -1;
150         mainconfig.radiusd_conf = "radiusd.conf";
151
152 #ifdef HAVE_SIGACTION
153         memset(&act, 0, sizeof(act));
154         act.sa_flags = 0 ;
155         sigemptyset( &act.sa_mask ) ;
156 #endif
157
158         /*  Process the options.  */
159         while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:n:p:sSvxXyz")) != EOF) {
160
161                 switch(argval) {
162
163                         case 'A':
164                                 log_auth_detail = TRUE;
165                                 break;
166
167                         case 'a':
168                                 if (radacct_dir) free(radacct_dir);
169                                 radacct_dir = strdup(optarg);
170                                 break;
171
172                         case 'c':
173                                 /* ignore for backwards compatibility with Cistron */
174                                 break;
175
176                         case 'd':
177                                 if (radius_dir) free(radius_dir);
178                                 radius_dir = strdup(optarg);
179                                 break;
180
181                         case 'f':
182                                 dont_fork = TRUE;
183                                 break;
184
185                         case 'h':
186                                 usage(0);
187                                 break;
188
189                         case 'i':
190                                 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
191                                         fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
192                                         exit(1);
193                                 }
194                                 break;
195
196                         case 'l':
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);
201                                         exit(1);
202                                 }
203                                 radlog_dir = strdup(optarg);
204                                 break;
205
206                         case 'g':
207                                 fprintf(stderr, "radiusd: -g is unsupported.  Use log_destination in radiusd.conf.\n");
208                                 exit(1);
209                                 break;
210
211                         case 'n':
212                                 if ((strchr(optarg, '/') != NULL) ||
213                                     (strchr(optarg, '.') != NULL) ||
214                                     (strlen(optarg) > 256)) usage(1);
215
216                                 snprintf(buffer, sizeof(buffer), "%s.conf",
217                                          optarg);
218                                 mainconfig.radiusd_conf = strdup(buffer);
219                                 break;
220
221                         case 'S':
222                                 log_stripped_names++;
223                                 break;
224
225                         case 'p':
226                                 mainconfig.port = atoi(optarg);
227                                 if ((mainconfig.port <= 0) ||
228                                     (mainconfig.port >= 65536)) {
229                                         fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
230                                         exit(1);
231                                 }
232                                 break;
233
234                         case 's':       /* Single process mode */
235                                 spawn_flag = FALSE;
236                                 dont_fork = TRUE;
237                                 break;
238
239                         case 'v':
240                                 version();
241                                 break;
242
243                                 /*
244                                  *  BIG debugging mode for users who are
245                                  *  TOO LAZY to type '-sfxxyz -l stdout' themselves.
246                                  */
247                         case 'X':
248                                 spawn_flag = FALSE;
249                                 dont_fork = TRUE;
250                                 debug_flag += 2;
251                                 mainconfig.log_auth = TRUE;
252                                 mainconfig.log_auth_badpass = TRUE;
253                                 mainconfig.log_auth_goodpass = TRUE;
254                                 mainconfig.radlog_dest = RADLOG_STDOUT;
255                                 break;
256
257                         case 'x':
258                                 debug_flag++;
259                                 break;
260
261                         case 'y':
262                                 mainconfig.log_auth = TRUE;
263                                 mainconfig.log_auth_badpass = TRUE;
264                                 break;
265
266                         case 'z':
267                                 mainconfig.log_auth_badpass = TRUE;
268                                 mainconfig.log_auth_goodpass = TRUE;
269                                 break;
270
271                         default:
272                                 usage(1);
273                                 break;
274                 }
275         }
276
277         /*
278          *      Get our PID.
279          */
280         radius_pid = getpid();
281
282         /*  Read the configuration files, BEFORE doing anything else.  */
283         if (read_mainconfig(0) < 0) {
284                 exit(1);
285         }
286
287         /*
288          *      If we're NOT debugging, trap fatal signals, so we can
289          *      easily clean up after ourselves.
290          *
291          *      If we ARE debugging, don't trap them, so we can
292          *      dump core.
293          */
294         if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
295 #ifdef SIGSEGV
296 #ifdef HAVE_SIGACTION
297                 act.sa_handler = sig_fatal;
298                 sigaction(SIGSEGV, &act, NULL);
299 #else
300                 signal(SIGSEGV, sig_fatal);
301 #endif
302 #endif
303         }
304
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");
309                 exit(1);
310         }
311
312 #ifdef WITH_SNMP
313         if (mainconfig.do_snmp) radius_snmp_init();
314 #endif
315
316         /*
317          *  Disconnect from session
318          */
319         if (debug_flag == 0 && dont_fork == FALSE) {
320                 pid = fork();
321                 if(pid < 0) {
322                         radlog(L_ERR|L_CONS, "Couldn't fork");
323                         exit(1);
324                 }
325
326                 /*
327                  *  The parent exits, so the child can run in the background.
328                  */
329                 if(pid > 0) {
330                         exit(0);
331                 }
332 #ifdef HAVE_SETSID
333                 setsid();
334 #endif
335         }
336
337         /*
338          *  Ensure that we're using the CORRECT pid after forking,
339          *  NOT the one we started with.
340          */
341         radius_pid = getpid();
342
343
344         /*
345          *  Only write the PID file if we're running as a daemon.
346          *
347          *  And write it AFTER we've forked, so that we write the
348          *  correct PID.
349          */
350         if (dont_fork == FALSE) {
351                 FILE *fp;
352
353                 fp = fopen(mainconfig.pid_file, "w");
354                 if (fp != NULL) {
355                         /*
356                          *      FIXME: What about following symlinks,
357                          *      and having it over-write a normal file?
358                          */
359                         fprintf(fp, "%d\n", (int) radius_pid);
360                         fclose(fp);
361                 } else {
362                         radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",
363                                mainconfig.pid_file, strerror(errno));
364                         exit(1);
365                 }
366         }
367
368         /*
369          *      If we're running as a daemon, close the default file
370          *      descriptors, AFTER forking.
371          */
372         mainconfig.radlog_fd = -1;
373         if (debug_flag) {
374                 mainconfig.radlog_fd = STDOUT_FILENO;
375         } else {
376                 int devnull;
377
378                 devnull = open("/dev/null", O_RDWR);
379                 if (devnull < 0) {
380                         radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
381                                strerror(errno));
382                         exit(1);
383                 }
384                 dup2(devnull, STDIN_FILENO);
385                 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
386                         mainconfig.radlog_fd = dup(STDOUT_FILENO);
387                 }
388                 dup2(devnull, STDOUT_FILENO);
389                 if (mainconfig.radlog_dest == RADLOG_STDERR) {
390                         mainconfig.radlog_fd = dup(STDERR_FILENO);
391                 }
392                 dup2(devnull, STDERR_FILENO);
393                 close(devnull);
394         }
395
396         /*
397          *      It's called the thread pool, but it does a little
398          *      more than that.
399          */
400         thread_pool_init(spawn_flag);
401
402         /*
403          *  Use linebuffered or unbuffered stdout if
404          *  the debug flag is on.
405          */
406         if (debug_flag == TRUE)
407                 setlinebuf(stdout);
408
409         /*
410          *      Print out which ports we're listening on.
411          */
412         for (listener = mainconfig.listen;
413              listener != NULL;
414              listener = listener->next) {
415                 if ((listener->ipaddr.af == AF_INET) &&
416                     (listener->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
417                         strcpy(buffer, "*");
418                 } else {
419                         ip_ntoh(&listener->ipaddr, buffer, sizeof(buffer));
420                 }
421                 
422                 switch (listener->type) {
423                 case RAD_LISTEN_AUTH:
424                         DEBUG("Listening on authentication address %s port %d",
425                               buffer, listener->port);
426                         break;
427
428                 case RAD_LISTEN_ACCT:
429                         DEBUG("Listening on accounting address %s port %d",
430                               buffer, listener->port);
431                         break;
432
433                 case RAD_LISTEN_PROXY:
434                         DEBUG("Listening on proxy address %s port %d",
435                               buffer, listener->port);
436                         break;
437
438                 case RAD_LISTEN_DETAIL:
439                         DEBUG("Listening on detail file %s", listener->detail);
440                         break;
441
442                 default:
443                         break;
444                 }
445         }
446
447         /*
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.
451          */
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);
458 #else
459         signal(SIGHUP, sig_hup);
460         signal(SIGTERM, sig_fatal);
461 #endif
462         /*
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.
466          */
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);
472 #else
473                 signal(SIGINT, sig_fatal);
474                 signal(SIGQUIT, sig_fatal);
475 #endif
476         }
477
478         radlog(L_INFO, "Ready to process requests.");
479
480         /*
481          *  Receive user requests
482          */
483         for (;;) {
484                 /*
485                  *      If we've been told to exit, then do so,
486                  *      even if we have data waiting.
487                  */
488                 if (do_exit) {
489                         DEBUG("Exiting...");
490
491                         /*
492                          *      Ignore the TERM signal: we're about
493                          *      to die.
494                          */
495                         signal(SIGTERM, SIG_IGN);
496
497                         /*
498                          *      Send a TERM signal to all associated
499                          *      processes (including us, which gets
500                          *      ignored.)
501                          */
502                         kill(-radius_pid, SIGTERM);
503
504                         /*
505                          *      FIXME: Kill child threads, and
506                          *      clean up?
507                          */
508
509                         /*
510                          *      Detach any modules.
511                          */
512                         detach_modules();
513
514                         /*
515                          *      FIXME: clean up any active REQUEST
516                          *      handles.
517                          */
518
519                         /*
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)
523                          */
524                         if (dont_fork == FALSE) {
525                                 unlink(mainconfig.pid_file);
526                         }
527
528                         /*
529                          *      Free the configuration items.
530                          */
531                         free_mainconfig();
532
533                         /*
534                          *      SIGTERM gets do_exit=0,
535                          *      and we want to exit cleanly.
536                          *
537                          *      Other signals make us exit
538                          *      with an error status.
539                          */
540                         exit(do_exit - 1);
541                 }
542
543                 if (need_reload) {
544 #ifdef HAVE_PTHREAD_H
545                         /*
546                          *      Threads: wait for all threads to stop
547                          *      processing before re-loading the
548                          *      config, so we don't pull the rug out
549                          *      from under them.
550                          */
551                         int max_wait = 0;
552                         if (!spawn_flag) for(;;) {
553                                 /*
554                                  * Block until there are '0' threads
555                                  * with a REQUEST handle.
556                                  */
557                                 sig_hup_block = TRUE;
558                                 if( (total_active_threads() == 0) ||
559                                     (max_wait >= 5) ) {
560                                         sig_hup_block = FALSE;
561                                         break;
562                                 }
563                                 sleep(1);
564                                 max_wait++;
565                         }
566 #endif
567                         if (read_mainconfig(TRUE) < 0) {
568                                 exit(1);
569                         }
570
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");
575                                 exit(1);
576                         }
577
578                         need_reload = FALSE;
579                         radlog(L_INFO, "Ready to process requests.");
580                 }
581
582                 FD_ZERO(&readfds);
583                 max_fd = 0;
584
585                 /*
586                  *      Loop over all the listening FD's.
587                  */
588                 for (listener = mainconfig.listen;
589                      listener != NULL;
590                      listener = listener->next) {
591                         if (listener->fd < 0) continue;
592
593                         FD_SET(listener->fd, &readfds);
594                         if (listener->fd > max_fd) max_fd = listener->fd;
595                 }
596
597 #ifdef WITH_SNMP
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;
602                 }
603 #endif
604
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);
608                 } else {
609                         struct timeval tv;
610
611                         DEBUG2("Waking up in %d seconds...", sleep_time);
612
613                         tv.tv_sec = sleep_time;
614                         tv.tv_usec = 0;
615                         status = select(max_fd + 1, &readfds, NULL, NULL, &tv);
616                 }
617                 if (status == -1) {
618                         /*
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.
624                          */
625                         if (errno == EINTR) {
626 #ifdef MEMORY_USE_DEBUGGING
627                                 /*
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,
633                                  *      and the like.
634                                  */
635                                 detach_modules();
636                                 free_mainconfig();
637                                 xlat_free();
638                                 dict_free();
639                                 exit(1);
640 #endif
641                                 continue;
642                         }
643                         radlog(L_ERR, "Unexpected error in select(): %s",
644                                         strerror(errno));
645                         exit(1);
646                 }
647
648                 time_now = time(NULL);
649 #ifndef HAVE_PTHREAD_H
650                 /*
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.
655                  */
656                 while (waitpid(-1, &argval, WNOHANG) > 0) {
657                         /* do nothing */
658                 }
659 #endif
660
661                 /*
662                  *      Loop over the open socket FD's, reading any data.
663                  */
664                 for (listener = mainconfig.listen;
665                      listener != NULL;
666                      listener = listener->next) {
667                         RAD_REQUEST_FUNP fun;
668
669                         if ((listener->fd >= 0) &&
670                             !FD_ISSET(listener->fd, &readfds))
671                                 continue;
672
673                         /*
674                          *  Receive the packet.
675                          */
676                         if (sig_hup_block != FALSE) {
677                                 continue;
678                         }
679
680                         /*
681                          *      Do per-socket receive processing of the
682                          *      packet.
683                          */
684                         if (!listener->recv(listener, &fun, &request)) {
685                                 continue;
686                         }
687                         
688                         /*
689                          *      Drop the request into the thread pool,
690                          *      and let the thread pool take care of
691                          *      doing something with it.
692                          */
693                         if (!thread_pool_addrequest(request, fun)) {
694                                 /*
695                                  *      FIXME: Maybe just drop
696                                  *      the packet on the floor?
697                                  */
698                                 request_reject(request, REQUEST_FAIL_NO_THREADS);
699                                 request->finished = TRUE;
700                         }
701                 } /* loop over listening sockets*/
702
703 #ifdef WITH_SNMP
704                 if (mainconfig.do_snmp) {
705                         /*
706                          *  After handling all authentication/accounting
707                          *  requests, THEN process any pending SMUX/SNMP
708                          *  queries.
709                          *
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.
713                          */
714                         if ((rad_snmp.smux_fd >= 0) &&
715                             FD_ISSET(rad_snmp.smux_fd, &readfds) &&
716                             (rad_snmp.smux_event == SMUX_READ)) {
717                                 smux_read();
718                         }
719
720                         /*
721                          *  If we've got to re-connect, then do so now,
722                          *  before calling select again.
723                          */
724                         if (rad_snmp.smux_event == SMUX_CONNECT) {
725                                 smux_connect();
726                         }
727                 }
728 #endif
729
730                 /*
731                  *      Loop through the request lists once per
732                  *      second, to clean up old requests.
733                  */
734                 if (last_cleaned_lists != time_now) {
735                         last_cleaned_lists = time_now;
736
737                         DEBUG2("--- Walking the entire request list ---");
738                         sleep_time = SLEEP_FOREVER;
739                         for (listener = mainconfig.listen;
740                              listener != NULL;
741                              listener = listener->next) {
742                                 int next;
743                                 
744                                 next = listener->update(listener, time_now);
745                                 if (next < sleep_time) {
746                                         sleep_time = next;
747                                 }
748                         }
749                 }
750
751 #ifdef HAVE_PTHREAD_H
752
753                 /*
754                  *      Only clean the thread pool if we're spawning
755                  *      child threads. 
756                  */
757                 if (spawn_flag) {
758                         thread_pool_clean(time_now);
759                 }
760 #endif
761         } /* loop forever */
762 }
763
764
765 /*
766  *  Display the syntax for starting this program.
767  */
768 static void usage(int status)
769 {
770         FILE *output = status?stderr:stdout;
771
772         fprintf(output,
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");
790         exit(status);
791 }
792
793
794 /*
795  *      We got a fatal signal.
796  */
797 static void sig_fatal(int sig)
798 {
799         switch(sig) {
800                 case SIGSEGV:
801                         /* We can't really do anything intelligent here so just die */
802                         exit(1);
803                 case SIGTERM:
804                         do_exit = 1;
805                         break;
806                 default:
807                         do_exit = 2;
808                         break;
809         }
810 }
811
812
813 /*
814  *  We got the hangup signal.
815  *  Re-read the configuration files.
816  */
817 /*ARGSUSED*/
818 static void sig_hup(int sig)
819 {
820         sig = sig; /* -Wunused */
821
822         reset_signal(SIGHUP, sig_hup);
823
824         /*
825          *  Only do the reload if we're the main server, both
826          *  for processes, and for threads.
827          */
828         if (getpid() == radius_pid) {
829                 need_reload = TRUE;
830         }
831 #ifdef WITH_SNMP
832         if (mainconfig.do_snmp) {
833                 rad_snmp.smux_failures = 0;
834                 rad_snmp.smux_event = SMUX_CONNECT;
835         }
836 #endif
837 }