⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radiusd.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	 */	if (debug_flag == 0 && dont_fork == FALSE) {		pid = fork();		if(pid < 0) {			radlog(L_ERR|L_CONS, "Couldn't fork");			exit(1);		}		/*		 *  The parent exits, so the child can run in the background.		 */		if(pid > 0) {			exit(0);		}#ifdef HAVE_SETSID		setsid();#endif	}	/*	 *  Ensure that we're using the CORRECT pid after forking,	 *  NOT the one we started with.	 */	radius_pid = getpid();	/*	 *  Only write the PID file if we're running as a daemon.	 *	 *  And write it AFTER we've forked, so that we write the	 *  correct PID.	 */	if (dont_fork == FALSE) {		FILE *fp;		fp = fopen(mainconfig.pid_file, "w");		if (fp != NULL) {			/*			 *	FIXME: What about following symlinks,			 *	and having it over-write a normal file?			 */			fprintf(fp, "%d\n", (int) radius_pid);			fclose(fp);		} else {			radlog(L_ERR|L_CONS, "Failed creating PID file %s: %s\n",			       mainconfig.pid_file, strerror(errno));			exit(1);		}	}	/*	 *	If we're running as a daemon, close the default file	 *	descriptors, AFTER forking.	 */	if (debug_flag == FALSE) {		int devnull;		devnull = open("/dev/null", O_RDWR);		if (devnull < 0) {			radlog(L_ERR|L_CONS, "Failed opening /dev/null: %s\n",			       strerror(errno));			exit(1);		}		dup2(devnull, STDIN_FILENO);		dup2(devnull, STDOUT_FILENO);		dup2(devnull, STDERR_FILENO);		close(devnull);	}#ifdef HAVE_PTHREAD_H	/*	 *  If we're spawning children, set up the thread pool.	 */	if (spawn_flag == TRUE) {		thread_pool_init();	}#else	/*	 *	Without threads, we ALWAYS run in single-server mode.	 */	spawn_flag = FALSE;#endif	/*	 *  Use linebuffered or unbuffered stdout if	 *  the debug flag is on.	 */	if (debug_flag == TRUE)		setlinebuf(stdout);	/*	 *	Print out which ports we're listening on.	 */	for (listener = mainconfig.listen;	     listener != NULL;	     listener = listener->next) {		if (listener->ipaddr == INADDR_ANY) {			strcpy((char *)buffer, "*");		} else {			ip_ntoa((char *)buffer, listener->ipaddr);		}				switch (listener->type) {		case RAD_LISTEN_AUTH:			DEBUG("Listening on authentication %s:%d",			      buffer, listener->port);			break;		case RAD_LISTEN_ACCT:			DEBUG("Listening on accounting %s:%d",			      buffer, listener->port);			break;		case RAD_LISTEN_PROXY:			DEBUG("Listening on proxy %s:%d",			      buffer, listener->port);			break;		default:			break;		}	}	/*	 *	Now that we've set everything up, we can install the signal	 *	handlers.  Before this, if we get any signal, we don't know	 *	what to do, so we might as well do the default, and die.	 */	signal(SIGPIPE, SIG_IGN);#ifdef HAVE_SIGACTION	act.sa_handler = sig_hup;	sigaction(SIGHUP, &act, NULL);	act.sa_handler = sig_fatal;	sigaction(SIGTERM, &act, NULL);#else	signal(SIGHUP, sig_hup);	signal(SIGTERM, sig_fatal);#endif	/*	 *	If we're debugging, then a CTRL-C will cause the	 *	server to die immediately.  Use SIGTERM to shut down	 *	the server cleanly in that case.	 */	if (debug_flag == 0) {#ifdef HAVE_SIGACTION	        act.sa_handler = sig_fatal;		sigaction(SIGINT, &act, NULL);		sigaction(SIGQUIT, &act, NULL);#else		signal(SIGINT, sig_fatal);		signal(SIGQUIT, sig_fatal);#endif	}	radlog(L_INFO, "Ready to process requests.");	start_time = time(NULL);	/*	 *  Receive user requests	 */	for (;;) {		/*		 *	If we've been told to exit, then do so,		 *	even if we have data waiting.		 */		if (do_exit) {			DEBUG("Exiting...");			/*			 *	Ignore the TERM signal: we're about			 *	to die.			 */			signal(SIGTERM, SIG_IGN);			/*			 *	Send a TERM signal to all associated			 *	processes (including us, which gets			 *	ignored.)			 */			kill(-radius_pid, SIGTERM);			/*			 *	FIXME: Kill child threads, and			 *	clean up?			 */			/*			 *	Detach any modules.			 */			detach_modules();			/*			 *	FIXME: clean up any active REQUEST			 *	handles.			 */			/*			 *	We're exiting, so we can delete the PID			 *	file.  (If it doesn't exist, we can ignore			 *	the error returned by unlink)			 */			if (dont_fork == FALSE) {				unlink(mainconfig.pid_file);			}			/*			 *	Free the configuration items.			 */			free_mainconfig();			/*			 *	SIGTERM gets do_exit=0,			 *	and we want to exit cleanly.			 *			 *	Other signals make us exit			 *	with an error status.			 */			exit(do_exit - 1);		}		if (need_reload) {#ifdef HAVE_PTHREAD_H			/*			 *	Threads: wait for all threads to stop			 *	processing before re-loading the			 *	config, so we don't pull the rug out			 *	from under them.			 */		        int max_wait = 0;		        if (!spawn_flag) for(;;) {			        /*				 * Block until there are '0' threads				 * with a REQUEST handle.				 */			        sig_hup_block = TRUE;			        if( (total_active_threads() == 0) ||				     (max_wait >= 5) ) {				  sig_hup_block = FALSE;				  break;				}				sleep(1);				max_wait++;			}#endif			if (read_mainconfig(TRUE) < 0) {				exit(1);			}			/*  Reload the modules.  */			DEBUG2("radiusd:  entering modules setup");			if (setup_modules() < 0) {				radlog(L_ERR|L_CONS, "Errors setting up modules");				exit(1);			}			need_reload = FALSE;			radlog(L_INFO, "Ready to process requests.");		}		FD_ZERO(&readfds);		max_fd = 0;		/*		 *	Loop over all the listening FD's.		 */		for (listener = mainconfig.listen;		     listener != NULL;		     listener = listener->next) {			FD_SET(listener->fd, &readfds);			if (listener->fd > max_fd) max_fd = listener->fd;		}#ifdef WITH_SNMP		if (mainconfig.do_snmp &&		    (rad_snmp.smux_fd >= 0)) {			FD_SET(rad_snmp.smux_fd, &readfds);			if (rad_snmp.smux_fd > max_fd) max_fd = rad_snmp.smux_fd;		}#endif		status = select(max_fd + 1, &readfds, NULL, NULL, tv);		if (status == -1) {			/*			 *	On interrupts, we clean up the request			 *	list.  We then continue with the loop,			 *	so that if we're supposed to exit,			 *	then the code at the start of the loop			 *	catches that, and exits.			 */			if (errno == EINTR) {				tv = rl_clean_list(time(NULL));				continue;			}			radlog(L_ERR, "Unexpected error in select(): %s",					strerror(errno));			exit(1);		}		time_now = time(NULL);#ifndef HAVE_PTHREAD_H		/*		 *	If there are no child threads, then there may		 *	be child processes.  In that case, wait for		 *	their exit status, and throw that exit status		 *	away.  This helps get rid of zxombie children.		 */		while (waitpid(-1, &argval, WNOHANG) > 0) {			/* do nothing */		}#endif		/*		 *	Loop over the open socket FD's, reading any data.		 */		for (listener = mainconfig.listen;		     listener != NULL;		     listener = listener->next) {			RAD_REQUEST_FUNP fun;			if (!FD_ISSET(listener->fd, &readfds))				continue;			/*			 *  Receive the packet.			 */			if (sig_hup_block != FALSE) {			  continue;			}			packet = rad_recv(listener->fd);			if (packet == NULL) {				radlog(L_ERR, "%s", librad_errstr);				continue;			}			/*			 *	If the destination IP is unknown, check			 *	if the listener has a known IP.  If so,			 *	use that.			 */			if ((packet->dst_ipaddr == htonl(INADDR_ANY)) &&			    (packet->dst_ipaddr != listener->ipaddr)) {				packet->dst_ipaddr = listener->ipaddr;			}			/*			 *	Fill in the destination port.			 */			packet->dst_port = listener->port;			RAD_SNMP_TYPE_INC(listener, total_requests);			/*			 *	FIXME: Move this next check into			 *	the packet_ok() function, and add			 *	a 'secret' to the RAIDUS_PACKET			 *	data structure.  This involves changing			 *	a bunch of code, but it's probably the			 *	best thing to do.			 */			/*			 *  Check if we know this client for			 *  authentication and accounting.  Check if we know			 *  this proxy for proxying.			 */			if (listener->type != RAD_LISTEN_PROXY) {				RADCLIENT *cl;				if ((cl = client_find(packet->src_ipaddr)) == NULL) {					RAD_SNMP_TYPE_INC(listener, total_invalid_requests);					radlog(L_ERR, "Ignoring request from unknown client %s:%d",					ip_ntoa((char *)buffer, packet->src_ipaddr),					packet->src_port);					rad_free(&packet);					continue;				}				secret = cl->secret;			} else {    /* It came in on the proxy port */				REALM *rl;				if ((rl = realm_findbyaddr(packet->src_ipaddr,packet->src_port)) == NULL) {					radlog(L_ERR, "Ignoring request from unknown home server %s:%d",					ip_ntoa((char *)buffer, packet->src_ipaddr),					packet->src_port);					rad_free(&packet);					continue;				}				/*				 *	The secret isn't needed here,				 *	as it's already in the old request				 */				secret = NULL;			}			/*			 *	Do some simple checks before we process			 *	the request.			 */			if ((fun = packet_ok(packet, listener)) == NULL) {				rad_free(&packet);				continue;			}						/*			 *	Allocate a new request for packets from			 *	our clients, OR find the old request,			 *	for packets which are replies from a home			 *	server.			 */			request = request_ok(packet, secret, listener);			if (!request) {				rad_free(&packet);				continue;			}			/*			 *	Drop the request into the thread pool,			 *	and let the thread pool take care of			 *	doing something with it.			 */#ifdef HAVE_PTHREAD_H			if (spawn_flag) {				if (!thread_pool_addrequest(request, fun)) {					/*					 *	FIXME: Maybe just drop					 *	the packet on the floor?					 */					request_reject(request);					request->finished = TRUE;				}			} else#endif				rad_respond(request, fun);		} /* loop over listening sockets*/#ifdef WITH_SNMP		if (mainconfig.do_snmp) {			/*			 *  After handling all authentication/accounting			 *  requests, THEN process any pending SMUX/SNMP			 *  queries.			 *			 *  Note that the handling is done in the main server,			 *  which probably isn't a Good Thing.  It really			 *  should be wrapped, and handled in a thread pool.			 */			if ((rad_snmp.smux_fd >= 0) &&			    FD_ISSET(rad_snmp.smux_fd, &readfds) &&			    (rad_snmp.smux_event == SMUX_READ)) {				smux_read();			}			/*			 *  If we've got to re-connect, then do so now,			 *  before calling select again.			 */			if (rad_snmp.smux_event == SMUX_CONNECT) {				smux_connect();			}		}#endif		/*		 *  After processing all new requests,		 *  check if we've got to delete old requests		 *  from the request list.		 */		tv = rl_clean_list(time_now);#ifdef HAVE_PTHREAD_H		/*		 *	Only clean the thread pool if we're spawning		 *	child threads. 		 */		if (spawn_flag) {			thread_pool_clean(time_now);		}#endif	} /* loop forever */}/* * FIXME:  The next two functions should all * be in a module.  But not until we have * more control over module execution. * -jcarneal *//* *  Lowercase the string value of a pair. */static int rad_lowerpair(REQUEST *request UNUSED, VALUE_PAIR *vp) {	if (vp == NULL) {		return -1;	}	rad_lowercase((char *)vp->strvalue);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -