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