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