1ca5f6566ceb2677ac3f0c0da581fc08f1699890
[freeradius.git] / src / main / radiusd.c
1 /*
2  * radiusd.c    Main loop of the radius server.
3  *
4  * Version:     $Id$
5  *
6  */
7
8 /* don't look here for the version, run radiusd -v or look in version.c */
9 static const char rcsid[] =
10 "$Id$";
11
12 #include        "autoconf.h"
13
14 #include        <sys/socket.h>
15 #include        <sys/file.h>
16
17 #if HAVE_NETINET_IN_H
18 #include        <netinet/in.h>
19 #endif
20
21 #include        <stdlib.h>
22 #include        <string.h>
23 #include        <netdb.h>
24 #include        <fcntl.h>
25 #include        <ctype.h>
26
27 #if HAVE_UNISTD_H
28 #include        <unistd.h>
29 #endif
30
31 #include        <signal.h>
32
33 #if HAVE_GETOPT_H
34 #include        <getopt.h>
35 #endif
36
37 #if HAVE_SYS_SELECT_H
38 #include        <sys/select.h>
39 #endif
40
41 #if HAVE_SYSLOG_H
42 #include        <syslog.h>
43 #endif
44
45 #if HAVE_SYS_WAIT_H
46 # include <sys/wait.h>
47 #endif
48 #ifndef WEXITSTATUS
49 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
50 #endif
51 #ifndef WIFEXITED
52 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
53 #endif
54
55 #include <assert.h>
56
57 #include        "radiusd.h"
58 #include        "conffile.h"
59
60 #if WITH_SNMP
61 #include        "radius_snmp.h"
62 #endif
63
64 #include        <sys/resource.h>
65
66 /*
67  *      Global variables.
68  */
69 const char              *progname = NULL;
70 char                    *radius_dir = NULL;
71 char                    *radacct_dir = NULL;
72 char                    *radlog_dir = NULL;
73 const char              *radlib_dir = NULL;
74 #ifdef WITH_SNMP
75 char                    *smux_password = NULL;
76 int                     snmp_write_access = FALSE;
77 int                     snmp_acctotalrequests = 0;
78 int                     snmp_authtotalrequests = 0;
79 enum smux_event         smux_event = SMUX_NONE;
80 #endif
81 int                     log_stripped_names;
82 int                     debug_flag;
83 int                     use_dbm = FALSE;
84 uint32_t                myip = INADDR_ANY;
85 int                     log_auth_detail = FALSE;
86 int                     log_auth = FALSE;
87 int                     log_auth_pass  = FALSE;
88 int                     auth_port = 0;
89 int                     acct_port;
90 int                     proxy_port;
91 int                     proxy_retry_delay = RETRY_DELAY;
92 int                     proxy_retry_count = RETRY_COUNT;
93 int                     proxy_synchronous = TRUE;
94 int                     need_reload = FALSE;
95 int                     radius_port = 0;
96 struct  servent         *svp;
97
98 static int              got_child = FALSE;
99 static int              request_list_busy = FALSE;
100 static int              authfd;
101 static int              acctfd;
102 int                     proxyfd;
103 #ifdef WITH_SNMP
104 int                     smuxfd;
105 #endif
106 static int              spawn_flag = TRUE;
107 static pid_t            radius_pid;
108 static struct rlimit    core_limits;
109 static int              proxy_requests = TRUE;
110
111 /*
112  *  We keep the incoming requests in an array, indexed by ID.
113  *
114  *  Each array element contains a linked list of active requests,
115  *  a count of the number of requests, and a time at which the first
116  *  request in the list must be serviced.
117  */
118 typedef struct REQUEST_LIST {
119   REQUEST       *first_request;
120   int           request_count;
121   time_t        service_time;
122 } REQUEST_LIST;
123
124 static REQUEST_LIST     request_list[256];
125
126 /*
127  *  Configuration items.
128  */
129 static int              allow_core_dumps = FALSE;
130 static int              max_request_time = MAX_REQUEST_TIME;
131 static int              cleanup_delay = CLEANUP_DELAY;
132 static int              max_requests = MAX_REQUESTS;
133 static int              dont_fork = FALSE;
134 static const char       *pid_file = NULL;
135
136 #if !defined(__linux__) && !defined(__GNU_LIBRARY__)
137 extern int      errno;
138 #endif
139
140 static void     usage(void);
141
142 static void     sig_fatal (int);
143 static void     sig_hup (int);
144
145 static void     rad_reject(REQUEST *request);
146 static int      rad_process (REQUEST *, int);
147 static int      rad_clean_list(time_t curtime);
148 static REQUEST  *rad_check_list(REQUEST *);
149 static REQUEST *proxy_check_list(REQUEST *request);
150 static struct timeval *setuptimeout(struct timeval *);
151 static void     proxy_retry(void);
152 #ifndef WITH_THREAD_POOL
153 static int      rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
154 #else
155 extern int      rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
156 #endif
157
158 /*
159  *      A mapping of configuration file names to internal variables
160  */
161 static CONF_PARSER server_config[] = {
162   { "max_request_time",   PW_TYPE_INTEGER,
163     &max_request_time,    Stringify(MAX_REQUEST_TIME) },
164   { "cleanup_delay",      PW_TYPE_INTEGER,
165     &cleanup_delay,       Stringify(CLEANUP_DELAY) },
166   { "max_requests",       PW_TYPE_INTEGER,
167     &max_requests,        Stringify(MAX_REQUESTS) },
168   { "port",               PW_TYPE_INTEGER,
169     &auth_port,           Stringify(PW_AUTH_UDP_PORT) },
170   { "allow_core_dumps",   PW_TYPE_BOOLEAN,    &allow_core_dumps,  "no" },
171   { "log_stripped_names", PW_TYPE_BOOLEAN,    &log_stripped_names,"no" },
172   { "log_auth",           PW_TYPE_BOOLEAN,    &log_auth,          "no" },
173   { "log_auth_pass",      PW_TYPE_BOOLEAN,    &log_auth_pass,     "no" },
174   { "pidfile",            PW_TYPE_STRING_PTR, &pid_file,          RADIUS_PID },
175   { "log_dir",            PW_TYPE_STRING_PTR, &radlog_dir,        RADLOG_DIR },
176   { "lib_dir",            PW_TYPE_STRING_PTR, &radlib_dir,        LIBDIR },
177   { "acct_dir",           PW_TYPE_STRING_PTR, &radacct_dir,       RADACCT_DIR },
178   { "bind_address",       PW_TYPE_IPADDR,     &myip,              "*" },
179   { "proxy_requests",     PW_TYPE_BOOLEAN,    &proxy_requests,    "yes" },
180 #if 0
181   { "confdir",            PW_TYPE_STRING_PTR, &radius_dir,        RADIUS_DIR },
182 #endif
183   { "hostname_lookups",   PW_TYPE_BOOLEAN,    &librad_dodns,      "0" },
184 #ifdef WITH_SNMP
185   { "smux_password",      PW_TYPE_STRING_PTR, &smux_password,     "" },
186   { "snmp_write_access",  PW_TYPE_BOOLEAN,    &snmp_write_access, "no" },
187 #endif
188   { NULL, -1, NULL, NULL }
189 };
190
191 /*
192  *      Map the proxy server configuration parameters to variables.
193  */
194 static CONF_PARSER proxy_config[] = {
195   { "retry_delay",  PW_TYPE_INTEGER,
196     &proxy_retry_delay, Stringify(RETRY_DELAY) },
197   { "retry_count",  PW_TYPE_INTEGER,
198     &proxy_retry_count, Stringify(RETRY_COUNT) },
199   { "synchronous",  PW_TYPE_BOOLEAN, &proxy_synchronous, "yes" },
200
201   { NULL, -1, NULL, NULL }
202 };
203
204 /*
205  *      Read config files.
206  */
207 static void reread_config(int reload)
208 {
209         int res = 0;
210         int pid = getpid();
211         CONF_SECTION *cs;
212
213         if (!reload) {
214                 radlog(L_INFO, "Starting - reading configuration files ...");
215 #ifdef WITH_USERCOLLIDE
216                 radlog(L_INFO, "User collision code on ... ");
217 #endif
218         } else if (pid == radius_pid) {
219                 radlog(L_INFO, "Reloading configuration files.");
220         }
221
222         /* Read users file etc. */
223         if (res == 0 && read_config_files() != 0)
224                 res = -1;
225
226         if (res != 0) {
227           if (pid == radius_pid) {
228                         radlog(L_ERR|L_CONS,
229                                 "Errors reading config file - EXITING");
230                 }
231                 exit(1);
232         }
233
234         /*
235          *      And parse the server's configuration values.
236          */
237         cs = cf_section_find(NULL);
238         if (!cs)
239                 return;
240
241         cf_section_parse(cs, server_config);
242         /*
243          *      We prefer (in order) the port from the command-line,
244          *      then the port from the configuration file, then
245          *      the port that the system names "radius", then
246          *      1645.
247          */
248         svp = getservbyname ("radius", "udp");
249         if (radius_port) {
250                 auth_port = radius_port;
251         } else {
252                 radius_port = auth_port;
253         }
254
255         if (auth_port == 0) {
256                 if (svp != NULL)
257                         auth_port = ntohs(svp->s_port);
258                 else
259                         auth_port = PW_AUTH_UDP_PORT;
260         }
261                 
262
263         /*
264          *      Go update our behaviour, based on the configuration
265          *      changes.
266          */
267         if (allow_core_dumps) {
268                 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
269                         radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
270                             strerror(errno));
271                         exit(1);
272
273                         /*
274                          *      If we're running as a daemon, and core
275                          *      dumps are enabled, log that information.
276                          */
277                 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
278                   radlog(L_INFO, "Core dumps are enabled.");
279
280         } else if (!debug_flag) {
281                 /*
282                  *      Not debugging.  Set the core size to zero, to
283                  *      prevent security breaches.  i.e. People
284                  *      reading passwords from the 'core' file.
285                  */
286                 struct rlimit limits;
287
288                 limits.rlim_cur = 0;
289                 limits.rlim_max = core_limits.rlim_max;
290                 
291                 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
292                         radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
293                             strerror(errno));
294                         exit(1);
295                 }
296         }
297
298         /*
299          *      Parse the server's proxy configuration values.
300          */
301         if (proxy_requests) {
302                 cs = cf_section_find("proxy");
303                 if (!cs)
304                         return;
305                 
306                 cf_section_parse(cs, proxy_config);
307         }
308 }
309
310 /*
311  *      Parse a string into a syslog facility level.
312  */
313 static int str2fac(const char *s)
314 {
315 #ifdef LOG_KERN
316         if(!strcmp(s, "kern"))
317                 return LOG_KERN;
318         else
319 #endif
320 #ifdef LOG_USER
321         if(!strcmp(s, "user"))
322                 return LOG_USER;
323         else
324 #endif
325 #ifdef LOG_MAIL
326         if(!strcmp(s, "mail"))
327                 return LOG_MAIL;
328         else
329 #endif
330 #ifdef LOG_DAEMON
331         if(!strcmp(s, "daemon"))
332                 return LOG_DAEMON;
333         else
334 #endif
335 #ifdef LOG_AUTH
336         if(!strcmp(s, "auth"))
337                 return LOG_AUTH;
338         else
339 #endif
340 #ifdef LOG_SYSLOG
341         if(!strcmp(s, "auth"))
342                 return LOG_AUTH;
343         else
344 #endif
345 #ifdef LOG_LPR
346         if(!strcmp(s, "lpr"))
347                 return LOG_LPR;
348         else
349 #endif
350 #ifdef LOG_NEWS
351         if(!strcmp(s, "news"))
352                 return LOG_NEWS;
353         else
354 #endif
355 #ifdef LOG_UUCP
356         if(!strcmp(s, "uucp"))
357                 return LOG_UUCP;
358         else
359 #endif
360 #ifdef LOG_CRON
361         if(!strcmp(s, "cron"))
362                 return LOG_CRON;
363         else
364 #endif
365 #ifdef LOG_AUTHPRIV
366         if(!strcmp(s, "authpriv"))
367                 return LOG_AUTHPRIV;
368         else
369 #endif
370 #ifdef LOG_FTP
371         if(!strcmp(s, "ftp"))
372                 return LOG_FTP;
373         else
374 #endif
375 #ifdef LOG_LOCAL0
376         if(!strcmp(s, "local0"))
377                 return LOG_LOCAL0;
378         else
379 #endif
380 #ifdef LOG_LOCAL1
381         if(!strcmp(s, "local1"))
382                 return LOG_LOCAL1;
383         else
384 #endif
385 #ifdef LOG_LOCAL2
386         if(!strcmp(s, "local2"))
387                 return LOG_LOCAL2;
388         else
389 #endif
390 #ifdef LOG_LOCAL3
391         if(!strcmp(s, "local3"))
392                 return LOG_LOCAL3;
393         else
394 #endif
395 #ifdef LOG_LOCAL4
396         if(!strcmp(s, "local4"))
397                 return LOG_LOCAL4;
398         else
399 #endif
400 #ifdef LOG_LOCAL5
401         if(!strcmp(s, "local5"))
402                 return LOG_LOCAL5;
403         else
404 #endif
405 #ifdef LOG_LOCAL6
406         if(!strcmp(s, "local6"))
407                 return LOG_LOCAL6;
408         else
409 #endif
410 #ifdef LOG_LOCAL7
411         if(!strcmp(s, "local7"))
412                 return LOG_LOCAL7;
413         else
414 #endif
415         {
416                 fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
417                         progname, s);
418                 exit(1);
419         }
420         
421         /* this should never be reached */
422         return LOG_DAEMON;
423 }
424
425 int main(int argc, char **argv)
426 {
427         REQUEST                 *request;
428         RADIUS_PACKET           *packet;
429         u_char                  *secret;
430         unsigned char           buffer[4096];
431         struct  sockaddr        salocal;
432         struct  sockaddr_in     *sa;
433         fd_set                  readfds;
434         struct timeval          tv;
435         int                     result;
436         int                     argval;
437         int                     t;
438         int                     pid;
439         int                     i;
440         int                     fd = 0;
441         int                     devnull;
442         int                     status;
443         int                     syslog_facility = LOG_DAEMON;
444  
445 #ifdef OSFC2
446         set_auth_parameters(argc,argv);
447 #endif
448
449         /*
450          *      Open /dev/null, and make sure filedescriptors
451          *      0, 1 and 2 are connected to something.
452          */
453         devnull = 0;
454         while (devnull >= 0 && devnull < 3)
455                 devnull = open("/dev/null", O_RDWR);
456
457         if ((progname = strrchr(argv[0], '/')) == NULL)
458                 progname = argv[0];
459         else
460                 progname++;
461
462         debug_flag = 0;
463         spawn_flag = TRUE;
464         radius_dir = strdup(RADIUS_DIR);
465
466         signal(SIGHUP, sig_hup);
467         signal(SIGINT, sig_fatal);
468         signal(SIGQUIT, sig_fatal);
469 #if WITH_SNMP
470         signal(SIGPIPE, SIG_IGN);
471 #endif
472 #ifdef SIGTRAP
473         signal(SIGTRAP, sig_fatal);
474 #endif
475 #ifdef SIGIOT
476         signal(SIGIOT, sig_fatal);
477 #endif
478
479         /*
480          *      Pooled threads and child threads define their own
481          *      signal handler.
482          */
483 #ifndef WITH_THREAD_POOL
484 #ifndef HAVE_PTHREAD_H
485         signal(SIGTERM, sig_fatal);
486 #endif
487 #endif
488         signal(SIGCHLD, sig_cleanup);
489 #if 0
490         signal(SIGFPE, sig_fatal);
491         signal(SIGSEGV, sig_fatal);
492         signal(SIGILL, sig_fatal);
493 #endif
494
495         /*
496          *      Close unused file descriptors.
497          */
498         for (t = 32; t >= 3; t--)
499             if(t!=devnull) close(t);
500
501         /*
502          *      Process the options.
503          */
504         while((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:p:sSvxXyz")) != EOF) {
505
506                 switch(argval) {
507
508                 case 'A':
509                         log_auth_detail = TRUE;
510                         break;
511
512                 case 'a':
513                         if (radacct_dir) free(radacct_dir);
514                         radacct_dir = strdup(optarg);
515                         break;
516                 
517 #if defined(WITH_DBM) || defined(WITH_NDBM)
518                 case 'b':
519                         use_dbm++;
520                         break;
521 #endif
522                 case 'c':
523                         /* ignore for backwards compatibility with Cistron */
524                         break;
525
526                 case 'd':
527                         if (radius_dir) free(radius_dir);
528                         radius_dir = strdup(optarg);
529                         break;
530                 
531                 case 'f':
532                         dont_fork = TRUE;
533                         break;
534
535                 case 'h':
536                         usage();
537                         break;
538
539                 case 'i':
540                         if ((myip = ip_getaddr(optarg)) == INADDR_NONE) {
541                                 fprintf(stderr, "radiusd: %s: host unknown\n",
542                                         optarg);
543                                 exit(1);
544                         }
545                         break;
546                 
547                 case 'l':
548                         if (radlog_dir) free(radlog_dir);
549                         radlog_dir = strdup(optarg);
550                         break;
551                 
552                         /*
553                          *      We should also have this as a configuration
554                          *      file directive.
555                          */
556                 case 'g':
557                         syslog_facility = str2fac(optarg);
558                         break;
559
560                 case 'S':
561                         log_stripped_names++;
562                         break;
563
564                 case 'p':
565                         radius_port = atoi(optarg);
566                         break;
567
568                 case 's':       /* Single process mode */
569                         spawn_flag = FALSE;
570                         break;
571
572                 case 'v':
573                         version();
574                         break;
575
576                         /*
577                          *  BIG debugging mode for users who are
578                          *  TOO LAZY to type '-sfxxyz -l stdout' themselves.
579                          */
580                 case 'X':
581                         spawn_flag = FALSE;
582                         dont_fork = TRUE;
583                         debug_flag = 2;
584                         librad_debug = 2;
585                         log_auth = TRUE;
586                         log_auth_pass = TRUE;
587                         radlog_dir = strdup("stdout");
588                         break;
589
590                 case 'x':
591                         debug_flag++;
592                         librad_debug++;
593                         break;
594                 
595                 case 'y':
596                         log_auth = TRUE;
597                         break;
598
599                 case 'z':
600                         log_auth_pass = TRUE;
601                         break;
602
603                 default:
604                         usage();
605                         break;
606                 }
607         }
608
609         /*
610          *      Get out PID: the configuration file reader uses it.
611          */
612         radius_pid = getpid();
613
614         /*
615          *      Get the current maximum for core files.
616          */
617         if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
618                 radlog(L_ERR|L_CONS, "Failed to get current core limit:"
619                     "  %s", strerror(errno));
620                 exit(1);
621         }
622
623         /*
624          *      Read the configuration files, BEFORE doing anything else.
625          */
626         reread_config(0);
627
628 #if HAVE_SYSLOG_H
629         /*
630          *      If they asked for syslog, then give it to them.
631          *      Also, initialize the logging facility with the
632          *      configuration that they asked for.
633          */
634         if (!strcmp(radlog_dir, "syslog")) {
635                 openlog(progname, LOG_PID, syslog_facility);
636         }
637         /* Do you want a warning if -g is used without a -l to activate it? */
638 #endif
639
640         /*
641          *      Initialize the request_list[] array.
642          */
643         for (i = 0; i < 256; i++) {
644           request_list[i].first_request = NULL;
645           request_list[i].request_count = 0;
646           request_list[i].service_time = 0;
647         }
648
649         /*
650          *      Open Authentication socket.
651          *
652          */
653         authfd = socket (AF_INET, SOCK_DGRAM, 0);
654         if (authfd < 0) {
655                 perror("auth socket");
656                 exit(1);
657         }
658
659         sa = (struct sockaddr_in *) & salocal;
660         memset ((char *) sa, '\0', sizeof (salocal));
661         sa->sin_family = AF_INET;
662         sa->sin_addr.s_addr = myip;
663         sa->sin_port = htons(auth_port);
664
665         result = bind (authfd, & salocal, sizeof (*sa));
666         if (result < 0) {
667                 perror ("auth bind");
668                 exit(1);
669         }
670
671         /*
672          *      Open Accounting Socket.
673          *
674          *      We prefer (in order) the authentication port + 1,
675          *      then the port that the system names "radacct".
676          */
677         svp = getservbyname ("radacct", "udp");
678         if (radius_port || svp == NULL)
679                 acct_port = auth_port + 1;
680         else
681                 acct_port = ntohs(svp->s_port);
682         
683         acctfd = socket (AF_INET, SOCK_DGRAM, 0);
684         if (acctfd < 0) {
685                 perror ("acct socket");
686                 exit(1);
687         }
688
689         sa = (struct sockaddr_in *) & salocal;
690         memset ((char *) sa, '\0', sizeof (salocal));
691         sa->sin_family = AF_INET;
692         sa->sin_addr.s_addr = myip;
693         sa->sin_port = htons(acct_port);
694
695         result = bind (acctfd, & salocal, sizeof (*sa));
696         if (result < 0) {
697                 perror ("acct bind");
698                 exit(1);
699         }
700
701         /*
702          *      If we're proxying requests, open the proxy FD.
703          *      Otherwise, don't do anything.
704          */
705         if (proxy_requests) {
706                 /*
707                  *      Open Proxy Socket.
708                  */
709                 proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
710                 if (proxyfd < 0) {
711                         perror ("proxy socket");
712                         exit(1);
713                 }
714                 
715                 sa = (struct sockaddr_in *) & salocal;
716                 memset ((char *) sa, '\0', sizeof (salocal));
717                 sa->sin_family = AF_INET;
718                 sa->sin_addr.s_addr = myip;
719                 
720                 /*
721                  *      Set the proxy port to be one more than the
722                  *      accounting port.
723                  */
724                 for (proxy_port = acct_port + 1; proxy_port < 64000; proxy_port++) {
725                         sa->sin_port = htons(proxy_port);
726                         result = bind (proxyfd, & salocal, sizeof (*sa));
727                         if (result == 0) {
728                                 break;
729                         }
730                 }
731                 
732                 /*
733                  *      Couldn't find a port to which we could bind.
734                  */
735                 if (proxy_port == 64000) {
736                         perror("proxy bind");
737                         exit(1);
738                 }
739
740         } else {
741                 /*
742                  *      NOT proxying requests, set the FD to a bad value.
743                  */
744                 proxyfd = -1;
745                 proxy_port = 0;
746         }
747
748         /*
749          *      Register built-in compare functions.
750          */
751         pair_builtincompare_init();
752
753 #if WITH_SNMP
754         radius_snmp_init();
755 #endif
756
757 #if 0
758         /*
759          *      Connect 0, 1 and 2 to /dev/null.
760          */
761         if (!debug_flag && devnull >= 0) {
762                 dup2(devnull, 0);
763                 if (strcmp(radlog_dir, "stdout") != 0) {
764                   dup2(devnull, 1);
765                 }
766                 dup2(devnull, 2);
767                 if (devnull > 2) close(devnull);
768         }
769 #endif
770
771         /*
772          *      Disconnect from session
773          */
774         if (debug_flag == 0 && dont_fork == 0) {
775                 pid = fork();
776                 if(pid < 0) {
777                         radlog(L_ERR|L_CONS, "Couldn't fork");
778                         exit(1);
779                 }
780
781                 /*
782                  *  The parent exits, so the child can run in the background.
783                  */
784                 if(pid > 0) {
785                         exit(0);
786                 }
787 #if HAVE_SETSID
788                 setsid();
789 #endif
790         }
791
792         /*
793          *      Ensure that we're using the CORRECT pid after forking,
794          *      NOT the one we started with.
795          */
796         radius_pid = getpid();
797
798 #ifdef RADIUS_PID
799         /*
800          *      Only write the PID file if we're running as a daemon.
801          *
802          *      And write it AFTER we've forked, so that we write the
803          *      correct PID.
804          */
805         if (dont_fork == FALSE) {
806                 FILE *fp;
807
808                 fp = fopen(pid_file, "w");
809                 if (fp != NULL) {
810                         fprintf(fp, "%d\n", (int) radius_pid);
811                         fclose(fp);
812                 } else {
813                         radlog(L_ERR|L_CONS, "Failed writing process id to file %s: %s\n",
814                             pid_file, strerror(errno));
815                 }
816         }
817 #endif
818
819 #if WITH_THREAD_POOL
820         /*
821          *      If we're spawning children, set up the thread pool.
822          */
823         if (spawn_flag) {
824                 thread_pool_init();
825         }
826 #endif
827
828         /*
829          *      Use linebuffered or unbuffered stdout if
830          *      the debug flag is on.
831          */
832         if (debug_flag) setlinebuf(stdout);
833
834         if (myip == 0) {
835                 strcpy((char *)buffer, "*");
836         } else {
837                 ip_ntoa((char *)buffer, myip);
838         }
839
840         if (proxy_requests) {
841                 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp, with proxy on %d/udp.",
842                     buffer, auth_port, acct_port, proxy_port);
843         } else {
844                 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp.",
845                     buffer, auth_port, acct_port);
846         }
847
848         /*
849          *      Note that we NO LONGER fork an accounting process!
850          *      We used to do it for historical reasons, but that
851          *      is no excuse...
852          */
853         radlog(L_INFO, "Ready to process requests.");
854
855         /*
856          *      Receive user requests
857          */
858         for(;;) {
859                 time_t now;
860
861                 if (need_reload) {
862                         reread_config(TRUE);
863                         need_reload = FALSE;
864                 }
865
866                 FD_ZERO(&readfds);
867                 if (authfd >= 0)
868                         FD_SET(authfd, &readfds);
869                 if (acctfd >= 0)
870                         FD_SET(acctfd, &readfds);
871                 if (proxyfd >= 0)
872                         FD_SET(proxyfd, &readfds);
873 #ifdef WITH_SNMP
874                 if (smuxfd >= 0)
875                         FD_SET(smuxfd, &readfds);
876 #endif
877
878                 status = select(32, &readfds, NULL, NULL,
879                                 setuptimeout(&tv));
880                 now = time(NULL);
881                 if (status == -1) {
882                         /*
883                          *      On interrupts, we clean up the
884                          *      request list.
885                          */
886                         if (errno == EINTR) {
887                                 rad_clean_list(now);
888                                 continue;
889                         }
890                         radlog(L_ERR, "Unexpected error in select(): %s",
891                             strerror(errno));
892                         sig_fatal(101);
893                 }
894
895                 /*
896                  *      When receiving a packet, or timeout,
897                  *      service the proxy request list.
898                  */
899                 if ((status == 0) && proxy_requests) {
900                         proxy_retry();
901                 }
902
903                 for (i = 0; i < 3; i++) {
904
905                         if (i == 0) fd = authfd;
906                         if (i == 1) fd = acctfd;
907                         if (i == 2) fd = proxyfd;
908                         if (fd < 0 || !FD_ISSET(fd, &readfds))
909                                 continue;
910                         /*
911                          *      Receive the packet.
912                          */
913                         packet = rad_recv(fd);
914                         if (packet == NULL) {
915                                 radlog(L_ERR, "%s", librad_errstr);
916                                 continue;
917                         }
918 #if WITH_SNMP
919                         if (fd == acctfd)
920                                 snmp_acctotalrequests++;
921                         if (fd == authfd)
922                                 snmp_authtotalrequests++;
923 #endif
924
925                         /*
926                          *      Check if we know this client for authfd and acctfd.
927                          *      Check if we know this proxy for proxyfd.
928                          */
929                         if(fd != proxyfd) {
930                                 RADCLIENT    *cl;
931                                 if ((cl = client_find(packet->src_ipaddr)) == NULL) {
932                                       radlog(L_ERR, "Ignoring request from unknown client %s:%d",
933                                       buffer, packet->src_port);
934                                       rad_free(packet);
935                                       continue;
936                                 } else {
937                                       secret = cl->secret;
938                                 }
939                                 
940                         } else {    /* It came in on the proxy port */
941                                 REALM         *rl;
942                                 if ((rl = realm_findbyaddr(packet->src_ipaddr)) == NULL) {
943                                       radlog(L_ERR, "Ignoring request from unknown proxy %s:%d",
944                                       buffer, packet->src_port);
945                                       rad_free(packet);
946                                       continue;
947                                 } else {
948                                       secret = rl->secret;
949                                 }
950                         }      
951
952                         /*
953                          *      Do yet another check, to see if the
954                          *      packet code is valid.  We only understand
955                          *      a few, so stripping off obviously invalid
956                          *      packets here will make our life easier.
957                          */
958                         if (packet->code > PW_ACCESS_CHALLENGE) {
959                                 radlog(L_ERR, "Ignoring request from client %s:%d with unknown code %d", buffer, packet->src_port, packet->code);
960                                 rad_free(packet);
961                                 continue;
962                         }
963
964                         if ((request = malloc(sizeof(REQUEST))) == NULL) {
965                                 radlog(L_ERR|L_CONS, "no memory");
966                                 exit(1);
967                         }
968                         memset(request, 0, sizeof(REQUEST));
969 #ifndef NDEBUG
970                         request->magic = REQUEST_MAGIC;
971 #endif
972                         request->packet = packet;
973                         request->proxy = NULL;
974                         request->reply = NULL;
975                         request->proxy_reply = NULL;
976                         request->config_items = NULL;
977                         request->username = NULL;
978                         request->password = NULL;
979                         request->timestamp = now;
980                         request->child_pid = NO_SUCH_CHILD_PID;
981                         request->prev = NULL;
982                         request->next = NULL;
983                         strNcpy(request->secret, secret, sizeof(request->secret));
984                         rad_process(request, spawn_flag);
985                 } /* loop over authfd, acctfd, proxyfd */
986
987                 /*
988                  *      After processing all new requests,
989                  *      check if we've got to delete old requests
990                  *      from the request list.
991                  */
992                 rad_clean_list(now);
993 #if WITH_SNMP
994                 /*
995                  *      After handling all authentication/accounting
996                  *      requests, THEN process any pending SMUX/SNMP
997                  *      queries.
998                  *
999                  *      Note that the handling is done in the main server,
1000                  *      which probably isn't a Good Thing.  It really
1001                  *      should be wrapped, and handled in a thread pool.
1002                  */
1003                 if ((smuxfd >= 0) &&
1004                     FD_ISSET(smuxfd, &readfds) &&
1005                     (smux_event == SMUX_READ)) {
1006                   smux_read();
1007                 }
1008                 
1009                 /*
1010                  *      If we've got to re-connect, then do so now,
1011                  *      before calling select again.
1012                  */
1013                 if (smux_event == SMUX_CONNECT) {
1014                   smux_connect();
1015                 }
1016 #endif
1017         } /* loop forever */
1018 }
1019
1020
1021 /*
1022  *      Process supported requests:
1023  *
1024  *              PW_AUTHENTICATION_REQUEST - Authentication request from
1025  *                              a client network access server.
1026  *
1027  *              PW_ACCOUNTING_REQUEST - Accounting request from
1028  *                              a client network access server.
1029  *
1030  *              PW_AUTHENTICATION_ACK
1031  *              PW_AUTHENTICATION_REJECT
1032  *              PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
1033  *                              Relay reply back to original NAS.
1034  *
1035  */
1036 int rad_process(REQUEST *request, int dospawn)
1037 {
1038         RAD_REQUEST_FUNP fun;
1039
1040         fun = NULL;
1041
1042         assert(request->magic == REQUEST_MAGIC);
1043
1044         switch(request->packet->code) {
1045
1046         case PW_AUTHENTICATION_REQUEST:
1047                 /*
1048                  *      Check for requests sent to the wrong port,
1049                  *      and ignore them, if so.
1050                  */
1051                 if (request->packet->sockfd != authfd) {
1052                   radlog(L_ERR, "Request packet code %d sent to authentication port from "
1053                       "client %s:%d - ID %d : IGNORED",
1054                       request->packet->code,
1055                       client_name(request->packet->src_ipaddr),
1056                       request->packet->src_port,
1057                       request->packet->id);
1058                   request_free(request);
1059                   return -1;
1060                 }
1061                 break;
1062
1063         case PW_ACCOUNTING_REQUEST:
1064                 /*
1065                  *      Check for requests sent to the wrong port,
1066                  *      and ignore them, if so.
1067                  */
1068                 if (request->packet->sockfd != acctfd) {
1069                   radlog(L_ERR, "Request packet code %d sent to accounting port from "
1070                       "client %s:%d - ID %d : IGNORED",
1071                       request->packet->code,
1072                       client_name(request->packet->src_ipaddr),
1073                       request->packet->src_port,
1074                       request->packet->id);
1075                   request_free(request);
1076                   return -1;
1077                 }
1078                 break;
1079
1080         case PW_AUTHENTICATION_ACK:
1081         case PW_AUTHENTICATION_REJECT:
1082         case PW_ACCOUNTING_RESPONSE:
1083                 /*
1084                  *      Replies NOT sent to the proxy port get an
1085                  *      error message logged, and the packet is
1086                  *      dropped.
1087                  */
1088                 if (request->packet->sockfd != proxyfd) {
1089                         radlog(L_ERR, "Reply packet code %d sent to request port from "
1090                             "client %s:%d - ID %d : IGNORED",
1091                             request->packet->code,
1092                             client_name(request->packet->src_ipaddr),
1093                             request->packet->src_port,
1094                             request->packet->id);
1095                         request_free(request);
1096                         return -1;
1097                 }
1098                 break;
1099         }
1100
1101         assert(request->magic == REQUEST_MAGIC);
1102
1103         /*
1104          *      Select the required function and indicate if
1105          *      we need to fork off a child to handle it.
1106          */
1107         switch(request->packet->code) {
1108
1109         case PW_AUTHENTICATION_ACK:
1110         case PW_AUTHENTICATION_REJECT:
1111         case PW_AUTHENTICATION_REQUEST:
1112                 fun = rad_authenticate;
1113                 break;
1114         
1115         case PW_ACCOUNTING_RESPONSE:
1116         case PW_ACCOUNTING_REQUEST:
1117                 fun = rad_accounting;
1118                 break;
1119         
1120         case PW_PASSWORD_REQUEST:
1121                 /*
1122                  *      We don't support this anymore.
1123                  */
1124                 radlog(L_ERR, "Deprecated password change request from client %s:%d "
1125                     "- ID %d : IGNORED",
1126                     client_name(request->packet->src_ipaddr),
1127                     request->packet->src_port,
1128                     request->packet->id);
1129                 request_free(request);
1130                 return -1;
1131                 break;
1132         
1133         default:
1134                 radlog(L_ERR, "Unknown packet type %d from client %s:%d "
1135                     "- ID %d : IGNORED",
1136                     request->packet->code,
1137                     client_name(request->packet->src_ipaddr),
1138                     request->packet->src_port,
1139                     request->packet->id);
1140                 request_free(request);
1141                 return -1;
1142                 break;
1143         }
1144
1145         /*
1146          *      If we did NOT select a function, then exit immediately.
1147          */
1148         if (!fun) {
1149                 request_free(request);
1150                 return 0;
1151         }
1152
1153         /*
1154          *      Check for a duplicate, or error.
1155          *      Throw away the the request if so.
1156          */
1157         request = rad_check_list(request);
1158         if (request == NULL) {
1159                 return 0;
1160         }
1161         
1162         assert(request->magic == REQUEST_MAGIC);
1163
1164         /*
1165          *      The request passes many of our sanity checks.  From
1166          *      here on in, if anything goes wrong, we send a reject
1167          *      message, instead of dropping the packet.
1168          *
1169          *      Build the reply template from the request template.
1170          */
1171         if ((request->reply = rad_alloc(0)) == NULL) {
1172                 fprintf(stderr, "out of memory\n");
1173                 exit(1);
1174         }
1175         request->reply->sockfd     = request->packet->sockfd;
1176         request->reply->dst_ipaddr = request->packet->src_ipaddr;
1177         request->reply->dst_port   = request->packet->src_port;
1178         request->reply->id         = request->packet->id;
1179         request->reply->code       = 0; /* UNKNOWN code */
1180         memcpy(request->reply->vector, request->packet->vector,
1181                sizeof(request->reply->vector));
1182         request->reply->vps = NULL;
1183         request->reply->data = NULL;
1184         
1185         /*
1186          *      If we're spawning a child thread, let it do all of
1187          *      the work of handling a request, and exit.
1188          */
1189         if (dospawn) {
1190                 /*
1191                  *      Maybe the spawn failed.  If so, then we
1192                  *      trivially reject the request (because we can't
1193                  *      handle it), and return.
1194                  */
1195                 if (rad_spawn_child(request, fun) < 0) {
1196                         rad_reject(request);
1197                         request->finished = TRUE;
1198                 }
1199                 return 0;
1200         }
1201
1202         rad_respond(request, fun);
1203         return 0;
1204 }
1205
1206 /*
1207  *      Reject a request, by sending a trivial reply packet.
1208  */
1209 static void rad_reject(REQUEST *request)
1210 {
1211         DEBUG2("Server rejecting request.");
1212         switch (request->packet->code) {
1213                 /*
1214                  *      Accounting requests, etc. get dropped on the floor.
1215                  */
1216         case PW_ACCOUNTING_REQUEST:
1217         default:
1218                 break;
1219
1220                 /*
1221                  *      Authentication requests get their Proxy-State
1222                  *      attributes copied over, and an otherwise blank
1223                  *      reject message sent.
1224                  */
1225         case PW_AUTHENTICATION_REQUEST:
1226                 request->reply->code = PW_AUTHENTICATION_REJECT;
1227                 break;
1228         }
1229         
1230         /*
1231          *      If a reply exists, send it.
1232          */
1233         if (request->reply->code) {
1234                 rad_send(request->reply, request->secret);
1235         }
1236 }
1237
1238 /*
1239  *      Respond to a request packet.
1240  *
1241  *      Maybe we reply, maybe we don't.
1242  *      Maybe we proxy the request to another server, or else maybe
1243  *      we replicate it to another server.
1244  */
1245 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
1246 {
1247         RADIUS_PACKET   *packet, *original;
1248         const char      *secret;
1249         int             finished = FALSE;
1250         int             proxy_sent = 0;
1251         
1252         /*
1253          *      Put the decoded packet into it's proper place.
1254          */
1255         if (request->proxy_reply != NULL) {
1256                 packet = request->proxy_reply;
1257                 secret = request->proxysecret;
1258                 original = request->proxy;
1259         } else {
1260                 packet = request->packet;
1261                 secret = request->secret;
1262                 original = NULL;
1263         }
1264
1265         assert(request->magic == REQUEST_MAGIC);
1266         
1267         /*
1268          *      Decode the packet, verifying it's signature,
1269          *      and parsing the attributes into structures.
1270          *
1271          *      Note that we do this CPU-intensive work in
1272          *      a child thread, not the master.  This helps to
1273          *      spread the load a little bit.
1274          */
1275         if (rad_decode(packet, original, secret) != 0) {
1276                 radlog(L_ERR, "%s", librad_errstr);
1277                 rad_reject(request);
1278                 goto finished_request;
1279         }
1280         
1281         /*
1282          *      For proxy replies, remove non-allowed
1283          *      attributes from the list of VP's.
1284          */
1285         if (request->proxy) {
1286                 int replicating;
1287                 replicating = proxy_receive(request);
1288                 if (replicating != 0) {
1289                         goto next_request;
1290                 }
1291         }
1292         
1293         /*
1294          *      We should have a User-Name attribute now.
1295          */
1296         if (request->username == NULL) {
1297                 request->username = pairfind(request->packet->vps,
1298                                              PW_USER_NAME);
1299         }
1300
1301         /*
1302          *      We have the semaphore, and have decoded the packet.
1303          *      Let's process the request.
1304          */
1305         assert(request->magic == REQUEST_MAGIC);
1306         (*fun)(request);
1307         
1308         /*
1309          *      If we don't already have a proxy
1310          *      packet for this request, we MIGHT have
1311          *      to go proxy it.
1312          */
1313         if (proxy_requests) {
1314                 if (request->proxy == NULL) {
1315                         proxy_sent = proxy_send(request);
1316                         
1317                         /*
1318                          *      sent==1 means it's been proxied.  The child
1319                          *      is done handling the request, but the request
1320                          *      is NOT finished!
1321                          */
1322                         if (proxy_sent == 1) {
1323                                 goto postpone_request;
1324                         }
1325                 }
1326         } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1327                    (request->reply == NULL)) {
1328                 /*
1329                  *      We're not configured to reply to the packet,
1330                  *      and we're not proxying, so the DEFAULT behaviour
1331                  *      is to REJECT the user.
1332                  */
1333                 DEBUG2("There was no response configured: rejecting the user.");
1334                 rad_reject(request);
1335                 goto finished_request;
1336         }
1337
1338         /*
1339          *      If we have a reply to send, copy the Proxy-State
1340          *      attributes from the request to the tail of the reply,
1341          *      and send the packet.
1342          */
1343         assert(request->magic == REQUEST_MAGIC);
1344         if (request->reply->code != 0) {
1345                 VALUE_PAIR *vp;
1346
1347                 /*
1348                  *      Need to copy Proxy-State from request->packet->vps
1349                  */
1350                 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1351                 if (vp != NULL)
1352                         pairadd(&(request->reply->vps), vp);
1353
1354                 rad_send(request->reply, request->secret);
1355         }
1356
1357         /*
1358          *      We're done processing the request, set the
1359          *      request to be finished, clean up as necessary,
1360          *      and forget about the request.
1361          */
1362  finished_request:
1363         /*
1364          *      We're done handling the request.  Free up the linked
1365          *      lists of value pairs.  This might take a long time,
1366          *      so it's more efficient to do it in a child thread,
1367          *      instead of in the main handler when it eventually
1368          *      gets around to deleting the request.
1369          *
1370          *      Also, no one should be using these items after the
1371          *      request is finished, and the reply is sent.  Cleaning
1372          *      them up here ensures that they're not being used again.
1373          *
1374          *      Hmm... cleaning them up in the child thread also seems
1375          *      to make the server run more efficiently!
1376          */
1377
1378         /*      If we proxied this request, it's not safe to delete it until
1379          *      after the proxy reply
1380          */
1381         if (proxy_sent)
1382                 goto postpone_request;
1383
1384         if (request->packet && request->packet->vps) {
1385                 pairfree(request->packet->vps);
1386                 request->packet->vps = NULL;
1387                 request->username = NULL;
1388                 request->password = NULL;
1389         }
1390         if (request->reply && request->reply->vps) {
1391                 pairfree(request->reply->vps);
1392                 request->reply->vps = NULL;
1393         }
1394         if (request->config_items) {
1395                 pairfree(request->config_items);
1396                 request->config_items = NULL;
1397         }
1398
1399         DEBUG2("Finished request");
1400         finished = TRUE;
1401         
1402         /*
1403          *      Go to the next request, without marking
1404          *      the current one as finished.
1405          */
1406  next_request:
1407         DEBUG2("Going to the next request");
1408
1409         /*
1410          *      If this is an accounting request, ensure
1411          *      that we delete it immediately, as there CANNOT be
1412          *      duplicate accounting packets.  If there are, then
1413          *      something else is seriously wrong...
1414          */
1415         if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1416                 request->timestamp = 0;
1417         }
1418
1419 #if WITH_THREAD_POOL
1420         request->child_pid = NO_SUCH_CHILD_PID;
1421 #endif
1422         request->finished = finished; /* do as the LAST thing before exiting */
1423
1424  postpone_request:
1425         return 0;
1426 }
1427
1428 /*
1429  *      Clean up the request list, every so often.
1430  *
1431  *      This is done by walking through ALL of the list, and
1432  *      - joining any child threads which have exited.  (If not pooling)
1433  *      - killing any processes which are NOT finished after a delay
1434  *      - deleting any requests which are finished, and expired
1435  */
1436 static int rad_clean_list(time_t curtime)
1437 {
1438         static time_t   last_cleaned_list = 0;
1439         REQUEST         *curreq;
1440         REQUEST         *prevreq;
1441         child_pid_t     child_pid;
1442         int             id;
1443         int             request_count;
1444         int             cleaned = FALSE;
1445
1446         /*
1447          *  Don't bother checking the list if we've done it
1448          *  within the last second.
1449          */
1450         if ((curtime - last_cleaned_list) == 0) {
1451                 return FALSE;
1452         }
1453
1454 #if WITH_THREAD_POOL
1455         /*
1456          *      Only clean the thread pool if we've spawned child threads.
1457          */
1458         if (spawn_flag) {
1459                 thread_pool_clean();
1460         }
1461 #endif
1462
1463         /*
1464          *      When mucking around with the request list, we block
1465          *      asynchronous access (through the SIGCHLD handler) to
1466          *      the list - equivalent to sigblock(SIGCHLD).
1467          */
1468         request_list_busy = TRUE;
1469                 
1470         for (id = 0; id < 256; id++) {
1471                 curreq = request_list[id].first_request;
1472                 prevreq = NULL;
1473
1474                 while (curreq != NULL) {
1475                         assert(curreq->magic == REQUEST_MAGIC);
1476
1477                         /*
1478                          *      Maybe the child process handling the request
1479                          *      has hung: kill it, and continue.
1480                          */
1481                         if (!curreq->finished &&
1482                             (curreq->timestamp + max_request_time) <= curtime) {
1483                                 if (curreq->child_pid != NO_SUCH_CHILD_PID) {
1484                                         /*
1485                                          *      This request seems to have hung
1486                                          *       - kill it
1487                                          */
1488                                         child_pid = curreq->child_pid;
1489                                         radlog(L_ERR, "Killing unresponsive child %d",
1490                                             child_pid);
1491                                         child_kill(child_pid, SIGTERM);
1492                                 } /* else no proxy reply, quietly fail */
1493
1494                                 /*
1495                                  *      Mark the request as unsalvagable.
1496                                  */
1497                                 curreq->child_pid = NO_SUCH_CHILD_PID;
1498                                 curreq->finished = TRUE;
1499                                 curreq->timestamp = 0;
1500                         }
1501
1502                         /*
1503                          *      Delete the current request, if it's
1504                          *      marked as such.  That is, the request
1505                          *      must be finished, there must be no
1506                          *      child associated with that request,
1507                          *      and it's timestamp must be marked to
1508                          *      be deleted.
1509                          */
1510                         if (curreq->finished &&
1511                             (curreq->child_pid == NO_SUCH_CHILD_PID) &&
1512                             (curreq->timestamp + cleanup_delay <= curtime)) {
1513                                 /*
1514                                  *      Request completed, delete it,
1515                                  *      and unlink it from the
1516                                  *      currently 'alive' list of
1517                                  *      requests.
1518                                  */
1519                                 DEBUG2("Cleaning up request ID %d with timestamp %08lx",
1520                                        curreq->packet->id,
1521                                        (unsigned long)curreq->timestamp);
1522                                 prevreq = curreq->prev;
1523                                 if (request_list[id].request_count == 0) {
1524                                   DEBUG("HORRIBLE ERROR!!!");
1525                                 } else {
1526                                   request_list[id].request_count--;
1527                                   cleaned = TRUE;
1528                                 }
1529
1530                                 if (prevreq == NULL) {
1531                                         request_list[id].first_request = curreq->next;
1532                                         request_free(curreq);
1533                                         curreq = request_list[id].first_request;
1534                                 } else {
1535                                         prevreq->next = curreq->next;
1536                                         request_free(curreq);
1537                                         curreq = prevreq->next;
1538                                 }
1539                                 if (curreq)
1540                                         curreq->prev = prevreq;
1541                                 
1542                         } else {        /* the request is still alive */
1543                                 prevreq = curreq;
1544                                 curreq = curreq->next;
1545                         }
1546                 } /* end of walking the request list for that ID */
1547         } /* for each entry in the request list array */
1548
1549         request_count = 0;
1550         for (id = 0; id < 256; id++) {
1551                 request_count += request_list[id].request_count;
1552         }
1553
1554         /*
1555          *      Only print this if anything's changed.
1556          */
1557         {
1558                 static int old_request_count = -1;
1559
1560                 if (request_count != old_request_count) {
1561                         DEBUG2("%d requests left in the list", request_count);
1562                         old_request_count = request_count;
1563                 }
1564         }
1565
1566         /*
1567          *      We're done playing with the request list.
1568          */
1569         request_list_busy = FALSE;
1570         last_cleaned_list = curtime;
1571
1572         return cleaned;
1573 }
1574
1575 /*
1576  *      Walk through the request list, cleaning up complete child
1577  *      requests, and verifing that there is only one process
1578  *      responding to each request (duplicate requests are filtered
1579  *      out).
1580  *
1581  *      Also, check if the request is a reply from a request proxied to
1582  *      a remote server.  If so, play games with the request, and return
1583  *      the old one.
1584  */
1585 static REQUEST *rad_check_list(REQUEST *request)
1586 {
1587         REQUEST         *curreq;
1588         REQUEST         *prevreq;
1589         RADIUS_PACKET   *pkt;
1590         int             request_count;
1591         REQUEST_LIST    *request_list_entry;
1592         int             i;
1593         time_t          curtime;
1594         int             id;
1595
1596         /*
1597          *      If the request has come in on the proxy FD, then
1598          *      it's a proxy reply, so pass it through the proxy
1599          *      code for checking the REQUEST_LIST.
1600          */
1601         if (request->packet->sockfd == proxyfd) {
1602                 return proxy_check_list(request);
1603
1604                 /*
1605                  *      If the request already has a proxy packet,
1606                  *      then it obviously is not a new request, either.
1607                  */
1608         } else if (request->proxy != NULL) {
1609                 return request;
1610         }
1611
1612         request_list_entry = &request_list[request->packet->id];
1613
1614         assert((request_list_entry->first_request == NULL) ||
1615                (request_list_entry->request_count != 0));
1616         assert((request_list_entry->first_request != NULL) ||
1617                (request_list_entry->request_count == 0));
1618
1619         curreq = request_list_entry->first_request;
1620         prevreq = NULL;
1621         pkt = request->packet;
1622         request_count = 0;
1623         curtime = request->timestamp; /* good enough for our purposes */
1624         id = pkt->id;
1625
1626         /*
1627          *      When mucking around with the request list, we block
1628          *      asynchronous access (through the SIGCHLD handler) to
1629          *      the list - equivalent to sigblock(SIGCHLD).
1630          */
1631         request_list_busy = TRUE;
1632
1633         while (curreq != NULL) {
1634                 assert(curreq->packet->id == pkt->id);
1635
1636                 /*
1637                  *      Let's see if we received a duplicate of
1638                  *      a packet we already have in our list.
1639                  *
1640                  *      We do this be checking the src IP, (NOT port)
1641                  *      the packet code, and ID.
1642                  */
1643                 if ((curreq->packet->src_ipaddr == pkt->src_ipaddr) &&
1644                     (curreq->packet->code == pkt->code)) {
1645                   /*
1646                    *    We now check the authentication vectors.
1647                    *    If the client has sent us a request with
1648                    *    identical code && ID, but different vector,
1649                    *    then they MUST have gotten our response, so
1650                    *    we can delete the original request, and process
1651                    *    the new one.
1652                    *
1653                    *    If the vectors are the same, then it's a duplicate
1654                    *    request, and we can send a duplicate reply.
1655                    */
1656                   if (memcmp(curreq->packet->vector, pkt->vector,
1657                             sizeof(pkt->vector)) == 0) {
1658                         /*
1659                          *      Maybe we've saved a reply packet.  If so,
1660                          *      re-send it.  Otherwise, just complain.
1661                          */
1662                         if (curreq->reply) {
1663                                 radlog(L_INFO,
1664                                 "Sending duplicate authentication reply"
1665                                 " to client %s:%d - ID: %d",
1666                                 client_name(request->packet->src_ipaddr),
1667                                 request->packet->src_port,
1668                                 request->packet->id);
1669
1670                                 /*
1671                                  *      Use the SOURCE port as the DESTINATION
1672                                  *      port of the duplicate reply.
1673                                  */
1674                                 curreq->reply->dst_port = request->packet->src_port;
1675                                 rad_send(curreq->reply, curreq->secret);
1676                                 
1677                                 /*
1678                                  *      There's no reply, but maybe there's
1679                                  *      an outstanding proxy request.
1680                                  *
1681                                  *      If so, then kick the proxy again.
1682                                  */
1683                         } else if (curreq->proxy != NULL) {
1684                                 if (proxy_synchronous) {
1685                                         DEBUG2("Sending duplicate proxy request to client %s:%d - ID: %d",
1686                                                client_name(curreq->proxy->dst_ipaddr),
1687                                                request->packet->src_port,
1688                                                curreq->proxy->id);
1689
1690                                         curreq->proxy_next_try = request->timestamp + proxy_retry_delay;
1691                                         rad_send(curreq->proxy, curreq->proxysecret);
1692                                 } else {
1693                                         DEBUG2("Ignoring duplicate authentication packet"
1694                                                " from client %s:%d - ID: %d, due to outstanding proxy request.",
1695                                                client_name(request->packet->src_ipaddr),
1696                                                request->packet->src_port,
1697                                                request->packet->id);
1698                                 }
1699                         } else {
1700                                 radlog(L_ERR,
1701                                 "Dropping duplicate authentication packet"
1702                                 " from client %s:%d - ID: %d",
1703                                 client_name(request->packet->src_ipaddr),
1704                                 request->packet->src_port,
1705                                 request->packet->id);
1706                         }
1707
1708                         /*
1709                          *      Delete the duplicate request, and
1710                          *      stop processing the request list.
1711                          */
1712                         request_free(request);
1713                         request = NULL;
1714                         break;
1715                   } else {
1716                           /*
1717                            *    The packet vectors are different, so
1718                            *    we can mark the old request to be
1719                            *    deleted from the list.
1720                            *
1721                            *    Note that we don't actually delete it...
1722                            *    Maybe we should?
1723                            */
1724                           if (curreq->finished) {
1725                                   curreq->timestamp = 0;
1726                           } else {
1727                                   /*
1728                                    *    ??? the client sent us a new request
1729                                    *    with the same ID, while we were
1730                                    *    processing the old one!  What should
1731                                    *    we do?
1732                                    */
1733                                 radlog(L_ERR,
1734                                 "Dropping conflicting authentication packet"
1735                                 " from client %s:%d - ID: %d",
1736                                 client_name(request->packet->src_ipaddr),
1737                                 request->packet->src_port,
1738                                 request->packet->id);
1739                                 request_free(request);
1740                                 request = NULL;
1741                                 break;
1742                           }
1743                   }
1744                 }
1745
1746                 /*
1747                  *      Ugh... duplicated code is bad...
1748                  */
1749
1750                 /*
1751                  *      Delete the current request, if it's
1752                  *      marked as such.  That is, the request
1753                  *      must be finished, there must be no
1754                  *      child associated with that request,
1755                  *      and it's timestamp must be marked to
1756                  *      be deleted.
1757                  */
1758                 if (curreq->finished &&
1759                     (curreq->child_pid == NO_SUCH_CHILD_PID) &&
1760                     (curreq->timestamp + cleanup_delay <= curtime)) {
1761                                 /*
1762                                  *      Request completed, delete it,
1763                                  *      and unlink it from the
1764                                  *      currently 'alive' list of
1765                                  *      requests.
1766                                  */
1767                         DEBUG2("Cleaning up request ID %d with timestamp %08lx",
1768                                curreq->packet->id,
1769                                (unsigned long)curreq->timestamp);
1770                         prevreq = curreq->prev;
1771                         if (request_list[id].request_count == 0) {
1772                                 DEBUG("HORRIBLE ERROR!!!");
1773                         } else {
1774                                 request_list[id].request_count--;
1775                         }
1776                         
1777                         if (prevreq == NULL) {
1778                                 request_list[id].first_request = curreq->next;
1779                                 request_free(curreq);
1780                                 curreq = request_list[id].first_request;
1781                         } else {
1782                                 prevreq->next = curreq->next;
1783                                 request_free(curreq);
1784                                 curreq = prevreq->next;
1785                         }
1786                         if (curreq)
1787                                 curreq->prev = prevreq;
1788                         
1789                 } else {        /* the request is still alive */
1790                         prevreq = curreq;
1791                         curreq = curreq->next;
1792                         request_count++;
1793                 }
1794         } /* end of walking the request list */
1795         
1796         /*
1797          *      If we've received a duplicate packet, 'request' is NULL.
1798          */
1799         if (request == NULL) {
1800                 request_list_busy = FALSE;
1801                 return NULL;
1802         }
1803
1804         assert(request_list_entry->request_count == request_count);
1805
1806         /*
1807          *      Count the total number of requests, to see if there
1808          *      are too many.  If so, stop counting immediately,
1809          *      and return with an error.
1810          */
1811         request_count = 0;
1812         for (i = 0; i < 256; i++) {
1813                 request_count += request_list[i].request_count;
1814
1815                 /*
1816                  *      This is a new request.  Let's see if it
1817                  *      makes us go over our configured bounds.
1818                  */
1819                 if (request_count > max_requests) {
1820                         radlog(L_ERR, "Dropping request (%d is too many): "
1821                             "from client %s:%d - ID: %d", request_count, 
1822                             client_name(request->packet->src_ipaddr),
1823                             request->packet->src_port,
1824                             request->packet->id);
1825                         request_free(request);
1826                         request_list_busy = FALSE;
1827                         return NULL;
1828                 }
1829         }
1830
1831         /*
1832          *      Add this request to the list
1833          */
1834         request->prev = prevreq;
1835         request->next = NULL;
1836         request->child_pid = NO_SUCH_CHILD_PID;
1837         request_list_entry->request_count++;
1838
1839         if (prevreq == NULL) {
1840                 assert(request_list_entry->first_request == NULL);
1841                 assert(request_list_entry->request_count == 1);
1842                 request_list_entry->first_request = request;
1843         } else {
1844                 assert(request_list_entry->first_request != NULL);
1845                 prevreq->next = request;
1846         }
1847
1848         /*
1849          *      And return the request to be handled.
1850          */
1851         request_list_busy = FALSE;
1852         return request;
1853 }
1854
1855 #ifndef WITH_THREAD_POOL
1856 #if HAVE_PTHREAD_H
1857 typedef struct spawn_thread_t {
1858   REQUEST *request;
1859   RAD_REQUEST_FUNP fun;
1860 } spawn_thread_t;
1861
1862 /*
1863  *      If the child *thread* gets a termination signal,
1864  *      then exit from the thread.
1865  */
1866 static void sig_term(int sig)
1867 {
1868         sig = sig;                      /* -Wunused */
1869         pthread_exit(NULL);
1870 }
1871
1872 /*
1873  *      Spawn a new child thread to handle this request, and ONLY
1874  *      this request.
1875  */
1876 static void *rad_spawn_thread(void *arg)
1877 {
1878         int replicating;
1879         spawn_thread_t *data = (spawn_thread_t *)arg;
1880         
1881         /*
1882          *      Note that this behaviour only works on Linux.
1883          *
1884          *      It's generally NOT the thing to do, and should
1885          *      be fixed somehow.
1886          *
1887          *      Q: How do we signal a hung thread, and tell it to
1888          *      kill itself?
1889          */
1890         signal(SIGTERM, sig_term);
1891         
1892         /*
1893          *      Keep only allowed attributes in the request.
1894          */
1895         if (data->request->proxy) {
1896                 replicating = proxy_receive(data->request);
1897                 if (replicating != 0) {
1898                         data->request->finished = TRUE;
1899                         free(data);
1900                         return NULL;
1901                 }
1902         }
1903         
1904         rad_respond(data->request, data->fun);
1905         data->request->child_pid = NO_SUCH_CHILD_PID;
1906         free(data);
1907         return NULL;
1908 }
1909 #endif
1910 #endif
1911
1912 /*
1913  *      If we're using the thread pool, then the function in
1914  *      'threads.c' replaces this one.
1915  */
1916 #ifndef WITH_THREAD_POOL
1917 /*
1918  *      Spawns a child process or thread to perform
1919  *      authentication/accounting and respond to RADIUS clients.
1920  */
1921 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
1922 {
1923         child_pid_t             child_pid;
1924
1925 #if HAVE_PTHREAD_H
1926         int rcode;
1927         spawn_thread_t *data;
1928
1929         data = (spawn_thread_t *) malloc(sizeof(spawn_thread_t));
1930         memset(data, 0, sizeof(data));
1931         data->request = request;
1932         data->fun = fun;
1933
1934         /*
1935          *      Create a child thread, complaining on error.
1936          */
1937         rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
1938         if (rcode != 0) {
1939                 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
1940                     nas_name2(request->packet),
1941                     request->packet->id,
1942                     strerror(errno));
1943                 return -1;
1944         }
1945
1946         /*
1947          *      Detach it, so it's state is automagically cleaned up on exit.
1948          */
1949         pthread_detach(child_pid);
1950
1951 #else
1952         /*
1953          *      fork our child
1954          */
1955         child_pid = fork();
1956         if (child_pid < 0) {
1957                 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
1958                                 nas_name2(request->packet),
1959                                 request->packet->id);
1960                 return -1;
1961         }
1962
1963         if (child_pid == 0) {
1964
1965                 /*
1966                  *      This is the child, it should go ahead and respond
1967                  */
1968                 signal(SIGCHLD, SIG_DFL);
1969                 rad_respond(request, fun);
1970                 exit(0);
1971         }
1972 #endif
1973
1974         /*
1975          *      Register the Child
1976          */
1977         request->child_pid = child_pid;
1978         return 0;
1979 }
1980 #endif /* WITH_THREAD_POOL */
1981
1982 /*ARGSUSED*/
1983 void sig_cleanup(int sig)
1984 {
1985 #ifndef HAVE_PTHREAD_H
1986         int             i;
1987         int             status;
1988         child_pid_t     pid;
1989         REQUEST         *curreq;
1990 #endif
1991
1992         sig = sig; /* -Wunused */
1993  
1994         /*
1995          *      request_list_busy is a lock on the request list
1996          */
1997         if (request_list_busy) {
1998                 got_child = TRUE;
1999                 return;
2000         }
2001         got_child = FALSE;
2002
2003         /*
2004          *      Reset the signal handler, if required.
2005          */
2006         reset_signal(SIGCHLD, sig_cleanup);
2007         
2008         /*
2009          *  If we're using pthreads, then there are NO child processes,
2010          *  so the waitpid() call, and the following code, is useless.
2011          */
2012 #ifndef HAVE_PTHREAD_H
2013         for (;;) {
2014                 pid = waitpid((pid_t)-1, &status, WNOHANG);
2015                 if (pid <= 0)
2016                         return;
2017
2018                 /*
2019                  *      Check to see if the child did a bad thing.
2020                  *      If so, kill ALL processes in the current
2021                  *      process group, to prevent further attacks.
2022                  */
2023                 if (debug_flag && (WIFSIGNALED(status))) {
2024                         radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
2025                             pid, WTERMSIG(status));
2026                         kill(0, SIGTERM);
2027                         exit(1);
2028                 }
2029
2030                 /*
2031                  *      Service all of the requests in the queues
2032                  */
2033                 for (i = 0; i < 256; i++) {
2034                         curreq = request_list[i].first_request;
2035                         while (curreq != (REQUEST *)NULL) {
2036                                 if (curreq->child_pid == pid) {
2037                                         curreq->child_pid = NO_SUCH_CHILD_PID;
2038                                         break;
2039                                 }
2040                                 curreq = curreq->next;
2041                         }
2042                 }
2043         }
2044 #endif /* !defined HAVE_PTHREAD_H */
2045 }
2046
2047 /*
2048  *      Display the syntax for starting this program.
2049  */
2050 static void usage(void)
2051 {
2052         fprintf(stderr,
2053                 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2054 #if defined(WITH_DBM) || defined(WITH_NDBM)
2055                 "b"
2056 #endif
2057                 "AcfnsSvXxyz]\n", progname);
2058         fprintf(stderr, "Options:\n\n");
2059         fprintf(stderr, "  -a acct_dir     use accounting directory 'acct_dir'.\n");
2060         fprintf(stderr, "  -A              Log auth detail.\n");
2061 #if defined(WITH_DBM) || defined(WITH_NDBM)
2062         fprintf(stderr, "  -b              Use DBM.\n");
2063 #endif
2064         fprintf(stderr, "  -d db_dir       Use database directory 'db_dir'.\n");
2065         fprintf(stderr, "  -f              Run as a foreground process, not a daemon.\n");
2066         fprintf(stderr, "  -h              Print this help message.\n");
2067         fprintf(stderr, "  -i address      Listen only in the given IP address.\n");
2068         fprintf(stderr, "  -l log_dir      Log messages to 'log_dir'.  Special values are:\n");
2069         fprintf(stderr, "                  stdout == log all messages to standard output.\n");
2070         fprintf(stderr, "                  syslog == log all messages to the system logger.\n");
2071         fprintf(stderr, "  -p port         Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2072         fprintf(stderr, "  -s              Do not spawn child processes to handle requests.\n");
2073         fprintf(stderr, "  -S              Log stripped names.\n");
2074         fprintf(stderr, "  -v              Print server version information.\n");
2075         fprintf(stderr, "  -X              Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2076         fprintf(stderr, "  -x              Turn on partial debugging. (-xx gives more debugging).\n");
2077         fprintf(stderr, "  -y              Log authentication failures, with password.\n");
2078         fprintf(stderr, "  -z              Log authentication successes, with password.\n");
2079         exit(1);
2080 }
2081
2082
2083 /*
2084  *      We got a fatal signal. Clean up and exit.
2085  */
2086 static void sig_fatal(int sig)
2087 {
2088         const char *me = "MASTER: ";
2089
2090         if (radius_pid != getpid()) {
2091                 me = "CHILD: ";
2092         }
2093
2094         switch(sig) {
2095                 case 100:
2096                         radlog(L_ERR, "%saccounting process died - exit.", me);
2097                         break;
2098                 case 101:
2099                         radlog(L_ERR, "%sfailed in select() - exit.", me);
2100                         break;
2101                 case SIGTERM:
2102                         radlog(L_INFO, "%sexit.", me);
2103                         break;
2104                 default:
2105                         radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2106                         break;
2107         }
2108
2109         /*
2110          *      We're running as a daemon, we're the MASTER daemon,
2111          *      and we got a fatal signal.  Tear the rest of the
2112          *      daemons down, as something absolutely horrible happened.
2113          */
2114         if ((debug_flag == 0) && (dont_fork == 0) &&
2115             (radius_pid == getpid())) {
2116                 /*
2117                  *      Kill all of the processes in the current
2118                  *      process group.
2119                  */
2120                 kill(0, SIGKILL);
2121         }
2122
2123         exit(sig == SIGTERM ? 0 : 1);
2124 }
2125
2126
2127 /*
2128  *      We got the hangup signal.
2129  *      Re-read the configuration files.
2130  */
2131 /*ARGSUSED*/
2132 static void sig_hup(int sig)
2133 {
2134         sig = sig; /* -Wunused */
2135         reset_signal(SIGHUP, sig_hup);
2136
2137         /*
2138          *      Only do the reload if we're the main server, both
2139          *      for processes, and for threads.
2140          */
2141         if (getpid() == radius_pid) {
2142                 need_reload = TRUE;
2143         }
2144 }
2145
2146 /*
2147  *      Do a proxy check of the REQUEST_LIST when using the new proxy code.
2148  *
2149  *      This function and the next two are here because they have to access
2150  *      the REQUEST_LIST structure, which is 'static' to this C file.
2151  */
2152 static REQUEST *proxy_check_list(REQUEST *request)
2153 {
2154         int id;
2155         REQUEST *oldreq;
2156         RADIUS_PACKET *pkt;
2157         
2158         /*
2159          *      Find the original request in the request list
2160          */
2161         oldreq = NULL;
2162         pkt = request->packet;
2163         
2164         for (id = 0; (id < 256) && (oldreq == NULL); id++) {
2165                 for (oldreq = request_list[id].first_request ;
2166                      oldreq != NULL ;
2167                      oldreq = oldreq->next) {
2168                         
2169                         /*
2170                          *      See if this reply packet matches a proxy
2171                          *      packet which we sent.
2172                          */
2173                         if (oldreq->proxy &&
2174                             (oldreq->proxy->dst_ipaddr == pkt->src_ipaddr) &&
2175                             (oldreq->proxy->dst_port == pkt->src_port) &&
2176                             (oldreq->proxy->id == pkt->id)) {
2177                                 /*
2178                                  *      If there is already a reply,
2179                                  *      maybe the new one is a duplicate?
2180                                  */
2181                                 if (oldreq->proxy_reply) {
2182                                         if (memcmp(oldreq->proxy_reply->vector,
2183                                                    request->packet->vector,
2184                                                    sizeof(oldreq->proxy_reply->vector)) == 0) {
2185                                                 DEBUG2("Ignoring duplicate proxy reply");
2186                                                 request_free(request);
2187                                                 return NULL;
2188                                         } else {
2189                                                 /*
2190                                                  *      ??? New reply ???
2191                                                  */
2192                                                 continue;
2193                                         }
2194                                 } /* else no reply, this one must match */
2195
2196                                 /*
2197                                  *      Exit from request list loop
2198                                  *      while oldreq != NULL, which will
2199                                  *      cause the outer loop to stop, too.
2200                                  */
2201                                 break;
2202                         } /* the reply matches a proxied request */
2203                 } /* for all requests in the id request list */
2204         } /* for all 256 id's*/
2205         
2206         /*
2207          *      If we haven't found the old request, complain.
2208          */
2209         if (oldreq == NULL) {
2210                 radlog(L_PROXY, "Unrecognized proxy reply from server %s - ID %d",
2211                     client_name(request->packet->src_ipaddr),
2212                     request->packet->id);
2213                 request_free(request);
2214                 return NULL;
2215         }
2216
2217         /*
2218          *      Refresh the old request, and update it with the proxy reply.
2219          *
2220          *      ??? Can we delete the proxy request here?
2221          *      Is there any more need for it?
2222          */
2223         oldreq->timestamp = request->timestamp;
2224         oldreq->proxy_reply = request->packet;
2225         request->packet = NULL;
2226         request_free(request);
2227         return oldreq;
2228 }
2229
2230 /*
2231  *      Walk through all of the requests, checking cleanup times,
2232  *      proxy retry times, and maximum request times.  We then set the
2233  *      time delay until the server has to service the request queue.
2234  *
2235  *      This time delay is used by the main select() loop, to sleep
2236  *      until either a packet comes in, or until there's some work
2237  *      to be done.
2238  */
2239 static struct timeval *setuptimeout(struct timeval *tv)
2240 {
2241         time_t now = time(NULL);
2242         time_t difference, smallest = 0;
2243         int foundone = FALSE;
2244         int id;
2245         REQUEST *curreq;
2246
2247         difference = 1;         /* initialize it to a non-zero value */
2248
2249         /*
2250          *      Loop over all of the outstanding requests.
2251          */
2252         for (id = 0; id < 256; id++) {
2253                 for (curreq = request_list[id].first_request; curreq; curreq = curreq->next) {
2254                         /*
2255                          *      The request is marked to be
2256                          *      cleaned up: ignore it.
2257                          */
2258                         if (curreq->timestamp == 0) {
2259                                 continue;
2260                         } else if (curreq->finished) {
2261                                 /*
2262                                  *      The request is finished.
2263                                  *      Wake up when it's time to clean
2264                                  *      it up.
2265                                  */
2266                                 difference = (curreq->timestamp + cleanup_delay) - now;
2267
2268                         } else if (curreq->proxy && !curreq->proxy_reply) {
2269                                 /*
2270                                  *      The request is NOT finished, but there
2271                                  *      is an outstanding proxy request,
2272                                  *      with no matching proxy reply.
2273                                  *
2274                                  *      Wake up when it's time to re-send
2275                                  *      the proxy request.
2276                                  */
2277                                 difference = curreq->proxy_next_try - now;
2278
2279                         } else {
2280                                 /*
2281                                  *      The request is NOT finished.
2282                                  *
2283                                  *      Wake up when it's time to kill
2284                                  *      the errant thread/process.
2285                                  */
2286                                 difference = (curreq->timestamp + max_request_time) - now;
2287                         }
2288
2289                         /*
2290                          *      Found a valid request, with a time at which
2291                          *      we're going to to wake up.
2292                          */
2293                         if (!foundone) {
2294                                 foundone = TRUE;
2295                                 smallest = difference;
2296                         } else {
2297                                 if (difference < smallest)
2298                                         smallest = difference;
2299                         }
2300
2301                         if (difference <= 0) break; /* short-circuit */
2302                 } /* loop over linked list for that ID */
2303
2304                 if (difference <= 0) break; /* short-circuit */
2305         } /* loop over 256 ID's */
2306
2307         /*
2308          *      We haven't found a time at which we need to wake up.
2309          *      Return NULL, so that the select() call will sleep forever.
2310          */
2311         if (!foundone) {
2312                 DEBUG2("Nothing to do.  Sleeping until we see a request.");
2313                 return NULL;
2314         }
2315
2316         /*
2317          *      If the server is CPU starved, then we CAN miss a time
2318          *      for servicing requests.  In which case the 'smallest'
2319          *      value will be negative.  select() doesn't like that,
2320          *      so we fix it.
2321          */
2322         if (smallest < 0) smallest = 0;
2323
2324         /*
2325          *      Set the time (in seconds) for how long we're
2326          *      supposed to sleep.
2327          */
2328         tv->tv_sec = smallest;
2329         tv->tv_usec = 0;
2330         DEBUG2("Waking up in %d seconds...", (int) smallest);
2331         return tv;
2332 }
2333
2334 /*
2335  *      Walk the request list, seeing if we need to re-send
2336  *      a proxy packet.
2337  */
2338 static void proxy_retry(void)
2339 {
2340         time_t now = time(NULL);
2341         REQUEST *p;
2342         int id;
2343
2344         /*
2345          *      If we're not proxying, or if we're not re-trying
2346          *      requests, then don't bother walking through the list.
2347          */
2348         if (!proxy_requests ||
2349             (proxy_retry_delay == 0)) {
2350                 return;
2351         }
2352         
2353         /*
2354          *      Walk over all of the Id's.
2355          */
2356         for (id = 0; id < 256; id++) {
2357         for (p = request_list[id].first_request; p; p = p->next) {
2358                 /*
2359                  *      The request is finished, (but it hasn't yet
2360                  *      been removed from the list.)
2361                  *      OR there is no proxy request,
2362                  *      OR we already have seen the reply (so we don't
2363                  *      need to send another proxy request),
2364                  *      OR the next try is to be done later.
2365                  *
2366                  *      Skip the try.
2367                  *
2368                  *      FIXME: These retries should be binned by
2369                  *      the next try time, so we don't have to do
2370                  *      all of this work on every second.
2371                  *
2372                  *      That will also get rid of these checks, as
2373                  *      a packet can get removed from the bin when
2374                  *      the proxy reply is received.
2375                  */
2376                 if ((p->finished) ||
2377                     (!p->proxy) ||
2378                     (p->proxy_reply) ||
2379                     (p->proxy_next_try > now)) {
2380                         continue;
2381                 }
2382
2383                 /*
2384                  *      If the proxy retry count is zero, then
2385                  *      we've sent the last try, and have NOT received
2386                  *      a reply from the end server.  In that case,
2387                  *      we don't bother trying again, but just mark
2388                  *      the request as finished, and go to the next one.
2389                  */
2390                 if (p->proxy_try_count == 0) {
2391                         p->finished = TRUE;
2392                         rad_reject(p);
2393                         continue;
2394                 }
2395
2396                 /*
2397                  *      We're trying one more time, so count down
2398                  *      the tries, and set the next try time.
2399                  */
2400                 --p->proxy_try_count;
2401                 p->proxy_next_try = now + proxy_retry_delay;
2402                 
2403                 /* Fix up Acct-Delay-Time */
2404                 if (p->proxy->code == PW_ACCOUNTING_REQUEST) {
2405                         VALUE_PAIR *delaypair;
2406                         delaypair = pairfind(p->proxy->vps, PW_ACCT_DELAY_TIME);
2407                         
2408                         if (!delaypair) {
2409                                 delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
2410                                 if (!delaypair) {
2411                                         radlog(L_ERR|L_CONS, "no memory");
2412                                         exit(1);
2413                                 }
2414                                 pairadd(&p->proxy->vps, delaypair);
2415                         }
2416                         delaypair->lvalue = now - p->proxy->timestamp;
2417                         
2418                         /* Must recompile the valuepairs to wire format */
2419                         free(p->proxy->data);
2420                         p->proxy->data = NULL;
2421                 } /* proxy accounting request */
2422                 
2423                 /*
2424                  *      Send the proxy packet.
2425                  */
2426                 rad_send(p->proxy, p->proxysecret);
2427         }
2428         }
2429 }