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