3 * @brief Handle requests
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Copyright 2011 The FreeRADIUS server project
22 * Copyright 2011 Alan DeKok <aland@deployingradius.com>
25 #include <freeradius-devel/ident.h>
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/process.h>
30 #include <freeradius-devel/event.h>
31 #include <freeradius-devel/packet.h>
32 #include <freeradius-devel/modules.h>
34 #include <freeradius-devel/rad_assert.h>
37 #include <freeradius-devel/detail.h>
43 #ifdef HAVE_SYS_WAIT_H
44 # include <sys/wait.h>
49 extern pid_t radius_pid;
50 extern int check_config;
51 extern char *debug_condition;
53 static int spawn_flag = 0;
54 static int just_started = TRUE;
56 static fr_packet_list_t *pl = NULL;
57 static fr_event_list_t *el = NULL;
59 static const char *action_codes[] = {
71 #ifdef DEBUG_STATE_MACHINE
72 #define TRACE_STATE_MACHINE if (debug_flag) printf("(%u) ********\tSTATE %s action %s live M%u C%u\t********\n", request->number, __FUNCTION__, action_codes[action], request->master_state, request->child_state)
74 #define TRACE_STATE_MACHINE {}
78 * Declare a state in the state machine.
81 #define STATE_MACHINE_DECL(_x) static void _x(REQUEST *request, int action)
83 #define STATE_MACHINE_TIMER(_x) request->timer_action = _x; \
84 fr_event_insert(el, request_timer, request, \
90 * @section request_timeline
92 * Time sequence of a request
95 * RQ-----------------P=============================Y-J-C
96 * ::::::::::::::::::::::::::::::::::::::::::::::::::::::::M
99 * - R: received. Duplicate detection is done, and request is
102 * - Q: Request is placed onto a queue for child threads to pick up.
103 * If there are no child threads, the request goes immediately
106 * - P: Processing the request through the modules.
108 * - Y: Reply is ready. Rejects MAY be delayed here. All other
109 * replies are sent immediately.
111 * - J: Reject is sent "reject_delay" after the reply is ready.
113 * - C: For Access-Requests, After "cleanup_delay", the request is
114 * deleted. Accounting-Request packets go directly from Y to C.
116 * - M: Max request time. If the request hits this timer, it is
119 * Other considerations include duplicate and conflicting
120 * packets. When a dupicate packet is received, it is ignored
121 * until we've reached Y, as no response is ready. If the reply
122 * is a reject, duplicates are ignored until J, when we're ready
123 * to send the reply. In between the reply being sent (Y or J),
124 * and C, the server responds to duplicates by sending the cached
127 * Conflicting packets are sent in 2 situations.
129 * The first is in between R and Y. In that case, we consider
130 * it as a hint that we're taking too long, and the NAS has given
131 * up on the request. We then behave just as if the M timer was
132 * reached, and we discard the current request. This allows us
133 * to process the new one.
135 * The second case is when we're at Y, but we haven't yet
136 * finished processing the request. This is a race condition in
137 * the threading code (avoiding locks is faster). It means that
138 * a thread has actually encoded and sent the reply, and that the
139 * NAS has responded with a new packet. The server can then
140 * safely mark the current request as "OK to delete", and behaves
141 * just as if the M timer was reached. This usually happens only
142 * in high-load situations.
144 * Duplicate packets are sent when the NAS thinks we're taking
145 * too long, and wants a reply. From R-Y, duplicates are
146 * ignored. From Y-J (for Access-Rejects), duplicates are also
147 * ignored. From Y-C, duplicates get a duplicate reply. *And*,
148 * they cause the "cleanup_delay" time to be extended. This
149 * extension means that we're more likely to send a duplicate
150 * reply (if we have one), or to suppress processing the packet
151 * twice if we didn't reply to it.
153 * All functions in this file should be thread-safe, and should
154 * assume thet the REQUEST structure is being accessed
155 * simultaneously by the main thread, and by the child worker
156 * threads. This means that timers, etc. cannot be updated in
159 * Instead, the master thread periodically calls request->process
160 * with action TIMER. It's up to the individual functions to
161 * determine how to handle that. They need to check if they're
162 * being called from a child thread or the master, and then do
163 * different things based on that.
168 static fr_packet_list_t *proxy_list = NULL;
171 #ifdef HAVE_PTHREAD_H
173 static pthread_mutex_t proxy_mutex;
174 static rad_listen_t *proxy_listener_list = NULL;
175 static int proxy_no_new_sockets = FALSE;
178 #define PTHREAD_MUTEX_LOCK if (spawn_flag) pthread_mutex_lock
179 #define PTHREAD_MUTEX_UNLOCK if (spawn_flag) pthread_mutex_unlock
181 static pthread_t NO_SUCH_CHILD_PID;
184 * This is easier than ifdef's throughout the code.
186 #define PTHREAD_MUTEX_LOCK(_x)
187 #define PTHREAD_MUTEX_UNLOCK(_x)
191 * We need mutexes around the event FD list *only* in certain
194 #if defined (HAVE_PTHREAD_H) && (defined(WITH_PROXY) || defined(WITH_TCP))
195 static pthread_mutex_t fd_mutex;
196 #define FD_MUTEX_LOCK if (spawn_flag) pthread_mutex_lock
197 #define FD_MUTEX_UNLOCK if (spawn_flag) pthread_mutex_unlock
200 * This is easier than ifdef's throughout the code.
202 #define FD_MUTEX_LOCK(_x)
203 #define FD_MUTEX_UNLOCK(_x)
206 static int request_num_counter = 0;
208 static int request_will_proxy(REQUEST *request);
209 static int request_proxy(REQUEST *request, int retransmit);
210 STATE_MACHINE_DECL(proxy_wait_for_reply);
211 STATE_MACHINE_DECL(proxy_running);
212 static int process_proxy_reply(REQUEST *request);
213 static void remove_from_proxy_hash(REQUEST *request);
214 static int insert_into_proxy_hash(REQUEST *request);
217 STATE_MACHINE_DECL(request_common);
219 #if defined(HAVE_PTHREAD_H) && !defined (NDEBUG)
220 static int we_are_master(void)
223 (pthread_equal(pthread_self(), NO_SUCH_CHILD_PID) == 0)) {
229 #define ASSERT_MASTER if (!we_are_master()) rad_panic("We are not master")
232 #define we_are_master(_x) (1)
233 #define ASSERT_MASTER
236 STATE_MACHINE_DECL(request_reject_delay);
237 STATE_MACHINE_DECL(request_cleanup_delay);
238 STATE_MACHINE_DECL(request_running);
240 static void request_coa_timer(REQUEST *request);
241 static void request_coa_originate(REQUEST *request);
242 STATE_MACHINE_DECL(request_coa_process);
243 static void request_coa_separate(REQUEST *coa);
247 #define USEC (1000000)
249 #define INSERT_EVENT(_function, _ctx) if (!fr_event_insert(el, _function, _ctx, &((_ctx)->when), &((_ctx)->ev))) { _rad_panic(__FILE__, __LINE__, "Failed to insert event"); }
251 static void NEVER_RETURNS _rad_panic(const char *file, unsigned int line,
254 radlog(L_ERR, "[%s:%d] %s", file, line, msg);
258 #define rad_panic(x) _rad_panic(__FILE__, __LINE__, x)
260 static void tv_add(struct timeval *tv, int usec_delay)
262 if (usec_delay >= USEC) {
263 tv->tv_sec += usec_delay / USEC;
266 tv->tv_usec += usec_delay;
268 if (tv->tv_usec >= USEC) {
269 tv->tv_sec += tv->tv_usec / USEC;
275 * In daemon mode, AND this request has debug flags set.
277 #define DEBUG_PACKET if (!debug_flag && request->options && request->radlog) debug_packet
279 static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
283 const char *received, *from;
284 const fr_ipaddr_t *ip;
289 rad_assert(request->radlog != NULL);
291 if (direction == 0) {
292 received = "Received";
293 from = "from"; /* what else? */
294 ip = &packet->src_ipaddr;
295 port = packet->src_port;
298 received = "Sending";
299 from = "to"; /* hah! */
300 ip = &packet->dst_ipaddr;
301 port = packet->dst_port;
305 * Client-specific debugging re-prints the input
306 * packet into the client log.
308 * This really belongs in a utility library
310 if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
311 RDEBUG("%s %s packet %s host %s port %d, id=%d, length=%d",
312 received, fr_packet_codes[packet->code], from,
313 inet_ntop(ip->af, &ip->ipaddr, buffer, sizeof(buffer)),
314 port, packet->id, packet->data_len);
316 RDEBUG("%s packet %s host %s port %d code=%d, id=%d, length=%d",
318 inet_ntop(ip->af, &ip->ipaddr, buffer, sizeof(buffer)),
320 packet->code, packet->id, packet->data_len);
323 for (vp = packet->vps; vp != NULL; vp = vp->next) {
324 vp_prints(buffer, sizeof(buffer), vp);
325 request->radlog(L_DBG, 0, request, "\t%s", buffer);
330 /***********************************************************************
332 * Start of RADIUS server state machine.
334 ***********************************************************************/
337 * Callback for ALL timer events related to the request.
339 static void request_timer(void *ctx)
341 REQUEST *request = ctx;
342 int action = request->timer_action;
346 request->process(request, action);
349 #define USEC (1000000)
352 * Only ever called from the master thread.
354 STATE_MACHINE_DECL(request_done)
356 struct timeval now, when;
362 * CoA requests can be cleaned up in the child thread,
363 * but ONLY if they aren't tied into anything.
365 if (request->parent && (request->parent->coa == request)) {
366 rad_assert(request->child_state == REQUEST_DONE);
367 rad_assert(!request->in_request_hash);
368 rad_assert(!request->in_proxy_hash);
369 rad_assert(action == FR_ACTION_DONE);
370 rad_assert(request->packet == NULL);
371 rad_assert(request->ev == NULL);
379 * Mark ourselves as handling the request.
381 request->process = request_done;
382 request->master_state = REQUEST_STOP_PROCESSING;
386 * Move the CoA request to its own handler.
388 if (request->coa) request_coa_separate(request->coa);
391 * If we're the CoA request, make the parent forget about
394 if (request->parent && (request->parent->coa == request)) {
395 request->parent->coa = NULL;
401 * It doesn't hurt to send duplicate replies. All other
402 * signals are ignored, as the request will be cleaned up
407 if (request->reply->code != 0) {
408 request->listener->send(request->listener, request);
414 * This is only called from the master thread
415 * when there is a child thread processing the
418 case FR_ACTION_CONFLICTING:
419 if (request->child_state == REQUEST_DONE) break;
422 * If there's a reply packet, then we presume
423 * that the child has sent the reply, and we get
424 * pinged here before the child has a chance to
427 if (request->reply->data) break;
429 radlog_request(L_ERR, 0, request,
430 "Received conflicting packet from "
431 "client %s port %d - ID: %d due to "
432 "unfinished request. Giving up on old request.",
433 request->client->shortname,
434 request->packet->src_port, request->packet->id);
438 * Called only when there's an error remembering
439 * the packet, or when the socket gets closed from
443 #ifdef HAVE_PTHREAD_H
445 * If we have child threads and we're NOT the
446 * thread handling the request, don't do anything.
449 !pthread_equal(pthread_self(), request->child_pid)) {
453 #ifdef DEBUG_STATE_MACHINE
454 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
456 request->child_state = REQUEST_DONE;
460 * Called when the child is taking too long to
461 * finish. We've already marked it "please
462 * stop", so we don't complain any more.
464 case FR_ACTION_TIMER:
469 * Child is still alive, and we're receiving more
470 * packets from the home server.
472 case FR_ACTION_PROXY_REPLY:
473 request_common(request, action);
478 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
483 * Remove it from the request hash.
485 if (request->in_request_hash) {
486 fr_packet_list_yank(pl, request->packet);
487 request->in_request_hash = FALSE;
489 request_stats_final(request);
492 request->listener->count--;
498 * Wait for the proxy ID to expire. This allows us to
499 * avoid re-use of proxy IDs for a while.
501 if (request->in_proxy_hash) {
502 rad_assert(request->proxy != NULL);
504 fr_event_now(el, &now);
505 when = request->proxy->timestamp;
508 if (((request->proxy->code == PW_COA_REQUEST) ||
509 (request->proxy->code == PW_DISCONNECT_REQUEST)) &&
510 (request->packet->code != request->proxy->code)) {
511 when.tv_sec += request->home_server->coa_mrd;
514 when.tv_sec += request->home_server->response_window;
517 * We haven't received all responses, AND there's still
518 * time to wait. Do so.
520 if ((request->num_proxied_requests > request->num_proxied_responses) &&
522 (request->home_server->proto != IPPROTO_TCP) &&
524 timercmp(&now, &when, <)) {
525 RDEBUG("Waiting for more responses from the home server");
532 remove_from_proxy_hash(request);
536 if (request->child_state != REQUEST_DONE) {
538 #ifdef HAVE_PTHREAD_H
542 rad_assert("Internal sanity check failed");
546 gettimeofday(&now, NULL);
551 #ifdef HAVE_PTHREAD_H
553 (pthread_equal(request->child_pid, NO_SUCH_CHILD_PID) == 0)) {
554 RDEBUG("Waiting for child thread to stop");
559 tv_add(&when, request->delay);
560 request->delay += request->delay >> 1;
561 if (request->delay > (10 * USEC)) request->delay = 10 * USEC;
563 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
567 #ifdef HAVE_PTHREAD_H
568 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
571 if (request->packet) {
572 RDEBUG2("Cleaning up request packet ID %d with timestamp +%d",
574 (unsigned int) (request->timestamp - fr_start_time));
575 } /* else don't print anything */
577 if (request->ev) fr_event_delete(el, &request->ev);
579 request_free(&request);
583 * Function to do all time-related events.
585 static void request_process_timer(REQUEST *request)
587 struct timeval now, when;
588 rad_assert(request->magic == REQUEST_MAGIC);
589 #ifdef DEBUG_STATE_MACHINE
590 int action = FR_ACTION_TIMER;
598 * If we originated a CoA request, divorce it from the
599 * parent. Then, set up the timers so that we can clean
600 * it up as appropriate.
602 if (request->coa) request_coa_separate(request->coa);
605 * Check request stuff ONLY if we're running the request.
607 if (!request->proxy || (request->packet->code == request->proxy->code))
610 rad_assert(request->listener != NULL);
613 * The socket was closed. Tell the request that
614 * there is no point in continuing.
616 if (request->listener->status != RAD_LISTEN_STATUS_KNOWN) {
617 DEBUG("WARNING: Socket was closed while processing request %u: Stopping it.", request->number);
622 gettimeofday(&now, NULL);
625 * A child thread is still working on the request,
626 * OR it was proxied, and there was no response.
628 if ((request->child_state != REQUEST_DONE) &&
629 (request->master_state != REQUEST_STOP_PROCESSING)) {
630 when = request->packet->timestamp;
631 when.tv_sec += request->root->max_request_time;
634 * Taking too long: tell it to die.
636 if (timercmp(&now, &when, >=)) {
637 #ifdef HAVE_PTHREAD_H
639 * If there's a child thread processing it,
643 (pthread_equal(request->child_pid, NO_SUCH_CHILD_PID) == 0)) {
644 radlog(L_ERR, "WARNING: Unresponsive child for request %u, in component %s module %s",
646 request->component ? request->component : "<server core>",
647 request->module ? request->module : "<server core>");
648 exec_trigger(request, NULL, "server.thread.unresponsive");
653 * Tell the request to stop it.
656 } /* else we're not at max_request_time */
659 if ((request->master_state != REQUEST_STOP_PROCESSING) &&
661 (request->process == request_running)) {
662 #ifdef DEBUG_STATE_MACHINE
663 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_proxied");
665 request->process = proxy_wait_for_reply;
670 * Wake up again in the future, to check for
674 tv_add(&when, request->delay);
675 request->delay += request->delay >> 1;
677 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
681 #ifdef WITH_ACCOUNTING
682 if (request->reply->code == PW_ACCOUNTING_RESPONSE) {
688 if (!request->proxy || (request->packet->code == request->proxy->code))
691 if ((request->reply->code == PW_AUTHENTICATION_REJECT) &&
692 (request->root->reject_delay)) {
693 when = request->reply->timestamp;
694 when.tv_sec += request->root->reject_delay;
697 * Set timer for when we need to send it.
699 if (timercmp(&when, &now, >)) {
700 #ifdef DEBUG_STATE_MACHINE
701 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_reject_delay");
703 request->process = request_reject_delay;
705 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
709 if (request->process == request_reject_delay) {
711 * Assume we're at (or near) the reject
714 request->reply->timestamp = now;
716 RDEBUG2("Sending delayed reject");
717 DEBUG_PACKET(request, request->reply, 1);
718 request->process = request_cleanup_delay;
719 request->listener->send(request->listener, request);
724 * The cleanup_delay is zero for accounting packets, and
725 * enforced for all other packets. We do the
726 * cleanup_delay even if we don't respond to the NAS, so
727 * that any retransmit is *not* processed as a new packet.
729 if ((request->packet->code != PW_ACCOUNTING_REQUEST) &&
730 (request->root->cleanup_delay)) {
731 when = request->reply->timestamp;
732 request->delay = request->root->cleanup_delay;
733 when.tv_sec += request->delay;
736 * Set timer for when we need to clean it up.
738 if (timercmp(&when, &now, >)) {
739 #ifdef DEBUG_STATE_MACHINE
740 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_cleanup_delay");
742 request->process = request_cleanup_delay;
744 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
750 request_done(request, FR_ACTION_DONE);
753 static void request_queue_or_run(UNUSED REQUEST *request,
754 fr_request_process_t process)
757 #ifdef DEBUG_STATE_MACHINE
758 int action = FR_ACTION_TIMER;
764 #ifdef HAVE_PTHREAD_H
765 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
769 * (re) set the initial delay.
771 request->delay = USEC / 3;
772 gettimeofday(&when, NULL);
773 tv_add(&when, request->delay);
774 request->delay += request->delay >> 1;
776 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
779 * Do this here so that fewer other functions need to do
782 if (request->master_state == REQUEST_STOP_PROCESSING) {
783 #ifdef DEBUG_STATE_MACHINE
784 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
786 request_done(request, FR_ACTION_DONE);
790 request->process = process;
792 #ifdef HAVE_PTHREAD_H
794 if (!request_enqueue(request)) {
795 request_done(request, FR_ACTION_DONE);
802 request->process(request, FR_ACTION_RUN);
806 * Requests that care about child process exit
807 * codes have already either called
808 * rad_waitpid(), or they've given up.
815 STATE_MACHINE_DECL(request_common)
826 if ((request->master_state != REQUEST_STOP_PROCESSING) &&
827 request->proxy && !request->proxy_reply) {
829 * TODO: deal with this in a better way?
831 proxy_wait_for_reply(request, action);
835 radlog(L_ERR, "Discarding duplicate request from "
836 "client %s port %d - ID: %u due to unfinished request %u",
837 request->client->shortname,
838 request->packet->src_port,request->packet->id,
842 case FR_ACTION_CONFLICTING:
844 * We're in the master thread, ask the child to
845 * stop processing the request.
847 request_done(request, action);
850 case FR_ACTION_TIMER:
851 request_process_timer(request);
855 case FR_ACTION_PROXY_REPLY:
856 DEBUG2("Reply from home server %s port %d - ID: %d arrived too late for request %u. Try increasing 'retry_delay' or 'max_request_time'",
857 inet_ntop(request->proxy->src_ipaddr.af,
858 &request->proxy->src_ipaddr.ipaddr,
859 buffer, sizeof(buffer)),
860 request->proxy->dst_port, request->proxy->id,
866 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
871 STATE_MACHINE_DECL(request_cleanup_delay)
880 if (request->reply->code != 0) {
881 request->listener->send(request->listener, request);
885 * Double the cleanup_delay to catch retransmits.
887 when = request->reply->timestamp;
888 request->delay += request->delay ;
889 when.tv_sec += request->delay;
891 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
895 case FR_ACTION_PROXY_REPLY:
897 case FR_ACTION_CONFLICTING:
898 case FR_ACTION_TIMER:
899 request_common(request, action);
903 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
908 STATE_MACHINE_DECL(request_reject_delay)
915 radlog(L_ERR, "Discarding duplicate request from "
916 "client %s port %d - ID: %u due to delayed reject %u",
917 request->client->shortname,
918 request->packet->src_port,request->packet->id,
923 case FR_ACTION_PROXY_REPLY:
925 case FR_ACTION_CONFLICTING:
926 case FR_ACTION_TIMER:
927 request_common(request, action);
931 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
937 static int request_pre_handler(REQUEST *request, UNUSED int action)
943 if (request->master_state == REQUEST_STOP_PROCESSING) return 0;
946 * Don't decode the packet if it's an internal "fake"
947 * request. Instead, just return so that the caller can
950 if (request->packet->dst_port == 0) {
951 request->username = pairfind(request->packet->vps,
953 request->password = pairfind(request->packet->vps,
954 PW_USER_PASSWORD, 0);
960 * Put the decoded packet into it's proper place.
962 if (request->proxy_reply != NULL) {
963 rcode = request->proxy_listener->decode(request->proxy_listener, request);
964 DEBUG_PACKET(request, request->proxy_reply, 0);
967 * Pro-actively remove it from the proxy hash.
968 * This is later than in 2.1.x, but it means that
969 * the replies are authenticated before being
970 * removed from the hash.
973 (request->num_proxied_requests <= request->num_proxied_responses)) {
974 remove_from_proxy_hash(request);
979 if (request->packet->vps == NULL) {
980 rcode = request->listener->decode(request->listener, request);
983 if (debug_condition) {
985 const char *my_debug = debug_condition;
988 * Ignore parse errors.
990 radius_evaluate_condition(request, RLM_MODULE_OK, 0,
994 request->options = 2;
995 request->radlog = radlog_request;
1000 DEBUG_PACKET(request, request->packet, 0);
1006 RDEBUG("Dropping packet without response because of error %s", fr_strerror());
1007 request->reply->offset = -2; /* bad authenticator */
1011 if (!request->username) {
1012 request->username = pairfind(request->packet->vps,
1017 if (action == FR_ACTION_PROXY_REPLY) {
1018 return process_proxy_reply(request);
1025 STATE_MACHINE_DECL(request_finish)
1029 TRACE_STATE_MACHINE;
1031 action = action; /* -Wunused */
1033 if (request->master_state == REQUEST_STOP_PROCESSING) return;
1036 * Don't send replies if there are none to send.
1038 if (!request->in_request_hash) return;
1041 * Catch Auth-Type := Reject BEFORE proxying the packet.
1043 if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1044 (request->reply->code == 0)) {
1045 if (((vp = pairfind(request->config_items, PW_AUTH_TYPE, 0)) != NULL) &&
1046 (vp->vp_integer == PW_AUTHTYPE_REJECT)) {
1047 request->reply->code = PW_AUTHENTICATION_REJECT;
1051 * Check if the lack of response is
1054 vp = pairfind(request->config_items,
1055 PW_RESPONSE_PACKET_TYPE, 0);
1057 RDEBUG2("There was no response configured: rejecting request");
1058 request->reply->code = PW_AUTHENTICATION_REJECT;
1060 } else if (vp->vp_integer == 256) {
1061 RDEBUG2("Not responding to request");
1064 request->reply->code = vp->vp_integer;
1070 * Copy Proxy-State from the request to the reply.
1072 vp = paircopy2(request->packet->vps, PW_PROXY_STATE, 0);
1073 if (vp) pairadd(&request->reply->vps, vp);
1076 * Run rejected packets through
1078 * Post-Auth-Type = Reject
1080 if (request->reply->code == PW_AUTHENTICATION_REJECT) {
1081 pairdelete(&request->config_items, PW_POST_AUTH_TYPE, 0);
1082 vp = radius_pairmake(request, &request->config_items,
1083 "Post-Auth-Type", "Reject",
1085 if (vp) rad_postauth(request);
1089 * Send the reply here.
1091 if ((request->reply->code != PW_AUTHENTICATION_REJECT) ||
1092 (request->root->reject_delay == 0)) {
1093 DEBUG_PACKET(request, request->reply, 1);
1094 request->listener->send(request->listener,
1098 gettimeofday(&request->reply->timestamp, NULL);
1101 * Clean up. These are no longer needed.
1103 pairfree(&request->config_items);
1105 pairfree(&request->packet->vps);
1106 request->username = NULL;
1107 request->password = NULL;
1109 if (request->reply->code != PW_AUTHENTICATION_REJECT) {
1110 pairfree(&request->reply->vps);
1114 if (request->proxy) {
1115 pairfree(&request->proxy->vps);
1117 if (request->proxy_reply) {
1118 pairfree(&request->proxy_reply->vps);
1123 RDEBUG2("Finished request %u.", request->number);
1126 STATE_MACHINE_DECL(request_running)
1128 TRACE_STATE_MACHINE;
1131 case FR_ACTION_CONFLICTING:
1133 case FR_ACTION_TIMER:
1134 request_common(request, action);
1138 case FR_ACTION_PROXY_REPLY:
1139 #ifdef HAVE_PTHREAD_H
1141 * Catch the case of a proxy reply when called
1142 * from the main worker thread.
1144 if (we_are_master() &&
1145 (request->process != proxy_running)) {
1146 request_queue_or_run(request, proxy_running);
1154 if (!request_pre_handler(request, action)) goto done;
1156 rad_assert(request->handle != NULL);
1157 request->handle(request);
1161 * We may need to send a proxied request.
1163 if ((action == FR_ACTION_RUN) &&
1164 request_will_proxy(request)) {
1165 #ifdef DEBUG_STATE_MACHINE
1166 if (debug_flag) printf("(%u) ********\tWill Proxy\t********\n", request->number);
1170 * takes care of setting
1171 * up the post proxy fail
1174 if (request_proxy(request, 0) < 0) goto done;
1178 #ifdef DEBUG_STATE_MACHINE
1179 if (debug_flag) printf("(%u) ********\tFinished\t********\n", request->number);
1184 * Maybe originate a CoA request.
1186 if ((action == FR_ACTION_RUN) && request->coa) {
1187 request_coa_originate(request);
1192 request_finish(request, action);
1194 #ifdef DEBUG_STATE_MACHINE
1195 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
1198 #ifdef HAVE_PTHREAD_H
1199 request->child_pid = NO_SUCH_CHILD_PID;
1201 request->child_state = REQUEST_DONE;
1206 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
1211 int request_receive(rad_listen_t *listener, RADIUS_PACKET *packet,
1212 RADCLIENT *client, RAD_REQUEST_FUNP fun)
1215 RADIUS_PACKET **packet_p;
1216 REQUEST *request = NULL;
1218 listen_socket_t *sock = listener->data;
1221 * Set the last packet received.
1223 gettimeofday(&now, NULL);
1224 sock->last_packet = now.tv_sec;
1226 packet_p = fr_packet_list_find(pl, packet);
1228 request = fr_packet2myptr(REQUEST, packet, packet_p);
1229 rad_assert(request->in_request_hash);
1232 * Same src/dst ip/port, length, and
1233 * authentication vector: must be a duplicate.
1235 if ((request->packet->data_len == packet->data_len) &&
1236 (memcmp(request->packet->vector, packet->vector,
1237 sizeof(packet->vector)) == 0)) {
1240 switch (packet->code) {
1241 case PW_AUTHENTICATION_REQUEST:
1242 FR_STATS_INC(auth, total_dup_requests);
1245 #ifdef WITH_ACCOUNTING
1246 case PW_ACCOUNTING_REQUEST:
1247 FR_STATS_INC(acct, total_dup_requests);
1251 case PW_COA_REQUEST:
1252 FR_STATS_INC(coa, total_dup_requests);
1255 case PW_DISCONNECT_REQUEST:
1256 FR_STATS_INC(dsc, total_dup_requests);
1263 #endif /* WITH_STATS */
1265 request->process(request, FR_ACTION_DUP);
1270 * Say we're ignoring the old one, and continue
1271 * to process the new one.
1273 request->process(request, FR_ACTION_CONFLICTING);
1278 * Quench maximum number of outstanding requests.
1280 if (mainconfig.max_requests &&
1281 ((count = fr_packet_list_num_elements(pl)) > mainconfig.max_requests)) {
1282 static time_t last_complained = 0;
1284 radlog(L_ERR, "Dropping request (%d is too many): from client %s port %d - ID: %d", count,
1286 packet->src_port, packet->id);
1287 radlog(L_INFO, "WARNING: Please check the configuration file.\n"
1288 "\tThe value for 'max_requests' is probably set too low.\n");
1291 * Complain once every 10 seconds.
1293 if ((last_complained + 10) < now.tv_sec) {
1294 last_complained = now.tv_sec;
1295 exec_trigger(NULL, NULL, "server.max_requests");
1301 return request_insert(listener, packet, client, fun, &now);
1304 int request_insert(rad_listen_t *listener, RADIUS_PACKET *packet,
1305 RADCLIENT *client, RAD_REQUEST_FUNP fun,
1306 struct timeval *pnow)
1311 * Create and initialize the new request.
1313 request = request_alloc(); /* never fails */
1315 if ((request->reply = rad_alloc(0)) == NULL) {
1316 radlog(L_ERR, "No memory");
1317 request_free(&request);
1321 request->listener = listener;
1322 request->client = client;
1323 request->packet = packet;
1324 request->packet->timestamp = *pnow;
1325 request->number = request_num_counter++;
1326 request->priority = listener->type;
1327 request->master_state = REQUEST_ACTIVE;
1328 #ifdef DEBUG_STATE_MACHINE
1329 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_ACTIVE);
1331 request->child_state = REQUEST_ACTIVE;
1332 request->handle = fun;
1333 request->options = RAD_REQUEST_OPTION_DEBUG2;
1334 #ifdef HAVE_PTHREAD_H
1335 request->child_pid = NO_SUCH_CHILD_PID;
1339 request->listener->stats.last_packet = request->packet->timestamp.tv_sec;
1340 if (packet->code == PW_AUTHENTICATION_REQUEST) {
1341 request->client->auth.last_packet = request->packet->timestamp.tv_sec;
1342 radius_auth_stats.last_packet = request->packet->timestamp.tv_sec;
1343 #ifdef WITH_ACCOUNTING
1344 } else if (packet->code == PW_ACCOUNTING_REQUEST) {
1345 request->client->acct.last_packet = request->packet->timestamp.tv_sec;
1346 radius_acct_stats.last_packet = request->packet->timestamp.tv_sec;
1349 #endif /* WITH_STATS */
1352 * Status-Server packets go to the head of the queue.
1354 if (request->packet->code == PW_STATUS_SERVER) request->priority = 0;
1357 * Set virtual server identity
1359 if (client->server) {
1360 request->server = client->server;
1361 } else if (listener->server) {
1362 request->server = listener->server;
1364 request->server = NULL;
1368 * Remember the request in the list.
1370 if (!fr_packet_list_insert(pl, &request->packet)) {
1371 radlog_request(L_ERR, 0, request, "Failed to insert request in the list of live requests: discarding it");
1372 request_done(request, FR_ACTION_DONE);
1376 request->in_request_hash = TRUE;
1377 request->root = &mainconfig;
1378 mainconfig.refcount++;
1380 request->listener->count++;
1384 * The request passes many of our sanity checks.
1385 * From here on in, if anything goes wrong, we
1386 * send a reject message, instead of dropping the
1391 * Build the reply template from the request.
1394 request->reply->sockfd = request->packet->sockfd;
1395 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1396 request->reply->src_ipaddr = request->packet->dst_ipaddr;
1397 request->reply->dst_port = request->packet->src_port;
1398 request->reply->src_port = request->packet->dst_port;
1399 request->reply->id = request->packet->id;
1400 request->reply->code = 0; /* UNKNOWN code */
1401 memcpy(request->reply->vector, request->packet->vector,
1402 sizeof(request->reply->vector));
1403 request->reply->vps = NULL;
1404 request->reply->data = NULL;
1405 request->reply->data_len = 0;
1407 request_queue_or_run(request, request_running);
1414 /***********************************************************************
1418 ***********************************************************************/
1421 * Timer function for all TCP sockets.
1423 static void tcp_socket_timer(void *ctx)
1425 rad_listen_t *listener = ctx;
1426 listen_socket_t *sock = listener->data;
1427 struct timeval end, now;
1430 fr_event_now(el, &now);
1433 * If we enforce a lifetime, do it now.
1435 if (sock->home->lifetime) {
1436 end.tv_sec = sock->opened + sock->home->lifetime;
1439 if (timercmp(&end, &now, <=)) {
1440 listener->print(listener, buffer, sizeof(buffer));
1441 DEBUG("Reached maximum lifetime on socket %s", buffer);
1445 listener->status = RAD_LISTEN_STATUS_CLOSED;
1446 event_new_fd(listener);
1455 * Enforce an idle timeout.
1457 if (sock->home->idle_timeout > 0) {
1458 struct timeval idle;
1460 idle.tv_sec = sock->last_packet + sock->home->idle_timeout;
1463 if (timercmp(&idle, &now, <=)) {
1464 listener->print(listener, buffer, sizeof(buffer));
1465 DEBUG("Reached idle timeout on socket %s", buffer);
1470 * Enforce the minimum of idle timeout or lifetime.
1472 if (timercmp(&idle, &end, <)) {
1478 * Wake up at t + 0.5s. The code above checks if the timers
1479 * are <= t. This addition gives us a bit of leeway.
1481 end.tv_usec = USEC / 2;
1483 if (!fr_event_insert(el, tcp_socket_timer, listener, &end, &sock->ev)) {
1484 rad_panic("Failed to insert event");
1490 * Add +/- 2s of jitter, as suggested in RFC 3539
1493 static void add_jitter(struct timeval *when)
1500 jitter ^= (jitter >> 10);
1501 jitter &= ((1 << 22) - 1); /* 22 bits of 1 */
1504 * Add in ~ (4 * USEC) of jitter.
1506 tv_add(when, jitter);
1510 static int remove_all_proxied_requests(void *ctx, void *data)
1512 rad_listen_t *this = ctx;
1513 RADIUS_PACKET **proxy_p = data;
1516 request = fr_packet2myptr(REQUEST, proxy, proxy_p);
1517 if (request->proxy->sockfd != this->fd) return 0;
1520 * FIXME: Force replies==requests, so that we can delete
1521 * the packet immediately.
1524 request_done(request, FR_ACTION_DONE);
1527 #endif /* WITH_PROXY */
1529 static int remove_all_requests(void *ctx, void *data)
1531 rad_listen_t *this = ctx;
1532 RADIUS_PACKET **packet_p = data;
1535 request = fr_packet2myptr(REQUEST, packet, packet_p);
1536 if (request->packet->sockfd != this->fd) return 0;
1538 request_done(request, FR_ACTION_DONE);
1541 #endif /* WITH_TCP */
1544 /***********************************************************************
1546 * Proxy handlers for the state machine.
1548 ***********************************************************************/
1550 static void remove_from_proxy_hash(REQUEST *request)
1553 * Check this without grabbing the mutex because it's a
1554 * lot faster that way.
1556 if (!request->in_proxy_hash) return;
1559 * The "not in hash" flag is definitive. However, if the
1560 * flag says that it IS in the hash, there might still be
1561 * a race condition where it isn't.
1563 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1565 if (!request->in_proxy_hash) {
1566 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1570 fr_packet_list_yank(proxy_list, request->proxy);
1571 fr_packet_list_id_free(proxy_list, request->proxy);
1574 * On the FIRST reply, decrement the count of outstanding
1575 * requests. Note that this is NOT the count of sent
1576 * packets, but whether or not the home server has
1579 if (!request->proxy_reply &&
1580 request->home_server &&
1581 request->home_server->currently_outstanding) {
1582 request->home_server->currently_outstanding--;
1586 request->proxy_listener->count--;
1588 request->proxy_listener = NULL;
1591 * Got from YES in hash, to NO, not in hash while we hold
1592 * the mutex. This guarantees that when another thread
1593 * grabs the mutex, the "not in hash" flag is correct.
1595 request->in_proxy_hash = FALSE;
1597 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1600 static int insert_into_proxy_hash(REQUEST *request)
1604 void *proxy_listener;
1606 rad_assert(request->proxy != NULL);
1607 rad_assert(proxy_list != NULL);
1611 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1612 rcode = fr_packet_list_id_alloc(proxy_list,
1613 request->home_server->proto,
1614 request->proxy, &proxy_listener);
1615 request->num_proxied_requests = 1;
1616 request->num_proxied_responses = 0;
1617 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1620 #ifdef HAVE_PTHREAD_H
1621 if (proxy_no_new_sockets) return 0;
1625 * Also locks the proxy mutex, so we have to call
1626 * it with the mutex unlocked. Some systems
1627 * don't support recursive mutexes.
1629 if (!proxy_new_listener(request->home_server, 0)) {
1630 radlog(L_ERR, "Failed to create a new socket for proxying requests.");
1633 request->proxy->src_port = 0; /* Use any new socket */
1637 RDEBUG2("ERROR: Failed allocating Id for new socket when proxying requests.");
1644 request->proxy_listener = proxy_listener;
1646 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1647 if (!fr_packet_list_insert(proxy_list, &request->proxy)) {
1648 fr_packet_list_id_free(proxy_list, request->proxy);
1649 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1650 radlog_request(L_PROXY, 0, request, "Failed to insert entry into proxy list.");
1654 request->in_proxy_hash = TRUE;
1657 * Keep track of maximum outstanding requests to a
1658 * particular home server. 'max_outstanding' is
1659 * enforced in home_server_ldb(), in realms.c.
1661 if (request->home_server) {
1662 request->home_server->currently_outstanding++;
1666 request->proxy_listener->count++;
1669 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1671 RDEBUG3(" proxy: allocating destination %s port %d - Id %d",
1672 inet_ntop(request->proxy->dst_ipaddr.af,
1673 &request->proxy->dst_ipaddr.ipaddr, buf, sizeof(buf)),
1674 request->proxy->dst_port,
1675 request->proxy->id);
1680 static int process_proxy_reply(REQUEST *request)
1683 int post_proxy_type = 0;
1687 * Delete any reply we had accumulated until now.
1689 pairfree(&request->reply->vps);
1692 * Run the packet through the post-proxy stage,
1693 * BEFORE playing games with the attributes.
1695 vp = pairfind(request->config_items, PW_POST_PROXY_TYPE, 0);
1697 RDEBUG2(" Found Post-Proxy-Type %s", vp->vp_strvalue);
1698 post_proxy_type = vp->vp_integer;
1701 if (request->home_pool && request->home_pool->virtual_server) {
1702 const char *old_server = request->server;
1704 request->server = request->home_pool->virtual_server;
1705 RDEBUG2(" server %s {", request->server);
1706 rcode = module_post_proxy(post_proxy_type, request);
1708 request->server = old_server;
1710 rcode = module_post_proxy(post_proxy_type, request);
1714 if (request->packet->code == request->proxy->code)
1716 * Don't run the next bit if we originated a CoA
1717 * packet, after receiving an Access-Request or
1718 * Accounting-Request.
1723 * There may NOT be a proxy reply, as we may be
1724 * running Post-Proxy-Type = Fail.
1726 if (request->proxy_reply) {
1728 * Delete the Proxy-State Attributes from
1729 * the reply. These include Proxy-State
1730 * attributes from us and remote server.
1732 pairdelete(&request->proxy_reply->vps, PW_PROXY_STATE, 0);
1735 * Add the attributes left in the proxy
1736 * reply to the reply list.
1738 pairadd(&request->reply->vps, request->proxy_reply->vps);
1739 request->proxy_reply->vps = NULL;
1742 * Free proxy request pairs.
1744 pairfree(&request->proxy->vps);
1748 default: /* Don't do anything */
1750 case RLM_MODULE_FAIL:
1753 case RLM_MODULE_HANDLED:
1760 int request_proxy_reply(RADIUS_PACKET *packet)
1762 RADIUS_PACKET **proxy_p;
1767 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1768 proxy_p = fr_packet_list_find_byreply(proxy_list, packet);
1771 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1772 radlog(L_PROXY, "No outstanding request was found for reply from host %s port %d - ID %d",
1773 inet_ntop(packet->src_ipaddr.af,
1774 &packet->src_ipaddr.ipaddr,
1775 buffer, sizeof(buffer)),
1776 packet->src_port, packet->id);
1780 request = fr_packet2myptr(REQUEST, proxy, proxy_p);
1781 request->num_proxied_responses++; /* needs to be protected by lock */
1783 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1786 * No reply, BUT the current packet fails verification:
1787 * ignore it. This does the MD5 calculations in the
1788 * server core, but I guess we can fix that later.
1790 if (!request->proxy_reply &&
1791 (rad_verify(packet, request->proxy,
1792 request->home_server->secret) != 0)) {
1793 DEBUG("Ignoring spoofed proxy reply. Signature is invalid");
1798 * The home server sent us a packet which doesn't match
1799 * something we have: ignore it. This is done only to
1800 * catch the case of broken systems.
1802 if (request->proxy_reply &&
1803 (memcmp(request->proxy_reply->vector,
1805 sizeof(request->proxy_reply->vector)) != 0)) {
1806 RDEBUG2("Ignoring conflicting proxy reply");
1810 gettimeofday(&now, NULL);
1813 * Status-Server packets don't count as real packets.
1815 if (request->proxy->code != PW_STATUS_SERVER) {
1816 listen_socket_t *sock = request->proxy_listener->data;
1818 request->home_server->last_packet = now.tv_sec;
1819 sock->last_packet = now.tv_sec;
1823 * If we have previously seen a reply, ignore the
1826 if (request->proxy_reply) {
1827 RDEBUG2("Discarding duplicate reply from host %s port %d - ID: %d",
1828 inet_ntop(packet->src_ipaddr.af,
1829 &packet->src_ipaddr.ipaddr,
1830 buffer, sizeof(buffer)),
1831 packet->src_port, packet->id);
1836 * Call the state machine to do something useful with the
1839 request->proxy_reply = packet;
1840 packet->timestamp = now;
1841 request->priority = RAD_LISTEN_PROXY;
1844 request->home_server->stats.last_packet = packet->timestamp.tv_sec;
1845 request->proxy_listener->stats.last_packet = packet->timestamp.tv_sec;
1847 if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
1848 proxy_auth_stats.last_packet = packet->timestamp.tv_sec;
1849 #ifdef WITH_ACCOUNTING
1850 } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
1851 proxy_acct_stats.last_packet = packet->timestamp.tv_sec;
1854 #endif /* WITH_STATS */
1858 * When we originate CoA requests, we patch them in here
1859 * so that they don't affect the rest of the state
1862 if (request->parent) {
1863 rad_assert(request->parent->coa == request);
1864 rad_assert((request->proxy->code == PW_COA_REQUEST) ||
1865 (request->proxy->code == PW_DISCONNECT_REQUEST));
1866 rad_assert(request->process != NULL);
1867 request_coa_separate(request);
1871 request->process(request, FR_ACTION_PROXY_REPLY);
1877 static int setup_post_proxy_fail(REQUEST *request)
1879 const DICT_VALUE *dval = NULL;
1882 if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
1883 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0,
1884 "Fail-Authentication");
1886 } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
1887 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0,
1890 } else if (request->proxy->code == PW_COA_REQUEST) {
1891 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail-CoA");
1893 } else if (request->proxy->code == PW_DISCONNECT_REQUEST) {
1894 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail-Disconnect");
1897 DEBUG("WARNING: Unknown packet type in Post-Proxy-Type Fail: ignoring");
1901 if (!dval) dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail");
1904 DEBUG("No Post-Proxy-Type Fail: ignoring");
1905 pairdelete(&request->config_items, PW_POST_PROXY_TYPE, 0);
1909 vp = pairfind(request->config_items, PW_POST_PROXY_TYPE, 0);
1910 if (!vp) vp = radius_paircreate(request, &request->config_items,
1911 PW_POST_PROXY_TYPE, 0, PW_TYPE_INTEGER);
1912 vp->vp_integer = dval->value;
1917 STATE_MACHINE_DECL(proxy_running)
1919 TRACE_STATE_MACHINE;
1922 case FR_ACTION_CONFLICTING:
1924 case FR_ACTION_TIMER:
1925 case FR_ACTION_PROXY_REPLY:
1926 request_common(request, action);
1930 request_running(request, FR_ACTION_PROXY_REPLY);
1934 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
1939 STATE_MACHINE_DECL(request_virtual_server)
1941 TRACE_STATE_MACHINE;
1944 case FR_ACTION_CONFLICTING:
1946 case FR_ACTION_TIMER:
1947 case FR_ACTION_PROXY_REPLY:
1948 request_common(request, action);
1952 request_running(request, action);
1956 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
1962 static int request_will_proxy(REQUEST *request)
1964 int rcode, pre_proxy_type = 0;
1965 const char *realmname = NULL;
1966 VALUE_PAIR *vp, *strippedname;
1968 REALM *realm = NULL;
1969 home_pool_t *pool = NULL;
1971 if (!request->root->proxy_requests) return 0;
1972 if (request->packet->dst_port == 0) return 0;
1973 if (request->packet->code == PW_STATUS_SERVER) return 0;
1974 if (request->in_proxy_hash) return 0;
1977 * FIXME: for 3.0, allow this only for rejects?
1979 if (request->reply->code != 0) return 0;
1981 vp = pairfind(request->config_items, PW_PROXY_TO_REALM, 0);
1983 realm = realm_find2(vp->vp_strvalue);
1985 RDEBUG2("ERROR: Cannot proxy to unknown realm %s",
1990 realmname = vp->vp_strvalue;
1993 * Figure out which pool to use.
1995 if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
1996 pool = realm->auth_pool;
1998 #ifdef WITH_ACCOUNTING
1999 } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
2000 pool = realm->acct_pool;
2004 } else if ((request->packet->code == PW_COA_REQUEST) ||
2005 (request->packet->code == PW_DISCONNECT_REQUEST)) {
2007 * FIXME: This is likely wrong. We don't
2008 * want to set Proxy-To-Realm for CoA
2009 * packets. OR, we have a CoA pool
2010 * specifically for them.
2012 pool = realm->acct_pool;
2022 vp = pairfind(request->config_items, PW_HOME_SERVER_POOL, 0);
2025 switch (request->packet->code) {
2026 case PW_AUTHENTICATION_REQUEST:
2027 pool_type = HOME_TYPE_AUTH;
2030 #ifdef WITH_ACCOUNTING
2031 case PW_ACCOUNTING_REQUEST:
2032 pool_type = HOME_TYPE_ACCT;
2037 case PW_COA_REQUEST:
2038 case PW_DISCONNECT_REQUEST:
2039 pool_type = HOME_TYPE_COA;
2047 pool = home_pool_byname(vp->vp_strvalue, pool_type);
2051 RDEBUG2(" WARNING: Cancelling proxy as no home pool exists");
2055 request->home_pool = pool;
2057 home = home_server_ldb(realmname, pool, request);
2059 RDEBUG2("ERROR: Failed to find live home server: Cancelling proxy");
2065 * Once we've decided to proxy a request, we cannot send
2066 * a CoA packet. So we free up any CoA packet here.
2068 if (request->coa) request_done(request->coa, FR_ACTION_DONE);
2072 * Remember that we sent the request to a Realm.
2074 if (realmname) pairadd(&request->packet->vps,
2075 pairmake("Realm", realmname, T_OP_EQ));
2078 * Strip the name, if told to.
2080 * Doing it here catches the case of proxied tunneled
2083 if (realm && (realm->striprealm == TRUE) &&
2084 (strippedname = pairfind(request->proxy->vps, PW_STRIPPED_USER_NAME, 0)) != NULL) {
2086 * If there's a Stripped-User-Name attribute in
2087 * the request, then use THAT as the User-Name
2088 * for the proxied request, instead of the
2091 * This is done by making a copy of the
2092 * Stripped-User-Name attribute, turning it into
2093 * a User-Name attribute, deleting the
2094 * Stripped-User-Name and User-Name attributes
2095 * from the vps list, and making the new
2096 * User-Name the head of the vps list.
2098 vp = pairfind(request->proxy->vps, PW_USER_NAME, 0);
2100 vp = radius_paircreate(request, NULL,
2101 PW_USER_NAME, 0, PW_TYPE_STRING);
2102 rad_assert(vp != NULL); /* handled by above function */
2103 /* Insert at the START of the list */
2104 vp->next = request->proxy->vps;
2105 request->proxy->vps = vp;
2107 memcpy(vp->vp_strvalue, strippedname->vp_strvalue,
2108 sizeof(vp->vp_strvalue));
2109 vp->length = strippedname->length;
2112 * Do NOT delete Stripped-User-Name.
2117 * If there is no PW_CHAP_CHALLENGE attribute but
2118 * there is a PW_CHAP_PASSWORD we need to add it
2119 * since we can't use the request authenticator
2120 * anymore - we changed it.
2122 if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
2123 pairfind(request->proxy->vps, PW_CHAP_PASSWORD, 0) &&
2124 pairfind(request->proxy->vps, PW_CHAP_CHALLENGE, 0) == NULL) {
2125 vp = radius_paircreate(request, &request->proxy->vps,
2126 PW_CHAP_CHALLENGE, 0, PW_TYPE_OCTETS);
2127 memcpy(vp->vp_strvalue, request->packet->vector,
2128 sizeof(request->packet->vector));
2129 vp->length = sizeof(request->packet->vector);
2133 * The RFC's say we have to do this, but FreeRADIUS
2136 vp = radius_paircreate(request, &request->proxy->vps,
2137 PW_PROXY_STATE, 0, PW_TYPE_OCTETS);
2138 snprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue), "%d",
2139 request->packet->id);
2140 vp->length = strlen(vp->vp_strvalue);
2143 * Should be done BEFORE inserting into proxy hash, as
2144 * pre-proxy may use this information, or change it.
2146 request->proxy->code = request->packet->code;
2149 * Call the pre-proxy routines.
2151 vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE, 0);
2153 RDEBUG2(" Found Pre-Proxy-Type %s", vp->vp_strvalue);
2154 pre_proxy_type = vp->vp_integer;
2157 rad_assert(request->home_pool != NULL);
2159 if (request->home_pool->virtual_server) {
2160 const char *old_server = request->server;
2162 request->server = request->home_pool->virtual_server;
2163 RDEBUG2(" server %s {", request->server);
2164 rcode = module_pre_proxy(pre_proxy_type, request);
2166 request->server = old_server;
2168 rcode = module_pre_proxy(pre_proxy_type, request);
2171 case RLM_MODULE_FAIL:
2172 case RLM_MODULE_INVALID:
2173 case RLM_MODULE_NOTFOUND:
2174 case RLM_MODULE_USERLOCK:
2176 /* FIXME: debug print failed stuff */
2179 case RLM_MODULE_REJECT:
2180 case RLM_MODULE_HANDLED:
2184 * Only proxy the packet if the pre-proxy code succeeded.
2186 case RLM_MODULE_NOOP:
2188 case RLM_MODULE_UPDATED:
2195 static int request_proxy(REQUEST *request, int retransmit)
2199 rad_assert(request->parent == NULL);
2200 rad_assert(request->home_server != NULL);
2202 if (request->master_state == REQUEST_STOP_PROCESSING) return 0;
2206 RDEBUG("WARNING: Cannot proxy and originate CoA packets at the same time. Cancelling CoA request");
2207 request_done(request->coa, FR_ACTION_DONE);
2212 * The request may be sent to a virtual server. If we're
2213 * in a child thread, just process it here. If we're the
2214 * master, push it back onto the queue for later
2217 if (request->home_server->server) {
2218 DEBUG("Proxying to virtual server %s",
2219 request->home_server->server);
2221 if (!we_are_master()) {
2222 request_virtual_server(request, FR_ACTION_RUN);
2223 #ifdef HAVE_PTHREAD_H
2224 request->child_pid = NO_SUCH_CHILD_PID;
2229 request_queue_or_run(request, request_virtual_server);
2234 * We're actually sending a proxied packet. Do that now.
2236 if (!insert_into_proxy_hash(request)) {
2237 radlog_request(L_PROXY, 0, request, "Failed to insert initial packet into the proxy list.");
2241 request->proxy_listener->encode(request->proxy_listener, request);
2243 RDEBUG2("Proxying request to home server %s port %d",
2244 inet_ntop(request->proxy->dst_ipaddr.af,
2245 &request->proxy->dst_ipaddr.ipaddr,
2246 buffer, sizeof(buffer)),
2247 request->proxy->dst_port);
2249 DEBUG_PACKET(request, request->proxy, 1);
2251 gettimeofday(&request->proxy_retransmit, NULL);
2252 if (!retransmit) request->proxy->timestamp = request->proxy_retransmit;
2254 #ifdef HAVE_PTHREAD_H
2255 request->child_pid = NO_SUCH_CHILD_PID;
2257 request->proxy_listener->send(request->proxy_listener,
2263 * Proxy the packet as if it was new.
2265 static int request_proxy_anew(REQUEST *request)
2268 * Keep a copy of the old Id so that the
2269 * re-transmitted request doesn't re-use the old
2272 RADIUS_PACKET old = *request->proxy;
2274 home_server *old_home = request->home_server;
2276 rad_listen_t *listener = request->proxy_listener;
2279 rad_assert(old_home != NULL);
2282 * Find a live home server for the request.
2284 home = home_server_ldb(NULL, request->home_pool, request);
2286 RDEBUG2("ERROR: Failed to find live home server for request");
2288 remove_from_proxy_hash(request);
2290 if (!setup_post_proxy_fail(request)) {
2294 request_queue_or_run(request, proxy_running);
2299 * Don't free the old Id on error.
2301 if (!insert_into_proxy_hash(request)) {
2302 radlog_request(L_PROXY, 0, request, "Failed to insert retransmission into the proxy list.");
2303 goto post_proxy_fail;
2307 * Now that we have a new Id, free the old one
2308 * and update the various statistics.
2310 PTHREAD_MUTEX_LOCK(&proxy_mutex);
2311 fr_packet_list_yank(proxy_list, &old);
2312 fr_packet_list_id_free(proxy_list, &old);
2313 old_home->currently_outstanding--;
2315 if (listener) listener->count--;
2317 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
2320 * Free the old packet, to force re-encoding
2322 free(request->proxy->data);
2323 request->proxy->data = NULL;
2324 request->proxy->data_len = 0;
2326 #ifdef WITH_ACCOUNTING
2328 * Update the Acct-Delay-Time attribute.
2330 if (request->packet->code == PW_ACCOUNTING_REQUEST) {
2333 vp = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME, 0);
2334 if (!vp) vp = radius_paircreate(request,
2335 &request->proxy->vps,
2336 PW_ACCT_DELAY_TIME, 0,
2341 gettimeofday(&now, NULL);
2342 vp->vp_integer += now.tv_sec - request->proxy_retransmit.tv_sec;
2347 if (request_proxy(request, 1) != 1) goto post_proxy_fail;
2352 STATE_MACHINE_DECL(request_ping)
2354 home_server *home = request->home_server;
2357 TRACE_STATE_MACHINE;
2361 case FR_ACTION_TIMER:
2362 radlog(L_ERR, "No response to status check %d for home server %s port %d",
2364 inet_ntop(request->proxy->dst_ipaddr.af,
2365 &request->proxy->dst_ipaddr.ipaddr,
2366 buffer, sizeof(buffer)),
2367 request->proxy->dst_port);
2370 case FR_ACTION_PROXY_REPLY:
2371 rad_assert(request->in_proxy_hash);
2373 request->home_server->num_received_pings++;
2374 radlog_request(L_PROXY, 0, request, "Received response to status check %d (%d in current sequence)",
2375 request->number, home->num_received_pings);
2378 * Remove the request from any hashes
2380 fr_event_delete(el, &request->ev);
2381 remove_from_proxy_hash(request);
2384 * The control socket may have marked the home server as
2385 * alive. OR, it may have suddenly started responding to
2386 * requests again. If so, don't re-do the "make alive"
2389 if (home->state == HOME_STATE_ALIVE) break;
2392 * We haven't received enough ping responses to mark it
2393 * "alive". Wait a bit.
2395 if (home->num_received_pings < home->num_pings_to_alive) {
2400 * Mark it alive and delete any outstanding
2403 home->state = HOME_STATE_ALIVE;
2404 exec_trigger(request, request->home_server->cs, "home_server.alive");
2405 home->currently_outstanding = 0;
2406 home->num_sent_pings = 0;
2407 home->num_received_pings = 0;
2408 gettimeofday(&home->revive_time, NULL);
2410 fr_event_delete(el, &home->ev);
2412 radlog_request(L_PROXY, 0, request, "Marking home server %s port %d alive",
2413 inet_ntop(request->proxy->dst_ipaddr.af,
2414 &request->proxy->dst_ipaddr.ipaddr,
2415 buffer, sizeof(buffer)),
2416 request->proxy->dst_port);
2420 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
2424 rad_assert(!request->in_request_hash);
2425 rad_assert(request->ev == NULL);
2426 request_done(request, FR_ACTION_DONE);
2430 * Called from start of zombie period, OR after control socket
2431 * marks the home server dead.
2433 static void ping_home_server(void *ctx)
2435 home_server *home = ctx;
2438 struct timeval when, now;
2440 if ((home->state == HOME_STATE_ALIVE) ||
2441 (home->ping_check == HOME_PING_CHECK_NONE) ||
2443 (home->proto == IPPROTO_TCP) ||
2445 (home->ev != NULL)) {
2449 gettimeofday(&now, NULL);
2451 if (home->state == HOME_STATE_ZOMBIE) {
2452 when = home->zombie_period_start;
2453 when.tv_sec += home->zombie_period;
2455 if (timercmp(&when, &now, <)) {
2456 DEBUG("PING: Zombie period is over for home server %s",
2458 mark_home_server_dead(home, &now);
2462 request = request_alloc();
2463 request->number = request_num_counter++;
2464 #ifdef HAVE_PTHREAD_H
2465 request->child_pid = NO_SUCH_CHILD_PID;
2468 request->proxy = rad_alloc(1);
2469 rad_assert(request->proxy != NULL);
2471 if (home->ping_check == HOME_PING_CHECK_STATUS_SERVER) {
2472 request->proxy->code = PW_STATUS_SERVER;
2474 radius_pairmake(request, &request->proxy->vps,
2475 "Message-Authenticator", "0x00", T_OP_SET);
2477 } else if (home->type == HOME_TYPE_AUTH) {
2478 request->proxy->code = PW_AUTHENTICATION_REQUEST;
2480 radius_pairmake(request, &request->proxy->vps,
2481 "User-Name", home->ping_user_name, T_OP_SET);
2482 radius_pairmake(request, &request->proxy->vps,
2483 "User-Password", home->ping_user_password, T_OP_SET);
2484 radius_pairmake(request, &request->proxy->vps,
2485 "Service-Type", "Authenticate-Only", T_OP_SET);
2486 radius_pairmake(request, &request->proxy->vps,
2487 "Message-Authenticator", "0x00", T_OP_SET);
2490 #ifdef WITH_ACCOUNTING
2491 request->proxy->code = PW_ACCOUNTING_REQUEST;
2493 radius_pairmake(request, &request->proxy->vps,
2494 "User-Name", home->ping_user_name, T_OP_SET);
2495 radius_pairmake(request, &request->proxy->vps,
2496 "Acct-Status-Type", "Stop", T_OP_SET);
2497 radius_pairmake(request, &request->proxy->vps,
2498 "Acct-Session-Id", "00000000", T_OP_SET);
2499 vp = radius_pairmake(request, &request->proxy->vps,
2500 "Event-Timestamp", "0", T_OP_SET);
2501 vp->vp_date = now.tv_sec;
2503 rad_assert("Internal sanity check failed");
2507 vp = radius_pairmake(request, &request->proxy->vps,
2508 "NAS-Identifier", "", T_OP_SET);
2510 snprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue),
2511 "Status Check %u. Are you alive?",
2512 home->num_sent_pings);
2513 vp->length = strlen(vp->vp_strvalue);
2516 request->proxy->dst_ipaddr = home->ipaddr;
2517 request->proxy->dst_port = home->port;
2518 request->home_server = home;
2519 #ifdef DEBUG_STATE_MACHINE
2520 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
2521 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_ping");
2523 #ifdef HAVE_PTHREAD_H
2524 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
2526 request->child_state = REQUEST_DONE;
2527 request->process = request_ping;
2529 rad_assert(request->proxy_listener == NULL);
2531 if (!insert_into_proxy_hash(request)) {
2532 radlog_request(L_PROXY, 0, request, "Failed to insert status check %d into proxy list. Discarding it.",
2535 rad_assert(!request->in_request_hash);
2536 rad_assert(!request->in_proxy_hash);
2537 rad_assert(request->ev == NULL);
2538 request_free(&request);
2543 * Set up the timer callback.
2546 when.tv_sec += home->ping_timeout;
2548 DEBUG("PING: Waiting %u seconds for response to ping",
2549 home->ping_timeout);
2551 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
2552 home->num_sent_pings++;
2554 rad_assert(request->proxy_listener != NULL);
2555 request->proxy_listener->send(request->proxy_listener,
2559 * Add +/- 2s of jitter, as suggested in RFC 3539
2560 * and in the Issues and Fixes draft.
2563 home->when.tv_sec += home->ping_interval;
2565 add_jitter(&home->when);
2567 DEBUG("PING: Next status packet in %u seconds", home->ping_interval);
2568 INSERT_EVENT(ping_home_server, home);
2571 static void home_trigger(home_server *home, const char *trigger)
2574 RADIUS_PACKET my_packet;
2576 memset(&my_request, 0, sizeof(my_request));
2577 memset(&my_packet, 0, sizeof(my_packet));
2578 my_request.proxy = &my_packet;
2579 my_packet.dst_ipaddr = home->ipaddr;
2580 my_packet.src_ipaddr = home->src_ipaddr;
2582 exec_trigger(&my_request, home->cs, trigger);
2585 static void mark_home_server_zombie(home_server *home)
2591 rad_assert(home->state == HOME_STATE_ALIVE);
2594 if (home->proto == IPPROTO_TCP) {
2595 DEBUG("WARNING: Not marking TCP server %s zombie", home->name);
2600 home->state = HOME_STATE_ZOMBIE;
2601 home_trigger(home, "home_server.zombie");
2603 home->zombie_period_start.tv_sec = home->last_packet;
2604 home->zombie_period_start.tv_usec = USEC / 2;
2606 fr_event_delete(el, &home->ev);
2607 home->num_sent_pings = 0;
2608 home->num_received_pings = 0;
2610 radlog(L_PROXY, "Marking home server %s port %d as zombie (it looks like it is dead).",
2611 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
2612 buffer, sizeof(buffer)),
2615 ping_home_server(home);
2619 void revive_home_server(void *ctx)
2621 home_server *home = ctx;
2625 rad_assert(home->proto != IPPROTO_TCP);
2628 home->state = HOME_STATE_ALIVE;
2629 home_trigger(home, "home_server.alive");
2630 home->currently_outstanding = 0;
2631 gettimeofday(&home->revive_time, NULL);
2634 * Delete any outstanding events.
2636 if (home->ev) fr_event_delete(el, &home->ev);
2638 radlog(L_PROXY, "Marking home server %s port %d alive again... we have no idea if it really is alive or not.",
2639 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
2640 buffer, sizeof(buffer)),
2644 void mark_home_server_dead(home_server *home, struct timeval *when)
2646 int previous_state = home->state;
2650 if (home->proto == IPPROTO_TCP) {
2651 DEBUG("WARNING: Not marking TCP server dead");
2656 radlog(L_PROXY, "Marking home server %s port %d as dead.",
2657 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
2658 buffer, sizeof(buffer)),
2661 home->state = HOME_STATE_IS_DEAD;
2662 home_trigger(home, "home_server.dead");
2664 if (home->ping_check != HOME_PING_CHECK_NONE) {
2666 * If the control socket marks us dead, start
2667 * pinging. Otherwise, we already started
2668 * pinging when it was marked "zombie".
2670 if (previous_state == HOME_STATE_ALIVE) {
2671 ping_home_server(home);
2673 DEBUG("PING: Already pinging home server %s",
2679 * Revive it after a fixed period of time. This
2680 * is very, very, bad.
2683 home->when.tv_sec += home->revive_interval;
2685 DEBUG("PING: Reviving home server %s in %u seconds",
2686 home->name, home->revive_interval);
2687 INSERT_EVENT(revive_home_server, home);
2691 STATE_MACHINE_DECL(proxy_wait_for_reply)
2693 struct timeval now, when;
2694 home_server *home = request->home_server;
2697 TRACE_STATE_MACHINE;
2699 rad_assert(request->packet->code != PW_STATUS_SERVER);
2700 rad_assert(request->home_server != NULL);
2702 gettimeofday(&now, NULL);
2704 rad_assert(request->child_state != REQUEST_DONE);
2706 if (request->master_state == REQUEST_STOP_PROCESSING) {
2707 request_done(request, FR_ACTION_DONE);
2713 if (!request->proxy_listener) return;
2715 if ((home->state == HOME_STATE_IS_DEAD) ||
2716 (request->proxy_listener->status != RAD_LISTEN_STATUS_KNOWN)) {
2717 request_proxy_anew(request);
2722 if (home->proto == IPPROTO_TCP) {
2723 DEBUG2("Suppressing duplicate proxied request to home server %s port %d proto TCP - ID: %d",
2724 inet_ntop(request->proxy->dst_ipaddr.af,
2725 &request->proxy->dst_ipaddr.ipaddr,
2726 buffer, sizeof(buffer)),
2727 request->proxy->dst_port,
2728 request->proxy->id);
2733 #ifdef WITH_ACCOUNTING
2735 * If we update the Acct-Delay-Time, we need to
2738 if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
2739 pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME, 0)) {
2740 request_proxy_anew(request);
2745 RDEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",
2746 inet_ntop(request->proxy->dst_ipaddr.af,
2747 &request->proxy->dst_ipaddr.ipaddr,
2748 buffer, sizeof(buffer)),
2749 request->proxy->dst_port,
2750 request->proxy->id);
2751 request->num_proxied_requests++;
2753 DEBUG_PACKET(request, request->proxy, 1);
2754 request->proxy_listener->send(request->proxy_listener,
2758 case FR_ACTION_TIMER:
2760 * If we haven't received a packet for a while,
2761 * mark it as zombie. If the connection is TCP,
2762 * then another "watchdog timer" function takes
2763 * care of pings, etc.
2765 if ((home->state == HOME_STATE_ALIVE) &&
2767 (home->proto != IPPROTO_TCP) &&
2769 ((home->last_packet + ((home->zombie_period + 3) / 4)) < now.tv_sec)) {
2770 mark_home_server_zombie(home);
2773 when = request->proxy->timestamp;
2774 when.tv_sec += home->response_window;
2777 * Not at the response window. Set the timer for
2780 if (timercmp(&when, &now, >)) {
2781 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
2786 * FIXME: debug log no response to proxied request
2790 * No response, but we're supposed to do nothing
2791 * when there's no response. The request is finished.
2793 if (!home->no_response_fail) {
2794 #ifdef HAVE_PTHREAD_H
2795 request->child_pid = NO_SUCH_CHILD_PID;
2797 gettimeofday(&request->reply->timestamp, NULL);
2798 #ifdef DEBUG_STATE_MACHINE
2799 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
2801 #ifdef HAVE_PTHREAD_H
2802 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
2804 request->child_state = REQUEST_DONE;
2805 request_process_timer(request);
2810 * Do "fail on no response".
2812 radlog_request(L_ERR, 0, request, "Rejecting request (proxy Id %d) due to lack of any response from home server %s port %d",
2814 inet_ntop(request->proxy->dst_ipaddr.af,
2815 &request->proxy->dst_ipaddr.ipaddr,
2816 buffer, sizeof(buffer)),
2817 request->proxy->dst_port);
2819 if (!setup_post_proxy_fail(request)) {
2825 * Duplicate proxy replies have been quenched by
2826 * now. This state is only called ONCE, when we
2827 * receive a new reply from the home server.
2829 case FR_ACTION_PROXY_REPLY:
2830 request_queue_or_run(request, proxy_running);
2833 case FR_ACTION_CONFLICTING:
2834 request_done(request, action);
2838 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
2842 #endif /* WITH_PROXY */
2844 /***********************************************************************
2848 ***********************************************************************/
2850 static int null_handler(UNUSED REQUEST *request)
2856 * See if we need to originate a CoA request.
2858 static void request_coa_originate(REQUEST *request)
2860 int rcode, pre_proxy_type = 0;
2866 rad_assert(request != NULL);
2867 rad_assert(request->coa != NULL);
2868 rad_assert(request->proxy == NULL);
2869 rad_assert(!request->in_proxy_hash);
2870 rad_assert(request->proxy_reply == NULL);
2873 * Check whether we want to originate one, or cancel one.
2875 vp = pairfind(request->config_items, PW_SEND_COA_REQUEST, 0);
2877 vp = pairfind(request->coa->proxy->vps, PW_SEND_COA_REQUEST, 0);
2881 if (vp->vp_integer == 0) {
2883 request_done(request->coa, FR_ACTION_DONE);
2891 * src_ipaddr will be set up in proxy_encode.
2893 memset(&ipaddr, 0, sizeof(ipaddr));
2894 vp = pairfind(coa->proxy->vps, PW_PACKET_DST_IP_ADDRESS, 0);
2896 ipaddr.af = AF_INET;
2897 ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
2899 } else if ((vp = pairfind(coa->proxy->vps,
2900 PW_PACKET_DST_IPV6_ADDRESS, 0)) != NULL) {
2901 ipaddr.af = AF_INET6;
2902 ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
2904 } else if ((vp = pairfind(coa->proxy->vps,
2905 PW_HOME_SERVER_POOL, 0)) != NULL) {
2906 coa->home_pool = home_pool_byname(vp->vp_strvalue,
2908 if (!coa->home_pool) {
2909 RDEBUG2("WARNING: No such home_server_pool %s",
2915 * Prefer the pool to one server
2917 } else if (request->client->coa_pool) {
2918 coa->home_pool = request->client->coa_pool;
2920 } else if (request->client->coa_server) {
2921 coa->home_server = request->client->coa_server;
2925 * If all else fails, send it to the client that
2926 * originated this request.
2928 memcpy(&ipaddr, &request->packet->src_ipaddr, sizeof(ipaddr));
2932 * Use the pool, if it exists.
2934 if (coa->home_pool) {
2935 coa->home_server = home_server_ldb(NULL, coa->home_pool, coa);
2936 if (!coa->home_server) {
2937 RDEBUG("WARNING: No live home server for home_server_pool %s", vp->vp_strvalue);
2941 } else if (!coa->home_server) {
2942 int port = PW_COA_UDP_PORT;
2944 vp = pairfind(coa->proxy->vps, PW_PACKET_DST_PORT, 0);
2945 if (vp) port = vp->vp_integer;
2947 coa->home_server = home_server_find(&ipaddr, port, IPPROTO_UDP);
2948 if (!coa->home_server) {
2949 RDEBUG2("WARNING: Unknown destination %s:%d for CoA request.",
2950 inet_ntop(ipaddr.af, &ipaddr.ipaddr,
2951 buffer, sizeof(buffer)), port);
2956 vp = pairfind(coa->proxy->vps, PW_PACKET_TYPE, 0);
2958 switch (vp->vp_integer) {
2959 case PW_COA_REQUEST:
2960 case PW_DISCONNECT_REQUEST:
2961 coa->proxy->code = vp->vp_integer;
2965 DEBUG("Cannot set CoA Packet-Type to code %d",
2971 if (!coa->proxy->code) coa->proxy->code = PW_COA_REQUEST;
2974 * The rest of the server code assumes that
2975 * request->packet && request->reply exist. Copy them
2976 * from the original request.
2978 rad_assert(coa->packet != NULL);
2979 rad_assert(coa->packet->vps == NULL);
2980 memcpy(coa->packet, request->packet, sizeof(*request->packet));
2981 coa->packet->vps = paircopy(request->packet->vps);
2982 coa->packet->data = NULL;
2983 rad_assert(coa->reply != NULL);
2984 rad_assert(coa->reply->vps == NULL);
2985 memcpy(coa->reply, request->reply, sizeof(*request->reply));
2986 coa->reply->vps = paircopy(request->reply->vps);
2987 coa->reply->data = NULL;
2988 coa->config_items = paircopy(request->config_items);
2989 coa->num_coa_requests = 0;
2990 coa->handle = null_handler;
2991 coa->number = request->number ^ (1 << 24);
2994 * Call the pre-proxy routines.
2996 vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE, 0);
2998 RDEBUG2(" Found Pre-Proxy-Type %s", vp->vp_strvalue);
2999 pre_proxy_type = vp->vp_integer;
3002 if (coa->home_pool && coa->home_pool->virtual_server) {
3003 const char *old_server = coa->server;
3005 coa->server = coa->home_pool->virtual_server;
3006 RDEBUG2(" server %s {", coa->server);
3007 rcode = module_pre_proxy(pre_proxy_type, coa);
3009 coa->server = old_server;
3011 rcode = module_pre_proxy(pre_proxy_type, coa);
3018 * Only send the CoA packet if the pre-proxy code succeeded.
3020 case RLM_MODULE_NOOP:
3022 case RLM_MODULE_UPDATED:
3027 * Source IP / port is set when the proxy socket
3030 coa->proxy->dst_ipaddr = coa->home_server->ipaddr;
3031 coa->proxy->dst_port = coa->home_server->port;
3033 if (!insert_into_proxy_hash(coa)) {
3034 radlog_request(L_PROXY, 0, coa, "Failed to insert CoA request into proxy list.");
3039 * We CANNOT divorce the CoA request from the parent
3040 * request. This function is running in a child thread,
3041 * and we need access to the main event loop in order to
3042 * to add the timers for the CoA packet.
3044 * Instead, we wait for the timer on the parent request
3047 gettimeofday(&coa->proxy->timestamp, NULL);
3048 coa->packet->timestamp = coa->proxy->timestamp; /* for max_request_time */
3049 coa->delay = 0; /* need to calculate a new delay */
3051 DEBUG_PACKET(coa, coa->proxy, 1);
3053 coa->process = request_coa_process;
3054 #ifdef DEBUG_STATE_MACHINE
3055 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_ACTIVE);
3057 coa->child_state = REQUEST_ACTIVE;
3058 rad_assert(coa->proxy_reply == NULL);
3059 coa->proxy_listener->send(coa->proxy_listener, coa);
3063 static void request_coa_separate(REQUEST *request)
3065 #ifdef DEBUG_STATE_MACHINE
3066 int action = FR_ACTION_TIMER;
3068 TRACE_STATE_MACHINE;
3070 rad_assert(request->parent != NULL);
3071 rad_assert(request->parent->coa == request);
3072 rad_assert(request->ev == NULL);
3073 rad_assert(!request->in_request_hash);
3075 request->parent->coa = NULL;
3076 request->parent = NULL;
3079 * Set up timers for the CoA request. These do all kinds
3080 * of different things....
3082 request_coa_timer(request);
3085 static void request_coa_timer(REQUEST *request)
3088 struct timeval now, when, mrd;
3090 rad_assert(request->parent == NULL);
3092 if (request->proxy_reply) return request_process_timer(request);
3094 gettimeofday(&now, NULL);
3096 if (request->delay == 0) {
3098 * Implement re-transmit algorithm as per RFC 5080
3101 * We want IRT + RAND*IRT
3102 * or 0.9 IRT + rand(0,.2) IRT
3104 * 2^20 ~ USEC, and we want 2.
3105 * rand(0,0.2) USEC ~ (rand(0,2^21) / 10)
3107 delay = (fr_rand() & ((1 << 22) - 1)) / 10;
3108 request->delay = delay * request->home_server->coa_irt;
3109 delay = request->home_server->coa_irt * USEC;
3110 delay -= delay / 10;
3111 delay += request->delay;
3112 request->delay = delay;
3114 when = request->proxy->timestamp;
3115 tv_add(&when, delay);
3117 if (timercmp(&when, &now, >)) {
3118 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
3124 * Retransmit CoA request.
3128 * Cap count at MRC, if it is non-zero.
3130 if (request->home_server->coa_mrc &&
3131 (request->num_coa_requests >= request->home_server->coa_mrc)) {
3132 if (!setup_post_proxy_fail(request)) {
3136 request_queue_or_run(request, proxy_running);
3141 * RFC 5080 Section 2.2.1
3143 * RT = 2*RTprev + RAND*RTprev
3144 * = 1.9 * RTprev + rand(0,.2) * RTprev
3145 * = 1.9 * RTprev + rand(0,1) * (RTprev / 5)
3148 delay ^= (delay >> 16);
3150 frac = request->delay / 5;
3151 delay = ((frac >> 16) * delay) + (((frac & 0xffff) * delay) >> 16);
3153 delay += (2 * request->delay) - (request->delay / 10);
3156 * Cap delay at MRT, if MRT is non-zero.
3158 if (request->home_server->coa_mrt &&
3159 (delay > (request->home_server->coa_mrt * USEC))) {
3160 int mrt_usec = request->home_server->coa_mrt * USEC;
3163 * delay = MRT + RAND * MRT
3164 * = 0.9 MRT + rand(0,.2) * MRT
3167 delay ^= (delay >> 15);
3169 delay = ((mrt_usec >> 16) * delay) + (((mrt_usec & 0xffff) * delay) >> 16);
3170 delay += mrt_usec - (mrt_usec / 10);
3173 request->delay = delay;
3175 tv_add(&when, request->delay);
3176 mrd = request->proxy->timestamp;
3177 mrd.tv_sec += request->home_server->coa_mrd;
3180 * Cap duration at MRD.
3182 if (timercmp(&mrd, &when, <)) {
3185 STATE_MACHINE_TIMER(FR_ACTION_TIMER);
3187 request->num_coa_requests++; /* is NOT reset by code 3 lines above! */
3189 request->proxy_listener->send(request->proxy_listener,
3194 #ifdef HAVE_PTHREAD_H
3195 STATE_MACHINE_DECL(coa_running)
3197 TRACE_STATE_MACHINE;
3200 case FR_ACTION_TIMER:
3201 request_coa_timer(request);
3204 case FR_ACTION_PROXY_REPLY:
3205 request_common(request, action);
3209 request_running(request, FR_ACTION_PROXY_REPLY);
3213 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
3217 #endif /* HAVE_PTHREAD_H */
3221 * Process CoA requests that we originated.
3223 STATE_MACHINE_DECL(request_coa_process)
3225 TRACE_STATE_MACHINE;
3228 case FR_ACTION_TIMER:
3229 request_coa_timer(request);
3232 case FR_ACTION_PROXY_REPLY:
3233 rad_assert(request->parent == NULL);
3234 #ifdef HAVE_PTHREAD_H
3236 * Catch the case of a proxy reply when called
3237 * from the main worker thread.
3239 if (we_are_master() &&
3240 (request->process != coa_running)) {
3241 request_queue_or_run(request, coa_running);
3247 request_running(request, action);
3251 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
3256 #endif /* WITH_COA */
3258 /***********************************************************************
3260 * End of the State machine. Start of additional helper code.
3262 ***********************************************************************/
3264 /***********************************************************************
3268 ***********************************************************************/
3269 static void event_socket_handler(fr_event_list_t *xel, UNUSED int fd,
3272 rad_listen_t *listener = ctx;
3274 rad_assert(xel == el);
3280 (listener->type != RAD_LISTEN_DETAIL) &&
3282 (listener->fd < 0)) {
3285 listener->print(listener, buffer, sizeof(buffer));
3286 radlog(L_ERR, "FATAL: Asked to read from closed socket: %s",
3289 rad_panic("Socket was closed on us!");
3293 listener->recv(listener);
3298 * This function is called periodically to see if this detail
3299 * file is available for reading.
3301 static void event_poll_detail(void *ctx)
3304 rad_listen_t *this = ctx;
3305 struct timeval when, now;
3306 listen_detail_t *detail = this->data;
3308 rad_assert(this->type == RAD_LISTEN_DETAIL);
3310 event_socket_handler(el, this->fd, this);
3312 fr_event_now(el, &now);
3316 * Backdoor API to get the delay until the next poll
3319 delay = this->encode(this, NULL);
3320 tv_add(&when, delay);
3322 if (!fr_event_insert(el, event_poll_detail, this,
3323 &when, &detail->ev)) {
3324 radlog(L_ERR, "Failed creating handler");
3330 static void event_status(struct timeval *wake)
3332 #if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)
3336 if (debug_flag == 0) {
3338 radlog(L_INFO, "Ready to process requests.");
3339 just_started = FALSE;
3345 radlog(L_INFO, "Ready to process requests.");
3347 } else if ((wake->tv_sec != 0) ||
3348 (wake->tv_usec >= 100000)) {
3349 DEBUG("Waking up in %d.%01u seconds.",
3350 (int) wake->tv_sec, (unsigned int) wake->tv_usec / 100000);
3355 * FIXME: Put this somewhere else, where it isn't called
3356 * all of the time...
3359 #if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)
3361 * If there are no child threads, then there may
3362 * be child processes. In that case, wait for
3363 * their exit status, and throw that exit status
3364 * away. This helps get rid of zxombie children.
3366 while (waitpid(-1, &argval, WNOHANG) > 0) {
3374 int event_new_fd(rad_listen_t *this)
3378 if (this->status == RAD_LISTEN_STATUS_KNOWN) return 1;
3380 this->print(this, buffer, sizeof(buffer));
3382 if (this->status == RAD_LISTEN_STATUS_INIT) {
3384 DEBUG("Listening on %s", buffer);
3386 radlog(L_INFO, " ... adding new socket %s", buffer);
3391 * Add it to the list of sockets we can use.
3392 * Server sockets (i.e. auth/acct) are never
3393 * added to the packet list.
3395 if (this->type == RAD_LISTEN_PROXY) {
3396 listen_socket_t *sock = this->data;
3398 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3399 if (!fr_packet_list_socket_add(proxy_list, this->fd,
3401 &sock->other_ipaddr, sock->other_port,
3404 #ifdef HAVE_PTHREAD_H
3405 proxy_no_new_sockets = TRUE;
3407 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3410 * This is bad. However, the
3411 * packet list now supports 256
3412 * open sockets, which should
3413 * minimize this problem.
3415 radlog(L_ERR, "Failed adding proxy socket: %s",
3421 sock->home->num_connections++;
3423 #ifdef HAVE_PTHREAD_H
3425 * If necessary, add it to the list of
3426 * new proxy listeners.
3428 if (sock->home->lifetime || sock->home->idle_timeout) {
3429 this->next = proxy_listener_list;
3430 proxy_listener_list = this;
3434 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3437 * Tell the main thread that we've added
3438 * a proxy listener, but only if we need
3439 * to update the event list. Do this
3440 * with the mutex unlocked, to reduce
3444 if (sock->home->lifetime || sock->home->idle_timeout) {
3445 radius_signal_self(RADIUS_SIGNAL_SELF_NEW_FD);
3453 * Detail files are always known, and aren't
3454 * put into the socket event loop.
3456 if (this->type == RAD_LISTEN_DETAIL) {
3457 this->status = RAD_LISTEN_STATUS_KNOWN;
3460 * Set up the first poll interval.
3462 event_poll_detail(this);
3467 FD_MUTEX_LOCK(&fd_mutex);
3468 if (!fr_event_fd_insert(el, 0, this->fd,
3469 event_socket_handler, this)) {
3470 radlog(L_ERR, "Failed adding event handler for proxy socket!");
3473 FD_MUTEX_UNLOCK(&fd_mutex);
3475 this->status = RAD_LISTEN_STATUS_KNOWN;
3480 * Something went wrong with the socket: make it harmless.
3482 if (this->status == RAD_LISTEN_STATUS_REMOVE_FD) {
3486 * Remove it from the list of live FD's.
3488 FD_MUTEX_LOCK(&fd_mutex);
3489 fr_event_fd_delete(el, 0, this->fd);
3490 FD_MUTEX_UNLOCK(&fd_mutex);
3494 * We track requests using this socket only for
3495 * TCP. For UDP, we don't currently close
3499 if (this->type != RAD_LISTEN_PROXY)
3502 if (this->count != 0) {
3503 fr_packet_list_walk(pl, this,
3504 remove_all_requests);
3507 if (this->count == 0) {
3508 this->status = RAD_LISTEN_STATUS_FINISH;
3519 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3520 if (!fr_packet_list_socket_freeze(proxy_list,
3522 radlog(L_ERR, "Fatal error freezing socket: %s",
3528 * Doing this with the proxy mutex held
3529 * is a Bad Thing. We should move to
3530 * finer-grained mutexes.
3532 count = this->count;
3534 fr_packet_list_walk(proxy_list, this,
3535 remove_all_proxied_requests);
3537 count = this->count; /* protected by mutex */
3538 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3541 this->status = RAD_LISTEN_STATUS_FINISH;
3545 #endif /* WITH_PROXY */
3546 #endif /* WITH_TCP */
3549 * Re-open the socket, pointing it to /dev/null.
3550 * This means that all writes proceed without
3551 * blocking, and all reads return "no data".
3553 * This leaves the socket active, so any child
3554 * threads won't go insane. But it means that
3555 * they cannot send or receive any packets.
3557 * This is EXTRA work in the normal case, when
3558 * sockets are closed without error. But it lets
3559 * us have one simple processing method for all
3562 devnull = open("/dev/null", O_RDWR);
3564 radlog(L_ERR, "FATAL failure opening /dev/null: %s",
3568 if (dup2(devnull, this->fd) < 0) {
3569 radlog(L_ERR, "FATAL failure closing socket: %s",
3575 this->status = RAD_LISTEN_STATUS_CLOSED;
3578 * Fall through to the next section.
3584 * Called ONLY from the main thread. On the following
3590 * (and falling through from "forcibly close FD" above)
3591 * client closed connection on us
3592 * client sent us a bad packet.
3594 if (this->status == RAD_LISTEN_STATUS_CLOSED) {
3595 int count = this->count;
3598 rad_assert(this->type != RAD_LISTEN_DETAIL);
3603 * Remove it from the list of active sockets, so
3604 * that it isn't used when proxying new packets.
3606 if (this->type == RAD_LISTEN_PROXY) {
3607 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3608 if (!fr_packet_list_socket_freeze(proxy_list,
3610 radlog(L_ERR, "Fatal error freezing socket: %s",
3614 count = this->count; /* protected by mutex */
3615 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3620 * Requests are still using the socket. Wait for
3624 struct timeval when;
3625 listen_socket_t *sock = this->data;
3628 * Try again to clean up the socket in 30
3631 gettimeofday(&when, NULL);
3634 if (!fr_event_insert(el,
3635 (fr_event_callback_t) event_new_fd,
3636 this, &when, &sock->ev)) {
3637 rad_panic("Failed to insert event");
3644 * No one is using this socket: we can delete it
3647 this->status = RAD_LISTEN_STATUS_FINISH;
3651 if (this->status == RAD_LISTEN_STATUS_FINISH) {
3652 listen_socket_t *sock = this->data;
3654 rad_assert(this->count == 0);
3655 radlog(L_INFO, " ... closing socket %s", buffer);
3658 * Remove it from the list of live FD's. Note
3659 * that it MAY also have been removed above. We
3660 * do it again here, to catch the case of sockets
3661 * closing on idle timeout, or max
3662 * lifetime... AFTER all requests have finished
3665 FD_MUTEX_LOCK(&fd_mutex);
3666 fr_event_fd_delete(el, 0, this->fd);
3667 FD_MUTEX_UNLOCK(&fd_mutex);
3671 * Remove it from the list of sockets to be used
3674 if (this->type == RAD_LISTEN_PROXY) {
3675 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3676 if (!fr_packet_list_socket_remove(proxy_list,
3678 radlog(L_ERR, "Fatal error removing socket: %s",
3682 if (sock->home) sock->home->num_connections--;
3683 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3688 * Remove any pending cleanups.
3690 if (sock->ev) fr_event_delete(el, &sock->ev);
3693 * And finally, close the socket.
3697 #endif /* WITH_TCP */
3702 /***********************************************************************
3706 ***********************************************************************/
3708 static void handle_signal_self(int flag)
3710 if ((flag & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
3711 if ((flag & RADIUS_SIGNAL_SELF_EXIT) != 0) {
3712 radlog(L_INFO, "Signalled to exit");
3713 fr_event_loop_exit(el, 1);
3715 radlog(L_INFO, "Signalled to terminate");
3716 exec_trigger(NULL, NULL, "server.signal.term");
3717 fr_event_loop_exit(el, 2);
3721 } /* else exit/term flags weren't set */
3724 * Tell the even loop to stop processing.
3726 if ((flag & RADIUS_SIGNAL_SELF_HUP) != 0) {
3728 static time_t last_hup = 0;
3731 if ((int) (when - last_hup) < 5) {
3732 radlog(L_INFO, "Ignoring HUP (less than 5s since last one)");
3736 radlog(L_INFO, "Received HUP signal.");
3740 exec_trigger(NULL, NULL, "server.signal.hup");
3741 fr_event_loop_exit(el, 0x80);
3745 if ((flag & RADIUS_SIGNAL_SELF_DETAIL) != 0) {
3749 * FIXME: O(N) loops suck.
3751 for (this = mainconfig.listen;
3753 this = this->next) {
3754 if (this->type != RAD_LISTEN_DETAIL) continue;
3757 * This one didn't send the signal, skip
3760 if (!this->decode(this, NULL)) continue;
3763 * Go service the interrupt.
3765 event_poll_detail(this);
3772 #ifdef HAVE_PTHREAD_H
3774 * Add event handlers for idle timeouts && maximum lifetime.
3776 if ((flag & RADIUS_SIGNAL_SELF_NEW_FD) != 0) {
3777 struct timeval when, now;
3779 fr_event_now(el, &now);
3781 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3783 while (proxy_listener_list) {
3784 rad_listen_t *this = proxy_listener_list;
3785 listen_socket_t *sock = this->data;
3787 rad_assert(sock->proto == IPPROTO_TCP);
3788 proxy_listener_list = this->next;
3791 if (!sock->home) continue; /* skip UDP sockets */
3795 if (!fr_event_insert(el, tcp_socket_timer, this, &when,
3797 rad_panic("Failed to insert event");
3801 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3803 #endif /* HAVE_PTHREAD_H */
3804 #endif /* WITH_PROXY */
3805 #endif /* WITH_TCP */
3808 #ifndef WITH_SELF_PIPE
3809 void radius_signal_self(int flag)
3811 handle_signal_self(flag);
3815 * Inform ourselves that we received a signal.
3817 void radius_signal_self(int flag)
3823 * The read MUST be non-blocking for this to work.
3825 rcode = read(self_pipe[0], buffer, sizeof(buffer));
3829 for (i = 0; i < rcode; i++) {
3830 buffer[0] |= buffer[i];
3838 write(self_pipe[1], buffer, 1);
3842 static void event_signal_handler(UNUSED fr_event_list_t *xel,
3843 UNUSED int fd, UNUSED void *ctx)
3848 rcode = read(self_pipe[0], buffer, sizeof(buffer));
3849 if (rcode <= 0) return;
3852 * Merge pending signals.
3854 for (i = 0; i < rcode; i++) {
3855 buffer[0] |= buffer[i];
3858 handle_signal_self(buffer[0]);
3862 /***********************************************************************
3864 * Bootstrapping code.
3866 ***********************************************************************/
3869 * Externally-visibly functions.
3871 int radius_event_init(CONF_SECTION *cs, int have_children)
3873 rad_listen_t *head = NULL;
3877 time(&fr_start_time);
3879 el = fr_event_list_create(event_status);
3882 pl = fr_packet_list_create(0);
3883 if (!pl) return 0; /* leak el */
3885 request_num_counter = 0;
3888 if (mainconfig.proxy_requests) {
3890 * Create the tree for managing proxied requests and
3893 proxy_list = fr_packet_list_create(1);
3894 if (!proxy_list) return 0;
3896 #ifdef HAVE_PTHREAD_H
3897 if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
3898 radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
3906 #ifdef HAVE_PTHREAD_H
3907 NO_SUCH_CHILD_PID = pthread_self(); /* not a child thread */
3910 * Initialize the threads ONLY if we're spawning, AND
3911 * we're running normally.
3913 if (have_children && !check_config &&
3914 (thread_pool_init(cs, &have_children) < 0)) {
3920 * Move all of the thread calls to this file?
3922 * It may be best for the mutexes to be in this file...
3924 spawn_flag = have_children;
3927 DEBUG("%s: #### Skipping IP addresses and Ports ####",
3929 if (listen_init(cs, &head, spawn_flag) < 0) {
3936 #ifdef WITH_SELF_PIPE
3938 * Child threads need a pipe to signal us, as do the
3941 if (pipe(self_pipe) < 0) {
3942 radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
3946 if (fcntl(self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
3947 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
3951 if (fcntl(self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
3952 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
3957 if (!fr_event_fd_insert(el, 0, self_pipe[0],
3958 event_signal_handler, el)) {
3959 radlog(L_ERR, "Failed creating handler for signals");
3962 #endif /* WITH_SELF_PIPE */
3964 DEBUG("%s: #### Opening IP addresses and Ports ####",
3968 * The server temporarily switches to an unprivileged
3969 * user very early in the bootstrapping process.
3970 * However, some sockets MAY require privileged access
3971 * (bind to device, or to port < 1024, or to raw
3972 * sockets). Those sockets need to call suid up/down
3973 * themselves around the functions that need a privileged
3976 if (listen_init(cs, &head, spawn_flag) < 0) {
3980 mainconfig.listen = head;
3983 * At this point, no one has any business *ever* going
3986 fr_suid_down_permanent();
3992 static int request_hash_cb(UNUSED void *ctx, void *data)
3994 REQUEST *request = fr_packet2myptr(REQUEST, packet, data);
3997 rad_assert(request->in_proxy_hash == FALSE);
4000 request_done(request, FR_ACTION_DONE);
4007 static int proxy_hash_cb(UNUSED void *ctx, void *data)
4009 REQUEST *request = fr_packet2myptr(REQUEST, proxy, data);
4011 request_done(request, FR_ACTION_DONE);
4017 void radius_event_free(void)
4020 * FIXME: Stop all threads, or at least check that
4021 * they're all waiting on the semaphore, and the queues
4027 * There are requests in the proxy hash that aren't
4028 * referenced from anywhere else. Remove them first.
4031 fr_packet_list_walk(proxy_list, NULL, proxy_hash_cb);
4032 fr_packet_list_free(proxy_list);
4037 fr_packet_list_walk(pl, NULL, request_hash_cb);
4039 fr_packet_list_free(pl);
4042 fr_event_list_free(el);
4045 int radius_event_process(void)
4049 return fr_event_loop(el);