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) {
801 if (strcmp(radlog_dir, "stderr") != 0) {
804 if (devnull > 2) close(devnull);
809 * Disconnect from session
811 if (debug_flag == 0 && dont_fork == 0) {
814 radlog(L_ERR|L_CONS, "Couldn't fork");
819 * The parent exits, so the child can run in the background.
830 * Ensure that we're using the CORRECT pid after forking,
831 * NOT the one we started with.
833 radius_pid = getpid();
836 * Only write the PID file if we're running as a daemon.
838 * And write it AFTER we've forked, so that we write the
841 if (dont_fork == FALSE) {
844 fp = fopen(pid_file, "w");
846 fprintf(fp, "%d\n", (int) radius_pid);
849 radlog(L_ERR|L_CONS, "Failed writing process id to file %s: %s\n",
850 pid_file, strerror(errno));
856 * If we're spawning children, set up the thread pool.
858 if (spawn_flag == TRUE) {
864 * Use linebuffered or unbuffered stdout if
865 * the debug flag is on.
867 if (debug_flag == TRUE)
871 strcpy((char *)buffer, "*");
873 ip_ntoa((char *)buffer, myip);
876 if (proxy_requests == TRUE) {
877 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp, with proxy on %d/udp.",
878 buffer, auth_port, acct_port, proxy_port);
880 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp.",
881 buffer, auth_port, acct_port);
885 * Note that we NO LONGER fork an accounting process!
886 * We used to do it for historical reasons, but that
889 radlog(L_INFO, "Ready to process requests.");
892 * Receive user requests
896 if (reread_config(TRUE) < 0) {
900 radlog(L_INFO, "Ready to process requests.");
905 FD_SET(authfd, &readfds);
907 FD_SET(acctfd, &readfds);
909 FD_SET(proxyfd, &readfds);
911 if (rad_snmp.smux_fd >= 0)
912 FD_SET(rad_snmp.smux_fd, &readfds);
915 status = select(32, &readfds, NULL, NULL, tv);
918 * On interrupts, we clean up the
921 if (errno == EINTR) {
922 tv = rad_clean_list(time(NULL));
925 radlog(L_ERR, "Unexpected error in select(): %s",
931 * Loop over the open socket FD's, reading any data.
933 for (i = 0; i < 3; i++) {
935 if (i == 0) fd = authfd;
936 if (i == 1) fd = acctfd;
937 if (i == 2) fd = proxyfd;
938 if (fd < 0 || !FD_ISSET(fd, &readfds))
941 * Receive the packet.
943 packet = rad_recv(fd);
944 if (packet == NULL) {
945 radlog(L_ERR, "%s", librad_errstr);
950 rad_snmp.acct.total_requests++;
952 rad_snmp.auth.total_requests++;
956 * Check if we know this client for
957 * authfd and acctfd. Check if we know
958 * this proxy for proxyfd.
962 if ((cl = client_find(packet->src_ipaddr)) == NULL) {
963 radlog(L_ERR, "Ignoring request from unknown client %s:%d",
964 ip_ntoa(buffer, packet->src_ipaddr),
972 } else { /* It came in on the proxy port */
974 if ((rl = realm_findbyaddr(packet->src_ipaddr)) == NULL) {
975 radlog(L_ERR, "Ignoring request from unknown proxy %s:%d",
976 ip_ntoa(buffer, packet->src_ipaddr),
986 * Do yet another check, to see if the
987 * packet code is valid. We only understand
988 * a few, so stripping off obviously invalid
989 * packets here will make our life easier.
991 if (packet->code > PW_ACCESS_CHALLENGE) {
992 radlog(L_ERR, "Ignoring request from client %s:%d with unknown code %d", buffer, packet->src_port, packet->code);
997 request = rad_malloc(sizeof(REQUEST));
998 memset(request, 0, sizeof(REQUEST));
1000 request->magic = REQUEST_MAGIC;
1002 request->packet = packet;
1003 request->proxy = NULL;
1004 request->reply = NULL;
1005 request->proxy_reply = NULL;
1006 request->config_items = NULL;
1007 request->username = NULL;
1008 request->password = NULL;
1009 request->timestamp = time(NULL);
1010 request->number = request_num_counter++;
1011 request->child_pid = NO_SUCH_CHILD_PID;
1012 request->container = NULL;
1013 strNcpy(request->secret, (char *)secret, sizeof(request->secret));
1014 rad_process(request, spawn_flag);
1015 } /* loop over authfd, acctfd, proxyfd */
1019 * After handling all authentication/accounting
1020 * requests, THEN process any pending SMUX/SNMP
1023 * Note that the handling is done in the main server,
1024 * which probably isn't a Good Thing. It really
1025 * should be wrapped, and handled in a thread pool.
1027 if ((rad_snmp.smux_fd >= 0) &&
1028 FD_ISSET(rad_snmp.smux_fd, &readfds) &&
1029 (rad_snmp.smux_event == SMUX_READ)) {
1034 * If we've got to re-connect, then do so now,
1035 * before calling select again.
1037 if (rad_snmp.smux_event == SMUX_CONNECT) {
1043 * After processing all new requests,
1044 * check if we've got to delete old requests
1045 * from the request list.
1047 tv = rad_clean_list(time(NULL));
1049 } /* loop forever */
1054 * Process supported requests:
1056 * PW_AUTHENTICATION_REQUEST - Authentication request from
1057 * a client network access server.
1059 * PW_ACCOUNTING_REQUEST - Accounting request from
1060 * a client network access server.
1062 * PW_AUTHENTICATION_ACK
1063 * PW_AUTHENTICATION_REJECT
1064 * PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
1065 * Relay reply back to original NAS.
1068 int rad_process(REQUEST *request, int dospawn)
1070 RAD_REQUEST_FUNP fun;
1074 assert(request->magic == REQUEST_MAGIC);
1076 switch(request->packet->code) {
1078 radlog(L_ERR, "Unknown packet type %d from client %s:%d "
1079 "- ID %d : IGNORED", request->packet->code,
1080 client_name(request->packet->src_ipaddr), request->packet->src_port,
1081 request->packet->id);
1082 request_free(&request);
1086 case PW_AUTHENTICATION_REQUEST:
1088 * Check for requests sent to the wrong port,
1089 * and ignore them, if so.
1091 if (request->packet->sockfd != authfd) {
1092 radlog(L_ERR, "Request packet code %d sent to authentication port from "
1093 "client %s:%d - ID %d : IGNORED", request->packet->code,
1094 client_name(request->packet->src_ipaddr), request->packet->src_port,
1095 request->packet->id);
1096 request_free(&request);
1099 fun = rad_authenticate;
1102 case PW_ACCOUNTING_REQUEST:
1104 * Check for requests sent to the wrong port,
1105 * and ignore them, if so.
1107 if (request->packet->sockfd != acctfd) {
1108 radlog(L_ERR, "Request packet code %d sent to accounting port from "
1109 "client %s:%d - ID %d : IGNORED", request->packet->code,
1110 client_name(request->packet->src_ipaddr), request->packet->src_port,
1111 request->packet->id);
1112 request_free(&request);
1115 fun = rad_accounting;
1118 case PW_AUTHENTICATION_ACK:
1119 case PW_AUTHENTICATION_REJECT:
1120 case PW_ACCOUNTING_RESPONSE:
1122 * Replies NOT sent to the proxy port get an
1123 * error message logged, and the packet is
1126 if (request->packet->sockfd != proxyfd) {
1127 radlog(L_ERR, "Reply packet code %d sent to request port from "
1128 "client %s:%d - ID %d : IGNORED", request->packet->code,
1129 client_name(request->packet->src_ipaddr), request->packet->src_port,
1130 request->packet->id);
1131 request_free(&request);
1134 if (request->packet->code != PW_ACCOUNTING_RESPONSE) {
1135 fun = rad_authenticate;
1137 fun = rad_accounting;
1141 case PW_PASSWORD_REQUEST:
1143 * We don't support this anymore.
1145 radlog(L_ERR, "Deprecated password change request from client %s:%d - ID %d : IGNORED",
1146 client_name(request->packet->src_ipaddr), request->packet->src_port,
1147 request->packet->id);
1148 request_free(&request);
1154 * Check for a duplicate, or error.
1155 * Throw away the the request if so.
1157 request = rad_check_list(request);
1158 if (request == NULL) {
1162 assert(request->magic == REQUEST_MAGIC);
1165 * The request passes many of our sanity checks. From
1166 * here on in, if anything goes wrong, we send a reject
1167 * message, instead of dropping the packet.
1169 * Build the reply template from the request template.
1171 if ((request->reply = rad_alloc(0)) == NULL) {
1172 radlog(L_ERR, "No memory");
1175 request->reply->sockfd = request->packet->sockfd;
1176 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1177 request->reply->dst_port = request->packet->src_port;
1178 request->reply->id = request->packet->id;
1179 request->reply->code = 0; /* UNKNOWN code */
1180 memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector));
1181 request->reply->vps = NULL;
1182 request->reply->data = NULL;
1183 request->reply->data_len = 0;
1186 * If we're spawning a child thread, let it do all of
1187 * the work of handling a request, and exit.
1189 if (dospawn == TRUE) {
1191 * Maybe the spawn failed. If so, then we
1192 * trivially reject the request (because we can't
1193 * handle it), and return.
1195 if (rad_spawn_child(request, fun) < 0) {
1196 rad_reject(request);
1197 request->finished = TRUE;
1202 rad_respond(request, fun);
1207 * Reject a request, by sending a trivial reply packet.
1209 static void rad_reject(REQUEST *request)
1213 DEBUG2("Server rejecting request %d.", request->number);
1214 switch (request->packet->code) {
1216 * Accounting requests, etc. get dropped on the floor.
1218 case PW_ACCOUNTING_REQUEST:
1223 * Authentication requests get their Proxy-State
1224 * attributes copied over, and an otherwise blank
1225 * reject message sent.
1227 case PW_AUTHENTICATION_REQUEST:
1228 request->reply->code = PW_AUTHENTICATION_REJECT;
1231 * Need to copy Proxy-State from request->packet->vps
1233 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
1235 pairadd(&(request->reply->vps), vps);
1240 * If a reply exists, send it.
1242 if (request->reply->code != 0)
1243 rad_send(request->reply, request->secret);
1247 * Perform any RFC specified cleaning of outgoing replies
1249 static void rfc_clean(RADIUS_PACKET *packet)
1251 VALUE_PAIR *vps = NULL;
1253 switch (packet->code) {
1258 * Authentication REJECT's can have only
1259 * Reply-Mesaage and Proxy-State. We delete
1260 * everything other than Reply-Message, and
1261 * Proxy-State is added below, just before
1262 * the reply is sent.
1264 case PW_AUTHENTICATION_REJECT:
1265 pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
1266 pairfree(&packet->vps);
1273 * FIXME: The next two functions should all
1274 * be in a module. But not until we have
1275 * more control over module execution.
1280 * Lowercase the string value of a pair.
1282 static int rad_lowerpair(REQUEST *request, VALUE_PAIR *vp) {
1287 rad_lowercase(vp->strvalue);
1288 DEBUG2("rad_lowerpair: %s now '%s'", vp->name, vp->strvalue);
1293 * Remove spaces in a pair.
1295 static int rad_rmspace_pair(REQUEST *request, VALUE_PAIR *vp) {
1300 rad_rmspace(vp->strvalue);
1301 vp->length = strlen(vp->strvalue);
1302 DEBUG2("rad_rmspace_pair: %s now '%s'", vp->name, vp->strvalue);
1308 * Respond to a request packet.
1310 * Maybe we reply, maybe we don't.
1311 * Maybe we proxy the request to another server, or else maybe
1312 * we replicate it to another server.
1314 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
1316 RADIUS_PACKET *packet, *original;
1318 int finished = FALSE;
1323 * Put the decoded packet into it's proper place.
1325 if (request->proxy_reply != NULL) {
1326 packet = request->proxy_reply;
1327 secret = request->proxysecret;
1328 original = request->proxy;
1330 packet = request->packet;
1331 secret = request->secret;
1335 assert(request->magic == REQUEST_MAGIC);
1338 * Decode the packet, verifying it's signature,
1339 * and parsing the attributes into structures.
1341 * Note that we do this CPU-intensive work in
1342 * a child thread, not the master. This helps to
1343 * spread the load a little bit.
1345 * Internal requests (ones that never go on the
1346 * wire) have ->data==NULL (data is the wire
1347 * format) and don't need to be "decoded"
1349 if (packet->data && rad_decode(packet, original, secret) != 0) {
1350 radlog(L_ERR, "%s", librad_errstr);
1351 rad_reject(request);
1352 goto finished_request;
1356 * For proxy replies, remove non-allowed
1357 * attributes from the list of VP's.
1359 if (request->proxy) {
1361 replicating = proxy_receive(request);
1362 if (replicating != 0) {
1368 * We should have a User-Name attribute now.
1370 if (request->username == NULL) {
1371 request->username = pairfind(request->packet->vps,
1376 * We have the semaphore, and have decoded the packet.
1377 * Let's process the request.
1379 assert(request->magic == REQUEST_MAGIC);
1382 * FIXME: All this lowercase/nospace junk will be moved
1383 * into a module after module failover is fully in place
1385 * See if we have to lower user/pass before processing
1387 if(strcmp(mainconfig.do_lower_user, "before") == 0)
1388 rad_lowerpair(request, request->username);
1389 if(strcmp(mainconfig.do_lower_pass, "before") == 0)
1390 rad_lowerpair(request, rad_getpass(request));
1392 if(strcmp(mainconfig.do_nospace_user, "before") == 0)
1393 rad_rmspace_pair(request, request->username);
1394 if(strcmp(mainconfig.do_nospace_pass, "before") == 0)
1395 rad_rmspace_pair(request, rad_getpass(request));
1399 /* See if we have to lower user/pass after processing */
1400 if(strcmp(mainconfig.do_lower_user, "after") == 0) {
1401 rad_lowerpair(request, request->username);
1404 if(strcmp(mainconfig.do_lower_pass, "after") == 0) {
1405 rad_lowerpair(request, rad_getpass(request));
1408 if(strcmp(mainconfig.do_nospace_user, "after") == 0) {
1409 rad_rmspace_pair(request, request->username);
1412 if(strcmp(mainconfig.do_nospace_pass, "after") == 0) {
1413 rad_rmspace_pair(request, rad_getpass(request));
1417 /* Reprocess if we rejected last time */
1418 if ((fun == rad_authenticate) &&
1419 (request->reply->code == PW_AUTHENTICATION_REJECT) &&
1421 pairfree(&request->config_items);
1426 * If we don't already have a proxy
1427 * packet for this request, we MIGHT have
1430 if (proxy_requests) {
1431 if (request->proxy == NULL) {
1432 proxy_sent = proxy_send(request);
1435 * sent==1 means it's been proxied. The child
1436 * is done handling the request, but the request
1439 if (proxy_sent == 1) {
1440 goto postpone_request;
1443 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1444 (request->reply == NULL)) {
1446 * We're not configured to reply to the packet,
1447 * and we're not proxying, so the DEFAULT behaviour
1448 * is to REJECT the user.
1450 DEBUG2("There was no response configured: rejecting request %d", request->number);
1451 rad_reject(request);
1452 goto finished_request;
1456 * If we have a reply to send, copy the Proxy-State
1457 * attributes from the request to the tail of the reply,
1458 * and send the packet.
1460 assert(request->magic == REQUEST_MAGIC);
1461 if (request->reply->code != 0) {
1462 VALUE_PAIR *vp = NULL;
1465 * Perform RFC limitations on outgoing replies.
1467 rfc_clean(request->reply);
1470 * Need to copy Proxy-State from request->packet->vps
1472 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1474 pairadd(&(request->reply->vps), vp);
1476 rad_send(request->reply, request->secret);
1480 * We're done processing the request, set the
1481 * request to be finished, clean up as necessary,
1482 * and forget about the request.
1488 * We're done handling the request. Free up the linked
1489 * lists of value pairs. This might take a long time,
1490 * so it's more efficient to do it in a child thread,
1491 * instead of in the main handler when it eventually
1492 * gets around to deleting the request.
1494 * Also, no one should be using these items after the
1495 * request is finished, and the reply is sent. Cleaning
1496 * them up here ensures that they're not being used again.
1498 * Hmm... cleaning them up in the child thread also seems
1499 * to make the server run more efficiently!
1502 /* If we proxied this request, it's not safe to delete it until
1503 * after the proxy reply
1506 goto postpone_request;
1508 if (request->packet && request->packet->vps) {
1509 pairfree(&request->packet->vps);
1510 request->username = NULL;
1511 request->password = NULL;
1513 if (request->reply && request->reply->vps) {
1514 pairfree(&request->reply->vps);
1517 if (request->config_items) pairfree(&request->config_items);
1519 DEBUG2("Finished request %d", request->number);
1523 * Go to the next request, without marking
1524 * the current one as finished.
1527 DEBUG2("Going to the next request");
1529 #if WITH_THREAD_POOL
1530 request->child_pid = NO_SUCH_CHILD_PID;
1532 request->finished = finished; /* do as the LAST thing before exiting */
1538 typedef struct rad_walk_t {
1544 * Clean up the request list, every so often.
1546 * This is done by walking through ALL of the list, and
1547 * - marking any requests which are finished, and expired
1548 * - killing any processes which are NOT finished after a delay
1549 * - deleting any marked requests.
1551 static REQUEST *last_request = NULL;
1552 static struct timeval *rad_clean_list(time_t now)
1555 * Static variables, so that we don't do all of this work
1556 * more than once per second.
1558 * Note that we have 'tv' and 'last_tv'. 'last_tv' is
1559 * pointed to by 'last_tv_ptr', and depending on the
1560 * system implementation of select(), it MAY be modified.
1562 * In that was, we want to use the ORIGINAL value, from
1563 * 'tv', and wipe out the (possibly modified) last_tv.
1565 static time_t last_cleaned_list = 0;
1566 static struct timeval tv, *last_tv_ptr = NULL;
1567 static struct timeval last_tv;
1575 * If we've already set up the timeout or cleaned the
1576 * request list this second, then don't do it again. We
1577 * simply return the sleep delay from last time.
1579 * Note that if we returned NULL last time, there was nothing
1580 * to do. BUT we've been woken up since then, which can only
1581 * happen if we received a packet. And if we've received a
1582 * packet, then there's some work to do in the future.
1584 * FIXME: We can probably use gettimeofday() for finer clock
1585 * resolution, as the current method will cause it to sleep
1588 if ((last_tv_ptr != NULL) &&
1589 (last_cleaned_list == now) &&
1594 * If we're NOT walking the entire request list,
1595 * then we want to iteratively check the request
1598 * If there is NO previous request, go look for one.
1601 last_request = rl_next(last_request);
1604 * On average, there will be one request per
1605 * 'cleanup_delay' requests, which needs to be
1608 * And only do this servicing, if we have a request
1612 for (i = 0; i < cleanup_delay; i++) {
1616 * This function call MAY delete the
1617 * request pointed to by 'last_request'.
1619 next = rl_next(last_request);
1620 refresh_request(last_request, &info);
1621 last_request = next;
1624 * Nothing to do any more, exit.
1631 DEBUG2("Waking up in %d seconds...",
1632 (int) last_tv_ptr->tv_sec);
1635 last_cleaned_list = now;
1636 last_request = NULL;
1637 DEBUG2("--- Walking the entire request list ---");
1639 #if WITH_THREAD_POOL
1641 * Only clean the thread pool if we've spawned child threads.
1644 thread_pool_clean(now);
1649 * Hmmm... this is Big Magic. We make it seem like
1650 * there's an additional second to wait, for a whole
1651 * host of reasons which I can't explain adequately,
1652 * but which cause the code to Just Work Right.
1656 rl_walk(refresh_request, &info);
1659 * We haven't found a time at which we need to wake up.
1660 * Return NULL, so that the select() call will sleep forever.
1662 if (info.smallest < 0) {
1663 DEBUG2("Nothing to do. Sleeping until we see a request.");
1668 * Set the time (in seconds) for how long we're
1669 * supposed to sleep.
1671 tv.tv_sec = info.smallest;
1673 DEBUG2("Waking up in %d seconds...", (int) info.smallest);
1676 * Remember how long we should sleep for.
1679 last_tv_ptr = &last_tv;
1684 * Walk through the request list, cleaning up complete child
1685 * requests, and verifing that there is only one process
1686 * responding to each request (duplicate requests are filtered
1689 * Also, check if the request is a reply from a request proxied to
1690 * a remote server. If so, play games with the request, and return
1693 static REQUEST *rad_check_list(REQUEST *request)
1699 * If the request has come in on the proxy FD, then
1700 * it's a proxy reply, so pass it through the proxy
1701 * code for checking the REQUEST list.
1703 if (request->packet->sockfd == proxyfd) {
1704 return proxy_check_list(request);
1707 * If the request already has a proxy packet,
1708 * then it obviously is not a new request, either.
1710 } else if (request->proxy != NULL) {
1714 now = request->timestamp; /* good enough for our purposes */
1717 * Look for an existing copy of this request.
1719 curreq = rl_find(request);
1720 if (curreq != NULL) {
1722 * We now check the authentication vectors.
1723 * If the client has sent us a request with
1724 * identical code && ID, but different vector,
1725 * then they MUST have gotten our response, so
1726 * we can delete the original request, and process
1729 * If the vectors are the same, then it's a duplicate
1730 * request, and we can send a duplicate reply.
1732 if (memcmp(curreq->packet->vector, request->packet->vector,
1733 sizeof(request->packet->vector)) == 0) {
1735 * Maybe we've saved a reply packet. If so,
1736 * re-send it. Otherwise, just complain.
1738 if (curreq->reply) {
1739 radlog(L_INFO, "Sending duplicate authentication reply"
1740 " to client %s:%d - ID: %d", client_name(curreq->packet->src_ipaddr),
1741 curreq->packet->src_port, curreq->packet->id);
1743 rad_send(curreq->reply, curreq->secret);
1746 * There's no reply, but maybe there's
1747 * an outstanding proxy request.
1749 * If so, then kick the proxy again.
1751 } else if (curreq->proxy != NULL) {
1752 if (proxy_synchronous) {
1753 DEBUG2("Sending duplicate proxy request to client %s:%d - ID: %d",
1754 client_name(curreq->proxy->dst_ipaddr), request->packet->src_port,
1757 curreq->proxy_next_try = request->timestamp + proxy_retry_delay;
1758 rad_send(curreq->proxy, curreq->proxysecret);
1760 DEBUG2("Ignoring duplicate authentication packet"
1761 " from client %s:%d - ID: %d, due to outstanding proxy request.",
1762 client_name(request->packet->src_ipaddr),
1763 request->packet->src_port,
1764 request->packet->id);
1768 * This request wasn't proxied.
1770 radlog(L_ERR, "Dropping duplicate authentication packet"
1771 " from client %s:%d - ID: %d", client_name(request->packet->src_ipaddr),
1772 request->packet->src_port, request->packet->id);
1776 * Delete the duplicate request.
1778 request_free(&request);
1782 * The packet vectors are different, so
1783 * we can delete the old request from
1786 } else if (curreq->finished) {
1787 if (last_request == curreq) {
1788 last_request = rl_next(last_request);
1793 * ??? the client sent us a new request
1794 * with the same ID, while we were
1795 * processing the old one! What should
1798 * Right now, we just drop the new packet..
1801 radlog(L_ERR, "Dropping conflicting authentication packet"
1802 " from client %s:%d - ID: %d",
1803 client_name(request->packet->src_ipaddr),
1804 request->packet->src_port,
1805 request->packet->id);
1806 request_free(&request);
1809 } /* a similar packet already exists. */
1812 * Count the total number of requests, to see if there
1813 * are too many. If so, return with an error.
1816 int request_count = rl_num_requests();
1819 * This is a new request. Let's see if it
1820 * makes us go over our configured bounds.
1822 if (request_count > max_requests) {
1823 radlog(L_ERR, "Dropping request (%d is too many): "
1824 "from client %s:%d - ID: %d", request_count,
1825 client_name(request->packet->src_ipaddr),
1826 request->packet->src_port,
1827 request->packet->id);
1828 radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n"
1829 "\tThe value for 'max_requests' is probably set too low.\n");
1830 request_free(&request);
1836 * Add this request to the list
1841 * And return the request to be handled.
1846 #ifndef WITH_THREAD_POOL
1848 typedef struct spawn_thread_t {
1850 RAD_REQUEST_FUNP fun;
1854 * If the child *thread* gets a termination signal,
1855 * then exit from the thread.
1857 static void sig_term(int sig)
1859 sig = sig; /* -Wunused */
1864 * Spawn a new child thread to handle this request, and ONLY
1867 static void *rad_spawn_thread(void *arg)
1870 spawn_thread_t *data = (spawn_thread_t *)arg;
1873 * Note that this behaviour only works on Linux.
1875 * It's generally NOT the thing to do, and should
1878 * Q: How do we signal a hung thread, and tell it to
1881 signal(SIGTERM, sig_term);
1884 * Keep only allowed attributes in the request.
1886 if (data->request->proxy) {
1887 replicating = proxy_receive(data->request);
1888 if (replicating != 0) {
1889 data->request->finished = TRUE;
1895 rad_respond(data->request, data->fun);
1896 data->request->child_pid = NO_SUCH_CHILD_PID;
1904 * If we're using the thread pool, then the function in
1905 * 'threads.c' replaces this one.
1907 #ifndef WITH_THREAD_POOL
1909 * Spawns a child process or thread to perform
1910 * authentication/accounting and respond to RADIUS clients.
1912 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
1914 child_pid_t child_pid;
1918 spawn_thread_t *data;
1920 data = (spawn_thread_t *) rad_malloc(sizeof(spawn_thread_t));
1921 memset(data, 0, sizeof(data));
1922 data->request = request;
1926 * Create a child thread, complaining on error.
1928 rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
1930 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
1931 nas_name2(request->packet), request->packet->id, strerror(errno));
1936 * Detach it, so it's state is automagically cleaned up on exit.
1938 pthread_detach(child_pid);
1945 if (child_pid < 0) {
1946 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
1947 nas_name2(request->packet),
1948 request->packet->id);
1952 if (child_pid == 0) {
1955 * This is the child, it should go ahead and respond
1957 signal(SIGCHLD, SIG_DFL);
1958 rad_respond(request, fun);
1964 * Register the Child
1966 request->child_pid = child_pid;
1969 #endif /* WITH_THREAD_POOL */
1972 void sig_cleanup(int sig)
1974 #ifndef HAVE_PTHREAD_H
1981 sig = sig; /* -Wunused */
1986 * Reset the signal handler, if required.
1988 reset_signal(SIGCHLD, sig_cleanup);
1991 * If we're using pthreads, then there are NO child processes,
1992 * so the waitpid() call, and the following code, is useless.
1994 #ifndef HAVE_PTHREAD_H
1996 pid = waitpid((pid_t)-1, &status, WNOHANG);
2001 * Check to see if the child did a bad thing.
2002 * If so, kill ALL processes in the current
2003 * process group, to prevent further attacks.
2005 if (debug_flag && (WIFSIGNALED(status))) {
2006 radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
2007 pid, WTERMSIG(status));
2013 * Loop over ALL of the active requests, looking
2014 * for the one which caused the signal.
2016 for (curreq = rl_next(NULL); curreq != NULL; curreq = rl_next(curreq)) {
2017 if (curreq->child_pid == pid) {
2018 curreq->child_pid = NO_SUCH_CHILD_PID;
2023 #endif /* !defined HAVE_PTHREAD_H */
2027 * Display the syntax for starting this program.
2029 static void usage(void)
2032 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2033 #if defined(WITH_DBM) || defined(WITH_NDBM)
2036 "AcfnsSvXxyz]\n", progname);
2037 fprintf(stderr, "Options:\n\n");
2038 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2039 fprintf(stderr, " -A Log auth detail.\n");
2040 #if defined(WITH_DBM) || defined(WITH_NDBM)
2041 fprintf(stderr, " -b Use DBM.\n");
2043 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2044 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2045 fprintf(stderr, " -h Print this help message.\n");
2046 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2047 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2048 fprintf(stderr, " stdout == log all messages to standard output.\n");
2049 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2050 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2051 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2052 fprintf(stderr, " -S Log stripped names.\n");
2053 fprintf(stderr, " -v Print server version information.\n");
2054 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2055 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2056 fprintf(stderr, " -y Log authentication failures, with password.\n");
2057 fprintf(stderr, " -z Log authentication successes, with password.\n");
2063 * We got a fatal signal. Clean up and exit.
2065 static void sig_fatal(int sig)
2067 const char *me = "MASTER: ";
2069 if (radius_pid != getpid()) {
2075 radlog(L_ERR, "%saccounting process died - exit.", me);
2078 radlog(L_ERR, "%sfailed in select() - exit.", me);
2081 radlog(L_INFO, "%sexit.", me);
2084 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2089 * We're running as a daemon, we're the MASTER daemon,
2090 * and we got a fatal signal. Tear the rest of the
2091 * daemons down, as something absolutely horrible happened.
2093 if ((debug_flag == 0) && (dont_fork == 0) &&
2094 (radius_pid == getpid())) {
2096 * Kill all of the processes in the current
2102 exit(sig == SIGTERM ? 0 : 1);
2107 * We got the hangup signal.
2108 * Re-read the configuration files.
2111 static void sig_hup(int sig)
2113 sig = sig; /* -Wunused */
2114 reset_signal(SIGHUP, sig_hup);
2117 * Only do the reload if we're the main server, both
2118 * for processes, and for threads.
2120 if (getpid() == radius_pid) {
2124 rad_snmp.smux_failures = 0;
2125 rad_snmp.smux_event = SMUX_CONNECT;
2130 * Do a proxy check of the REQUEST list when using the new proxy code.
2132 static REQUEST *proxy_check_list(REQUEST *request)
2137 * Find the original request in the request list
2139 oldreq = rl_find_proxy(request);
2142 * If there is already a reply,
2143 * maybe the new one is a duplicate?
2145 if (oldreq->proxy_reply) {
2146 if (memcmp(oldreq->proxy_reply->vector,
2147 request->packet->vector,
2148 sizeof(oldreq->proxy_reply->vector)) == 0) {
2149 DEBUG2("Ignoring duplicate proxy reply");
2150 request_free(&request);
2154 * ??? The home server gave us a new
2155 * proxy reply, which doesn't match
2156 * the old one. Delete it!
2158 DEBUG2("Ignoring conflicting proxy reply");
2159 request_free(&request);
2162 } /* else there's no reply yet. */
2166 * If we haven't found the old request, complain.
2168 radlog(L_PROXY, "No request found for proxy reply from server %s - ID %d",
2169 client_name(request->packet->src_ipaddr),
2170 request->packet->id);
2171 request_free(&request);
2176 * Refresh the old request, and update it with the proxy reply.
2178 * ??? Can we delete the proxy request here?
2179 * Is there any more need for it?
2181 oldreq->timestamp = request->timestamp;
2182 oldreq->proxy_reply = request->packet;
2183 request->packet = NULL;
2184 request_free(&request);
2189 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
2190 * max_request_time, etc.
2192 * When walking over the request list, all of the per-request
2193 * magic is done here.
2195 static int refresh_request(REQUEST *request, void *data)
2197 rad_walk_t *info = (rad_walk_t *) data;
2199 child_pid_t child_pid;
2201 assert(request->magic == REQUEST_MAGIC);
2204 * If the request has finished processing,
2205 * AND it's child has been cleaned up,
2206 * AND it's time to clean up the request,
2207 * OR, it's an accounting request.
2208 * THEN, go delete it.
2210 * If this is an accounting request, we delete it
2211 * immediately, as there CANNOT be duplicate accounting
2212 * packets. If there are, then something else is
2213 * seriously wrong...
2215 if (request->finished &&
2216 (request->child_pid == NO_SUCH_CHILD_PID) &&
2217 ((request->timestamp + cleanup_delay <= info->now) ||
2218 (request->packet->code == PW_ACCOUNTING_REQUEST))) {
2220 * Request completed, delete it, and unlink it
2221 * from the currently 'alive' list of requests.
2223 DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
2224 request->number, request->packet->id,
2225 (unsigned long)request->timestamp);
2228 * Delete the request.
2231 return RL_WALK_CONTINUE;
2235 * Maybe the child process
2236 * handling the request has hung:
2237 * kill it, and continue.
2239 if ((request->timestamp + max_request_time) <= info->now) {
2240 if (request->child_pid != NO_SUCH_CHILD_PID) {
2242 * This request seems to have hung
2245 child_pid = request->child_pid;
2246 radlog(L_ERR, "Killing unresponsive child %ld for request %d",
2247 child_pid, request->number);
2248 child_kill(child_pid, SIGTERM);
2249 } /* else no proxy reply, quietly fail */
2252 * Delete the request.
2255 return RL_WALK_CONTINUE;
2259 * The request is finished.
2261 if (request->finished) goto setup_timeout;
2264 * We're not proxying requests at all.
2266 if (!proxy_requests) goto setup_timeout;
2269 * We're proxying synchronously, so the retry_delay is zero.
2270 * Some other code takes care of retrying the proxy requests.
2272 if (proxy_retry_delay == 0) goto setup_timeout;
2275 * There is no proxied request for this packet, so there's
2278 if (!request->proxy) goto setup_timeout;
2281 * We've already seen the proxy reply, so we don't need
2282 * to send another proxy request.
2284 if (request->proxy_reply) goto setup_timeout;
2287 * It's not yet time to re-send this proxied request.
2289 if (request->proxy_next_try > info->now) goto setup_timeout;
2292 * If the proxy retry count is zero, then
2293 * we've sent the last try, and have NOT received
2294 * a reply from the end server. In that case,
2295 * we don't bother trying again, but just mark
2296 * the request as finished, and go to the next one.
2298 if (request->proxy_try_count == 0) {
2299 request->finished = TRUE;
2300 rad_reject(request);
2305 * We're trying one more time, so count down
2306 * the tries, and set the next try time.
2308 request->proxy_try_count--;
2309 request->proxy_next_try = info->now + proxy_retry_delay;
2311 /* Fix up Acct-Delay-Time */
2312 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2313 VALUE_PAIR *delaypair;
2314 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
2317 delaypair = paircreate(PW_ACCT_DELAY_TIME,
2320 radlog(L_ERR|L_CONS, "no memory");
2323 pairadd(&request->proxy->vps, delaypair);
2325 delaypair->lvalue = info->now - request->proxy->timestamp;
2327 /* Must recompile the valuepairs to wire format */
2328 free(request->proxy->data);
2329 request->proxy->data = NULL;
2330 } /* proxy accounting request */
2333 * Send the proxy packet.
2335 rad_send(request->proxy, request->proxysecret);
2339 * Don't do more long-term checks, if we've got to wake
2342 if (info->smallest == 0) {
2343 return RL_WALK_CONTINUE;
2347 * The request is finished. Wake up when it's time to
2350 if (request->finished) {
2351 difference = (request->timestamp + cleanup_delay) - info->now;
2353 } else if (request->proxy && !request->proxy_reply) {
2355 * The request is NOT finished, but there is an
2356 * outstanding proxy request, with no matching
2359 * Wake up when it's time to re-send
2360 * the proxy request.
2362 difference = request->proxy_next_try - info->now;
2366 * The request is NOT finished.
2368 * Wake up when it's time to kill the errant
2371 difference = (request->timestamp + max_request_time) - info->now;
2375 * If the server is CPU starved, then we CAN miss a time
2376 * for servicing requests. In which case the 'difference'
2377 * value will be negative. select() doesn't like that,
2380 if (difference < 0) {
2385 * Update the 'smallest' time.
2387 if ((info->smallest < 0) ||
2388 (difference < info->smallest)) {
2389 info->smallest = difference;
2392 return RL_WALK_CONTINUE;