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)
85 * @section request_timeline
87 * Time sequence of a request
90 * RQ-----------------P=============================Y-J-C
91 * ::::::::::::::::::::::::::::::::::::::::::::::::::::::::M
94 * - R: received. Duplicate detection is done, and request is
97 * - Q: Request is placed onto a queue for child threads to pick up.
98 * If there are no child threads, the request goes immediately
101 * - P: Processing the request through the modules.
103 * - Y: Reply is ready. Rejects MAY be delayed here. All other
104 * replies are sent immediately.
106 * - J: Reject is sent "reject_delay" after the reply is ready.
108 * - C: For Access-Requests, After "cleanup_delay", the request is
109 * deleted. Accounting-Request packets go directly from Y to C.
111 * - M: Max request time. If the request hits this timer, it is
114 * Other considerations include duplicate and conflicting
115 * packets. When a dupicate packet is received, it is ignored
116 * until we've reached Y, as no response is ready. If the reply
117 * is a reject, duplicates are ignored until J, when we're ready
118 * to send the reply. In between the reply being sent (Y or J),
119 * and C, the server responds to duplicates by sending the cached
122 * Conflicting packets are sent in 2 situations.
124 * The first is in between R and Y. In that case, we consider
125 * it as a hint that we're taking too long, and the NAS has given
126 * up on the request. We then behave just as if the M timer was
127 * reached, and we discard the current request. This allows us
128 * to process the new one.
130 * The second case is when we're at Y, but we haven't yet
131 * finished processing the request. This is a race condition in
132 * the threading code (avoiding locks is faster). It means that
133 * a thread has actually encoded and sent the reply, and that the
134 * NAS has responded with a new packet. The server can then
135 * safely mark the current request as "OK to delete", and behaves
136 * just as if the M timer was reached. This usually happens only
137 * in high-load situations.
139 * Duplicate packets are sent when the NAS thinks we're taking
140 * too long, and wants a reply. From R-Y, duplicates are
141 * ignored. From Y-J (for Access-Rejects), duplicates are also
142 * ignored. From Y-C, duplicates get a duplicate reply. *And*,
143 * they cause the "cleanup_delay" time to be extended. This
144 * extension means that we're more likely to send a duplicate
145 * reply (if we have one), or to suppress processing the packet
146 * twice if we didn't reply to it.
148 * All functions in this file should be thread-safe, and should
149 * assume thet the REQUEST structure is being accessed
150 * simultaneously by the main thread, and by the child worker
151 * threads. This means that timers, etc. cannot be updated in
154 * Instead, the master thread periodically calls request->process
155 * with action TIMER. It's up to the individual functions to
156 * determine how to handle that. They need to check if they're
157 * being called from a child thread or the master, and then do
158 * different things based on that.
163 static fr_packet_list_t *proxy_list = NULL;
166 #ifdef HAVE_PTHREAD_H
168 static pthread_mutex_t proxy_mutex;
169 static rad_listen_t *proxy_listener_list = NULL;
170 static int proxy_no_new_sockets = FALSE;
173 #define PTHREAD_MUTEX_LOCK if (spawn_flag) pthread_mutex_lock
174 #define PTHREAD_MUTEX_UNLOCK if (spawn_flag) pthread_mutex_unlock
176 static pthread_t NO_SUCH_CHILD_PID;
179 * This is easier than ifdef's throughout the code.
181 #define PTHREAD_MUTEX_LOCK(_x)
182 #define PTHREAD_MUTEX_UNLOCK(_x)
186 * We need mutexes around the event FD list *only* in certain
189 #if defined (HAVE_PTHREAD_H) && (defined(WITH_PROXY) || defined(WITH_TCP))
190 static pthread_mutex_t fd_mutex;
191 #define FD_MUTEX_LOCK if (spawn_flag) pthread_mutex_lock
192 #define FD_MUTEX_UNLOCK if (spawn_flag) pthread_mutex_unlock
195 * This is easier than ifdef's throughout the code.
197 #define FD_MUTEX_LOCK(_x)
198 #define FD_MUTEX_UNLOCK(_x)
201 static int request_num_counter = 0;
203 static int request_will_proxy(REQUEST *request);
204 static int request_proxy(REQUEST *request, int retransmit);
205 STATE_MACHINE_DECL(proxy_wait_for_reply);
206 STATE_MACHINE_DECL(proxy_running);
207 static int process_proxy_reply(REQUEST *request);
208 static void remove_from_proxy_hash(REQUEST *request);
209 static int insert_into_proxy_hash(REQUEST *request);
212 STATE_MACHINE_DECL(request_common);
214 #if defined(HAVE_PTHREAD_H) && !defined (NDEBUG)
215 static int we_are_master(void)
218 (pthread_equal(pthread_self(), NO_SUCH_CHILD_PID) == 0)) {
224 #define ASSERT_MASTER if (!we_are_master()) rad_panic("We are not master")
227 #define we_are_master(_x) (1)
228 #define ASSERT_MASTER
231 STATE_MACHINE_DECL(request_reject_delay);
232 STATE_MACHINE_DECL(request_cleanup_delay);
233 STATE_MACHINE_DECL(request_running);
235 static void request_coa_timer(REQUEST *request);
236 static void request_coa_originate(REQUEST *request);
237 STATE_MACHINE_DECL(request_coa_process);
238 static void request_coa_separate(REQUEST *coa);
242 #define USEC (1000000)
244 #define INSERT_EVENT(_function, _ctx) if (!fr_event_insert(el, _function, _ctx, &((_ctx)->when), &((_ctx)->ev))) { _rad_panic(__FILE__, __LINE__, "Failed to insert event"); }
246 static void NEVER_RETURNS _rad_panic(const char *file, unsigned int line,
249 radlog(L_ERR, "[%s:%d] %s", file, line, msg);
253 #define rad_panic(x) _rad_panic(__FILE__, __LINE__, x)
255 static void tv_add(struct timeval *tv, int usec_delay)
257 if (usec_delay >= USEC) {
258 tv->tv_sec += usec_delay / USEC;
261 tv->tv_usec += usec_delay;
263 if (tv->tv_usec >= USEC) {
264 tv->tv_sec += tv->tv_usec / USEC;
270 * In daemon mode, AND this request has debug flags set.
272 #define DEBUG_PACKET if (!debug_flag && request->options && request->radlog) debug_packet
274 static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
278 const char *received, *from;
279 const fr_ipaddr_t *ip;
284 rad_assert(request->radlog != NULL);
286 if (direction == 0) {
287 received = "Received";
288 from = "from"; /* what else? */
289 ip = &packet->src_ipaddr;
290 port = packet->src_port;
293 received = "Sending";
294 from = "to"; /* hah! */
295 ip = &packet->dst_ipaddr;
296 port = packet->dst_port;
300 * Client-specific debugging re-prints the input
301 * packet into the client log.
303 * This really belongs in a utility library
305 if ((packet->code > 0) && (packet->code < FR_MAX_PACKET_CODE)) {
306 RDEBUG("%s %s packet %s host %s port %d, id=%d, length=%d",
307 received, fr_packet_codes[packet->code], from,
308 inet_ntop(ip->af, &ip->ipaddr, buffer, sizeof(buffer)),
309 port, packet->id, packet->data_len);
311 RDEBUG("%s packet %s host %s port %d code=%d, id=%d, length=%d",
313 inet_ntop(ip->af, &ip->ipaddr, buffer, sizeof(buffer)),
315 packet->code, packet->id, packet->data_len);
318 for (vp = packet->vps; vp != NULL; vp = vp->next) {
319 vp_prints(buffer, sizeof(buffer), vp);
320 request->radlog(L_DBG, 0, request, "\t%s", buffer);
325 /***********************************************************************
327 * Start of RADIUS server state machine.
329 ***********************************************************************/
332 * Callback for ALL timer events related to the request.
334 static void request_timer(void *ctx)
336 REQUEST *request = ctx;
337 #ifdef DEBUG_STATE_MACHINE
338 int action = FR_ACTION_TIMER;
343 request->process(request, FR_ACTION_TIMER);
346 #define USEC (1000000)
349 * Only ever called from the master thread.
351 STATE_MACHINE_DECL(request_done)
359 * CoA requests can be cleaned up in the child thread,
360 * but ONLY if they aren't tied into anything.
362 if (request->parent && (request->parent->coa == request)) {
363 rad_assert(request->child_state == REQUEST_DONE);
364 rad_assert(!request->in_request_hash);
365 rad_assert(!request->in_proxy_hash);
366 rad_assert(action == FR_ACTION_DONE);
367 rad_assert(request->packet == NULL);
368 rad_assert(request->ev == NULL);
376 * Mark ourselves as handling the request.
378 request->process = request_done;
379 request->master_state = REQUEST_STOP_PROCESSING;
383 * Move the CoA request to its own handler.
385 if (request->coa) request_coa_separate(request->coa);
388 * If we're the CoA request, make the parent forget about
391 if (request->parent && (request->parent->coa == request)) {
392 request->parent->coa = NULL;
398 * It doesn't hurt to send duplicate replies. All other
399 * signals are ignored, as the request will be cleaned up
404 if (request->reply->code != 0) {
405 request->listener->send(request->listener, request);
411 * This is only called from the master thread
412 * when there is a child thread processing the
415 case FR_ACTION_CONFLICTING:
416 if (request->child_state == REQUEST_DONE) break;
419 * If there's a reply packet, then we presume
420 * that the child has sent the reply, and we get
421 * pinged here before the child has a chance to
424 if (request->reply->data) break;
426 radlog_request(L_ERR, 0, request,
427 "Received conflicting packet from "
428 "client %s port %d - ID: %d due to "
429 "unfinished request. Giving up on old request.",
430 request->client->shortname,
431 request->packet->src_port, request->packet->id);
435 * Called only when there's an error remembering
436 * the packet, or when the socket gets closed from
440 #ifdef HAVE_PTHREAD_H
442 * If we have child threads and we're NOT the
443 * thread handling the request, don't do anything.
446 !pthread_equal(pthread_self(), request->child_pid)) {
450 #ifdef DEBUG_STATE_MACHINE
451 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
453 request->child_state = REQUEST_DONE;
457 * Called when the child is taking too long to
458 * finish. We've already marked it "please
459 * stop", so we don't complain any more.
461 case FR_ACTION_TIMER:
466 * Child is still alive, and we're receiving more
467 * packets from the home server.
469 case FR_ACTION_PROXY_REPLY:
470 request_common(request, action);
475 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
480 * Remove it from the request hash.
482 if (request->in_request_hash) {
483 fr_packet_list_yank(pl, request->packet);
484 request->in_request_hash = FALSE;
486 request_stats_final(request);
489 request->listener->count--;
495 * Wait for the proxy ID to expire. This allows us to
496 * avoid re-use of proxy IDs for a while.
498 if (request->in_proxy_hash) {
501 rad_assert(request->proxy != NULL);
503 fr_event_now(el, &now);
504 when = request->proxy->timestamp;
507 if (((request->proxy->code == PW_COA_REQUEST) ||
508 (request->proxy->code == PW_DISCONNECT_REQUEST)) &&
509 (request->packet->code != request->proxy->code)) {
510 when.tv_sec += request->home_server->coa_mrd;
513 when.tv_sec += request->home_server->response_window;
516 * We haven't received all responses, AND there's still
517 * time to wait. Do so.
519 if ((request->num_proxied_requests > request->num_proxied_responses) &&
521 (request->home_server->proto != IPPROTO_TCP) &&
523 timercmp(&now, &when, <)) {
524 RDEBUG("Waiting for more responses from the home server");
531 remove_from_proxy_hash(request);
535 if (request->child_state != REQUEST_DONE) {
537 #ifdef HAVE_PTHREAD_H
541 rad_assert("Internal sanity check failed");
545 gettimeofday(&now, NULL);
550 #ifdef HAVE_PTHREAD_H
552 (pthread_equal(request->child_pid, NO_SUCH_CHILD_PID) == 0)) {
553 RDEBUG("Waiting for child thread to stop");
556 tv_add(&now, request->delay);
557 request->delay += request->delay >> 1;
558 if (request->delay > (10 * USEC)) request->delay = 10 * USEC;
559 fr_event_insert(el, request_timer, request, &now,
564 #ifdef HAVE_PTHREAD_H
565 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
568 if (request->packet) {
569 RDEBUG2("Cleaning up request packet ID %d with timestamp +%d",
571 (unsigned int) (request->timestamp - fr_start_time));
572 } /* else don't print anything */
574 if (request->ev) fr_event_delete(el, &request->ev);
576 request_free(&request);
580 * Function to do all time-related events.
582 static void request_process_timer(REQUEST *request)
584 struct timeval now, when;
585 rad_assert(request->magic == REQUEST_MAGIC);
586 #ifdef DEBUG_STATE_MACHINE
587 int action = FR_ACTION_TIMER;
595 * If we originated a CoA request, divorce it from the
596 * parent. Then, set up the timers so that we can clean
597 * it up as appropriate.
599 if (request->coa) request_coa_separate(request->coa);
602 * Check request stuff ONLY if we're running the request.
604 if (!request->proxy || (request->packet->code == request->proxy->code))
607 rad_assert(request->listener != NULL);
610 * The socket was closed. Tell the request that
611 * there is no point in continuing.
613 if (request->listener->status != RAD_LISTEN_STATUS_KNOWN) {
614 DEBUG("WARNING: Socket was closed while processing request %u: Stopping it.", request->number);
619 gettimeofday(&now, NULL);
622 * A child thread is still working on the request,
623 * OR it was proxied, and there was no response.
625 if ((request->child_state != REQUEST_DONE) &&
626 (request->master_state != REQUEST_STOP_PROCESSING)) {
627 when = request->packet->timestamp;
628 when.tv_sec += request->root->max_request_time;
631 * Taking too long: tell it to die.
633 if (timercmp(&now, &when, >=)) {
634 #ifdef HAVE_PTHREAD_H
636 * If there's a child thread processing it,
640 (pthread_equal(request->child_pid, NO_SUCH_CHILD_PID) == 0)) {
641 radlog(L_ERR, "WARNING: Unresponsive child for request %u, in component %s module %s",
643 request->component ? request->component : "<server core>",
644 request->module ? request->module : "<server core>");
645 exec_trigger(request, NULL, "server.thread.unresponsive");
650 * Tell the request to stop it.
653 } /* else we're not at max_request_time */
656 if ((request->master_state != REQUEST_STOP_PROCESSING) &&
658 (request->process == request_running)) {
659 #ifdef DEBUG_STATE_MACHINE
660 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_proxied");
662 request->process = proxy_wait_for_reply;
667 * Wake up again in the future, to check for
671 tv_add(&when, request->delay);
672 request->delay += request->delay >> 1;
673 fr_event_insert(el, request_timer, request,
674 &when, &request->ev);
678 #ifdef WITH_ACCOUNTING
679 if (request->reply->code == PW_ACCOUNTING_RESPONSE) {
685 if (!request->proxy || (request->packet->code == request->proxy->code))
688 if ((request->reply->code == PW_AUTHENTICATION_REJECT) &&
689 (request->root->reject_delay)) {
690 when = request->reply->timestamp;
691 when.tv_sec += request->root->reject_delay;
694 * Set timer for when we need to send it.
696 if (timercmp(&when, &now, >)) {
697 #ifdef DEBUG_STATE_MACHINE
698 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_reject_delay");
700 request->process = request_reject_delay;
702 fr_event_insert(el, request_timer, request,
703 &when, &request->ev);
707 if (request->process == request_reject_delay) {
709 * Assume we're at (or near) the reject
712 request->reply->timestamp = now;
714 RDEBUG2("Sending delayed reject");
715 DEBUG_PACKET(request, request->reply, 1);
716 request->process = request_cleanup_delay;
717 request->listener->send(request->listener, request);
722 * The cleanup_delay is zero for accounting packets, and
723 * enforced for all other packets. We do the
724 * cleanup_delay even if we don't respond to the NAS, so
725 * that any retransmit is *not* processed as a new packet.
727 if ((request->packet->code != PW_ACCOUNTING_REQUEST) &&
728 (request->root->cleanup_delay)) {
729 when = request->reply->timestamp;
730 request->delay = request->root->cleanup_delay;
731 when.tv_sec += request->delay;
734 * Set timer for when we need to clean it up.
736 if (timercmp(&when, &now, >)) {
737 #ifdef DEBUG_STATE_MACHINE
738 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_cleanup_delay");
740 request->process = request_cleanup_delay;
742 fr_event_insert(el, request_timer, request,
743 &when, &request->ev);
749 request_done(request, FR_ACTION_DONE);
752 static void request_queue_or_run(UNUSED REQUEST *request,
753 fr_request_process_t process)
756 #ifdef DEBUG_STATE_MACHINE
757 int action = FR_ACTION_TIMER;
763 #ifdef HAVE_PTHREAD_H
764 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
768 * (re) set the initial delay.
770 request->delay = USEC / 3;
771 gettimeofday(&now, NULL);
772 tv_add(&now, request->delay);
773 request->delay += request->delay >> 1;
774 fr_event_insert(el, request_timer, request, &now,
778 * Do this here so that fewer other functions need to do
781 if (request->master_state == REQUEST_STOP_PROCESSING) {
782 #ifdef DEBUG_STATE_MACHINE
783 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
785 request_done(request, FR_ACTION_DONE);
789 request->process = process;
791 #ifdef HAVE_PTHREAD_H
793 if (!request_enqueue(request)) {
794 request_done(request, FR_ACTION_DONE);
801 request->process(request, FR_ACTION_RUN);
805 * Requests that care about child process exit
806 * codes have already either called
807 * rad_waitpid(), or they've given up.
814 STATE_MACHINE_DECL(request_common)
825 if ((request->master_state != REQUEST_STOP_PROCESSING) &&
826 request->proxy && !request->proxy_reply) {
828 * TODO: deal with this in a better way?
830 proxy_wait_for_reply(request, action);
834 radlog(L_ERR, "Discarding duplicate request from "
835 "client %s port %d - ID: %u due to unfinished request %u",
836 request->client->shortname,
837 request->packet->src_port,request->packet->id,
841 case FR_ACTION_CONFLICTING:
843 * We're in the master thread, ask the child to
844 * stop processing the request.
846 request_done(request, action);
849 case FR_ACTION_TIMER:
850 request_process_timer(request);
854 case FR_ACTION_PROXY_REPLY:
855 DEBUG2("Reply from home server %s port %d - ID: %d arrived too late for request %u. Try increasing 'retry_delay' or 'max_request_time'",
856 inet_ntop(request->proxy->src_ipaddr.af,
857 &request->proxy->src_ipaddr.ipaddr,
858 buffer, sizeof(buffer)),
859 request->proxy->dst_port, request->proxy->id,
865 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
870 STATE_MACHINE_DECL(request_cleanup_delay)
879 if (request->reply->code != 0) {
880 request->listener->send(request->listener, request);
884 * Double the cleanup_delay to catch retransmits.
886 when = request->reply->timestamp;
887 request->delay += request->delay ;
888 when.tv_sec += request->delay;
889 fr_event_insert(el, request_timer, request,
890 &when, &request->ev);
894 case FR_ACTION_PROXY_REPLY:
896 case FR_ACTION_CONFLICTING:
897 case FR_ACTION_TIMER:
898 request_common(request, action);
902 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
907 STATE_MACHINE_DECL(request_reject_delay)
914 radlog(L_ERR, "Discarding duplicate request from "
915 "client %s port %d - ID: %u due to delayed reject %u",
916 request->client->shortname,
917 request->packet->src_port,request->packet->id,
922 case FR_ACTION_PROXY_REPLY:
924 case FR_ACTION_CONFLICTING:
925 case FR_ACTION_TIMER:
926 request_common(request, action);
930 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
936 static int request_pre_handler(REQUEST *request, UNUSED int action)
942 if (request->master_state == REQUEST_STOP_PROCESSING) return 0;
945 * Don't decode the packet if it's an internal "fake"
946 * request. Instead, just return so that the caller can
949 if (request->packet->dst_port == 0) {
950 request->username = pairfind(request->packet->vps,
952 request->password = pairfind(request->packet->vps,
953 PW_USER_PASSWORD, 0);
959 * Put the decoded packet into it's proper place.
961 if (request->proxy_reply != NULL) {
962 rcode = request->proxy_listener->decode(request->proxy_listener, request);
963 DEBUG_PACKET(request, request->proxy_reply, 0);
966 * Pro-actively remove it from the proxy hash.
967 * This is later than in 2.1.x, but it means that
968 * the replies are authenticated before being
969 * removed from the hash.
972 (request->num_proxied_requests <= request->num_proxied_responses)) {
973 remove_from_proxy_hash(request);
978 if (request->packet->vps == NULL) {
979 rcode = request->listener->decode(request->listener, request);
982 if (debug_condition) {
984 const char *my_debug = debug_condition;
987 * Ignore parse errors.
989 radius_evaluate_condition(request, RLM_MODULE_OK, 0,
993 request->options = 2;
994 request->radlog = radlog_request;
999 DEBUG_PACKET(request, request->packet, 0);
1005 RDEBUG("Dropping packet without response because of error %s", fr_strerror());
1006 request->reply->offset = -2; /* bad authenticator */
1010 if (!request->username) {
1011 request->username = pairfind(request->packet->vps,
1016 if (action == FR_ACTION_PROXY_REPLY) {
1017 return process_proxy_reply(request);
1024 STATE_MACHINE_DECL(request_finish)
1028 TRACE_STATE_MACHINE;
1030 action = action; /* -Wunused */
1032 if (request->master_state == REQUEST_STOP_PROCESSING) return;
1035 * Don't send replies if there are none to send.
1037 if (!request->in_request_hash) return;
1040 * Catch Auth-Type := Reject BEFORE proxying the packet.
1042 if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1043 (request->reply->code == 0)) {
1044 if (((vp = pairfind(request->config_items, PW_AUTH_TYPE, 0)) != NULL) &&
1045 (vp->vp_integer == PW_AUTHTYPE_REJECT)) {
1046 request->reply->code = PW_AUTHENTICATION_REJECT;
1050 * Check if the lack of response is
1053 vp = pairfind(request->config_items,
1054 PW_RESPONSE_PACKET_TYPE, 0);
1056 RDEBUG2("There was no response configured: rejecting request");
1057 request->reply->code = PW_AUTHENTICATION_REJECT;
1059 } else if (vp->vp_integer == 256) {
1060 RDEBUG2("Not responding to request");
1063 request->reply->code = vp->vp_integer;
1069 * Copy Proxy-State from the request to the reply.
1071 vp = paircopy2(request->packet->vps, PW_PROXY_STATE, 0);
1072 if (vp) pairadd(&request->reply->vps, vp);
1075 * Run rejected packets through
1077 * Post-Auth-Type = Reject
1079 if (request->reply->code == PW_AUTHENTICATION_REJECT) {
1080 pairdelete(&request->config_items, PW_POST_AUTH_TYPE, 0);
1081 vp = radius_pairmake(request, &request->config_items,
1082 "Post-Auth-Type", "Reject",
1084 if (vp) rad_postauth(request);
1088 * Send the reply here.
1090 if ((request->reply->code != PW_AUTHENTICATION_REJECT) ||
1091 (request->root->reject_delay == 0)) {
1092 DEBUG_PACKET(request, request->reply, 1);
1093 request->listener->send(request->listener,
1097 gettimeofday(&request->reply->timestamp, NULL);
1100 * Clean up. These are no longer needed.
1102 pairfree(&request->config_items);
1104 pairfree(&request->packet->vps);
1105 request->username = NULL;
1106 request->password = NULL;
1108 if (request->reply->code != PW_AUTHENTICATION_REJECT) {
1109 pairfree(&request->reply->vps);
1113 if (request->proxy) {
1114 pairfree(&request->proxy->vps);
1116 if (request->proxy_reply) {
1117 pairfree(&request->proxy_reply->vps);
1122 RDEBUG2("Finished request %u.", request->number);
1125 STATE_MACHINE_DECL(request_running)
1127 TRACE_STATE_MACHINE;
1130 case FR_ACTION_CONFLICTING:
1132 case FR_ACTION_TIMER:
1133 request_common(request, action);
1137 case FR_ACTION_PROXY_REPLY:
1138 #ifdef HAVE_PTHREAD_H
1140 * Catch the case of a proxy reply when called
1141 * from the main worker thread.
1143 if (we_are_master() &&
1144 (request->process != proxy_running)) {
1145 request_queue_or_run(request, proxy_running);
1153 if (!request_pre_handler(request, action)) goto done;
1155 rad_assert(request->handle != NULL);
1156 request->handle(request);
1160 * We may need to send a proxied request.
1162 if ((action == FR_ACTION_RUN) &&
1163 request_will_proxy(request)) {
1164 #ifdef DEBUG_STATE_MACHINE
1165 if (debug_flag) printf("(%u) ********\tWill Proxy\t********\n", request->number);
1169 * takes care of setting
1170 * up the post proxy fail
1173 if (request_proxy(request, 0) < 0) goto done;
1177 #ifdef DEBUG_STATE_MACHINE
1178 if (debug_flag) printf("(%u) ********\tFinished\t********\n", request->number);
1183 * Maybe originate a CoA request.
1185 if ((action == FR_ACTION_RUN) && request->coa) {
1186 request_coa_originate(request);
1191 request_finish(request, action);
1193 #ifdef DEBUG_STATE_MACHINE
1194 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
1197 #ifdef HAVE_PTHREAD_H
1198 request->child_pid = NO_SUCH_CHILD_PID;
1200 request->child_state = REQUEST_DONE;
1205 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
1210 int request_receive(rad_listen_t *listener, RADIUS_PACKET *packet,
1211 RADCLIENT *client, RAD_REQUEST_FUNP fun)
1214 RADIUS_PACKET **packet_p;
1215 REQUEST *request = NULL;
1217 listen_socket_t *sock = listener->data;
1220 * Set the last packet received.
1222 gettimeofday(&now, NULL);
1223 sock->last_packet = now.tv_sec;
1225 packet_p = fr_packet_list_find(pl, packet);
1227 request = fr_packet2myptr(REQUEST, packet, packet_p);
1228 rad_assert(request->in_request_hash);
1231 * Same src/dst ip/port, length, and
1232 * authentication vector: must be a duplicate.
1234 if ((request->packet->data_len == packet->data_len) &&
1235 (memcmp(request->packet->vector, packet->vector,
1236 sizeof(packet->vector)) == 0)) {
1239 switch (packet->code) {
1240 case PW_AUTHENTICATION_REQUEST:
1241 FR_STATS_INC(auth, total_dup_requests);
1244 #ifdef WITH_ACCOUNTING
1245 case PW_ACCOUNTING_REQUEST:
1246 FR_STATS_INC(acct, total_dup_requests);
1250 case PW_COA_REQUEST:
1251 FR_STATS_INC(coa, total_dup_requests);
1254 case PW_DISCONNECT_REQUEST:
1255 FR_STATS_INC(dsc, total_dup_requests);
1262 #endif /* WITH_STATS */
1264 request->process(request, FR_ACTION_DUP);
1269 * Say we're ignoring the old one, and continue
1270 * to process the new one.
1272 request->process(request, FR_ACTION_CONFLICTING);
1277 * Quench maximum number of outstanding requests.
1279 if (mainconfig.max_requests &&
1280 ((count = fr_packet_list_num_elements(pl)) > mainconfig.max_requests)) {
1281 static time_t last_complained = 0;
1283 radlog(L_ERR, "Dropping request (%d is too many): from client %s port %d - ID: %d", count,
1285 packet->src_port, packet->id);
1286 radlog(L_INFO, "WARNING: Please check the configuration file.\n"
1287 "\tThe value for 'max_requests' is probably set too low.\n");
1290 * Complain once every 10 seconds.
1292 if ((last_complained + 10) < now.tv_sec) {
1293 last_complained = now.tv_sec;
1294 exec_trigger(NULL, NULL, "server.max_requests");
1300 return request_insert(listener, packet, client, fun, &now);
1303 int request_insert(rad_listen_t *listener, RADIUS_PACKET *packet,
1304 RADCLIENT *client, RAD_REQUEST_FUNP fun,
1305 struct timeval *pnow)
1310 * Create and initialize the new request.
1312 request = request_alloc(); /* never fails */
1314 if ((request->reply = rad_alloc(0)) == NULL) {
1315 radlog(L_ERR, "No memory");
1316 request_free(&request);
1320 request->listener = listener;
1321 request->client = client;
1322 request->packet = packet;
1323 request->packet->timestamp = *pnow;
1324 request->number = request_num_counter++;
1325 request->priority = listener->type;
1326 request->master_state = REQUEST_ACTIVE;
1327 #ifdef DEBUG_STATE_MACHINE
1328 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_ACTIVE);
1330 request->child_state = REQUEST_ACTIVE;
1331 request->handle = fun;
1332 request->options = RAD_REQUEST_OPTION_DEBUG2;
1333 #ifdef HAVE_PTHREAD_H
1334 request->child_pid = NO_SUCH_CHILD_PID;
1338 request->listener->stats.last_packet = request->packet->timestamp.tv_sec;
1339 if (packet->code == PW_AUTHENTICATION_REQUEST) {
1340 request->client->auth.last_packet = request->packet->timestamp.tv_sec;
1341 radius_auth_stats.last_packet = request->packet->timestamp.tv_sec;
1342 #ifdef WITH_ACCOUNTING
1343 } else if (packet->code == PW_ACCOUNTING_REQUEST) {
1344 request->client->acct.last_packet = request->packet->timestamp.tv_sec;
1345 radius_acct_stats.last_packet = request->packet->timestamp.tv_sec;
1348 #endif /* WITH_STATS */
1351 * Status-Server packets go to the head of the queue.
1353 if (request->packet->code == PW_STATUS_SERVER) request->priority = 0;
1356 * Set virtual server identity
1358 if (client->server) {
1359 request->server = client->server;
1360 } else if (listener->server) {
1361 request->server = listener->server;
1363 request->server = NULL;
1367 * Remember the request in the list.
1369 if (!fr_packet_list_insert(pl, &request->packet)) {
1370 radlog_request(L_ERR, 0, request, "Failed to insert request in the list of live requests: discarding it");
1371 request_done(request, FR_ACTION_DONE);
1375 request->in_request_hash = TRUE;
1376 request->root = &mainconfig;
1377 mainconfig.refcount++;
1379 request->listener->count++;
1383 * The request passes many of our sanity checks.
1384 * From here on in, if anything goes wrong, we
1385 * send a reject message, instead of dropping the
1390 * Build the reply template from the request.
1393 request->reply->sockfd = request->packet->sockfd;
1394 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1395 request->reply->src_ipaddr = request->packet->dst_ipaddr;
1396 request->reply->dst_port = request->packet->src_port;
1397 request->reply->src_port = request->packet->dst_port;
1398 request->reply->id = request->packet->id;
1399 request->reply->code = 0; /* UNKNOWN code */
1400 memcpy(request->reply->vector, request->packet->vector,
1401 sizeof(request->reply->vector));
1402 request->reply->vps = NULL;
1403 request->reply->data = NULL;
1404 request->reply->data_len = 0;
1406 request_queue_or_run(request, request_running);
1413 /***********************************************************************
1417 ***********************************************************************/
1420 * Timer function for all TCP sockets.
1422 static void tcp_socket_timer(void *ctx)
1424 rad_listen_t *listener = ctx;
1425 listen_socket_t *sock = listener->data;
1426 struct timeval end, now;
1429 fr_event_now(el, &now);
1432 * If we enforce a lifetime, do it now.
1434 if (sock->home->lifetime) {
1435 end.tv_sec = sock->opened + sock->home->lifetime;
1438 if (timercmp(&end, &now, <=)) {
1439 listener->print(listener, buffer, sizeof(buffer));
1440 DEBUG("Reached maximum lifetime on socket %s", buffer);
1444 listener->status = RAD_LISTEN_STATUS_CLOSED;
1445 event_new_fd(listener);
1454 * Enforce an idle timeout.
1456 if (sock->home->idle_timeout > 0) {
1457 struct timeval idle;
1459 idle.tv_sec = sock->last_packet + sock->home->idle_timeout;
1462 if (timercmp(&idle, &now, <=)) {
1463 listener->print(listener, buffer, sizeof(buffer));
1464 DEBUG("Reached idle timeout on socket %s", buffer);
1469 * Enforce the minimum of idle timeout or lifetime.
1471 if (timercmp(&idle, &end, <)) {
1477 * Wake up at t + 0.5s. The code above checks if the timers
1478 * are <= t. This addition gives us a bit of leeway.
1480 end.tv_usec = USEC / 2;
1482 if (!fr_event_insert(el, tcp_socket_timer, listener, &end, &sock->ev)) {
1483 rad_panic("Failed to insert event");
1489 * Add +/- 2s of jitter, as suggested in RFC 3539
1492 static void add_jitter(struct timeval *when)
1499 jitter ^= (jitter >> 10);
1500 jitter &= ((1 << 22) - 1); /* 22 bits of 1 */
1503 * Add in ~ (4 * USEC) of jitter.
1505 tv_add(when, jitter);
1509 static int remove_all_proxied_requests(void *ctx, void *data)
1511 rad_listen_t *this = ctx;
1512 RADIUS_PACKET **proxy_p = data;
1515 request = fr_packet2myptr(REQUEST, proxy, proxy_p);
1516 if (request->proxy->sockfd != this->fd) return 0;
1519 * FIXME: Force replies==requests, so that we can delete
1520 * the packet immediately.
1523 request_done(request, FR_ACTION_DONE);
1526 #endif /* WITH_PROXY */
1528 static int remove_all_requests(void *ctx, void *data)
1530 rad_listen_t *this = ctx;
1531 RADIUS_PACKET **packet_p = data;
1534 request = fr_packet2myptr(REQUEST, packet, packet_p);
1535 if (request->packet->sockfd != this->fd) return 0;
1537 request_done(request, FR_ACTION_DONE);
1540 #endif /* WITH_TCP */
1543 /***********************************************************************
1545 * Proxy handlers for the state machine.
1547 ***********************************************************************/
1549 static void remove_from_proxy_hash(REQUEST *request)
1552 * Check this without grabbing the mutex because it's a
1553 * lot faster that way.
1555 if (!request->in_proxy_hash) return;
1558 * The "not in hash" flag is definitive. However, if the
1559 * flag says that it IS in the hash, there might still be
1560 * a race condition where it isn't.
1562 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1564 if (!request->in_proxy_hash) {
1565 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1569 fr_packet_list_yank(proxy_list, request->proxy);
1570 fr_packet_list_id_free(proxy_list, request->proxy);
1573 * On the FIRST reply, decrement the count of outstanding
1574 * requests. Note that this is NOT the count of sent
1575 * packets, but whether or not the home server has
1578 if (!request->proxy_reply &&
1579 request->home_server &&
1580 request->home_server->currently_outstanding) {
1581 request->home_server->currently_outstanding--;
1585 request->proxy_listener->count--;
1587 request->proxy_listener = NULL;
1590 * Got from YES in hash, to NO, not in hash while we hold
1591 * the mutex. This guarantees that when another thread
1592 * grabs the mutex, the "not in hash" flag is correct.
1594 request->in_proxy_hash = FALSE;
1596 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1599 static int insert_into_proxy_hash(REQUEST *request)
1603 void *proxy_listener;
1605 rad_assert(request->proxy != NULL);
1606 rad_assert(proxy_list != NULL);
1610 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1611 rcode = fr_packet_list_id_alloc(proxy_list,
1612 request->home_server->proto,
1613 request->proxy, &proxy_listener);
1614 request->num_proxied_requests = 1;
1615 request->num_proxied_responses = 0;
1616 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1619 if (proxy_no_new_sockets) return 0;
1622 * Also locks the proxy mutex, so we have to call
1623 * it with the mutex unlocked. Some systems
1624 * don't support recursive mutexes.
1626 if (!proxy_new_listener(request->home_server, 0)) {
1627 radlog(L_ERR, "Failed to create a new socket for proxying requests.");
1630 request->proxy->src_port = 0; /* Use any new socket */
1634 RDEBUG2("ERROR: Failed allocating Id for new socket when proxying requests.");
1641 request->proxy_listener = proxy_listener;
1643 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1644 if (!fr_packet_list_insert(proxy_list, &request->proxy)) {
1645 fr_packet_list_id_free(proxy_list, request->proxy);
1646 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1647 radlog_request(L_PROXY, 0, request, "Failed to insert entry into proxy list.");
1651 request->in_proxy_hash = TRUE;
1654 * Keep track of maximum outstanding requests to a
1655 * particular home server. 'max_outstanding' is
1656 * enforced in home_server_ldb(), in realms.c.
1658 if (request->home_server) {
1659 request->home_server->currently_outstanding++;
1663 request->proxy_listener->count++;
1666 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1668 RDEBUG3(" proxy: allocating destination %s port %d - Id %d",
1669 inet_ntop(request->proxy->dst_ipaddr.af,
1670 &request->proxy->dst_ipaddr.ipaddr, buf, sizeof(buf)),
1671 request->proxy->dst_port,
1672 request->proxy->id);
1677 static int process_proxy_reply(REQUEST *request)
1680 int post_proxy_type = 0;
1684 * Delete any reply we had accumulated until now.
1686 pairfree(&request->reply->vps);
1689 * Run the packet through the post-proxy stage,
1690 * BEFORE playing games with the attributes.
1692 vp = pairfind(request->config_items, PW_POST_PROXY_TYPE, 0);
1694 RDEBUG2(" Found Post-Proxy-Type %s", vp->vp_strvalue);
1695 post_proxy_type = vp->vp_integer;
1698 if (request->home_pool && request->home_pool->virtual_server) {
1699 const char *old_server = request->server;
1701 request->server = request->home_pool->virtual_server;
1702 RDEBUG2(" server %s {", request->server);
1703 rcode = module_post_proxy(post_proxy_type, request);
1705 request->server = old_server;
1707 rcode = module_post_proxy(post_proxy_type, request);
1711 if (request->packet->code == request->proxy->code)
1713 * Don't run the next bit if we originated a CoA
1714 * packet, after receiving an Access-Request or
1715 * Accounting-Request.
1720 * There may NOT be a proxy reply, as we may be
1721 * running Post-Proxy-Type = Fail.
1723 if (request->proxy_reply) {
1725 * Delete the Proxy-State Attributes from
1726 * the reply. These include Proxy-State
1727 * attributes from us and remote server.
1729 pairdelete(&request->proxy_reply->vps, PW_PROXY_STATE, 0);
1732 * Add the attributes left in the proxy
1733 * reply to the reply list.
1735 pairadd(&request->reply->vps, request->proxy_reply->vps);
1736 request->proxy_reply->vps = NULL;
1739 * Free proxy request pairs.
1741 pairfree(&request->proxy->vps);
1745 default: /* Don't do anything */
1747 case RLM_MODULE_FAIL:
1750 case RLM_MODULE_HANDLED:
1757 int request_proxy_reply(RADIUS_PACKET *packet)
1759 RADIUS_PACKET **proxy_p;
1764 PTHREAD_MUTEX_LOCK(&proxy_mutex);
1765 proxy_p = fr_packet_list_find_byreply(proxy_list, packet);
1768 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1769 radlog(L_PROXY, "No outstanding request was found for reply from host %s port %d - ID %d",
1770 inet_ntop(packet->src_ipaddr.af,
1771 &packet->src_ipaddr.ipaddr,
1772 buffer, sizeof(buffer)),
1773 packet->src_port, packet->id);
1777 request = fr_packet2myptr(REQUEST, proxy, proxy_p);
1778 request->num_proxied_responses++; /* needs to be protected by lock */
1780 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
1783 * No reply, BUT the current packet fails verification:
1784 * ignore it. This does the MD5 calculations in the
1785 * server core, but I guess we can fix that later.
1787 if (!request->proxy_reply &&
1788 (rad_verify(packet, request->proxy,
1789 request->home_server->secret) != 0)) {
1790 DEBUG("Ignoring spoofed proxy reply. Signature is invalid");
1795 * The home server sent us a packet which doesn't match
1796 * something we have: ignore it. This is done only to
1797 * catch the case of broken systems.
1799 if (request->proxy_reply &&
1800 (memcmp(request->proxy_reply->vector,
1802 sizeof(request->proxy_reply->vector)) != 0)) {
1803 RDEBUG2("Ignoring conflicting proxy reply");
1807 gettimeofday(&now, NULL);
1810 * Status-Server packets don't count as real packets.
1812 if (request->proxy->code != PW_STATUS_SERVER) {
1813 listen_socket_t *sock = request->proxy_listener->data;
1815 request->home_server->last_packet = now.tv_sec;
1816 sock->last_packet = now.tv_sec;
1820 * If we have previously seen a reply, ignore the
1823 if (request->proxy_reply) {
1824 RDEBUG2("Discarding duplicate reply from host %s port %d - ID: %d",
1825 inet_ntop(packet->src_ipaddr.af,
1826 &packet->src_ipaddr.ipaddr,
1827 buffer, sizeof(buffer)),
1828 packet->src_port, packet->id);
1833 * Call the state machine to do something useful with the
1836 request->proxy_reply = packet;
1837 packet->timestamp = now;
1838 request->priority = RAD_LISTEN_PROXY;
1841 request->home_server->stats.last_packet = packet->timestamp.tv_sec;
1842 request->proxy_listener->stats.last_packet = packet->timestamp.tv_sec;
1844 if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
1845 proxy_auth_stats.last_packet = packet->timestamp.tv_sec;
1846 #ifdef WITH_ACCOUNTING
1847 } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
1848 proxy_acct_stats.last_packet = packet->timestamp.tv_sec;
1851 #endif /* WITH_STATS */
1855 * When we originate CoA requests, we patch them in here
1856 * so that they don't affect the rest of the state
1859 if (request->parent) {
1860 rad_assert(request->parent->coa == request);
1861 rad_assert((request->proxy->code == PW_COA_REQUEST) ||
1862 (request->proxy->code == PW_DISCONNECT_REQUEST));
1863 rad_assert(request->process != NULL);
1864 request_coa_separate(request);
1868 request->process(request, FR_ACTION_PROXY_REPLY);
1874 static int setup_post_proxy_fail(REQUEST *request)
1876 const DICT_VALUE *dval = NULL;
1879 if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
1880 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0,
1881 "Fail-Authentication");
1883 } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
1884 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0,
1887 } else if (request->proxy->code == PW_COA_REQUEST) {
1888 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail-CoA");
1890 } else if (request->proxy->code == PW_DISCONNECT_REQUEST) {
1891 dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail-Disconnect");
1894 DEBUG("WARNING: Unknown packet type in Post-Proxy-Type Fail: ignoring");
1898 if (!dval) dval = dict_valbyname(PW_POST_PROXY_TYPE, 0, "Fail");
1901 DEBUG("No Post-Proxy-Type Fail: ignoring");
1902 pairdelete(&request->config_items, PW_POST_PROXY_TYPE, 0);
1906 vp = pairfind(request->config_items, PW_POST_PROXY_TYPE, 0);
1907 if (!vp) vp = radius_paircreate(request, &request->config_items,
1908 PW_POST_PROXY_TYPE, 0, PW_TYPE_INTEGER);
1909 vp->vp_integer = dval->value;
1914 STATE_MACHINE_DECL(proxy_running)
1916 TRACE_STATE_MACHINE;
1919 case FR_ACTION_CONFLICTING:
1921 case FR_ACTION_TIMER:
1922 case FR_ACTION_PROXY_REPLY:
1923 request_common(request, action);
1927 request_running(request, FR_ACTION_PROXY_REPLY);
1931 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
1936 STATE_MACHINE_DECL(request_virtual_server)
1938 TRACE_STATE_MACHINE;
1941 case FR_ACTION_CONFLICTING:
1943 case FR_ACTION_TIMER:
1944 case FR_ACTION_PROXY_REPLY:
1945 request_common(request, action);
1949 request_running(request, action);
1953 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
1959 static int request_will_proxy(REQUEST *request)
1961 int rcode, pre_proxy_type = 0;
1962 const char *realmname = NULL;
1963 VALUE_PAIR *vp, *strippedname;
1965 REALM *realm = NULL;
1966 home_pool_t *pool = NULL;
1968 if (!request->root->proxy_requests) return 0;
1969 if (request->packet->dst_port == 0) return 0;
1970 if (request->packet->code == PW_STATUS_SERVER) return 0;
1971 if (request->in_proxy_hash) return 0;
1974 * FIXME: for 3.0, allow this only for rejects?
1976 if (request->reply->code != 0) return 0;
1978 vp = pairfind(request->config_items, PW_PROXY_TO_REALM, 0);
1980 realm = realm_find2(vp->vp_strvalue);
1982 RDEBUG2("ERROR: Cannot proxy to unknown realm %s",
1987 realmname = vp->vp_strvalue;
1990 * Figure out which pool to use.
1992 if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
1993 pool = realm->auth_pool;
1995 #ifdef WITH_ACCOUNTING
1996 } else if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1997 pool = realm->acct_pool;
2001 } else if ((request->packet->code == PW_COA_REQUEST) ||
2002 (request->packet->code == PW_DISCONNECT_REQUEST)) {
2004 * FIXME: This is likely wrong. We don't
2005 * want to set Proxy-To-Realm for CoA
2006 * packets. OR, we have a CoA pool
2007 * specifically for them.
2009 pool = realm->acct_pool;
2019 vp = pairfind(request->config_items, PW_HOME_SERVER_POOL, 0);
2022 switch (request->packet->code) {
2023 case PW_AUTHENTICATION_REQUEST:
2024 pool_type = HOME_TYPE_AUTH;
2027 #ifdef WITH_ACCOUNTING
2028 case PW_ACCOUNTING_REQUEST:
2029 pool_type = HOME_TYPE_ACCT;
2034 case PW_COA_REQUEST:
2035 case PW_DISCONNECT_REQUEST:
2036 pool_type = HOME_TYPE_COA;
2044 pool = home_pool_byname(vp->vp_strvalue, pool_type);
2048 RDEBUG2(" WARNING: Cancelling proxy as no home pool exists");
2052 request->home_pool = pool;
2054 home = home_server_ldb(realmname, pool, request);
2056 RDEBUG2("ERROR: Failed to find live home server: Cancelling proxy");
2062 * Once we've decided to proxy a request, we cannot send
2063 * a CoA packet. So we free up any CoA packet here.
2065 if (request->coa) request_done(request->coa, FR_ACTION_DONE);
2069 * Remember that we sent the request to a Realm.
2071 if (realmname) pairadd(&request->packet->vps,
2072 pairmake("Realm", realmname, T_OP_EQ));
2075 * Strip the name, if told to.
2077 * Doing it here catches the case of proxied tunneled
2080 if (realm && (realm->striprealm == TRUE) &&
2081 (strippedname = pairfind(request->proxy->vps, PW_STRIPPED_USER_NAME, 0)) != NULL) {
2083 * If there's a Stripped-User-Name attribute in
2084 * the request, then use THAT as the User-Name
2085 * for the proxied request, instead of the
2088 * This is done by making a copy of the
2089 * Stripped-User-Name attribute, turning it into
2090 * a User-Name attribute, deleting the
2091 * Stripped-User-Name and User-Name attributes
2092 * from the vps list, and making the new
2093 * User-Name the head of the vps list.
2095 vp = pairfind(request->proxy->vps, PW_USER_NAME, 0);
2097 vp = radius_paircreate(request, NULL,
2098 PW_USER_NAME, 0, PW_TYPE_STRING);
2099 rad_assert(vp != NULL); /* handled by above function */
2100 /* Insert at the START of the list */
2101 vp->next = request->proxy->vps;
2102 request->proxy->vps = vp;
2104 memcpy(vp->vp_strvalue, strippedname->vp_strvalue,
2105 sizeof(vp->vp_strvalue));
2106 vp->length = strippedname->length;
2109 * Do NOT delete Stripped-User-Name.
2114 * If there is no PW_CHAP_CHALLENGE attribute but
2115 * there is a PW_CHAP_PASSWORD we need to add it
2116 * since we can't use the request authenticator
2117 * anymore - we changed it.
2119 if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
2120 pairfind(request->proxy->vps, PW_CHAP_PASSWORD, 0) &&
2121 pairfind(request->proxy->vps, PW_CHAP_CHALLENGE, 0) == NULL) {
2122 vp = radius_paircreate(request, &request->proxy->vps,
2123 PW_CHAP_CHALLENGE, 0, PW_TYPE_OCTETS);
2124 memcpy(vp->vp_strvalue, request->packet->vector,
2125 sizeof(request->packet->vector));
2126 vp->length = sizeof(request->packet->vector);
2130 * The RFC's say we have to do this, but FreeRADIUS
2133 vp = radius_paircreate(request, &request->proxy->vps,
2134 PW_PROXY_STATE, 0, PW_TYPE_OCTETS);
2135 snprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue), "%d",
2136 request->packet->id);
2137 vp->length = strlen(vp->vp_strvalue);
2140 * Should be done BEFORE inserting into proxy hash, as
2141 * pre-proxy may use this information, or change it.
2143 request->proxy->code = request->packet->code;
2146 * Call the pre-proxy routines.
2148 vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE, 0);
2150 RDEBUG2(" Found Pre-Proxy-Type %s", vp->vp_strvalue);
2151 pre_proxy_type = vp->vp_integer;
2154 rad_assert(request->home_pool != NULL);
2156 if (request->home_pool->virtual_server) {
2157 const char *old_server = request->server;
2159 request->server = request->home_pool->virtual_server;
2160 RDEBUG2(" server %s {", request->server);
2161 rcode = module_pre_proxy(pre_proxy_type, request);
2163 request->server = old_server;
2165 rcode = module_pre_proxy(pre_proxy_type, request);
2168 case RLM_MODULE_FAIL:
2169 case RLM_MODULE_INVALID:
2170 case RLM_MODULE_NOTFOUND:
2171 case RLM_MODULE_USERLOCK:
2173 /* FIXME: debug print failed stuff */
2176 case RLM_MODULE_REJECT:
2177 case RLM_MODULE_HANDLED:
2181 * Only proxy the packet if the pre-proxy code succeeded.
2183 case RLM_MODULE_NOOP:
2185 case RLM_MODULE_UPDATED:
2192 static int request_proxy(REQUEST *request, int retransmit)
2196 rad_assert(request->parent == NULL);
2197 rad_assert(request->home_server != NULL);
2199 if (request->master_state == REQUEST_STOP_PROCESSING) return 0;
2203 RDEBUG("WARNING: Cannot proxy and originate CoA packets at the same time. Cancelling CoA request");
2204 request_done(request->coa, FR_ACTION_DONE);
2209 * The request may be sent to a virtual server. If we're
2210 * in a child thread, just process it here. If we're the
2211 * master, push it back onto the queue for later
2214 if (request->home_server->server) {
2215 DEBUG("Proxying to virtual server %s",
2216 request->home_server->server);
2218 if (!we_are_master()) {
2219 request_virtual_server(request, FR_ACTION_RUN);
2220 #ifdef HAVE_PTHREAD_H
2221 request->child_pid = NO_SUCH_CHILD_PID;
2226 request_queue_or_run(request, request_virtual_server);
2231 * We're actually sending a proxied packet. Do that now.
2233 if (!insert_into_proxy_hash(request)) {
2234 radlog_request(L_PROXY, 0, request, "Failed to insert initial packet into the proxy list.");
2238 request->proxy_listener->encode(request->proxy_listener, request);
2240 RDEBUG2("Proxying request to home server %s port %d",
2241 inet_ntop(request->proxy->dst_ipaddr.af,
2242 &request->proxy->dst_ipaddr.ipaddr,
2243 buffer, sizeof(buffer)),
2244 request->proxy->dst_port);
2246 DEBUG_PACKET(request, request->proxy, 1);
2248 gettimeofday(&request->proxy_retransmit, NULL);
2249 if (!retransmit) request->proxy->timestamp = request->proxy_retransmit;
2251 #ifdef HAVE_PTHREAD_H
2252 request->child_pid = NO_SUCH_CHILD_PID;
2254 request->proxy_listener->send(request->proxy_listener,
2260 * Proxy the packet as if it was new.
2262 static int request_proxy_anew(REQUEST *request)
2265 * Keep a copy of the old Id so that the
2266 * re-transmitted request doesn't re-use the old
2269 RADIUS_PACKET old = *request->proxy;
2271 home_server *old_home = request->home_server;
2273 rad_listen_t *listener = request->proxy_listener;
2276 rad_assert(old_home != NULL);
2279 * Find a live home server for the request.
2281 home = home_server_ldb(NULL, request->home_pool, request);
2283 RDEBUG2("ERROR: Failed to find live home server for request");
2285 remove_from_proxy_hash(request);
2287 if (!setup_post_proxy_fail(request)) {
2291 request_queue_or_run(request, proxy_running);
2296 * Don't free the old Id on error.
2298 if (!insert_into_proxy_hash(request)) {
2299 radlog_request(L_PROXY, 0, request, "Failed to insert retransmission into the proxy list.");
2300 goto post_proxy_fail;
2304 * Now that we have a new Id, free the old one
2305 * and update the various statistics.
2307 PTHREAD_MUTEX_LOCK(&proxy_mutex);
2308 fr_packet_list_yank(proxy_list, &old);
2309 fr_packet_list_id_free(proxy_list, &old);
2310 old_home->currently_outstanding--;
2312 if (listener) listener->count--;
2314 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
2317 * Free the old packet, to force re-encoding
2319 free(request->proxy->data);
2320 request->proxy->data = NULL;
2321 request->proxy->data_len = 0;
2323 #ifdef WITH_ACCOUNTING
2325 * Update the Acct-Delay-Time attribute.
2327 if (request->packet->code == PW_ACCOUNTING_REQUEST) {
2330 vp = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME, 0);
2331 if (!vp) vp = radius_paircreate(request,
2332 &request->proxy->vps,
2333 PW_ACCT_DELAY_TIME, 0,
2338 gettimeofday(&now, NULL);
2339 vp->vp_integer += now.tv_sec - request->proxy_retransmit.tv_sec;
2344 if (request_proxy(request, 1) != 1) goto post_proxy_fail;
2349 STATE_MACHINE_DECL(request_ping)
2351 home_server *home = request->home_server;
2354 TRACE_STATE_MACHINE;
2358 case FR_ACTION_TIMER:
2359 radlog(L_ERR, "No response to status check %d for home server %s port %d",
2361 inet_ntop(request->proxy->dst_ipaddr.af,
2362 &request->proxy->dst_ipaddr.ipaddr,
2363 buffer, sizeof(buffer)),
2364 request->proxy->dst_port);
2367 case FR_ACTION_PROXY_REPLY:
2368 rad_assert(request->in_proxy_hash);
2370 request->home_server->num_received_pings++;
2371 radlog_request(L_PROXY, 0, request, "Received response to status check %d (%d in current sequence)",
2372 request->number, home->num_received_pings);
2375 * Remove the request from any hashes
2377 fr_event_delete(el, &request->ev);
2378 remove_from_proxy_hash(request);
2381 * The control socket may have marked the home server as
2382 * alive. OR, it may have suddenly started responding to
2383 * requests again. If so, don't re-do the "make alive"
2386 if (home->state == HOME_STATE_ALIVE) break;
2389 * We haven't received enough ping responses to mark it
2390 * "alive". Wait a bit.
2392 if (home->num_received_pings < home->num_pings_to_alive) {
2397 * Mark it alive and delete any outstanding
2400 home->state = HOME_STATE_ALIVE;
2401 exec_trigger(request, request->home_server->cs, "home_server.alive");
2402 home->currently_outstanding = 0;
2403 home->num_sent_pings = 0;
2404 home->num_received_pings = 0;
2405 gettimeofday(&home->revive_time, NULL);
2407 fr_event_delete(el, &home->ev);
2409 radlog_request(L_PROXY, 0, request, "Marking home server %s port %d alive",
2410 inet_ntop(request->proxy->dst_ipaddr.af,
2411 &request->proxy->dst_ipaddr.ipaddr,
2412 buffer, sizeof(buffer)),
2413 request->proxy->dst_port);
2417 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
2421 rad_assert(!request->in_request_hash);
2422 rad_assert(request->ev == NULL);
2423 request_done(request, FR_ACTION_DONE);
2427 * Called from start of zombie period, OR after control socket
2428 * marks the home server dead.
2430 static void ping_home_server(void *ctx)
2432 home_server *home = ctx;
2435 struct timeval when, now;
2437 if ((home->state == HOME_STATE_ALIVE) ||
2438 (home->ping_check == HOME_PING_CHECK_NONE) ||
2440 (home->proto == IPPROTO_TCP) ||
2442 (home->ev != NULL)) {
2446 gettimeofday(&now, NULL);
2448 if (home->state == HOME_STATE_ZOMBIE) {
2449 when = home->zombie_period_start;
2450 when.tv_sec += home->zombie_period;
2452 if (timercmp(&when, &now, <)) {
2453 DEBUG("PING: Zombie period is over for home server %s",
2455 mark_home_server_dead(home, &now);
2459 request = request_alloc();
2460 request->number = request_num_counter++;
2461 #ifdef HAVE_PTHREAD_H
2462 request->child_pid = NO_SUCH_CHILD_PID;
2465 request->proxy = rad_alloc(1);
2466 rad_assert(request->proxy != NULL);
2468 if (home->ping_check == HOME_PING_CHECK_STATUS_SERVER) {
2469 request->proxy->code = PW_STATUS_SERVER;
2471 radius_pairmake(request, &request->proxy->vps,
2472 "Message-Authenticator", "0x00", T_OP_SET);
2474 } else if (home->type == HOME_TYPE_AUTH) {
2475 request->proxy->code = PW_AUTHENTICATION_REQUEST;
2477 radius_pairmake(request, &request->proxy->vps,
2478 "User-Name", home->ping_user_name, T_OP_SET);
2479 radius_pairmake(request, &request->proxy->vps,
2480 "User-Password", home->ping_user_password, T_OP_SET);
2481 radius_pairmake(request, &request->proxy->vps,
2482 "Service-Type", "Authenticate-Only", T_OP_SET);
2483 radius_pairmake(request, &request->proxy->vps,
2484 "Message-Authenticator", "0x00", T_OP_SET);
2487 #ifdef WITH_ACCOUNTING
2488 request->proxy->code = PW_ACCOUNTING_REQUEST;
2490 radius_pairmake(request, &request->proxy->vps,
2491 "User-Name", home->ping_user_name, T_OP_SET);
2492 radius_pairmake(request, &request->proxy->vps,
2493 "Acct-Status-Type", "Stop", T_OP_SET);
2494 radius_pairmake(request, &request->proxy->vps,
2495 "Acct-Session-Id", "00000000", T_OP_SET);
2496 vp = radius_pairmake(request, &request->proxy->vps,
2497 "Event-Timestamp", "0", T_OP_SET);
2498 vp->vp_date = now.tv_sec;
2500 rad_assert("Internal sanity check failed");
2504 vp = radius_pairmake(request, &request->proxy->vps,
2505 "NAS-Identifier", "", T_OP_SET);
2507 snprintf(vp->vp_strvalue, sizeof(vp->vp_strvalue),
2508 "Status Check %u. Are you alive?",
2509 home->num_sent_pings);
2510 vp->length = strlen(vp->vp_strvalue);
2513 request->proxy->dst_ipaddr = home->ipaddr;
2514 request->proxy->dst_port = home->port;
2515 request->home_server = home;
2516 #ifdef DEBUG_STATE_MACHINE
2517 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
2518 if (debug_flag) printf("(%u) ********\tNEXT-STATE %s -> %s\n", request->number, __FUNCTION__, "request_ping");
2520 #ifdef HAVE_PTHREAD_H
2521 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
2523 request->child_state = REQUEST_DONE;
2524 request->process = request_ping;
2526 rad_assert(request->proxy_listener == NULL);
2528 if (!insert_into_proxy_hash(request)) {
2529 radlog_request(L_PROXY, 0, request, "Failed to insert status check %d into proxy list. Discarding it.",
2532 rad_assert(!request->in_request_hash);
2533 rad_assert(!request->in_proxy_hash);
2534 rad_assert(request->ev == NULL);
2535 request_free(&request);
2540 * Set up the timer callback.
2543 when.tv_sec += home->ping_timeout;
2545 DEBUG("PING: Waiting %u seconds for response to ping",
2546 home->ping_timeout);
2547 fr_event_insert(el, request_timer, request, &when,
2549 home->num_sent_pings++;
2551 rad_assert(request->proxy_listener != NULL);
2552 request->proxy_listener->send(request->proxy_listener,
2556 * Add +/- 2s of jitter, as suggested in RFC 3539
2557 * and in the Issues and Fixes draft.
2560 home->when.tv_sec += home->ping_interval;
2562 add_jitter(&home->when);
2564 DEBUG("PING: Next status packet in %u seconds", home->ping_interval);
2565 INSERT_EVENT(ping_home_server, home);
2568 static void home_trigger(home_server *home, const char *trigger)
2571 RADIUS_PACKET my_packet;
2573 memset(&my_request, 0, sizeof(my_request));
2574 memset(&my_packet, 0, sizeof(my_packet));
2575 my_request.proxy = &my_packet;
2576 my_packet.dst_ipaddr = home->ipaddr;
2577 my_packet.src_ipaddr = home->src_ipaddr;
2579 exec_trigger(&my_request, home->cs, trigger);
2582 static void mark_home_server_zombie(home_server *home)
2588 rad_assert(home->state == HOME_STATE_ALIVE);
2591 if (home->proto == IPPROTO_TCP) {
2592 DEBUG("WARNING: Not marking TCP server %s zombie", home->name);
2597 home->state = HOME_STATE_ZOMBIE;
2598 home_trigger(home, "home_server.zombie");
2600 home->zombie_period_start.tv_sec = home->last_packet;
2601 home->zombie_period_start.tv_usec = USEC / 2;
2603 fr_event_delete(el, &home->ev);
2604 home->num_sent_pings = 0;
2605 home->num_received_pings = 0;
2607 radlog(L_PROXY, "Marking home server %s port %d as zombie (it looks like it is dead).",
2608 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
2609 buffer, sizeof(buffer)),
2612 ping_home_server(home);
2616 void revive_home_server(void *ctx)
2618 home_server *home = ctx;
2622 rad_assert(home->proto != IPPROTO_TCP);
2625 home->state = HOME_STATE_ALIVE;
2626 home_trigger(home, "home_server.alive");
2627 home->currently_outstanding = 0;
2628 gettimeofday(&home->revive_time, NULL);
2631 * Delete any outstanding events.
2633 if (home->ev) fr_event_delete(el, &home->ev);
2635 radlog(L_PROXY, "Marking home server %s port %d alive again... we have no idea if it really is alive or not.",
2636 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
2637 buffer, sizeof(buffer)),
2641 void mark_home_server_dead(home_server *home, struct timeval *when)
2643 int previous_state = home->state;
2647 if (home->proto == IPPROTO_TCP) {
2648 DEBUG("WARNING: Not marking TCP server dead");
2653 radlog(L_PROXY, "Marking home server %s port %d as dead.",
2654 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr,
2655 buffer, sizeof(buffer)),
2658 home->state = HOME_STATE_IS_DEAD;
2659 home_trigger(home, "home_server.dead");
2661 if (home->ping_check != HOME_PING_CHECK_NONE) {
2663 * If the control socket marks us dead, start
2664 * pinging. Otherwise, we already started
2665 * pinging when it was marked "zombie".
2667 if (previous_state == HOME_STATE_ALIVE) {
2668 ping_home_server(home);
2670 DEBUG("PING: Already pinging home server %s",
2676 * Revive it after a fixed period of time. This
2677 * is very, very, bad.
2680 home->when.tv_sec += home->revive_interval;
2682 DEBUG("PING: Reviving home server %s in %u seconds",
2683 home->name, home->revive_interval);
2684 INSERT_EVENT(revive_home_server, home);
2688 STATE_MACHINE_DECL(proxy_wait_for_reply)
2690 struct timeval now, when;
2691 home_server *home = request->home_server;
2694 TRACE_STATE_MACHINE;
2696 rad_assert(request->packet->code != PW_STATUS_SERVER);
2697 rad_assert(request->home_server != NULL);
2699 gettimeofday(&now, NULL);
2701 rad_assert(request->child_state != REQUEST_DONE);
2703 if (request->master_state == REQUEST_STOP_PROCESSING) {
2704 request_done(request, FR_ACTION_DONE);
2710 if (!request->proxy_listener) return;
2712 if ((home->state == HOME_STATE_IS_DEAD) ||
2713 (request->proxy_listener->status != RAD_LISTEN_STATUS_KNOWN)) {
2714 request_proxy_anew(request);
2719 if (home->proto == IPPROTO_TCP) {
2720 DEBUG2("Suppressing duplicate proxied request to home server %s port %d proto TCP - ID: %d",
2721 inet_ntop(request->proxy->dst_ipaddr.af,
2722 &request->proxy->dst_ipaddr.ipaddr,
2723 buffer, sizeof(buffer)),
2724 request->proxy->dst_port,
2725 request->proxy->id);
2730 #ifdef WITH_ACCOUNTING
2732 * If we update the Acct-Delay-Time, we need to
2735 if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
2736 pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME, 0)) {
2737 request_proxy_anew(request);
2742 RDEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",
2743 inet_ntop(request->proxy->dst_ipaddr.af,
2744 &request->proxy->dst_ipaddr.ipaddr,
2745 buffer, sizeof(buffer)),
2746 request->proxy->dst_port,
2747 request->proxy->id);
2748 request->num_proxied_requests++;
2750 DEBUG_PACKET(request, request->proxy, 1);
2751 request->proxy_listener->send(request->proxy_listener,
2755 case FR_ACTION_TIMER:
2757 * If we haven't received a packet for a while,
2758 * mark it as zombie. If the connection is TCP,
2759 * then another "watchdog timer" function takes
2760 * care of pings, etc.
2762 if ((home->state == HOME_STATE_ALIVE) &&
2764 (home->proto != IPPROTO_TCP) &&
2766 ((home->last_packet + ((home->zombie_period + 3) / 4)) < now.tv_sec)) {
2767 mark_home_server_zombie(home);
2770 when = request->proxy->timestamp;
2771 when.tv_sec += home->response_window;
2774 * Not at the response window. Set the timer for
2777 if (timercmp(&when, &now, >)) {
2778 fr_event_insert(el, request_timer, request,
2779 &when, &request->ev);
2784 * FIXME: debug log no response to proxied request
2788 * No response, but we're supposed to do nothing
2789 * when there's no response. The request is finished.
2791 if (!home->no_response_fail) {
2792 #ifdef HAVE_PTHREAD_H
2793 request->child_pid = NO_SUCH_CHILD_PID;
2795 gettimeofday(&request->reply->timestamp, NULL);
2796 #ifdef DEBUG_STATE_MACHINE
2797 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_DONE);
2799 #ifdef HAVE_PTHREAD_H
2800 rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
2802 request->child_state = REQUEST_DONE;
2803 request_process_timer(request);
2808 * Do "fail on no response".
2810 radlog_request(L_ERR, 0, request, "Rejecting request (proxy Id %d) due to lack of any response from home server %s port %d",
2812 inet_ntop(request->proxy->dst_ipaddr.af,
2813 &request->proxy->dst_ipaddr.ipaddr,
2814 buffer, sizeof(buffer)),
2815 request->proxy->dst_port);
2817 if (!setup_post_proxy_fail(request)) {
2823 * Duplicate proxy replies have been quenched by
2824 * now. This state is only called ONCE, when we
2825 * receive a new reply from the home server.
2827 case FR_ACTION_PROXY_REPLY:
2828 request_queue_or_run(request, proxy_running);
2831 case FR_ACTION_CONFLICTING:
2832 request_done(request, action);
2836 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
2840 #endif /* WITH_PROXY */
2842 /***********************************************************************
2846 ***********************************************************************/
2848 static int null_handler(UNUSED REQUEST *request)
2854 * See if we need to originate a CoA request.
2856 static void request_coa_originate(REQUEST *request)
2858 int rcode, pre_proxy_type = 0;
2864 rad_assert(request != NULL);
2865 rad_assert(request->coa != NULL);
2866 rad_assert(request->proxy == NULL);
2867 rad_assert(!request->in_proxy_hash);
2868 rad_assert(request->proxy_reply == NULL);
2871 * Check whether we want to originate one, or cancel one.
2873 vp = pairfind(request->config_items, PW_SEND_COA_REQUEST, 0);
2875 vp = pairfind(request->coa->proxy->vps, PW_SEND_COA_REQUEST, 0);
2879 if (vp->vp_integer == 0) {
2881 request_done(request->coa, FR_ACTION_DONE);
2889 * src_ipaddr will be set up in proxy_encode.
2891 memset(&ipaddr, 0, sizeof(ipaddr));
2892 vp = pairfind(coa->proxy->vps, PW_PACKET_DST_IP_ADDRESS, 0);
2894 ipaddr.af = AF_INET;
2895 ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
2897 } else if ((vp = pairfind(coa->proxy->vps,
2898 PW_PACKET_DST_IPV6_ADDRESS, 0)) != NULL) {
2899 ipaddr.af = AF_INET6;
2900 ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
2902 } else if ((vp = pairfind(coa->proxy->vps,
2903 PW_HOME_SERVER_POOL, 0)) != NULL) {
2904 coa->home_pool = home_pool_byname(vp->vp_strvalue,
2906 if (!coa->home_pool) {
2907 RDEBUG2("WARNING: No such home_server_pool %s",
2913 * Prefer the pool to one server
2915 } else if (request->client->coa_pool) {
2916 coa->home_pool = request->client->coa_pool;
2918 } else if (request->client->coa_server) {
2919 coa->home_server = request->client->coa_server;
2923 * If all else fails, send it to the client that
2924 * originated this request.
2926 memcpy(&ipaddr, &request->packet->src_ipaddr, sizeof(ipaddr));
2930 * Use the pool, if it exists.
2932 if (coa->home_pool) {
2933 coa->home_server = home_server_ldb(NULL, coa->home_pool, coa);
2934 if (!coa->home_server) {
2935 RDEBUG("WARNING: No live home server for home_server_pool %s", vp->vp_strvalue);
2939 } else if (!coa->home_server) {
2940 int port = PW_COA_UDP_PORT;
2942 vp = pairfind(coa->proxy->vps, PW_PACKET_DST_PORT, 0);
2943 if (vp) port = vp->vp_integer;
2945 coa->home_server = home_server_find(&ipaddr, port, IPPROTO_UDP);
2946 if (!coa->home_server) {
2947 RDEBUG2("WARNING: Unknown destination %s:%d for CoA request.",
2948 inet_ntop(ipaddr.af, &ipaddr.ipaddr,
2949 buffer, sizeof(buffer)), port);
2954 vp = pairfind(coa->proxy->vps, PW_PACKET_TYPE, 0);
2956 switch (vp->vp_integer) {
2957 case PW_COA_REQUEST:
2958 case PW_DISCONNECT_REQUEST:
2959 coa->proxy->code = vp->vp_integer;
2963 DEBUG("Cannot set CoA Packet-Type to code %d",
2969 if (!coa->proxy->code) coa->proxy->code = PW_COA_REQUEST;
2972 * The rest of the server code assumes that
2973 * request->packet && request->reply exist. Copy them
2974 * from the original request.
2976 rad_assert(coa->packet != NULL);
2977 rad_assert(coa->packet->vps == NULL);
2978 memcpy(coa->packet, request->packet, sizeof(*request->packet));
2979 coa->packet->vps = paircopy(request->packet->vps);
2980 coa->packet->data = NULL;
2981 rad_assert(coa->reply != NULL);
2982 rad_assert(coa->reply->vps == NULL);
2983 memcpy(coa->reply, request->reply, sizeof(*request->reply));
2984 coa->reply->vps = paircopy(request->reply->vps);
2985 coa->reply->data = NULL;
2986 coa->config_items = paircopy(request->config_items);
2987 coa->num_coa_requests = 0;
2988 coa->handle = null_handler;
2989 coa->number = request->number ^ (1 << 24);
2992 * Call the pre-proxy routines.
2994 vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE, 0);
2996 RDEBUG2(" Found Pre-Proxy-Type %s", vp->vp_strvalue);
2997 pre_proxy_type = vp->vp_integer;
3000 if (coa->home_pool && coa->home_pool->virtual_server) {
3001 const char *old_server = coa->server;
3003 coa->server = coa->home_pool->virtual_server;
3004 RDEBUG2(" server %s {", coa->server);
3005 rcode = module_pre_proxy(pre_proxy_type, coa);
3007 coa->server = old_server;
3009 rcode = module_pre_proxy(pre_proxy_type, coa);
3016 * Only send the CoA packet if the pre-proxy code succeeded.
3018 case RLM_MODULE_NOOP:
3020 case RLM_MODULE_UPDATED:
3025 * Source IP / port is set when the proxy socket
3028 coa->proxy->dst_ipaddr = coa->home_server->ipaddr;
3029 coa->proxy->dst_port = coa->home_server->port;
3031 if (!insert_into_proxy_hash(coa)) {
3032 radlog_request(L_PROXY, 0, coa, "Failed to insert CoA request into proxy list.");
3037 * We CANNOT divorce the CoA request from the parent
3038 * request. This function is running in a child thread,
3039 * and we need access to the main event loop in order to
3040 * to add the timers for the CoA packet.
3042 * Instead, we wait for the timer on the parent request
3045 gettimeofday(&coa->proxy->timestamp, NULL);
3046 coa->packet->timestamp = coa->proxy->timestamp; /* for max_request_time */
3047 coa->delay = 0; /* need to calculate a new delay */
3049 DEBUG_PACKET(coa, coa->proxy, 1);
3051 coa->process = request_coa_process;
3052 #ifdef DEBUG_STATE_MACHINE
3053 if (debug_flag) printf("(%u) ********\tSTATE %s C%u -> C%u\t********\n", request->number, __FUNCTION__, request->child_state, REQUEST_ACTIVE);
3055 coa->child_state = REQUEST_ACTIVE;
3056 rad_assert(coa->proxy_reply == NULL);
3057 coa->proxy_listener->send(coa->proxy_listener, coa);
3061 static void request_coa_separate(REQUEST *request)
3063 #ifdef DEBUG_STATE_MACHINE
3064 int action = FR_ACTION_TIMER;
3066 TRACE_STATE_MACHINE;
3068 rad_assert(request->parent != NULL);
3069 rad_assert(request->parent->coa == request);
3070 rad_assert(request->ev == NULL);
3071 rad_assert(!request->in_request_hash);
3073 request->parent->coa = NULL;
3074 request->parent = NULL;
3077 * Set up timers for the CoA request. These do all kinds
3078 * of different things....
3080 request_coa_timer(request);
3083 static void request_coa_timer(REQUEST *request)
3086 struct timeval now, when, mrd;
3088 rad_assert(request->parent == NULL);
3090 if (request->proxy_reply) return request_process_timer(request);
3092 gettimeofday(&now, NULL);
3094 if (request->delay == 0) {
3096 * Implement re-transmit algorithm as per RFC 5080
3099 * We want IRT + RAND*IRT
3100 * or 0.9 IRT + rand(0,.2) IRT
3102 * 2^20 ~ USEC, and we want 2.
3103 * rand(0,0.2) USEC ~ (rand(0,2^21) / 10)
3105 delay = (fr_rand() & ((1 << 22) - 1)) / 10;
3106 request->delay = delay * request->home_server->coa_irt;
3107 delay = request->home_server->coa_irt * USEC;
3108 delay -= delay / 10;
3109 delay += request->delay;
3110 request->delay = delay;
3112 when = request->proxy->timestamp;
3113 tv_add(&when, delay);
3115 if (timercmp(&when, &now, >)) {
3116 fr_event_insert(el, request_timer, request, &when,
3123 * Retransmit CoA request.
3127 * Cap count at MRC, if it is non-zero.
3129 if (request->home_server->coa_mrc &&
3130 (request->num_coa_requests >= request->home_server->coa_mrc)) {
3131 if (!setup_post_proxy_fail(request)) {
3135 request_queue_or_run(request, proxy_running);
3140 * RFC 5080 Section 2.2.1
3142 * RT = 2*RTprev + RAND*RTprev
3143 * = 1.9 * RTprev + rand(0,.2) * RTprev
3144 * = 1.9 * RTprev + rand(0,1) * (RTprev / 5)
3147 delay ^= (delay >> 16);
3149 frac = request->delay / 5;
3150 delay = ((frac >> 16) * delay) + (((frac & 0xffff) * delay) >> 16);
3152 delay += (2 * request->delay) - (request->delay / 10);
3155 * Cap delay at MRT, if MRT is non-zero.
3157 if (request->home_server->coa_mrt &&
3158 (delay > (request->home_server->coa_mrt * USEC))) {
3159 int mrt_usec = request->home_server->coa_mrt * USEC;
3162 * delay = MRT + RAND * MRT
3163 * = 0.9 MRT + rand(0,.2) * MRT
3166 delay ^= (delay >> 15);
3168 delay = ((mrt_usec >> 16) * delay) + (((mrt_usec & 0xffff) * delay) >> 16);
3169 delay += mrt_usec - (mrt_usec / 10);
3172 request->delay = delay;
3174 tv_add(&when, request->delay);
3175 mrd = request->proxy->timestamp;
3176 mrd.tv_sec += request->home_server->coa_mrd;
3179 * Cap duration at MRD.
3181 if (timercmp(&mrd, &when, <)) {
3184 fr_event_insert(el, request_timer, request, &when, &request->ev);
3186 request->num_coa_requests++; /* is NOT reset by code 3 lines above! */
3188 request->proxy_listener->send(request->proxy_listener,
3193 STATE_MACHINE_DECL(coa_running)
3195 TRACE_STATE_MACHINE;
3198 case FR_ACTION_TIMER:
3199 request_coa_timer(request);
3202 case FR_ACTION_PROXY_REPLY:
3203 request_common(request, action);
3207 request_running(request, FR_ACTION_PROXY_REPLY);
3211 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
3218 * Process CoA requests that we originated.
3220 STATE_MACHINE_DECL(request_coa_process)
3222 TRACE_STATE_MACHINE;
3225 case FR_ACTION_TIMER:
3226 request_coa_timer(request);
3229 case FR_ACTION_PROXY_REPLY:
3230 rad_assert(request->parent == NULL);
3231 #ifdef HAVE_PTHREAD_H
3233 * Catch the case of a proxy reply when called
3234 * from the main worker thread.
3236 if (we_are_master() &&
3237 (request->process != coa_running)) {
3238 request_queue_or_run(request, coa_running);
3244 request_running(request, action);
3248 RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
3253 #endif /* WITH_COA */
3255 /***********************************************************************
3257 * End of the State machine. Start of additional helper code.
3259 ***********************************************************************/
3261 /***********************************************************************
3265 ***********************************************************************/
3266 static void event_socket_handler(fr_event_list_t *xel, UNUSED int fd,
3269 rad_listen_t *listener = ctx;
3271 rad_assert(xel == el);
3277 (listener->type != RAD_LISTEN_DETAIL) &&
3279 (listener->fd < 0)) {
3282 listener->print(listener, buffer, sizeof(buffer));
3283 radlog(L_ERR, "FATAL: Asked to read from closed socket: %s",
3286 rad_panic("Socket was closed on us!");
3290 listener->recv(listener);
3295 * This function is called periodically to see if this detail
3296 * file is available for reading.
3298 static void event_poll_detail(void *ctx)
3301 rad_listen_t *this = ctx;
3302 struct timeval when, now;
3303 listen_detail_t *detail = this->data;
3305 rad_assert(this->type == RAD_LISTEN_DETAIL);
3307 event_socket_handler(el, this->fd, this);
3309 fr_event_now(el, &now);
3313 * Backdoor API to get the delay until the next poll
3316 delay = this->encode(this, NULL);
3317 tv_add(&when, delay);
3319 if (!fr_event_insert(el, event_poll_detail, this,
3320 &when, &detail->ev)) {
3321 radlog(L_ERR, "Failed creating handler");
3327 static void event_status(struct timeval *wake)
3329 #if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)
3333 if (debug_flag == 0) {
3335 radlog(L_INFO, "Ready to process requests.");
3336 just_started = FALSE;
3342 radlog(L_INFO, "Ready to process requests.");
3344 } else if ((wake->tv_sec != 0) ||
3345 (wake->tv_usec >= 100000)) {
3346 DEBUG("Waking up in %d.%01u seconds.",
3347 (int) wake->tv_sec, (unsigned int) wake->tv_usec / 100000);
3352 * FIXME: Put this somewhere else, where it isn't called
3353 * all of the time...
3356 #if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)
3358 * If there are no child threads, then there may
3359 * be child processes. In that case, wait for
3360 * their exit status, and throw that exit status
3361 * away. This helps get rid of zxombie children.
3363 while (waitpid(-1, &argval, WNOHANG) > 0) {
3371 int event_new_fd(rad_listen_t *this)
3375 if (this->status == RAD_LISTEN_STATUS_KNOWN) return 1;
3377 this->print(this, buffer, sizeof(buffer));
3379 if (this->status == RAD_LISTEN_STATUS_INIT) {
3381 DEBUG("Listening on %s", buffer);
3383 radlog(L_INFO, " ... adding new socket %s", buffer);
3388 * Add it to the list of sockets we can use.
3389 * Server sockets (i.e. auth/acct) are never
3390 * added to the packet list.
3392 if (this->type == RAD_LISTEN_PROXY) {
3393 listen_socket_t *sock = this->data;
3395 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3396 if (!fr_packet_list_socket_add(proxy_list, this->fd,
3398 &sock->other_ipaddr, sock->other_port,
3401 proxy_no_new_sockets = TRUE;
3402 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3405 * This is bad. However, the
3406 * packet list now supports 256
3407 * open sockets, which should
3408 * minimize this problem.
3410 radlog(L_ERR, "Failed adding proxy socket: %s",
3416 sock->home->num_connections++;
3419 * If necessary, add it to the list of
3420 * new proxy listeners.
3422 if (sock->home->lifetime || sock->home->idle_timeout) {
3423 this->next = proxy_listener_list;
3424 proxy_listener_list = this;
3427 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3430 * Tell the main thread that we've added
3431 * a proxy listener, but only if we need
3432 * to update the event list. Do this
3433 * with the mutex unlocked, to reduce
3437 if (sock->home->lifetime || sock->home->idle_timeout) {
3438 radius_signal_self(RADIUS_SIGNAL_SELF_NEW_FD);
3446 * Detail files are always known, and aren't
3447 * put into the socket event loop.
3449 if (this->type == RAD_LISTEN_DETAIL) {
3450 this->status = RAD_LISTEN_STATUS_KNOWN;
3453 * Set up the first poll interval.
3455 event_poll_detail(this);
3460 FD_MUTEX_LOCK(&fd_mutex);
3461 if (!fr_event_fd_insert(el, 0, this->fd,
3462 event_socket_handler, this)) {
3463 radlog(L_ERR, "Failed adding event handler for proxy socket!");
3466 FD_MUTEX_UNLOCK(&fd_mutex);
3468 this->status = RAD_LISTEN_STATUS_KNOWN;
3473 * Something went wrong with the socket: make it harmless.
3475 if (this->status == RAD_LISTEN_STATUS_REMOVE_FD) {
3479 * Remove it from the list of live FD's.
3481 FD_MUTEX_LOCK(&fd_mutex);
3482 fr_event_fd_delete(el, 0, this->fd);
3483 FD_MUTEX_UNLOCK(&fd_mutex);
3487 * We track requests using this socket only for
3488 * TCP. For UDP, we don't currently close
3492 if (this->type != RAD_LISTEN_PROXY)
3495 if (this->count != 0) {
3496 fr_packet_list_walk(pl, this,
3497 remove_all_requests);
3500 if (this->count == 0) {
3501 this->status = RAD_LISTEN_STATUS_FINISH;
3512 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3513 if (!fr_packet_list_socket_freeze(proxy_list,
3515 radlog(L_ERR, "Fatal error freezing socket: %s",
3521 * Doing this with the proxy mutex held
3522 * is a Bad Thing. We should move to
3523 * finer-grained mutexes.
3525 count = this->count;
3527 fr_packet_list_walk(proxy_list, this,
3528 remove_all_proxied_requests);
3530 count = this->count; /* protected by mutex */
3531 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3534 this->status = RAD_LISTEN_STATUS_FINISH;
3538 #endif /* WITH_PROXY */
3539 #endif /* WITH_TCP */
3542 * Re-open the socket, pointing it to /dev/null.
3543 * This means that all writes proceed without
3544 * blocking, and all reads return "no data".
3546 * This leaves the socket active, so any child
3547 * threads won't go insane. But it means that
3548 * they cannot send or receive any packets.
3550 * This is EXTRA work in the normal case, when
3551 * sockets are closed without error. But it lets
3552 * us have one simple processing method for all
3555 devnull = open("/dev/null", O_RDWR);
3557 radlog(L_ERR, "FATAL failure opening /dev/null: %s",
3561 if (dup2(devnull, this->fd) < 0) {
3562 radlog(L_ERR, "FATAL failure closing socket: %s",
3568 this->status = RAD_LISTEN_STATUS_CLOSED;
3571 * Fall through to the next section.
3577 * Called ONLY from the main thread. On the following
3583 * (and falling through from "forcibly close FD" above)
3584 * client closed connection on us
3585 * client sent us a bad packet.
3587 if (this->status == RAD_LISTEN_STATUS_CLOSED) {
3588 int count = this->count;
3591 rad_assert(this->type != RAD_LISTEN_DETAIL);
3596 * Remove it from the list of active sockets, so
3597 * that it isn't used when proxying new packets.
3599 if (this->type == RAD_LISTEN_PROXY) {
3600 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3601 if (!fr_packet_list_socket_freeze(proxy_list,
3603 radlog(L_ERR, "Fatal error freezing socket: %s",
3607 count = this->count; /* protected by mutex */
3608 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3613 * Requests are still using the socket. Wait for
3617 struct timeval when;
3618 listen_socket_t *sock = this->data;
3621 * Try again to clean up the socket in 30
3624 gettimeofday(&when, NULL);
3627 if (!fr_event_insert(el,
3628 (fr_event_callback_t) event_new_fd,
3629 this, &when, &sock->ev)) {
3630 rad_panic("Failed to insert event");
3637 * No one is using this socket: we can delete it
3640 this->status = RAD_LISTEN_STATUS_FINISH;
3644 if (this->status == RAD_LISTEN_STATUS_FINISH) {
3645 listen_socket_t *sock = this->data;
3647 rad_assert(this->count == 0);
3648 radlog(L_INFO, " ... closing socket %s", buffer);
3651 * Remove it from the list of live FD's. Note
3652 * that it MAY also have been removed above. We
3653 * do it again here, to catch the case of sockets
3654 * closing on idle timeout, or max
3655 * lifetime... AFTER all requests have finished
3658 FD_MUTEX_LOCK(&fd_mutex);
3659 fr_event_fd_delete(el, 0, this->fd);
3660 FD_MUTEX_UNLOCK(&fd_mutex);
3664 * Remove it from the list of sockets to be used
3667 if (this->type == RAD_LISTEN_PROXY) {
3668 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3669 if (!fr_packet_list_socket_remove(proxy_list,
3671 radlog(L_ERR, "Fatal error removing socket: %s",
3675 if (sock->home) sock->home->num_connections--;
3676 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3681 * Remove any pending cleanups.
3683 if (sock->ev) fr_event_delete(el, &sock->ev);
3686 * And finally, close the socket.
3690 #endif /* WITH_TCP */
3695 /***********************************************************************
3699 ***********************************************************************/
3701 static void handle_signal_self(int flag)
3703 if ((flag & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {
3704 if ((flag & RADIUS_SIGNAL_SELF_EXIT) != 0) {
3705 radlog(L_INFO, "Signalled to exit");
3706 fr_event_loop_exit(el, 1);
3708 radlog(L_INFO, "Signalled to terminate");
3709 exec_trigger(NULL, NULL, "server.signal.term");
3710 fr_event_loop_exit(el, 2);
3714 } /* else exit/term flags weren't set */
3717 * Tell the even loop to stop processing.
3719 if ((flag & RADIUS_SIGNAL_SELF_HUP) != 0) {
3721 static time_t last_hup = 0;
3724 if ((int) (when - last_hup) < 5) {
3725 radlog(L_INFO, "Ignoring HUP (less than 5s since last one)");
3729 radlog(L_INFO, "Received HUP signal.");
3733 exec_trigger(NULL, NULL, "server.signal.hup");
3734 fr_event_loop_exit(el, 0x80);
3738 if ((flag & RADIUS_SIGNAL_SELF_DETAIL) != 0) {
3742 * FIXME: O(N) loops suck.
3744 for (this = mainconfig.listen;
3746 this = this->next) {
3747 if (this->type != RAD_LISTEN_DETAIL) continue;
3750 * This one didn't send the signal, skip
3753 if (!this->decode(this, NULL)) continue;
3756 * Go service the interrupt.
3758 event_poll_detail(this);
3766 * Add event handlers for idle timeouts && maximum lifetime.
3768 if ((flag & RADIUS_SIGNAL_SELF_NEW_FD) != 0) {
3769 struct timeval when, now;
3771 fr_event_now(el, &now);
3773 PTHREAD_MUTEX_LOCK(&proxy_mutex);
3775 while (proxy_listener_list) {
3776 rad_listen_t *this = proxy_listener_list;
3777 listen_socket_t *sock = this->data;
3779 rad_assert(sock->proto == IPPROTO_TCP);
3780 proxy_listener_list = this->next;
3783 if (!sock->home) continue; /* skip UDP sockets */
3787 if (!fr_event_insert(el, tcp_socket_timer, this, &when,
3789 rad_panic("Failed to insert event");
3793 PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
3795 #endif /* WITH_PROXY */
3796 #endif /* WITH_TCP */
3799 #ifndef WITH_SELF_PIPE
3800 void radius_signal_self(int flag)
3802 handle_signal_self(flag);
3806 * Inform ourselves that we received a signal.
3808 void radius_signal_self(int flag)
3814 * The read MUST be non-blocking for this to work.
3816 rcode = read(self_pipe[0], buffer, sizeof(buffer));
3820 for (i = 0; i < rcode; i++) {
3821 buffer[0] |= buffer[i];
3829 write(self_pipe[1], buffer, 1);
3833 static void event_signal_handler(UNUSED fr_event_list_t *xel,
3834 UNUSED int fd, UNUSED void *ctx)
3839 rcode = read(self_pipe[0], buffer, sizeof(buffer));
3840 if (rcode <= 0) return;
3843 * Merge pending signals.
3845 for (i = 0; i < rcode; i++) {
3846 buffer[0] |= buffer[i];
3849 handle_signal_self(buffer[0]);
3853 /***********************************************************************
3855 * Bootstrapping code.
3857 ***********************************************************************/
3860 * Externally-visibly functions.
3862 int radius_event_init(CONF_SECTION *cs, int have_children)
3864 rad_listen_t *head = NULL;
3868 time(&fr_start_time);
3870 el = fr_event_list_create(event_status);
3873 pl = fr_packet_list_create(0);
3874 if (!pl) return 0; /* leak el */
3876 request_num_counter = 0;
3879 if (mainconfig.proxy_requests) {
3881 * Create the tree for managing proxied requests and
3884 proxy_list = fr_packet_list_create(1);
3885 if (!proxy_list) return 0;
3887 #ifdef HAVE_PTHREAD_H
3888 if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {
3889 radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",
3897 #ifdef HAVE_PTHREAD_H
3898 NO_SUCH_CHILD_PID = pthread_self(); /* not a child thread */
3901 * Initialize the threads ONLY if we're spawning, AND
3902 * we're running normally.
3904 if (have_children && !check_config &&
3905 (thread_pool_init(cs, &have_children) < 0)) {
3911 * Move all of the thread calls to this file?
3913 * It may be best for the mutexes to be in this file...
3915 spawn_flag = have_children;
3918 DEBUG("%s: #### Skipping IP addresses and Ports ####",
3920 if (listen_init(cs, &head, spawn_flag) < 0) {
3927 #ifdef WITH_SELF_PIPE
3929 * Child threads need a pipe to signal us, as do the
3932 if (pipe(self_pipe) < 0) {
3933 radlog(L_ERR, "radiusd: Error opening internal pipe: %s",
3937 if (fcntl(self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
3938 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
3942 if (fcntl(self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {
3943 radlog(L_ERR, "radiusd: Error setting internal flags: %s",
3948 if (!fr_event_fd_insert(el, 0, self_pipe[0],
3949 event_signal_handler, el)) {
3950 radlog(L_ERR, "Failed creating handler for signals");
3953 #endif /* WITH_SELF_PIPE */
3955 DEBUG("%s: #### Opening IP addresses and Ports ####",
3959 * The server temporarily switches to an unprivileged
3960 * user very early in the bootstrapping process.
3961 * However, some sockets MAY require privileged access
3962 * (bind to device, or to port < 1024, or to raw
3963 * sockets). Those sockets need to call suid up/down
3964 * themselves around the functions that need a privileged
3967 if (listen_init(cs, &head, spawn_flag) < 0) {
3971 mainconfig.listen = head;
3974 * At this point, no one has any business *ever* going
3977 fr_suid_down_permanent();
3983 static int request_hash_cb(UNUSED void *ctx, void *data)
3985 REQUEST *request = fr_packet2myptr(REQUEST, packet, data);
3988 rad_assert(request->in_proxy_hash == FALSE);
3991 request_done(request, FR_ACTION_DONE);
3998 static int proxy_hash_cb(UNUSED void *ctx, void *data)
4000 REQUEST *request = fr_packet2myptr(REQUEST, proxy, data);
4002 request_done(request, FR_ACTION_DONE);
4008 void radius_event_free(void)
4011 * FIXME: Stop all threads, or at least check that
4012 * they're all waiting on the semaphore, and the queues
4018 * There are requests in the proxy hash that aren't
4019 * referenced from anywhere else. Remove them first.
4022 fr_packet_list_walk(proxy_list, NULL, proxy_hash_cb);
4023 fr_packet_list_free(proxy_list);
4028 fr_packet_list_walk(pl, NULL, request_hash_cb);
4030 fr_packet_list_free(pl);
4033 fr_event_list_free(el);
4036 int radius_event_process(void)
4040 return fr_event_loop(el);