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