2 * radiusd.c Main loop of the radius server.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Copyright 2000,2001 The FreeRADIUS server project
21 * Copyright 1999,2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
23 * Copyright 2000 Alan Curry <pacman-radius@cqc.com>
24 * Copyright 2000 Jeff Carneal <jeff@apex.net>
25 * Copyright 2000 Chad Miller <cmiller@surfsouth.com>
28 /* don't look here for the version, run radiusd -v or look in version.c */
29 static const char rcsid[] =
33 #include "libradius.h"
35 #include <sys/socket.h>
39 # include <netinet/in.h>
59 # include <sys/select.h>
67 # include <sys/wait.h>
70 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
73 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
81 #include "request_list.h"
84 # include "radius_snmp.h"
87 #include <sys/resource.h>
95 const char *progname = NULL;
96 const char *radius_dir = NULL;
97 const char *radacct_dir = NULL;
98 const char *radlog_dir = NULL;
99 const char *radlib_dir = NULL;
100 int log_stripped_names;
103 uint32_t myip = INADDR_ANY;
104 int log_auth_detail = FALSE;
108 int proxy_retry_delay = RETRY_DELAY;
109 int proxy_retry_count = RETRY_COUNT;
110 int proxy_synchronous = TRUE;
111 int need_reload = FALSE;
112 struct main_config_t mainconfig;
113 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
115 static int got_child = FALSE;
119 static pid_t radius_pid;
120 static int request_num_counter = 0; /* per-request unique ID */
123 * Configuration items.
125 static int allow_core_dumps = FALSE;
126 static int max_request_time = MAX_REQUEST_TIME;
127 static int kill_unresponsive_children = FALSE;
128 static int cleanup_delay = CLEANUP_DELAY;
129 static int max_requests = MAX_REQUESTS;
130 static int dont_fork = FALSE;
131 static const char *pid_file = NULL;
132 static uid_t server_uid;
133 static gid_t server_gid;
134 static const char *uid_name = NULL;
135 static const char *gid_name = NULL;
136 static int proxy_requests = TRUE;
137 int spawn_flag = TRUE;
138 static struct rlimit core_limits;
140 static void usage(void);
142 static void sig_fatal (int);
143 static void sig_hup (int);
145 static void rad_reject(REQUEST *request);
146 static struct timeval *rad_clean_list(time_t curtime);
147 static REQUEST *rad_check_list(REQUEST *);
148 static REQUEST *proxy_check_list(REQUEST *request);
149 static int refresh_request(REQUEST *request, void *data);
150 #ifndef WITH_THREAD_POOL
151 static int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
153 extern int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
157 * Map the proxy server configuration parameters to variables.
159 static CONF_PARSER proxy_config[] = {
160 { "retry_delay", PW_TYPE_INTEGER, 0, &proxy_retry_delay, Stringify(RETRY_DELAY) },
161 { "retry_count", PW_TYPE_INTEGER, 0, &proxy_retry_count, Stringify(RETRY_COUNT) },
162 { "synchronous", PW_TYPE_BOOLEAN, 0, &proxy_synchronous, "yes" },
163 { NULL, -1, 0, NULL, NULL }
167 * A mapping of configuration file names to internal variables
169 static CONF_PARSER server_config[] = {
170 { "max_request_time", PW_TYPE_INTEGER, 0, &max_request_time, Stringify(MAX_REQUEST_TIME) },
171 { "cleanup_delay", PW_TYPE_INTEGER, 0, &cleanup_delay, Stringify(CLEANUP_DELAY) },
172 { "max_requests", PW_TYPE_INTEGER, 0, &max_requests, Stringify(MAX_REQUESTS) },
173 { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &kill_unresponsive_children, Stringify(FALSE) },
174 { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
175 { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &allow_core_dumps, "no" },
176 { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
177 { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
178 { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
179 { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
180 { "pidfile", PW_TYPE_STRING_PTR, 0, &pid_file, "${run_dir}/radiusd.pid"},
181 { "bind_address", PW_TYPE_IPADDR, 0, &myip, "*" },
182 { "user", PW_TYPE_STRING_PTR, 0, &uid_name, "nobody"},
183 { "group", PW_TYPE_STRING_PTR, 0, &gid_name, "nobody"},
184 { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide, "no" },
185 { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
186 { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
187 { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
188 { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
189 { "proxy_requests", PW_TYPE_BOOLEAN, 0, &proxy_requests, "yes" },
190 { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
191 { NULL, -1, 0, NULL, NULL }
197 static int reread_config(int reload)
203 radlog(L_INFO, "Starting - reading configuration files ...");
204 } else if (pid == radius_pid) {
205 radlog(L_INFO, "Reloading configuration files.");
208 /* First read radiusd.conf */
209 DEBUG2("reread_config: reading radiusd.conf");
210 if (read_radius_conf_file() < 0) {
211 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
216 * And parse the server's configuration values.
218 cs = cf_section_find(NULL);
220 radlog(L_ERR|L_CONS, "No configuration information in radiusd.conf!");
223 cf_section_parse(cs, NULL, server_config);
226 * Reload the modules.
228 DEBUG2("read_config_files: entering modules setup");
229 if (setup_modules() < 0) {
230 radlog(L_ERR|L_CONS, "Errors setting up modules");
235 * Go update our behaviour, based on the configuration
238 if (allow_core_dumps) {
239 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
240 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
245 * If we're running as a daemon, and core
246 * dumps are enabled, log that information.
248 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
249 radlog(L_INFO, "Core dumps are enabled.");
251 } else if (!debug_flag) {
253 * Not debugging. Set the core size to zero, to
254 * prevent security breaches. i.e. People
255 * reading passwords from the 'core' file.
257 struct rlimit limits;
260 limits.rlim_max = core_limits.rlim_max;
262 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
263 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
270 * Set the UID and GID, but only if we're NOT running
278 if (gid_name != NULL) {
281 gr = getgrnam(gid_name);
283 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: %s", gid_name, strerror(errno));
286 server_gid = gr->gr_gid;
287 if (setgid(server_gid) < 0) {
288 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s", gid_name, strerror(errno));
296 if (uid_name != NULL) {
299 pw = getpwnam(uid_name);
301 radlog(L_ERR|L_CONS, "Cannot switch to User %s: %s", uid_name, strerror(errno));
304 server_uid = pw->pw_uid;
305 if (setuid(server_uid) < 0) {
306 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", uid_name, strerror(errno));
316 * Parse a string into a syslog facility level.
318 static int str2fac(const char *s)
321 if(!strcmp(s, "kern"))
326 if(!strcmp(s, "user"))
331 if(!strcmp(s, "mail"))
336 if(!strcmp(s, "daemon"))
341 if(!strcmp(s, "auth"))
346 if(!strcmp(s, "auth"))
351 if(!strcmp(s, "lpr"))
356 if(!strcmp(s, "news"))
361 if(!strcmp(s, "uucp"))
366 if(!strcmp(s, "cron"))
371 if(!strcmp(s, "authpriv"))
376 if(!strcmp(s, "ftp"))
381 if(!strcmp(s, "local0"))
386 if(!strcmp(s, "local1"))
391 if(!strcmp(s, "local2"))
396 if(!strcmp(s, "local3"))
401 if(!strcmp(s, "local4"))
406 if(!strcmp(s, "local5"))
411 if(!strcmp(s, "local6"))
416 if(!strcmp(s, "local7"))
421 fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
426 /* this should never be reached */
430 int main(int argc, char **argv)
433 RADIUS_PACKET *packet;
435 unsigned char buffer[4096];
436 struct sockaddr salocal;
437 struct sockaddr_in *sa;
447 int syslog_facility = LOG_DAEMON;
450 struct timeval *tv = NULL;
453 set_auth_parameters(argc,argv);
457 * Open /dev/null, and make sure filedescriptors
458 * 0, 1 and 2 are connected to something.
461 while (devnull >= 0 && devnull < 3)
462 devnull = open("/dev/null", O_RDWR);
464 if ((progname = strrchr(argv[0], '/')) == NULL)
471 radius_dir = strdup(RADIUS_DIR);
473 signal(SIGHUP, sig_hup);
474 signal(SIGINT, sig_fatal);
475 signal(SIGQUIT, sig_fatal);
477 signal(SIGPIPE, SIG_IGN);
480 signal(SIGTRAP, sig_fatal);
483 signal(SIGIOT, sig_fatal);
486 /* this is right for threads, too, right?
487 * (Threads shouldn't get signals (from us) -- just be pthread_cancel()led.)
489 signal(SIGTERM, sig_fatal);
490 signal(SIGCHLD, sig_cleanup);
492 signal(SIGFPE, sig_fatal);
493 signal(SIGSEGV, sig_fatal);
494 signal(SIGILL, sig_fatal);
498 * Close unused file descriptors.
500 for (t = 32; t >= 3; t--)
505 * Process the options.
507 while((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:p:sSvxXyz")) != EOF) {
512 log_auth_detail = TRUE;
516 radacct_dir = strdup(optarg);
519 #if defined(WITH_DBM) || defined(WITH_NDBM)
525 /* ignore for backwards compatibility with Cistron */
529 radius_dir = strdup(optarg);
541 if ((myip = ip_getaddr(optarg)) == INADDR_NONE) {
542 fprintf(stderr, "radiusd: %s: host unknown\n",
549 radlog_dir = strdup(optarg);
553 * We should also have this as a configuration
557 syslog_facility = str2fac(optarg);
561 log_stripped_names++;
565 radius_port = atoi(optarg);
568 case 's': /* Single process mode */
577 * BIG debugging mode for users who are
578 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
585 mainconfig.log_auth = TRUE;
586 mainconfig.log_auth_badpass = TRUE;
587 mainconfig.log_auth_goodpass = TRUE;
588 radlog_dir = strdup("stdout");
597 mainconfig.log_auth = TRUE;
598 mainconfig.log_auth_badpass = TRUE;
602 mainconfig.log_auth_badpass = TRUE;
603 mainconfig.log_auth_goodpass = TRUE;
613 * Get out PID: the configuration file reader uses it.
615 radius_pid = getpid();
618 * Get the current maximum for core files.
620 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
621 radlog(L_ERR|L_CONS, "Failed to get current core limit:"
622 " %s", strerror(errno));
627 * Read the configuration files, BEFORE doing anything else.
629 if (reread_config(0) < 0) {
635 * If they asked for syslog, then give it to them.
636 * Also, initialize the logging facility with the
637 * configuration that they asked for.
639 if (!strcmp(radlog_dir, "syslog")) {
640 openlog(progname, LOG_PID, syslog_facility);
642 /* Do you want a warning if -g is used without a -l to activate it? */
646 * Initialize the request list.
651 * We prefer (in order) the port from the command-line,
652 * then the port from the configuration file, then
653 * the port that the system names "radius", then
656 if (radius_port != 0) {
657 auth_port = radius_port;
658 } /* else auth_port is set from the config file */
661 * Maybe auth_port *wasn't* set from the config file,
662 * or the config file set it to zero.
665 if (auth_port == 0) {
666 svp = getservbyname ("radius", "udp");
668 auth_port = ntohs(svp->s_port);
671 * We're getting auth_port from
672 * /etc/services, get acct_port from
675 svp = getservbyname ("radacct", "udp");
677 acct_port = ntohs(svp->s_port);
679 auth_port = PW_AUTH_UDP_PORT;
684 * Open Authentication socket.
687 authfd = socket (AF_INET, SOCK_DGRAM, 0);
689 perror("auth socket");
693 sa = (struct sockaddr_in *) &salocal;
694 memset ((char *) sa, '\0', sizeof(salocal));
695 sa->sin_family = AF_INET;
696 sa->sin_addr.s_addr = myip;
697 sa->sin_port = htons(auth_port);
699 result = bind (authfd, & salocal, sizeof(*sa));
701 perror ("auth bind");
702 DEBUG(" There appears to be another RADIUS server already running on the authentication port UDP %d.", auth_port);
707 * Open Accounting Socket.
709 * If we haven't already gotten acct_port from /etc/services,
710 * then make it auth_port + 1.
713 acct_port = auth_port + 1;
715 acctfd = socket (AF_INET, SOCK_DGRAM, 0);
717 perror ("acct socket");
721 sa = (struct sockaddr_in *) &salocal;
722 memset ((char *) sa, '\0', sizeof(salocal));
723 sa->sin_family = AF_INET;
724 sa->sin_addr.s_addr = myip;
725 sa->sin_port = htons(acct_port);
727 result = bind (acctfd, & salocal, sizeof(*sa));
729 perror ("acct bind");
730 DEBUG(" There appears to be another RADIUS server already running on the accounting port UDP %d.", acct_port);
735 * If we're proxying requests, open the proxy FD.
736 * Otherwise, don't do anything.
738 if (proxy_requests == TRUE) {
742 proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
744 perror ("proxy socket");
748 sa = (struct sockaddr_in *) &salocal;
749 memset((char *) sa, '\0', sizeof(salocal));
750 sa->sin_family = AF_INET;
751 sa->sin_addr.s_addr = myip;
754 * Set the proxy port to be one more than the
757 for (proxy_port = acct_port + 1; proxy_port < 64000; proxy_port++) {
758 sa->sin_port = htons(proxy_port);
759 result = bind(proxyfd, & salocal, sizeof(*sa));
766 * Couldn't find a port to which we could bind.
768 if (proxy_port == 64000) {
769 perror("proxy bind");
775 * NOT proxying requests, set the FD to a bad value.
782 * Register built-in compare functions.
784 pair_builtincompare_init();
792 * Connect 0, 1 and 2 to /dev/null.
794 if (!debug_flag && devnull >= 0) {
796 if (strcmp(radlog_dir, "stdout") != 0) {
799 if (strcmp(radlog_dir, "stderr") != 0) {
802 if (devnull > 2) close(devnull);
807 * Disconnect from session
809 if (debug_flag == 0 && dont_fork == 0) {
812 radlog(L_ERR|L_CONS, "Couldn't fork");
817 * The parent exits, so the child can run in the background.
828 * Ensure that we're using the CORRECT pid after forking,
829 * NOT the one we started with.
831 radius_pid = getpid();
834 * Only write the PID file if we're running as a daemon.
836 * And write it AFTER we've forked, so that we write the
839 if (dont_fork == FALSE) {
842 fp = fopen(pid_file, "w");
844 fprintf(fp, "%d\n", (int) radius_pid);
847 radlog(L_ERR|L_CONS, "Failed writing process id to file %s: %s\n",
848 pid_file, strerror(errno));
854 * If we're spawning children, set up the thread pool.
856 if (spawn_flag == TRUE) {
862 * Use linebuffered or unbuffered stdout if
863 * the debug flag is on.
865 if (debug_flag == TRUE)
869 strcpy((char *)buffer, "*");
871 ip_ntoa((char *)buffer, myip);
874 if (proxy_requests == TRUE) {
875 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp, with proxy on %d/udp.",
876 buffer, auth_port, acct_port, proxy_port);
878 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp.",
879 buffer, auth_port, acct_port);
883 * Note that we NO LONGER fork an accounting process!
884 * We used to do it for historical reasons, but that
887 radlog(L_INFO, "Ready to process requests.");
890 * Receive user requests
894 if (reread_config(TRUE) < 0) {
898 radlog(L_INFO, "Ready to process requests.");
903 FD_SET(authfd, &readfds);
905 FD_SET(acctfd, &readfds);
907 FD_SET(proxyfd, &readfds);
909 if (rad_snmp.smux_fd >= 0)
910 FD_SET(rad_snmp.smux_fd, &readfds);
913 status = select(32, &readfds, NULL, NULL, tv);
916 * On interrupts, we clean up the
919 if (errno == EINTR) {
920 tv = rad_clean_list(time(NULL));
923 radlog(L_ERR, "Unexpected error in select(): %s",
929 * Loop over the open socket FD's, reading any data.
931 for (i = 0; i < 3; i++) {
933 if (i == 0) fd = authfd;
934 if (i == 1) fd = acctfd;
935 if (i == 2) fd = proxyfd;
936 if (fd < 0 || !FD_ISSET(fd, &readfds))
939 * Receive the packet.
941 packet = rad_recv(fd);
942 if (packet == NULL) {
943 radlog(L_ERR, "%s", librad_errstr);
948 rad_snmp.acct.total_requests++;
950 rad_snmp.auth.total_requests++;
954 * Check if we know this client for
955 * authfd and acctfd. Check if we know
956 * this proxy for proxyfd.
960 if ((cl = client_find(packet->src_ipaddr)) == NULL) {
961 radlog(L_ERR, "Ignoring request from unknown client %s:%d",
962 ip_ntoa((char *)buffer, packet->src_ipaddr),
970 } else { /* It came in on the proxy port */
972 if ((rl = realm_findbyaddr(packet->src_ipaddr)) == NULL) {
973 radlog(L_ERR, "Ignoring request from unknown proxy %s:%d",
974 ip_ntoa((char *)buffer, packet->src_ipaddr),
984 * Do yet another check, to see if the
985 * packet code is valid. We only understand
986 * a few, so stripping off obviously invalid
987 * packets here will make our life easier.
989 if (packet->code > PW_ACCESS_CHALLENGE) {
990 radlog(L_ERR, "Ignoring request from client %s:%d with unknown code %d", buffer, packet->src_port, packet->code);
995 request = rad_malloc(sizeof(REQUEST));
996 memset(request, 0, sizeof(REQUEST));
998 request->magic = REQUEST_MAGIC;
1000 request->packet = packet;
1001 request->proxy = NULL;
1002 request->reply = NULL;
1003 request->proxy_reply = NULL;
1004 request->config_items = NULL;
1005 request->username = NULL;
1006 request->password = NULL;
1007 request->timestamp = time(NULL);
1008 request->number = request_num_counter++;
1009 request->child_pid = NO_SUCH_CHILD_PID;
1010 request->container = NULL;
1011 strNcpy(request->secret, (char *)secret, sizeof(request->secret));
1012 rad_process(request, spawn_flag);
1013 } /* loop over authfd, acctfd, proxyfd */
1017 * After handling all authentication/accounting
1018 * requests, THEN process any pending SMUX/SNMP
1021 * Note that the handling is done in the main server,
1022 * which probably isn't a Good Thing. It really
1023 * should be wrapped, and handled in a thread pool.
1025 if ((rad_snmp.smux_fd >= 0) &&
1026 FD_ISSET(rad_snmp.smux_fd, &readfds) &&
1027 (rad_snmp.smux_event == SMUX_READ)) {
1032 * If we've got to re-connect, then do so now,
1033 * before calling select again.
1035 if (rad_snmp.smux_event == SMUX_CONNECT) {
1041 * After processing all new requests,
1042 * check if we've got to delete old requests
1043 * from the request list.
1045 tv = rad_clean_list(time(NULL));
1047 } /* loop forever */
1052 * Process supported requests:
1054 * PW_AUTHENTICATION_REQUEST - Authentication request from
1055 * a client network access server.
1057 * PW_ACCOUNTING_REQUEST - Accounting request from
1058 * a client network access server.
1060 * PW_AUTHENTICATION_ACK
1061 * PW_AUTHENTICATION_REJECT
1062 * PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
1063 * Relay reply back to original NAS.
1066 int rad_process(REQUEST *request, int dospawn)
1068 RAD_REQUEST_FUNP fun;
1072 assert(request->magic == REQUEST_MAGIC);
1074 switch(request->packet->code) {
1076 radlog(L_ERR, "Unknown packet type %d from client %s:%d "
1077 "- ID %d : IGNORED", request->packet->code,
1078 client_name(request->packet->src_ipaddr), request->packet->src_port,
1079 request->packet->id);
1080 request_free(&request);
1084 case PW_AUTHENTICATION_REQUEST:
1086 * Check for requests sent to the wrong port,
1087 * and ignore them, if so.
1089 if (request->packet->sockfd != authfd) {
1090 radlog(L_ERR, "Request packet code %d sent to authentication port from "
1091 "client %s:%d - ID %d : IGNORED", request->packet->code,
1092 client_name(request->packet->src_ipaddr), request->packet->src_port,
1093 request->packet->id);
1094 request_free(&request);
1097 fun = rad_authenticate;
1100 case PW_ACCOUNTING_REQUEST:
1102 * Check for requests sent to the wrong port,
1103 * and ignore them, if so.
1105 if (request->packet->sockfd != acctfd) {
1106 radlog(L_ERR, "Request packet code %d sent to accounting port from "
1107 "client %s:%d - ID %d : IGNORED", request->packet->code,
1108 client_name(request->packet->src_ipaddr), request->packet->src_port,
1109 request->packet->id);
1110 request_free(&request);
1113 fun = rad_accounting;
1116 case PW_AUTHENTICATION_ACK:
1117 case PW_AUTHENTICATION_REJECT:
1118 case PW_ACCOUNTING_RESPONSE:
1120 * Replies NOT sent to the proxy port get an
1121 * error message logged, and the packet is
1124 if (request->packet->sockfd != proxyfd) {
1125 radlog(L_ERR, "Reply packet code %d sent to request port from "
1126 "client %s:%d - ID %d : IGNORED", request->packet->code,
1127 client_name(request->packet->src_ipaddr), request->packet->src_port,
1128 request->packet->id);
1129 request_free(&request);
1132 if (request->packet->code != PW_ACCOUNTING_RESPONSE) {
1133 fun = rad_authenticate;
1135 fun = rad_accounting;
1139 case PW_PASSWORD_REQUEST:
1141 * We don't support this anymore.
1143 radlog(L_ERR, "Deprecated password change request from client %s:%d - ID %d : IGNORED",
1144 client_name(request->packet->src_ipaddr), request->packet->src_port,
1145 request->packet->id);
1146 request_free(&request);
1152 * Check for a duplicate, or error.
1153 * Throw away the the request if so.
1155 request = rad_check_list(request);
1156 if (request == NULL) {
1160 assert(request->magic == REQUEST_MAGIC);
1163 * The request passes many of our sanity checks. From
1164 * here on in, if anything goes wrong, we send a reject
1165 * message, instead of dropping the packet.
1167 * Build the reply template from the request template.
1169 if ((request->reply = rad_alloc(0)) == NULL) {
1170 radlog(L_ERR, "No memory");
1173 request->reply->sockfd = request->packet->sockfd;
1174 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1175 request->reply->dst_port = request->packet->src_port;
1176 request->reply->id = request->packet->id;
1177 request->reply->code = 0; /* UNKNOWN code */
1178 memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector));
1179 request->reply->vps = NULL;
1180 request->reply->data = NULL;
1181 request->reply->data_len = 0;
1184 * If we're spawning a child thread, let it do all of
1185 * the work of handling a request, and exit.
1187 if (dospawn == TRUE) {
1189 * Maybe the spawn failed. If so, then we
1190 * trivially reject the request (because we can't
1191 * handle it), and return.
1193 if (rad_spawn_child(request, fun) < 0) {
1194 rad_reject(request);
1195 request->finished = TRUE;
1200 rad_respond(request, fun);
1205 * Reject a request, by sending a trivial reply packet.
1207 static void rad_reject(REQUEST *request)
1211 DEBUG2("Server rejecting request %d.", request->number);
1212 switch (request->packet->code) {
1214 * Accounting requests, etc. get dropped on the floor.
1216 case PW_ACCOUNTING_REQUEST:
1221 * Authentication requests get their Proxy-State
1222 * attributes copied over, and an otherwise blank
1223 * reject message sent.
1225 case PW_AUTHENTICATION_REQUEST:
1226 request->reply->code = PW_AUTHENTICATION_REJECT;
1229 * Need to copy Proxy-State from request->packet->vps
1231 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
1233 pairadd(&(request->reply->vps), vps);
1238 * If a reply exists, send it.
1240 if (request->reply->code != 0)
1241 rad_send(request->reply, request->secret);
1245 * Perform any RFC specified cleaning of outgoing replies
1247 static void rfc_clean(RADIUS_PACKET *packet)
1249 VALUE_PAIR *vps = NULL;
1251 switch (packet->code) {
1256 * Authentication REJECT's can have only
1257 * Reply-Mesaage and Proxy-State. We delete
1258 * everything other than Reply-Message, and
1259 * Proxy-State is added below, just before
1260 * the reply is sent.
1262 case PW_AUTHENTICATION_REJECT:
1263 pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
1264 pairfree(&packet->vps);
1271 * FIXME: The next two functions should all
1272 * be in a module. But not until we have
1273 * more control over module execution.
1278 * Lowercase the string value of a pair.
1280 static int rad_lowerpair(REQUEST *request, VALUE_PAIR *vp) {
1285 rad_lowercase((char *)vp->strvalue);
1286 DEBUG2("rad_lowerpair: %s now '%s'", vp->name, vp->strvalue);
1291 * Remove spaces in a pair.
1293 static int rad_rmspace_pair(REQUEST *request, VALUE_PAIR *vp) {
1298 rad_rmspace((char *)vp->strvalue);
1299 vp->length = strlen((char *)vp->strvalue);
1300 DEBUG2("rad_rmspace_pair: %s now '%s'", vp->name, vp->strvalue);
1306 * Respond to a request packet.
1308 * Maybe we reply, maybe we don't.
1309 * Maybe we proxy the request to another server, or else maybe
1310 * we replicate it to another server.
1312 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
1314 RADIUS_PACKET *packet, *original;
1316 int finished = FALSE;
1321 * Put the decoded packet into it's proper place.
1323 if (request->proxy_reply != NULL) {
1324 packet = request->proxy_reply;
1325 secret = request->proxysecret;
1326 original = request->proxy;
1328 packet = request->packet;
1329 secret = request->secret;
1333 assert(request->magic == REQUEST_MAGIC);
1336 * Decode the packet, verifying it's signature,
1337 * and parsing the attributes into structures.
1339 * Note that we do this CPU-intensive work in
1340 * a child thread, not the master. This helps to
1341 * spread the load a little bit.
1343 * Internal requests (ones that never go on the
1344 * wire) have ->data==NULL (data is the wire
1345 * format) and don't need to be "decoded"
1347 if (packet->data && rad_decode(packet, original, secret) != 0) {
1348 radlog(L_ERR, "%s", librad_errstr);
1349 rad_reject(request);
1350 goto finished_request;
1354 * For proxy replies, remove non-allowed
1355 * attributes from the list of VP's.
1357 if (request->proxy) {
1359 replicating = proxy_receive(request);
1360 if (replicating != 0) {
1366 * We should have a User-Name attribute now.
1368 if (request->username == NULL) {
1369 request->username = pairfind(request->packet->vps,
1374 * We have the semaphore, and have decoded the packet.
1375 * Let's process the request.
1377 assert(request->magic == REQUEST_MAGIC);
1380 * FIXME: All this lowercase/nospace junk will be moved
1381 * into a module after module failover is fully in place
1383 * See if we have to lower user/pass before processing
1385 if(strcmp(mainconfig.do_lower_user, "before") == 0)
1386 rad_lowerpair(request, request->username);
1387 if(strcmp(mainconfig.do_lower_pass, "before") == 0)
1388 rad_lowerpair(request, rad_getpass(request));
1390 if(strcmp(mainconfig.do_nospace_user, "before") == 0)
1391 rad_rmspace_pair(request, request->username);
1392 if(strcmp(mainconfig.do_nospace_pass, "before") == 0)
1393 rad_rmspace_pair(request, rad_getpass(request));
1397 /* See if we have to lower user/pass after processing */
1398 if(strcmp(mainconfig.do_lower_user, "after") == 0) {
1399 rad_lowerpair(request, request->username);
1402 if(strcmp(mainconfig.do_lower_pass, "after") == 0) {
1403 rad_lowerpair(request, rad_getpass(request));
1406 if(strcmp(mainconfig.do_nospace_user, "after") == 0) {
1407 rad_rmspace_pair(request, request->username);
1410 if(strcmp(mainconfig.do_nospace_pass, "after") == 0) {
1411 rad_rmspace_pair(request, rad_getpass(request));
1415 /* Reprocess if we rejected last time */
1416 if ((fun == rad_authenticate) &&
1417 (request->reply->code == PW_AUTHENTICATION_REJECT) &&
1419 pairfree(&request->config_items);
1424 * If we don't already have a proxy
1425 * packet for this request, we MIGHT have
1428 if (proxy_requests) {
1429 if (request->proxy == NULL) {
1430 proxy_sent = proxy_send(request);
1433 * sent==1 means it's been proxied. The child
1434 * is done handling the request, but the request
1437 if (proxy_sent == 1) {
1438 goto postpone_request;
1441 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1442 (request->reply == NULL)) {
1444 * We're not configured to reply to the packet,
1445 * and we're not proxying, so the DEFAULT behaviour
1446 * is to REJECT the user.
1448 DEBUG2("There was no response configured: rejecting request %d", request->number);
1449 rad_reject(request);
1450 goto finished_request;
1454 * If we have a reply to send, copy the Proxy-State
1455 * attributes from the request to the tail of the reply,
1456 * and send the packet.
1458 assert(request->magic == REQUEST_MAGIC);
1459 if (request->reply->code != 0) {
1460 VALUE_PAIR *vp = NULL;
1463 * Perform RFC limitations on outgoing replies.
1465 rfc_clean(request->reply);
1468 * Need to copy Proxy-State from request->packet->vps
1470 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1472 pairadd(&(request->reply->vps), vp);
1474 rad_send(request->reply, request->secret);
1478 * We're done processing the request, set the
1479 * request to be finished, clean up as necessary,
1480 * and forget about the request.
1486 * We're done handling the request. Free up the linked
1487 * lists of value pairs. This might take a long time,
1488 * so it's more efficient to do it in a child thread,
1489 * instead of in the main handler when it eventually
1490 * gets around to deleting the request.
1492 * Also, no one should be using these items after the
1493 * request is finished, and the reply is sent. Cleaning
1494 * them up here ensures that they're not being used again.
1496 * Hmm... cleaning them up in the child thread also seems
1497 * to make the server run more efficiently!
1500 /* If we proxied this request, it's not safe to delete it until
1501 * after the proxy reply
1504 goto postpone_request;
1506 if (request->packet && request->packet->vps) {
1507 pairfree(&request->packet->vps);
1508 request->username = NULL;
1509 request->password = NULL;
1511 if (request->reply && request->reply->vps) {
1512 pairfree(&request->reply->vps);
1515 if (request->config_items) pairfree(&request->config_items);
1517 DEBUG2("Finished request %d", request->number);
1521 * Go to the next request, without marking
1522 * the current one as finished.
1525 DEBUG2("Going to the next request");
1527 #if WITH_THREAD_POOL
1528 request->child_pid = NO_SUCH_CHILD_PID; /* finished with child, so initialize for next use */
1530 request->finished = finished; /* do as the LAST thing before exiting */
1536 typedef struct rad_walk_t {
1542 * Clean up the request list, every so often.
1544 * This is done by walking through ALL of the list, and
1545 * - marking any requests which are finished, and expired
1546 * - killing any processes which are NOT finished after a delay
1547 * - deleting any marked requests.
1549 static REQUEST *last_request = NULL;
1550 static struct timeval *rad_clean_list(time_t now)
1553 * Static variables, so that we don't do all of this work
1554 * more than once per second.
1556 * Note that we have 'tv' and 'last_tv'. 'last_tv' is
1557 * pointed to by 'last_tv_ptr', and depending on the
1558 * system implementation of select(), it MAY be modified.
1560 * In that was, we want to use the ORIGINAL value, from
1561 * 'tv', and wipe out the (possibly modified) last_tv.
1563 static time_t last_cleaned_list = 0;
1564 static struct timeval tv, *last_tv_ptr = NULL;
1565 static struct timeval last_tv;
1573 * If we've already set up the timeout or cleaned the
1574 * request list this second, then don't do it again. We
1575 * simply return the sleep delay from last time.
1577 * Note that if we returned NULL last time, there was nothing
1578 * to do. BUT we've been woken up since then, which can only
1579 * happen if we received a packet. And if we've received a
1580 * packet, then there's some work to do in the future.
1582 * FIXME: We can probably use gettimeofday() for finer clock
1583 * resolution, as the current method will cause it to sleep
1586 if ((last_tv_ptr != NULL) &&
1587 (last_cleaned_list == now) &&
1592 * If we're NOT walking the entire request list,
1593 * then we want to iteratively check the request
1596 * If there is NO previous request, go look for one.
1599 last_request = rl_next(last_request);
1602 * On average, there will be one request per
1603 * 'cleanup_delay' requests, which needs to be
1606 * And only do this servicing, if we have a request
1610 for (i = 0; i < cleanup_delay; i++) {
1614 * This function call MAY delete the
1615 * request pointed to by 'last_request'.
1617 next = rl_next(last_request);
1618 refresh_request(last_request, &info);
1619 last_request = next;
1622 * Nothing to do any more, exit.
1629 DEBUG2("Waking up in %d seconds...",
1630 (int) last_tv_ptr->tv_sec);
1633 last_cleaned_list = now;
1634 last_request = NULL;
1635 DEBUG2("--- Walking the entire request list ---");
1637 #if WITH_THREAD_POOL
1639 * Only clean the thread pool if we've spawned child threads.
1642 thread_pool_clean(now);
1647 * Hmmm... this is Big Magic. We make it seem like
1648 * there's an additional second to wait, for a whole
1649 * host of reasons which I can't explain adequately,
1650 * but which cause the code to Just Work Right.
1654 rl_walk(refresh_request, &info);
1657 * We haven't found a time at which we need to wake up.
1658 * Return NULL, so that the select() call will sleep forever.
1660 if (info.smallest < 0) {
1661 DEBUG2("Nothing to do. Sleeping until we see a request.");
1666 * Set the time (in seconds) for how long we're
1667 * supposed to sleep.
1669 tv.tv_sec = info.smallest;
1671 DEBUG2("Waking up in %d seconds...", (int) info.smallest);
1674 * Remember how long we should sleep for.
1677 last_tv_ptr = &last_tv;
1682 * Walk through the request list, cleaning up complete child
1683 * requests, and verifing that there is only one process
1684 * responding to each request (duplicate requests are filtered
1687 * Also, check if the request is a reply from a request proxied to
1688 * a remote server. If so, play games with the request, and return
1691 static REQUEST *rad_check_list(REQUEST *request)
1697 * If the request has come in on the proxy FD, then
1698 * it's a proxy reply, so pass it through the proxy
1699 * code for checking the REQUEST list.
1701 if (request->packet->sockfd == proxyfd) {
1702 return proxy_check_list(request);
1705 * If the request already has a proxy packet,
1706 * then it obviously is not a new request, either.
1708 } else if (request->proxy != NULL) {
1712 now = request->timestamp; /* good enough for our purposes */
1715 * Look for an existing copy of this request.
1717 curreq = rl_find(request);
1718 if (curreq != NULL) {
1720 * We now check the authentication vectors.
1721 * If the client has sent us a request with
1722 * identical code && ID, but different vector,
1723 * then they MUST have gotten our response, so
1724 * we can delete the original request, and process
1727 * If the vectors are the same, then it's a duplicate
1728 * request, and we can send a duplicate reply.
1730 if (memcmp(curreq->packet->vector, request->packet->vector,
1731 sizeof(request->packet->vector)) == 0) {
1733 * Maybe we've saved a reply packet. If so,
1734 * re-send it. Otherwise, just complain.
1736 if ((curreq->reply) && (curreq->reply->code != 0)) {
1737 radlog(L_INFO, "Sending duplicate authentication reply"
1738 " to client %s:%d - ID: %d", client_name(curreq->packet->src_ipaddr),
1739 curreq->packet->src_port, curreq->packet->id);
1741 rad_send(curreq->reply, curreq->secret);
1744 * There's no reply, but maybe there's
1745 * an outstanding proxy request.
1747 * If so, then kick the proxy again.
1749 } else if (curreq->proxy != NULL) {
1750 if (proxy_synchronous) {
1751 DEBUG2("Sending duplicate proxy request to client %s:%d - ID: %d",
1752 client_name(curreq->proxy->dst_ipaddr), request->packet->src_port,
1755 curreq->proxy_next_try = request->timestamp + proxy_retry_delay;
1756 rad_send(curreq->proxy, curreq->proxysecret);
1758 DEBUG2("Ignoring duplicate authentication packet"
1759 " from client %s:%d - ID: %d, due to outstanding proxy request.",
1760 client_name(request->packet->src_ipaddr),
1761 request->packet->src_port,
1762 request->packet->id);
1766 * This request wasn't proxied.
1768 radlog(L_ERR, "Dropping duplicate authentication packet"
1769 " from client %s:%d - ID: %d", client_name(request->packet->src_ipaddr),
1770 request->packet->src_port, request->packet->id);
1774 * Delete the duplicate request.
1776 request_free(&request);
1780 * The packet vectors are different, so
1781 * we can delete the old request from
1784 } else if (curreq->finished) {
1785 if (last_request == curreq) {
1786 last_request = rl_next(last_request);
1791 * ??? the client sent us a new request
1792 * with the same ID, while we were
1793 * processing the old one! What should
1796 * Right now, we just drop the new packet..
1799 radlog(L_ERR, "Dropping conflicting authentication packet"
1800 " from client %s:%d - ID: %d",
1801 client_name(request->packet->src_ipaddr),
1802 request->packet->src_port,
1803 request->packet->id);
1804 request_free(&request);
1807 } /* a similar packet already exists. */
1810 * Count the total number of requests, to see if there
1811 * are too many. If so, return with an error.
1814 int request_count = rl_num_requests();
1817 * This is a new request. Let's see if it
1818 * makes us go over our configured bounds.
1820 if (request_count > max_requests) {
1821 radlog(L_ERR, "Dropping request (%d is too many): "
1822 "from client %s:%d - ID: %d", request_count,
1823 client_name(request->packet->src_ipaddr),
1824 request->packet->src_port,
1825 request->packet->id);
1826 radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n"
1827 "\tThe value for 'max_requests' is probably set too low.\n");
1828 request_free(&request);
1834 * Add this request to the list
1839 * And return the request to be handled.
1844 #ifndef WITH_THREAD_POOL
1846 typedef struct spawn_thread_t {
1848 RAD_REQUEST_FUNP fun;
1852 * Spawn a new child thread to handle this request, and ONLY
1855 static void *rad_spawn_thread(void *arg)
1858 spawn_thread_t *data = (spawn_thread_t *)arg;
1860 pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
1863 * Keep only allowed attributes in the request.
1865 if (data->request->proxy) {
1866 replicating = proxy_receive(data->request);
1867 if (replicating != 0) {
1868 data->request->finished = TRUE;
1874 rad_respond(data->request, data->fun);
1875 data->request->child_pid = NO_SUCH_CHILD_PID;
1883 * If we're using the thread pool, then the function in
1884 * 'threads.c' replaces this one.
1886 #ifndef WITH_THREAD_POOL
1888 * Spawns a child process or thread to perform
1889 * authentication/accounting and respond to RADIUS clients.
1891 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
1893 child_pid_t child_pid;
1897 spawn_thread_t *data;
1899 data = (spawn_thread_t *) rad_malloc(sizeof(spawn_thread_t));
1900 memset(data, 0, sizeof(data));
1901 data->request = request;
1905 * Create a child thread, complaining on error.
1907 rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
1909 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
1910 nas_name2(request->packet), request->packet->id, strerror(errno));
1915 * Detach it, so it's state is automagically cleaned up on exit.
1917 pthread_detach(child_pid);
1924 if (child_pid < 0) {
1925 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
1926 nas_name2(request->packet),
1927 request->packet->id);
1931 if (child_pid == 0) {
1934 * This is the child, it should go ahead and respond
1936 signal(SIGCHLD, SIG_DFL);
1937 rad_respond(request, fun);
1943 * Register the Child
1945 request->child_pid = child_pid;
1948 #endif /* WITH_THREAD_POOL */
1951 void sig_cleanup(int sig)
1953 #ifndef HAVE_PTHREAD_H
1959 sig = sig; /* -Wunused */
1964 * Reset the signal handler, if required.
1966 reset_signal(SIGCHLD, sig_cleanup);
1969 * If we're using pthreads, then there are NO child processes,
1970 * so the waitpid() call, and the following code, is useless.
1972 #ifndef HAVE_PTHREAD_H
1974 pid = waitpid((pid_t)-1, &status, WNOHANG);
1979 * Check to see if the child did a bad thing.
1980 * If so, kill ALL processes in the current
1981 * process group, to prevent further attacks.
1983 if (debug_flag && (WIFSIGNALED(status))) {
1984 radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
1985 pid, WTERMSIG(status));
1991 * Loop over ALL of the active requests, looking
1992 * for the one which caused the signal.
1994 for (curreq = rl_next(NULL); curreq != NULL; curreq = rl_next(curreq)) {
1995 if (curreq->child_pid == pid) {
1996 curreq->child_pid = NO_SUCH_CHILD_PID;
2001 #endif /* !defined HAVE_PTHREAD_H */
2005 * Display the syntax for starting this program.
2007 static void usage(void)
2010 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2011 #if defined(WITH_DBM) || defined(WITH_NDBM)
2014 "AcfnsSvXxyz]\n", progname);
2015 fprintf(stderr, "Options:\n\n");
2016 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2017 fprintf(stderr, " -A Log auth detail.\n");
2018 #if defined(WITH_DBM) || defined(WITH_NDBM)
2019 fprintf(stderr, " -b Use DBM.\n");
2021 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2022 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2023 fprintf(stderr, " -h Print this help message.\n");
2024 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2025 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2026 fprintf(stderr, " stdout == log all messages to standard output.\n");
2027 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2028 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2029 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2030 fprintf(stderr, " -S Log stripped names.\n");
2031 fprintf(stderr, " -v Print server version information.\n");
2032 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2033 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2034 fprintf(stderr, " -y Log authentication failures, with password.\n");
2035 fprintf(stderr, " -z Log authentication successes, with password.\n");
2041 * We got a fatal signal. Clean up and exit.
2043 static void sig_fatal(int sig)
2045 const char *me = "MASTER: ";
2047 if (radius_pid != getpid()) {
2053 radlog(L_ERR, "%sfailed in select() - exit.", me);
2056 radlog(L_INFO, "%sexit.", me);
2059 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2064 * We're running as a daemon, we're the MASTER daemon,
2065 * and we got a fatal signal. Tear the rest of the
2066 * daemons down, as something absolutely horrible happened.
2068 if ((debug_flag == 0) && (dont_fork == 0) &&
2069 (radius_pid == getpid())) {
2071 * Kill all of the processes in the current
2077 exit(sig == SIGTERM ? 0 : 1);
2082 * We got the hangup signal.
2083 * Re-read the configuration files.
2086 static void sig_hup(int sig)
2088 sig = sig; /* -Wunused */
2089 reset_signal(SIGHUP, sig_hup);
2092 * Only do the reload if we're the main server, both
2093 * for processes, and for threads.
2095 if (getpid() == radius_pid) {
2099 rad_snmp.smux_failures = 0;
2100 rad_snmp.smux_event = SMUX_CONNECT;
2105 * Do a proxy check of the REQUEST list when using the new proxy code.
2107 static REQUEST *proxy_check_list(REQUEST *request)
2112 * Find the original request in the request list
2114 oldreq = rl_find_proxy(request);
2117 * If there is already a reply,
2118 * maybe the new one is a duplicate?
2120 if (oldreq->proxy_reply) {
2121 if (memcmp(oldreq->proxy_reply->vector,
2122 request->packet->vector,
2123 sizeof(oldreq->proxy_reply->vector)) == 0) {
2124 DEBUG2("Ignoring duplicate proxy reply");
2125 request_free(&request);
2129 * ??? The home server gave us a new
2130 * proxy reply, which doesn't match
2131 * the old one. Delete it!
2133 DEBUG2("Ignoring conflicting proxy reply");
2134 request_free(&request);
2137 } /* else there's no reply yet. */
2141 * If we haven't found the old request, complain.
2143 radlog(L_PROXY, "No request found for proxy reply from server %s - ID %d",
2144 client_name(request->packet->src_ipaddr),
2145 request->packet->id);
2146 request_free(&request);
2151 * Refresh the old request, and update it with the proxy reply.
2153 * ??? Can we delete the proxy request here?
2154 * Is there any more need for it?
2156 oldreq->timestamp = request->timestamp;
2157 oldreq->proxy_reply = request->packet;
2158 request->packet = NULL;
2159 request_free(&request);
2164 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
2165 * max_request_time, etc.
2167 * When walking over the request list, all of the per-request
2168 * magic is done here.
2170 static int refresh_request(REQUEST *request, void *data)
2172 rad_walk_t *info = (rad_walk_t *) data;
2174 child_pid_t child_pid;
2176 assert(request->magic == REQUEST_MAGIC);
2179 * If the request has finished processing,
2180 * AND it's child has been cleaned up,
2181 * AND it's time to clean up the request,
2182 * OR, it's an accounting request.
2183 * THEN, go delete it.
2185 * If this is an accounting request, we delete it
2186 * immediately, as there CANNOT be duplicate accounting
2187 * packets. If there are, then something else is
2188 * seriously wrong...
2190 if (request->finished &&
2191 (request->child_pid == NO_SUCH_CHILD_PID) &&
2192 ((request->timestamp + cleanup_delay <= info->now) ||
2193 (request->packet->code == PW_ACCOUNTING_REQUEST))) {
2195 * Request completed, delete it, and unlink it
2196 * from the currently 'alive' list of requests.
2198 DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
2199 request->number, request->packet->id,
2200 (unsigned long)request->timestamp);
2203 * Delete the request.
2206 return RL_WALK_CONTINUE;
2210 * Maybe the child process
2211 * handling the request has hung:
2212 * kill it, and continue.
2214 if ((request->timestamp + max_request_time) <= info->now) {
2217 child_pid = request->child_pid;
2218 number = request->number;
2220 if (kill_unresponsive_children) {
2221 if (child_pid != NO_SUCH_CHILD_PID) {
2223 * This request seems to have hung
2226 #ifdef WITH_THREAD_POOL || HAVE_PTHREAD_H
2227 radlog(L_ERR, "Killing unresponsive thread for request %d",
2229 pthread_cancel(child_pid);
2231 radlog(L_ERR, "Killing unresponsive child %lu for request %d",
2232 child_pid, request->number);
2233 kill(child_pid, SIGTERM);
2235 } /* else no proxy reply, quietly fail */
2238 * Delete the request.
2241 child_pid = NO_SUCH_CHILD_PID; /* mark it as deleted. */
2244 * Maybe we haven't killed it. In that case, print
2247 } else if (child_pid != NO_SUCH_CHILD_PID) {
2248 radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d",
2251 return RL_WALK_CONTINUE;
2255 * The request is finished.
2257 if (request->finished) goto setup_timeout;
2260 * We're not proxying requests at all.
2262 if (!proxy_requests) goto setup_timeout;
2265 * We're proxying synchronously, so the retry_delay is zero.
2266 * Some other code takes care of retrying the proxy requests.
2268 if (proxy_retry_delay == 0) goto setup_timeout;
2271 * There is no proxied request for this packet, so there's
2274 if (!request->proxy) goto setup_timeout;
2277 * We've already seen the proxy reply, so we don't need
2278 * to send another proxy request.
2280 if (request->proxy_reply) goto setup_timeout;
2283 * It's not yet time to re-send this proxied request.
2285 if (request->proxy_next_try > info->now) goto setup_timeout;
2288 * If the proxy retry count is zero, then
2289 * we've sent the last try, and have NOT received
2290 * a reply from the end server. In that case,
2291 * we don't bother trying again, but just mark
2292 * the request as finished, and go to the next one.
2294 if (request->proxy_try_count == 0) {
2295 request->finished = TRUE;
2296 rad_reject(request);
2301 * We're trying one more time, so count down
2302 * the tries, and set the next try time.
2304 request->proxy_try_count--;
2305 request->proxy_next_try = info->now + proxy_retry_delay;
2307 /* Fix up Acct-Delay-Time */
2308 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2309 VALUE_PAIR *delaypair;
2310 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
2313 delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
2315 radlog(L_ERR|L_CONS, "no memory");
2318 pairadd(&request->proxy->vps, delaypair);
2320 delaypair->lvalue = info->now - request->proxy->timestamp;
2322 /* Must recompile the valuepairs to wire format */
2323 free(request->proxy->data);
2324 request->proxy->data = NULL;
2325 } /* proxy accounting request */
2328 * Send the proxy packet.
2330 rad_send(request->proxy, request->proxysecret);
2334 * Don't do more long-term checks, if we've got to wake
2337 if (info->smallest == 0) {
2338 return RL_WALK_CONTINUE;
2342 * The request is finished. Wake up when it's time to
2345 if (request->finished) {
2346 difference = (request->timestamp + cleanup_delay) - info->now;
2348 } else if (request->proxy && !request->proxy_reply) {
2350 * The request is NOT finished, but there is an
2351 * outstanding proxy request, with no matching
2354 * Wake up when it's time to re-send
2355 * the proxy request.
2357 difference = request->proxy_next_try - info->now;
2361 * The request is NOT finished.
2363 * Wake up when it's time to kill the errant
2366 difference = (request->timestamp + max_request_time) - info->now;
2370 * If the server is CPU starved, then we CAN miss a time
2371 * for servicing requests. In which case the 'difference'
2372 * value will be negative. select() doesn't like that,
2375 if (difference < 0) {
2380 * Update the 'smallest' time.
2382 if ((info->smallest < 0) ||
2383 (difference < info->smallest)) {
2384 info->smallest = difference;
2387 return RL_WALK_CONTINUE;