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