2 * request_list.c Hide the handling of the REQUEST list from
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.
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.
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
21 * Copyright 2003-2004 The FreeRADIUS server project
23 static const char rcsid[] = "$Id$";
26 #include "libradius.h"
32 #include "rad_assert.h"
33 #include "request_list.h"
34 #include "radius_snmp.h"
38 * We keep the incoming requests in an array, indexed by ID.
40 * Each array element contains a linked list of containers of
41 * active requests, a count of the number of requests, and a time
42 * at which the first request in the list must be serviced.
44 * Note that we ALSO keep a tree view of the same data, below.
45 * Both views are needed for the server to work optimally.
47 typedef struct REQNODE {
48 struct REQNODE *prev, *next;
52 typedef struct REQUESTINFO {
53 REQNODE *first_request;
54 REQNODE *last_request;
56 time_t last_cleaned_list;
59 static REQUESTINFO request_list[256];
62 * Remember the next request at which we start walking
65 static REQUEST *last_request = NULL;
68 * It MAY make more sense here to key off of the packet ID, just
69 * like the request_list. Then again, saving another 8 lookups
70 * (on average) isn't much of a problem.
72 * The "request_cmp" function keys off of the packet ID first,
73 * so the first 8 layers of the tree will be the fanned-out
74 * tree for packet ID's.
76 static rbtree_t *request_tree;
79 static pthread_mutex_t proxy_mutex;
82 * This is easier than ifdef's throughout the code.
84 #define pthread_mutex_lock(_x)
85 #define pthread_mutex_unlock(_x)
89 * We keep track of packets we're proxying, keyed by
90 * source socket, and destination ip/port, and Id.
92 static rbtree_t *proxy_tree;
95 * We keep track of free/used Id's, by destination ip/port.
97 * We need a different tree than above, because this one is NOT
98 * keyed by Id. Instead, we use this one to allocate Id's.
100 static rbtree_t *proxy_id_tree;
103 * We keep the proxy FD's here. The RADIUS Id's are marked
104 * "allocated" per Id, via a bit per proxy FD.
106 static int proxy_fds[32];
108 static uint32_t proxy_ipaddr;
111 * We can use 256 RADIUS Id's per dst ipaddr/port, per server
112 * socket. So, to allocate them, we key off of dst ipaddr/port,
113 * and then search the RADIUS Id's, looking for an unused socket.
115 * We do NOT key off of socket fd's, here, either. Instead,
116 * we look for a free Id from a sockfd, any sockfd.
118 typedef struct proxy_id_t {
123 * FIXME: Allocate more proxy sockets when this gets full.
126 uint32_t mask; /* of FD's we know about. */
127 uint32_t id[1]; /* really id[256] */
132 * Find a matching entry in the proxy ID tree.
134 static int proxy_id_cmp(const void *one, const void *two)
136 const proxy_id_t *a = one;
137 const proxy_id_t *b = two;
140 * The following comparisons look weird, but it's
141 * the only way to make the comparisons work.
143 if (a->dst_ipaddr < b->dst_ipaddr) return -1;
144 if (a->dst_ipaddr > b->dst_ipaddr) return +1;
146 if (a->dst_port < b->dst_port) return -1;
147 if (a->dst_port > b->dst_port) return +1;
150 * Everything's equal. Say so.
157 * Compare two REQUEST data structures, based on a number
160 static int request_cmp(const void *one, const void *two)
162 const REQUEST *a = one;
163 const REQUEST *b = two;
166 * The following comparisons look weird, but it's
167 * the only way to make the comparisons work.
171 * If the packets didn't arrive on the same socket,
172 * they're not identical, no matter what their src/dst
175 if (a->packet->sockfd < b->packet->sockfd) return -1;
176 if (a->packet->sockfd > b->packet->sockfd) return +1;
178 if (a->packet->id < b->packet->id) return -1;
179 if (a->packet->id > b->packet->id) return +1;
181 if (a->packet->code < b->packet->code) return -1;
182 if (a->packet->code > b->packet->code) return +1;
184 if (a->packet->src_ipaddr < b->packet->src_ipaddr) return -1;
185 if (a->packet->src_ipaddr > b->packet->src_ipaddr) return +1;
187 if (a->packet->src_port < b->packet->src_port) return -1;
188 if (a->packet->src_port > b->packet->src_port) return +1;
191 * Hmm... we may be listening on IPADDR_ANY, in which case
192 * the destination IP is important, too.
194 if (a->packet->dst_ipaddr < b->packet->dst_ipaddr) return -1;
195 if (a->packet->dst_ipaddr > b->packet->dst_ipaddr) return +1;
197 if (a->packet->dst_port < b->packet->dst_port) return -1;
198 if (a->packet->dst_port > b->packet->dst_port) return +1;
201 * Everything's equal. Say so.
207 * Compare two REQUEST data structures, based on a number
208 * of criteria, for proxied packets.
210 static int proxy_cmp(const void *one, const void *two)
212 const REQUEST *a = one;
213 const REQUEST *b = two;
215 rad_assert(a->magic == REQUEST_MAGIC);
216 rad_assert(b->magic == REQUEST_MAGIC);
218 rad_assert(a->proxy != NULL);
219 rad_assert(b->proxy != NULL);
222 * The following code looks unreasonable, but it's
223 * the only way to make the comparisons work.
225 if (a->proxy->sockfd < b->proxy->sockfd) return -1;
226 if (a->proxy->sockfd > b->proxy->sockfd) return +1;
228 if (a->proxy->id < b->proxy->id) return -1;
229 if (a->proxy->id > b->proxy->id) return +1;
232 * We've got to check packet codes, too. But
233 * this should be done later, by someone else...
236 if (a->proxy->dst_ipaddr < b->proxy->dst_ipaddr) return -1;
237 if (a->proxy->dst_ipaddr > b->proxy->dst_ipaddr) return +1;
239 if (a->proxy->dst_port < b->proxy->dst_port) return -1;
240 if (a->proxy->dst_port > b->proxy->dst_port) return +1;
243 * FIXME: Check the Proxy-State attribute, too.
244 * This will help cut down on duplicates.
248 * Everything's equal. Say so.
255 rbtree_free(request_tree);
256 rbtree_free(proxy_id_tree);
257 rbtree_free(proxy_tree);
262 * Initialize the request list.
267 * Initialize the request_list[] array.
269 memset(request_list, 0, sizeof(request_list));
271 request_tree = rbtree_create(request_cmp, NULL, 0);
273 rad_assert("FAIL" == NULL);
277 * Create the tree for managing proxied requests and
280 proxy_tree = rbtree_create(proxy_cmp, NULL, 1);
282 rad_assert("FAIL" == NULL);
286 * Create the tree for allocating proxy ID's.
288 proxy_id_tree = rbtree_create(proxy_id_cmp, NULL, 0);
289 if (!proxy_id_tree) {
290 rad_assert("FAIL" == NULL);
293 #ifdef HAVE_PTHREAD_H
295 * For now, always create the mutex.
297 * Later, we can only create it if there are multiple threads.
299 if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
300 radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
307 * The Id allocation table is done by bits, so we have
308 * 32 bits per Id. These bits indicate which entry
309 * in the proxy_fds array is used for that Id.
311 * This design allows 256*32 = 8k requests to be
312 * outstanding to a home server, before something goes
317 rad_listen_t *listener;
320 * Mark the Fd's as unused.
322 for (i = 0; i < 32; i++) proxy_fds[i] = -1;
324 for (listener = mainconfig.listen;
326 listener = listener->next) {
327 if (listener->type == RAD_LISTEN_PROXY) {
328 proxy_ipaddr = listener->ipaddr;
329 proxy_fds[listener->fd & 0x1f] = listener->fd;
340 * Delete a request from the proxy trees.
342 static void rl_delete_proxy(REQUEST *request, rbnode_t *node)
344 proxy_id_t myid, *entry;
346 rad_assert(node != NULL);
348 rbtree_delete(proxy_tree, node);
350 myid.dst_ipaddr = request->proxy->dst_ipaddr;
351 myid.dst_port = request->proxy->dst_port;
354 * Find the Id in the array of allocated Id's,
357 entry = rbtree_finddata(proxy_id_tree, &myid);
361 DEBUG3(" proxy: de-allocating %08x:%d %d",
367 * Find the proxy socket associated with this
368 * Id. We loop over all 32 proxy fd's, but we
369 * partially index by proxy fd's, which means
370 * that we almost always break out of the loop
373 for (i = 0; i < 32; i++) {
376 offset = (request->proxy->sockfd + i) & 0x1f;
378 if (proxy_fds[offset] == request->proxy->sockfd) {
380 entry->id[request->proxy->id] &= ~(1 << offset);
383 } /* else die horribly? */
386 * Hmm... not sure what to do here.
388 DEBUG3(" proxy: FAILED TO FIND %08x:%d %d",
397 * Delete a particular request.
399 void rl_delete(REQUEST *request)
402 REQNODE *prev, *next;
404 prev = ((REQNODE *) request->container)->prev;
405 next = ((REQNODE *) request->container)->next;
407 id = request->packet->id;
410 * Update the last request we touched.
412 * This is so the periodic "walk & clean list"
413 * function, below, doesn't walk over all requests
414 * all of the time. Rather, it tries to amortize
417 if (last_request == request) {
418 last_request = rl_next(last_request);
423 request_list[id].first_request = next;
429 request_list[id].last_request = prev;
434 free(request->container);
438 * Update the SNMP statistics.
440 * Note that we do NOT do this in rad_respond(),
441 * as that function is called from child threads.
442 * Instead, we update the stats when a request is
443 * deleted, because only the main server thread calls
446 if (mainconfig.do_snmp) {
447 switch (request->reply->code) {
448 case PW_AUTHENTICATION_ACK:
449 rad_snmp.auth.total_responses++;
450 rad_snmp.auth.total_access_accepts++;
453 case PW_AUTHENTICATION_REJECT:
454 rad_snmp.auth.total_responses++;
455 rad_snmp.auth.total_access_rejects++;
458 case PW_ACCESS_CHALLENGE:
459 rad_snmp.auth.total_responses++;
460 rad_snmp.auth.total_access_challenges++;
463 case PW_ACCOUNTING_RESPONSE:
464 rad_snmp.acct.total_responses++;
474 * Delete the request from the tree.
479 node = rbtree_find(request_tree, request);
480 rad_assert(node != NULL);
481 rbtree_delete(request_tree, node);
485 * If there's a proxied packet, and we're still
486 * waiting for a reply, then delete the packet
487 * from the list of outstanding proxied requests.
489 if (request->proxy &&
490 (request->proxy_outstanding > 0)) {
491 pthread_mutex_lock(&proxy_mutex);
492 node = rbtree_find(proxy_tree, request);
493 rl_delete_proxy(request, node);
494 pthread_mutex_unlock(&proxy_mutex);
498 request_free(&request);
499 request_list[id].request_count--;
504 * Add a request to the request list.
506 void rl_add(REQUEST *request)
508 int id = request->packet->id;
511 rad_assert(request->container == NULL);
513 request->container = rad_malloc(sizeof(REQNODE));
514 node = (REQNODE *) request->container;
520 if (!request_list[id].first_request) {
521 rad_assert(request_list[id].request_count == 0);
523 request_list[id].first_request = node;
524 request_list[id].last_request = node;
526 rad_assert(request_list[id].request_count != 0);
528 node->prev = request_list[id].last_request;
529 request_list[id].last_request->next = node;
530 request_list[id].last_request = node;
534 * Insert the request into the tree.
536 if (rbtree_insert(request_tree, request) == 0) {
537 rad_assert("FAIL" == NULL);
540 request_list[id].request_count++;
544 * Look up a particular request, using:
546 * Request ID, request code, source IP, source port,
548 * Note that we do NOT use the request vector to look up requests.
550 * We MUST NOT have two requests with identical (id/code/IP/port), and
551 * different vectors. This is a serious error!
553 REQUEST *rl_find(RADIUS_PACKET *packet)
557 myrequest.packet = packet;
559 return rbtree_finddata(request_tree, &myrequest);
565 extern int proxy_new_listener(void);
568 * Add an entry to the proxy tree.
570 * This is the ONLY function in this source file which may be called
571 * from a child thread. It therefore needs mutexes...
573 int rl_add_proxy(REQUEST *request)
577 proxy_id_t myid, *entry;
579 myid.dst_ipaddr = request->proxy->dst_ipaddr;
580 myid.dst_port = request->proxy->dst_port;
583 * Proxied requests get sent out the proxy FD ONLY.
585 * FIXME: Once we allocate multiple proxy FD's, move this
586 * code to below, so we can have more than 256 requests
589 request->proxy_outstanding = 1;
591 pthread_mutex_lock(&proxy_mutex);
596 entry = rbtree_finddata(proxy_id_tree, &myid);
597 if (!entry) { /* allocate it */
598 entry = rad_malloc(sizeof(*entry) + sizeof(entry->id) * 255);
600 entry->dst_ipaddr = request->proxy->dst_ipaddr;
601 entry->dst_port = request->proxy->dst_port;
604 DEBUG3(" proxy: creating %08x:%d",
609 * Insert the new home server entry into
612 * FIXME: We don't (currently) delete the
613 * entries, so this is technically a
616 if (rbtree_insert(proxy_id_tree, entry) == 0) {
617 DEBUG2("ERROR: Failed to insert entry into proxy Id tree");
623 * Clear out bits in the array which DO have
624 * proxy Fd's associated with them. We do this
625 * by getting the mask of bits which have proxy
628 for (i = 0; i < 32; i++) {
629 if (proxy_fds[i] != -1) {
633 rad_assert(mask != 0);
636 * Set bits here indicate that the Fd is in use.
643 * Set the bits which are unused (and therefore
644 * allocated). The clear bits indicate that the Id
645 * for that FD is unused.
647 for (i = 0; i < 256; i++) {
650 } /* else the entry already existed in the proxy Id tree */
654 * Try to find a free Id.
657 for (i = 0; i < 256; i++) {
659 * Some bits are still zero..
661 if (entry->id[(i + entry->index) & 0xff] != (uint32_t) ~0) {
662 found = (i + entry->index) & 0xff;
667 * Hmm... do we want to re-use Id's, when we
668 * haven't seen all of the responses?
673 * No free Id, try to get a new FD.
677 * First, see if there were FD's recently allocated,
678 * which we don't know about.
681 for (i = 0; i < 32; i++) {
682 if (proxy_fds[i] < 0) continue;
688 * There ARE more FD's than we know about.
689 * Update the masks for Id's, and re-try.
691 if (entry->mask != mask) {
693 * New mask always has more bits than
694 * the old one, but never fewer bits.
696 rad_assert((entry->mask & mask) == entry->mask);
699 * Clear the bits we already know about,
700 * and then or in those bits into the
708 * Clear the bits in the Id's for the new
711 for (i = 0; i < 256; i++) {
712 entry->id[i] &= mask;
716 * And try again to allocate an Id.
719 } /* else no new Fd's were allocated. */
722 * If all Fd's are allocated, die.
725 radlog(L_ERR|L_CONS, "ERROR: More than 8000 proxied requests outstanding for home server %08x:%d",
726 ntohs(entry->dst_ipaddr), entry->dst_port);
731 * Allocate a new proxy Fd. This function adds it
732 * into the list of listeners.
734 proxy = proxy_new_listener();
736 DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
744 for (i = 0; i < 32; i++) {
746 * Found a free entry. Save the socket,
747 * and remember where we saved it.
749 if (proxy_fds[(proxy + i) & 0x1f] == -1) {
750 proxy_fds[(proxy + i) & 0x1f] = proxy;
751 found = (proxy + i) & 0x1f;
755 rad_assert(found >= 0); /* i.e. the mask had free bits. */
762 * Clear the relevant bits in the mask.
764 for (i = 0; i < 256; i++) {
765 entry->id[i] &= mask;
769 * Pick a random Id to start from, as we've
770 * just guaranteed that it's free.
772 found = lrad_rand() & 0xff;
776 * Mark next (hopefully unused) entry.
778 entry->index = (found + 1) & 0xff;
781 * We now have to find WHICH proxy fd to use.
784 for (i = 0; i < 32; i++) {
786 * FIXME: pick a random socket to use?
788 if ((entry->id[found] & (1 << i)) == 0) {
795 * There was no bit clear, which we had just checked above...
797 rad_assert(proxy != -1);
800 * Mark the Id as allocated, for thei Fd.
802 entry->id[found] |= (1 << proxy);
803 request->proxy->id = found;
804 request->proxy->src_ipaddr = proxy_ipaddr;
806 rad_assert(proxy_fds[proxy] != -1);
807 request->proxy->sockfd = proxy_fds[proxy];
809 DEBUG3(" proxy: allocating %08x:%d %d",
814 if (!rbtree_insert(proxy_tree, request)) {
815 DEBUG2("ERROR: Failed to insert entry into proxy tree");
819 pthread_mutex_unlock(&proxy_mutex);
826 * Look up a particular request, using:
828 * Request Id, request code, source IP, source port,
830 * Note that we do NOT use the request vector to look up requests.
832 * We MUST NOT have two requests with identical (id/code/IP/port), and
833 * different vectors. This is a serious error!
835 REQUEST *rl_find_proxy(RADIUS_PACKET *packet)
838 REQUEST myrequest, *maybe = NULL;
839 RADIUS_PACKET myproxy;
842 * If we use the socket FD as an indicator,
843 * then that implicitely contains information
844 * as to our src ipaddr/port, so we don't need
845 * to use that in the comparisons.
847 myproxy.sockfd = packet->sockfd;
848 myproxy.id = packet->id;
849 myproxy.dst_ipaddr = packet->src_ipaddr;
850 myproxy.dst_port = packet->src_port;
853 myrequest.magic = REQUEST_MAGIC;
855 myrequest.proxy = &myproxy;
857 pthread_mutex_lock(&proxy_mutex);
858 node = rbtree_find(proxy_tree, &myrequest);
861 maybe = rbtree_node2data(proxy_tree, node);
862 rad_assert(maybe->proxy_outstanding > 0);
863 maybe->proxy_outstanding--;
866 * Received all of the replies we expect.
867 * delete it from both trees.
869 if (maybe->proxy_outstanding == 0) {
870 rl_delete_proxy(&myrequest, node);
873 pthread_mutex_unlock(&proxy_mutex);
880 * Walk over all requests, performing a callback for each request.
882 int rl_walk(RL_WALK_FUNC walker, void *data)
885 REQNODE *curreq, *next;
888 * Walk over all 256 ID's.
890 for (id = 0; id < 256; id++) {
893 * Walk over the request list for each ID.
895 for (curreq = request_list[id].first_request;
899 * The callback MIGHT delete the current
900 * request, so we CANNOT depend on curreq->next
901 * to be there, when going to the next element
906 rcode = walker(curreq->req, data);
907 if (rcode != RL_WALK_CONTINUE) {
918 * Walk from one request to the next.
920 REQUEST *rl_next(REQUEST *request)
926 * If we were passed a request, then go to the "next" one.
928 if (request != NULL) {
929 rad_assert(request->magic == REQUEST_MAGIC);
932 * It has a "next", return it.
934 if (((REQNODE *)request->container)->next != NULL) {
935 return ((REQNODE *)request->container)->next->req;
938 * No "next", increment the ID, and look
941 start_id = request->packet->id + 1;
947 * No input request, start looking at ID 0.
954 * Check all ID's, wrapping around at 255.
956 for (id = start_id; id < (start_id + count); id++) {
959 * This ID has a request, return it.
961 if (request_list[id & 0xff].first_request != NULL) {
962 rad_assert(request_list[id&0xff].first_request->req != request);
964 return request_list[id & 0xff].first_request->req;
969 * No requests at all in the list. Nothing to do.
971 DEBUG3("rl_next: returning NULL");
977 * Return the number of requests in the request list.
979 int rl_num_requests(void)
982 int request_count = 0;
984 for (id = 0; id < 256; id++) {
985 request_count += request_list[id].request_count;
988 return request_count;
992 typedef struct rl_walk_t {
999 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
1000 * max_request_time, etc.
1002 * When walking over the request list, all of the per-request
1003 * magic is done here.
1005 static int refresh_request(REQUEST *request, void *data)
1007 rl_walk_t *info = (rl_walk_t *) data;
1009 child_pid_t child_pid;
1011 rad_assert(request->magic == REQUEST_MAGIC);
1014 * If the request is marked as a delayed reject, AND it's
1015 * time to send the reject, then do so now.
1017 if (request->finished &&
1018 ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0)) {
1019 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
1021 difference = info->now - request->timestamp;
1022 if (difference >= (time_t) mainconfig.reject_delay) {
1025 * Clear the 'delayed reject' bit, so that we
1026 * don't do this again.
1028 request->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
1029 rad_send(request->reply, request->packet,
1035 * If the request has finished processing, AND it's child has
1036 * been cleaned up, AND it's time to clean up the request,
1037 * OR, it's an accounting request. THEN, go delete it.
1039 * If this is a request which had the "don't cache" option
1040 * set, then delete it immediately, as it CANNOT have a
1043 if (request->finished &&
1044 ((request->timestamp + mainconfig.cleanup_delay <= info->now) ||
1045 ((request->options & RAD_REQUEST_OPTION_DONT_CACHE) != 0))) {
1046 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
1049 * Request completed, delete it, and unlink it
1050 * from the currently 'alive' list of requests.
1052 DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
1053 request->number, request->packet->id,
1054 (unsigned long) request->timestamp);
1057 * Delete the request.
1060 return RL_WALK_CONTINUE;
1064 * Maybe the child process handling the request has hung:
1065 * kill it, and continue.
1067 if ((request->timestamp + mainconfig.max_request_time) <= info->now) {
1070 child_pid = request->child_pid;
1071 number = request->number;
1074 * There MUST be a RAD_PACKET reply.
1076 rad_assert(request->reply != NULL);
1079 * If we've tried to proxy the request, and
1080 * the proxy server hasn't responded, then
1081 * we send a REJECT back to the caller.
1083 * For safety, we assert that there is no child
1084 * handling the request. If the assertion fails,
1085 * it means that we've sent a proxied request to
1086 * the home server, and the child thread is still
1087 * sitting on the request!
1089 if (request->proxy && !request->proxy_reply) {
1090 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
1092 radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s:%d",
1094 client_name(request->packet->src_ipaddr),
1095 request->packet->src_port);
1096 request_reject(request);
1097 request->finished = TRUE;
1098 return RL_WALK_CONTINUE;
1101 if (mainconfig.kill_unresponsive_children) {
1102 if (child_pid != NO_SUCH_CHILD_PID) {
1104 * This request seems to have hung
1107 #ifdef HAVE_PTHREAD_H
1108 radlog(L_ERR, "Killing unresponsive thread for request %d",
1110 pthread_cancel(child_pid);
1112 } /* else no proxy reply, quietly fail */
1115 * Maybe we haven't killed it. In that
1116 * case, print a warning.
1118 } else if ((child_pid != NO_SUCH_CHILD_PID) &&
1119 ((request->options & RAD_REQUEST_OPTION_LOGGED_CHILD) == 0)) {
1120 radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d",
1121 (unsigned long)child_pid, number);
1124 * Set the option that we've sent a log message,
1125 * so that we don't send more than one message
1128 request->options |= RAD_REQUEST_OPTION_LOGGED_CHILD;
1132 * Send a reject message for the request, mark it
1133 * finished, and forget about the child.
1135 request_reject(request);
1136 request->child_pid = NO_SUCH_CHILD_PID;
1137 if (mainconfig.kill_unresponsive_children)
1138 request->finished = TRUE;
1139 return RL_WALK_CONTINUE;
1140 } /* the request has been in the queue for too long */
1143 * If the request is still being processed, then due to the
1144 * above check, it's still within it's time limit. In that
1145 * case, don't do anything.
1147 if (request->child_pid != NO_SUCH_CHILD_PID) {
1148 return RL_WALK_CONTINUE;
1152 * The request is finished.
1154 if (request->finished) goto setup_timeout;
1157 * We're not proxying requests at all.
1159 if (!mainconfig.proxy_requests) goto setup_timeout;
1162 * We're proxying synchronously, so we don't retry it here.
1163 * Some other code takes care of retrying the proxy requests.
1165 if (mainconfig.proxy_synchronous) goto setup_timeout;
1168 * The proxy retry delay is zero, meaning don't retry.
1170 if (mainconfig.proxy_retry_delay == 0) goto setup_timeout;
1173 * There is no proxied request for this packet, so there's
1176 if (!request->proxy) goto setup_timeout;
1179 * We've already seen the proxy reply, so we don't need
1180 * to send another proxy request.
1182 if (request->proxy_reply) goto setup_timeout;
1185 * It's not yet time to re-send this proxied request.
1187 if (request->proxy_next_try > info->now) goto setup_timeout;
1190 * If the proxy retry count is zero, then
1191 * we've sent the last try, and have NOT received
1192 * a reply from the end server. In that case,
1193 * we don't bother trying again, but just mark
1194 * the request as finished, and go to the next one.
1196 if (request->proxy_try_count == 0) {
1197 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
1198 request_reject(request);
1199 realm_disable(request->proxy->dst_ipaddr,request->proxy->dst_port);
1200 request->finished = TRUE;
1205 * We're trying one more time, so count down
1206 * the tries, and set the next try time.
1208 request->proxy_try_count--;
1209 request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
1211 /* Fix up Acct-Delay-Time */
1212 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
1213 VALUE_PAIR *delaypair;
1214 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
1217 delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
1219 radlog(L_ERR|L_CONS, "no memory");
1222 pairadd(&request->proxy->vps, delaypair);
1224 delaypair->lvalue = info->now - request->proxy->timestamp;
1226 /* Must recompile the valuepairs to wire format */
1227 free(request->proxy->data);
1228 request->proxy->data = NULL;
1229 } /* proxy accounting request */
1232 * Assert that we have NOT seen the proxy reply yet.
1234 * If we HAVE seen it, then we SHOULD NOT be bugging the
1237 rad_assert(request->proxy_reply == NULL);
1240 * Send the proxy packet.
1242 request->proxy_outstanding++;
1243 rad_send(request->proxy, NULL, request->proxysecret);
1247 * Don't do more long-term checks, if we've got to wake
1250 if (info->smallest == 0) {
1251 return RL_WALK_CONTINUE;
1255 * The request is finished. Wake up when it's time to
1258 if (request->finished) {
1259 difference = (request->timestamp + mainconfig.cleanup_delay) - info->now;
1262 * If the request is marked up to be rejected later,
1263 * then wake up later.
1265 if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0) {
1266 if (difference >= (time_t) mainconfig.reject_delay) {
1267 difference = (time_t) mainconfig.reject_delay;
1271 } else if (request->proxy && !request->proxy_reply) {
1273 * The request is NOT finished, but there is an
1274 * outstanding proxy request, with no matching
1277 * Wake up when it's time to re-send
1278 * the proxy request.
1280 * But in synchronous proxy, we don't retry but we update
1281 * the next retry time as NAS has not resent the request
1282 * in the given retry window.
1284 if (mainconfig.proxy_synchronous) {
1286 * If the retry_delay * count has passed,
1287 * then mark the realm dead.
1289 if (info->now > (request->timestamp + (mainconfig.proxy_retry_delay * mainconfig.proxy_retry_count))) {
1290 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
1291 request_reject(request);
1293 realm_disable(request->proxy->dst_ipaddr,
1294 request->proxy->dst_port);
1295 request->finished = TRUE;
1298 request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
1300 difference = request->proxy_next_try - info->now;
1303 * The request is NOT finished.
1305 * Wake up when it's time to kill the errant
1308 difference = (request->timestamp + mainconfig.max_request_time) - info->now;
1312 * If the server is CPU starved, then we CAN miss a time
1313 * for servicing requests. In which case the 'difference'
1314 * value will be negative. select() doesn't like that,
1317 if (difference < 0) {
1322 * Update the 'smallest' time.
1324 if ((info->smallest < 0) ||
1325 (difference < info->smallest)) {
1326 info->smallest = difference;
1329 return RL_WALK_CONTINUE;
1334 * Clean up the request list, every so often.
1336 * This is done by walking through ALL of the list, and
1337 * - marking any requests which are finished, and expired
1338 * - killing any processes which are NOT finished after a delay
1339 * - deleting any marked requests.
1341 struct timeval *rl_clean_list(time_t now)
1344 * Static variables, so that we don't do all of this work
1345 * more than once per second.
1347 * Note that we have 'tv' and 'last_tv'. 'last_tv' is
1348 * pointed to by 'last_tv_ptr', and depending on the
1349 * system implementation of select(), it MAY be modified.
1351 * In that was, we want to use the ORIGINAL value, from
1352 * 'tv', and wipe out the (possibly modified) last_tv.
1354 static time_t last_cleaned_list = 0;
1355 static struct timeval tv, *last_tv_ptr = NULL;
1356 static struct timeval last_tv;
1364 * If we've already set up the timeout or cleaned the
1365 * request list this second, then don't do it again. We
1366 * simply return the sleep delay from last time.
1368 * Note that if we returned NULL last time, there was nothing
1369 * to do. BUT we've been woken up since then, which can only
1370 * happen if we received a packet. And if we've received a
1371 * packet, then there's some work to do in the future.
1373 * FIXME: We can probably use gettimeofday() for finer clock
1374 * resolution, as the current method will cause it to sleep
1377 if ((last_tv_ptr != NULL) &&
1378 (last_cleaned_list == now) &&
1383 * If we're NOT walking the entire request list,
1384 * then we want to iteratively check the request
1387 * If there is NO previous request, go look for one.
1390 last_request = rl_next(last_request);
1393 * On average, there will be one request per
1394 * 'cleanup_delay' requests, which needs to be
1397 * And only do this servicing, if we have a request
1401 for (i = 0; i < mainconfig.cleanup_delay; i++) {
1405 * This function call MAY delete the
1406 * request pointed to by 'last_request'.
1408 next = rl_next(last_request);
1409 refresh_request(last_request, &info);
1410 last_request = next;
1413 * Nothing to do any more, exit.
1420 DEBUG2("Waking up in %d seconds...",
1421 (int) last_tv_ptr->tv_sec);
1424 last_cleaned_list = now;
1425 last_request = NULL;
1426 DEBUG2("--- Walking the entire request list ---");
1429 * Hmmm... this is Big Magic. We make it seem like
1430 * there's an additional second to wait, for a whole
1431 * host of reasons which I can't explain adequately,
1432 * but which cause the code to Just Work Right.
1436 rl_walk(refresh_request, &info);
1439 * We haven't found a time at which we need to wake up.
1440 * Return NULL, so that the select() call will sleep forever.
1442 if (info.smallest < 0) {
1444 * If we're not proxying, then there really isn't anything
1447 * If we ARE proxying, then we can safely sleep
1448 * forever if we're told to NEVER send proxy retries
1449 * ourselves, until the NAS kicks us again.
1451 * Otherwise, there are no outstanding requests, then
1452 * we can sleep forever. This happens when we get
1453 * woken up with a bad packet. It's discarded, so if
1454 * there are no live requests, we can safely sleep
1457 if ((!mainconfig.proxy_requests) ||
1458 mainconfig.proxy_synchronous ||
1459 (rl_num_requests() == 0)) {
1460 DEBUG2("Nothing to do. Sleeping until we see a request.");
1466 * We ARE proxying. In that case, we avoid a race condition
1467 * where a child thread handling a request proxies the
1468 * packet, and sets the retry delay. In that case, we're
1469 * supposed to wake up in N seconds, but we can't, as
1470 * we're sleeping forever.
1472 * Instead, we prevent the problem by waking up anyhow
1473 * at the 'proxy_retry_delay' time, even if there's
1474 * nothing to do. In the worst case, this will cause
1475 * the server to wake up every N seconds, to do a small
1476 * amount of unnecessary work.
1478 info.smallest = mainconfig.proxy_retry_delay;
1481 * Set the time (in seconds) for how long we're
1482 * supposed to sleep.
1484 tv.tv_sec = info.smallest;
1486 DEBUG2("Waking up in %d seconds...", (int) info.smallest);
1489 * Remember how long we should sleep for.
1492 last_tv_ptr = &last_tv;