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[] =
16 #include <sys/socket.h>
20 #include <netinet/in.h>
40 #include <sys/select.h>
48 # include <sys/wait.h>
51 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
54 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
62 #include "radius_snmp.h"
65 #include <sys/resource.h>
70 const char *progname = NULL;
71 char *radius_dir = NULL;
72 char *radacct_dir = NULL;
73 char *radlog_dir = NULL;
74 const char *radlib_dir = NULL;
76 char *smux_password = NULL;
77 int snmp_write_access = FALSE;
78 int snmp_acctotalrequests = 0;
79 int snmp_authtotalrequests = 0;
80 enum smux_event smux_event = SMUX_NONE;
82 int log_stripped_names;
85 uint32_t myip = INADDR_ANY;
86 int log_auth_detail = FALSE;
88 int log_auth_pass = FALSE;
92 int proxy_retry_delay = RETRY_DELAY;
93 int proxy_retry_count = RETRY_COUNT;
94 int proxy_synchronous = TRUE;
95 int need_reload = FALSE;
96 struct main_config_t mainconfig;
98 static int got_child = FALSE;
99 static int request_list_busy = FALSE;
106 static int spawn_flag = TRUE;
107 static pid_t radius_pid;
108 static struct rlimit core_limits;
109 static int proxy_requests = TRUE;
112 * We keep the incoming requests in an array, indexed by ID.
114 * Each array element contains a linked list of active requests,
115 * a count of the number of requests, and a time at which the first
116 * request in the list must be serviced.
118 typedef struct REQUEST_LIST {
119 REQUEST *first_request;
121 time_t last_cleaned_list;
124 static REQUEST_LIST request_list[256];
127 * Configuration items.
129 static int allow_core_dumps = FALSE;
130 static int max_request_time = MAX_REQUEST_TIME;
131 static int cleanup_delay = CLEANUP_DELAY;
132 static int max_requests = MAX_REQUESTS;
133 static int dont_fork = FALSE;
134 static const char *pid_file = NULL;
136 #if !defined(__linux__) && !defined(__GNU_LIBRARY__)
140 static void usage(void);
142 static void sig_fatal (int);
143 static void sig_hup (int);
145 static void rad_reject(REQUEST *request);
146 static int rad_process (REQUEST *, int);
147 static int rad_clean_list(time_t curtime);
148 static REQUEST *rad_check_list(REQUEST *);
149 static REQUEST *proxy_check_list(REQUEST *request);
150 static struct timeval *setuptimeout();
151 static void refresh_request(REQUEST *request, time_t now);
152 #ifndef WITH_THREAD_POOL
153 static int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
155 extern int rad_spawn_child(REQUEST *, RAD_REQUEST_FUNP);
159 * A mapping of configuration file names to internal variables
161 static CONF_PARSER server_config[] = {
162 { "max_request_time", PW_TYPE_INTEGER,
163 &max_request_time, Stringify(MAX_REQUEST_TIME) },
164 { "cleanup_delay", PW_TYPE_INTEGER,
165 &cleanup_delay, Stringify(CLEANUP_DELAY) },
166 { "max_requests", PW_TYPE_INTEGER,
167 &max_requests, Stringify(MAX_REQUESTS) },
168 { "port", PW_TYPE_INTEGER,
169 &auth_port, Stringify(PW_AUTH_UDP_PORT) },
170 { "allow_core_dumps", PW_TYPE_BOOLEAN, &allow_core_dumps, "no" },
171 { "log_stripped_names", PW_TYPE_BOOLEAN, &log_stripped_names,"no" },
172 { "log_auth", PW_TYPE_BOOLEAN, &log_auth, "no" },
173 { "log_auth_pass", PW_TYPE_BOOLEAN, &log_auth_pass, "no" },
174 { "pidfile", PW_TYPE_STRING_PTR, &pid_file, RADIUS_PID },
175 { "log_dir", PW_TYPE_STRING_PTR, &radlog_dir, RADLOG_DIR },
176 { "lib_dir", PW_TYPE_STRING_PTR, &radlib_dir, LIBDIR },
177 { "acct_dir", PW_TYPE_STRING_PTR, &radacct_dir, RADACCT_DIR },
178 { "bind_address", PW_TYPE_IPADDR, &myip, "*" },
179 { "proxy_requests", PW_TYPE_BOOLEAN, &proxy_requests, "yes" },
181 { "confdir", PW_TYPE_STRING_PTR, &radius_dir, RADIUS_DIR },
183 { "hostname_lookups", PW_TYPE_BOOLEAN, &librad_dodns, "0" },
185 { "smux_password", PW_TYPE_STRING_PTR, &smux_password, "" },
186 { "snmp_write_access", PW_TYPE_BOOLEAN, &snmp_write_access, "no" },
188 { "usercollide", PW_TYPE_BOOLEAN, &mainconfig.do_usercollide, "no" },
189 { "lower_user", PW_TYPE_BOOLEAN, &mainconfig.do_lower_user, "no" },
190 { "lower_pass", PW_TYPE_BOOLEAN, &mainconfig.do_lower_pass, "no" },
191 { "lower_time", PW_TYPE_STRING_PTR, &mainconfig.lower_time, "before" },
192 { "nospace_user", PW_TYPE_BOOLEAN, &mainconfig.do_nospace_user, "no" },
193 { "nospace_pass", PW_TYPE_BOOLEAN, &mainconfig.do_nospace_pass, "no" },
194 { "nospace_time", PW_TYPE_STRING_PTR, &mainconfig.nospace_time, "before" },
195 { NULL, -1, NULL, NULL }
199 * Map the proxy server configuration parameters to variables.
201 static CONF_PARSER proxy_config[] = {
202 { "retry_delay", PW_TYPE_INTEGER,
203 &proxy_retry_delay, Stringify(RETRY_DELAY) },
204 { "retry_count", PW_TYPE_INTEGER,
205 &proxy_retry_count, Stringify(RETRY_COUNT) },
206 { "synchronous", PW_TYPE_BOOLEAN, &proxy_synchronous, "yes" },
208 { NULL, -1, NULL, NULL }
214 static void reread_config(int reload)
221 radlog(L_INFO, "Starting - reading configuration files ...");
222 } else if (pid == radius_pid) {
223 radlog(L_INFO, "Reloading configuration files.");
226 /* First read radiusd.conf */
227 DEBUG2("reread_config: reading radiusd.conf");
228 if (read_radius_conf_file() < 0) {
229 radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
234 * And parse the server's configuration values.
236 cs = cf_section_find(NULL);
240 cf_section_parse(cs, server_config);
242 /* Read users file etc. */
243 if (res == 0 && read_config_files() != 0)
247 if (pid == radius_pid) {
249 "Errors reading config file - EXITING");
255 * Go update our behaviour, based on the configuration
258 if (allow_core_dumps) {
259 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
260 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
265 * If we're running as a daemon, and core
266 * dumps are enabled, log that information.
268 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
269 radlog(L_INFO, "Core dumps are enabled.");
271 } else if (!debug_flag) {
273 * Not debugging. Set the core size to zero, to
274 * prevent security breaches. i.e. People
275 * reading passwords from the 'core' file.
277 struct rlimit limits;
280 limits.rlim_max = core_limits.rlim_max;
282 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
283 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
290 * Parse the server's proxy configuration values.
292 if (proxy_requests) {
293 cs = cf_section_find("proxy");
297 cf_section_parse(cs, proxy_config);
302 * Parse a string into a syslog facility level.
304 static int str2fac(const char *s)
307 if(!strcmp(s, "kern"))
312 if(!strcmp(s, "user"))
317 if(!strcmp(s, "mail"))
322 if(!strcmp(s, "daemon"))
327 if(!strcmp(s, "auth"))
332 if(!strcmp(s, "auth"))
337 if(!strcmp(s, "lpr"))
342 if(!strcmp(s, "news"))
347 if(!strcmp(s, "uucp"))
352 if(!strcmp(s, "cron"))
357 if(!strcmp(s, "authpriv"))
362 if(!strcmp(s, "ftp"))
367 if(!strcmp(s, "local0"))
372 if(!strcmp(s, "local1"))
377 if(!strcmp(s, "local2"))
382 if(!strcmp(s, "local3"))
387 if(!strcmp(s, "local4"))
392 if(!strcmp(s, "local5"))
397 if(!strcmp(s, "local6"))
402 if(!strcmp(s, "local7"))
407 fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
412 /* this should never be reached */
416 int main(int argc, char **argv)
419 RADIUS_PACKET *packet;
421 unsigned char buffer[4096];
422 struct sockaddr salocal;
423 struct sockaddr_in *sa;
433 int syslog_facility = LOG_DAEMON;
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.
578 log_auth_pass = TRUE;
579 radlog_dir = strdup("stdout");
592 log_auth_pass = TRUE;
602 * Get out PID: the configuration file reader uses it.
604 radius_pid = getpid();
607 * Get the current maximum for core files.
609 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
610 radlog(L_ERR|L_CONS, "Failed to get current core limit:"
611 " %s", strerror(errno));
616 * Read the configuration files, BEFORE doing anything else.
622 * If they asked for syslog, then give it to them.
623 * Also, initialize the logging facility with the
624 * configuration that they asked for.
626 if (!strcmp(radlog_dir, "syslog")) {
627 openlog(progname, LOG_PID, syslog_facility);
629 /* Do you want a warning if -g is used without a -l to activate it? */
633 * Initialize the request_list[] array.
635 for (i = 0; i < 256; i++) {
636 request_list[i].first_request = NULL;
637 request_list[i].request_count = 0;
638 request_list[i].last_cleaned_list = 0;
642 * We prefer (in order) the port from the command-line,
643 * then the port from the configuration file, then
644 * the port that the system names "radius", then
648 auth_port = radius_port;
649 } /* else auth_port is set from the config file */
652 * Maybe auth_port *wasn't* set from the config file,
653 * or the config file set it to zero.
656 if (auth_port == 0) {
657 svp = getservbyname ("radius", "udp");
659 auth_port = ntohs(svp->s_port);
662 * We're getting auth_port from
663 * /etc/services, get acct_port from
666 svp = getservbyname ("radacct", "udp");
667 if (svp) acct_port = ntohs(svp->s_port);
669 auth_port = PW_AUTH_UDP_PORT;
674 * Open Authentication socket.
677 authfd = socket (AF_INET, SOCK_DGRAM, 0);
679 perror("auth socket");
683 sa = (struct sockaddr_in *) & salocal;
684 memset ((char *) sa, '\0', sizeof (salocal));
685 sa->sin_family = AF_INET;
686 sa->sin_addr.s_addr = myip;
687 sa->sin_port = htons(auth_port);
689 result = bind (authfd, & salocal, sizeof (*sa));
691 perror ("auth bind");
696 * Open Accounting Socket.
698 * If we haven't already gotten acct_port from /etc/services,
699 * then make it auth_port + 1.
702 acct_port = auth_port + 1;
704 acctfd = socket (AF_INET, SOCK_DGRAM, 0);
706 perror ("acct socket");
710 sa = (struct sockaddr_in *) & salocal;
711 memset ((char *) sa, '\0', sizeof (salocal));
712 sa->sin_family = AF_INET;
713 sa->sin_addr.s_addr = myip;
714 sa->sin_port = htons(acct_port);
716 result = bind (acctfd, & salocal, sizeof (*sa));
718 perror ("acct bind");
723 * If we're proxying requests, open the proxy FD.
724 * Otherwise, don't do anything.
726 if (proxy_requests) {
730 proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
732 perror ("proxy socket");
736 sa = (struct sockaddr_in *) & salocal;
737 memset ((char *) sa, '\0', sizeof (salocal));
738 sa->sin_family = AF_INET;
739 sa->sin_addr.s_addr = myip;
742 * Set the proxy port to be one more than the
745 for (proxy_port = acct_port + 1; proxy_port < 64000; proxy_port++) {
746 sa->sin_port = htons(proxy_port);
747 result = bind (proxyfd, & salocal, sizeof (*sa));
754 * Couldn't find a port to which we could bind.
756 if (proxy_port == 64000) {
757 perror("proxy bind");
763 * NOT proxying requests, set the FD to a bad value.
770 * Register built-in compare functions.
772 pair_builtincompare_init();
780 * Connect 0, 1 and 2 to /dev/null.
782 if (!debug_flag && devnull >= 0) {
784 if (strcmp(radlog_dir, "stdout") != 0) {
788 if (devnull > 2) close(devnull);
793 * Disconnect from session
795 if (debug_flag == 0 && dont_fork == 0) {
798 radlog(L_ERR|L_CONS, "Couldn't fork");
803 * The parent exits, so the child can run in the background.
814 * Ensure that we're using the CORRECT pid after forking,
815 * NOT the one we started with.
817 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));
842 * If we're spawning children, set up the thread pool.
850 * Use linebuffered or unbuffered stdout if
851 * the debug flag is on.
853 if (debug_flag) setlinebuf(stdout);
856 strcpy((char *)buffer, "*");
858 ip_ntoa((char *)buffer, myip);
861 if (proxy_requests) {
862 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp, with proxy on %d/udp.",
863 buffer, auth_port, acct_port, proxy_port);
865 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp.",
866 buffer, auth_port, acct_port);
870 * Note that we NO LONGER fork an accounting process!
871 * We used to do it for historical reasons, but that
874 radlog(L_INFO, "Ready to process requests.");
877 * Receive user requests
885 radlog(L_INFO, "Ready to process requests.");
890 FD_SET(authfd, &readfds);
892 FD_SET(acctfd, &readfds);
894 FD_SET(proxyfd, &readfds);
897 FD_SET(smuxfd, &readfds);
900 status = select(32, &readfds, NULL, NULL,
905 * On interrupts, we clean up the
908 if (errno == EINTR) {
912 radlog(L_ERR, "Unexpected error in select(): %s",
918 * Loop over the open socket FD's, reading any data.
920 for (i = 0; i < 3; i++) {
922 if (i == 0) fd = authfd;
923 if (i == 1) fd = acctfd;
924 if (i == 2) fd = proxyfd;
925 if (fd < 0 || !FD_ISSET(fd, &readfds))
928 * Receive the packet.
930 packet = rad_recv(fd);
931 if (packet == NULL) {
932 radlog(L_ERR, "%s", librad_errstr);
937 snmp_acctotalrequests++;
939 snmp_authtotalrequests++;
943 * Check if we know this client for authfd and acctfd.
944 * Check if we know this proxy for proxyfd.
948 if ((cl = client_find(packet->src_ipaddr)) == NULL) {
949 radlog(L_ERR, "Ignoring request from unknown client %s:%d",
950 buffer, packet->src_port);
957 } else { /* It came in on the proxy port */
959 if ((rl = realm_findbyaddr(packet->src_ipaddr)) == NULL) {
960 radlog(L_ERR, "Ignoring request from unknown proxy %s:%d",
961 buffer, packet->src_port);
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 if ((request = malloc(sizeof(REQUEST))) == NULL) {
982 radlog(L_ERR|L_CONS, "no memory");
985 memset(request, 0, sizeof(REQUEST));
987 request->magic = REQUEST_MAGIC;
989 request->packet = packet;
990 request->proxy = NULL;
991 request->reply = NULL;
992 request->proxy_reply = NULL;
993 request->config_items = NULL;
994 request->username = NULL;
995 request->password = NULL;
996 request->timestamp = now;
997 request->child_pid = NO_SUCH_CHILD_PID;
998 request->prev = NULL;
999 request->next = NULL;
1000 strNcpy(request->secret, (char *)secret, sizeof(request->secret));
1001 rad_process(request, spawn_flag);
1002 } /* loop over authfd, acctfd, proxyfd */
1005 * After processing all new requests,
1006 * check if we've got to delete old requests
1007 * from the request list.
1009 rad_clean_list(now);
1012 * When receiving a packet, or timeout,
1013 * service the proxy request list.
1018 * After handling all authentication/accounting
1019 * requests, THEN process any pending SMUX/SNMP
1022 * Note that the handling is done in the main server,
1023 * which probably isn't a Good Thing. It really
1024 * should be wrapped, and handled in a thread pool.
1026 if ((smuxfd >= 0) &&
1027 FD_ISSET(smuxfd, &readfds) &&
1028 (smux_event == SMUX_READ)) {
1033 * If we've got to re-connect, then do so now,
1034 * before calling select again.
1036 if (smux_event == SMUX_CONNECT) {
1040 } /* loop forever */
1045 * Process supported requests:
1047 * PW_AUTHENTICATION_REQUEST - Authentication request from
1048 * a client network access server.
1050 * PW_ACCOUNTING_REQUEST - Accounting request from
1051 * a client network access server.
1053 * PW_AUTHENTICATION_ACK
1054 * PW_AUTHENTICATION_REJECT
1055 * PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
1056 * Relay reply back to original NAS.
1059 int rad_process(REQUEST *request, int dospawn)
1061 RAD_REQUEST_FUNP fun;
1065 assert(request->magic == REQUEST_MAGIC);
1067 switch(request->packet->code) {
1069 case PW_AUTHENTICATION_REQUEST:
1071 * Check for requests sent to the wrong port,
1072 * and ignore them, if so.
1074 if (request->packet->sockfd != authfd) {
1075 radlog(L_ERR, "Request packet code %d sent to authentication port from "
1076 "client %s:%d - ID %d : IGNORED",
1077 request->packet->code,
1078 client_name(request->packet->src_ipaddr),
1079 request->packet->src_port,
1080 request->packet->id);
1081 request_free(request);
1086 case PW_ACCOUNTING_REQUEST:
1088 * Check for requests sent to the wrong port,
1089 * and ignore them, if so.
1091 if (request->packet->sockfd != acctfd) {
1092 radlog(L_ERR, "Request packet code %d sent to accounting port from "
1093 "client %s:%d - ID %d : IGNORED",
1094 request->packet->code,
1095 client_name(request->packet->src_ipaddr),
1096 request->packet->src_port,
1097 request->packet->id);
1098 request_free(request);
1103 case PW_AUTHENTICATION_ACK:
1104 case PW_AUTHENTICATION_REJECT:
1105 case PW_ACCOUNTING_RESPONSE:
1107 * Replies NOT sent to the proxy port get an
1108 * error message logged, and the packet is
1111 if (request->packet->sockfd != proxyfd) {
1112 radlog(L_ERR, "Reply packet code %d sent to request port from "
1113 "client %s:%d - ID %d : IGNORED",
1114 request->packet->code,
1115 client_name(request->packet->src_ipaddr),
1116 request->packet->src_port,
1117 request->packet->id);
1118 request_free(request);
1124 assert(request->magic == REQUEST_MAGIC);
1127 * Select the required function and indicate if
1128 * we need to fork off a child to handle it.
1130 switch(request->packet->code) {
1132 case PW_AUTHENTICATION_ACK:
1133 case PW_AUTHENTICATION_REJECT:
1134 case PW_AUTHENTICATION_REQUEST:
1135 fun = rad_authenticate;
1138 case PW_ACCOUNTING_RESPONSE:
1139 case PW_ACCOUNTING_REQUEST:
1140 fun = rad_accounting;
1143 case PW_PASSWORD_REQUEST:
1145 * We don't support this anymore.
1147 radlog(L_ERR, "Deprecated password change request from client %s:%d "
1148 "- ID %d : IGNORED",
1149 client_name(request->packet->src_ipaddr),
1150 request->packet->src_port,
1151 request->packet->id);
1152 request_free(request);
1157 radlog(L_ERR, "Unknown packet type %d from client %s:%d "
1158 "- ID %d : IGNORED",
1159 request->packet->code,
1160 client_name(request->packet->src_ipaddr),
1161 request->packet->src_port,
1162 request->packet->id);
1163 request_free(request);
1169 * If we did NOT select a function, then exit immediately.
1172 request_free(request);
1177 * Check for a duplicate, or error.
1178 * Throw away the the request if so.
1180 request = rad_check_list(request);
1181 if (request == NULL) {
1185 assert(request->magic == REQUEST_MAGIC);
1188 * The request passes many of our sanity checks. From
1189 * here on in, if anything goes wrong, we send a reject
1190 * message, instead of dropping the packet.
1192 * Build the reply template from the request template.
1194 if ((request->reply = rad_alloc(0)) == NULL) {
1195 fprintf(stderr, "out of memory\n");
1198 request->reply->sockfd = request->packet->sockfd;
1199 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1200 request->reply->dst_port = request->packet->src_port;
1201 request->reply->id = request->packet->id;
1202 request->reply->code = 0; /* UNKNOWN code */
1203 memcpy(request->reply->vector, request->packet->vector,
1204 sizeof(request->reply->vector));
1205 request->reply->vps = NULL;
1206 request->reply->data = NULL;
1209 * If we're spawning a child thread, let it do all of
1210 * the work of handling a request, and exit.
1214 * Maybe the spawn failed. If so, then we
1215 * trivially reject the request (because we can't
1216 * handle it), and return.
1218 if (rad_spawn_child(request, fun) < 0) {
1219 rad_reject(request);
1220 request->finished = TRUE;
1225 rad_respond(request, fun);
1230 * Reject a request, by sending a trivial reply packet.
1232 static void rad_reject(REQUEST *request)
1236 DEBUG2("Server rejecting request.");
1237 switch (request->packet->code) {
1239 * Accounting requests, etc. get dropped on the floor.
1241 case PW_ACCOUNTING_REQUEST:
1246 * Authentication requests get their Proxy-State
1247 * attributes copied over, and an otherwise blank
1248 * reject message sent.
1250 case PW_AUTHENTICATION_REQUEST:
1251 request->reply->code = PW_AUTHENTICATION_REJECT;
1254 * Need to copy Proxy-State from request->packet->vps
1256 vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
1258 pairadd(&(request->reply->vps), vps);
1263 * If a reply exists, send it.
1265 if (request->reply->code) {
1266 rad_send(request->reply, request->secret);
1271 * Perform any RFC specified cleaning of outgoing replies
1273 static void rfc_clean(RADIUS_PACKET *packet)
1275 VALUE_PAIR *vps = NULL;
1277 switch (packet->code) {
1282 * Authentication REJECT's can have only
1283 * Reply-Mesaage and Proxy-State. We delete
1284 * everything other than Reply-Message, and
1285 * Proxy-State is added below, just before
1286 * the reply is sent.
1288 case PW_AUTHENTICATION_REJECT:
1289 pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
1290 pairfree(packet->vps);
1297 * FIXME: The next two functions should all
1298 * be in a module. But not until we have
1299 * more control over module execution.
1304 * Lowercase the string value of a pair.
1306 static int rad_lowerpair(REQUEST *request, VALUE_PAIR *vp) {
1311 rad_lowercase(vp->strvalue);
1312 DEBUG2("rad_lowerpair: %s now '%s'", vp->name, vp->strvalue);
1317 * Remove spaces in a pair.
1319 static int rad_rmspace_pair(REQUEST *request, VALUE_PAIR *vp) {
1324 rad_rmspace(vp->strvalue);
1325 vp->length = strlen(vp->strvalue);
1326 DEBUG2("rad_rmspace_pair: %s now '%s'", vp->name, vp->strvalue);
1332 * Respond to a request packet.
1334 * Maybe we reply, maybe we don't.
1335 * Maybe we proxy the request to another server, or else maybe
1336 * we replicate it to another server.
1338 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
1340 RADIUS_PACKET *packet, *original;
1342 int finished = FALSE;
1347 * Put the decoded packet into it's proper place.
1349 if (request->proxy_reply != NULL) {
1350 packet = request->proxy_reply;
1351 secret = request->proxysecret;
1352 original = request->proxy;
1354 packet = request->packet;
1355 secret = request->secret;
1359 assert(request->magic == REQUEST_MAGIC);
1362 * Decode the packet, verifying it's signature,
1363 * and parsing the attributes into structures.
1365 * Note that we do this CPU-intensive work in
1366 * a child thread, not the master. This helps to
1367 * spread the load a little bit.
1369 if (rad_decode(packet, original, secret) != 0) {
1370 radlog(L_ERR, "%s", librad_errstr);
1371 rad_reject(request);
1372 goto finished_request;
1376 * For proxy replies, remove non-allowed
1377 * attributes from the list of VP's.
1379 if (request->proxy) {
1381 replicating = proxy_receive(request);
1382 if (replicating != 0) {
1388 * We should have a User-Name attribute now.
1390 if (request->username == NULL) {
1391 request->username = pairfind(request->packet->vps,
1396 * We have the semaphore, and have decoded the packet.
1397 * Let's process the request.
1399 assert(request->magic == REQUEST_MAGIC);
1402 * FIXME: All this lowercase/nospace junk will be moved
1403 * into a module after module failover is fully in place
1405 * See if we have to lower user/pass before processing
1407 if(strcmp(mainconfig.lower_time, "before") == 0) {
1408 if(mainconfig.do_lower_user)
1409 rad_lowerpair(request, request->username);
1410 if(mainconfig.do_lower_pass)
1411 rad_lowerpair(request, rad_getpass(request));
1413 if(strcmp(mainconfig.nospace_time, "before") == 0) {
1414 if(mainconfig.do_nospace_user)
1415 rad_rmspace_pair(request, request->username);
1416 if(mainconfig.do_nospace_pass)
1417 rad_rmspace_pair(request, rad_getpass(request));
1421 /* See if we have to lower user/pass after processing */
1422 if(strcmp(mainconfig.lower_time, "after") == 0) {
1423 if(mainconfig.do_lower_user)
1424 rad_lowerpair(request, request->username);
1425 if(mainconfig.do_lower_pass)
1426 rad_lowerpair(request, rad_getpass(request));
1430 if(strcmp(mainconfig.nospace_time, "after") == 0) {
1431 if(mainconfig.do_nospace_user)
1432 rad_rmspace_pair(request, request->username);
1433 if(mainconfig.do_nospace_pass)
1434 rad_rmspace_pair(request, rad_getpass(request));
1438 /* Reprocess if we rejected last time */
1439 if ((fun == rad_authenticate) &&
1440 (request->reply->code == PW_AUTHENTICATION_REJECT) &&
1445 * If we don't already have a proxy
1446 * packet for this request, we MIGHT have
1449 if (proxy_requests) {
1450 if (request->proxy == NULL) {
1451 proxy_sent = proxy_send(request);
1454 * sent==1 means it's been proxied. The child
1455 * is done handling the request, but the request
1458 if (proxy_sent == 1) {
1459 goto postpone_request;
1462 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1463 (request->reply == NULL)) {
1465 * We're not configured to reply to the packet,
1466 * and we're not proxying, so the DEFAULT behaviour
1467 * is to REJECT the user.
1469 DEBUG2("There was no response configured: rejecting the user.");
1470 rad_reject(request);
1471 goto finished_request;
1475 * If we have a reply to send, copy the Proxy-State
1476 * attributes from the request to the tail of the reply,
1477 * and send the packet.
1479 assert(request->magic == REQUEST_MAGIC);
1480 if (request->reply->code != 0) {
1481 VALUE_PAIR *vp = NULL;
1484 * Perform RFC limitations on outgoing replies.
1486 rfc_clean(request->reply);
1489 * Need to copy Proxy-State from request->packet->vps
1491 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1493 pairadd(&(request->reply->vps), vp);
1495 rad_send(request->reply, request->secret);
1499 * We're done processing the request, set the
1500 * request to be finished, clean up as necessary,
1501 * and forget about the request.
1505 * We're done handling the request. Free up the linked
1506 * lists of value pairs. This might take a long time,
1507 * so it's more efficient to do it in a child thread,
1508 * instead of in the main handler when it eventually
1509 * gets around to deleting the request.
1511 * Also, no one should be using these items after the
1512 * request is finished, and the reply is sent. Cleaning
1513 * them up here ensures that they're not being used again.
1515 * Hmm... cleaning them up in the child thread also seems
1516 * to make the server run more efficiently!
1519 /* If we proxied this request, it's not safe to delete it until
1520 * after the proxy reply
1523 goto postpone_request;
1525 if (request->packet && request->packet->vps) {
1526 pairfree(request->packet->vps);
1527 request->packet->vps = NULL;
1528 request->username = NULL;
1529 request->password = NULL;
1531 if (request->reply && request->reply->vps) {
1532 pairfree(request->reply->vps);
1533 request->reply->vps = NULL;
1535 if (request->config_items) {
1536 pairfree(request->config_items);
1537 request->config_items = NULL;
1540 DEBUG2("Finished request");
1544 * Go to the next request, without marking
1545 * the current one as finished.
1548 DEBUG2("Going to the next request");
1551 * If this is an accounting request, ensure
1552 * that we delete it immediately, as there CANNOT be
1553 * duplicate accounting packets. If there are, then
1554 * something else is seriously wrong...
1556 if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1557 request->timestamp = 0;
1560 #if WITH_THREAD_POOL
1561 request->child_pid = NO_SUCH_CHILD_PID;
1563 request->finished = finished; /* do as the LAST thing before exiting */
1570 * Clean up the request list, every so often.
1572 * This is done by walking through ALL of the list, and
1573 * - marking any requests which are finished, and expired
1574 * - killing any processes which are NOT finished after a delay
1575 * - deleting any marked requests.
1577 static int rad_clean_list(time_t now)
1579 static time_t last_cleaned_list = 0;
1582 int cleaned = FALSE;
1585 * Don't bother checking the list if we've done it
1586 * within the last second.
1588 * However, at LEAST once per second, go through the entire
1589 * request list again, ensuring that ALL of the request ID's
1590 * have been processed.
1592 if (last_cleaned_list == now) {
1595 last_cleaned_list = now;
1597 #if WITH_THREAD_POOL
1599 * Only clean the thread pool if we've spawned child threads.
1602 thread_pool_clean(now);
1607 * When mucking around with the request list, we block
1608 * asynchronous access (through the SIGCHLD handler) to
1609 * the list - equivalent to sigblock(SIGCHLD).
1611 request_list_busy = TRUE;
1614 for (id = 0; id < 256; id++) {
1619 * If we've cleaned this entry in the last
1620 * second, don't do it now.
1622 if (request_list[id].last_cleaned_list == now) {
1623 request_count += request_list[id].request_count;
1626 request_list[id].last_cleaned_list = now;
1629 * Set up for looping over the requests
1632 curreq = request_list[id].first_request;
1633 prevptr = &(request_list[id].first_request);
1635 while (curreq != NULL) {
1636 assert(curreq->magic == REQUEST_MAGIC);
1639 * Handle cleanup_delay, max_request_time,
1640 * proxy_retry, for this request.
1642 refresh_request(curreq, now);
1645 * If the request has been marked as deleted,
1646 * then remove it from the request list.
1648 if (curreq->timestamp == 0) {
1649 if (request_list[id].request_count == 0) {
1650 DEBUG("HORRIBLE ERROR!!!");
1652 request_list[id].request_count--;
1656 * Unlink the current request
1657 * from the request queue.
1659 *prevptr = curreq->next;
1661 curreq->next->prev = curreq->prev;
1663 request_free(curreq);
1667 * Else the request is still being
1668 * processed. Skip it.
1671 prevptr = &(curreq->next);
1672 curreq = curreq->next;
1674 } /* end of walking the request list for that ID */
1676 request_count += request_list[id].request_count;
1677 } /* for each entry in the request list array */
1680 * Only print debugging information if anything's changed.
1683 static int old_request_count = -1;
1685 if (request_count != old_request_count) {
1686 DEBUG2("%d requests left in the list", request_count);
1687 old_request_count = request_count;
1692 * We're done playing with the request list.
1694 request_list_busy = FALSE;
1700 * Walk through the request list, cleaning up complete child
1701 * requests, and verifing that there is only one process
1702 * responding to each request (duplicate requests are filtered
1705 * Also, check if the request is a reply from a request proxied to
1706 * a remote server. If so, play games with the request, and return
1709 static REQUEST *rad_check_list(REQUEST *request)
1715 REQUEST_LIST *request_list_entry;
1721 * If the request has come in on the proxy FD, then
1722 * it's a proxy reply, so pass it through the proxy
1723 * code for checking the REQUEST_LIST.
1725 if (request->packet->sockfd == proxyfd) {
1726 return proxy_check_list(request);
1729 * If the request already has a proxy packet,
1730 * then it obviously is not a new request, either.
1732 } else if (request->proxy != NULL) {
1736 request_list_entry = &request_list[request->packet->id];
1738 assert((request_list_entry->first_request == NULL) ||
1739 (request_list_entry->request_count != 0));
1740 assert((request_list_entry->first_request != NULL) ||
1741 (request_list_entry->request_count == 0));
1743 curreq = request_list_entry->first_request;
1745 pkt = request->packet;
1747 now = request->timestamp; /* good enough for our purposes */
1751 * When mucking around with the request list, we block
1752 * asynchronous access (through the SIGCHLD handler) to
1753 * the list - equivalent to sigblock(SIGCHLD).
1755 request_list_busy = TRUE;
1757 while (curreq != NULL) {
1759 * The packet ID's MUST be the same, as we're in
1760 * request_list[request->packet->id]
1762 assert(curreq->packet->id == pkt->id);
1765 * Let's see if we received a duplicate of
1766 * a packet we already have in our list.
1768 * We do this by checking the src IP, src port,
1769 * the packet code, and ID.
1771 if ((curreq->packet->src_ipaddr == pkt->src_ipaddr) &&
1772 (curreq->packet->src_port == pkt->src_port) &&
1773 (curreq->packet->code == pkt->code)) {
1775 * We now check the authentication vectors.
1776 * If the client has sent us a request with
1777 * identical code && ID, but different vector,
1778 * then they MUST have gotten our response, so
1779 * we can delete the original request, and process
1782 * If the vectors are the same, then it's a duplicate
1783 * request, and we can send a duplicate reply.
1785 if (memcmp(curreq->packet->vector, pkt->vector,
1786 sizeof(pkt->vector)) == 0) {
1788 * Maybe we've saved a reply packet. If so,
1789 * re-send it. Otherwise, just complain.
1791 if (curreq->reply) {
1793 "Sending duplicate authentication reply"
1794 " to client %s:%d - ID: %d",
1795 client_name(request->packet->src_ipaddr),
1796 request->packet->src_port,
1797 request->packet->id);
1800 * Use the SOURCE port as the DESTINATION
1801 * port of the duplicate reply.
1803 curreq->reply->dst_port = request->packet->src_port;
1804 rad_send(curreq->reply, curreq->secret);
1807 * There's no reply, but maybe there's
1808 * an outstanding proxy request.
1810 * If so, then kick the proxy again.
1812 } else if (curreq->proxy != NULL) {
1813 if (proxy_synchronous) {
1814 DEBUG2("Sending duplicate proxy request to client %s:%d - ID: %d",
1815 client_name(curreq->proxy->dst_ipaddr),
1816 request->packet->src_port,
1819 curreq->proxy_next_try = request->timestamp + proxy_retry_delay;
1820 rad_send(curreq->proxy, curreq->proxysecret);
1822 DEBUG2("Ignoring duplicate authentication packet"
1823 " from client %s:%d - ID: %d, due to outstanding proxy request.",
1824 client_name(request->packet->src_ipaddr),
1825 request->packet->src_port,
1826 request->packet->id);
1830 "Dropping duplicate authentication packet"
1831 " from client %s:%d - ID: %d",
1832 client_name(request->packet->src_ipaddr),
1833 request->packet->src_port,
1834 request->packet->id);
1838 * Delete the duplicate request, and
1839 * stop processing the request list.
1841 request_free(request);
1846 * The packet vectors are different, so
1847 * we can mark the old request to be
1848 * deleted from the list.
1850 * Note that we don't actually delete it...
1853 if (curreq->finished) {
1854 curreq->timestamp = 0;
1857 * ??? the client sent us a new request
1858 * with the same ID, while we were
1859 * processing the old one! What should
1863 "Dropping conflicting authentication packet"
1864 " from client %s:%d - ID: %d",
1865 client_name(request->packet->src_ipaddr),
1866 request->packet->src_port,
1867 request->packet->id);
1868 request_free(request);
1876 * Ugh... duplicated code is bad...
1880 * Delete the current request, if it's
1881 * marked as such. That is, the request
1882 * must be finished, there must be no
1883 * child associated with that request,
1884 * and it's timestamp must be marked to
1887 if (curreq->finished &&
1888 (curreq->child_pid == NO_SUCH_CHILD_PID) &&
1889 (curreq->timestamp + cleanup_delay <= now)) {
1891 * Request completed, delete it,
1892 * and unlink it from the
1893 * currently 'alive' list of
1896 DEBUG2("Cleaning up request ID %d with timestamp %08lx",
1898 (unsigned long)curreq->timestamp);
1899 prevreq = curreq->prev;
1900 if (request_list[id].request_count == 0) {
1901 DEBUG("HORRIBLE ERROR!!!");
1903 request_list[id].request_count--;
1906 if (prevreq == NULL) {
1907 request_list[id].first_request = curreq->next;
1908 request_free(curreq);
1909 curreq = request_list[id].first_request;
1911 prevreq->next = curreq->next;
1912 request_free(curreq);
1913 curreq = prevreq->next;
1916 curreq->prev = prevreq;
1918 } else { /* the request is still alive */
1920 curreq = curreq->next;
1923 } /* end of walking the request list */
1926 * If we've received a duplicate packet, 'request' is NULL.
1928 if (request == NULL) {
1929 request_list_busy = FALSE;
1933 assert(request_list_entry->request_count == request_count);
1936 * Count the total number of requests, to see if there
1937 * are too many. If so, stop counting immediately,
1938 * and return with an error.
1941 for (i = 0; i < 256; i++) {
1942 request_count += request_list[i].request_count;
1945 * This is a new request. Let's see if it
1946 * makes us go over our configured bounds.
1948 if (request_count > max_requests) {
1949 radlog(L_ERR, "Dropping request (%d is too many): "
1950 "from client %s:%d - ID: %d", request_count,
1951 client_name(request->packet->src_ipaddr),
1952 request->packet->src_port,
1953 request->packet->id);
1954 radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n\tThe value for 'max_requests' is probably set too low.\n");
1955 request_free(request);
1956 request_list_busy = FALSE;
1962 * Add this request to the list
1964 request->prev = prevreq;
1965 request->next = NULL;
1966 request->child_pid = NO_SUCH_CHILD_PID;
1967 request_list_entry->request_count++;
1969 if (prevreq == NULL) {
1970 assert(request_list_entry->first_request == NULL);
1971 assert(request_list_entry->request_count == 1);
1972 request_list_entry->first_request = request;
1974 assert(request_list_entry->first_request != NULL);
1975 prevreq->next = request;
1979 * And return the request to be handled.
1981 request_list_busy = FALSE;
1985 #ifndef WITH_THREAD_POOL
1987 typedef struct spawn_thread_t {
1989 RAD_REQUEST_FUNP fun;
1993 * If the child *thread* gets a termination signal,
1994 * then exit from the thread.
1996 static void sig_term(int sig)
1998 sig = sig; /* -Wunused */
2003 * Spawn a new child thread to handle this request, and ONLY
2006 static void *rad_spawn_thread(void *arg)
2009 spawn_thread_t *data = (spawn_thread_t *)arg;
2012 * Note that this behaviour only works on Linux.
2014 * It's generally NOT the thing to do, and should
2017 * Q: How do we signal a hung thread, and tell it to
2020 signal(SIGTERM, sig_term);
2023 * Keep only allowed attributes in the request.
2025 if (data->request->proxy) {
2026 replicating = proxy_receive(data->request);
2027 if (replicating != 0) {
2028 data->request->finished = TRUE;
2034 rad_respond(data->request, data->fun);
2035 data->request->child_pid = NO_SUCH_CHILD_PID;
2043 * If we're using the thread pool, then the function in
2044 * 'threads.c' replaces this one.
2046 #ifndef WITH_THREAD_POOL
2048 * Spawns a child process or thread to perform
2049 * authentication/accounting and respond to RADIUS clients.
2051 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
2053 child_pid_t child_pid;
2057 spawn_thread_t *data;
2059 data = (spawn_thread_t *) malloc(sizeof(spawn_thread_t));
2060 memset(data, 0, sizeof(data));
2061 data->request = request;
2065 * Create a child thread, complaining on error.
2067 rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
2069 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
2070 nas_name2(request->packet),
2071 request->packet->id,
2077 * Detach it, so it's state is automagically cleaned up on exit.
2079 pthread_detach(child_pid);
2086 if (child_pid < 0) {
2087 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
2088 nas_name2(request->packet),
2089 request->packet->id);
2093 if (child_pid == 0) {
2096 * This is the child, it should go ahead and respond
2098 signal(SIGCHLD, SIG_DFL);
2099 rad_respond(request, fun);
2105 * Register the Child
2107 request->child_pid = child_pid;
2110 #endif /* WITH_THREAD_POOL */
2113 void sig_cleanup(int sig)
2115 #ifndef HAVE_PTHREAD_H
2122 sig = sig; /* -Wunused */
2125 * request_list_busy is a lock on the request list
2127 if (request_list_busy) {
2134 * Reset the signal handler, if required.
2136 reset_signal(SIGCHLD, sig_cleanup);
2139 * If we're using pthreads, then there are NO child processes,
2140 * so the waitpid() call, and the following code, is useless.
2142 #ifndef HAVE_PTHREAD_H
2144 pid = waitpid((pid_t)-1, &status, WNOHANG);
2149 * Check to see if the child did a bad thing.
2150 * If so, kill ALL processes in the current
2151 * process group, to prevent further attacks.
2153 if (debug_flag && (WIFSIGNALED(status))) {
2154 radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
2155 pid, WTERMSIG(status));
2161 * Service all of the requests in the queues
2163 for (i = 0; i < 256; i++) {
2164 curreq = request_list[i].first_request;
2165 while (curreq != (REQUEST *)NULL) {
2166 if (curreq->child_pid == pid) {
2167 curreq->child_pid = NO_SUCH_CHILD_PID;
2170 curreq = curreq->next;
2174 #endif /* !defined HAVE_PTHREAD_H */
2178 * Display the syntax for starting this program.
2180 static void usage(void)
2183 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2184 #if defined(WITH_DBM) || defined(WITH_NDBM)
2187 "AcfnsSvXxyz]\n", progname);
2188 fprintf(stderr, "Options:\n\n");
2189 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2190 fprintf(stderr, " -A Log auth detail.\n");
2191 #if defined(WITH_DBM) || defined(WITH_NDBM)
2192 fprintf(stderr, " -b Use DBM.\n");
2194 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2195 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2196 fprintf(stderr, " -h Print this help message.\n");
2197 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2198 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2199 fprintf(stderr, " stdout == log all messages to standard output.\n");
2200 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2201 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2202 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2203 fprintf(stderr, " -S Log stripped names.\n");
2204 fprintf(stderr, " -v Print server version information.\n");
2205 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2206 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2207 fprintf(stderr, " -y Log authentication failures, with password.\n");
2208 fprintf(stderr, " -z Log authentication successes, with password.\n");
2214 * We got a fatal signal. Clean up and exit.
2216 static void sig_fatal(int sig)
2218 const char *me = "MASTER: ";
2220 if (radius_pid != getpid()) {
2226 radlog(L_ERR, "%saccounting process died - exit.", me);
2229 radlog(L_ERR, "%sfailed in select() - exit.", me);
2232 radlog(L_INFO, "%sexit.", me);
2235 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2240 * We're running as a daemon, we're the MASTER daemon,
2241 * and we got a fatal signal. Tear the rest of the
2242 * daemons down, as something absolutely horrible happened.
2244 if ((debug_flag == 0) && (dont_fork == 0) &&
2245 (radius_pid == getpid())) {
2247 * Kill all of the processes in the current
2253 exit(sig == SIGTERM ? 0 : 1);
2258 * We got the hangup signal.
2259 * Re-read the configuration files.
2262 static void sig_hup(int sig)
2264 sig = sig; /* -Wunused */
2265 reset_signal(SIGHUP, sig_hup);
2268 * Only do the reload if we're the main server, both
2269 * for processes, and for threads.
2271 if (getpid() == radius_pid) {
2277 * Do a proxy check of the REQUEST_LIST when using the new proxy code.
2279 * This function and the next two are here because they have to access
2280 * the REQUEST_LIST structure, which is 'static' to this C file.
2282 static REQUEST *proxy_check_list(REQUEST *request)
2289 * Find the original request in the request list
2292 pkt = request->packet;
2294 for (id = 0; (id < 256) && (oldreq == NULL); id++) {
2295 for (oldreq = request_list[id].first_request ;
2297 oldreq = oldreq->next) {
2300 * See if this reply packet matches a proxy
2301 * packet which we sent.
2303 if (oldreq->proxy &&
2304 (oldreq->proxy->dst_ipaddr == pkt->src_ipaddr) &&
2305 (oldreq->proxy->dst_port == pkt->src_port) &&
2306 (oldreq->proxy->id == pkt->id)) {
2308 * If there is already a reply,
2309 * maybe the new one is a duplicate?
2311 if (oldreq->proxy_reply) {
2312 if (memcmp(oldreq->proxy_reply->vector,
2313 request->packet->vector,
2314 sizeof(oldreq->proxy_reply->vector)) == 0) {
2315 DEBUG2("Ignoring duplicate proxy reply");
2316 request_free(request);
2324 } /* else no reply, this one must match */
2327 * Exit from request list loop
2328 * while oldreq != NULL, which will
2329 * cause the outer loop to stop, too.
2332 } /* the reply matches a proxied request */
2333 } /* for all requests in the id request list */
2334 } /* for all 256 id's*/
2337 * If we haven't found the old request, complain.
2339 if (oldreq == NULL) {
2340 radlog(L_PROXY, "Unrecognized proxy reply from server %s - ID %d",
2341 client_name(request->packet->src_ipaddr),
2342 request->packet->id);
2343 request_free(request);
2348 * Refresh the old request, and update it with the proxy reply.
2350 * ??? Can we delete the proxy request here?
2351 * Is there any more need for it?
2353 oldreq->timestamp = request->timestamp;
2354 oldreq->proxy_reply = request->packet;
2355 request->packet = NULL;
2356 request_free(request);
2361 * Walk through all of the requests, checking cleanup times,
2362 * proxy retry times, and maximum request times. We then set the
2363 * time delay until the server has to service the request queue.
2365 * This time delay is used by the main select() loop, to sleep
2366 * until either a packet comes in, or until there's some work
2369 static struct timeval *setuptimeout()
2371 time_t now = time(NULL);
2372 time_t difference, smallest = 0;
2373 int foundone = FALSE;
2378 * Static variables, so that we don't do all of this work
2379 * more than once per second.
2381 * Note that we have 'tv' and 'last_tv'. 'last_tv' is
2382 * pointed to by 'last_tv_ptr', and depending on the
2383 * system implementation of select(), it MAY be modified.
2385 * In that was, we want to use the ORIGINAL value, from
2386 * 'tv', and wipe out the (possibly modified) last_tv.
2388 static time_t last_setup = 0;
2389 static struct timeval tv, *last_tv_ptr = NULL;
2390 static struct timeval last_tv;
2393 * If we've already set up the timeout this second,
2394 * don't do it again. We simply return the sleep delay
2397 * Note that if we returned NULL last time, there was nothing
2398 * to do. BUT we've been woken up since then, which can only
2399 * happen if we received a packet. And if we've received a
2400 * packet, then there's some work to do in the future.
2402 * FIXME: We can probably use gettimeofday() for finer clock
2403 * resolution, as the current method will cause it to sleep
2406 if ((last_tv_ptr != NULL) &&
2407 (last_setup == now) &&
2410 DEBUG2("Waking up in %d seconds...",
2411 (int) last_tv_ptr->tv_sec);
2415 last_setup = now; /* remember when we last set up the sleep timer */
2417 difference = 1; /* initialize it to a non-zero value */
2420 * Loop over all of the outstanding requests.
2422 for (id = 0; id < 256; id++) {
2423 for (curreq = request_list[id].first_request; curreq; curreq = curreq->next) {
2425 * The request is marked to be
2426 * cleaned up: ignore it.
2428 if (curreq->timestamp == 0) {
2430 } else if (curreq->finished) {
2432 * The request is finished.
2433 * Wake up when it's time to clean
2436 difference = (curreq->timestamp + cleanup_delay) - now;
2438 } else if (curreq->proxy && !curreq->proxy_reply) {
2440 * The request is NOT finished, but there
2441 * is an outstanding proxy request,
2442 * with no matching proxy reply.
2444 * Wake up when it's time to re-send
2445 * the proxy request.
2447 difference = curreq->proxy_next_try - now;
2451 * The request is NOT finished.
2453 * Wake up when it's time to kill
2454 * the errant thread/process.
2456 difference = (curreq->timestamp + max_request_time) - now;
2460 * Found a valid request, with a time at which
2461 * we're going to to wake up.
2465 smallest = difference;
2467 if (difference < smallest)
2468 smallest = difference;
2471 if (difference <= 0) break; /* short-circuit */
2472 } /* loop over linked list for that ID */
2474 if (difference <= 0) break; /* short-circuit */
2475 } /* loop over 256 ID's */
2478 * We haven't found a time at which we need to wake up.
2479 * Return NULL, so that the select() call will sleep forever.
2482 DEBUG2("Nothing to do. Sleeping until we see a request.");
2488 * If the server is CPU starved, then we CAN miss a time
2489 * for servicing requests. In which case the 'smallest'
2490 * value will be negative. select() doesn't like that,
2493 if (smallest < 0) smallest = 0;
2496 * Set the time (in seconds) for how long we're
2497 * supposed to sleep.
2499 tv.tv_sec = smallest;
2501 DEBUG2("Waking up in %d seconds...", (int) smallest);
2504 * Remember how long we should sleep for.
2507 last_tv_ptr = &last_tv;
2512 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
2513 * max_request_time, etc.
2515 * When walking over the request list, all of the per-request
2516 * magic is done here.
2518 static void refresh_request(REQUEST *request, time_t now)
2520 child_pid_t child_pid;
2523 * If the request has finished processing,
2524 * AND it's child has been cleaned up,
2525 * AND it's time to clean up the request,
2526 * THEN, go delete it.
2528 if (request->finished &&
2529 (request->child_pid == NO_SUCH_CHILD_PID) &&
2530 (request->timestamp + cleanup_delay <= now)) {
2532 * Request completed, delete it, and unlink it
2533 * from the currently 'alive' list of requests.
2535 DEBUG2("Cleaning up request ID %d with timestamp %08lx",
2536 request->packet->id,
2537 (unsigned long)request->timestamp);
2540 * Mark the request to be deleted.
2542 request->timestamp = 0;
2548 * Maybe the child process
2549 * handling the request has hung:
2550 * kill it, and continue.
2552 if ((request->timestamp + max_request_time) <= now) {
2553 if (request->child_pid != NO_SUCH_CHILD_PID) {
2555 * This request seems to have hung
2558 child_pid = request->child_pid;
2559 radlog(L_ERR, "Killing unresponsive child %d",
2561 child_kill(child_pid, SIGTERM);
2562 } /* else no proxy reply, quietly fail */
2565 * Mark the request as unsalvagable.
2567 request->child_pid = NO_SUCH_CHILD_PID;
2568 request->finished = TRUE;
2569 request->timestamp = 0;
2574 * Do any proxy request handling.
2576 * If we're not doing proxy requests, OR if the retry delay
2577 * is zero (only retry synchronously), then don't bother
2578 * checking the request for proxy retries.
2580 if ((!proxy_requests) ||
2581 (proxy_retry_delay == 0)) {
2586 * The request is finished, (but it hasn't yet
2587 * been removed from the list.)
2588 * OR there is no proxy request,
2589 * OR we already have seen the reply (so we don't
2590 * need to send another proxy request),
2591 * OR the next try is to be done later.
2595 * FIXME: These retries should be binned by
2596 * the next try time, so we don't have to do
2597 * all of this work on every second.
2599 * That will also get rid of these checks, as
2600 * a packet can get removed from the bin when
2601 * the proxy reply is received.
2603 if ((request->finished) ||
2604 (!request->proxy) ||
2605 (request->proxy_reply) ||
2606 (request->proxy_next_try > now)) {
2611 * If the proxy retry count is zero, then
2612 * we've sent the last try, and have NOT received
2613 * a reply from the end server. In that case,
2614 * we don't bother trying again, but just mark
2615 * the request as finished, and go to the next one.
2617 * Note that we do NOT immediately delete the request,
2618 * on the off chance that the proxy replies before we've
2619 * thrown the request away.
2621 if (request->proxy_try_count == 0) {
2622 request->finished = TRUE;
2623 rad_reject(request);
2628 * We're trying one more time, so count down
2629 * the tries, and set the next try time.
2631 request->proxy_try_count--;
2632 request->proxy_next_try = now + proxy_retry_delay;
2634 /* Fix up Acct-Delay-Time */
2635 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2636 VALUE_PAIR *delaypair;
2637 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
2640 delaypair = paircreate(PW_ACCT_DELAY_TIME,
2643 radlog(L_ERR|L_CONS, "no memory");
2646 pairadd(&request->proxy->vps, delaypair);
2648 delaypair->lvalue = now - request->proxy->timestamp;
2650 /* Must recompile the valuepairs to wire format */
2651 free(request->proxy->data);
2652 request->proxy->data = NULL;
2653 } /* proxy accounting request */
2656 * Send the proxy packet.
2658 rad_send(request->proxy, request->proxysecret);