'X' means 'print output to stdout'
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 <freeradius-devel/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 <freeradius-devel/radiusd.h>
70 #include <freeradius-devel/rad_assert.h>
71 #include <freeradius-devel/conffile.h>
72 #include <freeradius-devel/modules.h>
73 #include <freeradius-devel/request_list.h>
74 #include <freeradius-devel/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
91 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
92
93 time_t time_now;
94 static pid_t radius_pid;
95
96 /*
97  *  Configuration items.
98  */
99 static int do_exit = 0;
100
101 /*
102  *      Static functions.
103  */
104 static void usage(int);
105
106 static void sig_fatal (int);
107 static void sig_hup (int);
108
109 /*
110  *      The main guy.
111  */
112 int main(int argc, char *argv[])
113 {
114         REQUEST *request;
115         unsigned char buffer[4096];
116         fd_set readfds;
117         int argval;
118         int pid;
119         int max_fd;
120         int status;
121         int sleep_time = SLEEP_FOREVER;
122         int spawn_flag = TRUE;
123         int dont_fork = FALSE;
124         int sig_hup_block = FALSE;
125         time_t last_cleaned_lists = 0;
126
127 #ifdef HAVE_SIGACTION
128         struct sigaction act;
129 #endif
130         rad_listen_t *listener;
131
132 #ifdef OSFC2
133         set_auth_parameters(argc,argv);
134 #endif
135
136         if ((progname = strrchr(argv[0], '/')) == NULL)
137                 progname = argv[0];
138         else
139                 progname++;
140
141         debug_flag = 0;
142         spawn_flag = TRUE;
143         radius_dir = strdup(RADIUS_DIR);
144
145         /*
146          *      Ensure that the configuration is initialized.
147          */
148         memset(&mainconfig, 0, sizeof(mainconfig));
149         mainconfig.myip.af = AF_UNSPEC;
150         mainconfig.port = -1;
151         mainconfig.radiusd_conf = strdup("radiusd.conf");
152
153 #ifdef HAVE_SIGACTION
154         memset(&act, 0, sizeof(act));
155         act.sa_flags = 0 ;
156         sigemptyset( &act.sa_mask ) ;
157 #endif
158
159         /*
160          *      Don't put output anywhere until we get told a little
161          *      more.
162          */
163         mainconfig.radlog_fd = -1;
164         mainconfig.log_file = NULL;
165
166         /*  Process the options.  */
167         while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:n:p:sSvxXyz")) != EOF) {
168
169                 switch(argval) {
170
171                         case 'A':
172                                 log_auth_detail = TRUE;
173                                 break;
174
175                         case 'a':
176                                 if (radacct_dir) free(radacct_dir);
177                                 radacct_dir = strdup(optarg);
178                                 break;
179
180                         case 'c':
181                                 /* ignore for backwards compatibility with Cistron */
182                                 break;
183
184                         case 'd':
185                                 if (radius_dir) free(radius_dir);
186                                 radius_dir = strdup(optarg);
187                                 break;
188
189                         case 'f':
190                                 dont_fork = TRUE;
191                                 break;
192
193                         case 'h':
194                                 usage(0);
195                                 break;
196
197                         case 'i':
198                                 if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
199                                         fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
200                                         exit(1);
201                                 }
202                                 break;
203
204                         case 'l':
205                                 if ((strcmp(optarg, "stdout") == 0) ||
206                                     (strcmp(optarg, "stderr") == 0) ||
207                                     (strcmp(optarg, "syslog") == 0)) {
208                                         fprintf(stderr, "radiusd: -l %s is unsupported.  Use log_destination in radiusd.conf\n", optarg);
209                                         exit(1);
210                                 }
211                                 if (radlog_dir) free(radlog_dir);
212                                 radlog_dir = strdup(optarg);
213                                 break;
214
215                         case 'g':
216                                 fprintf(stderr, "radiusd: -g is unsupported.  Use log_destination in radiusd.conf.\n");
217                                 exit(1);
218                                 break;
219
220                         case 'n':
221                                 if ((strchr(optarg, '/') != NULL) ||
222                                     (strchr(optarg, '.') != NULL) ||
223                                     (strlen(optarg) > 45)) usage(1);
224
225                                 snprintf(buffer, sizeof(buffer), "%s.conf",
226                                          optarg);
227                                 if (mainconfig.radiusd_conf)
228                                         free(mainconfig.radiusd_conf);
229                                 mainconfig.radiusd_conf = strdup(buffer);
230                                 break;
231
232                         case 'S':
233                                 log_stripped_names++;
234                                 break;
235
236                         case 'p':
237                                 mainconfig.port = atoi(optarg);
238                                 if ((mainconfig.port <= 0) ||
239                                     (mainconfig.port >= 65536)) {
240                                         fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
241                                         exit(1);
242                                 }
243                                 break;
244
245                         case 's':       /* Single process mode */
246                                 spawn_flag = FALSE;
247                                 dont_fork = TRUE;
248                                 break;
249
250                         case 'v':
251                                 version();
252                                 break;
253
254                                 /*
255                                  *  BIG debugging mode for users who are
256                                  *  TOO LAZY to type '-sfxxyz -l stdout' themselves.
257                                  */
258                         case 'X':
259                                 spawn_flag = FALSE;
260                                 dont_fork = TRUE;
261                                 debug_flag += 2;
262                                 mainconfig.log_auth = TRUE;
263                                 mainconfig.log_auth_badpass = TRUE;
264                                 mainconfig.log_auth_goodpass = TRUE;
265                                 mainconfig.radlog_dest = RADLOG_STDOUT;
266                                 mainconfig.radlog_fd = STDOUT_FILENO;
267                                 break;
268
269                         case 'x':
270                                 debug_flag++;
271                                 break;
272
273                         case 'y':
274                                 mainconfig.log_auth = TRUE;
275                                 mainconfig.log_auth_badpass = TRUE;
276                                 break;
277
278                         case 'z':
279                                 mainconfig.log_auth_badpass = TRUE;
280                                 mainconfig.log_auth_goodpass = TRUE;
281                                 break;
282
283                         default:
284                                 usage(1);
285                                 break;
286                 }
287         }
288
289         /*  Read the configuration files, BEFORE doing anything else.  */
290         if (read_mainconfig(0) < 0) {
291                 exit(1);
292         }
293
294         /*
295          *  Disconnect from session
296          */
297         if (debug_flag == 0 && dont_fork == FALSE) {
298                 pid = fork();
299                 if(pid < 0) {
300                         radlog(L_ERR|L_CONS, "Couldn't fork");
301                         exit(1);
302                 }
303
304                 /*
305                  *  The parent exits, so the child can run in the background.
306                  */
307                 if (pid > 0) {
308                         exit(0);
309                 }
310 #ifdef HAVE_SETSID
311                 setsid();
312 #endif
313         }
314
315         /*
316          *      If we're NOT debugging, trap fatal signals, so we can
317          *      easily clean up after ourselves.
318          *
319          *      If we ARE debugging, don't trap them, so we can
320          *      dump core.
321          */
322         if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
323 #ifdef SIGSEGV
324 #ifdef HAVE_SIGACTION
325                 act.sa_handler = sig_fatal;
326                 sigaction(SIGSEGV, &act, NULL);
327 #else
328                 signal(SIGSEGV, sig_fatal);
329 #endif
330 #endif
331         }
332
333 #ifdef WITH_SNMP
334         if (mainconfig.do_snmp) radius_snmp_init();
335 #endif
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         if (!debug_flag) {
373                 int devnull;
374
375                 devnull = open("/dev/null", O_RDWR);
376                 if (devnull < 0) {
377                         radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",
378                                strerror(errno));
379                         exit(1);
380                 }
381                 dup2(devnull, STDIN_FILENO);
382                 if (mainconfig.radlog_dest == RADLOG_STDOUT) {
383                         mainconfig.radlog_fd = dup(STDOUT_FILENO);
384                 }
385                 dup2(devnull, STDOUT_FILENO);
386                 if (mainconfig.radlog_dest == RADLOG_STDERR) {
387                         mainconfig.radlog_fd = dup(STDERR_FILENO);
388                 }
389                 dup2(devnull, STDERR_FILENO);
390                 close(devnull);
391         }
392
393         /*
394          *      It's called the thread pool, but it does a little
395          *      more than that.
396          */
397         thread_pool_init(spawn_flag);
398
399         /*
400          *  Use linebuffered or unbuffered stdout if
401          *  the debug flag is on.
402          */
403         if (debug_flag == TRUE)
404                 setlinebuf(stdout);
405
406         /*
407          *      Print out which ports we're listening on.
408          */
409         for (listener = mainconfig.listen;
410              listener != NULL;
411              listener = listener->next) {
412                 listener->print(listener, buffer, sizeof(buffer));
413                 switch (listener->type) {
414                 case RAD_LISTEN_AUTH:
415                         DEBUG("Listening on authentication address %s", buffer);
416                         break;
417
418                 case RAD_LISTEN_ACCT:
419                         DEBUG("Listening on accounting address %s", buffer);
420                         break;
421
422                 case RAD_LISTEN_PROXY:
423                         DEBUG("Listening on proxy address %s", buffer);
424                         break;
425
426                 case RAD_LISTEN_DETAIL:
427                         DEBUG("Listening on detail file %s", buffer);
428                         break;
429
430                 default:
431                         break;
432                 }
433         }
434
435         /*
436          *      Now that we've set everything up, we can install the signal
437          *      handlers.  Before this, if we get any signal, we don't know
438          *      what to do, so we might as well do the default, and die.
439          */
440         signal(SIGPIPE, SIG_IGN);
441 #ifdef HAVE_SIGACTION
442         act.sa_handler = sig_hup;
443         sigaction(SIGHUP, &act, NULL);
444         act.sa_handler = sig_fatal;
445         sigaction(SIGTERM, &act, NULL);
446 #else
447         signal(SIGHUP, sig_hup);
448         signal(SIGTERM, sig_fatal);
449 #endif
450         /*
451          *      If we're debugging, then a CTRL-C will cause the
452          *      server to die immediately.  Use SIGTERM to shut down
453          *      the server cleanly in that case.
454          */
455         if (debug_flag == 0) {
456 #ifdef HAVE_SIGACTION
457                 act.sa_handler = sig_fatal;
458                 sigaction(SIGINT, &act, NULL);
459                 sigaction(SIGQUIT, &act, NULL);
460 #else
461                 signal(SIGINT, sig_fatal);
462                 signal(SIGQUIT, sig_fatal);
463 #endif
464         }
465
466         radlog(L_INFO, "Ready to process requests.");
467
468         /*
469          *  Receive user requests
470          */
471         for (;;) {
472                 /*
473                  *      If we've been told to exit, then do so,
474                  *      even if we have data waiting.
475                  */
476                 if (do_exit) {
477                         DEBUG("Exiting...");
478
479                         /*
480                          *      Ignore the TERM signal: we're about
481                          *      to die.
482                          */
483                         signal(SIGTERM, SIG_IGN);
484
485                         /*
486                          *      Send a TERM signal to all associated
487                          *      processes (including us, which gets
488                          *      ignored.)
489                          */
490                         kill(-radius_pid, SIGTERM);
491
492                         /*
493                          *      FIXME: Kill child threads, and
494                          *      clean up?
495                          */
496
497                         /*
498                          *      Detach any modules.
499                          */
500                         detach_modules();
501
502                         /*
503                          *      FIXME: clean up any active REQUEST
504                          *      handles.
505                          */
506
507                         /*
508                          *      We're exiting, so we can delete the PID
509                          *      file.  (If it doesn't exist, we can ignore
510                          *      the error returned by unlink)
511                          */
512                         if (dont_fork == FALSE) {
513                                 unlink(mainconfig.pid_file);
514                         }
515
516                         /*
517                          *      Free the configuration items.
518                          */
519                         free_mainconfig();
520
521                         /*
522                          *      SIGTERM gets do_exit=0,
523                          *      and we want to exit cleanly.
524                          *
525                          *      Other signals make us exit
526                          *      with an error status.
527                          */
528                         exit(do_exit - 1);
529                 }
530
531                 if (need_reload) {
532 #ifdef HAVE_PTHREAD_H
533                         /*
534                          *      Threads: wait for all threads to stop
535                          *      processing before re-loading the
536                          *      config, so we don't pull the rug out
537                          *      from under them.
538                          */
539                         int max_wait = 0;
540                         if (spawn_flag) for(;;) {
541                                 /*
542                                  * Block until there are '0' threads
543                                  * with a REQUEST handle.
544                                  */
545                                 sig_hup_block = TRUE;
546                                 if( (total_active_threads() == 0) ||
547                                     (max_wait >= 5) ) {
548                                         sig_hup_block = FALSE;
549                                         break;
550                                 }
551                                 sleep(1);
552                                 max_wait++;
553                         }
554 #endif
555                         if (read_mainconfig(TRUE) < 0) {
556                                 exit(1);
557                         }
558
559                         need_reload = FALSE;
560                         radlog(L_INFO, "Ready to process requests.");
561                 }
562
563                 FD_ZERO(&readfds);
564                 max_fd = 0;
565
566                 /*
567                  *      Loop over all the listening FD's.
568                  */
569                 for (listener = mainconfig.listen;
570                      listener != NULL;
571                      listener = listener->next) {
572                         if (listener->fd < 0) continue;
573
574                         FD_SET(listener->fd, &readfds);
575                         if (listener->fd > max_fd) max_fd = listener->fd;
576                 }
577
578 #ifdef WITH_SNMP
579                 if (mainconfig.do_snmp &&
580                     (rad_snmp.smux_fd >= 0)) {
581                         FD_SET(rad_snmp.smux_fd, &readfds);
582                         if (rad_snmp.smux_fd > max_fd) max_fd = rad_snmp.smux_fd;
583                 }
584 #endif
585
586                 if (sleep_time == SLEEP_FOREVER) {
587                         DEBUG2("Nothing to do.  Sleeping until we see a request.");
588                         status = select(max_fd + 1, &readfds, NULL, NULL, NULL);
589                 } else {
590                         struct timeval tv;
591
592                         DEBUG2("Waking up in %d seconds...", sleep_time);
593
594                         tv.tv_sec = sleep_time;
595                         tv.tv_usec = 0;
596                         status = select(max_fd + 1, &readfds, NULL, NULL, &tv);
597                 }
598                 if (status == -1) {
599                         /*
600                          *      On interrupts, we clean up the request
601                          *      list.  We then continue with the loop,
602                          *      so that if we're supposed to exit,
603                          *      then the code at the start of the loop
604                          *      catches that, and exits.
605                          */
606                         if (errno == EINTR) {
607 #ifdef MEMORY_USE_DEBUGGING
608                                 /*
609                                  *      Run the server in debugging mode,
610                                  *      without threads, and give it a
611                                  *      SIGHUP.  It will clean up after
612                                  *      itself, and any memory left over
613                                  *      should be allocated by C libraries,
614                                  *      and the like.
615                                  */
616                                 detach_modules();
617                                 free_mainconfig();
618                                 xlat_free();
619                                 dict_free();
620                                 exit(1);
621 #endif
622                                 continue;
623                         }
624                         radlog(L_ERR, "Unexpected error in select(): %s",
625                                         strerror(errno));
626                         exit(1);
627                 }
628
629                 time_now = time(NULL);
630 #ifndef HAVE_PTHREAD_H
631                 /*
632                  *      If there are no child threads, then there may
633                  *      be child processes.  In that case, wait for
634                  *      their exit status, and throw that exit status
635                  *      away.  This helps get rid of zxombie children.
636                  */
637                 while (waitpid(-1, &argval, WNOHANG) > 0) {
638                         /* do nothing */
639                 }
640 #endif
641
642                 /*
643                  *      Loop over the open socket FD's, reading any data.
644                  */
645                 for (listener = mainconfig.listen;
646                      listener != NULL;
647                      listener = listener->next) {
648                         RAD_REQUEST_FUNP fun;
649
650                         if ((listener->fd >= 0) &&
651                             !FD_ISSET(listener->fd, &readfds))
652                                 continue;
653
654                         /*
655                          *  Receive the packet.
656                          */
657                         if (sig_hup_block != FALSE) {
658                                 continue;
659                         }
660
661                         /*
662                          *      Do per-socket receive processing of the
663                          *      packet.
664                          */
665                         if (!listener->recv(listener, &fun, &request)) {
666                                 continue;
667                         }
668                         
669                         /*
670                          *      Drop the request into the thread pool,
671                          *      and let the thread pool take care of
672                          *      doing something with it.
673                          */
674                         if (!thread_pool_addrequest(request, fun)) {
675                                 /*
676                                  *      FIXME: Maybe just drop
677                                  *      the packet on the floor?
678                                  */
679                                 request_reject(request, REQUEST_FAIL_NO_THREADS);
680                                 request->finished = TRUE;
681                         }
682                 } /* loop over listening sockets*/
683
684 #ifdef WITH_SNMP
685                 if (mainconfig.do_snmp) {
686                         /*
687                          *  After handling all authentication/accounting
688                          *  requests, THEN process any pending SMUX/SNMP
689                          *  queries.
690                          *
691                          *  Note that the handling is done in the main server,
692                          *  which probably isn't a Good Thing.  It really
693                          *  should be wrapped, and handled in a thread pool.
694                          */
695                         if ((rad_snmp.smux_fd >= 0) &&
696                             FD_ISSET(rad_snmp.smux_fd, &readfds) &&
697                             (rad_snmp.smux_event == SMUX_READ)) {
698                                 smux_read();
699                         }
700
701                         /*
702                          *  If we've got to re-connect, then do so now,
703                          *  before calling select again.
704                          */
705                         if (rad_snmp.smux_event == SMUX_CONNECT) {
706                                 smux_connect();
707                         }
708                 }
709 #endif
710
711                 /*
712                  *      Loop through the request lists once per
713                  *      second, to clean up old requests.
714                  */
715                 if (last_cleaned_lists != time_now) {
716                         last_cleaned_lists = time_now;
717
718                         DEBUG2("--- Walking the entire request list ---");
719                         sleep_time = SLEEP_FOREVER;
720                         for (listener = mainconfig.listen;
721                              listener != NULL;
722                              listener = listener->next) {
723                                 int next;
724                                 
725                                 next = listener->update(listener, time_now);
726                                 if (next < sleep_time) {
727                                         sleep_time = next;
728                                 }
729                         }
730                 }
731
732 #ifdef HAVE_PTHREAD_H
733
734                 /*
735                  *      Only clean the thread pool if we're spawning
736                  *      child threads. 
737                  */
738                 if (spawn_flag) {
739                         thread_pool_clean(time_now);
740                 }
741 #endif
742         } /* loop forever */
743 }
744
745
746 /*
747  *  Display the syntax for starting this program.
748  */
749 static void NEVER_RETURNS usage(int status)
750 {
751         FILE *output = status?stderr:stdout;
752
753         fprintf(output,
754                         "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
755         fprintf(output, "Options:\n\n");
756         fprintf(output, "  -a acct_dir     use accounting directory 'acct_dir'.\n");
757         fprintf(output, "  -A              Log auth detail.\n");
758         fprintf(output, "  -d raddb_dir    Configuration files are in \"raddbdir/*\".\n");
759         fprintf(output, "  -f              Run as a foreground process, not a daemon.\n");
760         fprintf(output, "  -h              Print this help message.\n");
761         fprintf(output, "  -i ipaddr       Listen on ipaddr ONLY\n");
762         fprintf(output, "  -l log_dir      Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
763         fprintf(output, "  -p port         Listen on port ONLY\n");
764         fprintf(output, "  -s              Do not spawn child processes to handle requests.\n");
765         fprintf(output, "  -S              Log stripped names.\n");
766         fprintf(output, "  -v              Print server version information.\n");
767         fprintf(output, "  -X              Turn on full debugging.\n");
768         fprintf(output, "  -x              Turn on additional debugging. (-xx gives more debugging).\n");
769         fprintf(output, "  -y              Log authentication failures, with password.\n");
770         fprintf(output, "  -z              Log authentication successes, with password.\n");
771         exit(status);
772 }
773
774
775 /*
776  *      We got a fatal signal.
777  */
778 static void sig_fatal(int sig)
779 {
780         switch(sig) {
781                 case SIGSEGV:
782                         /* We can't really do anything intelligent here so just die */
783                         _exit(1);
784                 case SIGTERM:
785                         do_exit = 1;
786                         break;
787                 default:
788                         do_exit = 2;
789                         break;
790         }
791 }
792
793
794 /*
795  *  We got the hangup signal.
796  *  Re-read the configuration files.
797  */
798 /*ARGSUSED*/
799 static void sig_hup(int sig)
800 {
801         sig = sig; /* -Wunused */
802
803         reset_signal(SIGHUP, sig_hup);
804
805         /*
806          *  Only do the reload if we're the main server, both
807          *  for processes, and for threads.
808          */
809         if (getpid() == radius_pid) {
810                 need_reload = TRUE;
811         }
812 #ifdef WITH_SNMP
813         if (mainconfig.do_snmp) {
814                 rad_snmp.smux_failures = 0;
815                 rad_snmp.smux_event = SMUX_CONNECT;
816         }
817 #endif
818 }