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.
1942 for (i = 0; i < 256; i++) {
1943 request_count += request_list[i].request_count;
1946 * This is a new request. Let's see if it
1947 * makes us go over our configured bounds.
1949 if (request_count > max_requests) {
1950 radlog(L_ERR, "Dropping request (%d is too many): "
1951 "from client %s:%d - ID: %d", request_count,
1952 client_name(request->packet->src_ipaddr),
1953 request->packet->src_port,
1954 request->packet->id);
1955 radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n\tThe value for 'max_requests' is probably set too low.\n");
1956 request_free(request);
1957 request_list_busy = FALSE;
1964 * Add this request to the list
1966 request->prev = prevreq;
1967 request->next = NULL;
1968 request->child_pid = NO_SUCH_CHILD_PID;
1969 request_list_entry->request_count++;
1971 if (prevreq == NULL) {
1972 assert(request_list_entry->first_request == NULL);
1973 assert(request_list_entry->request_count == 1);
1974 request_list_entry->first_request = request;
1976 assert(request_list_entry->first_request != NULL);
1977 prevreq->next = request;
1981 * And return the request to be handled.
1983 request_list_busy = FALSE;
1987 #ifndef WITH_THREAD_POOL
1989 typedef struct spawn_thread_t {
1991 RAD_REQUEST_FUNP fun;
1995 * If the child *thread* gets a termination signal,
1996 * then exit from the thread.
1998 static void sig_term(int sig)
2000 sig = sig; /* -Wunused */
2005 * Spawn a new child thread to handle this request, and ONLY
2008 static void *rad_spawn_thread(void *arg)
2011 spawn_thread_t *data = (spawn_thread_t *)arg;
2014 * Note that this behaviour only works on Linux.
2016 * It's generally NOT the thing to do, and should
2019 * Q: How do we signal a hung thread, and tell it to
2022 signal(SIGTERM, sig_term);
2025 * Keep only allowed attributes in the request.
2027 if (data->request->proxy) {
2028 replicating = proxy_receive(data->request);
2029 if (replicating != 0) {
2030 data->request->finished = TRUE;
2036 rad_respond(data->request, data->fun);
2037 data->request->child_pid = NO_SUCH_CHILD_PID;
2045 * If we're using the thread pool, then the function in
2046 * 'threads.c' replaces this one.
2048 #ifndef WITH_THREAD_POOL
2050 * Spawns a child process or thread to perform
2051 * authentication/accounting and respond to RADIUS clients.
2053 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
2055 child_pid_t child_pid;
2059 spawn_thread_t *data;
2061 data = (spawn_thread_t *) malloc(sizeof(spawn_thread_t));
2062 memset(data, 0, sizeof(data));
2063 data->request = request;
2067 * Create a child thread, complaining on error.
2069 rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
2071 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
2072 nas_name2(request->packet),
2073 request->packet->id,
2079 * Detach it, so it's state is automagically cleaned up on exit.
2081 pthread_detach(child_pid);
2088 if (child_pid < 0) {
2089 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
2090 nas_name2(request->packet),
2091 request->packet->id);
2095 if (child_pid == 0) {
2098 * This is the child, it should go ahead and respond
2100 signal(SIGCHLD, SIG_DFL);
2101 rad_respond(request, fun);
2107 * Register the Child
2109 request->child_pid = child_pid;
2112 #endif /* WITH_THREAD_POOL */
2115 void sig_cleanup(int sig)
2117 #ifndef HAVE_PTHREAD_H
2124 sig = sig; /* -Wunused */
2127 * request_list_busy is a lock on the request list
2129 if (request_list_busy) {
2136 * Reset the signal handler, if required.
2138 reset_signal(SIGCHLD, sig_cleanup);
2141 * If we're using pthreads, then there are NO child processes,
2142 * so the waitpid() call, and the following code, is useless.
2144 #ifndef HAVE_PTHREAD_H
2146 pid = waitpid((pid_t)-1, &status, WNOHANG);
2151 * Check to see if the child did a bad thing.
2152 * If so, kill ALL processes in the current
2153 * process group, to prevent further attacks.
2155 if (debug_flag && (WIFSIGNALED(status))) {
2156 radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
2157 pid, WTERMSIG(status));
2163 * Service all of the requests in the queues
2165 for (i = 0; i < 256; i++) {
2166 curreq = request_list[i].first_request;
2167 while (curreq != (REQUEST *)NULL) {
2168 if (curreq->child_pid == pid) {
2169 curreq->child_pid = NO_SUCH_CHILD_PID;
2172 curreq = curreq->next;
2176 #endif /* !defined HAVE_PTHREAD_H */
2180 * Display the syntax for starting this program.
2182 static void usage(void)
2185 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2186 #if defined(WITH_DBM) || defined(WITH_NDBM)
2189 "AcfnsSvXxyz]\n", progname);
2190 fprintf(stderr, "Options:\n\n");
2191 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2192 fprintf(stderr, " -A Log auth detail.\n");
2193 #if defined(WITH_DBM) || defined(WITH_NDBM)
2194 fprintf(stderr, " -b Use DBM.\n");
2196 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2197 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2198 fprintf(stderr, " -h Print this help message.\n");
2199 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2200 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2201 fprintf(stderr, " stdout == log all messages to standard output.\n");
2202 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2203 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2204 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2205 fprintf(stderr, " -S Log stripped names.\n");
2206 fprintf(stderr, " -v Print server version information.\n");
2207 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2208 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2209 fprintf(stderr, " -y Log authentication failures, with password.\n");
2210 fprintf(stderr, " -z Log authentication successes, with password.\n");
2216 * We got a fatal signal. Clean up and exit.
2218 static void sig_fatal(int sig)
2220 const char *me = "MASTER: ";
2222 if (radius_pid != getpid()) {
2228 radlog(L_ERR, "%saccounting process died - exit.", me);
2231 radlog(L_ERR, "%sfailed in select() - exit.", me);
2234 radlog(L_INFO, "%sexit.", me);
2237 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2242 * We're running as a daemon, we're the MASTER daemon,
2243 * and we got a fatal signal. Tear the rest of the
2244 * daemons down, as something absolutely horrible happened.
2246 if ((debug_flag == 0) && (dont_fork == 0) &&
2247 (radius_pid == getpid())) {
2249 * Kill all of the processes in the current
2255 exit(sig == SIGTERM ? 0 : 1);
2260 * We got the hangup signal.
2261 * Re-read the configuration files.
2264 static void sig_hup(int sig)
2266 sig = sig; /* -Wunused */
2267 reset_signal(SIGHUP, sig_hup);
2270 * Only do the reload if we're the main server, both
2271 * for processes, and for threads.
2273 if (getpid() == radius_pid) {
2279 * Do a proxy check of the REQUEST_LIST when using the new proxy code.
2281 * This function and the next two are here because they have to access
2282 * the REQUEST_LIST structure, which is 'static' to this C file.
2284 static REQUEST *proxy_check_list(REQUEST *request)
2291 * Find the original request in the request list
2294 pkt = request->packet;
2296 for (id = 0; (id < 256) && (oldreq == NULL); id++) {
2297 for (oldreq = request_list[id].first_request ;
2299 oldreq = oldreq->next) {
2302 * See if this reply packet matches a proxy
2303 * packet which we sent.
2305 if (oldreq->proxy &&
2306 (oldreq->proxy->dst_ipaddr == pkt->src_ipaddr) &&
2307 (oldreq->proxy->dst_port == pkt->src_port) &&
2308 (oldreq->proxy->id == pkt->id)) {
2310 * If there is already a reply,
2311 * maybe the new one is a duplicate?
2313 if (oldreq->proxy_reply) {
2314 if (memcmp(oldreq->proxy_reply->vector,
2315 request->packet->vector,
2316 sizeof(oldreq->proxy_reply->vector)) == 0) {
2317 DEBUG2("Ignoring duplicate proxy reply");
2318 request_free(request);
2326 } /* else no reply, this one must match */
2329 * Exit from request list loop
2330 * while oldreq != NULL, which will
2331 * cause the outer loop to stop, too.
2334 } /* the reply matches a proxied request */
2335 } /* for all requests in the id request list */
2336 } /* for all 256 id's*/
2339 * If we haven't found the old request, complain.
2341 if (oldreq == NULL) {
2342 radlog(L_PROXY, "Unrecognized proxy reply from server %s - ID %d",
2343 client_name(request->packet->src_ipaddr),
2344 request->packet->id);
2345 request_free(request);
2350 * Refresh the old request, and update it with the proxy reply.
2352 * ??? Can we delete the proxy request here?
2353 * Is there any more need for it?
2355 oldreq->timestamp = request->timestamp;
2356 oldreq->proxy_reply = request->packet;
2357 request->packet = NULL;
2358 request_free(request);
2363 * Walk through all of the requests, checking cleanup times,
2364 * proxy retry times, and maximum request times. We then set the
2365 * time delay until the server has to service the request queue.
2367 * This time delay is used by the main select() loop, to sleep
2368 * until either a packet comes in, or until there's some work
2371 static struct timeval *setuptimeout()
2373 time_t now = time(NULL);
2374 time_t difference, smallest = 0;
2375 int foundone = FALSE;
2380 * Static variables, so that we don't do all of this work
2381 * more than once per second.
2383 * Note that we have 'tv' and 'last_tv'. 'last_tv' is
2384 * pointed to by 'last_tv_ptr', and depending on the
2385 * system implementation of select(), it MAY be modified.
2387 * In that was, we want to use the ORIGINAL value, from
2388 * 'tv', and wipe out the (possibly modified) last_tv.
2390 static time_t last_setup = 0;
2391 static struct timeval tv, *last_tv_ptr = NULL;
2392 static struct timeval last_tv;
2395 * If we've already set up the timeout this second,
2396 * don't do it again. We simply return the sleep delay
2399 * Note that if we returned NULL last time, there was nothing
2400 * to do. BUT we've been woken up since then, which can only
2401 * happen if we received a packet. And if we've received a
2402 * packet, then there's some work to do in the future.
2404 * FIXME: We can probably use gettimeofday() for finer clock
2405 * resolution, as the current method will cause it to sleep
2408 if ((last_tv_ptr != NULL) &&
2409 (last_setup == now) &&
2412 DEBUG2("Waking up in %d seconds...",
2413 (int) last_tv_ptr->tv_sec);
2417 last_setup = now; /* remember when we last set up the sleep timer */
2419 difference = 1; /* initialize it to a non-zero value */
2422 * Loop over all of the outstanding requests.
2424 for (id = 0; id < 256; id++) {
2425 for (curreq = request_list[id].first_request; curreq; curreq = curreq->next) {
2427 * The request is marked to be
2428 * cleaned up: ignore it.
2430 if (curreq->timestamp == 0) {
2432 } else if (curreq->finished) {
2434 * The request is finished.
2435 * Wake up when it's time to clean
2438 difference = (curreq->timestamp + cleanup_delay) - now;
2440 } else if (curreq->proxy && !curreq->proxy_reply) {
2442 * The request is NOT finished, but there
2443 * is an outstanding proxy request,
2444 * with no matching proxy reply.
2446 * Wake up when it's time to re-send
2447 * the proxy request.
2449 difference = curreq->proxy_next_try - now;
2453 * The request is NOT finished.
2455 * Wake up when it's time to kill
2456 * the errant thread/process.
2458 difference = (curreq->timestamp + max_request_time) - now;
2462 * Found a valid request, with a time at which
2463 * we're going to to wake up.
2467 smallest = difference;
2469 if (difference < smallest)
2470 smallest = difference;
2473 if (difference <= 0) break; /* short-circuit */
2474 } /* loop over linked list for that ID */
2476 if (difference <= 0) break; /* short-circuit */
2477 } /* loop over 256 ID's */
2480 * We haven't found a time at which we need to wake up.
2481 * Return NULL, so that the select() call will sleep forever.
2484 DEBUG2("Nothing to do. Sleeping until we see a request.");
2490 * If the server is CPU starved, then we CAN miss a time
2491 * for servicing requests. In which case the 'smallest'
2492 * value will be negative. select() doesn't like that,
2495 if (smallest < 0) smallest = 0;
2498 * Set the time (in seconds) for how long we're
2499 * supposed to sleep.
2501 tv.tv_sec = smallest;
2503 DEBUG2("Waking up in %d seconds...", (int) smallest);
2506 * Remember how long we should sleep for.
2509 last_tv_ptr = &last_tv;
2514 * Refresh a request, by using proxy_retry_delay, cleanup_delay,
2515 * max_request_time, etc.
2517 * When walking over the request list, all of the per-request
2518 * magic is done here.
2520 static void refresh_request(REQUEST *request, time_t now)
2522 child_pid_t child_pid;
2525 * If the request has finished processing,
2526 * AND it's child has been cleaned up,
2527 * AND it's time to clean up the request,
2528 * THEN, go delete it.
2530 if (request->finished &&
2531 (request->child_pid == NO_SUCH_CHILD_PID) &&
2532 (request->timestamp + cleanup_delay <= now)) {
2534 * Request completed, delete it, and unlink it
2535 * from the currently 'alive' list of requests.
2537 DEBUG2("Cleaning up request ID %d with timestamp %08lx",
2538 request->packet->id,
2539 (unsigned long)request->timestamp);
2542 * Mark the request to be deleted.
2544 request->timestamp = 0;
2550 * Maybe the child process
2551 * handling the request has hung:
2552 * kill it, and continue.
2554 if ((request->timestamp + max_request_time) <= now) {
2555 if (request->child_pid != NO_SUCH_CHILD_PID) {
2557 * This request seems to have hung
2560 child_pid = request->child_pid;
2561 radlog(L_ERR, "Killing unresponsive child %d",
2563 child_kill(child_pid, SIGTERM);
2564 } /* else no proxy reply, quietly fail */
2567 * Mark the request as unsalvagable.
2569 request->child_pid = NO_SUCH_CHILD_PID;
2570 request->finished = TRUE;
2571 request->timestamp = 0;
2576 * Do any proxy request handling.
2578 * If we're not doing proxy requests, OR if the retry delay
2579 * is zero (only retry synchronously), then don't bother
2580 * checking the request for proxy retries.
2582 if ((!proxy_requests) ||
2583 (proxy_retry_delay == 0)) {
2588 * The request is finished, (but it hasn't yet
2589 * been removed from the list.)
2590 * OR there is no proxy request,
2591 * OR we already have seen the reply (so we don't
2592 * need to send another proxy request),
2593 * OR the next try is to be done later.
2597 * FIXME: These retries should be binned by
2598 * the next try time, so we don't have to do
2599 * all of this work on every second.
2601 * That will also get rid of these checks, as
2602 * a packet can get removed from the bin when
2603 * the proxy reply is received.
2605 if ((request->finished) ||
2606 (!request->proxy) ||
2607 (request->proxy_reply) ||
2608 (request->proxy_next_try > now)) {
2613 * If the proxy retry count is zero, then
2614 * we've sent the last try, and have NOT received
2615 * a reply from the end server. In that case,
2616 * we don't bother trying again, but just mark
2617 * the request as finished, and go to the next one.
2619 * Note that we do NOT immediately delete the request,
2620 * on the off chance that the proxy replies before we've
2621 * thrown the request away.
2623 if (request->proxy_try_count == 0) {
2624 request->finished = TRUE;
2625 rad_reject(request);
2630 * We're trying one more time, so count down
2631 * the tries, and set the next try time.
2633 request->proxy_try_count--;
2634 request->proxy_next_try = now + proxy_retry_delay;
2636 /* Fix up Acct-Delay-Time */
2637 if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
2638 VALUE_PAIR *delaypair;
2639 delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
2642 delaypair = paircreate(PW_ACCT_DELAY_TIME,
2645 radlog(L_ERR|L_CONS, "no memory");
2648 pairadd(&request->proxy->vps, delaypair);
2650 delaypair->lvalue = now - request->proxy->timestamp;
2652 /* Must recompile the valuepairs to wire format */
2653 free(request->proxy->data);
2654 request->proxy->data = NULL;
2655 } /* proxy accounting request */
2658 * Send the proxy packet.
2660 rad_send(request->proxy, request->proxysecret);