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