Permit per-request configuration to NOT reply to Access-Request.
[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
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/modules.h>
30 #include <freeradius-devel/event.h>
31 #include <freeradius-devel/radius_snmp.h>
32
33 #include <freeradius-devel/rad_assert.h>
34
35 #define USEC (1000000)
36
37 /*
38  *      Ridiculous amounts of local state.
39  */
40 static lrad_event_list_t        *el = NULL;
41 static lrad_packet_list_t       *pl = NULL;
42 static int                      request_num_counter = 0;
43 static struct timeval           now;
44 static time_t                   start_time;
45 static int                      have_children;
46
47 #ifdef HAVE_PTHREAD_H
48 static pthread_mutex_t  proxy_mutex;
49
50 #define PTHREAD_MUTEX_LOCK if (have_children) pthread_mutex_lock
51 #define PTHREAD_MUTEX_UNLOCK if (have_children) pthread_mutex_unlock
52 #else
53 /*
54  *      This is easier than ifdef's throughout the code.
55  */
56 #define PTHREAD_MUTEX_LOCK(_x)
57 #define PTHREAD_MUTEX_UNLOCK(_x)
58 #endif
59
60 #define INSERT_EVENT(_function, _ctx) if (!lrad_event_insert(el, _function, _ctx, &((_ctx)->when), &((_ctx)->ev))) { _rad_panic(__FILE__, __LINE__, "Failed to insert event"); }
61
62 static lrad_packet_list_t *proxy_list = NULL;
63
64 /*
65  *      We keep the proxy FD's here.  The RADIUS Id's are marked
66  *      "allocated" per Id, via a bit per proxy FD.
67  */
68 static int              proxy_fds[32];
69 static rad_listen_t     *proxy_listeners[32];
70
71 static void request_post_handler(REQUEST *request);
72 static void wait_a_bit(void *ctx);
73
74 static void NEVER_RETURNS _rad_panic(const char *file, unsigned int line,
75                                     const char *msg)
76 {
77         radlog(L_ERR, "]%s:%d] %s", file, line, msg);
78         _exit(1);
79 }
80
81 #define rad_panic(x) _rad_panic(__FILE__, __LINE__, x)
82
83
84 static void tv_add(struct timeval *tv, int usec_delay)
85 {
86         if (usec_delay > USEC) {
87                 tv->tv_sec += usec_delay / USEC;
88                 usec_delay %= USEC;
89         }
90         tv->tv_usec += usec_delay;
91
92         if (tv->tv_usec > USEC) {
93                 tv->tv_usec -= USEC;
94                 tv->tv_sec++;
95         }
96 }
97
98 #ifdef WITH_SNMP
99 static void snmp_inc_counters(REQUEST *request)
100 {
101         if (!mainconfig.do_snmp) return;
102
103         if (request->master_state == REQUEST_COUNTED) return;
104
105         if ((request->listener->type != RAD_LISTEN_AUTH) &&
106             (request->listener->type != RAD_LISTEN_ACCT)) return;
107
108         /*
109          *      Update the SNMP statistics.
110          *
111          *      Note that we do NOT do this in a child thread.
112          *      Instead, we update the stats when a request is
113          *      deleted, because only the main server thread calls
114          *      this function, which makes it thread-safe.
115          */
116         switch (request->reply->code) {
117         case PW_AUTHENTICATION_ACK:
118                 rad_snmp.auth.total_responses++;
119                 rad_snmp.auth.total_access_accepts++;
120                 if (request->client) request->client->auth->accepts++;
121                 break;
122
123         case PW_AUTHENTICATION_REJECT:
124                 rad_snmp.auth.total_responses++;
125                 rad_snmp.auth.total_access_rejects++;
126                 if (request->client) request->client->auth->rejects++;
127                 break;
128
129         case PW_ACCESS_CHALLENGE:
130                 rad_snmp.auth.total_responses++;
131                 rad_snmp.auth.total_access_challenges++;
132                 if (request->client) request->client->auth->challenges++;
133                 break;
134
135         case PW_ACCOUNTING_RESPONSE:
136                 rad_snmp.acct.total_responses++;
137                 if (request->client) request->client->auth->responses++;
138                 break;
139
140                 /*
141                  *      No response, it must have been a bad
142                  *      authenticator.
143                  */
144         case 0:
145                 if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
146                         rad_snmp.auth.total_bad_authenticators++;
147                         if (request->client) request->client->auth->bad_authenticators++;
148                 }
149                 break;
150
151         default:
152                 break;
153         }
154
155         request->master_state = REQUEST_COUNTED;
156 }
157 #else
158 #define snmp_inc_counters(_x)
159 #endif
160
161
162 static void remove_from_request_hash(REQUEST *request)
163 {
164         if (!request->in_request_hash) return;
165
166         lrad_packet_list_yank(pl, request->packet);
167         request->in_request_hash = FALSE;
168
169         snmp_inc_counters(request);
170 }
171
172
173 static REQUEST *lookup_in_proxy_hash(RADIUS_PACKET *reply)
174 {
175         RADIUS_PACKET **proxy_p;
176         REQUEST *request;
177
178         PTHREAD_MUTEX_LOCK(&proxy_mutex);
179         proxy_p = lrad_packet_list_find_byreply(proxy_list, reply);
180
181         if (!proxy_p) {
182                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
183                 return NULL;
184         }
185
186         request = lrad_packet2myptr(REQUEST, proxy, proxy_p);
187
188         if (!request) {
189                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
190                 return NULL;
191         }
192
193         request->num_proxied_responses++;
194
195         /*
196          *      Catch the most common case of everything working
197          *      correctly.
198          */
199         if (request->num_proxied_requests == request->num_proxied_responses) {
200                 lrad_packet_list_yank(proxy_list, request->proxy);
201                 lrad_packet_list_id_free(proxy_list, request->proxy);
202                 request->in_proxy_hash = FALSE;
203         }
204
205         /*
206          *      On the FIRST reply, decrement the count of outstanding
207          *      requests.  Note that this is NOT the count of sent
208          *      packets, but whether or not the home server has
209          *      responded at all.
210          */
211         if (!request->proxy_reply &&
212             request->home_server->currently_outstanding) {
213                 request->home_server->currently_outstanding--;
214         }
215
216         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
217
218         return request;
219 }
220
221
222 static void remove_from_proxy_hash(REQUEST *request)
223 {
224         if (!request->in_proxy_hash) return;
225
226         PTHREAD_MUTEX_LOCK(&proxy_mutex);
227         lrad_packet_list_yank(proxy_list, request->proxy);
228         lrad_packet_list_id_free(proxy_list, request->proxy);
229
230         /*
231          *      The home server hasn't replied, but we've given up on
232          *      this request.  Don't count this request against the
233          *      home server.
234          */
235         if (!request->proxy_reply &&
236             request->home_server->currently_outstanding) {
237                 request->home_server->currently_outstanding--;
238         }
239
240         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
241
242         request->in_proxy_hash = FALSE;
243 }
244
245
246 static int insert_into_proxy_hash(REQUEST *request)
247 {
248         int i, proxy;
249         char buf[128];
250
251         rad_assert(request->proxy != NULL);
252         rad_assert(proxy_list != NULL);
253
254         request->proxy->sockfd = -1;
255
256         PTHREAD_MUTEX_LOCK(&proxy_mutex);
257
258         request->home_server->currently_outstanding++;
259
260         if (!lrad_packet_list_id_alloc(proxy_list, request->proxy)) {
261                 int found;
262                 rad_listen_t *proxy_listener;
263
264                 /*
265                  *      Allocate a new proxy fd.  This function adds it
266                  *      into the list of listeners.
267                  */
268                 proxy_listener = proxy_new_listener();
269                 if (!proxy_listener) {
270                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
271                         DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
272                         return 0;
273                 }
274
275                 /*
276                  *      Cache it locally.
277                  */
278                 found = -1;
279                 proxy = proxy_listener->fd;
280                 for (i = 0; i < 32; i++) {
281                         DEBUG2("PROXY %d %d", i, proxy_fds[(proxy + i) & 0x1f]);
282
283                         /*
284                          *      Found a free entry.  Save the socket,
285                          *      and remember where we saved it.
286                          */
287                         if (proxy_fds[(proxy + i) & 0x1f] == -1) {
288                                 found = (proxy + i) & 0x1f;
289                                 proxy_fds[found] = proxy;
290                                 proxy_listeners[found] = proxy_listener;
291                                 break;
292                         }
293                 }
294                 rad_assert(found >= 0);
295
296                 if (!lrad_packet_list_socket_add(proxy_list, proxy_listener->fd)) {
297                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
298                         DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
299                         return 0; /* leak proxy_listener */
300
301                 }
302
303                 if (!lrad_packet_list_id_alloc(proxy_list, request->proxy)) {
304                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
305                         DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
306                         return 0;
307                 }
308         }
309         rad_assert(request->proxy->sockfd >= 0);
310
311         /*
312          *      FIXME: Hack until we get rid of rad_listen_t, and put
313          *      the information into the packet_list.
314          */
315         proxy = -1;
316         for (i = 0; i < 32; i++) {
317                 if (proxy_fds[i] == request->proxy->sockfd) {
318                         proxy = i;
319                         break;
320                 }
321         }
322
323         if (proxy < 0) {
324                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
325                 DEBUG2("ERROR: All sockets are full.");
326                 return 0;
327         }
328
329         rad_assert(proxy_fds[proxy] != -1);
330         rad_assert(proxy_listeners[proxy] != NULL);
331         request->proxy_listener = proxy_listeners[proxy];
332
333         if (!lrad_packet_list_insert(proxy_list, &request->proxy)) {
334                 lrad_packet_list_id_free(proxy_list, request->proxy);
335                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
336                 DEBUG2("ERROR: Failed to insert entry into proxy list");
337                 return 0;
338         }
339
340         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
341
342         DEBUG3(" proxy: allocating destination %s port %d - Id %d",
343                inet_ntop(request->proxy->dst_ipaddr.af,
344                          &request->proxy->dst_ipaddr.ipaddr, buf, sizeof(buf)),
345                request->proxy->dst_port,
346                request->proxy->id);
347
348         request->in_proxy_hash = TRUE;
349
350         return 1;
351 }
352
353
354 /*
355  *      Called as BOTH an event, and in-line from other functions.
356  */
357 static void wait_for_proxy_id_to_expire(void *ctx)
358 {
359         REQUEST *request = ctx;
360         home_server *home = request->home_server;
361
362         rad_assert(request->magic == REQUEST_MAGIC);
363         rad_assert(request->proxy != NULL);
364
365         request->when = request->proxy_when;
366         request->when.tv_sec += home->response_window;
367
368         if ((request->num_proxied_requests == request->num_proxied_responses) ||
369             timercmp(&now, &request->when, >)) {
370                 if (request->packet) {
371                         DEBUG2("Cleaning up request %d ID %d with timestamp +%d",
372                                request->number, request->packet->id,
373                                (unsigned int) (request->timestamp - start_time));
374                 } else {
375                         DEBUG2("Cleaning up request %d with timestamp +%d",
376                                request->number,
377                                (unsigned int) (request->timestamp - start_time));
378                 }
379                 lrad_event_delete(el, &request->ev);
380                 remove_from_proxy_hash(request);
381                 remove_from_request_hash(request);
382                 request_free(&request);
383                 return;
384         }
385
386         INSERT_EVENT(wait_for_proxy_id_to_expire, request);
387 }
388
389
390 static void wait_for_child_to_die(void *ctx)
391 {
392         REQUEST *request = ctx;
393
394         rad_assert(request->magic == REQUEST_MAGIC);
395
396         if ((request->child_state == REQUEST_QUEUED) |
397             (request->child_state == REQUEST_RUNNING)) {
398                 request->delay += (request->delay >> 1);
399                 tv_add(&request->when, request->delay);
400
401                 DEBUG2("Child is still stuck for request %d", request->number);
402
403                 INSERT_EVENT(wait_for_child_to_die, request);
404                 return;
405         }
406
407         DEBUG2("Child is finally responsive for request %d", request->number);
408         remove_from_request_hash(request);
409
410         if (request->proxy) {
411                 wait_for_proxy_id_to_expire(request);
412                 return;
413         }
414
415         request_free(&request);
416 }
417
418
419 static void cleanup_delay(void *ctx)
420 {
421         REQUEST *request = ctx;
422
423         rad_assert(request->magic == REQUEST_MAGIC);
424         rad_assert((request->child_state == REQUEST_CLEANUP_DELAY) ||
425                    (request->child_state == REQUEST_DONE));
426
427         remove_from_request_hash(request);
428
429         if (request->proxy && request->in_proxy_hash) {
430                 wait_for_proxy_id_to_expire(request);
431                 return;
432         }
433
434         DEBUG2("Cleaning up request %d ID %d with timestamp +%d",
435                request->number, request->packet->id,
436                (unsigned int) (request->timestamp - start_time));
437
438         lrad_event_delete(el, &request->ev);
439         request_free(&request);
440 }
441
442
443 static void reject_delay(void *ctx)
444 {
445         REQUEST *request = ctx;
446
447         rad_assert(request->magic == REQUEST_MAGIC);
448         rad_assert(request->child_state == REQUEST_REJECT_DELAY);
449
450         DEBUG2("Sending delayed reject for request %d", request->number);
451
452         request->listener->send(request->listener, request);
453
454         request->when.tv_sec += mainconfig.cleanup_delay;
455         request->child_state = REQUEST_CLEANUP_DELAY;
456
457         INSERT_EVENT(cleanup_delay, request);
458 }
459
460
461 static void revive_home_server(void *ctx)
462 {
463         home_server *home = ctx;
464
465         home->state = HOME_STATE_ALIVE;
466         DEBUG2("Marking home server alive again... we have no idea if it really is alive or not.");
467         home->currently_outstanding = 0;
468 }
469
470
471 static void no_response_to_ping(void *ctx)
472 {
473         REQUEST *request = ctx;
474         home_server *home = request->home_server;
475         char buffer[128];
476
477         home->num_received_pings = 0;
478
479         DEBUG2("No response to status check %d from home server %s port %d",
480                request->number,
481                inet_ntop(request->proxy->dst_ipaddr.af,
482                          &request->proxy->dst_ipaddr.ipaddr,
483                          buffer, sizeof(buffer)),
484                request->proxy->dst_port);
485
486         wait_for_proxy_id_to_expire(request);
487 }
488
489
490 static void received_response_to_ping(REQUEST *request)
491 {
492         home_server *home = request->home_server;
493         char buffer[128];
494
495         home->num_received_pings++;
496
497         DEBUG2("Received response to status check %d (%d in current sequence)",
498                request->number, home->num_received_pings);
499
500         if (home->num_received_pings < home->num_pings_to_alive) {
501                 wait_for_proxy_id_to_expire(request);
502                 return;
503         }
504
505         DEBUG2("Marking home server %s port %d alive",
506                inet_ntop(request->proxy->dst_ipaddr.af,
507                          &request->proxy->dst_ipaddr.ipaddr,
508                          buffer, sizeof(buffer)),
509                request->proxy->dst_port);
510
511         if (!lrad_event_delete(el, &home->ev)) {
512                 DEBUG2("Hmm... no event for home server, WTF?");
513         }
514
515         if (!lrad_event_delete(el, &request->ev)) {
516                 DEBUG2("Hmm... no event for request, WTF?");
517         }
518
519         wait_for_proxy_id_to_expire(request);
520
521         home->state = HOME_STATE_ALIVE;
522         home->currently_outstanding = 0;
523 }
524
525
526 static void ping_home_server(void *ctx)
527 {
528         uint32_t jitter;
529         home_server *home = ctx;
530         REQUEST *request;
531         VALUE_PAIR *vp;
532
533         if (home->state == HOME_STATE_ALIVE) {
534                 radlog(L_INFO, "Suspicious proxy state... continuing");
535                 return;
536         }
537
538         request = request_alloc();
539         request->number = request_num_counter++;
540
541         request->proxy = rad_alloc(1);
542         rad_assert(request->proxy != NULL);
543
544         gettimeofday(&request->when, NULL);
545         home->when = request->when;
546
547         if (home->ping_check == HOME_PING_CHECK_STATUS_SERVER) {
548                 request->proxy->code = PW_STATUS_SERVER;
549
550                 vp = pairmake("Message-Authenticator", "0x00", T_OP_SET);
551                 if (!vp) rad_panic("Out of memory");
552                 pairadd(&request->proxy->vps, vp);
553
554         } else if (home->type == HOME_TYPE_AUTH) {
555                 request->proxy->code = PW_AUTHENTICATION_REQUEST;
556
557                 vp = pairmake("User-Name", home->ping_user_name, T_OP_SET);
558                 if (!vp) rad_panic("Out of memory");
559                 pairadd(&request->proxy->vps, vp);
560
561                 vp = pairmake("User-Password", home->ping_user_password, T_OP_SET);
562                 if (!vp) rad_panic("Out of memory");
563                 pairadd(&request->proxy->vps, vp);
564
565                 vp = pairmake("Service-Type", "Authenticate-Only", T_OP_SET);
566                 if (!vp) rad_panic("Out of memory");
567                 pairadd(&request->proxy->vps, vp);
568
569                 vp = pairmake("Message-Authenticator", "0x00", T_OP_SET);
570                 if (!vp) rad_panic("Out of memory");
571                 pairadd(&request->proxy->vps, vp);
572
573         } else {
574                 request->proxy->code = PW_ACCOUNTING_REQUEST;
575
576                 vp = pairmake("User-Name", home->ping_user_name, T_OP_SET);
577                 if (!vp) rad_panic("Out of memory");
578                 pairadd(&request->proxy->vps, vp);
579
580                 vp = pairmake("Acct-Status-Type", "Stop", T_OP_SET);
581                 if (!vp) rad_panic("Out of memory");
582                 pairadd(&request->proxy->vps, vp);
583
584                 vp = pairmake("Acct-Session-Id", "00000000", T_OP_SET);
585                 if (!vp) rad_panic("Out of memory");
586                 pairadd(&request->proxy->vps, vp);
587
588                 vp = pairmake("Event-Timestamp", "0", T_OP_SET);
589                 if (!vp) rad_panic("Out of memory");
590                 vp->vp_date = now.tv_sec;
591                 pairadd(&request->proxy->vps, vp);
592         }
593
594         vp = pairmake("NAS-Identifier", "Status Check. Are you alive?", T_OP_SET);
595         if (!vp) rad_panic("Out of memory");
596         pairadd(&request->proxy->vps, vp);
597
598         request->proxy->dst_ipaddr = home->ipaddr;
599         request->proxy->dst_port = home->port;
600         request->home_server = home;
601
602         rad_assert(request->proxy_listener == NULL);
603
604         if (!insert_into_proxy_hash(request)) {
605                 DEBUG2("Failed inserting status check %d into proxy hash.  Discarding it.",
606                        request->number);
607                 request_free(&request);
608                 return;
609         }
610         rad_assert(request->proxy_listener != NULL);
611         request->proxy_listener->send(request->proxy_listener,
612                                       request);
613
614         request->child_state = REQUEST_PROXIED;
615         request->when.tv_sec += home->ping_timeout;;
616
617         INSERT_EVENT(no_response_to_ping, request);
618
619         /*
620          *      Add +/- 2s of jitter, as suggested in RFC 3539
621          *      and in the Issues and Fixes draft.
622          */
623         home->when.tv_sec += home->ping_interval - 2;
624
625         jitter = lrad_rand();
626         jitter ^= (jitter >> 10);
627         jitter &= ((1 << 23) - 1); /* 22 bits of 1 */
628
629         tv_add(&home->when, jitter);
630
631
632         INSERT_EVENT(ping_home_server, home);
633 }
634
635
636 static void check_for_zombie_home_server(REQUEST *request)
637 {
638         home_server *home;
639         struct timeval when;
640         char buffer[128];
641
642         home = request->home_server;
643
644         if (home->state != HOME_STATE_ZOMBIE) return;
645
646         when = home->zombie_period_start;
647         when.tv_sec += home->zombie_period;
648
649         if (timercmp(&now, &when, <)) {
650                 return;
651         }
652
653         /*
654          *      It's been a zombie for too long, mark it as
655          *      dead.
656          */
657         DEBUG2("FAILURE: Marking home server %s port %d as dead.",
658                inet_ntop(request->proxy->dst_ipaddr.af,
659                          &request->proxy->dst_ipaddr.ipaddr,
660                          buffer, sizeof(buffer)),
661                request->proxy->dst_port);
662         home->state = HOME_STATE_IS_DEAD;
663         home->num_received_pings = 0;
664         home->when = request->when;
665
666         if (home->ping_check != HOME_PING_CHECK_NONE) {
667                 rad_assert((home->ping_check == HOME_PING_CHECK_STATUS_SERVER) ||
668                            (home->ping_user_name != NULL));
669                 home->when.tv_sec += home->ping_interval;
670
671                 INSERT_EVENT(ping_home_server, home);
672         } else {
673                 home->when.tv_sec += home->revive_interval;
674
675                 INSERT_EVENT(revive_home_server, home);
676         }
677 }
678
679
680 static int setup_post_proxy_fail(REQUEST *request)
681 {
682         DICT_VALUE *dval = NULL;
683         VALUE_PAIR *vp;
684
685         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
686                 dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Authentication");
687
688         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
689                 dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Accounting");
690
691         } else {
692                 return 0;
693         }
694
695         if (!dval) dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail");
696
697         if (!dval) {
698                 pairdelete(&request->config_items, PW_POST_PROXY_TYPE);
699                 return 0;
700         }
701
702         vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
703         if (!vp) vp = radius_paircreate(request, &request->config_items,
704                                         PW_POST_PROXY_TYPE, PW_TYPE_INTEGER);
705         vp->vp_integer = dval->value;
706
707         rad_assert(request->proxy_reply == NULL);
708
709         return 1;
710 }
711
712
713 static int null_handler(UNUSED REQUEST *request)
714 {
715         return 0;
716 }
717
718 static void post_proxy_fail_handler(REQUEST *request)
719 {
720         /*
721          *      Not set up to run Post-Proxy-Type = Fail.
722          *
723          *      Mark the request as still running, and figure out what
724          *      to do next.
725          */
726         if (!setup_post_proxy_fail(request)) {
727                 request->child_state = REQUEST_RUNNING;
728                 request_post_handler(request);
729                 wait_a_bit(request);
730
731         } else {
732                 /*
733                  *      Re-queue the request.
734                  */
735                 request->child_state = REQUEST_QUEUED;
736
737                 wait_a_bit(request);
738
739                 /*
740                  *      There is a post-proxy-type of fail.  We run
741                  *      the request through the pre/post proxy
742                  *      handlers, just like it was a real proxied
743                  *      request.  However, we set the per-request
744                  *      handler to NULL, as we don't want to do
745                  *      anything else.
746                  */
747                 request->priority = 0;
748                 rad_assert(request->proxy != NULL);
749                 thread_pool_addrequest(request, null_handler);
750         }
751 }
752
753
754 /* maybe check this against wait_for_proxy_id_to_expire? */
755 static void no_response_to_proxied_request(void *ctx)
756 {
757         REQUEST *request = ctx;
758         home_server *home;
759         char buffer[128];
760
761         rad_assert(request->magic == REQUEST_MAGIC);
762         rad_assert(request->child_state == REQUEST_PROXIED);
763
764         radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s port %d",
765                request->number,
766                inet_ntop(request->proxy->dst_ipaddr.af,
767                          &request->proxy->dst_ipaddr.ipaddr,
768                          buffer, sizeof(buffer)),
769                request->proxy->dst_port);
770
771         check_for_zombie_home_server(request);
772
773         home = request->home_server;
774
775         post_proxy_fail_handler(request);
776
777         /*
778          *      Don't touch request due to race conditions
779          */
780         if (home->state == HOME_STATE_IS_DEAD) {
781                 rad_assert(home->ev != NULL); /* or it will never wake up */
782                 return;
783         }
784
785         /*
786          *      Enable the zombie period when we notice that the home
787          *      server hasn't responded.  We also back-date the start
788          *      of the zombie period to when the proxied request was
789          *      sent.
790          */
791         if (home->state == HOME_STATE_ALIVE) {
792                 DEBUG2("WARNING: Marking home server %s port %d as zombie (it looks like it is dead).",
793                        inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
794                                  buffer, sizeof(buffer)),
795                        home->port);
796                 home->state = HOME_STATE_ZOMBIE;
797                 home->zombie_period_start = now;
798                 home->zombie_period_start.tv_sec -= home->response_window;
799                 return;
800         }
801 }
802
803
804 static void wait_a_bit(void *ctx)
805 {
806         struct timeval when;
807         REQUEST *request = ctx;
808         lrad_event_callback_t callback = NULL;
809
810         rad_assert(request->magic == REQUEST_MAGIC);
811
812         switch (request->child_state) {
813         case REQUEST_QUEUED:
814         case REQUEST_RUNNING:
815                 when = request->received;
816                 when.tv_sec += mainconfig.max_request_time;
817
818                 if (timercmp(&now, &when, <)) {
819                         callback = wait_a_bit;
820                 } else {
821                         /* FIXME: kill unresponsive children? */
822                         radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d, in module %s component %s",
823                                (unsigned long)request->child_pid, request->number,
824                                request->module ? request->module : "<server core>",
825                                request->component ? request->component : "<server core>");
826
827                         request->master_state = REQUEST_STOP_PROCESSING;
828
829                         request->delay = USEC / 2;
830                         tv_add(&request->when, request->delay);
831                         callback = wait_for_child_to_die;
832                 }
833                 request->delay += request->delay >> 1;
834                 break;
835
836         case REQUEST_REJECT_DELAY:
837         case REQUEST_CLEANUP_DELAY:
838                 request->child_pid = NO_SUCH_CHILD_PID;
839                 snmp_inc_counters(request);
840
841         case REQUEST_PROXIED:
842                 rad_assert(request->next_callback != NULL);
843
844                 request->when = request->next_when;
845                 callback = request->next_callback;
846                 request->next_callback = NULL;
847                 break;
848
849                 /*
850                  *      Mark the request as no longer running,
851                  *      and clean it up.
852                  */
853         case REQUEST_DONE:
854                 request->child_pid = NO_SUCH_CHILD_PID;
855                 snmp_inc_counters(request);
856                 cleanup_delay(request);
857                 return;
858
859         default:
860                 rad_panic("Internal sanity check failure");
861                 return;
862         }
863
864         INSERT_EVENT(callback, request);
865 }
866
867
868 static int request_pre_handler(REQUEST *request)
869 {
870         int rcode;
871
872         rad_assert(request->magic == REQUEST_MAGIC);
873         rad_assert(request->packet != NULL);
874         rad_assert(request->packet->dst_port != 0);
875
876         request->child_state = REQUEST_RUNNING;
877
878         /*
879          *      Don't decode the packet if it's an internal "fake"
880          *      request.  Instead, just return so that the caller can
881          *      process it.
882          */
883         if (request->packet->dst_port == 0) {
884                 request->username = pairfind(request->packet->vps,
885                                              PW_USER_NAME);
886                 request->password = pairfind(request->packet->vps,
887                                              PW_USER_PASSWORD);
888                 return 1;
889         }
890
891         /*
892          *      Put the decoded packet into it's proper place.
893          */
894         if (request->proxy_reply != NULL) {
895                 rcode = request->proxy_listener->decode(request->proxy_listener,
896                                                         request);
897         } else if (request->packet->vps == NULL) {
898                 rcode = request->listener->decode(request->listener, request);
899
900         } else {
901                 rcode = 0;
902         }
903
904         if (rcode < 0) {
905                 radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
906                 request->child_state = REQUEST_DONE;
907                 return 0;
908         }
909
910         if (!request->proxy) {
911                 request->username = pairfind(request->packet->vps,
912                                              PW_USER_NAME);
913
914         } else {
915                 int post_proxy_type = 0;
916                 VALUE_PAIR *vp;
917
918                 /*
919                  *      Delete any reply we had accumulated until now.
920                  */
921                 pairfree(&request->reply->vps);
922
923                 /*
924                  *      Run the packet through the post-proxy stage,
925                  *      BEFORE playing games with the attributes.
926                  */
927                 vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
928                 if (vp) {
929                         DEBUG2("  Found Post-Proxy-Type %s", vp->vp_strvalue);
930                         post_proxy_type = vp->vp_integer;
931                 }
932                 rcode = module_post_proxy(post_proxy_type, request);
933
934                 /*
935                  *      There may NOT be a proxy reply, as we may be
936                  *      running Post-Proxy-Type = Fail.
937                  */
938                 if (request->proxy_reply) {
939                         /*
940                          *      Delete the Proxy-State Attributes from
941                          *      the reply.  These include Proxy-State
942                          *      attributes from us and remote server.
943                          */
944                         pairdelete(&request->proxy_reply->vps, PW_PROXY_STATE);
945
946                         /*
947                          *      Add the attributes left in the proxy
948                          *      reply to the reply list.
949                          */
950                         pairadd(&request->reply->vps, request->proxy_reply->vps);
951                         request->proxy_reply->vps = NULL;
952
953                         /*
954                          *      Free proxy request pairs.
955                          */
956                         pairfree(&request->proxy->vps);
957                 }
958
959                 switch (rcode) {
960                 default:  /* Don't do anything */
961                         break;
962                 case RLM_MODULE_FAIL:
963                         /* FIXME: debug print stuff */
964                         request->child_state = REQUEST_DONE;
965                         return 0;
966
967                 case RLM_MODULE_HANDLED:
968                         /* FIXME: debug print stuff */
969                         request->child_state = REQUEST_DONE;
970                         return 0;
971                 }
972         }
973
974         return 1;
975 }
976
977
978 /*
979  *      Return 1 if we did proxy it, or the proxy attempt failed
980  *      completely.  Either way, the caller doesn't touch the request
981  *      any more if we return 1.
982  */
983 static int successfully_proxied_request(REQUEST *request)
984 {
985         int rcode;
986         int pre_proxy_type = 0;
987         VALUE_PAIR *realmpair;
988         VALUE_PAIR *strippedname;
989         VALUE_PAIR *vp;
990         char *realmname;
991         home_server *home;
992         struct timeval when;
993         REALM *realm = NULL;
994         home_pool_t *pool;
995         char buffer[128];
996
997         realmpair = pairfind(request->config_items, PW_PROXY_TO_REALM);
998         if (!realmpair || (realmpair->length == 0)) {
999                 return 0;
1000         }
1001
1002         realmname = (char *) realmpair->vp_strvalue;
1003
1004         realm = realm_find(realmname);
1005         if (!realm) {
1006                 DEBUG2("ERROR: Cannot proxy to unknown realm %s", realmname);
1007                 return 0;
1008         }
1009
1010         /*
1011          *      Figure out which pool to use.
1012          */
1013         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
1014                 pool = realm->auth_pool;
1015
1016         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1017                 pool = realm->acct_pool;
1018
1019         } else {
1020                 rad_panic("Internal sanity check failed");
1021         }
1022
1023         if (!pool) {
1024                 DEBUG2(" WARNING: Cancelling proxy to Realm %s, as the realm is local.",
1025                        realmname);
1026                 return 0;
1027         }
1028
1029         home = home_server_ldb(realmname, pool, request);
1030         if (!home) {
1031                 DEBUG2("ERROR: Failed to find live home server for realm %s",
1032                        realmname);
1033                 return -1;
1034         }
1035         request->home_pool = pool;
1036
1037         /*
1038          *      Remember that we sent the request to a Realm.
1039          */
1040         pairadd(&request->packet->vps,
1041                 pairmake("Realm", realmname, T_OP_EQ));
1042
1043         /*
1044          *      We read the packet from a detail file, AND it came from
1045          *      the server we're about to send it to.  Don't do that.
1046          */
1047         if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
1048             (request->listener->type == RAD_LISTEN_DETAIL) &&
1049             (home->ipaddr.af == AF_INET) &&
1050             (request->packet->src_ipaddr.af == AF_INET) &&
1051             (home->ipaddr.ipaddr.ip4addr.s_addr == request->packet->src_ipaddr.ipaddr.ip4addr.s_addr)) {
1052                 DEBUG2("    rlm_realm: Packet came from realm %s, proxy cancelled", realmname);
1053                 return 0;
1054         }
1055
1056         /*
1057          *      Allocate the proxy packet, only if it wasn't already
1058          *      allocated by a module.  This check is mainly to support
1059          *      the proxying of EAP-TTLS and EAP-PEAP tunneled requests.
1060          *
1061          *      In those cases, the EAP module creates a "fake"
1062          *      request, and recursively passes it through the
1063          *      authentication stage of the server.  The module then
1064          *      checks if the request was supposed to be proxied, and
1065          *      if so, creates a proxy packet from the TUNNELED request,
1066          *      and not from the EAP request outside of the tunnel.
1067          *
1068          *      The proxy then works like normal, except that the response
1069          *      packet is "eaten" by the EAP module, and encapsulated into
1070          *      an EAP packet.
1071          */
1072         if (!request->proxy) {
1073                 if ((request->proxy = rad_alloc(TRUE)) == NULL) {
1074                         radlog(L_ERR|L_CONS, "no memory");
1075                         exit(1);
1076                 }
1077
1078                 /*
1079                  *      Copy the request, then look up name and
1080                  *      plain-text password in the copy.
1081                  *
1082                  *      Note that the User-Name attribute is the
1083                  *      *original* as sent over by the client.  The
1084                  *      Stripped-User-Name attribute is the one hacked
1085                  *      through the 'hints' file.
1086                  */
1087                 request->proxy->vps =  paircopy(request->packet->vps);
1088         }
1089
1090         /*
1091          *      Strip the name, if told to.
1092          *
1093          *      Doing it here catches the case of proxied tunneled
1094          *      requests.
1095          */
1096         if (realm->striprealm == TRUE &&
1097            (strippedname = pairfind(request->proxy->vps, PW_STRIPPED_USER_NAME)) != NULL) {
1098                 /*
1099                  *      If there's a Stripped-User-Name attribute in
1100                  *      the request, then use THAT as the User-Name
1101                  *      for the proxied request, instead of the
1102                  *      original name.
1103                  *
1104                  *      This is done by making a copy of the
1105                  *      Stripped-User-Name attribute, turning it into
1106                  *      a User-Name attribute, deleting the
1107                  *      Stripped-User-Name and User-Name attributes
1108                  *      from the vps list, and making the new
1109                  *      User-Name the head of the vps list.
1110                  */
1111                 vp = pairfind(request->proxy->vps, PW_USER_NAME);
1112                 if (!vp) {
1113                         vp = paircreate(PW_USER_NAME, PW_TYPE_STRING);
1114                         if (!vp) {
1115                                 radlog(L_ERR|L_CONS, "no memory");
1116                                 exit(1);
1117                         }
1118                         vp->next = request->proxy->vps;
1119                         request->proxy->vps = vp;
1120                 }
1121                 memcpy(vp->vp_strvalue, strippedname->vp_strvalue,
1122                        sizeof(vp->vp_strvalue));
1123                 vp->length = strippedname->length;
1124
1125                 /*
1126                  *      Do NOT delete Stripped-User-Name.
1127                  */
1128         }
1129
1130         /*
1131          *      If there is no PW_CHAP_CHALLENGE attribute but
1132          *      there is a PW_CHAP_PASSWORD we need to add it
1133          *      since we can't use the request authenticator
1134          *      anymore - we changed it.
1135          */
1136         if (pairfind(request->proxy->vps, PW_CHAP_PASSWORD) &&
1137             pairfind(request->proxy->vps, PW_CHAP_CHALLENGE) == NULL) {
1138                 vp = paircreate(PW_CHAP_CHALLENGE, PW_TYPE_STRING);
1139                 if (!vp) {
1140                         radlog(L_ERR|L_CONS, "no memory");
1141                         exit(1);
1142                 }
1143                 vp->length = AUTH_VECTOR_LEN;
1144                 memcpy(vp->vp_strvalue, request->packet->vector, AUTH_VECTOR_LEN);
1145                 pairadd(&(request->proxy->vps), vp);
1146         }
1147
1148         /*
1149          *      The RFC's say we have to do this, but FreeRADIUS
1150          *      doesn't need it.
1151          */
1152         vp = paircreate(PW_PROXY_STATE, PW_TYPE_STRING);
1153         if (!vp) {
1154                 radlog(L_ERR|L_CONS, "no memory");
1155                 exit(1);
1156         }
1157         sprintf(vp->vp_strvalue, "%d", request->packet->id);
1158         vp->length = strlen(vp->vp_strvalue);
1159
1160         pairadd(&request->proxy->vps, vp);
1161
1162         /*
1163          *      Should be done BEFORE inserting into proxy hash, as
1164          *      pre-proxy may use this information, or change it.
1165          */
1166         request->proxy->code = request->packet->code;
1167         request->proxy->dst_ipaddr = home->ipaddr;
1168         request->proxy->dst_port = home->port;
1169         request->home_server = home;
1170
1171         /*
1172          *      Call the pre-proxy routines.
1173          */
1174         vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE);
1175         if (vp) {
1176                 DEBUG2("  Found Pre-Proxy-Type %s", vp->vp_strvalue);
1177                 pre_proxy_type = vp->vp_integer;
1178         }
1179         rcode = module_pre_proxy(pre_proxy_type, request);
1180         switch (rcode) {
1181         case RLM_MODULE_FAIL:
1182         case RLM_MODULE_INVALID:
1183         case RLM_MODULE_NOTFOUND:
1184         case RLM_MODULE_USERLOCK:
1185         default:
1186                 /* FIXME: debug print failed stuff */
1187                 return -1;
1188
1189         case RLM_MODULE_REJECT:
1190         case RLM_MODULE_HANDLED:
1191                 return 0;
1192
1193         /*
1194          *      Only proxy the packet if the pre-proxy code succeeded.
1195          */
1196         case RLM_MODULE_NOOP:
1197         case RLM_MODULE_OK:
1198         case RLM_MODULE_UPDATED:
1199                 break;
1200         }
1201
1202         /*
1203          *      If it's a fake request, don't send the proxy
1204          *      packet.  The outer tunnel session will take
1205          *      care of doing that.
1206          */
1207         if (request->packet->dst_port == 0) {
1208                 request->home_server = NULL;
1209                 return 1;
1210         }
1211
1212         if (!insert_into_proxy_hash(request)) {
1213                 DEBUG("ERROR: Failed to proxy request %d", request->number);
1214                 return -1;
1215         }
1216
1217         request->proxy_listener->encode(request->proxy_listener, request);
1218
1219         when = request->received;
1220         when.tv_sec += mainconfig.max_request_time;
1221
1222         gettimeofday(&request->proxy_when, NULL);
1223
1224         request->next_when = request->proxy_when;
1225         request->next_when.tv_sec += home->response_window;
1226
1227         rad_assert(home->response_window > 0);
1228
1229         if (timercmp(&when, &request->next_when, <)) {
1230                 request->next_when = when;
1231         }
1232         request->next_callback = no_response_to_proxied_request;
1233
1234         DEBUG2("Proxying request %d to realm %s, home server %s port %d",
1235                request->number, realmname,
1236                inet_ntop(request->proxy->dst_ipaddr.af,
1237                          &request->proxy->dst_ipaddr.ipaddr,
1238                          buffer, sizeof(buffer)),
1239                request->proxy->dst_port);
1240
1241         /*
1242          *      Note that we set proxied BEFORE sending the packet.
1243          *
1244          *      Once we send it, the request is tainted, as
1245          *      another thread may have picked it up.  Don't
1246          *      touch it!
1247          */
1248         request->num_proxied_requests = 1;
1249         request->num_proxied_responses = 0;
1250         request->child_pid = NO_SUCH_CHILD_PID;
1251         request->child_state = REQUEST_PROXIED;
1252         request->proxy_listener->send(request->proxy_listener,
1253                                       request);
1254         return 1;
1255 }
1256
1257
1258 static void request_post_handler(REQUEST *request)
1259 {
1260         int child_state = -1;
1261         struct timeval when;
1262         VALUE_PAIR *vp;
1263
1264         if (request->master_state == REQUEST_STOP_PROCESSING) {
1265                 DEBUG2("Request %d was cancelled.", request->number);
1266                 request->child_pid = NO_SUCH_CHILD_PID;
1267                 request->child_state = REQUEST_DONE;
1268                 return;
1269         }
1270
1271         if (request->child_state != REQUEST_RUNNING) {
1272                 rad_panic("Internal sanity check failed");
1273         }
1274
1275         if ((request->reply->code == 0) &&
1276             ((vp = pairfind(request->config_items, PW_AUTH_TYPE)) != NULL) &&
1277             (vp->vp_integer == PW_AUTHTYPE_REJECT)) {
1278                 request->reply->code = PW_AUTHENTICATION_REJECT;
1279         }
1280
1281         if (mainconfig.proxy_requests &&
1282             !request->proxy &&
1283             (request->reply->code == 0) &&
1284             (request->packet->code != PW_STATUS_SERVER)) {
1285                 int rcode = successfully_proxied_request(request);
1286
1287                 if (rcode == 1) return;
1288
1289                 /*
1290                  *      Failed proxying it (dead home servers, etc.)
1291                  *      Run it through Post-Proxy-Type = Fail, and
1292                  *      respond to the request.
1293                  *
1294                  *      Note that we're in a child thread here, so we
1295                  *      do NOT re-schedule the request.  Instead, we
1296                  *      do what we would have done, which is run the
1297                  *      pre-handler, a NULL request handler, and then
1298                  *      the post handler.
1299                  */
1300                 if ((rcode < 0) && setup_post_proxy_fail(request)) {
1301                         request_pre_handler(request);
1302                 }
1303
1304                 /*
1305                  *      Else we weren't supposed to proxy it.
1306                  */
1307         }
1308
1309         /*
1310          *      Fake requests don't get encoded or signed.  The caller
1311          *      also requires the reply VP's, so we don't free them
1312          *      here!
1313          */
1314         if (request->packet->dst_port == 0) {
1315                 /* FIXME: DEBUG going to the next request */
1316                 request->child_pid = NO_SUCH_CHILD_PID;
1317                 request->child_state = REQUEST_DONE;
1318                 return;
1319         }
1320
1321         /*
1322          *      Copy Proxy-State from the request to the reply.
1323          */
1324         vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1325         if (vp) pairadd(&request->reply->vps, vp);
1326
1327         /*
1328          *      Access-Requests get delayed or cached.
1329          */
1330         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
1331                 gettimeofday(&request->next_when, NULL);
1332
1333                 if (request->reply->code == 0) {
1334                         /*
1335                          *      Check if the lack of response is intentional.
1336                          */
1337                         vp = pairfind(request->config_items,
1338                                       PW_RESPONSE_PACKET_TYPE);
1339                         if (!vp || (vp->vp_integer != 256)) {
1340                                 DEBUG2("There was no response configured: rejecting request %d",
1341                                        request->number);
1342                                 request->reply->code = PW_AUTHENTICATION_REJECT;
1343                         } else {
1344                                 DEBUG2("Not responding to request %d",
1345                                        request->number);
1346                         }
1347                 }
1348
1349                 /*
1350                  *      Run rejected packets through
1351                  *
1352                  *      Post-Auth-Type = Reject
1353                  */
1354                 if (request->reply->code == PW_AUTHENTICATION_REJECT) {
1355                         vp = pairmake("Post-Auth-Type", "Reject", T_OP_SET);
1356                         if (vp) {
1357                                 pairdelete(&request->config_items, PW_POST_AUTH_TYPE);
1358                                 pairadd(&request->config_items, vp);
1359                                 rad_postauth(request);
1360                         } /* else no Reject section defined */
1361
1362                         /*
1363                          *      If configured, delay Access-Reject packets.
1364                          *
1365                          *      If mainconfig.reject_delay = 0, we discover
1366                          *      that we have to send the packet now.
1367                          */
1368                         when = request->received;
1369                         when.tv_sec += mainconfig.reject_delay;
1370
1371                         if (timercmp(&when, &request->next_when, >)) {
1372                                 DEBUG2("Delaying reject of request %d for %d seconds",
1373                                        request->number,
1374                                        mainconfig.reject_delay);
1375                                 request->next_when = when;
1376                                 request->next_callback = reject_delay;
1377                                 request->child_pid = NO_SUCH_CHILD_PID;
1378                                 request->child_state = REQUEST_REJECT_DELAY;
1379                                 return;
1380                         }
1381                 }
1382
1383                 request->next_when.tv_sec += mainconfig.cleanup_delay;
1384                 request->next_callback = cleanup_delay;
1385                 child_state = REQUEST_CLEANUP_DELAY;
1386
1387         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1388                 request->next_callback = NULL; /* just to be safe */
1389                 child_state = REQUEST_DONE;
1390
1391                 /*
1392                  *      FIXME: Status-Server should probably not be
1393                  *      handled here...
1394                  */
1395         } else if (request->packet->code == PW_STATUS_SERVER) {
1396                 request->next_callback = NULL;
1397                 child_state = REQUEST_DONE;
1398
1399         } else {
1400                 rad_panic("Unknown packet type");
1401         }
1402
1403         /*
1404          *      If configured, encode, sign, and send.
1405          */
1406         if (request->reply->code != 0) {
1407                 request->listener->send(request->listener, request);
1408         }
1409
1410         /*
1411          *      Clean up.  These are no longer needed.
1412          */
1413         pairfree(&request->config_items);
1414
1415         pairfree(&request->packet->vps);
1416         request->username = NULL;
1417         request->password = NULL;
1418
1419         pairfree(&request->reply->vps);
1420
1421         if (request->proxy) {
1422                 pairfree(&request->proxy->vps);
1423
1424                 if (request->proxy_reply) {
1425                         pairfree(&request->proxy_reply->vps);
1426                 }
1427
1428                 /*
1429                  *      We're not tracking responses from the home
1430                  *      server, we can therefore free this memory in
1431                  *      the child thread.
1432                  */
1433                 if (!request->in_proxy_hash) {
1434                         rad_free(&request->proxy);
1435                         rad_free(&request->proxy_reply);
1436                         request->home_server = NULL;
1437                 }
1438         }
1439
1440         DEBUG2("Finished request %d state %d", request->number, child_state);
1441
1442         request->child_state = child_state;
1443 }
1444
1445
1446 static void received_retransmit(REQUEST *request, const RADCLIENT *client)
1447 {
1448         char buffer[128];
1449
1450         RAD_SNMP_TYPE_INC(request->listener, total_dup_requests);
1451         RAD_SNMP_CLIENT_INC(request->listener, client, dup_requests);
1452
1453         switch (request->child_state) {
1454         case REQUEST_QUEUED:
1455         case REQUEST_RUNNING:
1456         discard:
1457                 radlog(L_ERR, "Discarding duplicate request from "
1458                        "client %s port %d - ID: %d due to unfinished request %d",
1459                        client->shortname,
1460                        request->packet->src_port,request->packet->id,
1461                        request->number);
1462                 break;
1463
1464         case REQUEST_PROXIED:
1465                 /*
1466                  *      We're not supposed to have duplicate
1467                  *      accounting packets.  The other states handle
1468                  *      duplicates fine (discard, or send duplicate
1469                  *      reply).  But we do NOT want to retransmit an
1470                  *      accounting request here, because that would
1471                  *      involve updating the Acct-Delay-Time, and
1472                  *      therefore changing the packet Id, etc.
1473                  *
1474                  *      Instead, we just discard the packet.  We may
1475                  *      eventually respond, or the client will send a
1476                  *      new accounting packet.
1477                  */
1478                 if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1479                         goto discard;
1480                 }
1481
1482                 check_for_zombie_home_server(request);
1483
1484                 /*
1485                  *      If we've just discovered that the home server is
1486                  *      dead, send the packet to another one.
1487                  */
1488                 if ((request->packet->dst_port != 0) &&
1489                     (request->home_server->state == HOME_STATE_IS_DEAD)) {
1490                         home_server *home;
1491
1492                         remove_from_proxy_hash(request);
1493
1494                         home = home_server_ldb(NULL, request->home_pool, request);
1495                         if (!home) {
1496                                 DEBUG2("Failed to find live home server for request %d", request->number);
1497                         no_home_servers:
1498                                 /*
1499                                  *      Do post-request processing,
1500                                  *      and any insertion of necessary
1501                                  *      events.
1502                                  */
1503                                 post_proxy_fail_handler(request);
1504                                 return;
1505                         }
1506
1507                         request->proxy->code = request->packet->code;
1508                         request->proxy->dst_ipaddr = home->ipaddr;
1509                         request->proxy->dst_port = home->port;
1510                         request->home_server = home;
1511
1512                         if (!insert_into_proxy_hash(request)) {
1513                                 DEBUG("ERROR: Failed to re-proxy request %d", request->number);
1514                                 goto no_home_servers;
1515                         }
1516
1517                         /*
1518                          *      Free the old packet, to force re-encoding
1519                          */
1520                         free(request->proxy->data);
1521                         request->proxy->data = NULL;
1522                         request->proxy->data_len = 0;
1523
1524                         DEBUG2("RETRY: Proxying request %d to different home server %s port %d",
1525                                request->number,
1526                                inet_ntop(request->proxy->dst_ipaddr.af,
1527                                          &request->proxy->dst_ipaddr.ipaddr,
1528                                          buffer, sizeof(buffer)),
1529                                request->proxy->dst_port);
1530
1531                         /*
1532                          *      Restart timers.  Note that we leave
1533                          *      the old timeout in place, as that is a
1534                          *      place-holder for when the request
1535                          *      times out.
1536                          */
1537                         gettimeofday(&request->proxy_when, NULL);
1538                         request->num_proxied_requests = 1;
1539                         request->num_proxied_responses = 0;
1540                         request->child_pid = NO_SUCH_CHILD_PID;
1541                         request->child_state = REQUEST_PROXIED;
1542                         request->proxy_listener->send(request->proxy_listener,
1543                                                       request);
1544                         return;
1545                 } /* else the home server is still alive */
1546
1547                 DEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",
1548                        inet_ntop(request->proxy->dst_ipaddr.af,
1549                                  &request->proxy->dst_ipaddr.ipaddr,
1550                                  buffer, sizeof(buffer)),
1551                        request->proxy->dst_port,
1552                        request->proxy->id);
1553                 request->num_proxied_requests++;
1554                 request->proxy_listener->send(request->proxy_listener,
1555                                               request);
1556                 break;
1557
1558         case REQUEST_REJECT_DELAY:
1559                 DEBUG2("Waiting to send Access-Reject "
1560                        "to client %s port %d - ID: %d",
1561                        client->shortname,
1562                        request->packet->src_port, request->packet->id);
1563                 break;
1564
1565         case REQUEST_CLEANUP_DELAY:
1566         case REQUEST_DONE:
1567                 DEBUG2("Sending duplicate reply "
1568                        "to client %s port %d - ID: %d",
1569                        client->shortname,
1570                        request->packet->src_port, request->packet->id);
1571                 request->listener->send(request->listener, request);
1572                 break;
1573         }
1574 }
1575
1576
1577 static void received_conflicting_request(REQUEST *request,
1578                                          const RADCLIENT *client)
1579 {
1580         radlog(L_ERR, "Received conflicting packet from "
1581                "client %s port %d - ID: %d due to unfinished request %d.  Giving up on old request.",
1582                client->shortname,
1583                request->packet->src_port, request->packet->id,
1584                request->number);
1585
1586         switch (request->child_state) {
1587         case REQUEST_QUEUED:
1588         case REQUEST_RUNNING:
1589                 request->master_state = REQUEST_STOP_PROCESSING;
1590                 request->delay += request->delay >> 1;
1591
1592                 tv_add(&request->when, request->delay);
1593
1594                 INSERT_EVENT(wait_for_child_to_die, request);
1595                 return;
1596
1597         default:
1598                 break;
1599         }
1600
1601         remove_from_request_hash(request);
1602
1603         /*
1604          *      The request stays in the event queue.  At some point,
1605          *      the child will notice, and we can then delete it.
1606          */
1607 }
1608
1609
1610 static int can_handle_new_request(RADIUS_PACKET *packet,
1611                                   RADCLIENT *client)
1612 {
1613         /*
1614          *      Count the total number of requests, to see if
1615          *      there are too many.  If so, return with an
1616          *      error.
1617          */
1618         if (mainconfig.max_requests) {
1619                 int request_count = lrad_packet_list_num_elements(pl);
1620
1621                 /*
1622                  *      This is a new request.  Let's see if
1623                  *      it makes us go over our configured
1624                  *      bounds.
1625                  */
1626                 if (request_count > mainconfig.max_requests) {
1627                         radlog(L_ERR, "Dropping request (%d is too many): "
1628                                "from client %s port %d - ID: %d", request_count,
1629                                client->shortname,
1630                                packet->src_port, packet->id);
1631                         radlog(L_INFO, "WARNING: Please check the %s file.\n"
1632                                "\tThe value for 'max_requests' is probably set too low.\n", mainconfig.radiusd_conf);
1633                         return 0;
1634                 } /* else there were a small number of requests */
1635         } /* else there was no configured limit for requests */
1636
1637         /*
1638          *      FIXME: Add per-client checks.  If one client is sending
1639          *      too many packets, start discarding them.
1640          *
1641          *      We increment the counters here, and decrement them
1642          *      when the response is sent... somewhere in this file.
1643          */
1644
1645         /*
1646          *      FUTURE: Add checks for system load.  If the system is
1647          *      busy, start dropping requests...
1648          *
1649          *      We can probably keep some statistics ourselves...  if
1650          *      there are more requests coming in than we can handle,
1651          *      start dropping some.
1652          */
1653
1654         return 1;
1655 }
1656
1657
1658 int received_request(rad_listen_t *listener,
1659                      RADIUS_PACKET *packet, REQUEST **prequest,
1660                      RADCLIENT *client)
1661 {
1662         RADIUS_PACKET **packet_p;
1663         REQUEST *request = NULL;
1664
1665         packet_p = lrad_packet_list_find(pl, packet);
1666         if (packet_p) {
1667                 request = lrad_packet2myptr(REQUEST, packet, packet_p);
1668
1669                 if ((request->packet->data_len == packet->data_len) &&
1670                     (memcmp(request->packet->vector, packet->vector,
1671                             sizeof(packet->vector)) == 0)) {
1672                         received_retransmit(request, client);
1673                         return 0;
1674                 }
1675
1676                 /*
1677                  *      The new request is different from the old one,
1678                  *      but maybe the old is finished.  If so, delete
1679                  *      the old one.
1680                  */
1681                 switch (request->child_state) {
1682                 default:
1683                         received_conflicting_request(request, client);
1684                         request = NULL;
1685                         break;
1686
1687                 case REQUEST_REJECT_DELAY:
1688                 case REQUEST_CLEANUP_DELAY:
1689                         request->child_state = REQUEST_DONE;
1690                 case REQUEST_DONE:
1691                         cleanup_delay(request);
1692                         request = NULL;
1693                         break;
1694                 }
1695
1696
1697         }
1698
1699         /*
1700          *      We may want to quench the new request.
1701          */
1702         if (!can_handle_new_request(packet, client)) {
1703                 return 0;
1704         }
1705
1706         /*
1707          *      Create and initialize the new request.
1708          */
1709         request = request_alloc(); /* never fails */
1710
1711         if ((request->reply = rad_alloc(0)) == NULL) {
1712                 radlog(L_ERR, "No memory");
1713                 exit(1);
1714         }
1715
1716         request->listener = listener;
1717         request->client = client;
1718         request->packet = packet;
1719         request->packet->timestamp = request->timestamp;
1720         request->number = request_num_counter++;
1721         request->priority = listener->type;
1722
1723         /*
1724          *      Remember the request in the list.
1725          */
1726         if (!lrad_packet_list_insert(pl, &request->packet)) {
1727                 radlog(L_ERR, "Failed to insert request %d in the list of live requests: discarding", request->number);
1728                 request_free(&request);
1729                 return 0;
1730         }
1731         request->in_request_hash = TRUE;
1732
1733         /*
1734          *      The request passes many of our sanity checks.
1735          *      From here on in, if anything goes wrong, we
1736          *      send a reject message, instead of dropping the
1737          *      packet.
1738          */
1739
1740         /*
1741          *      Build the reply template from the request.
1742          */
1743
1744         request->reply->sockfd = request->packet->sockfd;
1745         request->reply->dst_ipaddr = request->packet->src_ipaddr;
1746         request->reply->src_ipaddr = request->packet->dst_ipaddr;
1747         request->reply->dst_port = request->packet->src_port;
1748         request->reply->src_port = request->packet->dst_port;
1749         request->reply->id = request->packet->id;
1750         request->reply->code = 0; /* UNKNOWN code */
1751         memcpy(request->reply->vector, request->packet->vector,
1752                sizeof(request->reply->vector));
1753         request->reply->vps = NULL;
1754         request->reply->data = NULL;
1755         request->reply->data_len = 0;
1756
1757         request->master_state = REQUEST_ACTIVE;
1758         request->child_state = REQUEST_QUEUED;
1759         request->next_callback = NULL;
1760
1761         gettimeofday(&request->received, NULL);
1762         request->timestamp = request->received.tv_sec;
1763         request->when = request->received;
1764
1765         request->delay = USEC / 10;
1766
1767         tv_add(&request->when, request->delay);
1768
1769         INSERT_EVENT(wait_a_bit, request);
1770
1771         *prequest = request;
1772         return 1;
1773 }
1774
1775
1776 REQUEST *received_proxy_response(RADIUS_PACKET *packet)
1777 {
1778         char            buffer[128];
1779         home_server     *home;
1780         REQUEST         *request;
1781
1782         if (!home_server_find(&packet->src_ipaddr, packet->src_port)) {
1783                 radlog(L_ERR, "Ignoring request from unknown home server %s port %d",
1784                        inet_ntop(packet->src_ipaddr.af,
1785                                  &packet->src_ipaddr.ipaddr,
1786                                  buffer, sizeof(buffer)),
1787                                packet->src_port);
1788                 rad_free(&packet);
1789                 return NULL;
1790         }
1791
1792         /*
1793          *      Also removes from the proxy hash if responses == requests
1794          */
1795         request = lookup_in_proxy_hash(packet);
1796
1797         if (!request) {
1798                 radlog(L_PROXY, "No outstanding request was found for proxy reply from home server %s port %d - ID %d",
1799                        inet_ntop(packet->src_ipaddr.af,
1800                                  &packet->src_ipaddr.ipaddr,
1801                                  buffer, sizeof(buffer)),
1802                        packet->src_port, packet->id);
1803                 rad_free(&packet);
1804                 return NULL;
1805         }
1806
1807         home = request->home_server;
1808
1809         gettimeofday(&now, NULL);
1810         home->state = HOME_STATE_ALIVE;
1811
1812         if (request->reply && request->reply->code != 0) {
1813                 DEBUG2("We already replied to this request.  Discarding response from home server.");
1814                 rad_free(&packet);
1815                 return NULL;
1816         }
1817
1818         /*
1819          *      We had previously received a reply, so we don't need
1820          *      to do anything here.
1821          */
1822         if (request->proxy_reply) {
1823                 if (memcmp(request->proxy_reply->vector,
1824                            packet->vector,
1825                            sizeof(request->proxy_reply->vector)) == 0) {
1826                         DEBUG2("Discarding duplicate reply from home server %s port %d  - ID: %d for request %d",
1827                                inet_ntop(packet->src_ipaddr.af,
1828                                          &packet->src_ipaddr.ipaddr,
1829                                          buffer, sizeof(buffer)),
1830                                packet->src_port, packet->id,
1831                                request->number);
1832                 } else {
1833                         /*
1834                          *      ? The home server gave us a new proxy
1835                          *      reply, which doesn't match the old
1836                          *      one.  Delete it.
1837                          */
1838                         DEBUG2("Ignoring conflicting proxy reply");
1839                 }
1840
1841                 /* assert that there's an event queued for request? */
1842                 rad_free(&packet);
1843                 return NULL;
1844         }
1845
1846         switch (request->child_state) {
1847         case REQUEST_QUEUED:
1848         case REQUEST_RUNNING:
1849                 rad_panic("Internal sanity check failed for child state");
1850                 break;
1851
1852         case REQUEST_REJECT_DELAY:
1853         case REQUEST_CLEANUP_DELAY:
1854         case REQUEST_DONE:
1855                 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'",
1856                        inet_ntop(packet->src_ipaddr.af,
1857                                  &packet->src_ipaddr.ipaddr,
1858                                  buffer, sizeof(buffer)),
1859                        packet->src_port, packet->id,
1860                        request->number);
1861                 /* assert that there's an event queued for request? */
1862                 rad_free(&packet);
1863                 return NULL;
1864
1865         case REQUEST_PROXIED:
1866                 break;
1867         }
1868
1869         request->proxy_reply = packet;
1870
1871 #if 0
1872         /*
1873          *      Perform RTT calculations, as per RFC 2988 (for TCP).
1874          *      Note that we do so only if we sent one request, and
1875          *      received one response.  If we sent two requests, we
1876          *      have no idea if the response is for the first, or for
1877          *      the second request/
1878          */
1879         if (request->num_proxied_requests == 1) {
1880                 int rtt;
1881                 home_server *home = request->home_server;
1882
1883                 rtt = now.tv_sec - request->proxy_when.tv_sec;
1884                 rtt *= USEC;
1885                 rtt += now.tv_usec;
1886                 rtt -= request->proxy_when.tv_usec;
1887
1888                 if (!home->has_rtt) {
1889                         home->has_rtt = TRUE;
1890
1891                         home->srtt = rtt;
1892                         home->rttvar = rtt / 2;
1893
1894                 } else {
1895                         home->rttvar -= home->rttvar >> 2;
1896                         home->rttvar += (home->srtt - rtt);
1897                         home->srtt -= home->srtt >> 3;
1898                         home->srtt += rtt >> 3;
1899                 }
1900
1901                 home->rto = home->srtt;
1902                 if (home->rttvar > (USEC / 4)) {
1903                         home->rto += home->rttvar * 4;
1904                 } else {
1905                         home->rto += USEC;
1906                 }
1907         }
1908 #endif
1909
1910         /*
1911          *      There's no incoming request, so it's a proxied packet
1912          *      we originated.
1913          */
1914         if (!request->packet) {
1915                 received_response_to_ping(request);
1916                 return NULL;
1917         }
1918
1919         request->child_state = REQUEST_QUEUED;
1920         request->when = now;
1921         request->delay = USEC / 10;
1922         request->priority = RAD_LISTEN_PROXY;
1923         tv_add(&request->when, request->delay);
1924
1925         /*
1926          *      Wait a bit will take care of max_request_time
1927          */
1928         INSERT_EVENT(wait_a_bit, request);
1929
1930         return request;
1931 }
1932
1933
1934 /*
1935  *      Externally-visibly functions.
1936  */
1937 int radius_event_init(int spawn_flag)
1938 {
1939         if (el) return 0;
1940
1941         time(&start_time);
1942
1943         el = lrad_event_list_create();
1944         if (!el) return 0;
1945
1946         pl = lrad_packet_list_create(0);
1947         if (!el) return 0;
1948
1949         request_num_counter = 0;
1950
1951         /*
1952          *      Move all of the thread calls to this file?
1953          *
1954          *      It may be best for the mutexes to be in this file...
1955          */
1956         have_children = spawn_flag;
1957
1958         if (mainconfig.proxy_requests) {
1959                 int i;
1960                 rad_listen_t *listener;
1961
1962                 /*
1963                  *      Create the tree for managing proxied requests and
1964                  *      responses.
1965                  */
1966                 proxy_list = lrad_packet_list_create(1);
1967                 if (!proxy_list) return 0;
1968
1969 #ifdef HAVE_PTHREAD_H
1970                 if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
1971                         radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
1972                                strerror(errno));
1973                         exit(1);
1974                 }
1975 #endif
1976
1977                 /*
1978                  *      Mark the Fd's as unused.
1979                  */
1980                 for (i = 0; i < 32; i++) proxy_fds[i] = -1;
1981
1982                 i = -1;
1983
1984                 for (listener = mainconfig.listen;
1985                      listener != NULL;
1986                      listener = listener->next) {
1987                         if (listener->type == RAD_LISTEN_PROXY) {
1988                                 /*
1989                                  *      FIXME: This works only because we
1990                                  *      start off with one proxy socket.
1991                                  */
1992                                 rad_assert(proxy_fds[listener->fd & 0x1f] == -1);
1993                                 rad_assert(proxy_listeners[listener->fd & 0x1f] == NULL);
1994
1995                                 proxy_fds[listener->fd & 0x1f] = listener->fd;
1996                                 proxy_listeners[listener->fd & 0x1f] = listener;
1997                                 if (!lrad_packet_list_socket_add(proxy_list, listener->fd)) {
1998                                         rad_assert(0 == 1);
1999                                 }
2000                                 i = listener->fd;
2001                         }
2002                 }
2003
2004                 if (mainconfig.proxy_requests) rad_assert(i >= 0);
2005         }
2006
2007         thread_pool_init(spawn_flag);
2008
2009         return 1;
2010 }
2011
2012
2013 static int request_hash_cb(void *ctx, void *data)
2014 {
2015         ctx = ctx;              /* -Wunused */
2016         REQUEST *request = lrad_packet2myptr(REQUEST, packet, data);
2017
2018         rad_assert(request->in_proxy_hash == FALSE);
2019
2020         lrad_event_delete(el, &request->ev);
2021         remove_from_request_hash(request);
2022         request_free(&request);
2023
2024         return 0;
2025 }
2026
2027
2028 static int proxy_hash_cb(void *ctx, void *data)
2029 {
2030         ctx = ctx;              /* -Wunused */
2031         REQUEST *request = lrad_packet2myptr(REQUEST, proxy, data);
2032
2033         lrad_packet_list_yank(proxy_list, request->proxy);
2034         request->in_proxy_hash = FALSE;
2035
2036         if (!request->in_request_hash) {
2037                 lrad_event_delete(el, &request->ev);
2038                 request_free(&request);
2039         }
2040
2041         return 0;
2042 }
2043
2044
2045 void radius_event_free(void)
2046 {
2047         /*
2048          *      FIXME: Stop all threads, or at least check that
2049          *      they're all waiting on the semaphore, and the queues
2050          *      are empty.
2051          */
2052
2053         /*
2054          *      There are requests in the proxy hash that aren't
2055          *      referenced from anywhere else.  Remove them first.
2056          */
2057         if (proxy_list) {
2058                 PTHREAD_MUTEX_LOCK(&proxy_mutex);
2059                 lrad_packet_list_walk(proxy_list, NULL, proxy_hash_cb);
2060                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
2061                 lrad_packet_list_free(proxy_list);
2062                 proxy_list = NULL;
2063         }
2064
2065         lrad_packet_list_walk(pl, NULL, request_hash_cb);
2066
2067         lrad_packet_list_free(pl);
2068         pl = NULL;
2069
2070         lrad_event_list_free(el);
2071 }
2072
2073 int radius_event_process(struct timeval **pptv)
2074 {
2075         int rcode;
2076         struct timeval when;
2077
2078         if (!el) return 0;
2079
2080         if (lrad_event_list_num_elements(el) == 0) {
2081                 *pptv = NULL;
2082                 return 1;
2083         }
2084
2085         gettimeofday(&now, NULL);
2086         when = now;
2087
2088         do {
2089                 rcode = lrad_event_run(el, &when);
2090         } while (rcode == 1);
2091
2092         gettimeofday(&now, NULL);
2093
2094         if ((when.tv_sec == 0) && (when.tv_usec == 0)) {
2095                 if (lrad_event_list_num_elements(el) == 0) {
2096                         *pptv = NULL;
2097                         return 1;
2098                 }
2099                 rad_panic("Internal sanity check failed");
2100
2101         } else if (timercmp(&now, &when, >)) {
2102                 DEBUG3("Event in the past... compensating");
2103                 when.tv_sec = 0;
2104                 when.tv_usec = 1;
2105
2106         } else {
2107                 when.tv_sec -= now.tv_sec;
2108                 when.tv_usec -= now.tv_usec;
2109                 if (when.tv_usec < 0) {
2110                         when.tv_sec--;
2111                         when.tv_usec += USEC;
2112                 }
2113         }
2114         **pptv = when;
2115
2116         return 1;
2117 }
2118
2119 void radius_handle_request(REQUEST *request, RAD_REQUEST_FUNP fun)
2120 {
2121         if (!request_pre_handler(request)) {
2122                 DEBUG2("Going to the next request");
2123                 return;
2124         }
2125
2126         rad_assert(fun != NULL);
2127         rad_assert(request != NULL);
2128
2129         fun(request);
2130
2131         request_post_handler(request);
2132         DEBUG2("Going to the next request");
2133         return;
2134 }