a0561eeea3b9be5d9948ea6b3a69cb993f1e7944
[freeradius.git] / src / main / request_list.c
1 /*
2  * request_list.c       Hide the handling of the REQUEST list from
3  *                      the main server.
4  *
5  * Version:     $Id$
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * Copyright 2003  The FreeRADIUS server project
22  */
23
24 /*
25  *      The functions in this file must be called ONLY from radiusd.c,
26  *      in the main server processing thread.  These functions are NOT
27  *      thread-safe!
28  */
29
30 static const char rcsid[] = "$Id$";
31
32 #include "autoconf.h"
33 #include "libradius.h"
34
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "radiusd.h"
39 #include "rad_assert.h"
40 #include "request_list.h"
41 #include "radius_snmp.h"
42
43
44 /*
45  *  We keep the incoming requests in an array, indexed by ID.
46  *
47  *  Each array element contains a linked list of containers of 
48  *  active requests, a count of the number of requests, and a time 
49  *  at which the first request in the list must be serviced.
50  */
51
52 typedef struct REQNODE {
53         struct REQNODE *prev, *next;
54         REQUEST *req;
55 } REQNODE;
56
57 typedef struct REQUESTINFO {
58         REQNODE *first_request;
59         REQNODE *last_request;
60         int request_count;
61         time_t last_cleaned_list;
62 } REQUESTINFO;
63
64 static REQUESTINFO      request_list[256];
65
66 #undef  WITH_RBTREE
67 #ifdef WITH_RBTREE
68
69 /*
70  *      It MAY make more sense here to key off of the packet ID, just
71  *      like the request_list.  Then again, saving another 8 lookups
72  *      (on average) isn't much of a problem.
73  *
74  *      The "request_cmp" function keys off of the packet ID first,
75  *      so the first 8 layers of the tree will be the fanned-out
76  *      tree for packet ID's.
77  */
78 static rbtree_t         *request_tree;
79
80 #ifdef HAVE_PTHREAD_H
81 static pthread_mutex_t  proxy_mutex;
82 #else
83 /*
84  *      This is easier than ifdef's throughout the code.
85  */
86 #define pthread_mutex_lock(_x)
87 #define pthread_mutex_unlock(_x)
88 #endif
89 static rbtree_t         *proxy_tree;
90
91 /*
92  *      Compare two REQUEST data structures, based on a number
93  *      of criteria.
94  */
95 static int request_cmp(const void *one, const void *two)
96 {
97         const REQUEST *a = one;
98         const REQUEST *b = two;
99
100         /*
101          *      The following code looks unreasonable, but it's
102          *      the only way to make the comparisons work.
103          */
104         if (a->packet->id < b->packet->id) return -1;
105         if (a->packet->id > b->packet->id) return +1;
106
107         if (a->packet->code < b->packet->code) return -1;
108         if (a->packet->code > b->packet->code) return +1;
109
110         if (a->packet->src_ipaddr < b->packet->src_ipaddr) return -1;
111         if (a->packet->src_ipaddr > b->packet->src_ipaddr) return +1;
112
113         if (a->packet->src_port < b->packet->src_port) return -1;
114         if (a->packet->src_port > b->packet->src_port) return +1;
115
116         if (a->packet->dst_ipaddr < b->packet->dst_ipaddr) return -1;
117         if (a->packet->dst_ipaddr > b->packet->dst_ipaddr) return +1;
118
119         if (a->packet->dst_port < b->packet->dst_port) return -1;
120         if (a->packet->dst_port > b->packet->dst_port) return +1;
121
122         /*
123          *      Everything's equal.  Say so.
124          */
125         return 0;
126 }
127
128 /*
129  *      Compare two REQUEST data structures, based on a number
130  *      of criteria, for proxied packets.
131  */
132 static int proxy_cmp(const void *one, const void *two)
133 {
134         const REQUEST *a = one;
135         const REQUEST *b = two;
136
137         rad_assert(a->proxy != NULL);
138         rad_assert(b->proxy != NULL);
139
140         /*
141          *      The following code looks unreasonable, but it's
142          *      the only way to make the comparisons work.
143          */
144         if (a->proxy->id < b->proxy->id) return -1;
145         if (a->proxy->id > b->proxy->id) return +1;
146
147         /*
148          *      Crap... we've got to check packet codes, too.
149          */
150
151 #if 0
152         /*
153          *      FIXME: Add later, when we have multiple sockets
154          *      for proxied requests.
155          */
156         if (a->proxy->src_ipaddr < b->proxy->src_ipaddr) return -1;
157         if (a->proxy->src_ipaddr > b->proxy->src_ipaddr) return +1;
158
159         if (a->proxy->src_port < b->proxy->src_port) return -1;
160         if (a->proxy->src_port > b->proxy->src_port) return +1;
161 #endif
162
163         if (a->proxy->dst_ipaddr < b->proxy->dst_ipaddr) return -1;
164         if (a->proxy->dst_ipaddr > b->proxy->dst_ipaddr) return +1;
165
166         if (a->proxy->dst_port < b->proxy->dst_port) return -1;
167         if (a->proxy->dst_port > b->proxy->dst_port) return +1;
168
169         /*
170          *      Everything's equal.  Say so.
171          */
172         return 0;
173 }
174
175 #endif
176
177 /*
178  *      Remember the next request at which we start walking
179  *      the list.
180  */
181 static REQUEST *last_request = NULL;
182
183
184 /*
185  *      Initialize the request list.
186  */
187 int rl_init(void)
188 {
189         int i;
190
191         /*
192          *      Initialize the request_list[] array.
193          */
194         for (i = 0; i < 256; i++) {
195                 request_list[i].first_request = NULL;
196                 request_list[i].last_request = NULL;
197                 request_list[i].request_count = 0;
198                 request_list[i].last_cleaned_list = 0;
199         }
200         
201 #ifdef WITH_RBTREE
202         request_tree = rbtree_create(request_cmp, NULL, 0);
203         if (!request_tree) {
204                 rad_assert("FAIL" == NULL);
205         }
206
207         proxy_tree = rbtree_create(proxy_cmp, NULL, 0);
208         if (!proxy_tree) {
209                 rad_assert("FAIL" == NULL);
210         }
211
212 #ifndef HAVE_PTHREAD_H
213         /*
214          *      For now, always create the mutex.
215          *
216          *      Later, we can only create it if there are multiple threads.
217          */
218         if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
219                 radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
220                        strerror(errno));
221                 exit(1);
222         }
223 #endif
224 #endif
225
226         return 0;
227 }
228
229 /*
230  *      Delete a particular request.
231  */
232 void rl_delete(REQUEST *request)
233 {
234         int id;
235         REQNODE *prev, *next;
236
237         prev = ((REQNODE *) request->container)->prev;
238         next = ((REQNODE *) request->container)->next;
239         
240         id = request->packet->id;
241
242         /*
243          *      Update the last request we touched.
244          *
245          *      This is so the periodic "walk & clean list"
246          *      function, below, doesn't walk over all requests
247          *      all of the time.  Rather, it tries to amortize
248          *      the cost...
249          */
250         if (last_request == request) {
251                 last_request = rl_next(last_request);
252         }
253         
254
255         if (prev == NULL) {
256                 request_list[id].first_request = next;
257         } else {
258                 prev->next = next;
259         }
260
261         if (next == NULL) {
262                 request_list[id].last_request = prev;
263         } else {
264                 next->prev = prev;
265         }
266         
267         free(request->container);
268
269 #ifdef WITH_SNMP
270         /*
271          *      Update the SNMP statistics.
272          *
273          *      Note that we do NOT do this in rad_respond(),
274          *      as that function is called from child threads.
275          *      Instead, we update the stats when a request is
276          *      deleted, because only the main server thread calls
277          *      this function...
278          */
279         if (mainconfig.do_snmp) {
280                 switch (request->reply->code) {
281                 case PW_AUTHENTICATION_ACK:
282                   rad_snmp.auth.total_responses++;
283                   rad_snmp.auth.total_access_accepts++;
284                   break;
285
286                 case PW_AUTHENTICATION_REJECT:
287                   rad_snmp.auth.total_responses++;
288                   rad_snmp.auth.total_access_rejects++;
289                   break;
290
291                 case PW_ACCESS_CHALLENGE:
292                   rad_snmp.auth.total_responses++;
293                   rad_snmp.auth.total_access_challenges++;
294                   break;
295
296                 case PW_ACCOUNTING_RESPONSE:
297                   rad_snmp.acct.total_responses++;
298                   break;
299
300                 default:
301                         break;
302                 }
303         }
304 #endif
305
306 #ifdef WITH_RBTREE
307         /*
308          *      Delete the request from the tree.
309          */
310         {
311                 rbnode_t *node;
312
313                 node = rbtree_find(request_tree, request);
314                 rad_assert(node != NULL);
315                 rbtree_delete(request_tree, node);
316
317
318                 /*
319                  *      Delete it from the proxy tree, too.
320                  */
321                 if (request->proxy) {
322                         pthread_mutex_lock(&proxy_mutex);
323                         node = rbtree_find(proxy_tree, request);
324                         if (node) rbtree_delete(proxy_tree, node);
325                         pthread_mutex_unlock(&proxy_mutex);
326                 }
327 #if 0
328                 /*
329                  *      For paranoia.  Delete when the RBTREE code
330                  *      is made live.
331                  */
332                 DEBUG2(" Trees: %d %d\n",
333                        rbtree_num_elements(request_tree),
334                        rbtree_num_elements(proxy_tree));
335 #endif
336         }
337 #endif
338
339         request_free(&request);
340         request_list[id].request_count--;
341
342 }
343
344 /*
345  *      Add a request to the request list.
346  */
347 void rl_add(REQUEST *request)
348 {
349         int id = request->packet->id;
350         REQNODE *node;
351
352         rad_assert(request->container == NULL);
353
354         request->container = rad_malloc(sizeof(REQNODE));
355         node = (REQNODE *) request->container;
356         node->req = request;
357
358         node->prev = NULL;
359         node->next = NULL;
360
361         if (!request_list[id].first_request) {
362                 rad_assert(request_list[id].request_count == 0);
363
364                 request_list[id].first_request = node;
365                 request_list[id].last_request = node;
366         } else {
367                 rad_assert(request_list[id].request_count != 0);
368
369                 node->prev = request_list[id].last_request;
370                 request_list[id].last_request->next = node;
371                 request_list[id].last_request = node;
372         }
373
374 #ifdef WITH_RBTREE
375         /*
376          *      Insert the request into the tree.
377          */
378         if (rbtree_insert(request_tree, request) == 0) {
379                 rad_assert("FAIL" == NULL);
380         }
381 #endif
382
383         request_list[id].request_count++;
384 }
385
386 /*
387  *      Look up a particular request, using:
388  *
389  *      Request ID, request code, source IP, source port, 
390  *
391  *      Note that we do NOT use the request vector to look up requests.
392  *
393  *      We MUST NOT have two requests with identical (id/code/IP/port), and
394  *      different vectors.  This is a serious error!
395  */
396 REQUEST *rl_find(RADIUS_PACKET *packet)
397 {
398 #ifdef WITH_RBTREE
399         REQUEST myrequest;
400         
401         myrequest.packet = packet;
402         
403         return rbtree_finddata(request_tree, &myrequest);
404 #else
405         REQNODE *curreq;
406
407         for (curreq = request_list[packet->id].first_request;
408                         curreq != NULL ;
409                         curreq = ((REQNODE *)curreq->req->container)->next) {
410                 /*
411                  *      FIXME: Check destination IP and port, too?
412                  *
413                  *      Can the same client send different packets
414                  *      from the same source IP/port to two different
415                  *      sockets on the server?
416                  *
417                  *      YES: If the server has multiple IP's, and the
418                  *      NAS thinks it's doing load balancing to two
419                  *      different servers..
420                  */
421                 if ((curreq->req->packet->code == packet->code) &&
422                     (curreq->req->packet->src_ipaddr == packet->src_ipaddr) &&
423                     (curreq->req->packet->src_port == packet->src_port)) {
424                         return curreq->req;
425                 }
426         }
427
428         return NULL;
429 #endif
430 }
431
432
433 /*
434  *      Add an entry to the proxy tree.
435  */
436 void rl_add_proxy(REQUEST *request)
437 {
438 #ifdef WITH_RBTREE
439         pthread_mutex_lock(&proxy_mutex);
440
441         /*
442          *      FIXME: Do magic to assign ID's, etc.
443          */
444
445         if (!rbtree_insert(proxy_tree, request)) {
446                 rad_assert("FAILED" == 0);
447         }
448
449         pthread_mutex_unlock(&proxy_mutex);
450 #else
451         /*
452          *      Do nothing.
453          */
454 #endif
455 }
456
457
458 /*
459  *      Look up a particular request, using:
460  *
461  *      Request Id, request code, source IP, source port,
462  *
463  *      Note that we do NOT use the request vector to look up requests.
464  *
465  *      We MUST NOT have two requests with identical (id/code/IP/port), and
466  *      different vectors.  This is a serious error!
467  */
468 REQUEST *rl_find_proxy(RADIUS_PACKET *packet)
469 {
470 #ifdef WITH_RBTREE
471         REQUEST myrequest, *maybe = NULL;
472         RADIUS_PACKET myproxy;
473         rbnode_t *node;
474         
475         myrequest.proxy = &myproxy;
476         
477         myproxy.id = packet->id;
478         
479         /*
480          *      FIXME: Look for BOTH src/dst stuff.
481          */
482         myproxy.dst_ipaddr = packet->src_ipaddr;
483         myproxy.dst_port = packet->src_port;
484         
485         pthread_mutex_lock(&proxy_mutex);
486         node = rbtree_find(proxy_tree, &myrequest);
487         if (node) {
488                 maybe = rbtree_node2data(proxy_tree, node);
489                 rbtree_delete(proxy_tree, node);
490         }
491         pthread_mutex_unlock(&proxy_mutex);
492         return maybe;
493 #else
494         REQNODE *curreq = NULL;
495         int id;
496         
497         /*
498          *      The Proxy RADIUS Id is completely independent
499          *      of the original request Id.  We've got to root through
500          *      *all* requests, in order to find it.
501          *
502          *      FIXME: Maybe we want to use the original packet Id
503          *      as the Proxy-State?
504          */
505         for (id = 0; (id < 256) && (curreq == NULL); id++) {
506                 for (curreq = request_list[id].first_request;
507                      curreq != NULL ;
508                      curreq = curreq->next) {
509                         if (curreq->req->proxy &&
510                             (curreq->req->proxy->id == packet->id) &&
511                             (curreq->req->proxy->dst_ipaddr == packet->src_ipaddr) &&
512                             (curreq->req->proxy->dst_port == packet->src_port)) {
513                                 return curreq->req;
514                         }
515                 } /* loop over all requests for this id. */
516         } /* loop over all id's... this is horribly inefficient */
517
518         return NULL;
519 #endif
520 }
521 /*
522  *      Walk over all requests, performing a callback for each request.
523  */
524 int rl_walk(RL_WALK_FUNC walker, void *data)
525 {
526         int id, rcode;
527         REQNODE *curreq, *next;
528
529         /*
530          *      Walk over all 256 ID's.
531          */
532         for (id = 0; id < 256; id++) {
533
534                 /*
535                  *      Walk over the request list for each ID.
536                  */
537                 for (curreq = request_list[id].first_request;
538                                 curreq != NULL ;
539                                 curreq = next) {
540                         /*
541                          *      The callback MIGHT delete the current
542                          *      request, so we CANNOT depend on curreq->next
543                          *      to be there, when going to the next element
544                          *      in the 'for' loop.
545                          */
546                         next = curreq->next;
547
548                         rcode = walker(curreq->req, data);
549                         if (rcode != RL_WALK_CONTINUE) {
550                                 return rcode;
551                         }
552                 }
553         }
554
555         return 0;
556 }
557
558 /*
559  *      Walk from one request to the next.
560  */
561 REQUEST *rl_next(REQUEST *request)
562 {
563         int id, start_id;
564         int count;
565
566         /*
567          *      If we were passed a request, then go to the "next" one.
568          */
569         if (request != NULL) {
570                 rad_assert(request->magic == REQUEST_MAGIC);
571
572                 /*
573                  *      It has a "next", return it.
574                  */
575                 if (((REQNODE *)request->container)->next != NULL) {
576                         return ((REQNODE *)request->container)->next->req;
577                 } else {
578                         /*
579                          *      No "next", increment the ID, and look
580                          *      at that one.
581                          */
582                         start_id = request->packet->id + 1;
583                         start_id &= 0xff;
584                         count = 255;
585                 }
586         } else {
587                 /*
588                  *      No input request, start looking at ID 0.
589                  */
590                 start_id = 0;
591                 count = 256;
592         }
593
594         /*
595          *      Check all ID's, wrapping around at 255.
596          */
597         for (id = start_id; id < (start_id + count); id++) {
598
599                 /*
600                  *      This ID has a request, return it.
601                  */
602                 if (request_list[id & 0xff].first_request != NULL) {
603                         rad_assert(request_list[id&0xff].first_request->req != request);
604
605                         return request_list[id & 0xff].first_request->req;
606                 }
607         }
608
609         /*
610          *      No requests at all in the list. Nothing to do.
611          */
612         DEBUG2("rl_next:  returning NULL");
613         return NULL;
614 }
615
616 /*
617  *      Return the number of requests in the request list.
618  */
619 int rl_num_requests(void)
620 {
621         int id;
622         int request_count = 0;
623
624         for (id = 0; id < 256; id++) {
625                 request_count += request_list[id].request_count;
626         }
627         
628         return request_count;
629 }
630
631 typedef struct rl_walk_t {
632         time_t  now;
633         time_t  smallest;
634 } rl_walk_t;
635
636
637 /*
638  *  Refresh a request, by using proxy_retry_delay, cleanup_delay,
639  *  max_request_time, etc.
640  *
641  *  When walking over the request list, all of the per-request
642  *  magic is done here.
643  */
644 static int refresh_request(REQUEST *request, void *data)
645 {
646         rl_walk_t *info = (rl_walk_t *) data;
647         time_t difference;
648         child_pid_t child_pid;
649
650         rad_assert(request->magic == REQUEST_MAGIC);
651
652         /*
653          *  If the request is marked as a delayed reject, AND it's
654          *  time to send the reject, then do so now.
655          */
656         if (request->finished &&
657             ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0)) {
658                 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
659
660                 difference = info->now - request->timestamp;
661                 if (difference >= (time_t) mainconfig.reject_delay) {
662
663                         /*
664                          *  Clear the 'delayed reject' bit, so that we
665                          *  don't do this again.
666                          */
667                         request->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
668                         rad_send(request->reply, request->packet,
669                                  request->secret);
670                 }
671         }
672
673         /*
674          *  If the request has finished processing, AND it's child has
675          *  been cleaned up, AND it's time to clean up the request,
676          *  OR, it's an accounting request.  THEN, go delete it.
677          *
678          *  If this is a request which had the "don't cache" option
679          *  set, then delete it immediately, as it CANNOT have a
680          *  duplicate.
681          */
682         if (request->finished &&
683             ((request->timestamp + mainconfig.cleanup_delay <= info->now) ||
684              ((request->options & RAD_REQUEST_OPTION_DONT_CACHE) != 0))) {
685                 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
686
687                 /*
688                  *  Request completed, delete it, and unlink it
689                  *  from the currently 'alive' list of requests.
690                  */
691                 DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
692                                 request->number, request->packet->id,
693                                 (unsigned long) request->timestamp);
694
695                 /*
696                  *  Delete the request.
697                  */
698                 rl_delete(request);
699                 return RL_WALK_CONTINUE;
700         }
701
702         /*
703          *  Maybe the child process handling the request has hung:
704          *  kill it, and continue.
705          */
706         if ((request->timestamp + mainconfig.max_request_time) <= info->now) {
707                 int number;
708
709                 child_pid = request->child_pid;
710                 number = request->number;
711
712                 /*
713                  *      There MUST be a RAD_PACKET reply.
714                  */
715                 rad_assert(request->reply != NULL);
716
717                 /*
718                  *      If we've tried to proxy the request, and
719                  *      the proxy server hasn't responded, then
720                  *      we send a REJECT back to the caller.
721                  *
722                  *      For safety, we assert that there is no child
723                  *      handling the request.  If the assertion fails,
724                  *      it means that we've sent a proxied request to
725                  *      the home server, and the child thread is still
726                  *      sitting on the request!
727                  */
728                 if (request->proxy && !request->proxy_reply) {
729                         rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
730                         
731                         radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s:%d",
732                                request->number,
733                                client_name(request->packet->src_ipaddr),
734                                request->packet->src_port);
735                         request_reject(request);
736                         request->finished = TRUE;
737                         return RL_WALK_CONTINUE;
738                 }
739
740                 if (mainconfig.kill_unresponsive_children) {
741                         if (child_pid != NO_SUCH_CHILD_PID) {
742                                 /*
743                                  *  This request seems to have hung
744                                  *   - kill it
745                                  */
746 #ifdef HAVE_PTHREAD_H
747                                 radlog(L_ERR, "Killing unresponsive thread for request %d",
748                                        request->number);
749                                 pthread_cancel(child_pid);
750 #endif
751                         } /* else no proxy reply, quietly fail */
752                 
753                         /*
754                          *      Maybe we haven't killed it.  In that
755                          *      case, print a warning.
756                          */
757                 } else if ((child_pid != NO_SUCH_CHILD_PID) &&
758                            ((request->options & RAD_REQUEST_OPTION_LOGGED_CHILD) == 0)) {
759                         radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d",
760                                (unsigned long)child_pid, number);
761
762                         /*
763                          *  Set the option that we've sent a log message,
764                          *  so that we don't send more than one message
765                          *  per request.
766                          */
767                         request->options |= RAD_REQUEST_OPTION_LOGGED_CHILD;
768                 }
769
770                 /*
771                  *  Send a reject message for the request, mark it
772                  *  finished, and forget about the child.
773                  */
774                 request_reject(request);
775                 request->child_pid = NO_SUCH_CHILD_PID;
776                 if (mainconfig.kill_unresponsive_children)
777                         request->finished = TRUE;
778                 return RL_WALK_CONTINUE;
779         } /* the request has been in the queue for too long */
780
781         /*
782          *  If the request is still being processed, then due to the
783          *  above check, it's still within it's time limit.  In that
784          *  case, don't do anything.
785          */
786         if (request->child_pid != NO_SUCH_CHILD_PID) {
787                 return RL_WALK_CONTINUE;
788         }
789
790         /*
791          *  The request is finished.
792          */
793         if (request->finished) goto setup_timeout;
794
795         /*
796          *  We're not proxying requests at all.
797          */
798         if (!mainconfig.proxy_requests) goto setup_timeout;
799
800         /*
801          *  We're proxying synchronously, so we don't retry it here.
802          *  Some other code takes care of retrying the proxy requests.
803          */
804         if (mainconfig.proxy_synchronous) goto setup_timeout;
805
806         /*
807          *  The proxy retry delay is zero, meaning don't retry.
808          */
809         if (mainconfig.proxy_retry_delay == 0) goto setup_timeout;
810
811         /*
812          *  There is no proxied request for this packet, so there's
813          *  no proxy retries.
814          */
815         if (!request->proxy) goto setup_timeout;
816
817         /*
818          *  We've already seen the proxy reply, so we don't need
819          *  to send another proxy request.
820          */
821         if (request->proxy_reply) goto setup_timeout;
822
823         /*
824          *  It's not yet time to re-send this proxied request.
825          */
826         if (request->proxy_next_try > info->now) goto setup_timeout;
827         
828         /*
829          *  If the proxy retry count is zero, then
830          *  we've sent the last try, and have NOT received
831          *  a reply from the end server.  In that case,
832          *  we don't bother trying again, but just mark
833          *  the request as finished, and go to the next one.
834          */
835         if (request->proxy_try_count == 0) {
836                 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
837                 request_reject(request);
838                 realm_disable(request->proxy->dst_ipaddr,request->proxy->dst_port);
839                 request->finished = TRUE;
840                 goto setup_timeout;
841         }
842
843         /*
844          *  We're trying one more time, so count down
845          *  the tries, and set the next try time.
846          */
847         request->proxy_try_count--;
848         request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
849                 
850         /* Fix up Acct-Delay-Time */
851         if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
852                 VALUE_PAIR *delaypair;
853                 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
854                 
855                 if (!delaypair) {
856                         delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
857                         if (!delaypair) {
858                                 radlog(L_ERR|L_CONS, "no memory");
859                                 exit(1);
860                         }
861                         pairadd(&request->proxy->vps, delaypair);
862                 }
863                 delaypair->lvalue = info->now - request->proxy->timestamp;
864                         
865                 /* Must recompile the valuepairs to wire format */
866                 free(request->proxy->data);
867                 request->proxy->data = NULL;
868         } /* proxy accounting request */
869
870         /*
871          *  Assert that we have NOT seen the proxy reply yet.
872          *
873          *  If we HAVE seen it, then we SHOULD NOT be bugging the
874          *  home server!
875          */
876         rad_assert(request->proxy_reply == NULL);
877
878         /*
879          *  Send the proxy packet.
880          */
881         rad_send(request->proxy, NULL, request->proxysecret);
882
883 setup_timeout:
884         /*
885          *  Don't do more long-term checks, if we've got to wake
886          *  up now.
887          */
888         if (info->smallest == 0) {
889                 return RL_WALK_CONTINUE;
890         }
891
892         /*
893          *  The request is finished.  Wake up when it's time to
894          *  clean it up.
895          */
896         if (request->finished) {
897                 difference = (request->timestamp + mainconfig.cleanup_delay) - info->now;
898
899                 /*
900                  *  If the request is marked up to be rejected later,
901                  *  then wake up later.
902                  */
903                 if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0) {
904                         if (difference >= (time_t) mainconfig.reject_delay) {
905                                 difference = (time_t) mainconfig.reject_delay;
906                         }
907                 }
908
909         } else if (request->proxy && !request->proxy_reply) {
910                 /*
911                  *  The request is NOT finished, but there is an
912                  *  outstanding proxy request, with no matching
913                  *  proxy reply.
914                  *
915                  *  Wake up when it's time to re-send
916                  *  the proxy request.
917                  *
918                  *  But in synchronous proxy, we don't retry but we update
919                  *  the next retry time as NAS has not resent the request
920                  *  in the given retry window.
921                  */
922                 if (mainconfig.proxy_synchronous) {
923                         request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
924                 }
925                 difference = request->proxy_next_try - info->now;
926         } else {
927                 /*
928                  *  The request is NOT finished.
929                  *
930                  *  Wake up when it's time to kill the errant
931                  *  thread/process.
932                  */
933                 difference = (request->timestamp + mainconfig.max_request_time) - info->now;
934         }
935
936         /*
937          *  If the server is CPU starved, then we CAN miss a time
938          *  for servicing requests.  In which case the 'difference'
939          *  value will be negative.  select() doesn't like that,
940          *  so we fix it.
941          */
942         if (difference < 0) {
943                 difference = 0;
944         }
945
946         /*
947          *  Update the 'smallest' time.
948          */
949         if ((info->smallest < 0) ||
950                 (difference < info->smallest)) {
951                 info->smallest = difference;
952         }
953
954         return RL_WALK_CONTINUE;
955 }
956
957
958 /*
959  *  Clean up the request list, every so often.
960  *
961  *  This is done by walking through ALL of the list, and
962  *  - marking any requests which are finished, and expired
963  *  - killing any processes which are NOT finished after a delay
964  *  - deleting any marked requests.
965  */
966 struct timeval *rl_clean_list(time_t now)
967 {
968         /*
969          *  Static variables, so that we don't do all of this work
970          *  more than once per second.
971          *
972          *  Note that we have 'tv' and 'last_tv'.  'last_tv' is
973          *  pointed to by 'last_tv_ptr', and depending on the
974          *  system implementation of select(), it MAY be modified.
975          *
976          *  In that was, we want to use the ORIGINAL value, from
977          *  'tv', and wipe out the (possibly modified) last_tv.
978          */
979         static time_t last_cleaned_list = 0;
980         static struct timeval tv, *last_tv_ptr = NULL;
981         static struct timeval last_tv;
982
983         rl_walk_t info;
984
985         info.now = now;
986         info.smallest = -1;
987
988         /*
989          *  If we've already set up the timeout or cleaned the
990          *  request list this second, then don't do it again.  We
991          *  simply return the sleep delay from last time.
992          *
993          *  Note that if we returned NULL last time, there was nothing
994          *  to do.  BUT we've been woken up since then, which can only
995          *  happen if we received a packet.  And if we've received a
996          *  packet, then there's some work to do in the future.
997          *
998          *  FIXME: We can probably use gettimeofday() for finer clock
999          *  resolution, as the current method will cause it to sleep
1000          *  too long...
1001          */
1002         if ((last_tv_ptr != NULL) &&
1003             (last_cleaned_list == now) &&
1004             (tv.tv_sec != 0)) {         
1005                 int i;
1006
1007                 /*
1008                  *  If we're NOT walking the entire request list,
1009                  *  then we want to iteratively check the request
1010                  *  list.
1011                  *
1012                  *  If there is NO previous request, go look for one.
1013                  */
1014                 if (!last_request) 
1015                         last_request = rl_next(last_request);
1016
1017                 /*
1018                  *  On average, there will be one request per
1019                  *  'cleanup_delay' requests, which needs to be
1020                  *  serviced.
1021                  *
1022                  *  And only do this servicing, if we have a request
1023                  *  to service.
1024                  */
1025                 if (last_request) 
1026                         for (i = 0; i < mainconfig.cleanup_delay; i++) {
1027                                 REQUEST *next;
1028                         
1029                                 /*
1030                                  *  This function call MAY delete the
1031                                  *  request pointed to by 'last_request'.
1032                                  */
1033                                 next = rl_next(last_request);
1034                                 refresh_request(last_request, &info);
1035                                 last_request = next;
1036
1037                                 /*
1038                                  *  Nothing to do any more, exit.
1039                                  */
1040                                 if (!last_request) 
1041                                         break;
1042                         }
1043
1044                 last_tv = tv;
1045                 DEBUG2("Waking up in %d seconds...",
1046                                 (int) last_tv_ptr->tv_sec);
1047                 return last_tv_ptr;
1048         }
1049         last_cleaned_list = now;
1050         last_request = NULL;
1051         DEBUG2("--- Walking the entire request list ---");
1052
1053         /*
1054          *  Hmmm... this is Big Magic.  We make it seem like
1055          *  there's an additional second to wait, for a whole
1056          *  host of reasons which I can't explain adequately,
1057          *  but which cause the code to Just Work Right.
1058          */
1059         info.now--;
1060
1061         rl_walk(refresh_request, &info);
1062
1063         /*
1064          *  We haven't found a time at which we need to wake up.
1065          *  Return NULL, so that the select() call will sleep forever.
1066          */
1067         if (info.smallest < 0) {
1068                 /*
1069                  *  If we're not proxying, then there really isn't anything
1070                  *  to do.
1071                  *
1072                  *  If we ARE proxying, then we can safely sleep
1073                  *  forever if we're told to NEVER send proxy retries
1074                  *  ourselves, until the NAS kicks us again.
1075                  * 
1076                  *  Otherwise, there are no outstanding requests, then
1077                  *  we can sleep forever.  This happens when we get
1078                  *  woken up with a bad packet.  It's discarded, so if
1079                  *  there are no live requests, we can safely sleep
1080                  *  forever.
1081                  */
1082                 if ((!mainconfig.proxy_requests) ||
1083                     mainconfig.proxy_synchronous ||
1084                     (rl_num_requests() == 0)) {
1085                         DEBUG2("Nothing to do.  Sleeping until we see a request.");
1086                         last_tv_ptr = NULL;
1087                         return NULL;
1088                 }
1089
1090                 /*
1091                  *  We ARE proxying.  In that case, we avoid a race condition
1092                  *  where a child thread handling a request proxies the
1093                  *  packet, and sets the retry delay.  In that case, we're
1094                  *  supposed to wake up in N seconds, but we can't, as
1095                  *  we're sleeping forever.
1096                  *
1097                  *  Instead, we prevent the problem by waking up anyhow
1098                  *  at the 'proxy_retry_delay' time, even if there's
1099                  *  nothing to do.  In the worst case, this will cause
1100                  *  the server to wake up every N seconds, to do a small
1101                  *  amount of unnecessary work.
1102                  */
1103                 info.smallest = mainconfig.proxy_retry_delay;
1104         }
1105         /*
1106          *  Set the time (in seconds) for how long we're
1107          *  supposed to sleep.
1108          */
1109         tv.tv_sec = info.smallest;
1110         tv.tv_usec = 0;
1111         DEBUG2("Waking up in %d seconds...", (int) info.smallest);
1112
1113         /*
1114          *  Remember how long we should sleep for.
1115          */
1116         last_tv = tv;
1117         last_tv_ptr = &last_tv;
1118         return last_tv_ptr;
1119 }
1120
1121