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;
114 static int got_child = FALSE;
118 static pid_t radius_pid;
119 static int request_num_counter = 0; /* per-request unique ID */
122 * Configuration items.
124 static int allow_core_dumps = FALSE;
125 static int max_request_time = MAX_REQUEST_TIME;
126 static int cleanup_delay = CLEANUP_DELAY;
127 static int max_requests = MAX_REQUESTS;
128 static int dont_fork = FALSE;
129 static const char *pid_file = NULL;
130 static uid_t server_uid;
131 static gid_t server_gid;
132 static const char *uid_name = NULL;
133 static const char *gid_name = NULL;
134 static int proxy_requests = TRUE;
135 int spawn_flag = TRUE;
136 static struct rlimit core_limits;
138 static void usage(void);
140 static void sig_fatal (int);
141 static void sig_hup (int);
143 static void rad_reject(REQUEST *request);
144 static struct timeval *rad_clean_list(time_t curtime);
145 static REQUEST *rad_check_list(REQUEST *);
146 static REQUEST *proxy_check_list(REQUEST *request);
147 static int refresh_request(REQUEST *request, void *data);
148 #ifndef WITH_THREAD_POOL
149 static int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
151 extern int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
155 * Map the proxy server configuration parameters to variables.
157 static CONF_PARSER proxy_config[] = {
158 { "retry_delay", PW_TYPE_INTEGER, 0, &proxy_retry_delay, Stringify(RETRY_DELAY) },
159 { "retry_count", PW_TYPE_INTEGER, 0, &proxy_retry_count, Stringify(RETRY_COUNT) },
160 { "synchronous", PW_TYPE_BOOLEAN, 0, &proxy_synchronous, "yes" },
161 { NULL, -1, 0, NULL, NULL }
165 * A mapping of configuration file names to internal variables
167 static CONF_PARSER server_config[] = {
168 { "max_request_time", PW_TYPE_INTEGER, 0, &max_request_time, Stringify(MAX_REQUEST_TIME) },
169 { "cleanup_delay", PW_TYPE_INTEGER, 0, &cleanup_delay, Stringify(CLEANUP_DELAY) },
170 { "max_requests", PW_TYPE_INTEGER, 0, &max_requests, Stringify(MAX_REQUESTS) },
171 { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
172 { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &allow_core_dumps, "no" },
173 { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
174 { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
175 { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
176 { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
177 { "pidfile", PW_TYPE_STRING_PTR, 0, &pid_file, "${run_dir}/radiusd.pid"},
178 { "bind_address", PW_TYPE_IPADDR, 0, &myip, "*" },
179 { "user", PW_TYPE_STRING_PTR, 0, &uid_name, "nobody"},
180 { "group", PW_TYPE_STRING_PTR, 0, &gid_name, "nobody"},
181 { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide, "no" },
182 { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
183 { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
184 { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
185 { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
186 { "proxy_requests", PW_TYPE_BOOLEAN, 0, &proxy_requests, "yes" },
187 { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
188 { NULL, -1, 0, NULL, NULL }
194 static int reread_config(int reload)
200 radlog(L_INFO, "Starting - reading configuration files ...");
201 } else if (pid == radius_pid) {
202 radlog(L_INFO, "Reloading configuration files.");
205 /* First read radiusd.conf */
206 DEBUG2("reread_config: reading radiusd.conf");
207 if (read_radius_conf_file() < 0) {
208 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
213 * And parse the server's configuration values.
215 cs = cf_section_find(NULL);
217 radlog(L_ERR|L_CONS, "No configuration information in radiusd.conf!");
220 cf_section_parse(cs, NULL, server_config);
223 * Reload the modules.
225 DEBUG2("read_config_files: entering modules setup");
226 if (setup_modules() < 0) {
227 radlog(L_ERR|L_CONS, "Errors setting up modules");
232 * Go update our behaviour, based on the configuration
235 if (allow_core_dumps) {
236 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
237 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
242 * If we're running as a daemon, and core
243 * dumps are enabled, log that information.
245 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
246 radlog(L_INFO, "Core dumps are enabled.");
248 } else if (!debug_flag) {
250 * Not debugging. Set the core size to zero, to
251 * prevent security breaches. i.e. People
252 * reading passwords from the 'core' file.
254 struct rlimit limits;
257 limits.rlim_max = core_limits.rlim_max;
259 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
260 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
267 * Set the UID and GID, but only if we're NOT running
275 if (gid_name != NULL) {
278 gr = getgrnam(gid_name);
280 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: %s", gid_name, strerror(errno));
283 server_gid = gr->gr_gid;
284 if (setgid(server_gid) < 0) {
285 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s", gid_name, strerror(errno));
293 if (uid_name != NULL) {
296 pw = getpwnam(uid_name);
298 radlog(L_ERR|L_CONS, "Cannot switch to User %s: %s", uid_name, strerror(errno));
301 server_uid = pw->pw_uid;
302 if (setuid(server_uid) < 0) {
303 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", uid_name, strerror(errno));
313 * Parse a string into a syslog facility level.
315 static int str2fac(const char *s)
318 if(!strcmp(s, "kern"))
323 if(!strcmp(s, "user"))
328 if(!strcmp(s, "mail"))
333 if(!strcmp(s, "daemon"))
338 if(!strcmp(s, "auth"))
343 if(!strcmp(s, "auth"))
348 if(!strcmp(s, "lpr"))
353 if(!strcmp(s, "news"))
358 if(!strcmp(s, "uucp"))
363 if(!strcmp(s, "cron"))
368 if(!strcmp(s, "authpriv"))
373 if(!strcmp(s, "ftp"))
378 if(!strcmp(s, "local0"))
383 if(!strcmp(s, "local1"))
388 if(!strcmp(s, "local2"))
393 if(!strcmp(s, "local3"))
398 if(!strcmp(s, "local4"))
403 if(!strcmp(s, "local5"))
408 if(!strcmp(s, "local6"))
413 if(!strcmp(s, "local7"))
418 fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
423 /* this should never be reached */
427 int main(int argc, char **argv)
430 RADIUS_PACKET *packet;
432 unsigned char buffer[4096];
433 struct sockaddr_in salocal;
434 struct sockaddr_in *sa;
444 int syslog_facility = LOG_DAEMON;
447 struct timeval *tv = NULL;
450 set_auth_parameters(argc,argv);
454 * Open /dev/null, and make sure filedescriptors
455 * 0, 1 and 2 are connected to something.
458 while (devnull >= 0 && devnull < 3)
459 devnull = open("/dev/null", O_RDWR);
461 if ((progname = strrchr(argv[0], '/')) == NULL)
468 radius_dir = strdup(RADIUS_DIR);
470 signal(SIGHUP, sig_hup);
471 signal(SIGINT, sig_fatal);
472 signal(SIGQUIT, sig_fatal);
474 signal(SIGPIPE, SIG_IGN);
477 signal(SIGTRAP, sig_fatal);
480 signal(SIGIOT, sig_fatal);
484 * Pooled threads and child threads define their own
487 #ifndef WITH_THREAD_POOL
488 #ifndef HAVE_PTHREAD_H
489 signal(SIGTERM, sig_fatal);
492 signal(SIGCHLD, sig_cleanup);
494 signal(SIGFPE, sig_fatal);
495 signal(SIGSEGV, sig_fatal);
496 signal(SIGILL, sig_fatal);
500 * Close unused file descriptors.
502 for (t = 32; t >= 3; t--)
507 * Process the options.
509 while((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:p:sSvxXyz")) != EOF) {
514 log_auth_detail = TRUE;
518 radacct_dir = strdup(optarg);
521 #if defined(WITH_DBM) || defined(WITH_NDBM)
527 /* ignore for backwards compatibility with Cistron */
531 radius_dir = strdup(optarg);
543 if ((myip = ip_getaddr(optarg)) == INADDR_NONE) {
544 fprintf(stderr, "radiusd: %s: host unknown\n",
551 radlog_dir = strdup(optarg);
555 * We should also have this as a configuration
559 syslog_facility = str2fac(optarg);
563 log_stripped_names++;
567 radius_port = atoi(optarg);
570 case 's': /* Single process mode */
579 * BIG debugging mode for users who are
580 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
587 mainconfig.log_auth = TRUE;
588 mainconfig.log_auth_badpass = TRUE;
589 mainconfig.log_auth_goodpass = TRUE;
590 radlog_dir = strdup("stdout");
599 mainconfig.log_auth = TRUE;
600 mainconfig.log_auth_badpass = TRUE;
604 mainconfig.log_auth_badpass = TRUE;
605 mainconfig.log_auth_goodpass = TRUE;
615 * Get out PID: the configuration file reader uses it.
617 radius_pid = getpid();
620 * Get the current maximum for core files.
622 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
623 radlog(L_ERR|L_CONS, "Failed to get current core limit:"
624 " %s", strerror(errno));
629 * Read the configuration files, BEFORE doing anything else.
631 if (reread_config(0) < 0) {
637 * If they asked for syslog, then give it to them.
638 * Also, initialize the logging facility with the
639 * configuration that they asked for.
641 if (!strcmp(radlog_dir, "syslog")) {
642 openlog(progname, LOG_PID, syslog_facility);
644 /* Do you want a warning if -g is used without a -l to activate it? */
648 * Initialize the request list.
653 * We prefer (in order) the port from the command-line,
654 * then the port from the configuration file, then
655 * the port that the system names "radius", then
658 if (radius_port != 0) {
659 auth_port = radius_port;
660 } /* else auth_port is set from the config file */
663 * Maybe auth_port *wasn't* set from the config file,
664 * or the config file set it to zero.
667 if (auth_port == 0) {
668 svp = getservbyname ("radius", "udp");
670 auth_port = ntohs(svp->s_port);
673 * We're getting auth_port from
674 * /etc/services, get acct_port from
677 svp = getservbyname ("radacct", "udp");
679 acct_port = ntohs(svp->s_port);
681 auth_port = PW_AUTH_UDP_PORT;
686 * Open Authentication socket.
689 authfd = socket (AF_INET, SOCK_DGRAM, 0);
691 perror("auth socket");
695 sa = (struct sockaddr_in *) &salocal;
696 memset ((char *) sa, '\0', sizeof(salocal));
697 sa->sin_family = AF_INET;
698 sa->sin_addr.s_addr = myip;
699 sa->sin_port = htons(auth_port);
701 result = bind (authfd, & salocal, sizeof(*sa));
703 perror ("auth bind");
704 DEBUG(" There appears to be another RADIUS server already running on the authentication port UDP %d.", auth_port);
709 * Open Accounting Socket.
711 * If we haven't already gotten acct_port from /etc/services,
712 * then make it auth_port + 1.
715 acct_port = auth_port + 1;
717 acctfd = socket (AF_INET, SOCK_DGRAM, 0);
719 perror ("acct socket");
723 sa = (struct sockaddr_in *) &salocal;
724 memset ((char *) sa, '\0', sizeof(salocal));
725 sa->sin_family = AF_INET;
726 sa->sin_addr.s_addr = myip;
727 sa->sin_port = htons(acct_port);
729 result = bind (acctfd, & salocal, sizeof(*sa));
731 perror ("acct bind");
732 DEBUG(" There appears to be another RADIUS server already running on the accounting port UDP %d.", acct_port);
737 * If we're proxying requests, open the proxy FD.
738 * Otherwise, don't do anything.
740 if (proxy_requests == TRUE) {
744 proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
746 perror ("proxy socket");
750 sa = (struct sockaddr_in *) &salocal;
751 memset((char *) sa, '\0', sizeof(salocal));
752 sa->sin_family = AF_INET;
753 sa->sin_addr.s_addr = myip;
756 * Set the proxy port to be one more than the
759 for (proxy_port = acct_port + 1; proxy_port < 64000; proxy_port++) {
760 sa->sin_port = htons(proxy_port);
761 result = bind(proxyfd, & salocal, sizeof(*sa));
768 * Couldn't find a port to which we could bind.
770 if (proxy_port == 64000) {
771 perror("proxy bind");
777 * NOT proxying requests, set the FD to a bad value.
784 * Register built-in compare functions.
786 pair_builtincompare_init();
794 * Connect 0, 1 and 2 to /dev/null.
796 if (!debug_flag && devnull >= 0) {
798 if (strcmp(radlog_dir, "stdout") != 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(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(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(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(vp->strvalue);
1299 vp->length = strlen(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;
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) {
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 * If the child *thread* gets a termination signal,
1853 * then exit from the thread.
1855 static void sig_term(int sig)
1857 sig = sig; /* -Wunused */
1862 * Spawn a new child thread to handle this request, and ONLY
1865 static void *rad_spawn_thread(void *arg)
1868 spawn_thread_t *data = (spawn_thread_t *)arg;
1871 * Note that this behaviour only works on Linux.
1873 * It's generally NOT the thing to do, and should
1876 * Q: How do we signal a hung thread, and tell it to
1879 signal(SIGTERM, sig_term);
1882 * Keep only allowed attributes in the request.
1884 if (data->request->proxy) {
1885 replicating = proxy_receive(data->request);
1886 if (replicating != 0) {
1887 data->request->finished = TRUE;
1893 rad_respond(data->request, data->fun);
1894 data->request->child_pid = NO_SUCH_CHILD_PID;
1902 * If we're using the thread pool, then the function in
1903 * 'threads.c' replaces this one.
1905 #ifndef WITH_THREAD_POOL
1907 * Spawns a child process or thread to perform
1908 * authentication/accounting and respond to RADIUS clients.
1910 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
1912 child_pid_t child_pid;
1916 spawn_thread_t *data;
1918 data = (spawn_thread_t *) rad_malloc(sizeof(spawn_thread_t));
1919 memset(data, 0, sizeof(data));
1920 data->request = request;
1924 * Create a child thread, complaining on error.
1926 rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
1928 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
1929 nas_name2(request->packet), request->packet->id, strerror(errno));
1934 * Detach it, so it's state is automagically cleaned up on exit.
1936 pthread_detach(child_pid);
1943 if (child_pid < 0) {
1944 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
1945 nas_name2(request->packet),
1946 request->packet->id);
1950 if (child_pid == 0) {
1953 * This is the child, it should go ahead and respond
1955 signal(SIGCHLD, SIG_DFL);
1956 rad_respond(request, fun);
1962 * Register the Child
1964 request->child_pid = child_pid;
1967 #endif /* WITH_THREAD_POOL */
1970 void sig_cleanup(int sig)
1972 #ifndef HAVE_PTHREAD_H
1979 sig = sig; /* -Wunused */
1984 * Reset the signal handler, if required.
1986 reset_signal(SIGCHLD, sig_cleanup);
1989 * If we're using pthreads, then there are NO child processes,
1990 * so the waitpid() call, and the following code, is useless.
1992 #ifndef HAVE_PTHREAD_H
1994 pid = waitpid((pid_t)-1, &status, WNOHANG);
1999 * Check to see if the child did a bad thing.
2000 * If so, kill ALL processes in the current
2001 * process group, to prevent further attacks.
2003 if (debug_flag && (WIFSIGNALED(status))) {
2004 radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
2005 pid, WTERMSIG(status));
2011 * Loop over ALL of the active requests, looking
2012 * for the one which caused the signal.
2014 for (curreq = rl_next(NULL); curreq != NULL; curreq = rl_next(curreq)) {
2015 if (curreq->child_pid == pid) {
2016 curreq->child_pid = NO_SUCH_CHILD_PID;
2021 #endif /* !defined HAVE_PTHREAD_H */
2025 * Display the syntax for starting this program.
2027 static void usage(void)
2030 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2031 #if defined(WITH_DBM) || defined(WITH_NDBM)
2034 "AcfnsSvXxyz]\n", progname);
2035 fprintf(stderr, "Options:\n\n");
2036 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2037 fprintf(stderr, " -A Log auth detail.\n");
2038 #if defined(WITH_DBM) || defined(WITH_NDBM)
2039 fprintf(stderr, " -b Use DBM.\n");
2041 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2042 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2043 fprintf(stderr, " -h Print this help message.\n");
2044 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2045 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2046 fprintf(stderr, " stdout == log all messages to standard output.\n");
2047 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2048 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2049 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2050 fprintf(stderr, " -S Log stripped names.\n");
2051 fprintf(stderr, " -v Print server version information.\n");
2052 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2053 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2054 fprintf(stderr, " -y Log authentication failures, with password.\n");
2055 fprintf(stderr, " -z Log authentication successes, with password.\n");
2061 * We got a fatal signal. Clean up and exit.
2063 static void sig_fatal(int sig)
2065 const char *me = "MASTER: ";
2067 if (radius_pid != getpid()) {
2073 radlog(L_ERR, "%saccounting process died - exit.", me);
2076 radlog(L_ERR, "%sfailed in select() - exit.", me);
2079 radlog(L_INFO, "%sexit.", me);
2082 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2087 * We're running as a daemon, we're the MASTER daemon,
2088 * and we got a fatal signal. Tear the rest of the
2089 * daemons down, as something absolutely horrible happened.
2091 if ((debug_flag == 0) && (dont_fork == 0) &&
2092 (radius_pid == getpid())) {
2094 * Kill all of the processes in the current
2100 exit(sig == SIGTERM ? 0 : 1);
2105 * We got the hangup signal.
2106 * Re-read the configuration files.
2109 static void sig_hup(int sig)
2111 sig = sig; /* -Wunused */
2112 reset_signal(SIGHUP, sig_hup);
2115 * Only do the reload if we're the main server, both
2116 * for processes, and for threads.
2118 if (getpid() == radius_pid) {
2122 rad_snmp.smux_failures = 0;
2123 rad_snmp.smux_event = SMUX_CONNECT;
2128 * Do a proxy check of the REQUEST list when using the new proxy code.
2130 static REQUEST *proxy_check_list(REQUEST *request)
2135 * Find the original request in the request list
2137 oldreq = rl_find_proxy(request);
2140 * If there is already a reply,
2141 * maybe the new one is a duplicate?
2143 if (oldreq->proxy_reply) {
2144 if (memcmp(oldreq->proxy_reply->vector,
2145 request->packet->vector,
2146 sizeof(oldreq->proxy_reply->vector)) == 0) {
2147 DEBUG2("Ignoring duplicate proxy reply");
2148 request_free(&request);
2152 * ??? The home server gave us a new
2153 * proxy reply, which doesn't match
2154 * the old one. Delete it!
2156 DEBUG2("Ignoring conflicting proxy reply");
2157 request_free(&request);
2160 } /* else there's no reply yet. */
2164 * If we haven't found the old request, complain.
2166 radlog(L_PROXY, "No request found for proxy reply from server %s - ID %d",
2167 client_name(request->packet->src_ipaddr),
2168 request->packet->id);
2169 request_free(&request);
2174 * Refresh the old request, and update it with the proxy reply.
2176 * ??? Can we delete the proxy request here?
2177 * Is there any more need for it?
2179 oldreq->timestamp = request->timestamp;
2180 oldreq->proxy_reply = request->packet;
2181 request->packet = NULL;
2182 request_free(&request);
2187 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
2188 * max_request_time, etc.
2190 * When walking over the request list, all of the per-request
2191 * magic is done here.
2193 static int refresh_request(REQUEST *request, void *data)
2195 rad_walk_t *info = (rad_walk_t *) data;
2197 child_pid_t child_pid;
2199 assert(request->magic == REQUEST_MAGIC);
2202 * If the request has finished processing,
2203 * AND it's child has been cleaned up,
2204 * AND it's time to clean up the request,
2205 * OR, it's an accounting request.
2206 * THEN, go delete it.
2208 * If this is an accounting request, we delete it
2209 * immediately, as there CANNOT be duplicate accounting
2210 * packets. If there are, then something else is
2211 * seriously wrong...
2213 if (request->finished &&
2214 (request->child_pid == NO_SUCH_CHILD_PID) &&
2215 ((request->timestamp + cleanup_delay <= info->now) ||
2216 (request->packet->code == PW_ACCOUNTING_REQUEST))) {
2218 * Request completed, delete it, and unlink it
2219 * from the currently 'alive' list of requests.
2221 DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
2222 request->number, request->packet->id,
2223 (unsigned long)request->timestamp);
2226 * Delete the request.
2229 return RL_WALK_CONTINUE;
2233 * Maybe the child process
2234 * handling the request has hung:
2235 * kill it, and continue.
2237 if ((request->timestamp + max_request_time) <= info->now) {
2238 if (request->child_pid != NO_SUCH_CHILD_PID) {
2240 * This request seems to have hung
2243 child_pid = request->child_pid;
2244 radlog(L_ERR, "Killing unresponsive child %ld for request %d",
2245 child_pid, request->number);
2246 child_kill(child_pid, SIGTERM);
2247 } /* else no proxy reply, quietly fail */
2250 * Delete the request.
2253 return RL_WALK_CONTINUE;
2257 * The request is finished.
2259 if (request->finished) goto setup_timeout;
2262 * We're not proxying requests at all.
2264 if (!proxy_requests) goto setup_timeout;
2267 * We're proxying synchronously, so the retry_delay is zero.
2268 * Some other code takes care of retrying the proxy requests.
2270 if (proxy_retry_delay == 0) goto setup_timeout;
2273 * There is no proxied request for this packet, so there's
2276 if (!request->proxy) goto setup_timeout;
2279 * We've already seen the proxy reply, so we don't need
2280 * to send another proxy request.
2282 if (request->proxy_reply) goto setup_timeout;
2285 * It's not yet time to re-send this proxied request.
2287 if (request->proxy_next_try > info->now) goto setup_timeout;
2290 * If the proxy retry count is zero, then
2291 * we've sent the last try, and have NOT received
2292 * a reply from the end server. In that case,
2293 * we don't bother trying again, but just mark
2294 * the request as finished, and go to the next one.
2296 if (request->proxy_try_count == 0) {
2297 request->finished = TRUE;
2298 rad_reject(request);
2303 * We're trying one more time, so count down
2304 * the tries, and set the next try time.
2306 request->proxy_try_count--;
2307 request->proxy_next_try = info->now + proxy_retry_delay;
2309 /* Fix up Acct-Delay-Time */
2310 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2311 VALUE_PAIR *delaypair;
2312 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
2315 delaypair = paircreate(PW_ACCT_DELAY_TIME,
2318 radlog(L_ERR|L_CONS, "no memory");
2321 pairadd(&request->proxy->vps, delaypair);
2323 delaypair->lvalue = info->now - request->proxy->timestamp;
2325 /* Must recompile the valuepairs to wire format */
2326 free(request->proxy->data);
2327 request->proxy->data = NULL;
2328 } /* proxy accounting request */
2331 * Send the proxy packet.
2333 rad_send(request->proxy, request->proxysecret);
2337 * Don't do more long-term checks, if we've got to wake
2340 if (info->smallest == 0) {
2341 return RL_WALK_CONTINUE;
2345 * The request is finished. Wake up when it's time to
2348 if (request->finished) {
2349 difference = (request->timestamp + cleanup_delay) - info->now;
2351 } else if (request->proxy && !request->proxy_reply) {
2353 * The request is NOT finished, but there is an
2354 * outstanding proxy request, with no matching
2357 * Wake up when it's time to re-send
2358 * the proxy request.
2360 difference = request->proxy_next_try - info->now;
2364 * The request is NOT finished.
2366 * Wake up when it's time to kill the errant
2369 difference = (request->timestamp + max_request_time) - info->now;
2373 * If the server is CPU starved, then we CAN miss a time
2374 * for servicing requests. In which case the 'difference'
2375 * value will be negative. select() doesn't like that,
2378 if (difference < 0) {
2383 * Update the 'smallest' time.
2385 if ((info->smallest < 0) ||
2386 (difference < info->smallest)) {
2387 info->smallest = difference;
2390 return RL_WALK_CONTINUE;