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[] =
14 #include <sys/socket.h>
18 #include <netinet/in.h>
38 #include <sys/select.h>
46 # include <sys/wait.h>
49 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
52 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
61 #include "radius_snmp.h"
64 #include <sys/resource.h>
69 const char *progname = NULL;
70 char *radius_dir = NULL;
71 char *radacct_dir = NULL;
72 char *radlog_dir = NULL;
73 const char *radlib_dir = NULL;
75 char *smux_password = NULL;
76 int snmp_write_access = FALSE;
77 int snmp_acctotalrequests = 0;
78 int snmp_authtotalrequests = 0;
79 enum smux_event smux_event = SMUX_NONE;
81 int log_stripped_names;
84 uint32_t myip = INADDR_ANY;
85 int log_auth_detail = FALSE;
87 int log_auth_pass = FALSE;
91 int proxy_retry_delay = RETRY_DELAY;
92 int proxy_retry_count = RETRY_COUNT;
93 int proxy_synchronous = TRUE;
94 int need_reload = FALSE;
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;
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(struct timeval *);
151 static void proxy_retry(void);
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 { NULL, -1, NULL, NULL }
192 * Map the proxy server configuration parameters to variables.
194 static CONF_PARSER proxy_config[] = {
195 { "retry_delay", PW_TYPE_INTEGER,
196 &proxy_retry_delay, Stringify(RETRY_DELAY) },
197 { "retry_count", PW_TYPE_INTEGER,
198 &proxy_retry_count, Stringify(RETRY_COUNT) },
199 { "synchronous", PW_TYPE_BOOLEAN, &proxy_synchronous, "yes" },
201 { NULL, -1, NULL, NULL }
207 static void reread_config(int reload)
214 radlog(L_INFO, "Starting - reading configuration files ...");
215 #ifdef WITH_USERCOLLIDE
216 radlog(L_INFO, "User collision code on ... ");
218 } else if (pid == radius_pid) {
219 radlog(L_INFO, "Reloading configuration files.");
222 /* Read users file etc. */
223 if (res == 0 && read_config_files() != 0)
227 if (pid == radius_pid) {
229 "Errors reading config file - EXITING");
235 * And parse the server's configuration values.
237 cs = cf_section_find(NULL);
241 cf_section_parse(cs, server_config);
243 * We prefer (in order) the port from the command-line,
244 * then the port from the configuration file, then
245 * the port that the system names "radius", then
248 svp = getservbyname ("radius", "udp");
250 auth_port = radius_port;
252 radius_port = auth_port;
255 if (auth_port == 0) {
257 auth_port = ntohs(svp->s_port);
259 auth_port = PW_AUTH_UDP_PORT;
264 * Go update our behaviour, based on the configuration
267 if (allow_core_dumps) {
268 if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
269 radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
274 * If we're running as a daemon, and core
275 * dumps are enabled, log that information.
277 } else if ((core_limits.rlim_cur != 0) && !debug_flag)
278 radlog(L_INFO, "Core dumps are enabled.");
280 } else if (!debug_flag) {
282 * Not debugging. Set the core size to zero, to
283 * prevent security breaches. i.e. People
284 * reading passwords from the 'core' file.
286 struct rlimit limits;
289 limits.rlim_max = core_limits.rlim_max;
291 if (setrlimit(RLIMIT_CORE, &limits) < 0) {
292 radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
299 * Parse the server's proxy configuration values.
301 if (proxy_requests) {
302 cs = cf_section_find("proxy");
306 cf_section_parse(cs, proxy_config);
311 * Parse a string into a syslog facility level.
313 static int str2fac(const char *s)
316 if(!strcmp(s, "kern"))
321 if(!strcmp(s, "user"))
326 if(!strcmp(s, "mail"))
331 if(!strcmp(s, "daemon"))
336 if(!strcmp(s, "auth"))
341 if(!strcmp(s, "auth"))
346 if(!strcmp(s, "lpr"))
351 if(!strcmp(s, "news"))
356 if(!strcmp(s, "uucp"))
361 if(!strcmp(s, "cron"))
366 if(!strcmp(s, "authpriv"))
371 if(!strcmp(s, "ftp"))
376 if(!strcmp(s, "local0"))
381 if(!strcmp(s, "local1"))
386 if(!strcmp(s, "local2"))
391 if(!strcmp(s, "local3"))
396 if(!strcmp(s, "local4"))
401 if(!strcmp(s, "local5"))
406 if(!strcmp(s, "local6"))
411 if(!strcmp(s, "local7"))
416 fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
421 /* this should never be reached */
425 int main(int argc, char **argv)
428 RADIUS_PACKET *packet;
430 unsigned char buffer[4096];
431 struct sockaddr salocal;
432 struct sockaddr_in *sa;
443 int syslog_facility = LOG_DAEMON;
446 set_auth_parameters(argc,argv);
450 * Open /dev/null, and make sure filedescriptors
451 * 0, 1 and 2 are connected to something.
454 while (devnull >= 0 && devnull < 3)
455 devnull = open("/dev/null", O_RDWR);
457 if ((progname = strrchr(argv[0], '/')) == NULL)
464 radius_dir = strdup(RADIUS_DIR);
466 signal(SIGHUP, sig_hup);
467 signal(SIGINT, sig_fatal);
468 signal(SIGQUIT, sig_fatal);
470 signal(SIGPIPE, SIG_IGN);
473 signal(SIGTRAP, sig_fatal);
476 signal(SIGIOT, sig_fatal);
480 * Pooled threads and child threads define their own
483 #ifndef WITH_THREAD_POOL
484 #ifndef HAVE_PTHREAD_H
485 signal(SIGTERM, sig_fatal);
488 signal(SIGCHLD, sig_cleanup);
490 signal(SIGFPE, sig_fatal);
491 signal(SIGSEGV, sig_fatal);
492 signal(SIGILL, sig_fatal);
496 * Close unused file descriptors.
498 for (t = 32; t >= 3; t--)
499 if(t!=devnull) close(t);
502 * Process the options.
504 while((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:p:sSvxXyz")) != EOF) {
509 log_auth_detail = TRUE;
513 if (radacct_dir) free(radacct_dir);
514 radacct_dir = strdup(optarg);
517 #if defined(WITH_DBM) || defined(WITH_NDBM)
523 /* ignore for backwards compatibility with Cistron */
527 if (radius_dir) free(radius_dir);
528 radius_dir = strdup(optarg);
540 if ((myip = ip_getaddr(optarg)) == INADDR_NONE) {
541 fprintf(stderr, "radiusd: %s: host unknown\n",
548 if (radlog_dir) free(radlog_dir);
549 radlog_dir = strdup(optarg);
553 * We should also have this as a configuration
557 syslog_facility = str2fac(optarg);
561 log_stripped_names++;
565 radius_port = atoi(optarg);
568 case 's': /* Single process mode */
577 * BIG debugging mode for users who are
578 * TOO LAZY to type '-sfxxyz -l stdout' themselves.
586 log_auth_pass = TRUE;
587 radlog_dir = strdup("stdout");
600 log_auth_pass = TRUE;
610 * Get out PID: the configuration file reader uses it.
612 radius_pid = getpid();
615 * Get the current maximum for core files.
617 if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
618 radlog(L_ERR|L_CONS, "Failed to get current core limit:"
619 " %s", strerror(errno));
624 * Read the configuration files, BEFORE doing anything else.
630 * If they asked for syslog, then give it to them.
631 * Also, initialize the logging facility with the
632 * configuration that they asked for.
634 if (!strcmp(radlog_dir, "syslog")) {
635 openlog(progname, LOG_PID, syslog_facility);
637 /* Do you want a warning if -g is used without a -l to activate it? */
641 * Initialize the request_list[] array.
643 for (i = 0; i < 256; i++) {
644 request_list[i].first_request = NULL;
645 request_list[i].request_count = 0;
646 request_list[i].service_time = 0;
650 * Open Authentication socket.
653 authfd = socket (AF_INET, SOCK_DGRAM, 0);
655 perror("auth socket");
659 sa = (struct sockaddr_in *) & salocal;
660 memset ((char *) sa, '\0', sizeof (salocal));
661 sa->sin_family = AF_INET;
662 sa->sin_addr.s_addr = myip;
663 sa->sin_port = htons(auth_port);
665 result = bind (authfd, & salocal, sizeof (*sa));
667 perror ("auth bind");
672 * Open Accounting Socket.
674 * We prefer (in order) the authentication port + 1,
675 * then the port that the system names "radacct".
677 svp = getservbyname ("radacct", "udp");
678 if (radius_port || svp == NULL)
679 acct_port = auth_port + 1;
681 acct_port = ntohs(svp->s_port);
683 acctfd = socket (AF_INET, SOCK_DGRAM, 0);
685 perror ("acct socket");
689 sa = (struct sockaddr_in *) & salocal;
690 memset ((char *) sa, '\0', sizeof (salocal));
691 sa->sin_family = AF_INET;
692 sa->sin_addr.s_addr = myip;
693 sa->sin_port = htons(acct_port);
695 result = bind (acctfd, & salocal, sizeof (*sa));
697 perror ("acct bind");
702 * If we're proxying requests, open the proxy FD.
703 * Otherwise, don't do anything.
705 if (proxy_requests) {
709 proxyfd = socket (AF_INET, SOCK_DGRAM, 0);
711 perror ("proxy socket");
715 sa = (struct sockaddr_in *) & salocal;
716 memset ((char *) sa, '\0', sizeof (salocal));
717 sa->sin_family = AF_INET;
718 sa->sin_addr.s_addr = myip;
721 * Set the proxy port to be one more than the
724 for (proxy_port = acct_port + 1; proxy_port < 64000; proxy_port++) {
725 sa->sin_port = htons(proxy_port);
726 result = bind (proxyfd, & salocal, sizeof (*sa));
733 * Couldn't find a port to which we could bind.
735 if (proxy_port == 64000) {
736 perror("proxy bind");
742 * NOT proxying requests, set the FD to a bad value.
749 * Register built-in compare functions.
751 pair_builtincompare_init();
759 * Connect 0, 1 and 2 to /dev/null.
761 if (!debug_flag && devnull >= 0) {
763 if (strcmp(radlog_dir, "stdout") != 0) {
767 if (devnull > 2) close(devnull);
772 * Disconnect from session
774 if (debug_flag == 0 && dont_fork == 0) {
777 radlog(L_ERR|L_CONS, "Couldn't fork");
782 * The parent exits, so the child can run in the background.
793 * Ensure that we're using the CORRECT pid after forking,
794 * NOT the one we started with.
796 radius_pid = getpid();
800 * Only write the PID file if we're running as a daemon.
802 * And write it AFTER we've forked, so that we write the
805 if (dont_fork == FALSE) {
808 fp = fopen(pid_file, "w");
810 fprintf(fp, "%d\n", (int) radius_pid);
813 radlog(L_ERR|L_CONS, "Failed writing process id to file %s: %s\n",
814 pid_file, strerror(errno));
821 * If we're spawning children, set up the thread pool.
829 * Use linebuffered or unbuffered stdout if
830 * the debug flag is on.
832 if (debug_flag) setlinebuf(stdout);
835 strcpy((char *)buffer, "*");
837 ip_ntoa((char *)buffer, myip);
840 if (proxy_requests) {
841 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp, with proxy on %d/udp.",
842 buffer, auth_port, acct_port, proxy_port);
844 radlog(L_INFO, "Listening on IP address %s, ports %d/udp and %d/udp.",
845 buffer, auth_port, acct_port);
849 * Note that we NO LONGER fork an accounting process!
850 * We used to do it for historical reasons, but that
853 radlog(L_INFO, "Ready to process requests.");
856 * Receive user requests
868 FD_SET(authfd, &readfds);
870 FD_SET(acctfd, &readfds);
872 FD_SET(proxyfd, &readfds);
875 FD_SET(smuxfd, &readfds);
878 status = select(32, &readfds, NULL, NULL,
883 * On interrupts, we clean up the
886 if (errno == EINTR) {
890 radlog(L_ERR, "Unexpected error in select(): %s",
896 * When receiving a packet, or timeout,
897 * service the proxy request list.
899 if ((status == 0) && proxy_requests) {
903 for (i = 0; i < 3; i++) {
905 if (i == 0) fd = authfd;
906 if (i == 1) fd = acctfd;
907 if (i == 2) fd = proxyfd;
908 if (fd < 0 || !FD_ISSET(fd, &readfds))
911 * Receive the packet.
913 packet = rad_recv(fd);
914 if (packet == NULL) {
915 radlog(L_ERR, "%s", librad_errstr);
920 snmp_acctotalrequests++;
922 snmp_authtotalrequests++;
926 * Check if we know this client for authfd and acctfd.
927 * Check if we know this proxy for proxyfd.
931 if ((cl = client_find(packet->src_ipaddr)) == NULL) {
932 radlog(L_ERR, "Ignoring request from unknown client %s:%d",
933 buffer, packet->src_port);
940 } else { /* It came in on the proxy port */
942 if ((rl = realm_findbyaddr(packet->src_ipaddr)) == NULL) {
943 radlog(L_ERR, "Ignoring request from unknown proxy %s:%d",
944 buffer, packet->src_port);
953 * Do yet another check, to see if the
954 * packet code is valid. We only understand
955 * a few, so stripping off obviously invalid
956 * packets here will make our life easier.
958 if (packet->code > PW_ACCESS_CHALLENGE) {
959 radlog(L_ERR, "Ignoring request from client %s:%d with unknown code %d", buffer, packet->src_port, packet->code);
964 if ((request = malloc(sizeof(REQUEST))) == NULL) {
965 radlog(L_ERR|L_CONS, "no memory");
968 memset(request, 0, sizeof(REQUEST));
970 request->magic = REQUEST_MAGIC;
972 request->packet = packet;
973 request->proxy = NULL;
974 request->reply = NULL;
975 request->proxy_reply = NULL;
976 request->config_items = NULL;
977 request->username = NULL;
978 request->password = NULL;
979 request->timestamp = now;
980 request->child_pid = NO_SUCH_CHILD_PID;
981 request->prev = NULL;
982 request->next = NULL;
983 strNcpy(request->secret, secret, sizeof(request->secret));
984 rad_process(request, spawn_flag);
985 } /* loop over authfd, acctfd, proxyfd */
988 * After processing all new requests,
989 * check if we've got to delete old requests
990 * from the request list.
995 * After handling all authentication/accounting
996 * requests, THEN process any pending SMUX/SNMP
999 * Note that the handling is done in the main server,
1000 * which probably isn't a Good Thing. It really
1001 * should be wrapped, and handled in a thread pool.
1003 if ((smuxfd >= 0) &&
1004 FD_ISSET(smuxfd, &readfds) &&
1005 (smux_event == SMUX_READ)) {
1010 * If we've got to re-connect, then do so now,
1011 * before calling select again.
1013 if (smux_event == SMUX_CONNECT) {
1017 } /* loop forever */
1022 * Process supported requests:
1024 * PW_AUTHENTICATION_REQUEST - Authentication request from
1025 * a client network access server.
1027 * PW_ACCOUNTING_REQUEST - Accounting request from
1028 * a client network access server.
1030 * PW_AUTHENTICATION_ACK
1031 * PW_AUTHENTICATION_REJECT
1032 * PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
1033 * Relay reply back to original NAS.
1036 int rad_process(REQUEST *request, int dospawn)
1038 RAD_REQUEST_FUNP fun;
1042 assert(request->magic == REQUEST_MAGIC);
1044 switch(request->packet->code) {
1046 case PW_AUTHENTICATION_REQUEST:
1048 * Check for requests sent to the wrong port,
1049 * and ignore them, if so.
1051 if (request->packet->sockfd != authfd) {
1052 radlog(L_ERR, "Request packet code %d sent to authentication port from "
1053 "client %s:%d - ID %d : IGNORED",
1054 request->packet->code,
1055 client_name(request->packet->src_ipaddr),
1056 request->packet->src_port,
1057 request->packet->id);
1058 request_free(request);
1063 case PW_ACCOUNTING_REQUEST:
1065 * Check for requests sent to the wrong port,
1066 * and ignore them, if so.
1068 if (request->packet->sockfd != acctfd) {
1069 radlog(L_ERR, "Request packet code %d sent to accounting port from "
1070 "client %s:%d - ID %d : IGNORED",
1071 request->packet->code,
1072 client_name(request->packet->src_ipaddr),
1073 request->packet->src_port,
1074 request->packet->id);
1075 request_free(request);
1080 case PW_AUTHENTICATION_ACK:
1081 case PW_AUTHENTICATION_REJECT:
1082 case PW_ACCOUNTING_RESPONSE:
1084 * Replies NOT sent to the proxy port get an
1085 * error message logged, and the packet is
1088 if (request->packet->sockfd != proxyfd) {
1089 radlog(L_ERR, "Reply packet code %d sent to request port from "
1090 "client %s:%d - ID %d : IGNORED",
1091 request->packet->code,
1092 client_name(request->packet->src_ipaddr),
1093 request->packet->src_port,
1094 request->packet->id);
1095 request_free(request);
1101 assert(request->magic == REQUEST_MAGIC);
1104 * Select the required function and indicate if
1105 * we need to fork off a child to handle it.
1107 switch(request->packet->code) {
1109 case PW_AUTHENTICATION_ACK:
1110 case PW_AUTHENTICATION_REJECT:
1111 case PW_AUTHENTICATION_REQUEST:
1112 fun = rad_authenticate;
1115 case PW_ACCOUNTING_RESPONSE:
1116 case PW_ACCOUNTING_REQUEST:
1117 fun = rad_accounting;
1120 case PW_PASSWORD_REQUEST:
1122 * We don't support this anymore.
1124 radlog(L_ERR, "Deprecated password change request from client %s:%d "
1125 "- ID %d : IGNORED",
1126 client_name(request->packet->src_ipaddr),
1127 request->packet->src_port,
1128 request->packet->id);
1129 request_free(request);
1134 radlog(L_ERR, "Unknown packet type %d from client %s:%d "
1135 "- ID %d : IGNORED",
1136 request->packet->code,
1137 client_name(request->packet->src_ipaddr),
1138 request->packet->src_port,
1139 request->packet->id);
1140 request_free(request);
1146 * If we did NOT select a function, then exit immediately.
1149 request_free(request);
1154 * Check for a duplicate, or error.
1155 * Throw away the the request if so.
1157 request = rad_check_list(request);
1158 if (request == NULL) {
1162 assert(request->magic == REQUEST_MAGIC);
1165 * The request passes many of our sanity checks. From
1166 * here on in, if anything goes wrong, we send a reject
1167 * message, instead of dropping the packet.
1169 * Build the reply template from the request template.
1171 if ((request->reply = rad_alloc(0)) == NULL) {
1172 fprintf(stderr, "out of memory\n");
1175 request->reply->sockfd = request->packet->sockfd;
1176 request->reply->dst_ipaddr = request->packet->src_ipaddr;
1177 request->reply->dst_port = request->packet->src_port;
1178 request->reply->id = request->packet->id;
1179 request->reply->code = 0; /* UNKNOWN code */
1180 memcpy(request->reply->vector, request->packet->vector,
1181 sizeof(request->reply->vector));
1182 request->reply->vps = NULL;
1183 request->reply->data = NULL;
1186 * If we're spawning a child thread, let it do all of
1187 * the work of handling a request, and exit.
1191 * Maybe the spawn failed. If so, then we
1192 * trivially reject the request (because we can't
1193 * handle it), and return.
1195 if (rad_spawn_child(request, fun) < 0) {
1196 rad_reject(request);
1197 request->finished = TRUE;
1202 rad_respond(request, fun);
1207 * Reject a request, by sending a trivial reply packet.
1209 static void rad_reject(REQUEST *request)
1211 DEBUG2("Server rejecting request.");
1212 switch (request->packet->code) {
1214 * Accounting requests, etc. get dropped on the floor.
1216 case PW_ACCOUNTING_REQUEST:
1221 * Authentication requests get their Proxy-State
1222 * attributes copied over, and an otherwise blank
1223 * reject message sent.
1225 case PW_AUTHENTICATION_REQUEST:
1226 request->reply->code = PW_AUTHENTICATION_REJECT;
1231 * If a reply exists, send it.
1233 if (request->reply->code) {
1234 rad_send(request->reply, request->secret);
1239 * Respond to a request packet.
1241 * Maybe we reply, maybe we don't.
1242 * Maybe we proxy the request to another server, or else maybe
1243 * we replicate it to another server.
1245 int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
1247 RADIUS_PACKET *packet, *original;
1249 int finished = FALSE;
1253 * Put the decoded packet into it's proper place.
1255 if (request->proxy_reply != NULL) {
1256 packet = request->proxy_reply;
1257 secret = request->proxysecret;
1258 original = request->proxy;
1260 packet = request->packet;
1261 secret = request->secret;
1265 assert(request->magic == REQUEST_MAGIC);
1268 * Decode the packet, verifying it's signature,
1269 * and parsing the attributes into structures.
1271 * Note that we do this CPU-intensive work in
1272 * a child thread, not the master. This helps to
1273 * spread the load a little bit.
1275 if (rad_decode(packet, original, secret) != 0) {
1276 radlog(L_ERR, "%s", librad_errstr);
1277 rad_reject(request);
1278 goto finished_request;
1282 * For proxy replies, remove non-allowed
1283 * attributes from the list of VP's.
1285 if (request->proxy) {
1287 replicating = proxy_receive(request);
1288 if (replicating != 0) {
1294 * We should have a User-Name attribute now.
1296 if (request->username == NULL) {
1297 request->username = pairfind(request->packet->vps,
1302 * We have the semaphore, and have decoded the packet.
1303 * Let's process the request.
1305 assert(request->magic == REQUEST_MAGIC);
1309 * If we don't already have a proxy
1310 * packet for this request, we MIGHT have
1313 if (proxy_requests) {
1314 if (request->proxy == NULL) {
1315 proxy_sent = proxy_send(request);
1318 * sent==1 means it's been proxied. The child
1319 * is done handling the request, but the request
1322 if (proxy_sent == 1) {
1323 goto postpone_request;
1326 } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
1327 (request->reply == NULL)) {
1329 * We're not configured to reply to the packet,
1330 * and we're not proxying, so the DEFAULT behaviour
1331 * is to REJECT the user.
1333 DEBUG2("There was no response configured: rejecting the user.");
1334 rad_reject(request);
1335 goto finished_request;
1339 * If we have a reply to send, copy the Proxy-State
1340 * attributes from the request to the tail of the reply,
1341 * and send the packet.
1343 assert(request->magic == REQUEST_MAGIC);
1344 if (request->reply->code != 0) {
1348 * Need to copy Proxy-State from request->packet->vps
1350 vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
1352 pairadd(&(request->reply->vps), vp);
1354 rad_send(request->reply, request->secret);
1358 * We're done processing the request, set the
1359 * request to be finished, clean up as necessary,
1360 * and forget about the request.
1364 * We're done handling the request. Free up the linked
1365 * lists of value pairs. This might take a long time,
1366 * so it's more efficient to do it in a child thread,
1367 * instead of in the main handler when it eventually
1368 * gets around to deleting the request.
1370 * Also, no one should be using these items after the
1371 * request is finished, and the reply is sent. Cleaning
1372 * them up here ensures that they're not being used again.
1374 * Hmm... cleaning them up in the child thread also seems
1375 * to make the server run more efficiently!
1378 /* If we proxied this request, it's not safe to delete it until
1379 * after the proxy reply
1382 goto postpone_request;
1384 if (request->packet && request->packet->vps) {
1385 pairfree(request->packet->vps);
1386 request->packet->vps = NULL;
1387 request->username = NULL;
1388 request->password = NULL;
1390 if (request->reply && request->reply->vps) {
1391 pairfree(request->reply->vps);
1392 request->reply->vps = NULL;
1394 if (request->config_items) {
1395 pairfree(request->config_items);
1396 request->config_items = NULL;
1399 DEBUG2("Finished request");
1403 * Go to the next request, without marking
1404 * the current one as finished.
1407 DEBUG2("Going to the next request");
1410 * If this is an accounting request, ensure
1411 * that we delete it immediately, as there CANNOT be
1412 * duplicate accounting packets. If there are, then
1413 * something else is seriously wrong...
1415 if (request->packet->code == PW_ACCOUNTING_REQUEST) {
1416 request->timestamp = 0;
1419 #if WITH_THREAD_POOL
1420 request->child_pid = NO_SUCH_CHILD_PID;
1422 request->finished = finished; /* do as the LAST thing before exiting */
1429 * Clean up the request list, every so often.
1431 * This is done by walking through ALL of the list, and
1432 * - joining any child threads which have exited. (If not pooling)
1433 * - killing any processes which are NOT finished after a delay
1434 * - deleting any requests which are finished, and expired
1436 static int rad_clean_list(time_t curtime)
1438 static time_t last_cleaned_list = 0;
1441 child_pid_t child_pid;
1444 int cleaned = FALSE;
1447 * Don't bother checking the list if we've done it
1448 * within the last second.
1450 if ((curtime - last_cleaned_list) == 0) {
1454 #if WITH_THREAD_POOL
1456 * Only clean the thread pool if we've spawned child threads.
1459 thread_pool_clean();
1464 * When mucking around with the request list, we block
1465 * asynchronous access (through the SIGCHLD handler) to
1466 * the list - equivalent to sigblock(SIGCHLD).
1468 request_list_busy = TRUE;
1470 for (id = 0; id < 256; id++) {
1471 curreq = request_list[id].first_request;
1474 while (curreq != NULL) {
1475 assert(curreq->magic == REQUEST_MAGIC);
1478 * Maybe the child process handling the request
1479 * has hung: kill it, and continue.
1481 if (!curreq->finished &&
1482 (curreq->timestamp + max_request_time) <= curtime) {
1483 if (curreq->child_pid != NO_SUCH_CHILD_PID) {
1485 * This request seems to have hung
1488 child_pid = curreq->child_pid;
1489 radlog(L_ERR, "Killing unresponsive child %d",
1491 child_kill(child_pid, SIGTERM);
1492 } /* else no proxy reply, quietly fail */
1495 * Mark the request as unsalvagable.
1497 curreq->child_pid = NO_SUCH_CHILD_PID;
1498 curreq->finished = TRUE;
1499 curreq->timestamp = 0;
1503 * Delete the current request, if it's
1504 * marked as such. That is, the request
1505 * must be finished, there must be no
1506 * child associated with that request,
1507 * and it's timestamp must be marked to
1510 if (curreq->finished &&
1511 (curreq->child_pid == NO_SUCH_CHILD_PID) &&
1512 (curreq->timestamp + cleanup_delay <= curtime)) {
1514 * Request completed, delete it,
1515 * and unlink it from the
1516 * currently 'alive' list of
1519 DEBUG2("Cleaning up request ID %d with timestamp %08lx",
1521 (unsigned long)curreq->timestamp);
1522 prevreq = curreq->prev;
1523 if (request_list[id].request_count == 0) {
1524 DEBUG("HORRIBLE ERROR!!!");
1526 request_list[id].request_count--;
1530 if (prevreq == NULL) {
1531 request_list[id].first_request = curreq->next;
1532 request_free(curreq);
1533 curreq = request_list[id].first_request;
1535 prevreq->next = curreq->next;
1536 request_free(curreq);
1537 curreq = prevreq->next;
1540 curreq->prev = prevreq;
1542 } else { /* the request is still alive */
1544 curreq = curreq->next;
1546 } /* end of walking the request list for that ID */
1547 } /* for each entry in the request list array */
1550 for (id = 0; id < 256; id++) {
1551 request_count += request_list[id].request_count;
1555 * Only print this if anything's changed.
1558 static int old_request_count = -1;
1560 if (request_count != old_request_count) {
1561 DEBUG2("%d requests left in the list", request_count);
1562 old_request_count = request_count;
1567 * We're done playing with the request list.
1569 request_list_busy = FALSE;
1570 last_cleaned_list = curtime;
1576 * Walk through the request list, cleaning up complete child
1577 * requests, and verifing that there is only one process
1578 * responding to each request (duplicate requests are filtered
1581 * Also, check if the request is a reply from a request proxied to
1582 * a remote server. If so, play games with the request, and return
1585 static REQUEST *rad_check_list(REQUEST *request)
1591 REQUEST_LIST *request_list_entry;
1597 * If the request has come in on the proxy FD, then
1598 * it's a proxy reply, so pass it through the proxy
1599 * code for checking the REQUEST_LIST.
1601 if (request->packet->sockfd == proxyfd) {
1602 return proxy_check_list(request);
1605 * If the request already has a proxy packet,
1606 * then it obviously is not a new request, either.
1608 } else if (request->proxy != NULL) {
1612 request_list_entry = &request_list[request->packet->id];
1614 assert((request_list_entry->first_request == NULL) ||
1615 (request_list_entry->request_count != 0));
1616 assert((request_list_entry->first_request != NULL) ||
1617 (request_list_entry->request_count == 0));
1619 curreq = request_list_entry->first_request;
1621 pkt = request->packet;
1623 curtime = request->timestamp; /* good enough for our purposes */
1627 * When mucking around with the request list, we block
1628 * asynchronous access (through the SIGCHLD handler) to
1629 * the list - equivalent to sigblock(SIGCHLD).
1631 request_list_busy = TRUE;
1633 while (curreq != NULL) {
1634 assert(curreq->packet->id == pkt->id);
1637 * Let's see if we received a duplicate of
1638 * a packet we already have in our list.
1640 * We do this be checking the src IP, (NOT port)
1641 * the packet code, and ID.
1643 if ((curreq->packet->src_ipaddr == pkt->src_ipaddr) &&
1644 (curreq->packet->code == pkt->code)) {
1646 * We now check the authentication vectors.
1647 * If the client has sent us a request with
1648 * identical code && ID, but different vector,
1649 * then they MUST have gotten our response, so
1650 * we can delete the original request, and process
1653 * If the vectors are the same, then it's a duplicate
1654 * request, and we can send a duplicate reply.
1656 if (memcmp(curreq->packet->vector, pkt->vector,
1657 sizeof(pkt->vector)) == 0) {
1659 * Maybe we've saved a reply packet. If so,
1660 * re-send it. Otherwise, just complain.
1662 if (curreq->reply) {
1664 "Sending duplicate authentication reply"
1665 " to client %s:%d - ID: %d",
1666 client_name(request->packet->src_ipaddr),
1667 request->packet->src_port,
1668 request->packet->id);
1671 * Use the SOURCE port as the DESTINATION
1672 * port of the duplicate reply.
1674 curreq->reply->dst_port = request->packet->src_port;
1675 rad_send(curreq->reply, curreq->secret);
1678 * There's no reply, but maybe there's
1679 * an outstanding proxy request.
1681 * If so, then kick the proxy again.
1683 } else if (curreq->proxy != NULL) {
1684 if (proxy_synchronous) {
1685 DEBUG2("Sending duplicate proxy request to client %s:%d - ID: %d",
1686 client_name(curreq->proxy->dst_ipaddr),
1687 request->packet->src_port,
1690 curreq->proxy_next_try = request->timestamp + proxy_retry_delay;
1691 rad_send(curreq->proxy, curreq->proxysecret);
1693 DEBUG2("Ignoring duplicate authentication packet"
1694 " from client %s:%d - ID: %d, due to outstanding proxy request.",
1695 client_name(request->packet->src_ipaddr),
1696 request->packet->src_port,
1697 request->packet->id);
1701 "Dropping duplicate authentication packet"
1702 " from client %s:%d - ID: %d",
1703 client_name(request->packet->src_ipaddr),
1704 request->packet->src_port,
1705 request->packet->id);
1709 * Delete the duplicate request, and
1710 * stop processing the request list.
1712 request_free(request);
1717 * The packet vectors are different, so
1718 * we can mark the old request to be
1719 * deleted from the list.
1721 * Note that we don't actually delete it...
1724 if (curreq->finished) {
1725 curreq->timestamp = 0;
1728 * ??? the client sent us a new request
1729 * with the same ID, while we were
1730 * processing the old one! What should
1734 "Dropping conflicting authentication packet"
1735 " from client %s:%d - ID: %d",
1736 client_name(request->packet->src_ipaddr),
1737 request->packet->src_port,
1738 request->packet->id);
1739 request_free(request);
1747 * Ugh... duplicated code is bad...
1751 * Delete the current request, if it's
1752 * marked as such. That is, the request
1753 * must be finished, there must be no
1754 * child associated with that request,
1755 * and it's timestamp must be marked to
1758 if (curreq->finished &&
1759 (curreq->child_pid == NO_SUCH_CHILD_PID) &&
1760 (curreq->timestamp + cleanup_delay <= curtime)) {
1762 * Request completed, delete it,
1763 * and unlink it from the
1764 * currently 'alive' list of
1767 DEBUG2("Cleaning up request ID %d with timestamp %08lx",
1769 (unsigned long)curreq->timestamp);
1770 prevreq = curreq->prev;
1771 if (request_list[id].request_count == 0) {
1772 DEBUG("HORRIBLE ERROR!!!");
1774 request_list[id].request_count--;
1777 if (prevreq == NULL) {
1778 request_list[id].first_request = curreq->next;
1779 request_free(curreq);
1780 curreq = request_list[id].first_request;
1782 prevreq->next = curreq->next;
1783 request_free(curreq);
1784 curreq = prevreq->next;
1787 curreq->prev = prevreq;
1789 } else { /* the request is still alive */
1791 curreq = curreq->next;
1794 } /* end of walking the request list */
1797 * If we've received a duplicate packet, 'request' is NULL.
1799 if (request == NULL) {
1800 request_list_busy = FALSE;
1804 assert(request_list_entry->request_count == request_count);
1807 * Count the total number of requests, to see if there
1808 * are too many. If so, stop counting immediately,
1809 * and return with an error.
1812 for (i = 0; i < 256; i++) {
1813 request_count += request_list[i].request_count;
1816 * This is a new request. Let's see if it
1817 * makes us go over our configured bounds.
1819 if (request_count > max_requests) {
1820 radlog(L_ERR, "Dropping request (%d is too many): "
1821 "from client %s:%d - ID: %d", request_count,
1822 client_name(request->packet->src_ipaddr),
1823 request->packet->src_port,
1824 request->packet->id);
1825 request_free(request);
1826 request_list_busy = FALSE;
1832 * Add this request to the list
1834 request->prev = prevreq;
1835 request->next = NULL;
1836 request->child_pid = NO_SUCH_CHILD_PID;
1837 request_list_entry->request_count++;
1839 if (prevreq == NULL) {
1840 assert(request_list_entry->first_request == NULL);
1841 assert(request_list_entry->request_count == 1);
1842 request_list_entry->first_request = request;
1844 assert(request_list_entry->first_request != NULL);
1845 prevreq->next = request;
1849 * And return the request to be handled.
1851 request_list_busy = FALSE;
1855 #ifndef WITH_THREAD_POOL
1857 typedef struct spawn_thread_t {
1859 RAD_REQUEST_FUNP fun;
1863 * If the child *thread* gets a termination signal,
1864 * then exit from the thread.
1866 static void sig_term(int sig)
1868 sig = sig; /* -Wunused */
1873 * Spawn a new child thread to handle this request, and ONLY
1876 static void *rad_spawn_thread(void *arg)
1879 spawn_thread_t *data = (spawn_thread_t *)arg;
1882 * Note that this behaviour only works on Linux.
1884 * It's generally NOT the thing to do, and should
1887 * Q: How do we signal a hung thread, and tell it to
1890 signal(SIGTERM, sig_term);
1893 * Keep only allowed attributes in the request.
1895 if (data->request->proxy) {
1896 replicating = proxy_receive(data->request);
1897 if (replicating != 0) {
1898 data->request->finished = TRUE;
1904 rad_respond(data->request, data->fun);
1905 data->request->child_pid = NO_SUCH_CHILD_PID;
1913 * If we're using the thread pool, then the function in
1914 * 'threads.c' replaces this one.
1916 #ifndef WITH_THREAD_POOL
1918 * Spawns a child process or thread to perform
1919 * authentication/accounting and respond to RADIUS clients.
1921 static int rad_spawn_child(REQUEST *request, RAD_REQUEST_FUNP fun)
1923 child_pid_t child_pid;
1927 spawn_thread_t *data;
1929 data = (spawn_thread_t *) malloc(sizeof(spawn_thread_t));
1930 memset(data, 0, sizeof(data));
1931 data->request = request;
1935 * Create a child thread, complaining on error.
1937 rcode = pthread_create(&child_pid, NULL, rad_spawn_thread, data);
1939 radlog(L_ERR, "Thread create failed for request from nas %s - ID: %d : %s",
1940 nas_name2(request->packet),
1941 request->packet->id,
1947 * Detach it, so it's state is automagically cleaned up on exit.
1949 pthread_detach(child_pid);
1956 if (child_pid < 0) {
1957 radlog(L_ERR, "Fork failed for request from nas %s - ID: %d",
1958 nas_name2(request->packet),
1959 request->packet->id);
1963 if (child_pid == 0) {
1966 * This is the child, it should go ahead and respond
1968 signal(SIGCHLD, SIG_DFL);
1969 rad_respond(request, fun);
1975 * Register the Child
1977 request->child_pid = child_pid;
1980 #endif /* WITH_THREAD_POOL */
1983 void sig_cleanup(int sig)
1985 #ifndef HAVE_PTHREAD_H
1992 sig = sig; /* -Wunused */
1995 * request_list_busy is a lock on the request list
1997 if (request_list_busy) {
2004 * Reset the signal handler, if required.
2006 reset_signal(SIGCHLD, sig_cleanup);
2009 * If we're using pthreads, then there are NO child processes,
2010 * so the waitpid() call, and the following code, is useless.
2012 #ifndef HAVE_PTHREAD_H
2014 pid = waitpid((pid_t)-1, &status, WNOHANG);
2019 * Check to see if the child did a bad thing.
2020 * If so, kill ALL processes in the current
2021 * process group, to prevent further attacks.
2023 if (debug_flag && (WIFSIGNALED(status))) {
2024 radlog(L_ERR|L_CONS, "MASTER: Child PID %d failed to catch signal %d: killing all active servers.\n",
2025 pid, WTERMSIG(status));
2031 * Service all of the requests in the queues
2033 for (i = 0; i < 256; i++) {
2034 curreq = request_list[i].first_request;
2035 while (curreq != (REQUEST *)NULL) {
2036 if (curreq->child_pid == pid) {
2037 curreq->child_pid = NO_SUCH_CHILD_PID;
2040 curreq = curreq->next;
2044 #endif /* !defined HAVE_PTHREAD_H */
2048 * Display the syntax for starting this program.
2050 static void usage(void)
2053 "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-"
2054 #if defined(WITH_DBM) || defined(WITH_NDBM)
2057 "AcfnsSvXxyz]\n", progname);
2058 fprintf(stderr, "Options:\n\n");
2059 fprintf(stderr, " -a acct_dir use accounting directory 'acct_dir'.\n");
2060 fprintf(stderr, " -A Log auth detail.\n");
2061 #if defined(WITH_DBM) || defined(WITH_NDBM)
2062 fprintf(stderr, " -b Use DBM.\n");
2064 fprintf(stderr, " -d db_dir Use database directory 'db_dir'.\n");
2065 fprintf(stderr, " -f Run as a foreground process, not a daemon.\n");
2066 fprintf(stderr, " -h Print this help message.\n");
2067 fprintf(stderr, " -i address Listen only in the given IP address.\n");
2068 fprintf(stderr, " -l log_dir Log messages to 'log_dir'. Special values are:\n");
2069 fprintf(stderr, " stdout == log all messages to standard output.\n");
2070 fprintf(stderr, " syslog == log all messages to the system logger.\n");
2071 fprintf(stderr, " -p port Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
2072 fprintf(stderr, " -s Do not spawn child processes to handle requests.\n");
2073 fprintf(stderr, " -S Log stripped names.\n");
2074 fprintf(stderr, " -v Print server version information.\n");
2075 fprintf(stderr, " -X Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
2076 fprintf(stderr, " -x Turn on partial debugging. (-xx gives more debugging).\n");
2077 fprintf(stderr, " -y Log authentication failures, with password.\n");
2078 fprintf(stderr, " -z Log authentication successes, with password.\n");
2084 * We got a fatal signal. Clean up and exit.
2086 static void sig_fatal(int sig)
2088 const char *me = "MASTER: ";
2090 if (radius_pid != getpid()) {
2096 radlog(L_ERR, "%saccounting process died - exit.", me);
2099 radlog(L_ERR, "%sfailed in select() - exit.", me);
2102 radlog(L_INFO, "%sexit.", me);
2105 radlog(L_ERR, "%sexit on signal (%d)", me, sig);
2110 * We're running as a daemon, we're the MASTER daemon,
2111 * and we got a fatal signal. Tear the rest of the
2112 * daemons down, as something absolutely horrible happened.
2114 if ((debug_flag == 0) && (dont_fork == 0) &&
2115 (radius_pid == getpid())) {
2117 * Kill all of the processes in the current
2123 exit(sig == SIGTERM ? 0 : 1);
2128 * We got the hangup signal.
2129 * Re-read the configuration files.
2132 static void sig_hup(int sig)
2134 sig = sig; /* -Wunused */
2135 reset_signal(SIGHUP, sig_hup);
2138 * Only do the reload if we're the main server, both
2139 * for processes, and for threads.
2141 if (getpid() == radius_pid) {
2147 * Do a proxy check of the REQUEST_LIST when using the new proxy code.
2149 * This function and the next two are here because they have to access
2150 * the REQUEST_LIST structure, which is 'static' to this C file.
2152 static REQUEST *proxy_check_list(REQUEST *request)
2159 * Find the original request in the request list
2162 pkt = request->packet;
2164 for (id = 0; (id < 256) && (oldreq == NULL); id++) {
2165 for (oldreq = request_list[id].first_request ;
2167 oldreq = oldreq->next) {
2170 * See if this reply packet matches a proxy
2171 * packet which we sent.
2173 if (oldreq->proxy &&
2174 (oldreq->proxy->dst_ipaddr == pkt->src_ipaddr) &&
2175 (oldreq->proxy->dst_port == pkt->src_port) &&
2176 (oldreq->proxy->id == pkt->id)) {
2178 * If there is already a reply,
2179 * maybe the new one is a duplicate?
2181 if (oldreq->proxy_reply) {
2182 if (memcmp(oldreq->proxy_reply->vector,
2183 request->packet->vector,
2184 sizeof(oldreq->proxy_reply->vector)) == 0) {
2185 DEBUG2("Ignoring duplicate proxy reply");
2186 request_free(request);
2194 } /* else no reply, this one must match */
2197 * Exit from request list loop
2198 * while oldreq != NULL, which will
2199 * cause the outer loop to stop, too.
2202 } /* the reply matches a proxied request */
2203 } /* for all requests in the id request list */
2204 } /* for all 256 id's*/
2207 * If we haven't found the old request, complain.
2209 if (oldreq == NULL) {
2210 radlog(L_PROXY, "Unrecognized proxy reply from server %s - ID %d",
2211 client_name(request->packet->src_ipaddr),
2212 request->packet->id);
2213 request_free(request);
2218 * Refresh the old request, and update it with the proxy reply.
2220 * ??? Can we delete the proxy request here?
2221 * Is there any more need for it?
2223 oldreq->timestamp = request->timestamp;
2224 oldreq->proxy_reply = request->packet;
2225 request->packet = NULL;
2226 request_free(request);
2231 * Walk through all of the requests, checking cleanup times,
2232 * proxy retry times, and maximum request times. We then set the
2233 * time delay until the server has to service the request queue.
2235 * This time delay is used by the main select() loop, to sleep
2236 * until either a packet comes in, or until there's some work
2239 static struct timeval *setuptimeout(struct timeval *tv)
2241 time_t now = time(NULL);
2242 time_t difference, smallest = 0;
2243 int foundone = FALSE;
2247 difference = 1; /* initialize it to a non-zero value */
2250 * Loop over all of the outstanding requests.
2252 for (id = 0; id < 256; id++) {
2253 for (curreq = request_list[id].first_request; curreq; curreq = curreq->next) {
2255 * The request is marked to be
2256 * cleaned up: ignore it.
2258 if (curreq->timestamp == 0) {
2260 } else if (curreq->finished) {
2262 * The request is finished.
2263 * Wake up when it's time to clean
2266 difference = (curreq->timestamp + cleanup_delay) - now;
2268 } else if (curreq->proxy && !curreq->proxy_reply) {
2270 * The request is NOT finished, but there
2271 * is an outstanding proxy request,
2272 * with no matching proxy reply.
2274 * Wake up when it's time to re-send
2275 * the proxy request.
2277 difference = curreq->proxy_next_try - now;
2281 * The request is NOT finished.
2283 * Wake up when it's time to kill
2284 * the errant thread/process.
2286 difference = (curreq->timestamp + max_request_time) - now;
2290 * Found a valid request, with a time at which
2291 * we're going to to wake up.
2295 smallest = difference;
2297 if (difference < smallest)
2298 smallest = difference;
2301 if (difference <= 0) break; /* short-circuit */
2302 } /* loop over linked list for that ID */
2304 if (difference <= 0) break; /* short-circuit */
2305 } /* loop over 256 ID's */
2308 * We haven't found a time at which we need to wake up.
2309 * Return NULL, so that the select() call will sleep forever.
2312 DEBUG2("Nothing to do. Sleeping until we see a request.");
2317 * If the server is CPU starved, then we CAN miss a time
2318 * for servicing requests. In which case the 'smallest'
2319 * value will be negative. select() doesn't like that,
2322 if (smallest < 0) smallest = 0;
2325 * Set the time (in seconds) for how long we're
2326 * supposed to sleep.
2328 tv->tv_sec = smallest;
2330 DEBUG2("Waking up in %d seconds...", (int) smallest);
2335 * Walk the request list, seeing if we need to re-send
2338 static void proxy_retry(void)
2340 time_t now = time(NULL);
2345 * If we're not proxying, or if we're not re-trying
2346 * requests, then don't bother walking through the list.
2348 if (!proxy_requests ||
2349 (proxy_retry_delay == 0)) {
2354 * Walk over all of the Id's.
2356 for (id = 0; id < 256; id++) {
2357 for (p = request_list[id].first_request; p; p = p->next) {
2359 * The request is finished, (but it hasn't yet
2360 * been removed from the list.)
2361 * OR there is no proxy request,
2362 * OR we already have seen the reply (so we don't
2363 * need to send another proxy request),
2364 * OR the next try is to be done later.
2368 * FIXME: These retries should be binned by
2369 * the next try time, so we don't have to do
2370 * all of this work on every second.
2372 * That will also get rid of these checks, as
2373 * a packet can get removed from the bin when
2374 * the proxy reply is received.
2376 if ((p->finished) ||
2379 (p->proxy_next_try > now)) {
2384 * If the proxy retry count is zero, then
2385 * we've sent the last try, and have NOT received
2386 * a reply from the end server. In that case,
2387 * we don't bother trying again, but just mark
2388 * the request as finished, and go to the next one.
2390 if (p->proxy_try_count == 0) {
2397 * We're trying one more time, so count down
2398 * the tries, and set the next try time.
2400 --p->proxy_try_count;
2401 p->proxy_next_try = now + proxy_retry_delay;
2403 /* Fix up Acct-Delay-Time */
2404 if (p->proxy->code == PW_ACCOUNTING_REQUEST) {
2405 VALUE_PAIR *delaypair;
2406 delaypair = pairfind(p->proxy->vps, PW_ACCT_DELAY_TIME);
2409 delaypair = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
2411 radlog(L_ERR|L_CONS, "no memory");
2414 pairadd(&p->proxy->vps, delaypair);
2416 delaypair->lvalue = now - p->proxy->timestamp;
2418 /* Must recompile the valuepairs to wire format */
2419 free(p->proxy->data);
2420 p->proxy->data = NULL;
2421 } /* proxy accounting request */
2424 * Send the proxy packet.
2426 rad_send(p->proxy, p->proxysecret);