L_INFO, "PROXY:... --> L_PROXY, "...
[freeradius.git] / src / main / event.c
1 /*
2  * event.c      Server event handling
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2007  The FreeRADIUS server project
21  * Copyright 2007  Alan DeKok <aland@deployingradius.com>
22  */
23
24 #include <freeradius-devel/ident.h>
25 RCSID("$Id$")
26
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/event.h>
30 #include <freeradius-devel/detail.h>
31
32 #include <freeradius-devel/rad_assert.h>
33
34 #include <signal.h>
35 #include <fcntl.h>
36
37 #ifdef HAVE_SYS_WAIT_H
38 #       include <sys/wait.h>
39 #endif
40
41 #define USEC (1000000)
42
43 extern pid_t radius_pid;
44 extern int dont_fork;
45 extern int check_config;
46 extern void force_log_reopen(void);
47 extern char *debug_condition;
48
49 /*
50  *      Ridiculous amounts of local state.
51  */
52 static fr_event_list_t  *el = NULL;
53 static fr_packet_list_t *pl = NULL;
54 static int                      request_num_counter = 0;
55 static struct timeval           now;
56 time_t                          fr_start_time;
57 static int                      have_children;
58 static int                      just_started = TRUE;
59
60 #ifndef __MINGW32__
61 #ifdef HAVE_PTHREAD_H
62 #define WITH_SELF_PIPE (1)
63 #endif
64 #endif
65
66 #ifdef WITH_SELF_PIPE
67 static int self_pipe[2];
68 #endif
69
70 #ifdef HAVE_PTHREAD_H
71 #ifdef WITH_PROXY
72 static pthread_mutex_t  proxy_mutex;
73 static rad_listen_t *proxy_listener_list = NULL;
74 #endif
75
76 #define PTHREAD_MUTEX_LOCK if (have_children) pthread_mutex_lock
77 #define PTHREAD_MUTEX_UNLOCK if (have_children) pthread_mutex_unlock
78
79 static pthread_t NO_SUCH_CHILD_PID;
80 #else
81 /*
82  *      This is easier than ifdef's throughout the code.
83  */
84 #define PTHREAD_MUTEX_LOCK(_x)
85 #define PTHREAD_MUTEX_UNLOCK(_x)
86 int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
87 {
88         radius_handle_request(request, fun);
89         return 1;
90 }
91 #endif
92
93 /*
94  *      We need mutexes around the event FD list *only* in certain
95  *      cases.
96  */
97 #if defined (HAVE_PTHREAD_H) && (defined(WITH_PROXY) || defined(WITH_TCP))
98 static pthread_mutex_t  fd_mutex;
99 #define FD_MUTEX_LOCK if (have_children) pthread_mutex_lock
100 #define FD_MUTEX_UNLOCK if (have_children) pthread_mutex_unlock
101 #else
102 /*
103  *      This is easier than ifdef's throughout the code.
104  */
105 #define FD_MUTEX_LOCK(_x)
106 #define FD_MUTEX_UNLOCK(_x)
107 #endif
108
109
110 #define INSERT_EVENT(_function, _ctx) if (!fr_event_insert(el, _function, _ctx, &((_ctx)->when), &((_ctx)->ev))) { _rad_panic(__FILE__, __LINE__, "Failed to insert event"); }
111
112 #ifdef WITH_PROXY
113 static fr_packet_list_t *proxy_list = NULL;
114 static void remove_from_proxy_hash(REQUEST *request);
115
116 static void check_for_zombie_home_server(REQUEST *request);
117 #else
118 #define remove_from_proxy_hash(foo)
119 #endif
120
121 static void request_post_handler(REQUEST *request);
122 static void wait_a_bit(void *ctx);
123 static void event_socket_handler(fr_event_list_t *xel, UNUSED int fd, void *ctx);
124 #ifdef WITH_DETAIL
125 static void event_poll_detail(void *ctx);
126 #endif
127
128 static void NEVER_RETURNS _rad_panic(const char *file, unsigned int line,
129                                     const char *msg)
130 {
131         radlog(L_ERR, "[%s:%d] %s", file, line, msg);
132         _exit(1);
133 }
134
135 #define rad_panic(x) _rad_panic(__FILE__, __LINE__, x)
136
137
138 static void tv_add(struct timeval *tv, int usec_delay)
139 {
140         if (usec_delay > USEC) {
141                 tv->tv_sec += usec_delay / USEC;
142                 usec_delay %= USEC;
143         }
144         tv->tv_usec += usec_delay;
145
146         if (tv->tv_usec > USEC) {
147                 tv->tv_usec -= USEC;
148                 tv->tv_sec++;
149         }
150 }
151
152 static void remove_from_request_hash(REQUEST *request)
153 {
154         if (!request->in_request_hash) return;
155
156         fr_packet_list_yank(pl, request->packet);
157         request->in_request_hash = FALSE;
158
159         request_stats_final(request);
160
161 #ifdef WITH_TCP
162         request->listener->count--;
163 #endif
164 }
165
166 #ifdef WITH_PROXY
167 static REQUEST *lookup_in_proxy_hash(RADIUS_PACKET *reply)
168 {
169         int done = FALSE;
170         RADIUS_PACKET **proxy_p;
171         REQUEST *request;
172
173         PTHREAD_MUTEX_LOCK(&proxy_mutex);
174         proxy_p = fr_packet_list_find_byreply(proxy_list, reply);
175
176         if (!proxy_p) {
177                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
178                 return NULL;
179         }
180
181         request = fr_packet2myptr(REQUEST, proxy, proxy_p);
182         request->num_proxied_responses++; /* needs to be protected by lock */
183
184         done = (request->num_proxied_requests == request->num_proxied_responses);
185         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
186
187
188         /*
189          *      Catch the most common case of everything working
190          *      correctly.
191          */
192         if (done) remove_from_proxy_hash(request);
193
194         return request;
195 }
196
197
198 static void remove_from_proxy_hash(REQUEST *request)
199 {
200         /*
201          *      Check this without grabbing the mutex because it's a
202          *      lot faster that way.
203          */
204         if (!request->in_proxy_hash) return;
205
206         /*
207          *      The "not in hash" flag is definitive.  However, if the
208          *      flag says that it IS in the hash, there might still be
209          *      a race condition where it isn't.
210          */
211         PTHREAD_MUTEX_LOCK(&proxy_mutex);
212
213         if (!request->in_proxy_hash) {
214                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
215                 return;
216         }
217
218         fr_packet_list_yank(proxy_list, request->proxy);
219         fr_packet_list_id_free(proxy_list, request->proxy);
220
221         /*
222          *      On the FIRST reply, decrement the count of outstanding
223          *      requests.  Note that this is NOT the count of sent
224          *      packets, but whether or not the home server has
225          *      responded at all.
226          */
227         if (!request->proxy_reply &&
228             request->home_server &&
229             request->home_server->currently_outstanding) {
230                 request->home_server->currently_outstanding--;
231         }
232
233 #ifdef WITH_TCP
234         request->proxy_listener->count--;
235         request->proxy_listener = NULL;
236 #endif
237
238         /*
239          *      Got from YES in hash, to NO, not in hash while we hold
240          *      the mutex.  This guarantees that when another thread
241          *      grabs the mutex, the "not in hash" flag is correct.
242          */
243         request->in_proxy_hash = FALSE;
244
245         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
246 }
247 #endif  /* WITH_PROXY */
248
249 static void ev_request_free(REQUEST **prequest)
250 {
251         REQUEST *request;
252         
253         if (!prequest || !*prequest) return;
254
255         request = *prequest;
256
257 #ifdef WITH_COA
258         if (request->coa) {
259                 /*
260                  *      Divorce the child from the parent first,
261                  *      then clean up the child.
262                  */
263                 request->coa->parent = NULL;
264                 ev_request_free(&request->coa);
265         }
266
267         /*
268          *      Divorce the parent from the child, and leave the
269          *      parent still alive.
270          */
271         if (request->parent && (request->parent->coa == request)) {
272                 request->parent->coa = NULL;
273         }
274 #endif
275
276         if (request->ev) fr_event_delete(el, &request->ev);
277 #ifdef WITH_PROXY
278         if (request->in_proxy_hash) remove_from_proxy_hash(request);
279 #endif
280         if (request->in_request_hash) remove_from_request_hash(request);
281
282         request_free(prequest);
283 }
284
285 #ifdef WITH_TCP
286 static int remove_all_requests(void *ctx, void *data)
287 {
288         rad_listen_t *this = ctx;
289         RADIUS_PACKET **packet_p = data;
290         REQUEST *request;
291         
292         request = fr_packet2myptr(REQUEST, packet, packet_p);
293         if (request->packet->sockfd != this->fd) return 0;
294
295         switch (request->child_state) {
296         case REQUEST_RUNNING:
297                 rad_assert(request->ev != NULL); /* or it's lost forever */
298         case REQUEST_QUEUED:
299                 request->master_state = REQUEST_STOP_PROCESSING;
300                 return 0;
301
302                 /*
303                  *      Waiting for a reply.  There's no point in
304                  *      doing anything else.  We remove it from the
305                  *      request hash so that we can close the upstream
306                  *      socket.
307                  */
308         case REQUEST_PROXIED:
309                 remove_from_request_hash(request);
310                 request->child_state = REQUEST_DONE;
311                 return 0;
312
313         case REQUEST_REJECT_DELAY:
314         case REQUEST_CLEANUP_DELAY:
315         case REQUEST_DONE:
316                 ev_request_free(&request);
317                 break;
318         }
319
320         return 0;
321 }
322
323 #ifdef WITH_PROXY
324 static int remove_all_proxied_requests(void *ctx, void *data)
325 {
326         rad_listen_t *this = ctx;
327         RADIUS_PACKET **proxy_p = data;
328         REQUEST *request;
329         
330         request = fr_packet2myptr(REQUEST, proxy, proxy_p);
331         if (request->proxy->sockfd != this->fd) return 0;
332
333         switch (request->child_state) {
334         case REQUEST_RUNNING:
335                 rad_assert(request->ev != NULL); /* or it's lost forever */
336         case REQUEST_QUEUED:
337                 request->master_state = REQUEST_STOP_PROCESSING;
338                 return 0;
339
340                 /*
341                  *      Eventually we will discover that there is no
342                  *      response to the proxied request.
343                  */
344         case REQUEST_PROXIED:
345                 break;
346
347                 /*
348                  *      Keep it in the cache for duplicate detection.
349                  */
350         case REQUEST_REJECT_DELAY:
351         case REQUEST_CLEANUP_DELAY:
352         case REQUEST_DONE:
353                 break;
354         }
355
356         remove_from_proxy_hash(request);
357         return 0;
358 }
359 #endif  /* WITH_PROXY */
360 #endif  /* WITH_TCP */
361
362
363 #ifdef WITH_PROXY
364 static int insert_into_proxy_hash(REQUEST *request)
365 {
366         char buf[128];
367         int rcode, tries;
368         void *proxy_listener;
369
370         rad_assert(request->proxy != NULL);
371         rad_assert(proxy_list != NULL);
372
373         tries = 1;
374 retry:
375         PTHREAD_MUTEX_LOCK(&proxy_mutex);
376         rcode = fr_packet_list_id_alloc(proxy_list,
377                                         request->home_server->proto,
378                                         request->proxy, &proxy_listener);
379         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
380         
381         if (!rcode) {
382                 /*
383                  *      Also locks the proxy mutex, so we have to call
384                  *      it with the mutex unlocked.  Some systems
385                  *      don't support recursive mutexes.
386                  */
387                 if (!proxy_new_listener(request->home_server, 0)) {
388                         radlog(L_ERR, "Failed to create a new socket for proxying requests.");
389                         return 0;
390                 }
391                 request->proxy->src_port = 0; /* Use any new socket */
392
393                 tries++;
394                 if (tries > 2) {
395                         RDEBUG2("ERROR: Failed allocating Id for new socket when proxying requests.");
396                         return 0;
397                 }
398                 
399                 goto retry;
400         }
401
402         request->proxy_listener = proxy_listener;
403
404         PTHREAD_MUTEX_LOCK(&proxy_mutex);
405         if (!fr_packet_list_insert(proxy_list, &request->proxy)) {
406                 fr_packet_list_id_free(proxy_list, request->proxy);
407                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
408                 radlog(L_PROXY, "Failed to insert entry into proxy list");
409                 return 0;
410         }
411
412         request->in_proxy_hash = TRUE;
413
414         /*
415          *      Keep track of maximum outstanding requests to a
416          *      particular home server.  'max_outstanding' is
417          *      enforced in home_server_ldb(), in realms.c.
418          */
419         if (request->home_server) {
420                 request->home_server->currently_outstanding++;
421         }
422
423 #ifdef WITH_TCP
424         request->proxy_listener->count++;
425 #endif
426
427         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
428
429         RDEBUG3(" proxy: allocating destination %s port %d - Id %d",
430                inet_ntop(request->proxy->dst_ipaddr.af,
431                          &request->proxy->dst_ipaddr.ipaddr, buf, sizeof(buf)),
432                request->proxy->dst_port,
433                request->proxy->id);
434
435         return 1;
436 }
437
438
439 /*
440  *      Called as BOTH an event, and in-line from other functions.
441  */
442 static void wait_for_proxy_id_to_expire(void *ctx)
443 {
444         REQUEST *request = ctx;
445
446         rad_assert(request->magic == REQUEST_MAGIC);
447         rad_assert(request->proxy != NULL);
448
449         if (!fr_event_now(el, &now)) gettimeofday(&now, NULL);
450         request->when = request->proxy_when;
451
452 #ifdef WITH_COA
453         if (((request->proxy->code == PW_COA_REQUEST) ||
454              (request->proxy->code == PW_DISCONNECT_REQUEST)) &&
455             (request->packet->code != request->proxy->code)) {
456                 request->when.tv_sec += request->home_server->coa_mrd;
457         } else
458 #endif
459         request->when.tv_sec += request->home_server->response_window;
460
461         if ((request->num_proxied_requests == request->num_proxied_responses) ||
462 #ifdef WITH_TCP
463             (request->home_server->proto == IPPROTO_TCP) ||
464 #endif
465             timercmp(&now, &request->when, >)) {
466                 if (request->packet) {
467                         RDEBUG2("Cleaning up request %d ID %d with timestamp +%d",
468                                request->number, request->packet->id,
469                                (unsigned int) (request->timestamp - fr_start_time));
470                 } else {
471                         RDEBUG2("Cleaning up request %d with timestamp +%d",
472                                request->number,
473                                (unsigned int) (request->timestamp - fr_start_time));
474                 }
475
476                 ev_request_free(&request);
477                 return;
478         }
479
480         INSERT_EVENT(wait_for_proxy_id_to_expire, request);
481 }
482 #endif
483
484 #ifdef HAVE_PTHREAD_H
485 static void wait_for_child_to_die(void *ctx)
486 {
487         REQUEST *request = ctx;
488
489         rad_assert(request->magic == REQUEST_MAGIC);
490
491         if ((request->child_state == REQUEST_QUEUED) ||
492             (request->child_state == REQUEST_RUNNING)) {
493                 request->delay += (request->delay >> 1);
494                 tv_add(&request->when, request->delay);
495
496                 RDEBUG2("Child is still stuck for request %d", request->number);
497
498                 INSERT_EVENT(wait_for_child_to_die, request);
499                 return;
500         }
501
502         RDEBUG2("Child is responsive for request %d", request->number);
503         remove_from_request_hash(request);
504
505 #ifdef WITH_PROXY
506         if (request->proxy) {
507                 wait_for_proxy_id_to_expire(request);
508                 return;
509         }
510 #endif
511
512         ev_request_free(&request);
513 }
514 #endif
515
516 static void cleanup_delay(void *ctx)
517 {
518         REQUEST *request = ctx;
519
520         rad_assert(request->magic == REQUEST_MAGIC);
521         rad_assert((request->child_state == REQUEST_CLEANUP_DELAY) ||
522                    (request->child_state == REQUEST_DONE));
523
524         remove_from_request_hash(request);
525
526 #ifdef WITH_PROXY
527         if (request->proxy && request->in_proxy_hash) {
528                 wait_for_proxy_id_to_expire(request);
529                 return;
530         }
531 #endif
532
533         RDEBUG2("Cleaning up request %d ID %d with timestamp +%d",
534                request->number, request->packet->id,
535                (unsigned int) (request->timestamp - fr_start_time));
536
537         ev_request_free(&request);
538 }
539
540
541 /*
542  *      In daemon mode, AND this request has debug flags set.
543  */
544 #define DEBUG_PACKET if (!debug_flag && request->options && request->radlog) debug_packet
545
546 static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
547 {
548         VALUE_PAIR *vp;
549         char buffer[1024];
550         const char *received, *from;
551         const fr_ipaddr_t *ip;
552         int port;
553
554         if (!packet) return;
555
556         rad_assert(request->radlog != NULL);
557
558         if (direction == 0) {
559                 received = "Received";
560                 from = "from";  /* what else? */
561                 ip = &packet->src_ipaddr;
562                 port = packet->src_port;
563
564         } else {
565                 received = "Sending";
566                 from = "to";    /* hah! */
567                 ip = &packet->dst_ipaddr;
568                 port = packet->dst_port;
569         }
570         
571         /*
572          *      Client-specific debugging re-prints the input
573          *      packet into the client log.
574          *
575          *      This really belongs in a utility library
576          */
577         if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
578                 RDEBUG("%s %s packet %s host %s port %d, id=%d, length=%d",
579                        received, fr_packet_codes[packet->code], from,
580                        inet_ntop(ip->af, &ip->ipaddr, buffer, sizeof(buffer)),
581                        port, packet->id, packet->data_len);
582         } else {
583                 RDEBUG("%s packet %s host %s port %d code=%d, id=%d, length=%d",
584                        received, from,
585                        inet_ntop(ip->af, &ip->ipaddr, buffer, sizeof(buffer)),
586                        port,
587                        packet->code, packet->id, packet->data_len);
588         }
589
590         for (vp = packet->vps; vp != NULL; vp = vp->next) {
591                 vp_prints(buffer, sizeof(buffer), vp);
592                 request->radlog(L_DBG, 0, request, "\t%s", buffer);
593         }
594 }
595
596 static void reject_delay(void *ctx)
597 {
598         REQUEST *request = ctx;
599
600         rad_assert(request->magic == REQUEST_MAGIC);
601         rad_assert(request->child_state == REQUEST_REJECT_DELAY);
602
603         RDEBUG2("Sending delayed reject for request %d", request->number);
604
605         DEBUG_PACKET(request, request->reply, 1);
606
607         request->listener->send(request->listener, request);
608
609         request->when.tv_sec += request->root->cleanup_delay;
610         request->child_state = REQUEST_CLEANUP_DELAY;
611
612         INSERT_EVENT(cleanup_delay, request);
613 }
614
615
616 #ifdef WITH_PROXY
617 void revive_home_server(void *ctx)
618 {
619         home_server *home = ctx;
620         char buffer[128];
621
622 #ifdef WITH_TCP
623         rad_assert(home->proto != IPPROTO_TCP);
624 #endif
625
626         home->state = HOME_STATE_ALIVE;
627         home->currently_outstanding = 0;
628         home->revive_time = now;
629
630         /*
631          *      Delete any outstanding events.
632          */
633         if (home->ev) fr_event_delete(el, &home->ev);
634
635         radlog(L_PROXY, "Marking home server %s port %d alive again... we have no idea if it really is alive or not.",
636                inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
637                          buffer, sizeof(buffer)),
638                home->port);
639
640 }
641
642
643 static void no_response_to_ping(void *ctx)
644 {
645         REQUEST *request = ctx;
646         home_server *home;
647         char buffer[128];
648
649         rad_assert(request->home_server != NULL);
650
651         home = request->home_server;
652 #ifdef WITH_TCP
653         rad_assert(home->proto != IPPROTO_TCP);
654 #endif
655
656         home->num_received_pings = 0;
657
658         radlog(L_ERR, "No response to status check %d for home server %s port %d",
659                request->number,
660                inet_ntop(request->proxy->dst_ipaddr.af,
661                          &request->proxy->dst_ipaddr.ipaddr,
662                          buffer, sizeof(buffer)),
663                request->proxy->dst_port);
664
665         check_for_zombie_home_server(request);
666
667         wait_for_proxy_id_to_expire(request);
668 }
669
670
671 static void received_response_to_ping(REQUEST *request)
672 {
673         home_server *home;
674         char buffer[128];
675
676         rad_assert(request->home_server != NULL);
677
678         home = request->home_server;
679 #ifdef WITH_TCP
680         rad_assert(home->proto != IPPROTO_TCP);
681 #endif
682
683         home->num_received_pings++;
684
685         radlog(L_PROXY, "Received response to status check %d (%d in current sequence)",
686                request->number, home->num_received_pings);
687
688         /*
689          *      Remove the request from any hashes
690          */
691         fr_event_delete(el, &request->ev);
692         remove_from_proxy_hash(request);
693         rad_assert(request->in_request_hash == FALSE);
694
695         /*
696          *      The control socket may have marked the home server as
697          *      alive.  OR, it may have suddenly started responding to
698          *      requests again.  If so, don't re-do the "make alive"
699          *      work.
700          */
701         if (home->state == HOME_STATE_ALIVE) return;
702
703         /*
704          *      We haven't received enough ping responses to mark it
705          *      "alive".  Wait a bit.
706          */
707         if (home->num_received_pings < home->num_pings_to_alive) {
708                 return;
709         }
710
711         home->state = HOME_STATE_ALIVE;
712         home->currently_outstanding = 0;
713         home->revive_time = now;
714
715         if (!fr_event_delete(el, &home->ev)) {
716                 RDEBUG2("Hmm... no event for home server.  Oh well.");
717         }
718
719         radlog(L_PROXY, "Marking home server %s port %d alive",
720                inet_ntop(request->proxy->dst_ipaddr.af,
721                          &request->proxy->dst_ipaddr.ipaddr,
722                          buffer, sizeof(buffer)),
723                request->proxy->dst_port);
724 }
725
726
727 /*
728  *      Called from start of zombie period, OR after control socket
729  *      marks the home server dead.
730  */
731 static void ping_home_server(void *ctx)
732 {
733         uint32_t jitter;
734         home_server *home = ctx;
735         REQUEST *request;
736         VALUE_PAIR *vp;
737
738 #ifdef WITH_TCP
739         rad_assert(home->proto != IPPROTO_TCP);
740 #endif
741
742         if ((home->state == HOME_STATE_ALIVE) ||
743             (home->ping_check == HOME_PING_CHECK_NONE) ||
744             (home->ev != NULL)) {
745                 return;
746         }
747
748         request = request_alloc();
749         request->number = request_num_counter++;
750
751         request->proxy = rad_alloc(1);
752         rad_assert(request->proxy != NULL);
753
754         fr_event_now(el, &request->when);
755         home->when = request->when;
756
757         if (home->ping_check == HOME_PING_CHECK_STATUS_SERVER) {
758                 request->proxy->code = PW_STATUS_SERVER;
759
760                 radius_pairmake(request, &request->proxy->vps,
761                                 "Message-Authenticator", "0x00", T_OP_SET);
762
763         } else if (home->type == HOME_TYPE_AUTH) {
764                 request->proxy->code = PW_AUTHENTICATION_REQUEST;
765
766                 radius_pairmake(request, &request->proxy->vps,
767                                 "User-Name", home->ping_user_name, T_OP_SET);
768                 radius_pairmake(request, &request->proxy->vps,
769                                 "User-Password", home->ping_user_password, T_OP_SET);
770                 radius_pairmake(request, &request->proxy->vps,
771                                 "Service-Type", "Authenticate-Only", T_OP_SET);
772                 radius_pairmake(request, &request->proxy->vps,
773                                 "Message-Authenticator", "0x00", T_OP_SET);
774
775         } else {
776 #ifdef WITH_ACCOUNTING
777                 request->proxy->code = PW_ACCOUNTING_REQUEST;
778                 
779                 radius_pairmake(request, &request->proxy->vps,
780                                 "User-Name", home->ping_user_name, T_OP_SET);
781                 radius_pairmake(request, &request->proxy->vps,
782                                 "Acct-Status-Type", "Stop", T_OP_SET);
783                 radius_pairmake(request, &request->proxy->vps,
784                                 "Acct-Session-Id", "00000000", T_OP_SET);
785                 vp = radius_pairmake(request, &request->proxy->vps,
786                                      "Event-Timestamp", "0", T_OP_SET);
787                 vp->vp_date = now.tv_sec;
788 #else
789                 rad_assert("Internal sanity check failed");
790 #endif
791         }
792
793         radius_pairmake(request, &request->proxy->vps,
794                         "NAS-Identifier", "Status Check. Are you alive?",
795                         T_OP_SET);
796
797         request->proxy->dst_ipaddr = home->ipaddr;
798         request->proxy->dst_port = home->port;
799         request->home_server = home;
800
801         rad_assert(request->proxy_listener == NULL);
802
803         if (!insert_into_proxy_hash(request)) {
804                 radlog(L_PROXY, "Failed inserting status check %d into proxy hash.  Discarding it.",
805                        request->number);
806                 ev_request_free(&request);
807                 return;
808         }
809         rad_assert(request->proxy_listener != NULL);
810         request->proxy_listener->send(request->proxy_listener,
811                                       request);
812
813         request->next_callback = NULL;
814         request->child_state = REQUEST_PROXIED;
815         gettimeofday(&request->when, NULL);
816         home->when = request->when;
817         request->when.tv_sec += home->ping_timeout;;
818
819         INSERT_EVENT(no_response_to_ping, request);
820
821         /*
822          *      Add +/- 2s of jitter, as suggested in RFC 3539
823          *      and in the Issues and Fixes draft.
824          */
825         home->when.tv_sec += home->ping_interval - 2;
826
827         jitter = fr_rand();
828         jitter ^= (jitter >> 10);
829         jitter &= ((1 << 23) - 1); /* 22 bits of 1 */
830
831         tv_add(&home->when, jitter);
832
833         INSERT_EVENT(ping_home_server, home);
834 }
835
836
837 void mark_home_server_dead(home_server *home, struct timeval *when)
838 {
839         int previous_state = home->state;
840         char buffer[128];
841
842         radlog(L_PROXY, "Marking home server %s port %d as dead.",
843                inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
844                          buffer, sizeof(buffer)),
845                home->port);
846
847         home->state = HOME_STATE_IS_DEAD;
848         home->num_received_pings = 0;
849
850         if (home->ping_check != HOME_PING_CHECK_NONE) {
851                 /*
852                  *      If the control socket marks us dead, start
853                  *      pinging.  Otherwise, we already started
854                  *      pinging when it was marked "zombie".
855                  */
856                 if (previous_state == HOME_STATE_ALIVE) {
857                         ping_home_server(home);
858                 }
859
860         } else {
861                 /*
862                  *      Revive it after a fixed period of time.  This
863                  *      is very, very, bad.
864                  */
865                 home->when = *when;
866                 home->when.tv_sec += home->revive_interval;
867
868                 INSERT_EVENT(revive_home_server, home);
869         }
870 }
871
872 static void check_for_zombie_home_server(REQUEST *request)
873 {
874         home_server *home;
875         struct timeval when;
876
877         home = request->home_server;
878
879         if (home->state != HOME_STATE_ZOMBIE) return;
880
881         when = home->zombie_period_start;
882         when.tv_sec += home->zombie_period;
883
884         fr_event_now(el, &now);
885         if (timercmp(&now, &when, <)) {
886                 return;
887         }
888
889         mark_home_server_dead(home, &request->when);
890 }
891
892 static int proxy_to_virtual_server(REQUEST *request);
893
894 static int virtual_server_handler(UNUSED REQUEST *request)
895 {
896         proxy_to_virtual_server(request);
897         return 0;
898 }
899
900 static void proxy_fallback_handler(REQUEST *request)
901 {
902         /*
903          *      A proper time is required for wait_a_bit.
904          */
905         request->delay = USEC / 10;
906         gettimeofday(&now, NULL);
907         request->next_when = now;
908         tv_add(&request->next_when, request->delay);
909         request->next_callback = wait_a_bit;
910
911         /*
912          *      Re-queue the request.
913          */
914         request->child_state = REQUEST_QUEUED;
915         
916         rad_assert(request->proxy != NULL);
917         if (!thread_pool_addrequest(request, virtual_server_handler)) {
918                 request->child_state = REQUEST_DONE;
919         }
920
921 #ifdef HAVE_PTHREAD_H
922         /*
923          *      MAY free the request if we're over max_request_time,
924          *      AND we're not in threaded mode!
925          *
926          *      Note that we call this ONLY if we're threaded, as
927          *      if we're NOT threaded, request_post_handler() calls
928          *      wait_a_bit(), which means that "request" may not
929          *      exist any more...
930          */
931         if (have_children) wait_a_bit(request);
932 #endif
933 }
934
935
936 static int setup_post_proxy_fail(REQUEST *request)
937 {
938         DICT_VALUE *dval = NULL;
939         VALUE_PAIR *vp;
940
941         request->child_state = REQUEST_RUNNING;
942
943         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
944                 dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Authentication");
945
946         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
947                 dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Accounting");
948
949 #ifdef WITH_COA
950                 /*
951                  *      See no_response_to_coa_request
952                  */
953         } else if (((request->packet->code >> 8) & 0xff) == PW_COA_REQUEST) {
954                 request->packet->code &= 0xff; /* restore it */
955
956                 if (request->proxy->code == PW_COA_REQUEST) {
957                         dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-CoA");
958
959                 } else if (request->proxy->code == PW_DISCONNECT_REQUEST) {
960                         dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail-Disconnect");
961                 } else {
962                         return 0;
963                 }
964
965 #endif
966         } else {
967                 return 0;
968         }
969
970         if (!dval) dval = dict_valbyname(PW_POST_PROXY_TYPE, "Fail");
971
972         if (!dval) {
973                 pairdelete(&request->config_items, PW_POST_PROXY_TYPE);
974                 return 0;
975         }
976
977         vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
978         if (!vp) vp = radius_paircreate(request, &request->config_items,
979                                         PW_POST_PROXY_TYPE, PW_TYPE_INTEGER);
980         vp->vp_integer = dval->value;
981
982         rad_assert(request->proxy_reply == NULL);
983
984         return 1;
985 }
986
987
988 static int null_handler(UNUSED REQUEST *request)
989 {
990         return 0;
991 }
992
993 static void post_proxy_fail_handler(REQUEST *request)
994 {
995         /*
996          *      A proper time is required for wait_a_bit.
997          */
998         request->delay = USEC / 10;
999         gettimeofday(&now, NULL);
1000
1001         /*
1002          *      Not set up to run Post-Proxy-Type = Fail.
1003          *
1004          *      Mark the request as still running, and figure out what
1005          *      to do next.
1006          */
1007         if (!setup_post_proxy_fail(request)) {
1008                 request_post_handler(request);
1009
1010         } else {
1011                 /*
1012                  *      Re-queue the request.
1013                  */
1014                 request->child_state = REQUEST_QUEUED;
1015
1016                 /*
1017                  *      There is a post-proxy-type of fail.  We run
1018                  *      the request through the pre/post proxy
1019                  *      handlers, just like it was a real proxied
1020                  *      request.  However, we set the per-request
1021                  *      handler to NULL, as we don't want to do
1022                  *      anything else.
1023                  *
1024                  *      Note that when we're not threaded, this will
1025                  *      process the request even if it's greater than
1026                  *      max_request_time.  That's not fatal.
1027                  */
1028                 request->priority = 0;
1029                 rad_assert(request->proxy != NULL);
1030                 thread_pool_addrequest(request, null_handler);
1031         }
1032
1033         /*
1034          *      MAY free the request if we're over max_request_time,
1035          *      AND we're not in threaded mode!
1036          *
1037          *      Note that we call this ONLY if we're threaded, as
1038          *      if we're NOT threaded, request_post_handler() calls
1039          *      wait_a_bit(), which means that "request" may not
1040          *      exist any more...
1041          */
1042         if (have_children) wait_a_bit(request);
1043 }
1044
1045 /* maybe check this against wait_for_proxy_id_to_expire? */
1046 static void no_response_to_proxied_request(void *ctx)
1047 {
1048         REQUEST *request = ctx;
1049         home_server *home;
1050         char buffer[128];
1051
1052         rad_assert(request->magic == REQUEST_MAGIC);
1053
1054         if (request->master_state == REQUEST_STOP_PROCESSING) {
1055                 ev_request_free(&request);
1056                 return;
1057         }
1058
1059         rad_assert(request->child_state == REQUEST_PROXIED);
1060
1061         /*
1062          *      If we've failed over to an internal home server,
1063          *      replace the callback with the correct one.  This
1064          *      is due to locking issues with child threads...
1065          */
1066         if (request->home_server->server) {
1067                 wait_a_bit(request);
1068                 return;
1069         }
1070
1071 #ifdef WITH_TCP
1072         if (request->home_server->proto != IPPROTO_TCP)
1073 #endif
1074                 check_for_zombie_home_server(request);
1075
1076         home = request->home_server;
1077
1078         /*
1079          *      The default as of 2.1.7 is to allow requests to
1080          *      fail-over to a backup home server when this one does
1081          *      not respond.  The old behavior can be configured as
1082          *      well.
1083          */
1084         if (home->no_response_fail) {
1085                 radlog(L_ERR, "Rejecting request %d (proxy Id %d) due to lack of any response from home server %s port %d",
1086                        request->number, request->proxy->id,
1087                        inet_ntop(request->proxy->dst_ipaddr.af,
1088                                  &request->proxy->dst_ipaddr.ipaddr,
1089                                  buffer, sizeof(buffer)),
1090                        request->proxy->dst_port);
1091
1092                 post_proxy_fail_handler(request);
1093         } else {
1094                 /*
1095                  *      Ensure that there is a callback for the request.
1096                  */
1097                 request->child_state = REQUEST_RUNNING;
1098                 wait_a_bit(request);
1099         }
1100
1101         /*
1102          *      Don't touch request due to race conditions
1103          */
1104
1105 #ifdef WITH_TCP
1106         /*
1107          *      Do nothing more.  The home server didn't respond,
1108          *      but that isn't a catastrophic failure.  Some home
1109          *      servers don't respond to packets...
1110          */
1111         if (home->proto == IPPROTO_TCP) {
1112                 /*
1113                  *      FIXME: Set up TCP pinging on this connection.
1114                  *
1115                  *      Maybe the CONNECTION is dead, but the home
1116                  *      server is alive.  In that case, we need to start
1117                  *      pinging on the connection.
1118                  *
1119                  *      This means doing the pinging BEFORE the
1120                  *      post_proxy_fail_handler above, as it may do
1121                  *      something with the request, and cause the
1122                  *      proxy listener to go away!
1123                  */
1124                 return;
1125         }
1126 #endif
1127
1128         if (home->state == HOME_STATE_IS_DEAD) {
1129                 rad_assert(home->ev != NULL); /* or it will never wake up */
1130                 return;
1131         }
1132
1133         /*
1134          *      Enable the zombie period when we notice that the home
1135          *      server hasn't responded.  We do NOT back-date the start
1136          *      of the zombie period.
1137          */
1138         if (home->state == HOME_STATE_ALIVE) {
1139                 home->state = HOME_STATE_ZOMBIE;
1140                 home->zombie_period_start = now;        
1141
1142                 radlog(L_PROXY, "Marking home server %s port %d as zombie (it looks like it is dead).",
1143                        inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
1144                                  buffer, sizeof(buffer)),
1145                        home->port);
1146
1147                 /*
1148                  *      Start pinging the home server.
1149                  */
1150                 ping_home_server(home);
1151         }
1152 }
1153 #endif
1154
1155 static void wait_a_bit(void *ctx)
1156 {
1157         struct timeval when;
1158         REQUEST *request = ctx;
1159         fr_event_callback_t callback = NULL;
1160
1161         rad_assert(request->magic == REQUEST_MAGIC);
1162
1163         /*
1164          *      The socket was closed.  Tell the request that
1165          *      there is no point in continuing.
1166          */
1167         if (request->listener->status != RAD_LISTEN_STATUS_KNOWN) {
1168                 goto stop_processing;
1169         }
1170
1171 #ifdef WITH_COA
1172         /*
1173          *      The CoA request is a new (internally generated)
1174          *      request, created in a child thread.  We therefore need
1175          *      some way to tie its events back into the main event
1176          *      handler.
1177          */
1178         if (request->coa && !request->coa->proxy_reply &&
1179             request->coa->next_callback) {
1180                 request->coa->when = request->coa->next_when;
1181                 INSERT_EVENT(request->coa->next_callback, request->coa);
1182                 request->coa->next_callback = NULL;
1183                 request->coa->parent = NULL;
1184                 request->coa = NULL;
1185         }
1186 #endif
1187
1188         switch (request->child_state) {
1189         case REQUEST_QUEUED:
1190         case REQUEST_RUNNING:
1191                 when = request->received;
1192                 when.tv_sec += request->root->max_request_time;
1193
1194                 /*
1195                  *      Normally called from the event loop with the
1196                  *      proper event loop time.  Otherwise, called from
1197                  *      post proxy fail handler, which sets "now", and
1198                  *      this call won't re-set it, because we're not
1199                  *      in the event loop.
1200                  */
1201                 fr_event_now(el, &now);
1202
1203                 /*
1204                  *      Request still has more time.  Continue
1205                  *      waiting.
1206                  */
1207                 if (timercmp(&now, &when, <) ||
1208                     ((request->listener->type == RAD_LISTEN_DETAIL) &&
1209                      (request->child_state == REQUEST_QUEUED))) {
1210                         if (request->delay < (USEC / 10)) {
1211                                 request->delay = USEC / 10;
1212                         }
1213                         request->delay += request->delay >> 1;
1214
1215 #ifdef WITH_DETAIL
1216                         /*
1217                          *      Cap wait at some sane value for detail
1218                          *      files.
1219                          */
1220                         if ((request->listener->type == RAD_LISTEN_DETAIL) &&
1221                             (request->delay > (request->root->max_request_time * USEC))) {
1222                                 request->delay = request->root->max_request_time * USEC;
1223                         }
1224 #endif
1225
1226                         request->when = now;
1227                         tv_add(&request->when, request->delay);
1228                         callback = wait_a_bit;
1229                         break;
1230                 }
1231
1232 #if defined(HAVE_PTHREAD_H) || defined(WITH_PROXY)
1233                 /*
1234                  *      A child thread MAY still be running on the
1235                  *      request.  Ask the thread to stop working on
1236                  *      the request.
1237                  */
1238                 if (have_children) {
1239                         /* FIXME: kill unresponsive children? */
1240
1241                         /*
1242                          *      Print this error message ONLY if
1243                          *      there's a child currently processing
1244                          *      the request.  As we don't have thread
1245                          *      locks here, there may be race
1246                          *      conditions on this check.  But it's
1247                          *      just an error message, so that's OK.
1248                          */
1249                         if (!pthread_equal(request->child_pid, NO_SUCH_CHILD_PID)) {
1250                                 radlog(L_ERR, "WARNING: Unresponsive child for request %d, in module %s component %s",
1251                                        request->number,
1252                                        request->module ? request->module : "<server core>",
1253                                        request->component ? request->component : "<server core>");
1254                         }
1255
1256                 stop_processing:
1257                         request->master_state = REQUEST_STOP_PROCESSING;
1258                         
1259                         request->delay = USEC / 4;
1260                         tv_add(&request->when, request->delay);
1261                         callback = wait_for_child_to_die;
1262                         break;
1263                 }
1264 #else  /* no child threads */
1265         stop_processing:
1266 #endif
1267
1268                 /*
1269                  *      Else there are no child threads.  We probably
1270                  *      should have just marked the request as 'done'
1271                  *      elsewhere, like in the post-proxy-fail
1272                  *      handler.  But doing that would involve
1273                  *      checking for max_request_time in multiple
1274                  *      places, so this may be simplest.
1275                  */
1276                 request->child_state = REQUEST_DONE;
1277                 /* FALL-THROUGH */
1278
1279                 /*
1280                  *      Mark the request as no longer running,
1281                  *      and clean it up.
1282                  */
1283         case REQUEST_DONE:
1284 #ifdef HAVE_PTHREAD_H
1285                 request->child_pid = NO_SUCH_CHILD_PID;
1286 #endif
1287
1288 #ifdef WTH_COA
1289                 /*
1290                  *      This is a CoA request.  It's been divorced
1291                  *      from everything else, so we clean it up now.
1292                  */
1293                 if (!request->in_request_hash &&
1294                     request->proxy &&
1295                     (request->packet->code != request->proxy->code) &&
1296                     ((request->proxy->code == PW_COA_REQUEST) ||
1297                      (request->proxy->code == PW_DISCONNECT_REQUEST))) {
1298                         /*
1299                          *      FIXME: Do CoA MIBs
1300                          */
1301                         ev_request_free(&request);
1302                         return;
1303                 }
1304 #endif
1305                 request_stats_final(request);
1306                 cleanup_delay(request);
1307                 return;
1308
1309         case REQUEST_REJECT_DELAY:
1310         case REQUEST_CLEANUP_DELAY:
1311 #ifdef HAVE_PTHREAD_H
1312                 request->child_pid = NO_SUCH_CHILD_PID;
1313 #endif
1314                 request_stats_final(request);
1315
1316         case REQUEST_PROXIED:
1317                 rad_assert(request->next_callback != NULL);
1318                 rad_assert(request->next_callback != wait_a_bit);
1319
1320                 request->when = request->next_when;
1321                 callback = request->next_callback;
1322                 request->next_callback = NULL;
1323                 break;
1324
1325         default:
1326                 rad_panic("Internal sanity check failure");
1327                 return;
1328         }
1329
1330         /*
1331          *      Something major went wrong.  Discard the request, and
1332          *      keep running.
1333          *
1334          *      FIXME: No idea why this happens or how to fix it...
1335          *      It seems to happen *only* when requests are proxied,
1336          *      and where the home server doesn't respond.  So it looks
1337          *      like a race condition above, but it happens in debug
1338          *      mode, with no threads...
1339          */
1340         if (!callback) {
1341                 RDEBUG("WARNING: Internal sanity check failed in event handler for request %d: Discarding the request!", request->number);
1342                 ev_request_free(&request);
1343                 return;
1344         }
1345
1346         INSERT_EVENT(callback, request);
1347 }
1348
1349 #ifdef WITH_COA
1350 static void no_response_to_coa_request(void *ctx)
1351 {
1352         REQUEST *request = ctx;
1353         char buffer[128];
1354
1355         rad_assert(request->magic == REQUEST_MAGIC);
1356         rad_assert(request->child_state == REQUEST_PROXIED);
1357         rad_assert(request->home_server != NULL);
1358         rad_assert(!request->in_request_hash);
1359
1360         radlog(L_ERR, "No response to CoA request sent to %s",
1361                inet_ntop(request->proxy->dst_ipaddr.af,
1362                          &request->proxy->dst_ipaddr.ipaddr,
1363                          buffer, sizeof(buffer)));
1364
1365         /*
1366          *      Hack.
1367          */
1368         request->packet->code |= (PW_COA_REQUEST << 8);
1369         post_proxy_fail_handler(request);
1370 }
1371
1372
1373 static int update_event_timestamp(RADIUS_PACKET *packet, time_t when)
1374 {
1375         VALUE_PAIR *vp;
1376
1377         vp = pairfind(packet->vps, PW_EVENT_TIMESTAMP);
1378         if (!vp) return 0;
1379
1380         vp->vp_date = when;
1381
1382         if (packet->data) {
1383                 free(packet->data);
1384                 packet->data = NULL;
1385                 packet->data_len = 0;
1386         }
1387
1388         return 1;               /* time stamp updated */
1389 }
1390
1391
1392 /*
1393  *      Called when we haven't received a response to a CoA request.
1394  */
1395 static void retransmit_coa_request(void *ctx)
1396 {
1397         int delay, frac;
1398         struct timeval mrd;
1399         REQUEST *request = ctx;
1400
1401         rad_assert(request->magic == REQUEST_MAGIC);
1402         rad_assert(request->child_state == REQUEST_PROXIED);
1403         rad_assert(request->home_server != NULL);
1404         rad_assert(!request->in_request_hash);
1405         rad_assert(request->parent == NULL);
1406         
1407         fr_event_now(el, &now);
1408
1409         /*
1410          *      Cap count at MRC, if it is non-zero.
1411          */
1412         if (request->home_server->coa_mrc &&
1413             (request->num_coa_requests >= request->home_server->coa_mrc)) {
1414                 no_response_to_coa_request(request);
1415                 return;
1416         }
1417
1418         /*
1419          *      RFC 5080 Section 2.2.1
1420          *
1421          *      RT = 2*RTprev + RAND*RTprev
1422          *         = 1.9 * RTprev + rand(0,.2) * RTprev
1423          *         = 1.9 * RTprev + rand(0,1) * (RTprev / 5)
1424          */
1425         delay = fr_rand();
1426         delay ^= (delay >> 16);
1427         delay &= 0xffff;
1428         frac = request->delay / 5;
1429         delay = ((frac >> 16) * delay) + (((frac & 0xffff) * delay) >> 16);
1430
1431         delay += (2 * request->delay) - (request->delay / 10);
1432
1433         /*
1434          *      Cap delay at MRT, if MRT is non-zero.
1435          */
1436         if (request->home_server->coa_mrt &&
1437             (delay > (request->home_server->coa_mrt * USEC))) {
1438                 int mrt_usec = request->home_server->coa_mrt * USEC;
1439
1440                 /*
1441                  *      delay = MRT + RAND * MRT
1442                  *            = 0.9 MRT + rand(0,.2)  * MRT
1443                  */
1444                 delay = fr_rand();
1445                 delay ^= (delay >> 15);
1446                 delay &= 0x1ffff;
1447                 delay = ((mrt_usec >> 16) * delay) + (((mrt_usec & 0xffff) * delay) >> 16);
1448                 delay += mrt_usec - (mrt_usec / 10);
1449         }
1450
1451         request->delay = delay;
1452         request->when = now;
1453         tv_add(&request->when, request->delay);
1454         mrd = request->proxy_when;
1455         mrd.tv_sec += request->home_server->coa_mrd;
1456
1457         /*
1458          *      Cap duration at MRD.
1459          */
1460         if (timercmp(&mrd, &request->when, <)) {
1461                 request->when = mrd;
1462                 INSERT_EVENT(no_response_to_coa_request, request);
1463
1464         } else {
1465                 INSERT_EVENT(retransmit_coa_request, request);
1466         }
1467         
1468         if (update_event_timestamp(request->proxy, now.tv_sec)) {
1469                 /*
1470                  *      Keep a copy of the old Id so that the
1471                  *      re-transmitted request doesn't re-use the old
1472                  *      Id.
1473                  */
1474                 RADIUS_PACKET old = *request->proxy;
1475
1476                 /*
1477                  *      Don't free the old Id on error.
1478                  */
1479                 if (!insert_into_proxy_hash(request)) {
1480                         radlog(L_PROXY,"Failed re-inserting CoA request into proxy hash.");
1481                         return;
1482                 }
1483
1484                 /*
1485                  *      Now that we have a new Id, free the old one.
1486                  */
1487                 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1488                 fr_packet_list_yank(proxy_list, &old);
1489                 fr_packet_list_id_free(proxy_list, &old);
1490                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1491
1492                 request->num_proxied_requests = 0;
1493                 request->num_proxied_responses = 0;
1494         }
1495
1496         request->num_proxied_requests++;
1497         request->num_coa_requests++; /* is NOT reset by code 3 lines above! */
1498
1499         request->proxy_listener->send(request->proxy_listener,
1500                                       request);
1501 }
1502
1503
1504 /*
1505  *      The original request is either DONE, or in CLEANUP_DELAY.
1506  */
1507 static int originated_coa_request(REQUEST *request)
1508 {
1509         int delay, rcode, pre_proxy_type = 0;
1510         VALUE_PAIR *vp;
1511         REQUEST *coa;
1512         fr_ipaddr_t ipaddr;
1513         char buffer[256];
1514
1515         rad_assert(request->proxy == NULL);
1516         rad_assert(!request->in_proxy_hash);
1517         rad_assert(request->proxy_reply == NULL);
1518
1519         vp = pairfind(request->config_items, PW_SEND_COA_REQUEST);
1520         if (!vp && request->coa) vp = pairfind(request->coa->proxy->vps, PW_SEND_COA_REQUEST);
1521         if (vp) {
1522                 if (vp->vp_integer == 0) {
1523                         ev_request_free(&request->coa);
1524                         return 1;       /* success */
1525                 }
1526
1527                 if (!request->coa) request_alloc_coa(request);
1528                 if (!request->coa) return 0;
1529         }
1530
1531         coa = request->coa;
1532
1533         /*
1534          *      src_ipaddr will be set up in proxy_encode.
1535          */
1536         memset(&ipaddr, 0, sizeof(ipaddr));
1537         vp = pairfind(coa->proxy->vps, PW_PACKET_DST_IP_ADDRESS);
1538         if (vp) {
1539                 ipaddr.af = AF_INET;
1540                 ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1541
1542         } else if ((vp = pairfind(coa->proxy->vps,
1543                                   PW_PACKET_DST_IPV6_ADDRESS)) != NULL) {
1544                 ipaddr.af = AF_INET6;
1545                 ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
1546                 
1547         } else if ((vp = pairfind(coa->proxy->vps,
1548                                   PW_HOME_SERVER_POOL)) != NULL) {
1549                 coa->home_pool = home_pool_byname(vp->vp_strvalue,
1550                                                   HOME_TYPE_COA);
1551                 if (!coa->home_pool) {
1552                         RDEBUG2("WARNING: No such home_server_pool %s",
1553                                vp->vp_strvalue);
1554         fail:
1555                         ev_request_free(&request->coa);
1556                         return 0;
1557                 }
1558
1559                 /*
1560                  *      Prefer
1561                  */
1562         } else if (request->client->coa_pool) {
1563                 coa->home_pool = request->client->coa_pool;
1564
1565         } else if (request->client->coa_server) {
1566                 coa->home_server = request->client->coa_server;
1567
1568         } else {
1569                 /*
1570                  *      If all else fails, send it to the client that
1571                  *      originated this request.
1572                  */
1573                 memcpy(&ipaddr, &request->packet->src_ipaddr, sizeof(ipaddr));
1574         }
1575
1576         /*
1577          *      Use the pool, if it exists.
1578          */
1579         if (coa->home_pool) {
1580                 coa->home_server = home_server_ldb(NULL, coa->home_pool, coa);
1581                 if (!coa->home_server) {
1582                         RDEBUG("WARNING: No live home server for home_server_pool %s", vp->vp_strvalue);
1583                         goto fail;
1584                 }
1585
1586         } else if (!coa->home_server) {
1587                 int port = PW_COA_UDP_PORT;
1588
1589                 vp = pairfind(coa->proxy->vps, PW_PACKET_DST_PORT);
1590                 if (vp) port = vp->vp_integer;
1591
1592                 coa->home_server = home_server_find(&ipaddr, port, IPPROTO_UDP);
1593                 if (!coa->home_server) {
1594                         RDEBUG2("WARNING: Unknown destination %s:%d for CoA request.",
1595                                inet_ntop(ipaddr.af, &ipaddr.ipaddr,
1596                                          buffer, sizeof(buffer)), port);
1597                         goto fail;
1598                 }
1599         }
1600
1601         vp = pairfind(coa->proxy->vps, PW_PACKET_TYPE);
1602         if (vp) {
1603                 switch (vp->vp_integer) {
1604                 case PW_COA_REQUEST:
1605                 case PW_DISCONNECT_REQUEST:
1606                         coa->proxy->code = vp->vp_integer;
1607                         break;
1608                         
1609                 default:
1610                         DEBUG("Cannot set CoA Packet-Type to code %d",
1611                               vp->vp_integer);
1612                         goto fail;
1613                 }
1614         }
1615
1616         if (!coa->proxy->code) coa->proxy->code = PW_COA_REQUEST;
1617
1618         /*
1619          *      The rest of the server code assumes that
1620          *      request->packet && request->reply exist.  Copy them
1621          *      from the original request.
1622          */
1623         rad_assert(coa->packet != NULL);
1624         rad_assert(coa->packet->vps == NULL);
1625         memcpy(coa->packet, request->packet, sizeof(*request->packet));
1626         coa->packet->vps = paircopy(request->packet->vps);
1627         coa->packet->data = NULL;
1628         rad_assert(coa->reply != NULL);
1629         rad_assert(coa->reply->vps == NULL);
1630         memcpy(coa->reply, request->reply, sizeof(*request->reply));
1631         coa->reply->vps = paircopy(request->reply->vps);
1632         coa->reply->data = NULL;
1633         coa->config_items = paircopy(request->config_items);
1634
1635         /*
1636          *      Call the pre-proxy routines.
1637          */
1638         vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE);
1639         if (vp) {
1640                 RDEBUG2("  Found Pre-Proxy-Type %s", vp->vp_strvalue);
1641                 pre_proxy_type = vp->vp_integer;
1642         }
1643
1644         if (coa->home_pool && coa->home_pool->virtual_server) {
1645                 const char *old_server = coa->server;
1646                 
1647                 coa->server = coa->home_pool->virtual_server;
1648                 RDEBUG2(" server %s {", coa->server);
1649                 rcode = module_pre_proxy(pre_proxy_type, coa);
1650                 RDEBUG2(" }");
1651                 coa->server = old_server;
1652         } else {
1653                 rcode = module_pre_proxy(pre_proxy_type, coa);
1654         }
1655         switch (rcode) {
1656         default:
1657                 goto fail;
1658
1659         /*
1660          *      Only send the CoA packet if the pre-proxy code succeeded.
1661          */
1662         case RLM_MODULE_NOOP:
1663         case RLM_MODULE_OK:
1664         case RLM_MODULE_UPDATED:
1665                 break;
1666         }
1667
1668         /*
1669          *      Source IP / port is set when the proxy socket
1670          *      is chosen.
1671          */
1672         coa->proxy->dst_ipaddr = coa->home_server->ipaddr;
1673         coa->proxy->dst_port = coa->home_server->port;
1674
1675         if (!insert_into_proxy_hash(coa)) {
1676                 radlog(L_PROXY, "Failed inserting CoA request into proxy hash.");
1677                 goto fail;
1678         }
1679
1680         /*
1681          *      We CANNOT divorce the CoA request from the parent
1682          *      request.  This function is running in a child thread,
1683          *      and we need access to the main event loop in order to
1684          *      to add the timers for the CoA packet.  See
1685          *      wait_a_bit().
1686          */
1687
1688         /*
1689          *      Forget about the original request completely at this
1690          *      point.
1691          */
1692         request = coa;
1693
1694         gettimeofday(&request->proxy_when, NULL);       
1695         request->received = request->next_when = request->proxy_when;
1696         rad_assert(request->proxy_reply == NULL);
1697
1698         /*
1699          *      Implement re-transmit algorithm as per RFC 5080
1700          *      Section 2.2.1.
1701          *
1702          *      We want IRT + RAND*IRT
1703          *      or 0.9 IRT + rand(0,.2) IRT
1704          *
1705          *      2^20 ~ USEC, and we want 2.
1706          *      rand(0,0.2) USEC ~ (rand(0,2^21) / 10)
1707          */
1708         delay = (fr_rand() & ((1 << 22) - 1)) / 10;
1709         request->delay = delay * request->home_server->coa_irt;
1710         delay = request->home_server->coa_irt * USEC;
1711         delay -= delay / 10;
1712         delay += request->delay;
1713      
1714         request->delay = delay;
1715         tv_add(&request->next_when, delay);
1716         request->next_callback = retransmit_coa_request;
1717         
1718         /*
1719          *      Note that we set proxied BEFORE sending the packet.
1720          *
1721          *      Once we send it, the request is tainted, as
1722          *      another thread may have picked it up.  Don't
1723          *      touch it!
1724          */
1725         request->num_proxied_requests = 1;
1726         request->num_proxied_responses = 0;
1727         request->child_pid = NO_SUCH_CHILD_PID;
1728
1729         update_event_timestamp(request->proxy, request->proxy_when.tv_sec);
1730
1731         request->child_state = REQUEST_PROXIED;
1732
1733         DEBUG_PACKET(request, request->proxy, 1);
1734
1735         request->proxy_listener->send(request->proxy_listener,
1736                                       request);
1737         return 1;
1738 }
1739 #endif  /* WITH_COA */
1740
1741 #ifdef WITH_PROXY
1742 static int process_proxy_reply(REQUEST *request)
1743 {
1744         int rcode;
1745         int post_proxy_type = 0;
1746         VALUE_PAIR *vp;
1747         
1748         /*
1749          *      Delete any reply we had accumulated until now.
1750          */
1751         pairfree(&request->reply->vps);
1752         
1753         /*
1754          *      Run the packet through the post-proxy stage,
1755          *      BEFORE playing games with the attributes.
1756          */
1757         vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
1758         if (vp) {
1759                 RDEBUG2("  Found Post-Proxy-Type %s", vp->vp_strvalue);
1760                 post_proxy_type = vp->vp_integer;
1761         }
1762         
1763         if (request->home_pool && request->home_pool->virtual_server) {
1764                 const char *old_server = request->server;
1765                 
1766                 request->server = request->home_pool->virtual_server;
1767                 RDEBUG2(" server %s {", request->server);
1768                 rcode = module_post_proxy(post_proxy_type, request);
1769                 RDEBUG2(" }");
1770                 request->server = old_server;
1771         } else {
1772                 rcode = module_post_proxy(post_proxy_type, request);
1773         }
1774
1775 #ifdef WITH_COA
1776         if (request->packet->code == request->proxy->code)
1777           /*
1778            *    Don't run the next bit if we originated a CoA
1779            *    packet, after receiving an Access-Request or
1780            *    Accounting-Request.
1781            */
1782 #endif
1783         
1784         /*
1785          *      There may NOT be a proxy reply, as we may be
1786          *      running Post-Proxy-Type = Fail.
1787          */
1788         if (request->proxy_reply) {
1789                 /*
1790                  *      Delete the Proxy-State Attributes from
1791                  *      the reply.  These include Proxy-State
1792                  *      attributes from us and remote server.
1793                  */
1794                 pairdelete(&request->proxy_reply->vps, PW_PROXY_STATE);
1795                 
1796                 /*
1797                  *      Add the attributes left in the proxy
1798                  *      reply to the reply list.
1799                  */
1800                 pairadd(&request->reply->vps, request->proxy_reply->vps);
1801                 request->proxy_reply->vps = NULL;
1802                 
1803                 /*
1804                  *      Free proxy request pairs.
1805                  */
1806                 pairfree(&request->proxy->vps);
1807         }
1808         
1809         switch (rcode) {
1810         default:  /* Don't do anything */
1811                 break;
1812         case RLM_MODULE_FAIL:
1813                 /* FIXME: debug print stuff */
1814                 request->child_state = REQUEST_DONE;
1815                 return 0;
1816                 
1817         case RLM_MODULE_HANDLED:
1818                 /* FIXME: debug print stuff */
1819                 request->child_state = REQUEST_DONE;
1820                 return 0;
1821         }
1822
1823         return 1;
1824 }
1825 #endif
1826
1827 static int request_pre_handler(REQUEST *request)
1828 {
1829         int rcode;
1830
1831         rad_assert(request->magic == REQUEST_MAGIC);
1832         rad_assert(request->packet != NULL);
1833
1834         request->child_state = REQUEST_RUNNING;
1835
1836         /*
1837          *      Don't decode the packet if it's an internal "fake"
1838          *      request.  Instead, just return so that the caller can
1839          *      process it.
1840          */
1841         if (request->packet->dst_port == 0) {
1842                 request->username = pairfind(request->packet->vps,
1843                                              PW_USER_NAME);
1844                 request->password = pairfind(request->packet->vps,
1845                                              PW_USER_PASSWORD);
1846                 return 1;
1847         }
1848
1849 #ifdef WITH_PROXY
1850         /*
1851          *      Put the decoded packet into it's proper place.
1852          */
1853         if (request->proxy_reply != NULL) {
1854                 /*
1855                  *      FIXME: For now, we can only proxy RADIUS packets.
1856                  *
1857                  *      In order to proxy other packets, we need to
1858                  *      somehow cache the "decode" function.
1859                  */
1860                 rcode = rad_decode(request->proxy_reply, request->proxy,
1861                                    request->home_server->secret);
1862                 DEBUG_PACKET(request, request->proxy_reply, 0);
1863         } else
1864 #endif
1865         if (request->packet->vps == NULL) {
1866                 rcode = request->listener->decode(request->listener, request);
1867                 
1868                 if (debug_condition) {
1869                         int result = FALSE;
1870                         const char *my_debug = debug_condition;
1871
1872                         /*
1873                          *      Ignore parse errors.
1874                          */
1875                         radius_evaluate_condition(request, RLM_MODULE_OK, 0,
1876                                                   &my_debug, 1,
1877                                                   &result);
1878                         if (result) {
1879                                 request->options = 2;
1880                                 request->radlog = radlog_request;
1881                         }
1882                 }
1883                 
1884                 DEBUG_PACKET(request, request->packet, 0);
1885         } else {
1886                 rcode = 0;
1887         }
1888
1889         if (rcode < 0) {
1890                 radlog(L_ERR, "%s Dropping packet without response.", fr_strerror());
1891                 request->child_state = REQUEST_DONE;
1892                 return 0;
1893         }
1894
1895         if (!request->username) {
1896                 request->username = pairfind(request->packet->vps,
1897                                              PW_USER_NAME);
1898         }
1899
1900 #ifdef WITH_PROXY
1901         if (request->proxy) {
1902                 return process_proxy_reply(request);
1903 #endif
1904         }
1905
1906         return 1;
1907 }
1908
1909
1910 #ifdef WITH_PROXY
1911 /*
1912  *      Do state handling when we proxy a request.
1913  */
1914 static int proxy_request(REQUEST *request)
1915 {
1916         struct timeval when;
1917         char buffer[128];
1918
1919         if (request->home_server->server) {
1920                 RDEBUG("ERROR: Cannot perform real proxying to a virtual server.");
1921                 return 0;
1922         }
1923
1924         if (!insert_into_proxy_hash(request)) {
1925                 radlog(L_PROXY, "Failed inserting request into proxy hash.");
1926                 return 0;
1927         }
1928
1929         request->proxy_listener->encode(request->proxy_listener, request);
1930
1931         when = request->received;
1932         when.tv_sec += request->root->max_request_time;
1933
1934         gettimeofday(&request->proxy_when, NULL);
1935
1936         request->next_when = request->proxy_when;
1937         request->next_when.tv_sec += request->home_server->response_window;
1938
1939         rad_assert(request->home_server->response_window > 0);
1940
1941         if (timercmp(&when, &request->next_when, <)) {
1942                 request->next_when = when;
1943         }
1944         request->next_callback = no_response_to_proxied_request;
1945
1946         RDEBUG2("Proxying request %d to home server %s port %d",
1947                request->number,
1948                inet_ntop(request->proxy->dst_ipaddr.af,
1949                          &request->proxy->dst_ipaddr.ipaddr,
1950                          buffer, sizeof(buffer)),
1951                 request->proxy->dst_port);
1952
1953         /*
1954          *      Note that we set proxied BEFORE sending the packet.
1955          *
1956          *      Once we send it, the request is tainted, as
1957          *      another thread may have picked it up.  Don't
1958          *      touch it!
1959          */
1960         request->num_proxied_requests = 1;
1961         request->num_proxied_responses = 0;
1962 #ifdef HAVE_PTHREAD_H
1963         request->child_pid = NO_SUCH_CHILD_PID;
1964 #endif
1965         request->child_state = REQUEST_PROXIED;
1966
1967         DEBUG_PACKET(request, request->proxy, 1);
1968
1969         request->proxy_listener->send(request->proxy_listener,
1970                                       request);
1971         return 1;
1972 }
1973
1974
1975 /*
1976  *      "Proxy" the request by sending it to a new virtual server.
1977  */
1978 static int proxy_to_virtual_server(REQUEST *request)
1979 {
1980         REQUEST *fake;
1981         RAD_REQUEST_FUNP fun;
1982
1983         if (!request->home_server || !request->home_server->server) return 0;
1984
1985         if (request->parent) {
1986                 RDEBUG2("WARNING: Cancelling proxy request to virtual server %s as this request was itself proxied.", request->home_server->server);
1987                 return 0;
1988         }
1989
1990         fake = request_alloc_fake(request);
1991         if (!fake) {
1992                 RDEBUG2("WARNING: Out of memory");
1993                 return 0;
1994         }
1995
1996         fake->packet->vps = paircopy(request->proxy->vps);
1997         fake->server = request->home_server->server;
1998
1999         if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
2000                 fun = rad_authenticate;
2001
2002 #ifdef WITH_ACCOUNTING
2003         } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2004                 fun = rad_accounting;
2005 #endif
2006
2007         } else {
2008                 RDEBUG2("Unknown packet type %d", request->proxy->code);
2009                 ev_request_free(&fake);
2010                 return 0;
2011         }
2012
2013         RDEBUG2(">>> Sending proxied request internally to virtual server.");
2014         radius_handle_request(fake, fun);
2015         RDEBUG2("<<< Received proxied response code %d from internal virtual server.", fake->reply->code);
2016
2017         if (fake->reply->code != 0) {
2018                 request->proxy_reply = fake->reply;
2019                 fake->reply = NULL;
2020         } else {
2021                 /*
2022                  *      There was no response
2023                  */
2024                 setup_post_proxy_fail(request);
2025         }
2026
2027         ev_request_free(&fake);
2028
2029         process_proxy_reply(request);
2030
2031         /*
2032          *      Process it through the normal section again, but ONLY
2033          *      if we received a proxy reply..
2034          */
2035         if (request->proxy_reply) {
2036                 if (request->server) RDEBUG("server %s {",
2037                                             request->server != NULL ?
2038                                             request->server : ""); 
2039                 fun(request);
2040                 
2041                 if (request->server) RDEBUG("} # server %s",
2042                                             request->server != NULL ?
2043                                             request->server : "");
2044         }
2045
2046         return 2;               /* success, but NOT '1' !*/
2047 }
2048
2049 /*
2050  *      Return 1 if we did proxy it, or the proxy attempt failed
2051  *      completely.  Either way, the caller doesn't touch the request
2052  *      any more if we return 1.
2053  */
2054 static int successfully_proxied_request(REQUEST *request)
2055 {
2056         int rcode;
2057         int pre_proxy_type = 0;
2058         VALUE_PAIR *realmpair;
2059         VALUE_PAIR *strippedname;
2060         VALUE_PAIR *vp;
2061         char *realmname = NULL;
2062         home_server *home;
2063         REALM *realm = NULL;
2064         home_pool_t *pool;
2065
2066         /*
2067          *      If it was already proxied, do nothing.
2068          *
2069          *      FIXME: This should really be a serious error.
2070          */
2071         if (request->in_proxy_hash ||
2072             (request->proxy_reply && (request->proxy_reply->code != 0))) {
2073                 return 0;
2074         }
2075
2076         realmpair = pairfind(request->config_items, PW_PROXY_TO_REALM);
2077         if (!realmpair || (realmpair->length == 0)) {
2078                 int pool_type;
2079
2080                 vp = pairfind(request->config_items, PW_HOME_SERVER_POOL);
2081                 if (!vp) return 0;
2082
2083                 switch (request->packet->code) {
2084                 case PW_AUTHENTICATION_REQUEST:
2085                         pool_type = HOME_TYPE_AUTH;
2086                         break;
2087
2088 #ifdef WITH_ACCOUNTING
2089                 case PW_ACCOUNTING_REQUEST:
2090                         pool_type = HOME_TYPE_ACCT;
2091                         break;
2092 #endif
2093
2094 #ifdef WITH_COA
2095                 case PW_COA_REQUEST:
2096                 case PW_DISCONNECT_REQUEST:
2097                         pool_type = HOME_TYPE_COA;
2098                         break;
2099 #endif
2100
2101                 default:
2102                         return 0;
2103                 }
2104
2105                 pool = home_pool_byname(vp->vp_strvalue, pool_type);
2106                 if (!pool) {
2107                         RDEBUG2("ERROR: Cannot proxy to unknown pool %s",
2108                                 vp->vp_strvalue);
2109                         return 0;
2110                 }
2111
2112                 realmname = NULL; /* no realms */
2113                 realm = NULL;
2114                 goto found_pool;
2115         }
2116
2117         realmname = (char *) realmpair->vp_strvalue;
2118
2119         realm = realm_find2(realmname);
2120         if (!realm) {
2121                 RDEBUG2("ERROR: Cannot proxy to unknown realm %s", realmname);
2122                 return 0;
2123         }
2124
2125         /*
2126          *      Figure out which pool to use.
2127          */
2128         if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
2129                 pool = realm->auth_pool;
2130
2131 #ifdef WITH_ACCOUNTING
2132         } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
2133                 pool = realm->acct_pool;
2134 #endif
2135
2136 #ifdef WITH_COA
2137         } else if ((request->packet->code == PW_COA_REQUEST) ||
2138                    (request->packet->code == PW_DISCONNECT_REQUEST)) {
2139                 pool = realm->acct_pool;
2140 #endif
2141
2142         } else {
2143                 rad_panic("Internal sanity check failed");
2144         }
2145
2146         if (!pool) {
2147                 RDEBUG2(" WARNING: Cancelling proxy to Realm %s, as the realm is local.",
2148                        realmname);
2149                 return 0;
2150         }
2151
2152 found_pool:
2153         home = home_server_ldb(realmname, pool, request);
2154         if (!home) {
2155                 RDEBUG2("ERROR: Failed to find live home server for realm %s",
2156                        realmname);
2157                 return -1;
2158         }
2159         request->home_pool = pool;
2160
2161 #ifdef WITH_COA
2162         /*
2163          *      Once we've decided to proxy a request, we cannot send
2164          *      a CoA packet.  So we free up any CoA packet here.
2165          */
2166         ev_request_free(&request->coa);
2167 #endif
2168         /*
2169          *      Remember that we sent the request to a Realm.
2170          */
2171         if (realmname) pairadd(&request->packet->vps,
2172                                pairmake("Realm", realmname, T_OP_EQ));
2173
2174         /*
2175          *      Strip the name, if told to.
2176          *
2177          *      Doing it here catches the case of proxied tunneled
2178          *      requests.
2179          */
2180         if (realm && (realm->striprealm == TRUE) &&
2181            (strippedname = pairfind(request->proxy->vps, PW_STRIPPED_USER_NAME)) != NULL) {
2182                 /*
2183                  *      If there's a Stripped-User-Name attribute in
2184                  *      the request, then use THAT as the User-Name
2185                  *      for the proxied request, instead of the
2186                  *      original name.
2187                  *
2188                  *      This is done by making a copy of the
2189                  *      Stripped-User-Name attribute, turning it into
2190                  *      a User-Name attribute, deleting the
2191                  *      Stripped-User-Name and User-Name attributes
2192                  *      from the vps list, and making the new
2193                  *      User-Name the head of the vps list.
2194                  */
2195                 vp = pairfind(request->proxy->vps, PW_USER_NAME);
2196                 if (!vp) {
2197                         vp = radius_paircreate(request, NULL,
2198                                                PW_USER_NAME, PW_TYPE_STRING);
2199                         rad_assert(vp != NULL); /* handled by above function */
2200                         /* Insert at the START of the list */
2201                         vp->next = request->proxy->vps;
2202                         request->proxy->vps = vp;
2203                 }
2204                 memcpy(vp->vp_strvalue, strippedname->vp_strvalue,
2205                        sizeof(vp->vp_strvalue));
2206                 vp->length = strippedname->length;
2207
2208                 /*
2209                  *      Do NOT delete Stripped-User-Name.
2210                  */
2211         }
2212
2213         /*
2214          *      If there is no PW_CHAP_CHALLENGE attribute but
2215          *      there is a PW_CHAP_PASSWORD we need to add it
2216          *      since we can't use the request authenticator
2217          *      anymore - we changed it.
2218          */
2219         if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
2220             pairfind(request->proxy->vps, PW_CHAP_PASSWORD) &&
2221             pairfind(request->proxy->vps, PW_CHAP_CHALLENGE) == NULL) {
2222                 vp = radius_paircreate(request, &request->proxy->vps,
2223                                        PW_CHAP_CHALLENGE, PW_TYPE_OCTETS);
2224                 vp->length = AUTH_VECTOR_LEN;
2225                 memcpy(vp->vp_strvalue, request->packet->vector, AUTH_VECTOR_LEN);
2226         }
2227
2228         /*
2229          *      The RFC's say we have to do this, but FreeRADIUS
2230          *      doesn't need it.
2231          */
2232         vp = radius_paircreate(request, &request->proxy->vps,
2233                                PW_PROXY_STATE, PW_TYPE_OCTETS);
2234         snprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue), "%d",
2235                  request->packet->id);
2236         vp->length = strlen(vp->vp_strvalue);
2237
2238         /*
2239          *      Should be done BEFORE inserting into proxy hash, as
2240          *      pre-proxy may use this information, or change it.
2241          */
2242         request->proxy->code = request->packet->code;
2243
2244         /*
2245          *      Call the pre-proxy routines.
2246          */
2247         vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE);
2248         if (vp) {
2249                 RDEBUG2("  Found Pre-Proxy-Type %s", vp->vp_strvalue);
2250                 pre_proxy_type = vp->vp_integer;
2251         }
2252
2253         rad_assert(request->home_pool != NULL);
2254
2255         if (request->home_pool->virtual_server) {
2256                 const char *old_server = request->server;
2257                 
2258                 request->server = request->home_pool->virtual_server;
2259                 RDEBUG2(" server %s {", request->server);
2260                 rcode = module_pre_proxy(pre_proxy_type, request);
2261                 RDEBUG2(" }");
2262                         request->server = old_server;
2263         } else {
2264                 rcode = module_pre_proxy(pre_proxy_type, request);
2265         }
2266         switch (rcode) {
2267         case RLM_MODULE_FAIL:
2268         case RLM_MODULE_INVALID:
2269         case RLM_MODULE_NOTFOUND:
2270         case RLM_MODULE_USERLOCK:
2271         default:
2272                 /* FIXME: debug print failed stuff */
2273                 return -1;
2274
2275         case RLM_MODULE_REJECT:
2276         case RLM_MODULE_HANDLED:
2277                 return 0;
2278
2279         /*
2280          *      Only proxy the packet if the pre-proxy code succeeded.
2281          */
2282         case RLM_MODULE_NOOP:
2283         case RLM_MODULE_OK:
2284         case RLM_MODULE_UPDATED:
2285                 break;
2286         }
2287
2288         /*
2289          *      If it's a fake request, don't send the proxy
2290          *      packet.  The outer tunnel session will take
2291          *      care of doing that.
2292          */
2293         if (request->packet->dst_port == 0) {
2294                 request->home_server = NULL;
2295                 return 1;
2296         }
2297
2298         if (request->home_server->server) {
2299                 return proxy_to_virtual_server(request);
2300         }
2301
2302         if (!proxy_request(request)) {
2303                 RDEBUG("ERROR: Failed to proxy request %d", request->number);
2304                 return -1;
2305         }
2306         
2307         return 1;
2308 }
2309 #endif
2310
2311 static void request_post_handler(REQUEST *request)
2312 {
2313         int child_state = -1;
2314         struct timeval when;
2315         VALUE_PAIR *vp;
2316
2317         if ((request->master_state == REQUEST_STOP_PROCESSING) ||
2318             (request->parent &&
2319              (request->parent->master_state == REQUEST_STOP_PROCESSING))) {
2320                 RDEBUG2("Request %d was cancelled.", request->number);
2321 #ifdef HAVE_PTHREAD_H
2322                 request->child_pid = NO_SUCH_CHILD_PID;
2323 #endif
2324                 child_state = REQUEST_DONE;
2325                 goto cleanup;
2326         }
2327
2328         if (request->child_state != REQUEST_RUNNING) {
2329                 rad_panic("Internal sanity check failed");
2330         }
2331
2332 #ifdef WITH_COA
2333         /*
2334          *      If it's not in the request hash, it's a CoA request.
2335          *      We hope.
2336          */
2337         if (!request->in_request_hash &&
2338             request->proxy &&
2339             ((request->proxy->code == PW_COA_REQUEST) ||
2340              (request->proxy->code == PW_DISCONNECT_REQUEST))) {
2341                 request->next_callback = NULL;
2342                 child_state = REQUEST_DONE;
2343                 goto cleanup;
2344         }
2345 #endif
2346
2347         /*
2348          *      Catch Auth-Type := Reject BEFORE proxying the packet.
2349          */
2350         if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
2351             (request->reply->code == 0) &&
2352             ((vp = pairfind(request->config_items, PW_AUTH_TYPE)) != NULL) &&
2353             (vp->vp_integer == PW_AUTHTYPE_REJECT)) {
2354                 request->reply->code = PW_AUTHENTICATION_REJECT;
2355         }
2356
2357 #ifdef WITH_PROXY
2358         if (request->root->proxy_requests &&
2359             !request->in_proxy_hash &&
2360             (request->reply->code == 0) &&
2361             (request->packet->dst_port != 0) &&
2362             (request->packet->code != PW_STATUS_SERVER)) {
2363                 int rcode = successfully_proxied_request(request);
2364
2365                 if (rcode == 1) return; /* request is invalid */
2366
2367                 /*
2368                  *      Failed proxying it (dead home servers, etc.)
2369                  *      Run it through Post-Proxy-Type = Fail, and
2370                  *      respond to the request.
2371                  *
2372                  *      Note that we're in a child thread here, so we
2373                  *      do NOT re-schedule the request.  Instead, we
2374                  *      do what we would have done, which is run the
2375                  *      pre-handler, a NULL request handler, and then
2376                  *      the post handler.
2377                  */
2378                 if ((rcode < 0) && setup_post_proxy_fail(request)) {
2379                         request_pre_handler(request);
2380                 }
2381
2382                 /*
2383                  *      Else we weren't supposed to proxy it,
2384                  *      OR we proxied it internally to a virutal server.
2385                  */
2386         }
2387 #endif
2388
2389         /*
2390          *      Fake requests don't get encoded or signed.  The caller
2391          *      also requires the reply VP's, so we don't free them
2392          *      here!
2393          */
2394         if (request->packet->dst_port == 0) {
2395                 /* FIXME: RDEBUG going to the next request */
2396 #ifdef HAVE_PTHREAD_H
2397                 request->child_pid = NO_SUCH_CHILD_PID;
2398 #endif
2399                 request->child_state = REQUEST_DONE;
2400                 return;
2401         }
2402
2403 #ifdef WITH_PROXY
2404         /*
2405          *      Copy Proxy-State from the request to the reply.
2406          */
2407         vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
2408         if (vp) pairadd(&request->reply->vps, vp);
2409 #endif
2410
2411         /*
2412          *      Access-Requests get delayed or cached.
2413          */
2414         switch (request->packet->code) {
2415         case PW_AUTHENTICATION_REQUEST:
2416                 gettimeofday(&request->next_when, NULL);
2417
2418                 if (request->reply->code == 0) {
2419                         /*
2420                          *      Check if the lack of response is intentional.
2421                          */
2422                         vp = pairfind(request->config_items,
2423                                       PW_RESPONSE_PACKET_TYPE);
2424                         if (!vp) {
2425                                 RDEBUG2("There was no response configured: rejecting request %d",
2426                                        request->number);
2427                                 request->reply->code = PW_AUTHENTICATION_REJECT;
2428
2429                         } else if (vp->vp_integer == 256) {
2430                                 RDEBUG2("Not responding to request %d",
2431                                        request->number);
2432
2433                                 /*
2434                                  *      Force cleanup after a long
2435                                  *      time, so that we don't
2436                                  *      re-process the packet.
2437                                  */
2438                                 request->next_when.tv_sec += request->root->max_request_time;
2439                                 request->next_callback = cleanup_delay;
2440                                 child_state = REQUEST_CLEANUP_DELAY;
2441                                 break;
2442                         } else {
2443                                 request->reply->code = vp->vp_integer;
2444
2445                         }
2446                 }
2447
2448                 /*
2449                  *      Run rejected packets through
2450                  *
2451                  *      Post-Auth-Type = Reject
2452                  */
2453                 if (request->reply->code == PW_AUTHENTICATION_REJECT) {
2454                         pairdelete(&request->config_items, PW_POST_AUTH_TYPE);
2455                         vp = radius_pairmake(request, &request->config_items,
2456                                              "Post-Auth-Type", "Reject",
2457                                              T_OP_SET);
2458                         if (vp) rad_postauth(request);
2459
2460                         /*
2461                          *      If configured, delay Access-Reject packets.
2462                          *
2463                          *      If request->root->reject_delay = 0, we discover
2464                          *      that we have to send the packet now.
2465                          */
2466                         when = request->received;
2467                         when.tv_sec += request->root->reject_delay;
2468
2469                         if (timercmp(&when, &request->next_when, >)) {
2470                                 RDEBUG2("Delaying reject of request %d for %d seconds",
2471                                        request->number,
2472                                        request->root->reject_delay);
2473                                 request->next_when = when;
2474                                 request->next_callback = reject_delay;
2475 #ifdef HAVE_PTHREAD_H
2476                                 request->child_pid = NO_SUCH_CHILD_PID;
2477 #endif
2478                                 request->child_state = REQUEST_REJECT_DELAY;
2479                                 return;
2480                         }
2481                 }
2482
2483 #ifdef WITH_COA
2484         case PW_COA_REQUEST:
2485         case PW_DISCONNECT_REQUEST:
2486 #endif
2487                 request->next_when.tv_sec += request->root->cleanup_delay;
2488                 request->next_callback = cleanup_delay;
2489                 child_state = REQUEST_CLEANUP_DELAY;
2490                 break;
2491
2492         case PW_ACCOUNTING_REQUEST:
2493                 request->next_callback = NULL; /* just to be safe */
2494                 child_state = REQUEST_DONE;
2495                 break;
2496
2497                 /*
2498                  *      FIXME: Status-Server should probably not be
2499                  *      handled here...
2500                  */
2501         case PW_STATUS_SERVER:
2502                 request->next_callback = NULL;
2503                 child_state = REQUEST_DONE;
2504                 break;
2505
2506         default:
2507                 /*
2508                  *      DHCP, VMPS, etc.
2509                  */
2510                 request->next_callback = NULL;
2511                 child_state = REQUEST_DONE;
2512                 break;
2513         }
2514
2515         /*
2516          *      Suppress "no reply" packets here, unless we're reading
2517          *      from the "detail" file.  In that case, we've got to
2518          *      tell the detail file handler that the request is dead,
2519          *      and it should re-send it.
2520          *      If configured, encode, sign, and send.
2521          */
2522         if ((request->reply->code != 0) ||
2523             (request->listener->type == RAD_LISTEN_DETAIL)) {
2524                 DEBUG_PACKET(request, request->reply, 1);
2525                 request->listener->send(request->listener, request);
2526         }
2527
2528 #ifdef WITH_COA
2529         /*
2530          *      Now that we've completely processed the request,
2531          *      see if we need to originate a CoA request.
2532          */
2533         if (request->coa ||
2534             (pairfind(request->config_items, PW_SEND_COA_REQUEST) != NULL)) {
2535                 if (!originated_coa_request(request)) {
2536                         RDEBUG2("Do CoA Fail handler here");
2537                 }
2538                 /* request->coa is stil set, so we can update events */
2539         }
2540 #endif
2541
2542  cleanup:
2543         /*
2544          *      Clean up.  These are no longer needed.
2545          */
2546         pairfree(&request->config_items);
2547
2548         pairfree(&request->packet->vps);
2549         request->username = NULL;
2550         request->password = NULL;
2551
2552         pairfree(&request->reply->vps);
2553
2554 #ifdef WITH_PROXY
2555         if (request->proxy) {
2556                 pairfree(&request->proxy->vps);
2557
2558                 if (request->proxy_reply) {
2559                         pairfree(&request->proxy_reply->vps);
2560                 }
2561
2562 #if 0
2563                 /*
2564                  *      We're not tracking responses from the home
2565                  *      server, we can therefore free this memory in
2566                  *      the child thread.
2567                  */
2568                 if (!request->in_proxy_hash) {
2569                         rad_free(&request->proxy);
2570                         rad_free(&request->proxy_reply);
2571                         request->home_server = NULL;
2572                 }
2573 #endif
2574         }
2575 #endif
2576
2577         RDEBUG2("Finished request %d.", request->number);
2578         rad_assert(child_state >= 0);
2579         request->child_state = child_state;
2580
2581         /*
2582          *      Single threaded mode: update timers now.
2583          */
2584         if (!have_children) wait_a_bit(request);
2585 }
2586
2587
2588 static void received_retransmit(REQUEST *request, const RADCLIENT *client)
2589 {
2590 #ifdef WITH_PROXY
2591         char buffer[128];
2592 #endif
2593
2594         RAD_STATS_TYPE_INC(request->listener, total_dup_requests);
2595         RAD_STATS_CLIENT_INC(request->listener, client, total_dup_requests);
2596         
2597         switch (request->child_state) {
2598         case REQUEST_QUEUED:
2599         case REQUEST_RUNNING:
2600 #ifdef WITH_PROXY
2601         discard:
2602 #endif
2603                 radlog(L_ERR, "Discarding duplicate request from "
2604                        "client %s port %d - ID: %d due to unfinished request %d",
2605                        client->shortname,
2606                        request->packet->src_port,request->packet->id,
2607                        request->number);
2608                 break;
2609
2610 #ifdef WITH_PROXY
2611         case REQUEST_PROXIED:
2612                 /*
2613                  *      We're not supposed to have duplicate
2614                  *      accounting packets.  The other states handle
2615                  *      duplicates fine (discard, or send duplicate
2616                  *      reply).  But we do NOT want to retransmit an
2617                  *      accounting request here, because that would
2618                  *      involve updating the Acct-Delay-Time, and
2619                  *      therefore changing the packet Id, etc.
2620                  *
2621                  *      Instead, we just discard the packet.  We may
2622                  *      eventually respond, or the client will send a
2623                  *      new accounting packet.            
2624                  *
2625                  *      The same comments go for Status-Server, and
2626                  *      other packet types.
2627                  *
2628                  *      FIXME: coa: when we proxy CoA && Disconnect
2629                  *      packets, this logic has to be fixed.
2630                  */
2631                 if (request->packet->code != PW_AUTHENTICATION_REQUEST) {
2632                         goto discard;
2633                 }
2634
2635                 check_for_zombie_home_server(request);
2636
2637                 /*
2638                  *      If we've just discovered that the home server
2639                  *      is dead, OR the socket has been closed, look for
2640                  *      another connection to a home server.
2641                  */
2642                 if (((request->packet->dst_port != 0) &&
2643                      (request->home_server->state == HOME_STATE_IS_DEAD)) ||
2644                     (request->proxy_listener->status != RAD_LISTEN_STATUS_KNOWN)) {
2645                         home_server *home;
2646
2647                         remove_from_proxy_hash(request);
2648
2649                         home = home_server_ldb(NULL, request->home_pool, request);
2650                         if (!home) {
2651                                 RDEBUG2("Failed to find live home server for request %d", request->number);
2652                         no_home_servers:
2653                                 /*
2654                                  *      Do post-request processing,
2655                                  *      and any insertion of necessary
2656                                  *      events.
2657                                  */
2658                                 post_proxy_fail_handler(request);
2659                                 return;
2660                         }
2661
2662                         request->proxy->code = request->packet->code;
2663
2664                         /*
2665                          *      Free the old packet, to force re-encoding
2666                          */
2667                         free(request->proxy->data);
2668                         request->proxy->data = NULL;
2669                         request->proxy->data_len = 0;
2670
2671                         /*
2672                          *      This request failed over to a virtual
2673                          *      server.  Push it back onto the queue
2674                          *      to be processed.
2675                          */
2676                         if (request->home_server->server) {
2677                                 proxy_fallback_handler(request);
2678                                 return;
2679                         }
2680
2681                         /*
2682                          *      Try to proxy the request.
2683                          */
2684                         if (!proxy_request(request)) {
2685                                 RDEBUG("ERROR: Failed to re-proxy request %d", request->number);
2686                                 goto no_home_servers;
2687                         }
2688
2689                         /*
2690                          *      This code executes in the main server
2691                          *      thread, so there's no need for locking.
2692                          */
2693                         rad_assert(request->next_callback != NULL);
2694                         INSERT_EVENT(request->next_callback, request);
2695                         request->next_callback = NULL;
2696                         return;
2697                 } /* else the home server is still alive */
2698
2699 #ifdef WITH_TCP
2700                 if (request->home_server->proto == IPPROTO_TCP) {
2701                         DEBUG2("Suppressing duplicate proxied request to home server %s port %d proto TCP - ID: %d",
2702                                inet_ntop(request->proxy->dst_ipaddr.af,
2703                                          &request->proxy->dst_ipaddr.ipaddr,
2704                                          buffer, sizeof(buffer)),
2705                                request->proxy->dst_port,
2706                                request->proxy->id);
2707                         break;
2708                 }
2709 #endif
2710
2711                 RDEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",
2712                        inet_ntop(request->proxy->dst_ipaddr.af,
2713                                  &request->proxy->dst_ipaddr.ipaddr,
2714                                  buffer, sizeof(buffer)),
2715                        request->proxy->dst_port,
2716                        request->proxy->id);
2717                 request->num_proxied_requests++;
2718
2719                 DEBUG_PACKET(request, request->proxy, 1);
2720                 request->proxy_listener->send(request->proxy_listener,
2721                                               request);
2722                 break;
2723 #endif
2724
2725         case REQUEST_REJECT_DELAY:
2726                 RDEBUG2("Waiting to send Access-Reject "
2727                        "to client %s port %d - ID: %d",
2728                        client->shortname,
2729                        request->packet->src_port, request->packet->id);
2730                 break;
2731
2732         case REQUEST_CLEANUP_DELAY:
2733         case REQUEST_DONE:
2734                 if (request->reply->code == 0) {
2735                         RDEBUG2("Ignoring retransmit from client %s port %d "
2736                                 "- ID: %d, no reply was configured",
2737                                 client->shortname,
2738                                 request->packet->src_port, request->packet->id);
2739                         return;
2740                 }
2741
2742                 /*
2743                  *      FIXME: This sends duplicate replies to
2744                  *      accounting requests, even if Acct-Delay-Time
2745                  *      or Event-Timestamp is in the packet.  In those
2746                  *      cases, the Id should be changed, and the packet
2747                  *      re-calculated.
2748                  */
2749                 RDEBUG2("Sending duplicate reply "
2750                        "to client %s port %d - ID: %d",
2751                        client->shortname,
2752                        request->packet->src_port, request->packet->id);
2753                 DEBUG_PACKET(request, request->reply, 1);
2754                 request->listener->send(request->listener, request);
2755                 break;
2756         }
2757 }
2758
2759
2760 static void received_conflicting_request(REQUEST *request,
2761                                          const RADCLIENT *client)
2762 {
2763         radlog(L_ERR, "Received conflicting packet from "
2764                "client %s port %d - ID: %d due to unfinished request %d.  Giving up on old request.",
2765                client->shortname,
2766                request->packet->src_port, request->packet->id,
2767                request->number);
2768
2769         /*
2770          *      Nuke it from the request hash, so we can receive new
2771          *      packets.
2772          */
2773         remove_from_request_hash(request);
2774
2775         switch (request->child_state) {
2776                 /*
2777                  *      Tell it to stop, and wait for it to do so.
2778                  */
2779         default:
2780                 request->master_state = REQUEST_STOP_PROCESSING;
2781                 request->delay += request->delay >> 1;
2782
2783                 tv_add(&request->when, request->delay);
2784
2785                 INSERT_EVENT(wait_for_child_to_die, request);
2786                 return;
2787
2788                 /*
2789                  *      Catch race conditions.  It may have switched
2790                  *      from running to done while this code is being
2791                  *      executed.
2792                  */
2793         case REQUEST_REJECT_DELAY:
2794         case REQUEST_CLEANUP_DELAY:
2795         case REQUEST_DONE:
2796                 break;
2797         }
2798 }
2799
2800
2801 static int can_handle_new_request(RADIUS_PACKET *packet,
2802                                   RADCLIENT *client,
2803                                   struct main_config_t *root)
2804 {
2805         /*
2806          *      Count the total number of requests, to see if
2807          *      there are too many.  If so, return with an
2808          *      error.
2809          */
2810         if (root->max_requests) {
2811                 int request_count = fr_packet_list_num_elements(pl);
2812
2813                 /*
2814                  *      This is a new request.  Let's see if
2815                  *      it makes us go over our configured
2816                  *      bounds.
2817                  */
2818                 if (request_count > root->max_requests) {
2819                         radlog(L_ERR, "Dropping request (%d is too many): "
2820                                "from client %s port %d - ID: %d", request_count,
2821                                client->shortname,
2822                                packet->src_port, packet->id);
2823                         radlog(L_INFO, "WARNING: Please check the configuration file.\n"
2824                                "\tThe value for 'max_requests' is probably set too low.\n");
2825                         return 0;
2826                 } /* else there were a small number of requests */
2827         } /* else there was no configured limit for requests */
2828
2829         /*
2830          *      FIXME: Add per-client checks.  If one client is sending
2831          *      too many packets, start discarding them.
2832          *
2833          *      We increment the counters here, and decrement them
2834          *      when the response is sent... somewhere in this file.
2835          */
2836
2837         /*
2838          *      FUTURE: Add checks for system load.  If the system is
2839          *      busy, start dropping requests...
2840          *
2841          *      We can probably keep some statistics ourselves...  if
2842          *      there are more requests coming in than we can handle,
2843          *      start dropping some.
2844          */
2845
2846         return 1;
2847 }
2848
2849
2850 int received_request(rad_listen_t *listener,
2851                      RADIUS_PACKET *packet, REQUEST **prequest,
2852                      RADCLIENT *client)
2853 {
2854         RADIUS_PACKET **packet_p;
2855         REQUEST *request = NULL;
2856         struct main_config_t *root = &mainconfig;
2857
2858         packet_p = fr_packet_list_find(pl, packet);
2859         if (packet_p) {
2860                 request = fr_packet2myptr(REQUEST, packet, packet_p);
2861                 rad_assert(request->in_request_hash);
2862
2863                 if ((request->packet->data_len == packet->data_len) &&
2864                     (memcmp(request->packet->vector, packet->vector,
2865                             sizeof(packet->vector)) == 0)) {
2866                         received_retransmit(request, client);
2867                         return 0;
2868                 }
2869
2870                 /*
2871                  *      The new request is different from the old one,
2872                  *      but maybe the old is finished.  If so, delete
2873                  *      the old one.
2874                  */
2875                 switch (request->child_state) {
2876                         struct timeval when;
2877
2878                 default:
2879                         /*
2880                          *      Special hacks for race conditions.
2881                          *      The reply is encoded, and therefore
2882                          *      likely sent.  We received a *new*
2883                          *      packet from the client, likely before
2884                          *      the next line or two of code which
2885                          *      updated the child state.  In this
2886                          *      case, just accept the new request.
2887                          */
2888                         if ((request->reply->code != 0) &&
2889                             request->reply->data) {
2890                                 radlog(L_INFO, "WARNING: Allowing fast client %s port %d - ID: %d for recent request %d.",
2891                                        client->shortname,
2892                                        packet->src_port, packet->id,
2893                                        request->number);
2894                                 remove_from_request_hash(request);
2895                                 request = NULL;
2896                                 break;
2897                         }
2898
2899                         gettimeofday(&when, NULL);
2900                         when.tv_sec -= 1;
2901
2902                         /*
2903                          *      If the cached request was received
2904                          *      within the last second, then we
2905                          *      discard the NEW request instead of the
2906                          *      old one.  This will happen ONLY when
2907                          *      the client is severely broken, and is
2908                          *      sending conflicting packets very
2909                          *      quickly.
2910                          */
2911                         if (timercmp(&when, &request->received, <)) {
2912                                 radlog(L_ERR, "Discarding conflicting packet from "
2913                                        "client %s port %d - ID: %d due to recent request %d.",
2914                                        client->shortname,
2915                                        packet->src_port, packet->id,
2916                                        request->number);
2917                                 return 0;
2918                         }
2919
2920                         received_conflicting_request(request, client);
2921                         request = NULL;
2922                         break;
2923
2924                 case REQUEST_REJECT_DELAY:
2925                 case REQUEST_CLEANUP_DELAY:
2926                         request->child_state = REQUEST_DONE;
2927                 case REQUEST_DONE:
2928                         cleanup_delay(request);
2929                         request = NULL;
2930                         break;
2931                 }
2932         }
2933
2934         /*
2935          *      We may want to quench the new request.
2936          */
2937         if ((listener->type != RAD_LISTEN_DETAIL) &&
2938             !can_handle_new_request(packet, client, root)) {
2939                 return 0;
2940         }
2941
2942         /*
2943          *      Create and initialize the new request.
2944          */
2945         request = request_alloc(); /* never fails */
2946
2947         if ((request->reply = rad_alloc(0)) == NULL) {
2948                 radlog(L_ERR, "No memory");
2949                 exit(1);
2950         }
2951
2952         request->listener = listener;
2953         request->client = client;
2954         request->packet = packet;
2955         request->packet->timestamp = request->timestamp;
2956         request->number = request_num_counter++;
2957         request->priority = listener->type;
2958 #ifdef HAVE_PTHREAD_H
2959         request->child_pid = NO_SUCH_CHILD_PID;
2960 #endif
2961
2962         /*
2963          *      Status-Server packets go to the head of the queue.
2964          */
2965         if (request->packet->code == PW_STATUS_SERVER) request->priority = 0;
2966
2967         /*
2968          *      Set virtual server identity
2969          */
2970         if (client->server) {
2971                 request->server = client->server;
2972         } else if (listener->server) {
2973                 request->server = listener->server;
2974         } else {
2975                 request->server = NULL;
2976         }
2977
2978         /*
2979          *      Remember the request in the list.
2980          */
2981         if (!fr_packet_list_insert(pl, &request->packet)) {
2982                 radlog(L_ERR, "Failed to insert request %d in the list of live requests: discarding", request->number);
2983                 ev_request_free(&request);
2984                 return 0;
2985         }
2986
2987         request->in_request_hash = TRUE;
2988         request->root = root;
2989         root->refcount++;
2990 #ifdef WITH_TCP
2991         request->listener->count++;
2992 #endif
2993
2994         /*
2995          *      The request passes many of our sanity checks.
2996          *      From here on in, if anything goes wrong, we
2997          *      send a reject message, instead of dropping the
2998          *      packet.
2999          */
3000
3001         /*
3002          *      Build the reply template from the request.
3003          */
3004
3005         request->reply->sockfd = request->packet->sockfd;
3006         request->reply->dst_ipaddr = request->packet->src_ipaddr;
3007         request->reply->src_ipaddr = request->packet->dst_ipaddr;
3008         request->reply->dst_port = request->packet->src_port;
3009         request->reply->src_port = request->packet->dst_port;
3010         request->reply->id = request->packet->id;
3011         request->reply->code = 0; /* UNKNOWN code */
3012         memcpy(request->reply->vector, request->packet->vector,
3013                sizeof(request->reply->vector));
3014         request->reply->vps = NULL;
3015         request->reply->data = NULL;
3016         request->reply->data_len = 0;
3017
3018         request->master_state = REQUEST_ACTIVE;
3019         request->child_state = REQUEST_QUEUED;
3020         request->next_callback = NULL;
3021
3022         gettimeofday(&request->received, NULL);
3023         request->timestamp = request->received.tv_sec;
3024         request->when = request->received;
3025
3026         request->delay = USEC;
3027
3028         tv_add(&request->when, request->delay);
3029
3030         INSERT_EVENT(wait_a_bit, request);
3031
3032         *prequest = request;
3033         return 1;
3034 }
3035
3036
3037 #ifdef WITH_PROXY
3038 REQUEST *received_proxy_response(RADIUS_PACKET *packet)
3039 {
3040         char            buffer[128];
3041         REQUEST         *request;
3042
3043         /*
3044          *      Also removes from the proxy hash if responses == requests
3045          */
3046         request = lookup_in_proxy_hash(packet);
3047
3048         if (!request) {
3049                 radlog(L_PROXY, "No outstanding request was found for reply from host %s port %d - ID %d",
3050                        inet_ntop(packet->src_ipaddr.af,
3051                                  &packet->src_ipaddr.ipaddr,
3052                                  buffer, sizeof(buffer)),
3053                        packet->src_port, packet->id);
3054                 return NULL;
3055         }
3056
3057         /*
3058          *      We haven't replied to the NAS, but we have seen an
3059          *      earlier reply from the home server.  Ignore this packet,
3060          *      as we're likely still processing the previous reply.
3061          */
3062         if (request->proxy_reply) {
3063                 if (memcmp(request->proxy_reply->vector,
3064                            packet->vector,
3065                            sizeof(request->proxy_reply->vector)) == 0) {
3066                         RDEBUG2("Discarding duplicate reply from host %s port %d  - ID: %d for request %d",
3067                                inet_ntop(packet->src_ipaddr.af,
3068                                          &packet->src_ipaddr.ipaddr,
3069                                          buffer, sizeof(buffer)),
3070                                packet->src_port, packet->id,
3071                                request->number);
3072                 } else {
3073                         /*
3074                          *      ? The home server gave us a new proxy
3075                          *      reply which doesn't match the old
3076                          *      one.  Delete it.
3077                          */
3078                         RDEBUG2("Ignoring conflicting proxy reply");
3079                 }
3080                 
3081                 /* assert that there's an event queued for request? */
3082                 return NULL;
3083         }
3084
3085         /*
3086          *      Verify the packet before doing ANYTHING with it.  This
3087          *      means we're doing more MD5 checks in the server core.
3088          *      However, we can fix that by moving to multiple threads
3089          *      listening on sockets.
3090          *
3091          *      We do this AFTER looking the request up in the hash,
3092          *      and AFTER vhecking if we saw a previous request.  This
3093          *      helps minimize the DoS effect of people attacking us
3094          *      with spoofed packets.
3095          */
3096         if (rad_verify(packet, request->proxy,
3097                        request->home_server->secret) != 0) {
3098                 DEBUG("Ignoring spoofed proxy reply.  Signature is invalid");
3099                 return NULL;
3100         }
3101
3102         gettimeofday(&now, NULL);
3103
3104         /*
3105          *      Maybe move this earlier in the decision process?
3106          *      Having it here means that late or duplicate proxy
3107          *      replies no longer get the home server marked as
3108          *      "alive".  This might be good for stability, though.
3109          *
3110          *      FIXME: Do we really want to do this whenever we
3111          *      receive a packet?  Setting this here means that we
3112          *      mark it alive on *any* packet, even if it's lost all
3113          *      of the *other* packets in the last 10s.
3114          */
3115         if (request->proxy->code != PW_STATUS_SERVER) {
3116                 request->home_server->state = HOME_STATE_ALIVE;
3117         }
3118         
3119 #ifdef WITH_COA
3120         /*
3121          *      When originating CoA, the "proxy" reply is the reply
3122          *      to the CoA request that we originated.  At this point,
3123          *      the original request is finished, and it has a reply.
3124          *
3125          *      However, if we haven't separated the two requests, do
3126          *      so now.  This is done so that cleaning up the original
3127          *      request won't cause the CoA request to be free'd.  See
3128          *      util.c, request_free()
3129          */
3130         if (request->parent && (request->parent->coa == request)) {
3131                 request->parent->coa = NULL;
3132                 request->parent = NULL;
3133
3134         } else
3135                 /*
3136                  *      Skip the next set of checks, as the original
3137                  *      reply is cached.  We want to be able to still
3138                  *      process the CoA reply, AND to reference the
3139                  *      original request/reply.
3140                  *
3141                  *      This is getting to be really quite a bit of a
3142                  *      hack.
3143                  */
3144 #endif
3145
3146         /*
3147          *      If there's a reply to the NAS, ignore everything
3148          *      related to proxy responses
3149          */
3150         if (request->reply && request->reply->code != 0) {
3151                 RDEBUG2("Ignoring proxy reply that arrived after we sent a reply to the NAS");
3152                 return NULL;
3153         }
3154         
3155 #ifdef WITH_STATS
3156         /*
3157          *      The average includes our time to receive packets and
3158          *      look them up in the hashes, which should be the same
3159          *      for all packets.
3160          *
3161          *      We update the response time only for the FIRST packet
3162          *      we receive.
3163          */
3164         if (request->home_server->ema.window > 0) {
3165                 radius_stats_ema(&request->home_server->ema,
3166                                  &now, &request->proxy_when);
3167         }
3168 #endif
3169
3170         switch (request->child_state) {
3171         case REQUEST_QUEUED:
3172         case REQUEST_RUNNING:
3173                 radlog(L_ERR, "Internal sanity check failed for child state");
3174                 /* FALL-THROUGH */
3175
3176         case REQUEST_REJECT_DELAY:
3177         case REQUEST_CLEANUP_DELAY:
3178         case REQUEST_DONE:
3179                 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'",
3180                        inet_ntop(packet->src_ipaddr.af,
3181                                  &packet->src_ipaddr.ipaddr,
3182                                  buffer, sizeof(buffer)),
3183                        packet->src_port, packet->id,
3184                        request->number);
3185                 /* assert that there's an event queued for request? */
3186                 return NULL;
3187
3188         case REQUEST_PROXIED:
3189                 break;
3190         }
3191
3192         request->proxy_reply = packet;
3193
3194 #if 0
3195         /*
3196          *      Perform RTT calculations, as per RFC 2988 (for TCP).
3197          *      Note that we only do so on the first response.
3198          */
3199         if ((request->num_proxied_responses == 1)
3200                 int rtt;
3201                 home_server *home = request->home_server;
3202
3203                 rtt = now.tv_sec - request->proxy_when.tv_sec;
3204                 rtt *= USEC;
3205                 rtt += now.tv_usec;
3206                 rtt -= request->proxy_when.tv_usec;
3207
3208                 if (!home->has_rtt) {
3209                         home->has_rtt = TRUE;
3210
3211                         home->srtt = rtt;
3212                         home->rttvar = rtt / 2;
3213
3214                 } else {
3215                         home->rttvar -= home->rttvar >> 2;
3216                         home->rttvar += (home->srtt - rtt);
3217                         home->srtt -= home->srtt >> 3;
3218                         home->srtt += rtt >> 3;
3219                 }
3220
3221                 home->rto = home->srtt;
3222                 if (home->rttvar > (USEC / 4)) {
3223                         home->rto += home->rttvar * 4;
3224                 } else {
3225                         home->rto += USEC;
3226                 }
3227         }
3228 #endif
3229
3230         /*
3231          *      There's no incoming request, so it's a proxied packet
3232          *      we originated.
3233          */
3234         if (!request->packet) {
3235                 received_response_to_ping(request);
3236                 request->proxy_reply = NULL; /* caller will free it */
3237                 ev_request_free(&request);
3238                 return NULL;
3239         }
3240
3241         request->child_state = REQUEST_QUEUED;
3242         request->when = now;
3243         request->delay = USEC;
3244         request->priority = RAD_LISTEN_PROXY;
3245         tv_add(&request->when, request->delay);
3246
3247         /*
3248          *      Wait a bit will take care of max_request_time
3249          */
3250         INSERT_EVENT(wait_a_bit, request);
3251
3252         return request;
3253 }
3254
3255 #endif /* WITH_PROXY */
3256
3257 #ifdef WITH_TCP
3258 static void tcp_socket_lifetime(void *ctx)
3259 {
3260         rad_listen_t *listener = ctx;
3261         char buffer[256];
3262
3263         listener->print(listener, buffer, sizeof(buffer));
3264
3265         DEBUG("Reached maximum lifetime on socket %s", buffer);
3266
3267         listener->status = RAD_LISTEN_STATUS_CLOSED;
3268         event_new_fd(listener);
3269 }
3270
3271 static void tcp_socket_idle_timeout(void *ctx)
3272 {
3273         rad_listen_t *listener = ctx;
3274         listen_socket_t *sock = listener->data;
3275         char buffer[256];
3276
3277         fr_event_now(el, &now); /* should always succeed... */
3278
3279         rad_assert(sock->home != NULL);
3280
3281         /*
3282          *      We implement idle timeout by polling, because it's
3283          *      cheaper than resetting the idle timeout every time
3284          *      we send / receive a packet.
3285          */
3286         if ((sock->last_packet + sock->home->idle_timeout) > now.tv_sec) {
3287                 struct timeval when;
3288                 void *fun = tcp_socket_idle_timeout;
3289                 
3290                 when.tv_sec = sock->last_packet;
3291                 when.tv_sec += sock->home->idle_timeout;
3292                 when.tv_usec = 0;
3293
3294                 if (sock->home->lifetime &&
3295                     (sock->opened + sock->home->lifetime < when.tv_sec)) {
3296                         when.tv_sec = sock->opened + sock->home->lifetime;
3297                         fun = tcp_socket_lifetime;
3298                 }
3299                 
3300                 if (!fr_event_insert(el, fun, listener, &when, &sock->ev)) {
3301                         rad_panic("Failed to insert event");
3302                 }
3303
3304                 return;
3305         }
3306
3307         listener->print(listener, buffer, sizeof(buffer));
3308         
3309         DEBUG("Reached idle timeout on socket %s", buffer);
3310
3311         listener->status = RAD_LISTEN_STATUS_CLOSED;
3312         event_new_fd(listener);
3313 }
3314 #endif
3315
3316 void event_new_fd(rad_listen_t *this)
3317 {
3318         char buffer[1024];
3319
3320         if (this->status == RAD_LISTEN_STATUS_KNOWN) return;
3321
3322         this->print(this, buffer, sizeof(buffer));
3323
3324         if (this->status == RAD_LISTEN_STATUS_INIT) {
3325                 if (just_started) {
3326                         DEBUG("Listening on %s", buffer);
3327                 } else {
3328                         radlog(L_INFO, " ... adding new socket %s", buffer);
3329                 }
3330
3331 #ifdef WITH_PROXY
3332                 /*
3333                  *      Add it to the list of sockets we can use.
3334                  *      Server sockets (i.e. auth/acct) are never
3335                  *      added to the packet list.
3336                  */
3337                 if (this->type == RAD_LISTEN_PROXY) {
3338                         listen_socket_t *sock = this->data;
3339
3340                         PTHREAD_MUTEX_LOCK(&proxy_mutex);
3341                         if (!fr_packet_list_socket_add(proxy_list, this->fd,
3342                                                        sock->proto,
3343                                                        &sock->other_ipaddr, sock->other_port,
3344                                                        this)) {
3345                                 radlog(L_ERR, "Fatal error adding socket: %s",
3346                                        fr_strerror());
3347                                 exit(1);
3348
3349                         }
3350
3351                         if (sock->home) {
3352                                 sock->home->num_connections++;
3353                                 
3354                                 /*
3355                                  *      If necessary, add it to the list of
3356                                  *      new proxy listeners.
3357                                  */
3358                                 if (sock->home->lifetime || sock->home->idle_timeout) {
3359                                         this->next = proxy_listener_list;
3360                                         proxy_listener_list = this;
3361                                 }
3362                         }
3363                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3364
3365                         /*
3366                          *      Tell the main thread that we've added
3367                          *      a proxy listener, but only if we need
3368                          *      to update the event list.  Do this
3369                          *      with the mutex unlocked, to reduce
3370                          *      contention.
3371                          */
3372                         if (sock->home) {
3373                                 if (sock->home->lifetime || sock->home->idle_timeout) {
3374                                         radius_signal_self(RADIUS_SIGNAL_SELF_NEW_FD);
3375                                 }
3376                         }
3377                 }
3378 #endif          
3379
3380 #ifdef WITH_DETAIL
3381                 /*
3382                  *      Detail files are always known, and aren't
3383                  *      put into the socket event loop.
3384                  */
3385                 if (this->type == RAD_LISTEN_DETAIL) {
3386                         this->status = RAD_LISTEN_STATUS_KNOWN;
3387                         
3388                         /*
3389                          *      Set up the first poll interval.
3390                          */
3391                         event_poll_detail(this);
3392                         return;
3393                 }
3394 #endif
3395
3396                 FD_MUTEX_LOCK(&fd_mutex);
3397                 if (!fr_event_fd_insert(el, 0, this->fd,
3398                                         event_socket_handler, this)) {
3399                         radlog(L_ERR, "Failed remembering handle for proxy socket!");
3400                         exit(1);
3401                 }
3402                 FD_MUTEX_UNLOCK(&fd_mutex);
3403                 
3404                 this->status = RAD_LISTEN_STATUS_KNOWN;
3405                 return;
3406         }
3407
3408         /*
3409          *      Something went wrong with the socket: make it harmless.
3410          */
3411         if (this->status == RAD_LISTEN_STATUS_REMOVE_FD) {
3412                 int devnull;
3413
3414                 /*
3415                  *      Remove it from the list of live FD's.
3416                  */
3417                 FD_MUTEX_LOCK(&fd_mutex);
3418                 fr_event_fd_delete(el, 0, this->fd);
3419                 FD_MUTEX_UNLOCK(&fd_mutex);
3420
3421 #ifdef WITH_PROXY
3422                 if (this->type != RAD_LISTEN_PROXY)
3423 #endif
3424                 {
3425                         if (this->count != 0) {
3426                                 fr_packet_list_walk(pl, this,
3427                                                     remove_all_requests);
3428                         }
3429
3430                         if (this->count == 0) {
3431                                 this->status = RAD_LISTEN_STATUS_FINISH;
3432                                 goto finish;
3433                         }
3434                 }               
3435 #ifdef WITH_PROXY
3436                 else {
3437                         int count = this->count;
3438
3439                         /*
3440                          *      Duplicate code
3441                          */
3442                         PTHREAD_MUTEX_LOCK(&proxy_mutex);
3443                         if (!fr_packet_list_socket_freeze(proxy_list,
3444                                                           this->fd)) {
3445                                 radlog(L_ERR, "Fatal error freezing socket: %s",
3446                                        fr_strerror());
3447                                 exit(1);
3448                         }
3449
3450                         /*
3451                          *      Doing this with the proxy mutex held
3452                          *      is a Bad Thing.  We should move to
3453                          *      finer-grained mutexes.
3454                          */
3455                         count = this->count;
3456                         if (count > 0) {
3457                                 fr_packet_list_walk(proxy_list, this,
3458                                                     remove_all_proxied_requests);
3459                         }
3460                         count = this->count; /* protected by mutex */
3461                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3462
3463                         if (count == 0) {
3464                                 this->status = RAD_LISTEN_STATUS_FINISH;
3465                                 goto finish;
3466                         }
3467                 }
3468 #endif
3469
3470                 /*
3471                  *      Re-open the socket, pointing it to /dev/null.
3472                  *      This means that all writes proceed without
3473                  *      blocking, and all reads return "no data".
3474                  *
3475                  *      This leaves the socket active, so any child
3476                  *      threads won't go insane.  But it means that
3477                  *      they cannot send or receive any packets.
3478                  *
3479                  *      This is EXTRA work in the normal case, when
3480                  *      sockets are closed without error.  But it lets
3481                  *      us have one simple processing method for all
3482                  *      sockets.
3483                  */
3484                 devnull = open("/dev/null", O_RDWR);
3485                 if (devnull < 0) {
3486                         radlog(L_ERR, "FATAL failure opening /dev/null: %s",
3487                                strerror(errno));
3488                         exit(1);
3489                 }
3490                 if (dup2(devnull, this->fd) < 0) {
3491                         radlog(L_ERR, "FATAL failure closing socket: %s",
3492                                strerror(errno));
3493                         exit(1);
3494                 }
3495                 close(devnull);
3496
3497                 this->status = RAD_LISTEN_STATUS_CLOSED;
3498
3499                 /*
3500                  *      Fall through to the next section.
3501                  */
3502         }
3503
3504         /*
3505          *      Called ONLY from the main thread.  On the following
3506          *      conditions:
3507          *
3508          *      idle timeout
3509          *      max lifetime
3510          *
3511          *      (and falling through from "forcibly close FD" above)
3512          *      client closed connection on us
3513          *      client sent us a bad packet.
3514          */
3515         if (this->status == RAD_LISTEN_STATUS_CLOSED) {
3516                 int count = this->count;
3517                 rad_assert(this->type != RAD_LISTEN_DETAIL);
3518
3519 #ifdef WITH_PROXY
3520                 /*
3521                  *      Remove it from the list of active sockets, so
3522                  *      that it isn't used when proxying new packets.
3523                  */
3524                 if (this->type == RAD_LISTEN_PROXY) {
3525                         PTHREAD_MUTEX_LOCK(&proxy_mutex);
3526                         if (!fr_packet_list_socket_freeze(proxy_list,
3527                                                           this->fd)) {
3528                                 radlog(L_ERR, "Fatal error freezing socket: %s",
3529                                        fr_strerror());
3530                                 exit(1);
3531                         }
3532                         count = this->count; /* protected by mutex */
3533                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3534                 }
3535 #endif
3536
3537                 /*
3538                  *      Requests are still using the socket.  Wait for
3539                  *      them to finish.
3540                  */
3541                 if (count != 0) {
3542                         struct timeval when;
3543                         listen_socket_t *sock = this->data;
3544
3545                         /*
3546                          *      Try again to clean up the socket in 30
3547                          *      seconds.
3548                          */
3549                         gettimeofday(&when, NULL);
3550                         when.tv_sec += 30;
3551                         
3552                         if (!fr_event_insert(el,
3553                                              (fr_event_callback_t) event_new_fd,
3554                                              this, &when, &sock->ev)) {
3555                                 rad_panic("Failed to insert event");
3556                         }
3557                        
3558                         return;
3559                 }
3560
3561                 /*
3562                  *      No one is using this socket: we can delete it
3563                  *      immediately.
3564                  */
3565                 this->status = RAD_LISTEN_STATUS_FINISH;
3566         }
3567         
3568 finish:
3569         if (this->status == RAD_LISTEN_STATUS_FINISH) {
3570                 listen_socket_t *sock = this->data;
3571
3572                 rad_assert(this->count == 0);
3573                 radlog(L_INFO, " ... closing socket %s", buffer);
3574
3575                 /*
3576                  *      Remove it from the list of live FD's.  Note
3577                  *      that it MAY also have been removed above.  We
3578                  *      do it again here, to catch the case of sockets
3579                  *      closing on idle timeout, or max
3580                  *      lifetime... AFTER all requests have finished
3581                  *      using it.
3582                  */
3583                 FD_MUTEX_LOCK(&fd_mutex);
3584                 fr_event_fd_delete(el, 0, this->fd);
3585                 FD_MUTEX_UNLOCK(&fd_mutex);
3586                 
3587 #ifdef WITH_PROXY
3588                 /*
3589                  *      Remove it from the list of sockets to be used
3590                  *      when proxying.
3591                  */
3592                 if (this->type == RAD_LISTEN_PROXY) {
3593                         PTHREAD_MUTEX_LOCK(&proxy_mutex);
3594                         if (!fr_packet_list_socket_remove(proxy_list,
3595                                                           this->fd, NULL)) {
3596                                 radlog(L_ERR, "Fatal error removing socket: %s",
3597                                        fr_strerror());
3598                                 exit(1);
3599                         }
3600                         if (sock->home) sock->home->num_connections--;
3601                         PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3602                 }
3603 #endif
3604
3605                 /*
3606                  *      Remove any pending cleanups.
3607                  */
3608                 if (sock->ev) fr_event_delete(el, &sock->ev);
3609
3610                 /*
3611                  *      And finally, close the socket.
3612                  */
3613                 listen_free(&this);
3614         }
3615 }
3616
3617 static void handle_signal_self(int flag)
3618 {
3619         if ((flag & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
3620                 if ((flag & RADIUS_SIGNAL_SELF_EXIT) != 0) {
3621                         radlog(L_INFO, "Received TERM signal");
3622                         fr_event_loop_exit(el, 1);
3623                 } else {
3624                         fr_event_loop_exit(el, 2);
3625                 }
3626
3627                 return;
3628         } /* else exit/term flags weren't set */
3629
3630         /*
3631          *      Tell the even loop to stop processing.
3632          */
3633         if ((flag & RADIUS_SIGNAL_SELF_HUP) != 0) {
3634                 time_t when;
3635                 static time_t last_hup = 0;
3636
3637                 radlog(L_INFO, "Received HUP signal.");
3638
3639                 when = time(NULL);
3640                 if ((int) (when - last_hup) < 5) {
3641                         radlog(L_INFO, "Ignoring HUP (less than 5s since last one)");
3642                         return;
3643                 }
3644                 last_hup = when;
3645
3646                 fr_event_loop_exit(el, 0x80);
3647         }
3648
3649 #ifdef WITH_DETAIL
3650         if ((flag & RADIUS_SIGNAL_SELF_DETAIL) != 0) {
3651                 rad_listen_t *this;
3652                 
3653                 /*
3654                  *      FIXME: O(N) loops suck.
3655                  */
3656                 for (this = mainconfig.listen;
3657                      this != NULL;
3658                      this = this->next) {
3659                         if (this->type != RAD_LISTEN_DETAIL) continue;
3660
3661                         /*
3662                          *      This one didn't send the signal, skip
3663                          *      it.
3664                          */
3665                         if (!this->decode(this, NULL)) continue;
3666
3667                         /*
3668                          *      Go service the interrupt.
3669                          */
3670                         event_poll_detail(this);
3671                 }
3672         }
3673 #endif
3674
3675 #ifdef WITH_PROXY
3676         /*
3677          *      Add event handlers for idle timeouts && maximum lifetime.
3678          */
3679         if ((flag & RADIUS_SIGNAL_SELF_NEW_FD) != 0) {
3680                 struct timeval when;
3681                 void *fun = NULL;
3682
3683                 if (!fr_event_now(el, &now)) gettimeofday(&now, NULL);
3684
3685                 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3686
3687                 while (proxy_listener_list) {
3688                         rad_listen_t *this = proxy_listener_list;
3689                         listen_socket_t *sock = this->data;
3690
3691                         proxy_listener_list = this->next;
3692                         this->next = NULL;
3693
3694                         if (!sock->home) continue; /* skip UDP sockets */
3695
3696                         when = now;
3697
3698                         if (!sock->home->idle_timeout) {
3699                                 rad_assert(sock->home->lifetime != 0);
3700
3701                                 when.tv_sec += sock->home->lifetime;
3702                                 fun = tcp_socket_lifetime;
3703                         } else {
3704                                 rad_assert(sock->home->idle_timeout != 0);
3705
3706                                 when.tv_sec += sock->home->idle_timeout;
3707                                 fun = tcp_socket_idle_timeout;
3708                         }
3709
3710                         if (!fr_event_insert(el, fun, this, &when,
3711                                              &(sock->ev))) {
3712                                 rad_panic("Failed to insert event");
3713                         }
3714                 }
3715
3716                 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3717         }
3718 #endif
3719 }
3720
3721 #ifndef WITH_SELF_PIPE
3722 void radius_signal_self(int flag)
3723 {
3724         handle_signal_self(flag);
3725 }
3726 #else
3727 /*
3728  *      Inform ourselves that we received a signal.
3729  */
3730 void radius_signal_self(int flag)
3731 {
3732         ssize_t rcode;
3733         uint8_t buffer[16];
3734
3735         /*
3736          *      The read MUST be non-blocking for this to work.
3737          */
3738         rcode = read(self_pipe[0], buffer, sizeof(buffer));
3739         if (rcode > 0) {
3740                 ssize_t i;
3741
3742                 for (i = 0; i < rcode; i++) {
3743                         buffer[0] |= buffer[i];
3744                 }
3745         } else {
3746                 buffer[0] = 0;
3747         }
3748
3749         buffer[0] |= flag;
3750
3751         write(self_pipe[1], buffer, 1);
3752 }
3753
3754
3755 static void event_signal_handler(UNUSED fr_event_list_t *xel,
3756                                  UNUSED int fd, UNUSED void *ctx)
3757 {
3758         ssize_t i, rcode;
3759         uint8_t buffer[32];
3760
3761         rcode = read(self_pipe[0], buffer, sizeof(buffer));
3762         if (rcode <= 0) return;
3763
3764         /*
3765          *      Merge pending signals.
3766          */
3767         for (i = 0; i < rcode; i++) {
3768                 buffer[0] |= buffer[i];
3769         }
3770
3771         handle_signal_self(buffer[0]);
3772 }
3773 #endif
3774
3775
3776 static void event_socket_handler(fr_event_list_t *xel, UNUSED int fd,
3777                                  void *ctx)
3778 {
3779         rad_listen_t *listener = ctx;
3780         RAD_REQUEST_FUNP fun;
3781         REQUEST *request;
3782
3783         rad_assert(xel == el);
3784
3785         xel = xel;
3786
3787         if (listener->fd < 0) rad_panic("Socket was closed on us!");
3788         
3789         if (!listener->recv(listener, &fun, &request)) return;
3790
3791         if (!thread_pool_addrequest(request, fun)) {
3792                 request->child_state = REQUEST_DONE;
3793         }
3794 }
3795
3796 typedef struct listen_detail_t {
3797         fr_event_t      *ev;
3798 } listen_detail_t;
3799
3800 /*
3801  *      This function is called periodically to see if this detail
3802  *      file is available for reading.
3803  */
3804 static void event_poll_detail(void *ctx)
3805 {
3806         int rcode, delay;
3807         RAD_REQUEST_FUNP fun;
3808         REQUEST *request;
3809         rad_listen_t *this = ctx;
3810         struct timeval when;
3811         listen_detail_t *detail = this->data;
3812
3813         rad_assert(this->type == RAD_LISTEN_DETAIL);
3814
3815         /*
3816          *      Try to read something.
3817          *
3818          *      FIXME: This does poll AND receive.
3819          */
3820         rcode = this->recv(this, &fun, &request);
3821         if (rcode != 0) {
3822                 rad_assert(fun != NULL);
3823                 rad_assert(request != NULL);
3824                 
3825                 if (!thread_pool_addrequest(request, fun)) {
3826                         request->child_state = REQUEST_DONE;
3827                 }
3828         }
3829
3830         if (!fr_event_now(el, &now)) gettimeofday(&now, NULL);
3831         when = now;
3832
3833         /*
3834          *      Backdoor API to get the delay until the next poll
3835          *      time.
3836          */
3837         delay = this->encode(this, NULL);
3838         tv_add(&when, delay);
3839
3840         if (!fr_event_insert(el, event_poll_detail, this,
3841                              &when, &detail->ev)) {
3842                 radlog(L_ERR, "Failed creating handler");
3843                 exit(1);
3844         }
3845 }
3846
3847
3848 static void event_status(struct timeval *wake)
3849 {
3850 #if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)
3851         int argval;
3852 #endif
3853
3854         if (debug_flag == 0) {
3855                 if (just_started) {
3856                         radlog(L_INFO, "Ready to process requests.");
3857                         just_started = FALSE;
3858                 }
3859                 return;
3860         }
3861
3862         if (!wake) {
3863                 radlog(L_INFO, "Ready to process requests.");
3864
3865         } else if ((wake->tv_sec != 0) ||
3866                    (wake->tv_usec >= 100000)) {
3867                 DEBUG("Waking up in %d.%01u seconds.",
3868                       (int) wake->tv_sec, (unsigned int) wake->tv_usec / 100000);
3869         }
3870
3871
3872         /*
3873          *      FIXME: Put this somewhere else, where it isn't called
3874          *      all of the time...
3875          */
3876
3877 #if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)
3878         /*
3879          *      If there are no child threads, then there may
3880          *      be child processes.  In that case, wait for
3881          *      their exit status, and throw that exit status
3882          *      away.  This helps get rid of zxombie children.
3883          */
3884         while (waitpid(-1, &argval, WNOHANG) > 0) {
3885                 /* do nothing */
3886         }
3887 #endif
3888
3889 }
3890
3891 /*
3892  *      Externally-visibly functions.
3893  */
3894 int radius_event_init(CONF_SECTION *cs, int spawn_flag)
3895 {
3896         rad_listen_t *head = NULL;
3897
3898         if (el) return 0;
3899
3900         time(&fr_start_time);
3901
3902         el = fr_event_list_create(event_status);
3903         if (!el) return 0;
3904
3905         pl = fr_packet_list_create(0);
3906         if (!pl) return 0;      /* leak el */
3907
3908         request_num_counter = 0;
3909
3910 #ifdef WITH_PROXY
3911         if (mainconfig.proxy_requests) {
3912                 /*
3913                  *      Create the tree for managing proxied requests and
3914                  *      responses.
3915                  */
3916                 proxy_list = fr_packet_list_create(1);
3917                 if (!proxy_list) return 0;
3918
3919 #ifdef HAVE_PTHREAD_H
3920                 if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
3921                         radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
3922                                strerror(errno));
3923                         exit(1);
3924                 }
3925 #endif
3926         }
3927 #endif
3928
3929         /*
3930          *      Just before we spawn the child threads, force the log
3931          *      subsystem to re-open the log file for every write.
3932          */
3933         if (spawn_flag) force_log_reopen();
3934
3935 #ifdef HAVE_PTHREAD_H
3936 #ifndef __MINGW32__
3937         NO_SUCH_CHILD_PID = (pthread_t ) (0);
3938 #else
3939         NO_SUCH_CHILD_PID = pthread_self(); /* not a child thread */
3940 #endif
3941         /*
3942          *      Initialize the threads ONLY if we're spawning, AND
3943          *      we're running normally.
3944          */
3945         if (spawn_flag && !check_config &&
3946             (thread_pool_init(cs, &spawn_flag) < 0)) {
3947                 exit(1);
3948         }
3949 #endif
3950
3951         /*
3952          *      Move all of the thread calls to this file?
3953          *
3954          *      It may be best for the mutexes to be in this file...
3955          */
3956         have_children = spawn_flag;
3957
3958         if (check_config) {
3959                 DEBUG("%s: #### Skipping IP addresses and Ports ####",
3960                        mainconfig.name);
3961                 return 1;
3962         }
3963
3964 #ifdef WITH_SELF_PIPE
3965         /*
3966          *      Child threads need a pipe to signal us, as do the
3967          *      signal handlers.
3968          */
3969         if (pipe(self_pipe) < 0) {
3970                 radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
3971                        strerror(errno));
3972                 exit(1);
3973         }
3974         if (fcntl(self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
3975                 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
3976                        strerror(errno));
3977                 exit(1);
3978         }
3979         if (fcntl(self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
3980                 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
3981                        strerror(errno));
3982                 exit(1);
3983         }
3984
3985         if (!fr_event_fd_insert(el, 0, self_pipe[0],
3986                                   event_signal_handler, el)) {
3987                 radlog(L_ERR, "Failed creating handler for signals");
3988                 exit(1);
3989         }
3990 #endif  /* WITH_SELF_PIPE */
3991
3992        DEBUG("%s: #### Opening IP addresses and Ports ####",
3993                mainconfig.name);
3994
3995        /*
3996         *       The server temporarily switches to an unprivileged
3997         *       user very early in the bootstrapping process.
3998         *       However, some sockets MAY require privileged access
3999         *       (bind to device, or to port < 1024, or to raw
4000         *       sockets).  Those sockets need to call suid up/down
4001         *       themselves around the functions that need a privileged
4002         *       uid.
4003         */
4004         if (listen_init(cs, &head) < 0) {
4005                 _exit(1);
4006         }
4007         
4008         mainconfig.listen = head;
4009
4010         /*
4011          *      At this point, no one has any business *ever* going
4012          *      back to root uid.
4013          */
4014         fr_suid_down_permanent();
4015
4016         return 1;
4017 }
4018
4019
4020 static int request_hash_cb(UNUSED void *ctx, void *data)
4021 {
4022         REQUEST *request = fr_packet2myptr(REQUEST, packet, data);
4023
4024 #ifdef WITH_PROXY
4025         rad_assert(request->in_proxy_hash == FALSE);
4026 #endif
4027
4028         ev_request_free(&request);
4029
4030         return 0;
4031 }
4032
4033
4034 #ifdef WITH_PROXY
4035 static int proxy_hash_cb(UNUSED void *ctx, void *data)
4036 {
4037         REQUEST *request = fr_packet2myptr(REQUEST, proxy, data);
4038
4039         ev_request_free(&request);
4040
4041         return 0;
4042 }
4043 #endif
4044
4045 void radius_event_free(void)
4046 {
4047         /*
4048          *      FIXME: Stop all threads, or at least check that
4049          *      they're all waiting on the semaphore, and the queues
4050          *      are empty.
4051          */
4052
4053 #ifdef WITH_PROXY
4054         /*
4055          *      There are requests in the proxy hash that aren't
4056          *      referenced from anywhere else.  Remove them first.
4057          */
4058         if (proxy_list) {
4059                 fr_packet_list_walk(proxy_list, NULL, proxy_hash_cb);
4060                 fr_packet_list_free(proxy_list);
4061                 proxy_list = NULL;
4062         }
4063 #endif
4064
4065         fr_packet_list_walk(pl, NULL, request_hash_cb);
4066
4067         fr_packet_list_free(pl);
4068         pl = NULL;
4069
4070         fr_event_list_free(el);
4071 }
4072
4073 int radius_event_process(void)
4074 {
4075         if (!el) return 0;
4076
4077         return fr_event_loop(el);
4078 }
4079
4080 void radius_handle_request(REQUEST *request, RAD_REQUEST_FUNP fun)
4081 {
4082         request->options = RAD_REQUEST_OPTION_DEBUG2;
4083
4084         if (request_pre_handler(request)) {
4085                 rad_assert(fun != NULL);
4086                 rad_assert(request != NULL);
4087                 
4088                 if (request->server) RDEBUG("server %s {",
4089                                             request->server != NULL ?
4090                                             request->server : ""); 
4091                 fun(request);
4092
4093                 if (request->server) RDEBUG("} # server %s",
4094                                              request->server != NULL ?
4095                                             request->server : "");
4096
4097                 request_post_handler(request);
4098         }
4099
4100         DEBUG2("Going to the next request");
4101         return;
4102 }