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