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

📄 event.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 *	We had previously received a reply, so we don't need	 *	to do anything here.	 */	if (request->proxy_reply) {		if (memcmp(request->proxy_reply->vector,			   packet->vector,			   sizeof(request->proxy_reply->vector)) == 0) {			DEBUG2("Discarding duplicate reply from home server %s port %d  - ID: %d for request %d",			       inet_ntop(packet->src_ipaddr.af,					 &packet->src_ipaddr.ipaddr,					 buffer, sizeof(buffer)),			       packet->src_port, packet->id,			       request->number);		} else {			/*			 *	? The home server gave us a new proxy			 *	reply, which doesn't match the old			 *	one.  Delete it.			 */			DEBUG2("Ignoring conflicting proxy reply");		}		/* assert that there's an event queued for request? */		rad_free(&packet);		return NULL;	}	switch (request->child_state) {	case REQUEST_QUEUED:	case REQUEST_RUNNING:		rad_panic("Internal sanity check failed for child state");		break;	case REQUEST_REJECT_DELAY:	case REQUEST_CLEANUP_DELAY:	case REQUEST_DONE:		radlog(L_ERR, "Reply from home server %s port %d  - ID: %d arrived too late for request %d. Try increasing 'retry_delay' or 'max_request_time'",		       inet_ntop(packet->src_ipaddr.af,				 &packet->src_ipaddr.ipaddr,				 buffer, sizeof(buffer)),		       packet->src_port, packet->id,		       request->number);		/* assert that there's an event queued for request? */		rad_free(&packet);		return NULL;	case REQUEST_PROXIED:		break;	}	request->proxy_reply = packet;#if 0	/*	 *	Perform RTT calculations, as per RFC 2988 (for TCP).	 *	Note that we do so only if we sent one request, and	 *	received one response.  If we sent two requests, we	 *	have no idea if the response is for the first, or for	 *	the second request/	 */	if (request->num_proxied_requests == 1) {		int rtt;		home_server *home = request->home_server;		rtt = now.tv_sec - request->proxy_when.tv_sec;		rtt *= USEC;		rtt += now.tv_usec;		rtt -= request->proxy_when.tv_usec;		if (!home->has_rtt) {			home->has_rtt = TRUE;			home->srtt = rtt;			home->rttvar = rtt / 2;		} else {			home->rttvar -= home->rttvar >> 2;			home->rttvar += (home->srtt - rtt);			home->srtt -= home->srtt >> 3;			home->srtt += rtt >> 3;		}		home->rto = home->srtt;		if (home->rttvar > (USEC / 4)) {			home->rto += home->rttvar * 4;		} else {			home->rto += USEC;		}	}#endif	/*	 *	There's no incoming request, so it's a proxied packet	 *	we originated.	 */	if (!request->packet) {		received_response_to_ping(request);		return NULL;	}	request->child_state = REQUEST_QUEUED;	request->when = now;	request->delay = USEC;	request->priority = RAD_LISTEN_PROXY;	tv_add(&request->when, request->delay);	/*	 *	Wait a bit will take care of max_request_time	 */	INSERT_EVENT(wait_a_bit, request);	return request;}static void event_detail_timer(void *ctx){	rad_listen_t *listener = ctx;	RAD_REQUEST_FUNP fun;	REQUEST *request;	if (listener->recv(listener, &fun, &request)) {		if (!thread_pool_addrequest(request, fun)) {			request->child_state = REQUEST_DONE;		}	}}static void handle_signal_self(int flag){	if ((flag & (RADIUS_SIGNAL_SELF_EXIT | RADIUS_SIGNAL_SELF_TERM)) != 0) {		if ((flag & RADIUS_SIGNAL_SELF_EXIT) != 0) {			fr_event_loop_exit(el, 1);		} else {			fr_event_loop_exit(el, 2);		}		return;	} /* else exit/term flags weren't set */	/*	 *	Tell the even loop to stop processing.	 */	if ((flag & RADIUS_SIGNAL_SELF_HUP) != 0) {		time_t when;		static time_t last_hup = 0;		DEBUG("Received HUP signal.");		when = time(NULL);		if ((int) (when - last_hup) < 5) {			radlog(L_INFO, "Ignoring HUP (less than 5s since last one)");			return;		}		last_hup = when;		fr_event_loop_exit(el, 0x80);	}	if ((flag & RADIUS_SIGNAL_SELF_DETAIL) != 0) {		rad_listen_t *this;				for (this = mainconfig.listen;		     this != NULL;		     this = this->next) {			int delay;			struct timeval when;			if (this->type != RAD_LISTEN_DETAIL) continue;						delay = detail_delay(this);			if (!delay) continue;			fr_event_now(el, &now);			when = now;			tv_add(&when, delay);			if (delay > 100000) {				DEBUG2("Delaying next detail event for %d.%01u seconds.",				       delay / USEC, (delay % USEC) / 100000);			}			if (!fr_event_insert(el, event_detail_timer, this,					     &when, NULL)) {				radlog(L_ERR, "Failed remembering timer");				exit(1);			}		}	}	if ((flag & RADIUS_SIGNAL_SELF_NEW_FD) != 0) {		rad_listen_t *this;				for (this = mainconfig.listen;		     this != NULL;		     this = this->next) {			if (this->type != RAD_LISTEN_PROXY) continue;						if (!fr_event_fd_insert(el, 0, this->fd,						event_socket_handler, this)) {				radlog(L_ERR, "Failed remembering handle for proxy socket!");				exit(1);			}		}	}}#ifdef __MINGW32__void radius_signal_self(int flag){	handle_signal_self(flag);}#else/* *	Inform ourselves that we received a signal. */void radius_signal_self(int flag){	ssize_t rcode;	uint8_t buffer[16];	/*	 *	The read MUST be non-blocking for this to work.	 */	rcode = read(self_pipe[0], buffer, sizeof(buffer));	if (rcode > 0) {		ssize_t i;		for (i = 0; i < rcode; i++) {			buffer[0] |= buffer[i];		}	} else {		buffer[0] = 0;	}	buffer[0] |= flag;	write(self_pipe[1], buffer, 1);}static void event_signal_handler(UNUSED fr_event_list_t *xel,				 UNUSED int fd, UNUSED void *ctx){	ssize_t i, rcode;	uint8_t buffer[32];	rcode = read(self_pipe[0], buffer, sizeof(buffer));	if (rcode <= 0) return;	/*	 *	Merge pending signals.	 */	for (i = 0; i < rcode; i++) {		buffer[0] |= buffer[i];	}	handle_signal_self(buffer[0]);}#endifstatic void event_socket_handler(fr_event_list_t *xel, UNUSED int fd,				 void *ctx){	rad_listen_t *listener = ctx;	RAD_REQUEST_FUNP fun;	REQUEST *request;	rad_assert(xel == el);	xel = xel;	if (listener->fd < 0) rad_panic("Socket was closed on us!");		if (!listener->recv(listener, &fun, &request)) return;	if (!thread_pool_addrequest(request, fun)) {		request->child_state = REQUEST_DONE;	}}/* *	This function is called periodically to see if any FD's are *	available for reading. */static void event_poll_fds(UNUSED void *ctx){	int rcode;	RAD_REQUEST_FUNP fun;	REQUEST *request;	rad_listen_t *this;	struct timeval when;	fr_event_now(el, &now);	when = now;	when.tv_sec += 1;	for (this = mainconfig.listen; this != NULL; this = this->next) {		if (this->fd >= 0) continue;		/*		 *	Try to read something.		 *		 *	FIXME: This does poll AND receive.		 */		rcode = this->recv(this, &fun, &request);		if (!rcode) continue;				rad_assert(fun != NULL);		rad_assert(request != NULL);					if (!thread_pool_addrequest(request, fun)) {			request->child_state = REQUEST_DONE;		}		/*		 *	We have an FD.  Start watching it.		 */		if (this->fd >= 0) {			/*			 *	... unless it's a detail file.  In			 *	that case, we rely on the signal to			 *	self to know when to continue			 *	processing the detail file.			 */			if (this->type == RAD_LISTEN_DETAIL) continue;			/*			 *	FIXME: this should be SNMP handler,			 *	and we should do SOMETHING when the			 *	fd is closed!			 */			if (!fr_event_fd_insert(el, 0, this->fd,						event_socket_handler, this)) {				char buffer[256];								this->print(this, buffer, sizeof(buffer));				rad_panic("Failed creating handler for snmp");			}		}	}	/*	 *	Reset the poll.	 */	if (!fr_event_insert(el, event_poll_fds, NULL,			     &when, NULL)) {		radlog(L_ERR, "Failed creating handler");		exit(1);	}}static void event_status(struct timeval *wake){#if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)	int argval;#endif	if (debug_flag == 0) {		if (just_started) {			radlog(L_INFO, "Ready to process requests.");			just_started = FALSE;		}		return;	}	if (!wake) {		DEBUG("Ready to process requests.");	} else if ((wake->tv_sec != 0) ||		   (wake->tv_usec >= 100000)) {		DEBUG("Waking up in %d.%01u seconds.",		      (int) wake->tv_sec, (unsigned int) wake->tv_usec / 100000);	}	/*	 *	FIXME: Put this somewhere else, where it isn't called	 *	all of the time...	 */#if !defined(HAVE_PTHREAD_H) && defined(WNOHANG)	/*	 *	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}/* *	Externally-visibly functions. */int radius_event_init(CONF_SECTION *cs, int spawn_flag){	int i;	int has_snmp_listener = FALSE;	rad_listen_t *this, *head = NULL;	if (el) return 0;	time(&start_time);	el = fr_event_list_create(event_status);	if (!el) return 0;	pl = fr_packet_list_create(0);	if (!el) return 0;	request_num_counter = 0;	/*	 *	Move all of the thread calls to this file?	 *	 *	It may be best for the mutexes to be in this file...	 */	have_children = spawn_flag;	if (mainconfig.proxy_requests) {		/*		 *	Create the tree for managing proxied requests and		 *	responses.		 */		proxy_list = fr_packet_list_create(1);		if (!proxy_list) return 0;#ifdef HAVE_PTHREAD_H		if (pthread_mutex_init(&proxy_mutex, NULL) != 0) {			radlog(L_ERR, "FATAL: Failed to initialize proxy mutex: %s",			       strerror(errno));			exit(1);		}#endif	}	/*	 *	Just before we spawn the child threads, force the log	 *	subsystem to re-open the log file for every write.	 */	if (spawn_flag) force_log_reopen();#ifdef HAVE_PTHREAD_H	if (thread_pool_init(cs, spawn_flag) < 0) {		exit(1);	}#endif	if (check_config) {		DEBUG2("%s: #### Skipping IP addresses and Ports ####",		       mainconfig.name);		return 1;	}#ifndef __MINGW32__	/*	 *	Child threads need a pipe to signal us, as do the	 *	signal handlers.	 */	if (pipe(self_pipe) < 0) {		radlog(L_ERR, "radiusd: Error opening internal pipe: %s",		       strerror(errno));		exit(1);	}	if (fcntl(self_pipe[0], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {		radlog(L_ERR, "radiusd: Error setting internal flags: %s",		       strerror(errno));		exit(1);	}	if (fcntl(self_pipe[1], F_SETFL, O_NONBLOCK | FD_CLOEXEC) < 0) {		radlog(L_ERR, "radiusd: Error setting internal flags: %s",		       strerror(errno));		exit(1);	}	if (!fr_event_fd_insert(el, 0, self_pipe[0],				  event_signal_handler, el)) {		radlog(L_ERR, "Failed creating handler for signals");		exit(1);	}#endif	/*	 *	Mark the proxy Fd's as unused.	 */	for (i = 0; i < 32; i++) proxy_fds[i] = -1;	DEBUG2("%s: #### Opening IP addresses and Ports ####",	       mainconfig.name);	if (listen_init(cs, &head) < 0) {		_exit(1);	}		/*	 *	Add all of the sockets to the event loop.	 */	for (this = head;	     this != NULL;	     this = this->next) {		char buffer[256];		this->print(this, buffer, sizeof(buffer));		switch (this->type) {		case RAD_LISTEN_DETAIL:			DEBUG("Listening on %s", buffer);			has_detail_listener = TRUE;			break;		case 

⌨️ 快捷键说明

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