2 * radiusd.c Main loop of the radius server.
8 /* don't look here for the version, run radiusd -v or look in version.c */
9 static const char rcsid[] =
13 #include "libradius.h"
15 #include <sys/socket.h>
19 #include <netinet/in.h>
39 #include <sys/select.h>
47 # include <sys/wait.h>
50 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
53 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
61 #include "request_list.h"
64 #include "radius_snmp.h"
67 #include <sys/resource.h>
75 const char *progname = NULL;
76 char *radius_dir = NULL;
77 char *radacct_dir = NULL;
78 char *radlog_dir = NULL;
79 const char *radlib_dir = NULL;
80 int log_stripped_names;
83 uint32_t myip = INADDR_ANY;
84 int log_auth_detail = FALSE;
88 int proxy_retry_delay = RETRY_DELAY;
89 int proxy_retry_count = RETRY_COUNT;
90 int proxy_synchronous = TRUE;
91 int need_reload = FALSE;
92 struct main_config_t mainconfig;
94 static int got_child = FALSE;
98 static pid_t radius_pid;
99 static int request_num_counter = 0; /* per-request unique ID */
102 * Configuration items.
104 static int allow_core_dumps = FALSE;
105 static int max_request_time = MAX_REQUEST_TIME;
106 static int cleanup_delay = CLEANUP_DELAY;
107 static int max_requests = MAX_REQUESTS;
108 static int dont_fork = FALSE;
109 static const char *pid_file = NULL;
110 static uid_t server_uid;
111 static gid_t server_gid;
112 static const char *uid_name = NULL;
113 static const char *gid_name = NULL;
114 static int proxy_requests = TRUE;
115 static int spawn_flag = TRUE;
116 static struct rlimit core_limits;
118 static void usage(void);
120 static void sig_fatal (int);
121 static void sig_hup (int);
123 static void rad_reject(REQUEST *request);
124 static int rad_process (REQUEST *, int);
125 static struct timeval *rad_clean_list(time_t curtime);
126 static REQUEST *rad_check_list(REQUEST *);
127 static REQUEST *proxy_check_list(REQUEST *request);
128 static int refresh_request(REQUEST *request, void *data);
129 #ifndef WITH_THREAD_POOL
130 static int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
132 extern int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
136 * Map the proxy server configuration parameters to variables.
138 static CONF_PARSER proxy_config[] = {
139 { "retry_delay", PW_TYPE_INTEGER,
140 &proxy_retry_delay, Stringify(RETRY_DELAY) },
141 { "retry_count", PW_TYPE_INTEGER,
142 &proxy_retry_count, Stringify(RETRY_COUNT) },
143 { "synchronous", PW_TYPE_BOOLEAN, &proxy_synchronous, "yes" },
145 { NULL, -1, NULL, NULL }
149 * A mapping of configuration file names to internal variables
151 static CONF_PARSER server_config[] = {
152 { "max_request_time", PW_TYPE_INTEGER,
153 &max_request_time, Stringify(MAX_REQUEST_TIME) },
154 { "cleanup_delay", PW_TYPE_INTEGER,
155 &cleanup_delay, Stringify(CLEANUP_DELAY) },
156 { "max_requests", PW_TYPE_INTEGER,
157 &max_requests, Stringify(MAX_REQUESTS) },
158 { "port", PW_TYPE_INTEGER,
159 &auth_port, Stringify(PW_AUTH_UDP_PORT) },
160 { "allow_core_dumps", PW_TYPE_BOOLEAN, &allow_core_dumps, "no" },
161 { "log_stripped_names", PW_TYPE_BOOLEAN, &log_stripped_names,"no" },
162 { "log_auth", PW_TYPE_BOOLEAN, &mainconfig.log_auth, "no" },
163 { "log_auth_badpass", PW_TYPE_BOOLEAN, &mainconfig.log_auth_badpass, "no" },
164 { "log_auth_goodpass", PW_TYPE_BOOLEAN, &mainconfig.log_auth_goodpass, "no" },
165 { "pidfile", PW_TYPE_STRING_PTR, &pid_file, "${run_dir}/radiusd.pid"},
166 { "bind_address", PW_TYPE_IPADDR, &myip, "*" },
167 { "user", PW_TYPE_STRING_PTR, &uid_name, NULL},
168 { "group", PW_TYPE_STRING_PTR, &gid_name, NULL},
169 { "usercollide", PW_TYPE_BOOLEAN, &mainconfig.do_usercollide, "no" },
170 { "lower_user", PW_TYPE_STRING_PTR, &mainconfig.do_lower_user, "no" },
171 { "lower_pass", PW_TYPE_STRING_PTR, &mainconfig.do_lower_pass, "no" },
172 { "nospace_user", PW_TYPE_STRING_PTR, &mainconfig.do_nospace_user, "no" },
173 { "nospace_pass", PW_TYPE_STRING_PTR, &mainconfig.do_nospace_pass, "no" },
175 { "proxy_requests", PW_TYPE_BOOLEAN, &proxy_requests, "yes" },
176 { "proxy", PW_TYPE_SUBSECTION, proxy_config, NULL },
177 { NULL, -1, NULL, NULL }
183 static int reread_config(int reload)
189 radlog(L_INFO, "Starting - reading configuration files ...");
190 } else if (pid == radius_pid) {
191 radlog(L_INFO, "Reloading configuration files.");
194 /* First read radiusd.conf */
195 DEBUG2("reread_config: reading radiusd.conf");
196 if (read_radius_conf_file() < 0) {
197 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
202 * And parse the server's configuration values.
204 cs = cf_section_find(NULL);
206 radlog(L_ERR|L_CONS, "No configuration information in radiusd.conf!");
209 cf_section_parse(cs, server_config);
212 * Reload the modules.
214 DEBUG2("read_config_files: entering modules setup");
215 if (setup_modules() < 0) {
216 radlog(L_ERR|L_CONS, "Errors setting up modules");
221 * Go update our behaviour, based on the configuration
224 if (allow_core_dumps) {
225 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
226 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
231 * If we're running as a daemon, and core
232 * dumps are enabled, log that information.
234 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
235 radlog(L_INFO, "Core dumps are enabled.");
237 } else if (!debug_flag) {
239 * Not debugging. Set the core size to zero, to
240 * prevent security breaches. i.e. People
241 * reading passwords from the 'core' file.
243 struct rlimit limits;
246 limits.rlim_max = core_limits.rlim_max;
248 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
249 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
256 * Set the UID and GID, but only if we're NOT running
266 gr = getgrnam(gid_name);
268 radlog(L_ERR|L_CONS, "Cannot switch to Group %s: %s", gid_name, strerror(errno));
271 server_gid = gr->gr_gid;
272 if (setgid(server_gid) < 0) {
273 radlog(L_ERR|L_CONS, "Failed setting Group to %s: %s", gid_name, strerror(errno));
284 pw = getpwnam(uid_name);
286 radlog(L_ERR|L_CONS, "Cannot switch to User %s: %s", uid_name, strerror(errno));
289 server_uid = pw->pw_uid;
290 if (setuid(server_uid) < 0) {
291 radlog(L_ERR|L_CONS, "Failed setting User to %s: %s", uid_name, strerror(errno));
301 * Parse a string into a syslog facility level.
303 static int str2fac(const char *s)
306 if(!strcmp(s, "kern"))
311 if(!strcmp(s, "user"))
316 if(!strcmp(s, "mail"))
321 if(!strcmp(s, "daemon"))
326 if(!strcmp(s, "auth"))
331 if(!strcmp(s, "auth"))
336 if(!strcmp(s, "lpr"))
341 if(!strcmp(s, "news"))
346 if(!strcmp(s, "uucp"))
351 if(!strcmp(s, "cron"))
356 if(!strcmp(s, "authpriv"))
361 if(!strcmp(s, "ftp"))
366 if(!strcmp(s, "local0"))
371 if(!strcmp(s, "local1"))
376 if(!strcmp(s, "local2"))
381 if(!strcmp(s, "local3"))
386 if(!strcmp(s, "local4"))
391 if(!strcmp(s, "local5"))
396 if(!strcmp(s, "local6"))
401 if(!strcmp(s, "local7"))
406 fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
411 /* this should never be reached */
415 int main(int argc, char **argv)
418 RADIUS_PACKET *packet;
420 unsigned char buffer[4096];
421 struct sockaddr salocal;
422 struct sockaddr_in *sa;
432 int syslog_facility = LOG_DAEMON;
435 struct timeval *tv = NULL;
438 set_auth_parameters(argc,argv);
442 * Open /dev/null, and make sure filedescriptors
443 * 0, 1 and 2 are connected to something.
446 while (devnull >= 0 && devnull < 3)
447 devnull = open("/dev/null", O_RDWR);
449 if ((progname = strrchr(argv[0], '/')) == NULL)
456 radius_dir = strdup(RADIUS_DIR);
458 signal(SIGHUP, sig_hup);
459 signal(SIGINT, sig_fatal);
460 signal(SIGQUIT, sig_fatal);
462 signal(SIGPIPE, SIG_IGN);
465 signal(SIGTRAP, sig_fatal);
468 signal(SIGIOT, sig_fatal);
472 * Pooled threads and child threads define their own
475 #ifndef WITH_THREAD_POOL
476 #ifndef HAVE_PTHREAD_H
477 signal(SIGTERM, sig_fatal);
480 signal(SIGCHLD, sig_cleanup);
482 signal(SIGFPE, sig_fatal);
483 signal(SIGSEGV, sig_fatal);
484 signal(SIGILL, sig_fatal);
488 * Close unused file descriptors.
490 for (t = 32; t >= 3; t--)
491 if(t!=devnull) close(t);
494 * Process the options.
496 while((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:p:sSvxXyz")) != EOF) {
501 log_auth_detail = TRUE;
505 if (radacct_dir) free(radacct_dir);
506 radacct_dir = strdup(optarg);
509 #if defined(WITH_DBM) || defined(WITH_NDBM)
515 /* ignore for backwards compatibility with Cistron */
519 if (radius_dir) free(radius_dir);
520 radius_dir = strdup(optarg);
532 if ((myip = ip_getaddr(optarg)) == INADDR_NONE) {
533 fprintf(stderr, "radiusd: %s: host unknown\n",
540 if (radlog_dir) free(radlog_dir);
541 radlog_dir = strdup(optarg);
545 * We should also have this as a configuration
549 syslog_facility = str2fac(optarg);
553 log_stripped_names++;
557 radius_port = atoi(optarg);
560 case 's': /* Single process mode */
569 * BIG debugging mode for users who are
570 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
577 mainconfig.log_auth = TRUE;
578 mainconfig.log_auth_badpass = TRUE;
579 mainconfig.log_auth_goodpass = TRUE;
580 radlog_dir = strdup("stdout");
589 mainconfig.log_auth = TRUE;
590 mainconfig.log_auth_badpass = TRUE;
594 mainconfig.log_auth_badpass = TRUE;
595 mainconfig.log_auth_goodpass = TRUE;
605 * Get out PID: the configuration file reader uses it.
607 radius_pid = getpid();
610 * Get the current maximum for core files.
612 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
613 radlog(L_ERR|L_CONS, "Failed to get current core limit:"
614 " %s", strerror(errno));
619 * Read the configuration files, BEFORE doing anything else.
621 if (reread_config(0) < 0) {
627 * If they asked for syslog, then give it to them.
628 * Also, initialize the logging facility with the
629 * configuration that they asked for.
631 if (!strcmp(radlog_dir, "syslog")) {
632 openlog(progname, LOG_PID, syslog_facility);
634 /* Do you want a warning if -g is used without a -l to activate it? */
638 * Initialize the request list.
643 * We prefer (in order) the port from the command-line,
644 * then the port from the configuration file, then
645 * the port that the system names "radius", then
649 auth_port = radius_port;
650 } /* else auth_port is set from the config file */
653 * Maybe auth_port *wasn't* set from the config file,
654 * or the config file set it to zero.
657 if (auth_port == 0) {
658 svp = getservbyname ("radius", "udp");
660 auth_port = ntohs(svp->s_port);
663 * We're getting auth_port from
664 * /etc/services, get acct_port from
667 svp = getservbyname ("radacct", "udp");
668 if (svp) acct_port = ntohs(svp->s_port);
670 auth_port = PW_AUTH_UDP_PORT;
675 * Open Authentication socket.
678 authfd = socket (AF_INET, SOCK_DGRAM, 0);
680 perror("auth socket");
684 sa = (struct sockaddr_in *) & salocal;
685 memset ((char *) sa, '\0', sizeof (salocal));
686 sa->sin_family = AF_INET;
687 sa->sin_addr.s_addr = myip;
688 sa->sin_port = htons(auth_port);
690 result = bind (authfd, & salocal, sizeof (*sa));
692 perror ("auth bind");
697 * Open Accounting Socket.
699 * If we haven't already gotten acct_port from /etc/services,
700 * then make it auth_port + 1.
703 acct_port = auth_port + 1;
705 acctfd = socket (AF_INET, SOCK_DGRAM, 0);
707 perror ("acct socket");
711 sa = (struct sockaddr_in *) & salocal;
712 memset ((char *) sa, '\0', sizeof (salocal));
713 sa->sin_family = AF_INET;
714 sa->sin_addr.s_addr = myip;
715 sa->sin_port = htons(acct_port);
717 result = bind (acctfd, & salocal, sizeof (*sa));
719 perror ("acct bind");
724 * If we're proxying requests, open the proxy FD.
725 * Otherwise, don't do anything.
727 if (proxy_requests) {
731 proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
733 perror ("proxy socket");
737 sa = (struct sockaddr_in *) & salocal;
738 memset ((char *) sa, '\0', sizeof (salocal));
739 sa->sin_family = AF_INET;
740 sa->sin_addr.s_addr = myip;
743 * Set the proxy port to be one more than the
746 for (proxy_port = acct_port + 1; proxy_port < 64000; proxy_port++) {
747 sa->sin_port = htons(proxy_port);
748 result = bind (proxyfd, & salocal, sizeof (*sa));
755 * Couldn't find a port to which we could bind.
757 if (proxy_port == 64000) {
758 perror("proxy bind");
764 * NOT proxying requests, set the FD to a bad value.
771 * Register built-in compare functions.
773 pair_builtincompare_init();
781 * Connect 0, 1 and 2 to /dev/null.
783 if (!debug_flag && devnull >= 0) {
785 if (strcmp(radlog_dir, "stdout") != 0) {
789 if (devnull > 2) close(devnull);
794 * Disconnect from session
796 if (debug_flag == 0 && dont_fork == 0) {
799 radlog(L_ERR|L_CONS, "Couldn't fork");
804 * The parent exits, so the child can run in the background.
815 * Ensure that we're using the CORRECT pid after forking,
816 * NOT the one we started with.
818 radius_pid = getpid();
821 * Only write the PID file if we're running as a daemon.
823 * And write it AFTER we've forked, so that we write the
826 if (dont_fork == FALSE) {
829 fp = fopen(pid_file, "w");
831 fprintf(fp, "%d\n", (int) radius_pid);
834 radlog(L_ERR|L_CONS, "Failed writing process id to file %s: %s\n",
835 pid_file, strerror(errno));
841 * If we're spawning children, set up the thread pool.
849 * Use linebuffered or unbuffered stdout if
850 * the debug flag is on.
852 if (debug_flag) setlinebuf(stdout);
855 strcpy((char *)buffer, "*");
857 ip_ntoa((char *)buffer, myip);
860 if (proxy_requests) {
861 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp, with proxy on %d/udp.",
862 buffer, auth_port, acct_port, proxy_port);
864 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp.",
865 buffer, auth_port, acct_port);
869 * Note that we NO LONGER fork an accounting process!
870 * We used to do it for historical reasons, but that
873 radlog(L_INFO, "Ready to process requests.");
876 * Receive user requests
880 if (reread_config(TRUE) < 0) {
884 radlog(L_INFO, "Ready to process requests.");
889 FD_SET(authfd, &readfds);
891 FD_SET(acctfd, &readfds);
893 FD_SET(proxyfd, &readfds);
895 if (rad_snmp.smux_fd >= 0)
896 FD_SET(rad_snmp.smux_fd, &readfds);
899 status = select(32, &readfds, NULL, NULL, tv);
902 * On interrupts, we clean up the
905 if (errno == EINTR) {
906 tv = rad_clean_list(time(NULL));
909 radlog(L_ERR, "Unexpected error in select(): %s",
915 * Loop over the open socket FD's, reading any data.
917 for (i = 0; i < 3; i++) {
919 if (i == 0) fd = authfd;
920 if (i == 1) fd = acctfd;
921 if (i == 2) fd = proxyfd;
922 if (fd < 0 || !FD_ISSET(fd, &readfds))
925 * Receive the packet.
927 packet = rad_recv(fd);
928 if (packet == NULL) {
929 radlog(L_ERR, "%s", librad_errstr);
934 rad_snmp.acct_total_requests++;
936 rad_snmp.auth_total_requests++;
940 * Check if we know this client for
941 * authfd and acctfd. Check if we know
942 * this proxy for proxyfd.
946 if ((cl = client_find(packet->src_ipaddr)) == NULL) {
947 radlog(L_ERR, "Ignoring request from unknown client %s:%d",
948 ip_ntoa(buffer, packet->src_ipaddr),
956 } else { /* It came in on the proxy port */
958 if ((rl = realm_findbyaddr(packet->src_ipaddr)) == NULL) {
959 radlog(L_ERR, "Ignoring request from unknown proxy %s:%d",
960 ip_ntoa(buffer, packet->src_ipaddr),
970 * Do yet another check, to see if the
971 * packet code is valid. We only understand
972 * a few, so stripping off obviously invalid
973 * packets here will make our life easier.
975 if (packet->code > PW_ACCESS_CHALLENGE) {
976 radlog(L_ERR, "Ignoring request from client %s:%d with unknown code %d", buffer, packet->src_port, packet->code);
981 request = rad_malloc(sizeof(REQUEST));
982 memset(request, 0, sizeof(REQUEST));
984 request->magic = REQUEST_MAGIC;
986 request->packet = packet;
987 request->proxy = NULL;
988 request->reply = NULL;
989 request->proxy_reply = NULL;
990 request->config_items = NULL;
991 request->username = NULL;
992 request->password = NULL;
993 request->timestamp = time(NULL);
994 request->number = request_num_counter++;
995 request->child_pid = NO_SUCH_CHILD_PID;
996 request->prev = NULL;
997 request->next = NULL;
998 strNcpy(request->secret, (char *)secret, sizeof(request->secret));
999 rad_process(request, spawn_flag);
1000 } /* loop over authfd, acctfd, proxyfd */
1004 * After handling all authentication/accounting
1005 * requests, THEN process any pending SMUX/SNMP
1008 * Note that the handling is done in the main server,
1009 * which probably isn't a Good Thing. It really
1010 * should be wrapped, and handled in a thread pool.
1012 if ((rad_snmp.smux_fd >= 0) &&
1013 FD_ISSET(rad_snmp.smux_fd, &readfds) &&
1014 (rad_snmp.smux_event == SMUX_READ)) {
1019 * If we've got to re-connect, then do so now,
1020 * before calling select again.
1022 if (rad_snmp.smux_event == SMUX_CONNECT) {
1028 * After processing all new requests,
1029 * check if we've got to delete old requests
1030 * from the request list.
1032 tv = rad_clean_list(time(NULL));
1034 } /* loop forever */
1039 * Process supported requests:
1041 * PW_AUTHENTICATION_REQUEST - Authentication request from
1042 * a client network access server.
1044 * PW_ACCOUNTING_REQUEST - Accounting request from
1045 * a client network access server.
1047 * PW_AUTHENTICATION_ACK
1048 * PW_AUTHENTICATION_REJECT
1049 * PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
1050 * Relay reply back to original NAS.
1053 int rad_process(REQUEST *request, int dospawn)
1055 RAD_REQUEST_FUNP fun;
1059 assert(request->magic == REQUEST_MAGIC);
1061 switch(request->packet->code) {
1063 radlog(L_ERR, "Unknown packet type %d from client %s:%d "
1064 "- ID %d : IGNORED",
1065 request->packet->code,
1066 client_name(request->packet->src_ipaddr),
1067 request->packet->src_port,
1068 request->packet->id);
1069 request_free(&request);
1073 case PW_AUTHENTICATION_REQUEST:
1075 * Check for requests sent to the wrong port,
1076 * and ignore them, if so.
1078 if (request->packet->sockfd != authfd) {
1079 radlog(L_ERR, "Request packet code %d sent to authentication port from "
1080 "client %s:%d - ID %d : IGNORED",
1081 request->packet->code,
1082 client_name(request->packet->src_ipaddr),
1083 request->packet->src_port,
1084 request->packet->id);
1085 request_free(&request);
1088 fun = rad_authenticate;
1091 case PW_ACCOUNTING_REQUEST:
1093 * Check for requests sent to the wrong port,
1094 * and ignore them, if so.
1096 if (request->packet->sockfd != acctfd) {
1097 radlog(L_ERR, "Request packet code %d sent to accounting port from "
1098 "client %s:%d - ID %d : IGNORED",
1099 request->packet->code,
1100 client_name(request->packet->src_ipaddr),
1101 request->packet->src_port,
1102 request->packet->id);
1103 request_free(&request);
1106 fun = rad_accounting;
1109 case PW_AUTHENTICATION_ACK:
1110 case PW_AUTHENTICATION_REJECT:
1111 case PW_ACCOUNTING_RESPONSE:
1113 * Replies NOT sent to the proxy port get an
1114 * error message logged, and the packet is
1117 if (request->packet->sockfd != proxyfd) {
1118 radlog(L_ERR, "Reply packet code %d sent to request port from "
1119 "client %s:%d - ID %d : IGNORED",
1120 request->packet->code,
1121 client_name(request->packet->src_ipaddr),
1122 request->packet->src_port,
1123 request->packet->id);
1124 request_free(&request);
1127 if (request->packet->code == PW_AUTHENTICATION_ACK) {
1128 fun = rad_authenticate;
1130 fun = rad_accounting;
1134 case PW_PASSWORD_REQUEST:
1136 * We don't support this anymore.
1138 radlog(L_ERR, "Deprecated password change request from client %s:%d - ID %d : IGNORED",
1139 client_name(request->packet->src_ipaddr),
1140 request->packet->src_port,
1141 request->packet->id);
1142 request_free(&request);
1148 * Check for a duplicate, or error.
1149 * Throw away the the request if so.
1151 request = rad_check_list(request);
1152 if (request == NULL) {
1156 assert(request->magic == REQUEST_MAGIC);
1159 * The request passes many of our sanity checks. From
1160 * here on in, if anything goes wrong, we send a reject
1161 * message, instead of dropping the packet.
1163 * Build the reply template from the request template.
1165 if ((request->reply = rad_alloc(0)) == NULL) {
1166 radlog(L_ERR, "No memory");
1169 request->reply->sockfd = request->packet->sockfd;
1170 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1171 request->reply->dst_port = request->packet->src_port;
1172 request->reply->id = request->packet->id;
1173 request->reply->code = 0; /* UNKNOWN code */
1174 memcpy(request->reply->vector, request->packet->vector,
1175 sizeof(request->reply->vector));
1176 request->reply->vps = NULL;
1177 request->reply->data = NULL;
1178 request->reply->data_len = 0;
1181 * If we're spawning a child thread, let it do all of
1182 * the work of handling a request, and exit.
1186 * Maybe the spawn failed. If so, then we
1187 * trivially reject the request (because we can't
1188 * handle it), and return.
1190 if (rad_spawn_child(request, fun) < 0) {
1191 rad_reject(request);
1192 request->finished = TRUE;
1197 rad_respond(request, fun);
1202 * Reject a request, by sending a trivial reply packet.
1204 static void rad_reject(REQUEST *request)
1208 DEBUG2("Server rejecting request %d.", request->number);
1209 switch (request->packet->code) {
1211 * Accounting requests, etc. get dropped on the floor.
1213 case PW_ACCOUNTING_REQUEST:
1218 * Authentication requests get their Proxy-State
1219 * attributes copied over, and an otherwise blank
1220 * reject message sent.
1222 case PW_AUTHENTICATION_REQUEST:
1223 request->reply->code = PW_AUTHENTICATION_REJECT;
1226 * Need to copy Proxy-State from request->packet->vps
1228 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
1230 pairadd(&(request->reply->vps), vps);
1235 * If a reply exists, send it.
1237 if (request->reply->code) rad_send(request->reply, request->secret);
1241 * Perform any RFC specified cleaning of outgoing replies
1243 static void rfc_clean(RADIUS_PACKET *packet)
1245 VALUE_PAIR *vps = NULL;
1247 switch (packet->code) {
1252 * Authentication REJECT's can have only
1253 * Reply-Mesaage and Proxy-State. We delete
1254 * everything other than Reply-Message, and
1255 * Proxy-State is added below, just before
1256 * the reply is sent.
1258 case PW_AUTHENTICATION_REJECT:
1259 pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
1260 pairfree(&packet->vps);
1267 * FIXME: The next two functions should all
1268 * be in a module. But not until we have
1269 * more control over module execution.
1274 * Lowercase the string value of a pair.
1276 static int rad_lowerpair(REQUEST *request, VALUE_PAIR *vp) {
1281 rad_lowercase(vp->strvalue);
1282 DEBUG2("rad_lowerpair: %s now '%s'", vp->name, vp->strvalue);
1287 * Remove spaces in a pair.
1289 static int rad_rmspace_pair(REQUEST *request, VALUE_PAIR *vp) {
1294 rad_rmspace(vp->strvalue);
1295 vp->length = strlen(vp->strvalue);
1296 DEBUG2("rad_rmspace_pair: %s now '%s'", vp->name, vp->strvalue);
1302 * Respond to a request packet.
1304 * Maybe we reply, maybe we don't.
1305 * Maybe we proxy the request to another server, or else maybe
1306 * we replicate it to another server.
1308 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
1310 RADIUS_PACKET *packet, *original;
1312 int finished = FALSE;
1317 * Put the decoded packet into it's proper place.
1319 if (request->proxy_reply != NULL) {
1320 packet = request->proxy_reply;
1321 secret = request->proxysecret;
1322 original = request->proxy;
1324 packet = request->packet;
1325 secret = request->secret;
1329 assert(request->magic == REQUEST_MAGIC);
1332 * Decode the packet, verifying it's signature,
1333 * and parsing the attributes into structures.
1335 * Note that we do this CPU-intensive work in
1336 * a child thread, not the master. This helps to
1337 * spread the load a little bit.
1339 if (rad_decode(packet, original, secret) != 0) {
1340 radlog(L_ERR, "%s", librad_errstr);
1341 rad_reject(request);
1342 goto finished_request;
1346 * For proxy replies, remove non-allowed
1347 * attributes from the list of VP's.
1349 if (request->proxy) {
1351 replicating = proxy_receive(request);
1352 if (replicating != 0) {
1358 * We should have a User-Name attribute now.
1360 if (request->username == NULL) {
1361 request->username = pairfind(request->packet->vps,
1366 * We have the semaphore, and have decoded the packet.
1367 * Let's process the request.
1369 assert(request->magic == REQUEST_MAGIC);
1372 * FIXME: All this lowercase/nospace junk will be moved
1373 * into a module after module failover is fully in place
1375 * See if we have to lower user/pass before processing
1377 if(strcmp(mainconfig.do_lower_user, "before") == 0)
1378 rad_lowerpair(request, request->username);
1379 if(strcmp(mainconfig.do_lower_pass, "before") == 0)
1380 rad_lowerpair(request, rad_getpass(request));
1382 if(strcmp(mainconfig.do_nospace_user, "before") == 0)
1383 rad_rmspace_pair(request, request->username);
1384 if(strcmp(mainconfig.do_nospace_pass, "before") == 0)
1385 rad_rmspace_pair(request, rad_getpass(request));
1389 /* See if we have to lower user/pass after processing */
1390 if(strcmp(mainconfig.do_lower_user, "after") == 0) {
1391 rad_lowerpair(request, request->username);
1394 if(strcmp(mainconfig.do_lower_pass, "after") == 0) {
1395 rad_lowerpair(request, rad_getpass(request));
1398 if(strcmp(mainconfig.do_nospace_user, "after") == 0) {
1399 rad_rmspace_pair(request, request->username);
1402 if(strcmp(mainconfig.do_nospace_pass, "after") == 0) {
1403 rad_rmspace_pair(request, rad_getpass(request));
1407 /* Reprocess if we rejected last time */
1408 if ((fun == rad_authenticate) &&
1409 (request->reply->code == PW_AUTHENTICATION_REJECT) &&
1411 pairfree(&request->config_items);
1416 * If we don't already have a proxy
1417 * packet for this request, we MIGHT have
1420 if (proxy_requests) {
1421 if (request->proxy == NULL) {
1422 proxy_sent = proxy_send(request);
1425 * sent==1 means it's been proxied. The child
1426 * is done handling the request, but the request
1429 if (proxy_sent == 1) {
1430 goto postpone_request;
1433 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1434 (request->reply == NULL)) {
1436 * We're not configured to reply to the packet,
1437 * and we're not proxying, so the DEFAULT behaviour
1438 * is to REJECT the user.
1440 DEBUG2("There was no response configured: rejecting request %d", request->number);
1441 rad_reject(request);
1442 goto finished_request;
1446 * If we have a reply to send, copy the Proxy-State
1447 * attributes from the request to the tail of the reply,
1448 * and send the packet.
1450 assert(request->magic == REQUEST_MAGIC);
1451 if (request->reply->code != 0) {
1452 VALUE_PAIR *vp = NULL;
1455 * Perform RFC limitations on outgoing replies.
1457 rfc_clean(request->reply);
1460 * Need to copy Proxy-State from request->packet->vps
1462 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1463 if (vp != NULL) pairadd(&(request->reply->vps), vp);
1465 rad_send(request->reply, request->secret);
1469 * We're done processing the request, set the
1470 * request to be finished, clean up as necessary,
1471 * and forget about the request.
1475 * We're done handling the request. Free up the linked
1476 * lists of value pairs. This might take a long time,
1477 * so it's more efficient to do it in a child thread,
1478 * instead of in the main handler when it eventually
1479 * gets around to deleting the request.
1481 * Also, no one should be using these items after the
1482 * request is finished, and the reply is sent. Cleaning
1483 * them up here ensures that they're not being used again.
1485 * Hmm... cleaning them up in the child thread also seems
1486 * to make the server run more efficiently!
1489 /* If we proxied this request, it's not safe to delete it until
1490 * after the proxy reply
1493 goto postpone_request;
1495 if (request->packet && request->packet->vps) {
1496 pairfree(&request->packet->vps);
1497 request->username = NULL;
1498 request->password = NULL;
1500 if (request->reply && request->reply->vps) {
1501 pairfree(&request->reply->vps);
1504 if (request->config_items) pairfree(&request->config_items);
1506 DEBUG2("Finished request %d", request->number);
1510 * Go to the next request, without marking
1511 * the current one as finished.
1514 DEBUG2("Going to the next request");
1516 #if WITH_THREAD_POOL
1517 request->child_pid = NO_SUCH_CHILD_PID;
1519 request->finished = finished; /* do as the LAST thing before exiting */
1525 typedef struct rad_walk_t {
1531 * Clean up the request list, every so often.
1533 * This is done by walking through ALL of the list, and
1534 * - marking any requests which are finished, and expired
1535 * - killing any processes which are NOT finished after a delay
1536 * - deleting any marked requests.
1538 static REQUEST *last_request = NULL;
1539 static struct timeval *rad_clean_list(time_t now)
1542 * Static variables, so that we don't do all of this work
1543 * more than once per second.
1545 * Note that we have 'tv' and 'last_tv'. 'last_tv' is
1546 * pointed to by 'last_tv_ptr', and depending on the
1547 * system implementation of select(), it MAY be modified.
1549 * In that was, we want to use the ORIGINAL value, from
1550 * 'tv', and wipe out the (possibly modified) last_tv.
1552 static time_t last_cleaned_list = 0;
1553 static struct timeval tv, *last_tv_ptr = NULL;
1554 static struct timeval last_tv;
1562 * If we've already set up the timeout or cleaned the
1563 * request list this second, then don't do it again. We
1564 * simply return the sleep delay from last time.
1566 * Note that if we returned NULL last time, there was nothing
1567 * to do. BUT we've been woken up since then, which can only
1568 * happen if we received a packet. And if we've received a
1569 * packet, then there's some work to do in the future.
1571 * FIXME: We can probably use gettimeofday() for finer clock
1572 * resolution, as the current method will cause it to sleep
1575 if ((last_tv_ptr != NULL) &&
1576 (last_cleaned_list == now) &&
1581 * If we're NOT walking the entire request list,
1582 * then we want to iteratively check the request
1585 * If there is NO previous request, go look for one.
1587 if (!last_request) last_request = rl_next(last_request);
1590 * On average, there will be one request per
1591 * 'cleanup_delay' requests, which needs to be
1594 * And only do this servicing, if we have a request
1597 if (last_request) for (i = 0; i < cleanup_delay; i++) {
1601 * This function call MAY delete the
1602 * request pointed to by 'last_request'.
1604 next = rl_next(last_request);
1605 refresh_request(last_request, &info);
1606 last_request = next;
1609 * Nothing to do any more, exit.
1611 if (!last_request) break;
1615 DEBUG2("Waking up in %d seconds...",
1616 (int) last_tv_ptr->tv_sec);
1619 last_cleaned_list = now;
1620 last_request = NULL;
1621 DEBUG2("--- Walking the entire request list ---");
1623 #if WITH_THREAD_POOL
1625 * Only clean the thread pool if we've spawned child threads.
1628 thread_pool_clean(now);
1633 * Hmmm... this is Big Magic. We make it seem like
1634 * there's an additional second to wait, for a whole
1635 * host of reasons which I can't explain adequately,
1636 * but which cause the code to Just Work Right.
1640 rl_walk(refresh_request, &info);
1643 * We haven't found a time at which we need to wake up.
1644 * Return NULL, so that the select() call will sleep forever.
1646 if (info.smallest < 0) {
1647 DEBUG2("Nothing to do. Sleeping until we see a request.");
1652 * Set the time (in seconds) for how long we're
1653 * supposed to sleep.
1655 tv.tv_sec = info.smallest;
1657 DEBUG2("Waking up in %d seconds...", (int) info.smallest);
1660 * Remember how long we should sleep for.
1663 last_tv_ptr = &last_tv;
1668 * Walk through the request list, cleaning up complete child
1669 * requests, and verifing that there is only one process
1670 * responding to each request (duplicate requests are filtered
1673 * Also, check if the request is a reply from a request proxied to
1674 * a remote server. If so, play games with the request, and return
1677 static REQUEST *rad_check_list(REQUEST *request)
1683 * If the request has come in on the proxy FD, then
1684 * it's a proxy reply, so pass it through the proxy
1685 * code for checking the REQUEST list.
1687 if (request->packet->sockfd == proxyfd) {
1688 return proxy_check_list(request);
1691 * If the request already has a proxy packet,
1692 * then it obviously is not a new request, either.
1694 } else if (request->proxy != NULL) {
1698 now = request->timestamp; /* good enough for our purposes */
1701 * Look for an existing copy of this request.
1703 curreq = rl_find(request);
1704 if (curreq != NULL) {
1706 * We now check the authentication vectors.
1707 * If the client has sent us a request with
1708 * identical code && ID, but different vector,
1709 * then they MUST have gotten our response, so
1710 * we can delete the original request, and process
1713 * If the vectors are the same, then it's a duplicate
1714 * request, and we can send a duplicate reply.
1716 if (memcmp(curreq->packet->vector, request->packet->vector,
1717 sizeof(request->packet->vector)) == 0) {
1719 * Maybe we've saved a reply packet. If so,
1720 * re-send it. Otherwise, just complain.
1722 if (curreq->reply) {
1724 "Sending duplicate authentication reply"
1725 " to client %s:%d - ID: %d",
1726 client_name(curreq->packet->src_ipaddr),
1727 curreq->packet->src_port,
1728 curreq->packet->id);
1730 rad_send(curreq->reply, curreq->secret);
1733 * There's no reply, but maybe there's
1734 * an outstanding proxy request.
1736 * If so, then kick the proxy again.
1738 } else if (curreq->proxy != NULL) {
1739 if (proxy_synchronous) {
1740 DEBUG2("Sending duplicate proxy request to client %s:%d - ID: %d",
1741 client_name(curreq->proxy->dst_ipaddr),
1742 request->packet->src_port,
1745 curreq->proxy_next_try = request->timestamp + proxy_retry_delay;
1746 rad_send(curreq->proxy, curreq->proxysecret);
1748 DEBUG2("Ignoring duplicate authentication packet"
1749 " from client %s:%d - ID: %d, due to outstanding proxy request.",
1750 client_name(request->packet->src_ipaddr),
1751 request->packet->src_port,
1752 request->packet->id);
1756 * This request wasn't proxied.
1759 "Dropping duplicate authentication packet"
1760 " from client %s:%d - ID: %d",
1761 client_name(request->packet->src_ipaddr),
1762 request->packet->src_port,
1763 request->packet->id);
1767 * Delete the duplicate request, and
1768 * stop processing the request list.
1770 request_free(&request);
1773 * The packet vectors are different, so
1774 * we can delete the old request from
1777 } else if (curreq->finished) {
1778 if (last_request == curreq) {
1779 last_request = rl_next(last_request);
1784 * ??? the client sent us a new request
1785 * with the same ID, while we were
1786 * processing the old one! What should
1789 * Right now, we just drop the new packet..
1793 "Dropping conflicting authentication packet"
1794 " from client %s:%d - ID: %d",
1795 client_name(request->packet->src_ipaddr),
1796 request->packet->src_port,
1797 request->packet->id);
1798 request_free(&request);
1800 } /* a similar packet already exists. */
1803 * If we've received a duplicate packet, 'request' is NULL,
1804 * and we have nothing more to do.
1806 if (request == NULL) {
1811 * Count the total number of requests, to see if there
1812 * are too many. If so, return with an error.
1815 int request_count = rl_num_requests();
1818 * This is a new request. Let's see if it
1819 * makes us go over our configured bounds.
1821 if (request_count > max_requests) {
1822 radlog(L_ERR, "Dropping request (%d is too many): "
1823 "from client %s:%d - ID: %d", request_count,
1824 client_name(request->packet->src_ipaddr),
1825 request->packet->src_port,
1826 request->packet->id);
1827 radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n\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),
1930 request->packet->id,
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;
2022 #endif /* !defined HAVE_PTHREAD_H */
2026 * Display the syntax for starting this program.
2028 static void usage(void)
2031 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2032 #if defined(WITH_DBM) || defined(WITH_NDBM)
2035 "AcfnsSvXxyz]\n", progname);
2036 fprintf(stderr, "Options:\n\n");
2037 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2038 fprintf(stderr, " -A Log auth detail.\n");
2039 #if defined(WITH_DBM) || defined(WITH_NDBM)
2040 fprintf(stderr, " -b Use DBM.\n");
2042 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2043 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2044 fprintf(stderr, " -h Print this help message.\n");
2045 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2046 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2047 fprintf(stderr, " stdout == log all messages to standard output.\n");
2048 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2049 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2050 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2051 fprintf(stderr, " -S Log stripped names.\n");
2052 fprintf(stderr, " -v Print server version information.\n");
2053 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2054 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2055 fprintf(stderr, " -y Log authentication failures, with password.\n");
2056 fprintf(stderr, " -z Log authentication successes, with password.\n");
2062 * We got a fatal signal. Clean up and exit.
2064 static void sig_fatal(int sig)
2066 const char *me = "MASTER: ";
2068 if (radius_pid != getpid()) {
2074 radlog(L_ERR, "%saccounting process died - exit.", me);
2077 radlog(L_ERR, "%sfailed in select() - exit.", me);
2080 radlog(L_INFO, "%sexit.", me);
2083 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2088 * We're running as a daemon, we're the MASTER daemon,
2089 * and we got a fatal signal. Tear the rest of the
2090 * daemons down, as something absolutely horrible happened.
2092 if ((debug_flag == 0) && (dont_fork == 0) &&
2093 (radius_pid == getpid())) {
2095 * Kill all of the processes in the current
2101 exit(sig == SIGTERM ? 0 : 1);
2106 * We got the hangup signal.
2107 * Re-read the configuration files.
2110 static void sig_hup(int sig)
2112 sig = sig; /* -Wunused */
2113 reset_signal(SIGHUP, sig_hup);
2116 * Only do the reload if we're the main server, both
2117 * for processes, and for threads.
2119 if (getpid() == radius_pid) {
2125 * Do a proxy check of the REQUEST list when using the new proxy code.
2127 static REQUEST *proxy_check_list(REQUEST *request)
2132 * Find the original request in the request list
2134 oldreq = rl_find_proxy(request);
2137 * If there is already a reply,
2138 * maybe the new one is a duplicate?
2140 if (oldreq->proxy_reply) {
2141 if (memcmp(oldreq->proxy_reply->vector,
2142 request->packet->vector,
2143 sizeof(oldreq->proxy_reply->vector)) == 0) {
2144 DEBUG2("Ignoring duplicate proxy reply");
2145 request_free(&request);
2149 * ??? The home server gave us a new
2150 * proxy reply, which doesn't match
2151 * the old one. Delete it!
2153 DEBUG2("Ignoring conflicting proxy reply");
2154 request_free(&request);
2157 } /* else there's no reply yet. */
2161 * If we haven't found the old request, complain.
2163 radlog(L_PROXY, "Unrecognized proxy reply from server %s - ID %d",
2164 client_name(request->packet->src_ipaddr),
2165 request->packet->id);
2166 request_free(&request);
2171 * Refresh the old request, and update it with the proxy reply.
2173 * ??? Can we delete the proxy request here?
2174 * Is there any more need for it?
2176 oldreq->timestamp = request->timestamp;
2177 oldreq->proxy_reply = request->packet;
2178 request->packet = NULL;
2179 request_free(&request);
2184 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
2185 * max_request_time, etc.
2187 * When walking over the request list, all of the per-request
2188 * magic is done here.
2190 static int refresh_request(REQUEST *request, void *data)
2192 rad_walk_t *info = (rad_walk_t *) data;
2194 child_pid_t child_pid;
2196 assert(request->magic == REQUEST_MAGIC);
2199 * If the request has finished processing,
2200 * AND it's child has been cleaned up,
2201 * AND it's time to clean up the request,
2202 * OR, it's an accounting request.
2203 * THEN, go delete it.
2205 * If this is an accounting request, we delete it
2206 * immediately, as there CANNOT be duplicate accounting
2207 * packets. If there are, then something else is
2208 * seriously wrong...
2210 if (request->finished &&
2211 (request->child_pid == NO_SUCH_CHILD_PID) &&
2212 ((request->timestamp + cleanup_delay <= info->now) ||
2213 (request->packet->code == PW_ACCOUNTING_REQUEST))) {
2215 * Request completed, delete it, and unlink it
2216 * from the currently 'alive' list of requests.
2218 DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
2219 request->number, request->packet->id,
2220 (unsigned long)request->timestamp);
2223 * Delete the request.
2226 return RL_WALK_CONTINUE;
2230 * Maybe the child process
2231 * handling the request has hung:
2232 * kill it, and continue.
2234 if ((request->timestamp + max_request_time) <= info->now) {
2235 if (request->child_pid != NO_SUCH_CHILD_PID) {
2237 * This request seems to have hung
2240 child_pid = request->child_pid;
2241 radlog(L_ERR, "Killing unresponsive child %d for request %d",
2242 child_pid, request->number);
2243 child_kill(child_pid, SIGTERM);
2244 } /* else no proxy reply, quietly fail */
2247 * Delete the request.
2250 return RL_WALK_CONTINUE;
2254 * The request is finished.
2256 if (request->finished) goto setup_timeout;
2259 * We're not proxying requests at all.
2261 if (!proxy_requests) goto setup_timeout;
2264 * We're proxying synchronously, so the retry_delay is zero.
2265 * Some other code takes care of retrying the proxy requests.
2267 if (proxy_retry_delay == 0) goto setup_timeout;
2270 * There is no proxied request for this packet, so there's
2273 if (!request->proxy) goto setup_timeout;
2276 * We've already seen the proxy reply, so we don't need
2277 * to send another proxy request.
2279 if (request->proxy_reply) goto setup_timeout;
2282 * It's not yet time to re-send this proxied request.
2284 if (request->proxy_next_try > info->now) goto setup_timeout;
2287 * If the proxy retry count is zero, then
2288 * we've sent the last try, and have NOT received
2289 * a reply from the end server. In that case,
2290 * we don't bother trying again, but just mark
2291 * the request as finished, and go to the next one.
2293 if (request->proxy_try_count == 0) {
2294 request->finished = TRUE;
2295 rad_reject(request);
2300 * We're trying one more time, so count down
2301 * the tries, and set the next try time.
2303 request->proxy_try_count--;
2304 request->proxy_next_try = info->now + proxy_retry_delay;
2306 /* Fix up Acct-Delay-Time */
2307 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2308 VALUE_PAIR *delaypair;
2309 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
2312 delaypair = paircreate(PW_ACCT_DELAY_TIME,
2315 radlog(L_ERR|L_CONS, "no memory");
2318 pairadd(&request->proxy->vps, delaypair);
2320 delaypair->lvalue = info->now - request->proxy->timestamp;
2322 /* Must recompile the valuepairs to wire format */
2323 free(request->proxy->data);
2324 request->proxy->data = NULL;
2325 } /* proxy accounting request */
2328 * Send the proxy packet.
2330 rad_send(request->proxy, request->proxysecret);
2334 * Don't do more long-term checks, if we've got to wake
2337 if (info->smallest == 0) {
2338 return RL_WALK_CONTINUE;
2342 * The request is finished. Wake up when it's time to
2345 if (request->finished) {
2346 difference = (request->timestamp + cleanup_delay) - info->now;
2348 } else if (request->proxy && !request->proxy_reply) {
2350 * The request is NOT finished, but there is an
2351 * outstanding proxy request, with no matching
2354 * Wake up when it's time to re-send
2355 * the proxy request.
2357 difference = request->proxy_next_try - info->now;
2361 * The request is NOT finished.
2363 * Wake up when it's time to kill the errant
2366 difference = (request->timestamp + max_request_time) - info->now;
2370 * If the server is CPU starved, then we CAN miss a time
2371 * for servicing requests. In which case the 'difference'
2372 * value will be negative. select() doesn't like that,
2375 if (difference < 0) {
2380 * Update the 'smallest' time.
2382 if ((info->smallest < 0) ||
2383 (difference < info->smallest)) {
2384 info->smallest = difference;
2387 return RL_WALK_CONTINUE;