4f9d731fa3b258f23ae1013dc77a1598894839dd
[freeradius.git] / src / main / event.c
1 /*
2  * event.c      Server event handling
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2007  The FreeRADIUS server project
21  * Copyright 2007  Alan DeKok <aland@deployingradius.com>
22  */
23
24 #include <freeradius-devel/ident.h>
25 RCSID("$Id$")
26
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/event.h>
30 #include <freeradius-devel/radius_snmp.h>
31
32 #include <freeradius-devel/rad_assert.h>
33
34 #include <signal.h>
35 #include <fcntl.h>
36
37 #ifdef HAVE_SYS_WAIT_H
38 #       include <sys/wait.h>
39 #endif
40
41 #define USEC (1000000)
42
43 extern pid_t radius_pid;
44 extern int dont_fork;
45
46
47 /*
48  *      Ridiculous amounts of local state.
49  */
50 static lrad_event_list_t        *el = NULL;
51 static lrad_packet_list_t       *pl = NULL;
52 static int                      request_num_counter = 0;
53 static struct timeval           now;
54 static time_t                   start_time;
55 static int                      have_children;
56 static int                      has_detail_listener = FALSE;
57 static int                      read_from_detail = TRUE;
58
59 static int self_pipe[2];
60
61 #ifdef HAVE_PTHREAD_H
62 static pthread_mutex_t  proxy_mutex;
63
64 #define PTHREAD_MUTEX_LOCK if (have_children) pthread_mutex_lock
65 #define PTHREAD_MUTEX_UNLOCK if (have_children) pthread_mutex_unlock
66 #else
67 /*
68  *      This is easier than ifdef's throughout the code.
69  */
70 #define PTHREAD_MUTEX_LOCK(_x)
71 #define PTHREAD_MUTEX_UNLOCK(_x)
72 #endif
73
74 #define INSERT_EVENT(_function, _ctx) if (!lrad_event_insert(el, _function, _ctx, &((_ctx)->when), &((_ctx)->ev))) { _rad_panic(__FILE__, __LINE__, "Failed to insert event"); }
75
76 static lrad_packet_list_t *proxy_list = NULL;
77
78 /*
79  *      We keep the proxy FD's here.  The RADIUS Id's are marked
80  *      "allocated" per Id, via a bit per proxy FD.
81  */
82 static int              proxy_fds[32];
83 static rad_listen_t     *proxy_listeners[32];
84
85 static void request_post_handler(REQUEST *request);
86 static void wait_a_bit(void *ctx);
87 static void event_poll_fd(void *ctx);
88
89 static void NEVER_RETURNS _rad_panic(const char *file, unsigned int line,
90                                     const char *msg)
91 {
92         radlog(L_ERR, "]%s:%d] %s", file, line, msg);
93         _exit(1);
94 }
95
96 #define rad_panic(x) _rad_panic(__FILE__, __LINE__, x)
97
98
99 static void tv_add(struct timeval *tv, int usec_delay)
100 {
101         if (usec_delay > USEC) {
102                 tv->tv_sec += usec_delay / USEC;
103                 usec_delay %= USEC;
104         }
105         tv->tv_usec += usec_delay;
106
107         if (tv->tv_usec > USEC) {
108                 tv->tv_usec -= USEC;
109                 tv->tv_sec++;
110         }
111 }
112
113 static VALUE_PAIR * radius_pairmake(REQUEST *request, VALUE_PAIR **vps,
114                                    const char *attribute, const char *value)
115 {
116         VALUE_PAIR *vp;
117
118         request = request;      /* -Wunused */
119
120         vp = pairmake(attribute, value, T_OP_SET);
121         if (!vp) {
122                 radlog(L_ERR, "No memory!");
123                 rad_assert("No memory" == NULL);
124                 _exit(1);
125         }
126
127         pairadd(vps, vp);
128
129         return vp;
130 }
131
132 #ifdef WITH_SNMP
133 static void snmp_inc_counters(REQUEST *request)
134 {
135         if (!request->root->do_snmp) return;
136
137         if (request->master_state == REQUEST_COUNTED) return;
138
139         if ((request->listener->type != RAD_LISTEN_AUTH) &&
140             (request->listener->type != RAD_LISTEN_ACCT)) return;
141
142         /*
143          *      Update the SNMP statistics.
144          *
145          *      Note that we do NOT do this in a child thread.
146          *      Instead, we update the stats when a request is
147          *      deleted, because only the main server thread calls
148          *      this function, which makes it thread-safe.
149          */
150         switch (request->reply->code) {
151         case PW_AUTHENTICATION_ACK:
152                 rad_snmp.auth.total_responses++;
153                 rad_snmp.auth.total_access_accepts++;
154                 if (request->client) request->client->auth->accepts++;
155                 break;
156
157         case PW_AUTHENTICATION_REJECT:
158                 rad_snmp.auth.total_responses++;
159                 rad_snmp.auth.total_access_rejects++;
160                 if (request->client) request->client->auth->rejects++;
161                 break;
162
163         case PW_ACCESS_CHALLENGE:
164                 rad_snmp.auth.total_responses++;
165                 rad_snmp.auth.total_access_challenges++;
166                 if (request->client) request->client->auth->challenges++;
167                 break;
168
169         case PW_ACCOUNTING_RESPONSE:
170                 rad_snmp.acct.total_responses++;
171                 if (request->client) request->client->auth->responses++;
172                 break;
173
174                 /*
175                  *      No response, it must have been a bad
176                  *      authenticator.
177                  */
178         case 0:
179                 if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
180                         rad_snmp.auth.total_bad_authenticators++;
181                         if (request->client) request->client->auth->bad_authenticators++;
182                 }
183                 break;
184
185         default:
186                 break;
187         }
188
189         request->master_state = REQUEST_COUNTED;
190 }
191 #else
192 #define snmp_inc_counters(_x)
193 #endif
194
195
196 static void remove_from_request_hash(REQUEST *request)
197 {
198         if (!request->in_request_hash) return;
199
200         lrad_packet_list_yank(pl, request->packet);
201         request->in_request_hash = FALSE;
202
203         snmp_inc_counters(request);
204 }
205
206
207 static REQUEST *lookup_in_proxy_hash(RADIUS_PACKET *reply)
208 {
209         RADIUS_PACKET **proxy_p;
210         REQUEST *request;
211
212         PTHREAD_MUTEX_LOCK(&proxy_mutex);
213         proxy_p = lrad_packet_list_find_byreply(proxy_list, reply);
214
215         if (!proxy_p) {
216                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
217                 return NULL;
218         }
219
220         request = lrad_packet2myptr(REQUEST, proxy, proxy_p);
221
222         if (!request) {
223                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
224                 return NULL;
225         }
226
227         request->num_proxied_responses++;
228
229         /*
230          *      Catch the most common case of everything working
231          *      correctly.
232          */
233         if (request->num_proxied_requests == request->num_proxied_responses) {
234                 lrad_packet_list_yank(proxy_list, request->proxy);
235                 lrad_packet_list_id_free(proxy_list, request->proxy);
236                 request->in_proxy_hash = FALSE;
237         }
238
239         /*
240          *      On the FIRST reply, decrement the count of outstanding
241          *      requests.  Note that this is NOT the count of sent
242          *      packets, but whether or not the home server has
243          *      responded at all.
244          */
245         if (!request->proxy_reply &&
246             request->home_server->currently_outstanding) {
247                 request->home_server->currently_outstanding--;
248         }
249
250         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
251
252         return request;
253 }
254
255
256 static void remove_from_proxy_hash(REQUEST *request)
257 {
258         if (!request->in_proxy_hash) return;
259
260         PTHREAD_MUTEX_LOCK(&proxy_mutex);
261         lrad_packet_list_yank(proxy_list, request->proxy);
262         lrad_packet_list_id_free(proxy_list, request->proxy);
263
264         /*
265          *      The home server hasn't replied, but we've given up on
266          *      this request.  Don't count this request against the
267          *      home server.
268          */
269         if (!request->proxy_reply &&
270             request->home_server->currently_outstanding) {
271                 request->home_server->currently_outstanding--;
272         }
273
274         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
275
276         request->in_proxy_hash = FALSE;
277 }
278
279
280 static int insert_into_proxy_hash(REQUEST *request)
281 {
282         int i, proxy;
283         char buf[128];
284
285         rad_assert(request->proxy != NULL);
286         rad_assert(proxy_list != NULL);
287
288         request->proxy->sockfd = -1;
289
290         PTHREAD_MUTEX_LOCK(&proxy_mutex);
291
292         request->home_server->currently_outstanding++;
293         request->home_server->total_requests_sent++;
294
295         /*
296          *      On overflow, back up to ~0.
297          */
298         if (!request->home_server->total_requests_sent) {
299                 request->home_server->total_requests_sent--;
300         }
301
302         if (!lrad_packet_list_id_alloc(proxy_list, request->proxy)) {
303                 int found;
304                 rad_listen_t *proxy_listener;
305
306                 /*
307                  *      Allocate a new proxy fd.  This function adds it
308                  *      into the list of listeners.
309                  *
310                  *      FIXME!: Call event_fd_insert()!  Otherwise this
311                  *      FD will never be used in select()!
312                  *
313                  *      We probably want to add RADIUS_SIGNAL_SELF_FD,
314                  *      which tells us to walk over the listeners,
315                  *      adding a new FD.
316                  *
317                  *      Hmm... maybe do this for the detail file, too.
318                  *      that will simplify some of the rest of the code.
319                  */
320                 proxy_listener = proxy_new_listener();
321                 if (!proxy_listener) {
322                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
323                         DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
324                         return 0;
325                 }
326
327                 /*
328                  *      Cache it locally.
329                  */
330                 found = -1;
331                 proxy = proxy_listener->fd;
332                 for (i = 0; i < 32; i++) {
333                         DEBUG2("PROXY %d %d", i, proxy_fds[(proxy + i) & 0x1f]);
334
335                         /*
336                          *      Found a free entry.  Save the socket,
337                          *      and remember where we saved it.
338                          */
339                         if (proxy_fds[(proxy + i) & 0x1f] == -1) {
340                                 found = (proxy + i) & 0x1f;
341                                 proxy_fds[found] = proxy;
342                                 proxy_listeners[found] = proxy_listener;
343                                 break;
344                         }
345                 }
346                 rad_assert(found >= 0);
347
348                 if (!lrad_packet_list_socket_add(proxy_list, proxy_listener->fd)) {
349                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
350                         DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
351                         return 0; /* leak proxy_listener */
352
353                 }
354
355                 if (!lrad_packet_list_id_alloc(proxy_list, request->proxy)) {
356                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
357                         DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
358                         return 0;
359                 }
360         }
361         rad_assert(request->proxy->sockfd >= 0);
362
363         /*
364          *      FIXME: Hack until we get rid of rad_listen_t, and put
365          *      the information into the packet_list.
366          */
367         proxy = -1;
368         for (i = 0; i < 32; i++) {
369                 if (proxy_fds[i] == request->proxy->sockfd) {
370                         proxy = i;
371                         break;
372                 }
373         }
374
375         if (proxy < 0) {
376                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
377                 DEBUG2("ERROR: All sockets are full.");
378                 return 0;
379         }
380
381         rad_assert(proxy_fds[proxy] != -1);
382         rad_assert(proxy_listeners[proxy] != NULL);
383         request->proxy_listener = proxy_listeners[proxy];
384
385         if (!lrad_packet_list_insert(proxy_list, &request->proxy)) {
386                 lrad_packet_list_id_free(proxy_list, request->proxy);
387                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
388                 DEBUG2("ERROR: Failed to insert entry into proxy list");
389                 return 0;
390         }
391
392         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
393
394         DEBUG3(" proxy: allocating destination %s port %d - Id %d",
395                inet_ntop(request->proxy->dst_ipaddr.af,
396                          &request->proxy->dst_ipaddr.ipaddr, buf, sizeof(buf)),
397                request->proxy->dst_port,
398                request->proxy->id);
399
400         request->in_proxy_hash = TRUE;
401
402         return 1;
403 }
404
405
406 /*
407  *      Called as BOTH an event, and in-line from other functions.
408  */
409 static void wait_for_proxy_id_to_expire(void *ctx)
410 {
411         REQUEST *request = ctx;
412         home_server *home = request->home_server;
413
414         rad_assert(request->magic == REQUEST_MAGIC);
415         rad_assert(request->proxy != NULL);
416
417         request->when = request->proxy_when;
418         request->when.tv_sec += home->response_window;
419
420         if ((request->num_proxied_requests == request->num_proxied_responses) ||
421             timercmp(&now, &request->when, >)) {
422                 if (request->packet) {
423                         DEBUG2("Cleaning up request %d ID %d with timestamp +%d",
424                                request->number, request->packet->id,
425                                (unsigned int) (request->timestamp - start_time));
426                 } else {
427                         DEBUG2("Cleaning up request %d with timestamp +%d",
428                                request->number,
429                                (unsigned int) (request->timestamp - start_time));
430                 }
431                 lrad_event_delete(el, &request->ev);
432                 remove_from_proxy_hash(request);
433                 remove_from_request_hash(request);
434                 request_free(&request);
435                 return;
436         }
437
438         INSERT_EVENT(wait_for_proxy_id_to_expire, request);
439 }
440
441
442 static void wait_for_child_to_die(void *ctx)
443 {
444         REQUEST *request = ctx;
445
446         rad_assert(request->magic == REQUEST_MAGIC);
447
448         if ((request->child_state == REQUEST_QUEUED) |
449             (request->child_state == REQUEST_RUNNING)) {
450                 request->delay += (request->delay >> 1);
451                 tv_add(&request->when, request->delay);
452
453                 DEBUG2("Child is still stuck for request %d", request->number);
454
455                 INSERT_EVENT(wait_for_child_to_die, request);
456                 return;
457         }
458
459         DEBUG2("Child is finally responsive for request %d", request->number);
460         remove_from_request_hash(request);
461
462         if (request->proxy) {
463                 wait_for_proxy_id_to_expire(request);
464                 return;
465         }
466
467         request_free(&request);
468 }
469
470
471 static void cleanup_delay(void *ctx)
472 {
473         REQUEST *request = ctx;
474
475         rad_assert(request->magic == REQUEST_MAGIC);
476         rad_assert((request->child_state == REQUEST_CLEANUP_DELAY) ||
477                    (request->child_state == REQUEST_DONE));
478
479         remove_from_request_hash(request);
480
481         if (request->proxy && request->in_proxy_hash) {
482                 wait_for_proxy_id_to_expire(request);
483                 return;
484         }
485
486         DEBUG2("Cleaning up request %d ID %d with timestamp +%d",
487                request->number, request->packet->id,
488                (unsigned int) (request->timestamp - start_time));
489
490         lrad_event_delete(el, &request->ev);
491         request_free(&request);
492 }
493
494
495 static void reject_delay(void *ctx)
496 {
497         REQUEST *request = ctx;
498
499         rad_assert(request->magic == REQUEST_MAGIC);
500         rad_assert(request->child_state == REQUEST_REJECT_DELAY);
501
502         DEBUG2("Sending delayed reject for request %d", request->number);
503
504         request->listener->send(request->listener, request);
505
506         request->when.tv_sec += request->root->cleanup_delay;
507         request->child_state = REQUEST_CLEANUP_DELAY;
508
509         INSERT_EVENT(cleanup_delay, request);
510 }
511
512
513 static void revive_home_server(void *ctx)
514 {
515         home_server *home = ctx;
516
517         home->state = HOME_STATE_ALIVE;
518         DEBUG2("Marking home server alive again... we have no idea if it really is alive or not.");
519         home->currently_outstanding = 0;
520 }
521
522
523 static void no_response_to_ping(void *ctx)
524 {
525         REQUEST *request = ctx;
526         home_server *home = request->home_server;
527         char buffer[128];
528
529         home->num_received_pings = 0;
530
531         DEBUG2("No response to status check %d from home server %s port %d",
532                request->number,
533                inet_ntop(request->proxy->dst_ipaddr.af,
534                          &request->proxy->dst_ipaddr.ipaddr,
535                          buffer, sizeof(buffer)),
536                request->proxy->dst_port);
537
538         wait_for_proxy_id_to_expire(request);
539 }
540
541
542 static void received_response_to_ping(REQUEST *request)
543 {
544         home_server *home = request->home_server;
545         char buffer[128];
546
547         home->num_received_pings++;
548
549         DEBUG2("Received response to status check %d (%d in current sequence)",
550                request->number, home->num_received_pings);
551
552         if (home->num_received_pings < home->num_pings_to_alive) {
553                 wait_for_proxy_id_to_expire(request);
554                 return;
555         }
556
557         DEBUG2("Marking home server %s port %d alive",
558                inet_ntop(request->proxy->dst_ipaddr.af,
559                          &request->proxy->dst_ipaddr.ipaddr,
560                          buffer, sizeof(buffer)),
561                request->proxy->dst_port);
562
563         if (!lrad_event_delete(el, &home->ev)) {
564                 DEBUG2("Hmm... no event for home server, WTF?");
565         }
566
567         if (!lrad_event_delete(el, &request->ev)) {
568                 DEBUG2("Hmm... no event for request, WTF?");
569         }
570
571         wait_for_proxy_id_to_expire(request);
572
573         home->state = HOME_STATE_ALIVE;
574         home->currently_outstanding = 0;
575 }
576
577
578 static void ping_home_server(void *ctx)
579 {
580         uint32_t jitter;
581         home_server *home = ctx;
582         REQUEST *request;
583         VALUE_PAIR *vp;
584
585         if (home->state == HOME_STATE_ALIVE) {
586                 radlog(L_INFO, "Suspicious proxy state... continuing");
587                 return;
588         }
589
590         request = request_alloc();
591         request->number = request_num_counter++;
592
593         request->proxy = rad_alloc(1);
594         rad_assert(request->proxy != NULL);
595
596         gettimeofday(&request->when, NULL);
597         home->when = request->when;
598
599         if (home->ping_check == HOME_PING_CHECK_STATUS_SERVER) {
600                 request->proxy->code = PW_STATUS_SERVER;
601
602                 radius_pairmake(request, &request->proxy->vps,
603                                 "Message-Authenticator", "0x00");
604
605         } else if (home->type == HOME_TYPE_AUTH) {
606                 request->proxy->code = PW_AUTHENTICATION_REQUEST;
607
608                 radius_pairmake(request, &request->proxy->vps,
609                                 "User-Name", home->ping_user_name);
610                 radius_pairmake(request, &request->proxy->vps,
611                                 "User-Password", home->ping_user_password);
612                 radius_pairmake(request, &request->proxy->vps,
613                                 "Service-Type", "Authenticate-Only");
614                 radius_pairmake(request, &request->proxy->vps,
615                                 "Message-Authenticator", "0x00");
616
617         } else {
618                 request->proxy->code = PW_ACCOUNTING_REQUEST;
619                 
620                 radius_pairmake(request, &request->proxy->vps,
621                                 "User-Name", home->ping_user_name);
622                 radius_pairmake(request, &request->proxy->vps,
623                                 "Acct-Status-Type", "Stop");
624                 radius_pairmake(request, &request->proxy->vps,
625                                 "Acct-Session-Id", "00000000");
626                 vp = radius_pairmake(request, &request->proxy->vps,
627                                      "Event-Timestamp", "0");
628                 vp->vp_date = now.tv_sec;
629         }
630
631         radius_pairmake(request, &request->proxy->vps,
632                         "NAS-Identifier", "Status Check. Are you alive?");
633
634         request->proxy->dst_ipaddr = home->ipaddr;
635         request->proxy->dst_port = home->port;
636         request->home_server = home;
637
638         rad_assert(request->proxy_listener == NULL);
639
640         if (!insert_into_proxy_hash(request)) {
641                 DEBUG2("Failed inserting status check %d into proxy hash.  Discarding it.",
642                        request->number);
643                 request_free(&request);
644                 return;
645         }
646         rad_assert(request->proxy_listener != NULL);
647         request->proxy_listener->send(request->proxy_listener,
648                                       request);
649
650         request->next_callback = NULL;
651         request->child_state = REQUEST_PROXIED;
652         request->when.tv_sec += home->ping_timeout;;
653
654         INSERT_EVENT(no_response_to_ping, request);
655
656         /*
657          *      Add +/- 2s of jitter, as suggested in RFC 3539
658          *      and in the Issues and Fixes draft.
659          */
660         home->when.tv_sec += home->ping_interval - 2;
661
662         jitter = lrad_rand();
663         jitter ^= (jitter >> 10);
664         jitter &= ((1 << 23) - 1); /* 22 bits of 1 */
665
666         tv_add(&home->when, jitter);
667
668
669         INSERT_EVENT(ping_home_server, home);
670 }
671
672
673 static void check_for_zombie_home_server(REQUEST *request)
674 {
675         home_server *home;
676         struct timeval when;
677         char buffer[128];
678
679         home = request->home_server;
680
681         if (home->state != HOME_STATE_ZOMBIE) return;
682
683         when = home->zombie_period_start;
684         when.tv_sec += home->zombie_period;
685
686         if (timercmp(&now, &when, <)) {
687                 return;
688         }
689
690         /*
691          *      It's been a zombie for too long, mark it as
692          *      dead.
693          */
694         DEBUG2("FAILURE: Marking home server %s port %d as dead.",
695                inet_ntop(request->proxy->dst_ipaddr.af,
696                          &request->proxy->dst_ipaddr.ipaddr,
697                          buffer, sizeof(buffer)),
698                request->proxy->dst_port);
699         home->state = HOME_STATE_IS_DEAD;
700         home->num_received_pings = 0;
701         home->when = request->when;
702
703         if (home->ping_check != HOME_PING_CHECK_NONE) {
704                 rad_assert((home->ping_check == HOME_PING_CHECK_STATUS_SERVER) ||
705                            (home->ping_user_name != NULL));
706                 home->when.tv_sec += home->ping_interval;
707
708                 INSERT_EVENT(ping_home_server, home);
709         } else {
710                 home->when.tv_sec += home->revive_interval;
711
712                 INSERT_EVENT(revive_home_server, home);
713         }
714 }
715
716
717 static int setup_post_proxy_fail(REQUEST *request)
718 {
719         DICT_VALUE *dval = NULL;
720         VALUE_PAIR *vp;
721
722         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
723                 dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Authentication");
724
725         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
726                 dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Accounting");
727
728         } else {
729                 return 0;
730         }
731
732         if (!dval) dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail");
733
734         if (!dval) {
735                 pairdelete(&request->config_items, PW_POST_PROXY_TYPE);
736                 return 0;
737         }
738
739         vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
740         if (!vp) vp = radius_paircreate(request, &request->config_items,
741                                         PW_POST_PROXY_TYPE, PW_TYPE_INTEGER);
742         vp->vp_integer = dval->value;
743
744         rad_assert(request->proxy_reply == NULL);
745
746         return 1;
747 }
748
749
750 static int null_handler(UNUSED REQUEST *request)
751 {
752         return 0;
753 }
754
755 static void post_proxy_fail_handler(REQUEST *request)
756 {
757         /*
758          *      Not set up to run Post-Proxy-Type = Fail.
759          *
760          *      Mark the request as still running, and figure out what
761          *      to do next.
762          */
763         if (!setup_post_proxy_fail(request)) {
764                 request->child_state = REQUEST_RUNNING;
765                 request_post_handler(request);
766                 wait_a_bit(request);
767
768         } else {
769                 /*
770                  *      Re-queue the request.
771                  */
772                 request->child_state = REQUEST_QUEUED;
773
774                 wait_a_bit(request);
775
776                 /*
777                  *      There is a post-proxy-type of fail.  We run
778                  *      the request through the pre/post proxy
779                  *      handlers, just like it was a real proxied
780                  *      request.  However, we set the per-request
781                  *      handler to NULL, as we don't want to do
782                  *      anything else.
783                  */
784                 request->priority = 0;
785                 rad_assert(request->proxy != NULL);
786                 thread_pool_addrequest(request, null_handler);
787         }
788 }
789
790
791 /* maybe check this against wait_for_proxy_id_to_expire? */
792 static void no_response_to_proxied_request(void *ctx)
793 {
794         REQUEST *request = ctx;
795         home_server *home;
796         char buffer[128];
797
798         rad_assert(request->magic == REQUEST_MAGIC);
799         rad_assert(request->child_state == REQUEST_PROXIED);
800
801         radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s port %d",
802                request->number,
803                inet_ntop(request->proxy->dst_ipaddr.af,
804                          &request->proxy->dst_ipaddr.ipaddr,
805                          buffer, sizeof(buffer)),
806                request->proxy->dst_port);
807
808         check_for_zombie_home_server(request);
809
810         home = request->home_server;
811
812         post_proxy_fail_handler(request);
813
814         /*
815          *      Don't touch request due to race conditions
816          */
817         if (home->state == HOME_STATE_IS_DEAD) {
818                 rad_assert(home->ev != NULL); /* or it will never wake up */
819                 return;
820         }
821
822         /*
823          *      Enable the zombie period when we notice that the home
824          *      server hasn't responded.  We also back-date the start
825          *      of the zombie period to when the proxied request was
826          *      sent.
827          */
828         if (home->state == HOME_STATE_ALIVE) {
829                 DEBUG2("WARNING: Marking home server %s port %d as zombie (it looks like it is dead).",
830                        inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
831                                  buffer, sizeof(buffer)),
832                        home->port);
833                 home->state = HOME_STATE_ZOMBIE;
834                 home->zombie_period_start = now;
835                 home->zombie_period_start.tv_sec -= home->response_window;
836                 return;
837         }
838 }
839
840
841 static void wait_a_bit(void *ctx)
842 {
843         struct timeval when;
844         REQUEST *request = ctx;
845         lrad_event_callback_t callback = NULL;
846
847         rad_assert(request->magic == REQUEST_MAGIC);
848
849         switch (request->child_state) {
850         case REQUEST_QUEUED:
851         case REQUEST_RUNNING:
852                 when = request->received;
853                 when.tv_sec += request->root->max_request_time;
854
855                 if (timercmp(&now, &when, <)) {
856                         callback = wait_a_bit;
857                 } else {
858                         /* FIXME: kill unresponsive children? */
859                         radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d, in module %s component %s",
860                                (unsigned long)request->child_pid, request->number,
861                                request->module ? request->module : "<server core>",
862                                request->component ? request->component : "<server core>");
863
864                         request->master_state = REQUEST_STOP_PROCESSING;
865
866                         request->delay = USEC / 2;
867                         tv_add(&request->when, request->delay);
868                         callback = wait_for_child_to_die;
869                 }
870                 request->delay += request->delay >> 1;
871                 break;
872
873         case REQUEST_REJECT_DELAY:
874         case REQUEST_CLEANUP_DELAY:
875                 request->child_pid = NO_SUCH_CHILD_PID;
876                 snmp_inc_counters(request);
877
878         case REQUEST_PROXIED:
879                 rad_assert(request->next_callback != NULL);
880                 rad_assert(request->next_callback != wait_a_bit);
881
882                 request->when = request->next_when;
883                 callback = request->next_callback;
884                 request->next_callback = NULL;
885                 break;
886
887                 /*
888                  *      Mark the request as no longer running,
889                  *      and clean it up.
890                  */
891         case REQUEST_DONE:
892                 request->child_pid = NO_SUCH_CHILD_PID;
893                 snmp_inc_counters(request);
894                 cleanup_delay(request);
895                 return;
896
897         default:
898                 rad_panic("Internal sanity check failure");
899                 return;
900         }
901
902         INSERT_EVENT(callback, request);
903 }
904
905
906 static int request_pre_handler(REQUEST *request)
907 {
908         int rcode;
909
910         rad_assert(request->magic == REQUEST_MAGIC);
911         rad_assert(request->packet != NULL);
912         rad_assert(request->packet->dst_port != 0);
913
914         request->child_state = REQUEST_RUNNING;
915
916         /*
917          *      Don't decode the packet if it's an internal "fake"
918          *      request.  Instead, just return so that the caller can
919          *      process it.
920          */
921         if (request->packet->dst_port == 0) {
922                 request->username = pairfind(request->packet->vps,
923                                              PW_USER_NAME);
924                 request->password = pairfind(request->packet->vps,
925                                              PW_USER_PASSWORD);
926                 return 1;
927         }
928
929         /*
930          *      Put the decoded packet into it's proper place.
931          */
932         if (request->proxy_reply != NULL) {
933                 rcode = request->proxy_listener->decode(request->proxy_listener,
934                                                         request);
935         } else if (request->packet->vps == NULL) {
936                 rcode = request->listener->decode(request->listener, request);
937
938         } else {
939                 rcode = 0;
940         }
941
942         if (rcode < 0) {
943                 radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
944                 request->child_state = REQUEST_DONE;
945                 return 0;
946         }
947
948         if (!request->proxy) {
949                 request->username = pairfind(request->packet->vps,
950                                              PW_USER_NAME);
951
952         } else {
953                 int post_proxy_type = 0;
954                 VALUE_PAIR *vp;
955
956                 /*
957                  *      Delete any reply we had accumulated until now.
958                  */
959                 pairfree(&request->reply->vps);
960
961                 /*
962                  *      Run the packet through the post-proxy stage,
963                  *      BEFORE playing games with the attributes.
964                  */
965                 vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
966                 if (vp) {
967                         DEBUG2("  Found Post-Proxy-Type %s", vp->vp_strvalue);
968                         post_proxy_type = vp->vp_integer;
969                 }
970
971                 rad_assert(request->home_pool != NULL);
972
973                 if (request->home_pool->virtual_server) {
974                         const char *old_server = request->server;
975
976                         request->server = request->home_pool->virtual_server;
977                         DEBUG2(" server %s {", request->server);
978                         rcode = module_post_proxy(post_proxy_type, request);
979                         DEBUG2(" }");
980                         request->server = old_server;
981                 } else {
982                         rcode = module_post_proxy(post_proxy_type, request);
983                 }
984
985                 /*
986                  *      There may NOT be a proxy reply, as we may be
987                  *      running Post-Proxy-Type = Fail.
988                  */
989                 if (request->proxy_reply) {
990                         /*
991                          *      Delete the Proxy-State Attributes from
992                          *      the reply.  These include Proxy-State
993                          *      attributes from us and remote server.
994                          */
995                         pairdelete(&request->proxy_reply->vps, PW_PROXY_STATE);
996
997                         /*
998                          *      Add the attributes left in the proxy
999                          *      reply to the reply list.
1000                          */
1001                         pairadd(&request->reply->vps, request->proxy_reply->vps);
1002                         request->proxy_reply->vps = NULL;
1003
1004                         /*
1005                          *      Free proxy request pairs.
1006                          */
1007                         pairfree(&request->proxy->vps);
1008                 }
1009
1010                 switch (rcode) {
1011                 default:  /* Don't do anything */
1012                         break;
1013                 case RLM_MODULE_FAIL:
1014                         /* FIXME: debug print stuff */
1015                         request->child_state = REQUEST_DONE;
1016                         return 0;
1017
1018                 case RLM_MODULE_HANDLED:
1019                         /* FIXME: debug print stuff */
1020                         request->child_state = REQUEST_DONE;
1021                         return 0;
1022                 }
1023         }
1024
1025         return 1;
1026 }
1027
1028
1029 /*
1030  *      Do state handling when we proxy a request.
1031  */
1032 static int proxy_request(REQUEST *request)
1033 {
1034         struct timeval when;
1035         char buffer[128];
1036
1037         if (!insert_into_proxy_hash(request)) {
1038                 DEBUG("Error: Failed inserting request into proxy hash.");
1039                 return 0;
1040         }
1041
1042         request->proxy_listener->encode(request->proxy_listener, request);
1043
1044         when = request->received;
1045         when.tv_sec += request->root->max_request_time;
1046
1047         gettimeofday(&request->proxy_when, NULL);
1048
1049         request->next_when = request->proxy_when;
1050         request->next_when.tv_sec += request->home_server->response_window;
1051
1052         rad_assert(request->home_server->response_window > 0);
1053
1054         if (timercmp(&when, &request->next_when, <)) {
1055                 request->next_when = when;
1056         }
1057         request->next_callback = no_response_to_proxied_request;
1058
1059         DEBUG2("Proxying request %d to home server %s port %d",
1060                request->number,
1061                inet_ntop(request->proxy->dst_ipaddr.af,
1062                          &request->proxy->dst_ipaddr.ipaddr,
1063                          buffer, sizeof(buffer)),
1064                request->proxy->dst_port);
1065
1066         /*
1067          *      Note that we set proxied BEFORE sending the packet.
1068          *
1069          *      Once we send it, the request is tainted, as
1070          *      another thread may have picked it up.  Don't
1071          *      touch it!
1072          */
1073         request->num_proxied_requests = 1;
1074         request->num_proxied_responses = 0;
1075         request->child_pid = NO_SUCH_CHILD_PID;
1076         request->child_state = REQUEST_PROXIED;
1077         request->proxy_listener->send(request->proxy_listener,
1078                                       request);
1079         return 1;
1080 }
1081
1082 /*
1083  *      Return 1 if we did proxy it, or the proxy attempt failed
1084  *      completely.  Either way, the caller doesn't touch the request
1085  *      any more if we return 1.
1086  */
1087 static int successfully_proxied_request(REQUEST *request)
1088 {
1089         int rcode;
1090         int pre_proxy_type = 0;
1091         VALUE_PAIR *realmpair;
1092         VALUE_PAIR *strippedname;
1093         VALUE_PAIR *vp;
1094         char *realmname;
1095         home_server *home;
1096         REALM *realm = NULL;
1097         home_pool_t *pool;
1098
1099         realmpair = pairfind(request->config_items, PW_PROXY_TO_REALM);
1100         if (!realmpair || (realmpair->length == 0)) {
1101                 return 0;
1102         }
1103
1104         realmname = (char *) realmpair->vp_strvalue;
1105
1106         realm = realm_find(realmname);
1107         if (!realm) {
1108                 DEBUG2("ERROR: Cannot proxy to unknown realm %s", realmname);
1109                 return 0;
1110         }
1111
1112         /*
1113          *      Figure out which pool to use.
1114          */
1115         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
1116                 pool = realm->auth_pool;
1117
1118         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1119                 pool = realm->acct_pool;
1120
1121         } else {
1122                 rad_panic("Internal sanity check failed");
1123         }
1124
1125         if (!pool) {
1126                 DEBUG2(" WARNING: Cancelling proxy to Realm %s, as the realm is local.",
1127                        realmname);
1128                 return 0;
1129         }
1130
1131         home = home_server_ldb(realmname, pool, request);
1132         if (!home) {
1133                 DEBUG2("ERROR: Failed to find live home server for realm %s",
1134                        realmname);
1135                 return -1;
1136         }
1137         request->home_pool = pool;
1138
1139         /*
1140          *      Remember that we sent the request to a Realm.
1141          */
1142         pairadd(&request->packet->vps,
1143                 pairmake("Realm", realmname, T_OP_EQ));
1144
1145         /*
1146          *      We read the packet from a detail file, AND it came from
1147          *      the server we're about to send it to.  Don't do that.
1148          */
1149         if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
1150             (request->listener->type == RAD_LISTEN_DETAIL) &&
1151             (home->ipaddr.af == AF_INET) &&
1152             (request->packet->src_ipaddr.af == AF_INET) &&
1153             (home->ipaddr.ipaddr.ip4addr.s_addr == request->packet->src_ipaddr.ipaddr.ip4addr.s_addr)) {
1154                 DEBUG2("    rlm_realm: Packet came from realm %s, proxy cancelled", realmname);
1155                 return 0;
1156         }
1157
1158         /*
1159          *      Allocate the proxy packet, only if it wasn't already
1160          *      allocated by a module.  This check is mainly to support
1161          *      the proxying of EAP-TTLS and EAP-PEAP tunneled requests.
1162          *
1163          *      In those cases, the EAP module creates a "fake"
1164          *      request, and recursively passes it through the
1165          *      authentication stage of the server.  The module then
1166          *      checks if the request was supposed to be proxied, and
1167          *      if so, creates a proxy packet from the TUNNELED request,
1168          *      and not from the EAP request outside of the tunnel.
1169          *
1170          *      The proxy then works like normal, except that the response
1171          *      packet is "eaten" by the EAP module, and encapsulated into
1172          *      an EAP packet.
1173          */
1174         if (!request->proxy) {
1175                 if ((request->proxy = rad_alloc(TRUE)) == NULL) {
1176                         radlog(L_ERR|L_CONS, "no memory");
1177                         exit(1);
1178                 }
1179
1180                 /*
1181                  *      Copy the request, then look up name and
1182                  *      plain-text password in the copy.
1183                  *
1184                  *      Note that the User-Name attribute is the
1185                  *      *original* as sent over by the client.  The
1186                  *      Stripped-User-Name attribute is the one hacked
1187                  *      through the 'hints' file.
1188                  */
1189                 request->proxy->vps =  paircopy(request->packet->vps);
1190         }
1191
1192         /*
1193          *      Strip the name, if told to.
1194          *
1195          *      Doing it here catches the case of proxied tunneled
1196          *      requests.
1197          */
1198         if (realm->striprealm == TRUE &&
1199            (strippedname = pairfind(request->proxy->vps, PW_STRIPPED_USER_NAME)) != NULL) {
1200                 /*
1201                  *      If there's a Stripped-User-Name attribute in
1202                  *      the request, then use THAT as the User-Name
1203                  *      for the proxied request, instead of the
1204                  *      original name.
1205                  *
1206                  *      This is done by making a copy of the
1207                  *      Stripped-User-Name attribute, turning it into
1208                  *      a User-Name attribute, deleting the
1209                  *      Stripped-User-Name and User-Name attributes
1210                  *      from the vps list, and making the new
1211                  *      User-Name the head of the vps list.
1212                  */
1213                 vp = pairfind(request->proxy->vps, PW_USER_NAME);
1214                 if (!vp) {
1215                         vp = paircreate(PW_USER_NAME, PW_TYPE_STRING);
1216                         if (!vp) {
1217                                 radlog(L_ERR|L_CONS, "no memory");
1218                                 exit(1);
1219                         }
1220                         /* Insert at the START of the list */
1221                         vp->next = request->proxy->vps;
1222                         request->proxy->vps = vp;
1223                 }
1224                 memcpy(vp->vp_strvalue, strippedname->vp_strvalue,
1225                        sizeof(vp->vp_strvalue));
1226                 vp->length = strippedname->length;
1227
1228                 /*
1229                  *      Do NOT delete Stripped-User-Name.
1230                  */
1231         }
1232
1233         /*
1234          *      If there is no PW_CHAP_CHALLENGE attribute but
1235          *      there is a PW_CHAP_PASSWORD we need to add it
1236          *      since we can't use the request authenticator
1237          *      anymore - we changed it.
1238          */
1239         if (pairfind(request->proxy->vps, PW_CHAP_PASSWORD) &&
1240             pairfind(request->proxy->vps, PW_CHAP_CHALLENGE) == NULL) {
1241                 vp = radius_paircreate(request, &request->proxy->vps,
1242                                        PW_CHAP_CHALLENGE, PW_TYPE_OCTETS);
1243                 vp->length = AUTH_VECTOR_LEN;
1244                 memcpy(vp->vp_strvalue, request->packet->vector, AUTH_VECTOR_LEN);
1245         }
1246
1247         /*
1248          *      The RFC's say we have to do this, but FreeRADIUS
1249          *      doesn't need it.
1250          */
1251         vp = radius_paircreate(request, &request->proxy->vps,
1252                                PW_PROXY_STATE, PW_TYPE_OCTETS);
1253         sprintf(vp->vp_strvalue, "%d", request->packet->id);
1254         vp->length = strlen(vp->vp_strvalue);
1255
1256         /*
1257          *      Should be done BEFORE inserting into proxy hash, as
1258          *      pre-proxy may use this information, or change it.
1259          */
1260         request->proxy->code = request->packet->code;
1261         request->proxy->dst_ipaddr = home->ipaddr;
1262         request->proxy->dst_port = home->port;
1263         request->home_server = home;
1264
1265         /*
1266          *      Call the pre-proxy routines.
1267          */
1268         vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE);
1269         if (vp) {
1270                 DEBUG2("  Found Pre-Proxy-Type %s", vp->vp_strvalue);
1271                 pre_proxy_type = vp->vp_integer;
1272         }
1273
1274         rad_assert(request->home_pool != NULL);
1275
1276         if (request->home_pool->virtual_server) {
1277                 const char *old_server = request->server;
1278                 
1279                 request->server = request->home_pool->virtual_server;
1280                 DEBUG2(" server %s {", request->server);
1281                 rcode = module_pre_proxy(pre_proxy_type, request);
1282                 DEBUG2(" }");
1283                         request->server = old_server;
1284         } else {
1285                 rcode = module_pre_proxy(pre_proxy_type, request);
1286         }
1287         switch (rcode) {
1288         case RLM_MODULE_FAIL:
1289         case RLM_MODULE_INVALID:
1290         case RLM_MODULE_NOTFOUND:
1291         case RLM_MODULE_USERLOCK:
1292         default:
1293                 /* FIXME: debug print failed stuff */
1294                 return -1;
1295
1296         case RLM_MODULE_REJECT:
1297         case RLM_MODULE_HANDLED:
1298                 return 0;
1299
1300         /*
1301          *      Only proxy the packet if the pre-proxy code succeeded.
1302          */
1303         case RLM_MODULE_NOOP:
1304         case RLM_MODULE_OK:
1305         case RLM_MODULE_UPDATED:
1306                 break;
1307         }
1308
1309         /*
1310          *      If it's a fake request, don't send the proxy
1311          *      packet.  The outer tunnel session will take
1312          *      care of doing that.
1313          */
1314         if (request->packet->dst_port == 0) {
1315                 request->home_server = NULL;
1316                 return 1;
1317         }
1318
1319         if (!proxy_request(request)) {
1320                 DEBUG("ERROR: Failed to proxy request %d", request->number);
1321                 return -1;
1322         }
1323         
1324         return 1;
1325 }
1326
1327
1328 static void request_post_handler(REQUEST *request)
1329 {
1330         int child_state = -1;
1331         struct timeval when;
1332         VALUE_PAIR *vp;
1333
1334         if ((request->master_state == REQUEST_STOP_PROCESSING) ||
1335             (request->parent &&
1336              (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
1337                 DEBUG2("Request %d was cancelled.", request->number);
1338                 request->child_pid = NO_SUCH_CHILD_PID;
1339                 request->child_state = REQUEST_DONE;
1340                 return;
1341         }
1342
1343         if (request->child_state != REQUEST_RUNNING) {
1344                 rad_panic("Internal sanity check failed");
1345         }
1346
1347         if ((request->reply->code == 0) &&
1348             ((vp = pairfind(request->config_items, PW_AUTH_TYPE)) != NULL) &&
1349             (vp->vp_integer == PW_AUTHTYPE_REJECT)) {
1350                 request->reply->code = PW_AUTHENTICATION_REJECT;
1351         }
1352
1353         if (request->root->proxy_requests &&
1354             !request->proxy &&
1355             (request->reply->code == 0) &&
1356             (request->packet->code != PW_STATUS_SERVER)) {
1357                 int rcode = successfully_proxied_request(request);
1358
1359                 if (rcode == 1) return;
1360
1361                 /*
1362                  *      Failed proxying it (dead home servers, etc.)
1363                  *      Run it through Post-Proxy-Type = Fail, and
1364                  *      respond to the request.
1365                  *
1366                  *      Note that we're in a child thread here, so we
1367                  *      do NOT re-schedule the request.  Instead, we
1368                  *      do what we would have done, which is run the
1369                  *      pre-handler, a NULL request handler, and then
1370                  *      the post handler.
1371                  */
1372                 if ((rcode < 0) && setup_post_proxy_fail(request)) {
1373                         request_pre_handler(request);
1374                 }
1375
1376                 /*
1377                  *      Else we weren't supposed to proxy it.
1378                  */
1379         }
1380
1381         /*
1382          *      Fake requests don't get encoded or signed.  The caller
1383          *      also requires the reply VP's, so we don't free them
1384          *      here!
1385          */
1386         if (request->packet->dst_port == 0) {
1387                 /* FIXME: DEBUG going to the next request */
1388                 request->child_pid = NO_SUCH_CHILD_PID;
1389                 request->child_state = REQUEST_DONE;
1390                 return;
1391         }
1392
1393         /*
1394          *      Copy Proxy-State from the request to the reply.
1395          */
1396         vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1397         if (vp) pairadd(&request->reply->vps, vp);
1398
1399         /*
1400          *      Access-Requests get delayed or cached.
1401          */
1402         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
1403                 gettimeofday(&request->next_when, NULL);
1404
1405                 if (request->reply->code == 0) {
1406                         /*
1407                          *      Check if the lack of response is intentional.
1408                          */
1409                         vp = pairfind(request->config_items,
1410                                       PW_RESPONSE_PACKET_TYPE);
1411                         if (!vp || (vp->vp_integer != 256)) {
1412                                 DEBUG2("There was no response configured: rejecting request %d",
1413                                        request->number);
1414                                 request->reply->code = PW_AUTHENTICATION_REJECT;
1415                         } else {
1416                                 DEBUG2("Not responding to request %d",
1417                                        request->number);
1418                         }
1419                 }
1420
1421                 /*
1422                  *      Run rejected packets through
1423                  *
1424                  *      Post-Auth-Type = Reject
1425                  */
1426                 if (request->reply->code == PW_AUTHENTICATION_REJECT) {
1427                         vp = pairmake("Post-Auth-Type", "Reject", T_OP_SET);
1428                         if (vp) {
1429                                 pairdelete(&request->config_items, PW_POST_AUTH_TYPE);
1430                                 pairadd(&request->config_items, vp);
1431                                 rad_postauth(request);
1432                         } /* else no Reject section defined */
1433
1434                         /*
1435                          *      If configured, delay Access-Reject packets.
1436                          *
1437                          *      If request->root->reject_delay = 0, we discover
1438                          *      that we have to send the packet now.
1439                          */
1440                         when = request->received;
1441                         when.tv_sec += request->root->reject_delay;
1442
1443                         if (timercmp(&when, &request->next_when, >)) {
1444                                 DEBUG2("Delaying reject of request %d for %d seconds",
1445                                        request->number,
1446                                        request->root->reject_delay);
1447                                 request->next_when = when;
1448                                 request->next_callback = reject_delay;
1449                                 request->child_pid = NO_SUCH_CHILD_PID;
1450                                 request->child_state = REQUEST_REJECT_DELAY;
1451                                 return;
1452                         }
1453                 }
1454
1455                 request->next_when.tv_sec += request->root->cleanup_delay;
1456                 request->next_callback = cleanup_delay;
1457                 child_state = REQUEST_CLEANUP_DELAY;
1458
1459         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1460                 request->next_callback = NULL; /* just to be safe */
1461                 child_state = REQUEST_DONE;
1462
1463                 /*
1464                  *      FIXME: Status-Server should probably not be
1465                  *      handled here...
1466                  */
1467         } else if (request->packet->code == PW_STATUS_SERVER) {
1468                 request->next_callback = NULL;
1469                 child_state = REQUEST_DONE;
1470
1471         } else {
1472                 rad_panic("Unknown packet type");
1473         }
1474
1475         /*
1476          *      Suppress "no reply" packets here, unless we're reading
1477          *      from the "detail" file.  In that case, we've got to
1478          *      tell the detail file handler that the request is dead,
1479          *      and it should re-send it.
1480          *      If configured, encode, sign, and send.
1481          */
1482         if ((request->reply->code != 0) ||
1483             (request->listener->type == RAD_LISTEN_DETAIL)) {
1484                 request->listener->send(request->listener, request);
1485         }
1486
1487         /*
1488          *      Clean up.  These are no longer needed.
1489          */
1490         pairfree(&request->config_items);
1491
1492         pairfree(&request->packet->vps);
1493         request->username = NULL;
1494         request->password = NULL;
1495
1496         pairfree(&request->reply->vps);
1497
1498         if (request->proxy) {
1499                 pairfree(&request->proxy->vps);
1500
1501                 if (request->proxy_reply) {
1502                         pairfree(&request->proxy_reply->vps);
1503                 }
1504
1505                 /*
1506                  *      We're not tracking responses from the home
1507                  *      server, we can therefore free this memory in
1508                  *      the child thread.
1509                  */
1510                 if (!request->in_proxy_hash) {
1511                         rad_free(&request->proxy);
1512                         rad_free(&request->proxy_reply);
1513                         request->home_server = NULL;
1514                 }
1515         }
1516
1517         DEBUG2("Finished request %d.", request->number);
1518
1519         request->child_state = child_state;
1520 }
1521
1522
1523 static void received_retransmit(REQUEST *request, const RADCLIENT *client)
1524 {
1525         char buffer[128];
1526
1527         RAD_SNMP_TYPE_INC(request->listener, total_dup_requests);
1528         RAD_SNMP_CLIENT_INC(request->listener, client, dup_requests);
1529
1530         switch (request->child_state) {
1531         case REQUEST_QUEUED:
1532         case REQUEST_RUNNING:
1533         discard:
1534                 radlog(L_ERR, "Discarding duplicate request from "
1535                        "client %s port %d - ID: %d due to unfinished request %d",
1536                        client->shortname,
1537                        request->packet->src_port,request->packet->id,
1538                        request->number);
1539                 break;
1540
1541         case REQUEST_PROXIED:
1542                 /*
1543                  *      We're not supposed to have duplicate
1544                  *      accounting packets.  The other states handle
1545                  *      duplicates fine (discard, or send duplicate
1546                  *      reply).  But we do NOT want to retransmit an
1547                  *      accounting request here, because that would
1548                  *      involve updating the Acct-Delay-Time, and
1549                  *      therefore changing the packet Id, etc.
1550                  *
1551                  *      Instead, we just discard the packet.  We may
1552                  *      eventually respond, or the client will send a
1553                  *      new accounting packet.
1554                  */
1555                 if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1556                         goto discard;
1557                 }
1558
1559                 check_for_zombie_home_server(request);
1560
1561                 /*
1562                  *      If we've just discovered that the home server is
1563                  *      dead, send the packet to another one.
1564                  */
1565                 if ((request->packet->dst_port != 0) &&
1566                     (request->home_server->state == HOME_STATE_IS_DEAD)) {
1567                         home_server *home;
1568
1569                         remove_from_proxy_hash(request);
1570
1571                         home = home_server_ldb(NULL, request->home_pool, request);
1572                         if (!home) {
1573                                 DEBUG2("Failed to find live home server for request %d", request->number);
1574                         no_home_servers:
1575                                 /*
1576                                  *      Do post-request processing,
1577                                  *      and any insertion of necessary
1578                                  *      events.
1579                                  */
1580                                 post_proxy_fail_handler(request);
1581                                 return;
1582                         }
1583
1584                         request->proxy->code = request->packet->code;
1585                         request->proxy->dst_ipaddr = home->ipaddr;
1586                         request->proxy->dst_port = home->port;
1587                         request->home_server = home;
1588
1589                         /*
1590                          *      Free the old packet, to force re-encoding
1591                          */
1592                         free(request->proxy->data);
1593                         request->proxy->data = NULL;
1594                         request->proxy->data_len = 0;
1595
1596                         /*
1597                          *      Try to proxy the request.
1598                          */
1599                         if (!proxy_request(request)) {
1600                                 DEBUG("ERROR: Failed to re-proxy request %d", request->number);
1601                                 goto no_home_servers;
1602                         }
1603
1604                         /*
1605                          *      This code executes in the main server
1606                          *      thread, so there's no need for locking.
1607                          */
1608                         rad_assert(request->next_callback != NULL);
1609                         INSERT_EVENT(request->next_callback, request);
1610                         request->next_callback = NULL;
1611                         return;
1612                 } /* else the home server is still alive */
1613
1614                 DEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",
1615                        inet_ntop(request->proxy->dst_ipaddr.af,
1616                                  &request->proxy->dst_ipaddr.ipaddr,
1617                                  buffer, sizeof(buffer)),
1618                        request->proxy->dst_port,
1619                        request->proxy->id);
1620                 request->num_proxied_requests++;
1621                 request->proxy_listener->send(request->proxy_listener,
1622                                               request);
1623                 break;
1624
1625         case REQUEST_REJECT_DELAY:
1626                 DEBUG2("Waiting to send Access-Reject "
1627                        "to client %s port %d - ID: %d",
1628                        client->shortname,
1629                        request->packet->src_port, request->packet->id);
1630                 break;
1631
1632         case REQUEST_CLEANUP_DELAY:
1633         case REQUEST_DONE:
1634                 DEBUG2("Sending duplicate reply "
1635                        "to client %s port %d - ID: %d",
1636                        client->shortname,
1637                        request->packet->src_port, request->packet->id);
1638                 request->listener->send(request->listener, request);
1639                 break;
1640         }
1641 }
1642
1643
1644 static void received_conflicting_request(REQUEST *request,
1645                                          const RADCLIENT *client)
1646 {
1647         radlog(L_ERR, "Received conflicting packet from "
1648                "client %s port %d - ID: %d due to unfinished request %d.  Giving up on old request.",
1649                client->shortname,
1650                request->packet->src_port, request->packet->id,
1651                request->number);
1652
1653         /*
1654          *      Nuke it from the request hash, so we can receive new
1655          *      packets.
1656          */
1657         remove_from_request_hash(request);
1658
1659         switch (request->child_state) {
1660                 /*
1661                  *      It's queued or running.  Tell it to stop, and
1662                  *      wait for it to do so.
1663                  */
1664         case REQUEST_QUEUED:
1665         case REQUEST_RUNNING:
1666                 request->master_state = REQUEST_STOP_PROCESSING;
1667                 request->delay += request->delay >> 1;
1668
1669                 tv_add(&request->when, request->delay);
1670
1671                 INSERT_EVENT(wait_for_child_to_die, request);
1672                 return;
1673
1674                 /*
1675                  *      It's in some other state, and therefore also
1676                  *      in the event queue.  At some point, the
1677                  *      child will notice, and we can then delete it.
1678                  */
1679         default:
1680                 rad_assert(request->ev != NULL);
1681                 break;
1682         }
1683 }
1684
1685
1686 static int can_handle_new_request(RADIUS_PACKET *packet,
1687                                   RADCLIENT *client,
1688                                   struct main_config_t *root)
1689 {
1690         /*
1691          *      Count the total number of requests, to see if
1692          *      there are too many.  If so, return with an
1693          *      error.
1694          */
1695         if (root->max_requests) {
1696                 int request_count = lrad_packet_list_num_elements(pl);
1697
1698                 /*
1699                  *      This is a new request.  Let's see if
1700                  *      it makes us go over our configured
1701                  *      bounds.
1702                  */
1703                 if (request_count > root->max_requests) {
1704                         radlog(L_ERR, "Dropping request (%d is too many): "
1705                                "from client %s port %d - ID: %d", request_count,
1706                                client->shortname,
1707                                packet->src_port, packet->id);
1708                         radlog(L_INFO, "WARNING: Please check the %s file.\n"
1709                                "\tThe value for 'max_requests' is probably set too low.\n", root->radiusd_conf);
1710                         return 0;
1711                 } /* else there were a small number of requests */
1712         } /* else there was no configured limit for requests */
1713
1714         /*
1715          *      FIXME: Add per-client checks.  If one client is sending
1716          *      too many packets, start discarding them.
1717          *
1718          *      We increment the counters here, and decrement them
1719          *      when the response is sent... somewhere in this file.
1720          */
1721
1722         /*
1723          *      FUTURE: Add checks for system load.  If the system is
1724          *      busy, start dropping requests...
1725          *
1726          *      We can probably keep some statistics ourselves...  if
1727          *      there are more requests coming in than we can handle,
1728          *      start dropping some.
1729          */
1730
1731         return 1;
1732 }
1733
1734
1735 int received_request(rad_listen_t *listener,
1736                      RADIUS_PACKET *packet, REQUEST **prequest,
1737                      RADCLIENT *client)
1738 {
1739         RADIUS_PACKET **packet_p;
1740         REQUEST *request = NULL;
1741         struct main_config_t *root = &mainconfig;
1742
1743         packet_p = lrad_packet_list_find(pl, packet);
1744         if (packet_p) {
1745                 request = lrad_packet2myptr(REQUEST, packet, packet_p);
1746                 rad_assert(request->in_request_hash);
1747
1748                 if ((request->packet->data_len == packet->data_len) &&
1749                     (memcmp(request->packet->vector, packet->vector,
1750                             sizeof(packet->vector)) == 0)) {
1751                         received_retransmit(request, client);
1752                         return 0;
1753                 }
1754
1755                 /*
1756                  *      The new request is different from the old one,
1757                  *      but maybe the old is finished.  If so, delete
1758                  *      the old one.
1759                  */
1760                 switch (request->child_state) {
1761                         struct timeval when;
1762
1763                 default:
1764                         gettimeofday(&when, NULL);
1765                         when.tv_sec -= 1;
1766
1767                         /*
1768                          *      If the cached request was received
1769                          *      within the last second, then we
1770                          *      discard the NEW request instead of the
1771                          *      old one.  This will happen ONLY when
1772                          *      the client is severely broken, and is
1773                          *      sending conflicting packets very
1774                          *      quickly.
1775                          */
1776                         if (timercmp(&when, &request->received, <)) {
1777                                 radlog(L_ERR, "Discarding conflicting packet from "
1778                                        "client %s port %d - ID: %d due to recent request %d.",
1779                                        client->shortname,
1780                                        packet->src_port, packet->id,
1781                                        request->number);
1782                                 return 0;
1783                         }
1784
1785                         received_conflicting_request(request, client);
1786                         request = NULL;
1787                         break;
1788
1789                 case REQUEST_REJECT_DELAY:
1790                 case REQUEST_CLEANUP_DELAY:
1791                         request->child_state = REQUEST_DONE;
1792                 case REQUEST_DONE:
1793                         cleanup_delay(request);
1794                         request = NULL;
1795                         break;
1796                 }
1797
1798
1799         }
1800
1801         /*
1802          *      We may want to quench the new request.
1803          */
1804         if (!can_handle_new_request(packet, client, root)) {
1805                 return 0;
1806         }
1807
1808         /*
1809          *      Create and initialize the new request.
1810          */
1811         request = request_alloc(); /* never fails */
1812
1813         if ((request->reply = rad_alloc(0)) == NULL) {
1814                 radlog(L_ERR, "No memory");
1815                 exit(1);
1816         }
1817
1818         request->listener = listener;
1819         request->client = client;
1820         request->packet = packet;
1821         request->packet->timestamp = request->timestamp;
1822         request->number = request_num_counter++;
1823         request->priority = listener->type;
1824         request->root = root;
1825
1826         /*
1827          *      Set virtual server identity
1828          */
1829         if (client->server) {
1830                 request->server = client->server;
1831         } else if (listener->server) {
1832                 request->server = listener->server;
1833         } else {
1834                 request->server = NULL;
1835         }
1836
1837         /*
1838          *      Remember the request in the list.
1839          */
1840         if (!lrad_packet_list_insert(pl, &request->packet)) {
1841                 radlog(L_ERR, "Failed to insert request %d in the list of live requests: discarding", request->number);
1842                 request_free(&request);
1843                 return 0;
1844         }
1845         request->in_request_hash = TRUE;
1846
1847         /*
1848          *      The request passes many of our sanity checks.
1849          *      From here on in, if anything goes wrong, we
1850          *      send a reject message, instead of dropping the
1851          *      packet.
1852          */
1853
1854         /*
1855          *      Build the reply template from the request.
1856          */
1857
1858         request->reply->sockfd = request->packet->sockfd;
1859         request->reply->dst_ipaddr = request->packet->src_ipaddr;
1860         request->reply->src_ipaddr = request->packet->dst_ipaddr;
1861         request->reply->dst_port = request->packet->src_port;
1862         request->reply->src_port = request->packet->dst_port;
1863         request->reply->id = request->packet->id;
1864         request->reply->code = 0; /* UNKNOWN code */
1865         memcpy(request->reply->vector, request->packet->vector,
1866                sizeof(request->reply->vector));
1867         request->reply->vps = NULL;
1868         request->reply->data = NULL;
1869         request->reply->data_len = 0;
1870
1871         request->master_state = REQUEST_ACTIVE;
1872         request->child_state = REQUEST_QUEUED;
1873         request->next_callback = NULL;
1874
1875         gettimeofday(&request->received, NULL);
1876         request->timestamp = request->received.tv_sec;
1877         request->when = request->received;
1878
1879         request->delay = USEC / 10;
1880
1881         tv_add(&request->when, request->delay);
1882
1883         INSERT_EVENT(wait_a_bit, request);
1884
1885         *prequest = request;
1886         return 1;
1887 }
1888
1889
1890 REQUEST *received_proxy_response(RADIUS_PACKET *packet)
1891 {
1892         char            buffer[128];
1893         home_server     *home;
1894         REQUEST         *request;
1895
1896         if (!home_server_find(&packet->src_ipaddr, packet->src_port)) {
1897                 radlog(L_ERR, "Ignoring request from unknown home server %s port %d",
1898                        inet_ntop(packet->src_ipaddr.af,
1899                                  &packet->src_ipaddr.ipaddr,
1900                                  buffer, sizeof(buffer)),
1901                                packet->src_port);
1902                 rad_free(&packet);
1903                 return NULL;
1904         }
1905
1906         /*
1907          *      Also removes from the proxy hash if responses == requests
1908          */
1909         request = lookup_in_proxy_hash(packet);
1910
1911         if (!request) {
1912                 radlog(L_PROXY, "No outstanding request was found for proxy reply from home server %s port %d - ID %d",
1913                        inet_ntop(packet->src_ipaddr.af,
1914                                  &packet->src_ipaddr.ipaddr,
1915                                  buffer, sizeof(buffer)),
1916                        packet->src_port, packet->id);
1917                 rad_free(&packet);
1918                 return NULL;
1919         }
1920
1921         home = request->home_server;
1922
1923         gettimeofday(&now, NULL);
1924         home->state = HOME_STATE_ALIVE;
1925
1926         if (request->reply && request->reply->code != 0) {
1927                 DEBUG2("We already replied to this request.  Discarding response from home server.");
1928                 rad_free(&packet);
1929                 return NULL;
1930         }
1931
1932         /*
1933          *      We had previously received a reply, so we don't need
1934          *      to do anything here.
1935          */
1936         if (request->proxy_reply) {
1937                 if (memcmp(request->proxy_reply->vector,
1938                            packet->vector,
1939                            sizeof(request->proxy_reply->vector)) == 0) {
1940                         DEBUG2("Discarding duplicate reply from home server %s port %d  - ID: %d for request %d",
1941                                inet_ntop(packet->src_ipaddr.af,
1942                                          &packet->src_ipaddr.ipaddr,
1943                                          buffer, sizeof(buffer)),
1944                                packet->src_port, packet->id,
1945                                request->number);
1946                 } else {
1947                         /*
1948                          *      ? The home server gave us a new proxy
1949                          *      reply, which doesn't match the old
1950                          *      one.  Delete it.
1951                          */
1952                         DEBUG2("Ignoring conflicting proxy reply");
1953                 }
1954
1955                 /* assert that there's an event queued for request? */
1956                 rad_free(&packet);
1957                 return NULL;
1958         }
1959
1960         switch (request->child_state) {
1961         case REQUEST_QUEUED:
1962         case REQUEST_RUNNING:
1963                 rad_panic("Internal sanity check failed for child state");
1964                 break;
1965
1966         case REQUEST_REJECT_DELAY:
1967         case REQUEST_CLEANUP_DELAY:
1968         case REQUEST_DONE:
1969                 radlog(L_ERR, "Reply from home server %s port %d  - ID: %d arrived too late for request %d. Try increasing 'retry_delay' or 'max_request_time'",
1970                        inet_ntop(packet->src_ipaddr.af,
1971                                  &packet->src_ipaddr.ipaddr,
1972                                  buffer, sizeof(buffer)),
1973                        packet->src_port, packet->id,
1974                        request->number);
1975                 /* assert that there's an event queued for request? */
1976                 rad_free(&packet);
1977                 return NULL;
1978
1979         case REQUEST_PROXIED:
1980                 break;
1981         }
1982
1983         request->proxy_reply = packet;
1984
1985 #if 0
1986         /*
1987          *      Perform RTT calculations, as per RFC 2988 (for TCP).
1988          *      Note that we do so only if we sent one request, and
1989          *      received one response.  If we sent two requests, we
1990          *      have no idea if the response is for the first, or for
1991          *      the second request/
1992          */
1993         if (request->num_proxied_requests == 1) {
1994                 int rtt;
1995                 home_server *home = request->home_server;
1996
1997                 rtt = now.tv_sec - request->proxy_when.tv_sec;
1998                 rtt *= USEC;
1999                 rtt += now.tv_usec;
2000                 rtt -= request->proxy_when.tv_usec;
2001
2002                 if (!home->has_rtt) {
2003                         home->has_rtt = TRUE;
2004
2005                         home->srtt = rtt;
2006                         home->rttvar = rtt / 2;
2007
2008                 } else {
2009                         home->rttvar -= home->rttvar >> 2;
2010                         home->rttvar += (home->srtt - rtt);
2011                         home->srtt -= home->srtt >> 3;
2012                         home->srtt += rtt >> 3;
2013                 }
2014
2015                 home->rto = home->srtt;
2016                 if (home->rttvar > (USEC / 4)) {
2017                         home->rto += home->rttvar * 4;
2018                 } else {
2019                         home->rto += USEC;
2020                 }
2021         }
2022 #endif
2023
2024         /*
2025          *      There's no incoming request, so it's a proxied packet
2026          *      we originated.
2027          */
2028         if (!request->packet) {
2029                 received_response_to_ping(request);
2030                 return NULL;
2031         }
2032
2033         request->child_state = REQUEST_QUEUED;
2034         request->when = now;
2035         request->delay = USEC / 10;
2036         request->priority = RAD_LISTEN_PROXY;
2037         tv_add(&request->when, request->delay);
2038
2039         /*
2040          *      Wait a bit will take care of max_request_time
2041          */
2042         INSERT_EVENT(wait_a_bit, request);
2043
2044         return request;
2045 }
2046
2047
2048 /*
2049  *      Inform ourselves that we received a signal.
2050  */
2051 void radius_signal_self(int flag)
2052 {
2053         ssize_t rcode;
2054         uint8_t buffer[16];
2055
2056         /*
2057          *      The caller is telling us it's OK to read from the
2058          *      detail files.  However, we're not even listening on
2059          *      the detail files.  Therefore, suppress the flag to
2060          *      avoid bothering the main worker thread.
2061          */
2062         if ((flag == RADIUS_SIGNAL_SELF_DETAIL) &&
2063             !has_detail_listener) {
2064                 return;
2065         }
2066
2067         /*
2068          *      The read MUST be non-blocking for this to work.
2069          */
2070         rcode = read(self_pipe[0], buffer, sizeof(buffer));
2071         if (rcode > 0) {
2072                 ssize_t i;
2073
2074                 for (i = 1; i < rcode; i++) {
2075                         buffer[0] |= buffer[i];
2076                 }
2077         }
2078
2079 #ifndef NDEBUG
2080         memset(buffer + 1, 0, sizeof(buffer) - 1);
2081 #endif
2082
2083         buffer[0] |= flag;
2084
2085         write(self_pipe[1], buffer, 1);
2086 }
2087
2088
2089 static void event_signal_handler(lrad_event_list_t *xel, int fd, void *ctx)
2090 {
2091         size_t i, rcode;
2092         char buffer[32];
2093
2094         xel = xel;
2095         fd = fd;
2096         ctx = ctx;
2097
2098         rcode = read(self_pipe[0], buffer, sizeof(buffer));
2099         if (rcode <= 0) return;
2100
2101         /*
2102          *      Merge pending signals.
2103          */
2104         for (i = 1; i < rcode; i++) {
2105                 buffer[0] |= buffer[i];
2106         }
2107         
2108         /*
2109          *      The thread pool has nothing more to do.  Start reading
2110          *      from the detail file.
2111          */
2112         if ((buffer[0] & (RADIUS_SIGNAL_SELF_DETAIL)) != 0) {
2113                 read_from_detail = TRUE;
2114         }
2115
2116         if ((buffer[0] & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
2117                 if ((buffer[0] & RADIUS_SIGNAL_SELF_EXIT) != 0) {
2118                         lrad_event_loop_exit(el, 1);
2119                 } else {
2120                         lrad_event_loop_exit(el, 2);
2121                 }
2122                         
2123                 return;
2124         } /* else exit/term flags weren't set */
2125
2126         /*
2127          *      Tell the even loop to stop processing.
2128          */
2129         if ((buffer[0] & RADIUS_SIGNAL_SELF_HUP) != 0) {
2130                 DEBUG("Received HUP signal.");
2131
2132                 lrad_event_loop_exit(el, 0x80);
2133         }
2134 }
2135
2136
2137 /*
2138  *      The given FD is closed.  Delete it from the list of FD's to poll,
2139  *      and set a timer to periodically look for an FD again.
2140  */
2141 static void event_reset_fd(rad_listen_t *listener, int fd, int usec)
2142 {
2143         struct timeval when;
2144         gettimeofday(&when, NULL);
2145
2146         tv_add(&when, usec);    
2147
2148         if (!lrad_event_fd_delete(el, 0, fd)) {
2149                 rad_panic("Failed deleting fd");
2150         }
2151         
2152         if (!lrad_event_insert(el, event_poll_fd, listener,
2153                                &when, NULL)) {
2154                 rad_panic("Failed inserting event");
2155         }
2156 }
2157
2158
2159 /*
2160  *      Reads from the detail file if possible, OR sets up a timeout
2161  *      to see if the detail file is ready for reading.
2162  *
2163  *      FIXME: On Linux, use inotify to watch the detail file.  This
2164  *      
2165  */
2166 static void event_detail_handler(lrad_event_list_t *xel, int fd, void *ctx)
2167 {
2168         rad_listen_t *listener = ctx;
2169         RAD_REQUEST_FUNP fun;
2170         REQUEST *request;
2171
2172         rad_assert(xel == el);
2173         rad_assert(fd == listener->fd);
2174
2175         xel = xel;
2176
2177         /*
2178          *      We're too busy to read from the detail file.  Stop
2179          *      watching the file, and instead go back to polling.
2180          */
2181         if (!read_from_detail) {
2182                 event_reset_fd(listener, fd, USEC);
2183                 return;
2184         }
2185         
2186         /*
2187          *      FIXME: Put this somewhere else, where it isn't called
2188          *      all of the time...
2189          */
2190 #ifndef HAVE_PTHREAD_H
2191         /*
2192          *      If there are no child threads, then there may
2193          *      be child processes.  In that case, wait for
2194          *      their exit status, and throw that exit status
2195          *      away.  This helps get rid of zxombie children.
2196          */
2197         while (waitpid(-1, &argval, WNOHANG) > 0) {
2198                 /* do nothing */
2199         }
2200 #endif
2201
2202         /*
2203          *      Didn't read anything from the detail file.
2204          *      Wake up in one second to check it again.
2205          */
2206         if (!listener->recv(listener, &fun, &request)) {
2207                 event_reset_fd(listener, fd, USEC);
2208                 return;
2209         }
2210
2211         /*
2212          *      Drop the request into the thread pool,
2213          *      and let the thread pool take care of
2214          *      doing something with it.
2215          */
2216         if (!thread_pool_addrequest(request, fun)) {
2217                 request->child_state = REQUEST_DONE;
2218         }
2219
2220         /*
2221          *      Reset based on the fd we were given, as detail_recv()
2222          *      may have read all of the file, and closed it.  It then
2223          *      sets listener->fd = -1.
2224          */
2225         event_reset_fd(listener, fd, *(int *) listener->data);
2226 }
2227
2228
2229 static void event_socket_handler(lrad_event_list_t *xel, int fd, void *ctx)
2230 {
2231         rad_listen_t *listener = ctx;
2232         RAD_REQUEST_FUNP fun;
2233         REQUEST *request;
2234
2235         rad_assert(xel == el);
2236
2237         xel = xel;
2238         fd = fd;
2239
2240         if (listener->fd < 0) rad_panic("Socket was closed on us!");
2241         
2242         /*
2243          *      FIXME: Put this somewhere else, where it isn't called
2244          *      all of the time...
2245          */
2246 #ifndef HAVE_PTHREAD_H
2247         /*
2248          *      If there are no child threads, then there may
2249          *      be child processes.  In that case, wait for
2250          *      their exit status, and throw that exit status
2251          *      away.  This helps get rid of zxombie children.
2252          */
2253         while (waitpid(-1, &argval, WNOHANG) > 0) {
2254                 /* do nothing */
2255         }
2256 #endif
2257
2258         if (!listener->recv(listener, &fun, &request)) return;
2259
2260         if (!thread_pool_addrequest(request, fun)) {
2261                 request->child_state = REQUEST_DONE;
2262         }
2263
2264         /*
2265          *      If we've read a packet from a socket OTHER than the
2266          *      detail file, we start ignoring the detail file.
2267          *
2268          *      When the child thread pulls the request off of the
2269          *      queues, it will check if the queues are empty.  Once
2270          *      all queues are empty, it will signal us to read the
2271          *      detail file again.
2272          */
2273         read_from_detail = FALSE;
2274 }
2275
2276
2277 /*
2278  *      This function is called periodically to see if a file
2279  *      descriptor is available for reading.
2280  */
2281 static void event_poll_fd(void *ctx)
2282 {
2283         int rcode;
2284         RAD_REQUEST_FUNP fun;
2285         REQUEST *request;
2286         rad_listen_t *listener = ctx;
2287         lrad_event_fd_handler_t handler;
2288
2289         /*
2290          *      Ignore the detail file if we're busy with other work.
2291          */
2292         if ((listener->type == RAD_LISTEN_DETAIL) && !read_from_detail) {
2293                 goto reset;
2294         }
2295
2296         /*
2297          *      Try to read a RADIUS packet.  This also opens the FD.
2298          *
2299          *      FIXME: This does poll AND receive.
2300          */
2301         rcode = listener->recv(listener, &fun, &request);
2302
2303         /*
2304          *      We read a request.  Add it to the list for processing.
2305          */
2306         if (rcode == 1) {
2307                 rad_assert(fun != NULL);
2308                 rad_assert(request != NULL);
2309
2310                 if (!thread_pool_addrequest(request, fun)) {
2311                         request->child_state = REQUEST_DONE;
2312                 }
2313         }
2314
2315         /*
2316          *      Still no FD, OR the fd was read completely, and then
2317          *      closed.  Re-set the polling timer and return.
2318          */
2319         if (listener->fd < 0) {
2320                 struct timeval when;
2321
2322         reset:
2323                 gettimeofday(&when, NULL);
2324                 when.tv_sec += 1;
2325                 
2326                 if (!lrad_event_insert(el, event_poll_fd, listener,
2327                                        &when, NULL)) {
2328                         rad_panic("Failed inserting event");
2329                 }
2330
2331                 return;
2332         }
2333
2334         if (listener->type == RAD_LISTEN_DETAIL) {
2335                 handler = event_detail_handler;
2336         } else {
2337                 handler = event_socket_handler;
2338         }
2339
2340         /*
2341          *      We have an FD.  Start watching it.
2342          */
2343         if (!lrad_event_fd_insert(el, 0, listener->fd,
2344                                   handler, listener)) {
2345                 char buffer[256];
2346                 
2347                 listener->print(listener, buffer, sizeof(buffer));
2348                 rad_panic("Failed creating handler for socket");
2349         }
2350 }
2351
2352
2353 static void event_status(struct timeval *wake)
2354 {
2355         if (debug_flag == 0) return;
2356
2357         if (!wake) {
2358                 DEBUG("Waiting for the next request.");
2359         } else if ((wake->tv_sec != 0) ||
2360                    (wake->tv_usec >= 100000)) {
2361                 DEBUG("Waking up in %d.%01d seconds.\n",
2362                       (int) wake->tv_sec, (int) wake->tv_usec / 100000);
2363         }
2364 }
2365
2366
2367 /*
2368  *      Externally-visibly functions.
2369  */
2370 int radius_event_init(CONF_SECTION *cs, int spawn_flag)
2371 {
2372         int i;
2373         rad_listen_t *this, *head = NULL;
2374
2375         if (el) return 0;
2376
2377         time(&start_time);
2378
2379         el = lrad_event_list_create(event_status);
2380         if (!el) return 0;
2381
2382         pl = lrad_packet_list_create(0);
2383         if (!el) return 0;
2384
2385         request_num_counter = 0;
2386
2387         /*
2388          *      Move all of the thread calls to this file?
2389          *
2390          *      It may be best for the mutexes to be in this file...
2391          */
2392         have_children = spawn_flag;
2393
2394         if (mainconfig.proxy_requests) {
2395                 /*
2396                  *      Create the tree for managing proxied requests and
2397                  *      responses.
2398                  */
2399                 proxy_list = lrad_packet_list_create(1);
2400                 if (!proxy_list) return 0;
2401
2402 #ifdef HAVE_PTHREAD_H
2403                 if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
2404                         radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
2405                                strerror(errno));
2406                         exit(1);
2407                 }
2408 #endif
2409         }
2410
2411         if (thread_pool_init(cs, spawn_flag) < 0) {
2412                 exit(1);
2413         }
2414
2415         /*
2416          *      Child threads need a pipe to signal us, as do the
2417          *      signal handlers.
2418          */
2419         if (pipe(self_pipe) < 0) {
2420                 radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
2421                        strerror(errno));
2422                 exit(1);
2423         }
2424         if (fcntl(self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
2425                 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
2426                        strerror(errno));
2427                 exit(1);
2428         }
2429         if (fcntl(self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
2430                 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
2431                        strerror(errno));
2432                 exit(1);
2433         }
2434
2435         if (!lrad_event_fd_insert(el, 0, self_pipe[0],
2436                                   event_signal_handler, el)) {
2437                 radlog(L_ERR, "Failed creating handler for signals");
2438                 exit(1);
2439         }
2440
2441
2442         /*
2443          *      Mark the proxy Fd's as unused.
2444          */
2445         for (i = 0; i < 32; i++) proxy_fds[i] = -1;
2446
2447         DEBUG2("radiusd: #### Opening IP addresses and Ports ####");
2448
2449         if (listen_init(cs, &head) < 0) {
2450                 _exit(1);
2451         }
2452         
2453         /*
2454          *      Add all of the sockets to the event loop.
2455          *
2456          *      FIXME: New proxy sockets aren't currently added to the
2457          *      event loop.  They're allocated in a child thread, and
2458          *      we don't have (or want) a mutex around the event
2459          *      handling code.
2460          */
2461         for (this = head;
2462              this != NULL;
2463              this = this->next) {
2464                 char buffer[256];
2465
2466                 this->print(this, buffer, sizeof(buffer));
2467
2468                 switch (this->type) {
2469                 case RAD_LISTEN_DETAIL:
2470                         DEBUG("Listening on %s", buffer);
2471                         has_detail_listener = TRUE;
2472                         break;
2473
2474                 case RAD_LISTEN_PROXY:
2475                         rad_assert(proxy_fds[this->fd & 0x1f] == -1);
2476                         rad_assert(proxy_listeners[this->fd & 0x1f] == NULL);
2477                         
2478                         proxy_fds[this->fd & 0x1f] = this->fd;
2479                         proxy_listeners[this->fd & 0x1f] = this;
2480                         if (!lrad_packet_list_socket_add(proxy_list,
2481                                                          this->fd)) {
2482                                 rad_assert(0 == 1);
2483                         }
2484                         break;
2485
2486                 case RAD_LISTEN_SNMP:
2487                         DEBUG("Listening on SNMP %s", buffer);
2488                         break;
2489
2490                 default:
2491                         DEBUG("Listening on %s", buffer);
2492                         break;
2493                 }
2494
2495                 /*
2496                  *      The file descriptor isn't ready.  Poll for
2497                  *      when it will become ready.  This is for SNMP
2498                  *      and detail file fd's.
2499                  */
2500                 if (this->fd < 0) {
2501                         struct timeval when;
2502
2503                         gettimeofday(&when, NULL);
2504                         when.tv_sec += 1;
2505
2506                         if (!lrad_event_insert(el, event_poll_fd, this,
2507                                                &when, NULL)) {
2508                                 radlog(L_ERR, "Failed creating handler");
2509                                 exit(1);
2510                         }
2511                         continue;
2512                 }
2513
2514                 /*
2515                  *      The socket is open.  It MUST be a socket,
2516                  *      as we don't pre-open the detail files (yet).
2517                  *
2518                  *      FIXME: if we DO open the detail files automatically,
2519                  *      then much of this code becomes simpler.
2520                  */
2521                 if (!lrad_event_fd_insert(el, 0, this->fd,
2522                                           event_socket_handler, this)) {
2523                         this->print(this, buffer, sizeof(buffer));
2524                         radlog(L_ERR, "Failed creating handler for socket %s",
2525                                buffer);
2526                         exit(1);
2527                 }
2528         }
2529
2530         return 1;
2531 }
2532
2533
2534 static int request_hash_cb(void *ctx, void *data)
2535 {
2536         ctx = ctx;              /* -Wunused */
2537         REQUEST *request = lrad_packet2myptr(REQUEST, packet, data);
2538
2539         rad_assert(request->in_proxy_hash == FALSE);
2540
2541         lrad_event_delete(el, &request->ev);
2542         remove_from_request_hash(request);
2543         request_free(&request);
2544
2545         return 0;
2546 }
2547
2548
2549 static int proxy_hash_cb(void *ctx, void *data)
2550 {
2551         ctx = ctx;              /* -Wunused */
2552         REQUEST *request = lrad_packet2myptr(REQUEST, proxy, data);
2553
2554         lrad_packet_list_yank(proxy_list, request->proxy);
2555         request->in_proxy_hash = FALSE;
2556
2557         if (!request->in_request_hash) {
2558                 lrad_event_delete(el, &request->ev);
2559                 request_free(&request);
2560         }
2561
2562         return 0;
2563 }
2564
2565
2566 void radius_event_free(void)
2567 {
2568         /*
2569          *      FIXME: Stop all threads, or at least check that
2570          *      they're all waiting on the semaphore, and the queues
2571          *      are empty.
2572          */
2573
2574         /*
2575          *      There are requests in the proxy hash that aren't
2576          *      referenced from anywhere else.  Remove them first.
2577          */
2578         if (proxy_list) {
2579                 PTHREAD_MUTEX_LOCK(&proxy_mutex);
2580                 lrad_packet_list_walk(proxy_list, NULL, proxy_hash_cb);
2581                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
2582                 lrad_packet_list_free(proxy_list);
2583                 proxy_list = NULL;
2584         }
2585
2586         lrad_packet_list_walk(pl, NULL, request_hash_cb);
2587
2588         lrad_packet_list_free(pl);
2589         pl = NULL;
2590
2591         lrad_event_list_free(el);
2592 }
2593
2594 int radius_event_process(void)
2595 {
2596         if (!el) return 0;
2597
2598         radlog(L_INFO, "Ready to process requests.");
2599
2600         return lrad_event_loop(el);
2601 }
2602
2603 void radius_handle_request(REQUEST *request, RAD_REQUEST_FUNP fun)
2604 {
2605         if (request_pre_handler(request)) {
2606                 rad_assert(fun != NULL);
2607                 rad_assert(request != NULL);
2608                 
2609                 if (request->server) DEBUG("server %s {",
2610                                              request->server); 
2611                 fun(request);
2612
2613                 if (request->server) DEBUG("} # server %s",
2614                                              request->server);
2615
2616                 request_post_handler(request);
2617         }
2618
2619         DEBUG2("Going to the next request");
2620         return;
2621 }