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

📄 event.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		if (request->reply->code == PW_AUTHENTICATION_REJECT) {			pairdelete(&request->config_items, PW_POST_AUTH_TYPE);			vp = radius_pairmake(request, &request->config_items,					     "Post-Auth-Type", "Reject",					     T_OP_SET);			if (vp) rad_postauth(request);			/*			 *	If configured, delay Access-Reject packets.			 *			 *	If request->root->reject_delay = 0, we discover			 *	that we have to send the packet now.			 */			when = request->received;			when.tv_sec += request->root->reject_delay;			if (timercmp(&when, &request->next_when, >)) {				DEBUG2("Delaying reject of request %d for %d seconds",				       request->number,				       request->root->reject_delay);				request->next_when = when;				request->next_callback = reject_delay;				request->child_pid = NO_SUCH_CHILD_PID;				request->child_state = REQUEST_REJECT_DELAY;				return;			}		}		request->next_when.tv_sec += request->root->cleanup_delay;		request->next_callback = cleanup_delay;		child_state = REQUEST_CLEANUP_DELAY;		break;	case PW_ACCOUNTING_REQUEST:		request->next_callback = NULL; /* just to be safe */		child_state = REQUEST_DONE;		break;		/*		 *	FIXME: Status-Server should probably not be		 *	handled here...		 */	case PW_STATUS_SERVER:		request->next_callback = NULL;		child_state = REQUEST_DONE;		break;	default:		if ((request->packet->code > 1024) &&		    (request->packet->code < (1024 + 254 + 1))) {			request->next_callback = NULL;			child_state = REQUEST_DONE;			break;		}		radlog(L_ERR, "Unknown packet type %d", request->packet->code);		rad_panic("Unknown packet type");		break;	}	/*	 *      Suppress "no reply" packets here, unless we're reading	 *      from the "detail" file.  In that case, we've got to	 *      tell the detail file handler that the request is dead,	 *      and it should re-send it.	 *	If configured, encode, sign, and send.	 */	if ((request->reply->code != 0) ||	    (request->listener->type == RAD_LISTEN_DETAIL)) {		request->listener->send(request->listener, request);	}	/*	 *	Clean up.  These are no longer needed.	 */	pairfree(&request->config_items);	pairfree(&request->packet->vps);	request->username = NULL;	request->password = NULL;	pairfree(&request->reply->vps);	if (request->proxy) {		pairfree(&request->proxy->vps);		if (request->proxy_reply) {			pairfree(&request->proxy_reply->vps);		}		/*		 *	We're not tracking responses from the home		 *	server, we can therefore free this memory in		 *	the child thread.		 */		if (!request->in_proxy_hash) {			rad_free(&request->proxy);			rad_free(&request->proxy_reply);			request->home_server = NULL;		}	}	DEBUG2("Finished request %d.", request->number);	request->child_state = child_state;	/*	 *	Single threaded mode: update timers now.	 */	if (!have_children) wait_a_bit(request);}static void received_retransmit(REQUEST *request, const RADCLIENT *client){	char buffer[128];	RAD_SNMP_TYPE_INC(request->listener, total_dup_requests);	RAD_SNMP_CLIENT_INC(request->listener, client, dup_requests);	switch (request->child_state) {	case REQUEST_QUEUED:	case REQUEST_RUNNING:	discard:		radlog(L_ERR, "Discarding duplicate request from "		       "client %s port %d - ID: %d due to unfinished request %d",		       client->shortname,		       request->packet->src_port,request->packet->id,		       request->number);		break;	case REQUEST_PROXIED:		/*		 *	We're not supposed to have duplicate		 *	accounting packets.  The other states handle		 *	duplicates fine (discard, or send duplicate		 *	reply).  But we do NOT want to retransmit an		 *	accounting request here, because that would		 *	involve updating the Acct-Delay-Time, and		 *	therefore changing the packet Id, etc.		 *		 *	Instead, we just discard the packet.  We may		 *	eventually respond, or the client will send a		 *	new accounting packet.		 */		if (request->packet->code == PW_ACCOUNTING_REQUEST) {			goto discard;		}		check_for_zombie_home_server(request);		/*		 *	If we've just discovered that the home server is		 *	dead, send the packet to another one.		 */		if ((request->packet->dst_port != 0) &&		    (request->home_server->state == HOME_STATE_IS_DEAD)) {			home_server *home;			remove_from_proxy_hash(request);			home = home_server_ldb(NULL, request->home_pool, request);			if (!home) {				DEBUG2("Failed to find live home server for request %d", request->number);			no_home_servers:				/*				 *	Do post-request processing,				 *	and any insertion of necessary				 *	events.				 */				post_proxy_fail_handler(request);				return;			}			request->proxy->code = request->packet->code;			request->proxy->dst_ipaddr = home->ipaddr;			request->proxy->dst_port = home->port;			request->home_server = home;			/*			 *	Free the old packet, to force re-encoding			 */			free(request->proxy->data);			request->proxy->data = NULL;			request->proxy->data_len = 0;			/*			 *	Try to proxy the request.			 */			if (!proxy_request(request)) {				DEBUG("ERROR: Failed to re-proxy request %d", request->number);				goto no_home_servers;			}			/*			 *	This code executes in the main server			 *	thread, so there's no need for locking.			 */			rad_assert(request->next_callback != NULL);			INSERT_EVENT(request->next_callback, request);			request->next_callback = NULL;			return;		} /* else the home server is still alive */		DEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",		       inet_ntop(request->proxy->dst_ipaddr.af,				 &request->proxy->dst_ipaddr.ipaddr,				 buffer, sizeof(buffer)),		       request->proxy->dst_port,		       request->proxy->id);		request->num_proxied_requests++;		request->proxy_listener->send(request->proxy_listener,					      request);		break;	case REQUEST_REJECT_DELAY:		DEBUG2("Waiting to send Access-Reject "		       "to client %s port %d - ID: %d",		       client->shortname,		       request->packet->src_port, request->packet->id);		break;	case REQUEST_CLEANUP_DELAY:	case REQUEST_DONE:		DEBUG2("Sending duplicate reply "		       "to client %s port %d - ID: %d",		       client->shortname,		       request->packet->src_port, request->packet->id);		request->listener->send(request->listener, request);		break;	}}static void received_conflicting_request(REQUEST *request,					 const RADCLIENT *client){	radlog(L_ERR, "Received conflicting packet from "	       "client %s port %d - ID: %d due to unfinished request %d.  Giving up on old request.",	       client->shortname,	       request->packet->src_port, request->packet->id,	       request->number);	/*	 *	Nuke it from the request hash, so we can receive new	 *	packets.	 */	remove_from_request_hash(request);	switch (request->child_state) {		/*		 *	It's queued or running.  Tell it to stop, and		 *	wait for it to do so.		 */	case REQUEST_QUEUED:	case REQUEST_RUNNING:		request->master_state = REQUEST_STOP_PROCESSING;		request->delay += request->delay >> 1;		tv_add(&request->when, request->delay);		INSERT_EVENT(wait_for_child_to_die, request);		return;		/*		 *	It's in some other state, and therefore also		 *	in the event queue.  At some point, the		 *	child will notice, and we can then delete it.		 */	default:		rad_assert(request->ev != NULL);		break;	}}static int can_handle_new_request(RADIUS_PACKET *packet,				  RADCLIENT *client,				  struct main_config_t *root){	/*	 *	Count the total number of requests, to see if	 *	there are too many.  If so, return with an	 *	error.	 */	if (root->max_requests) {		int request_count = fr_packet_list_num_elements(pl);		/*		 *	This is a new request.  Let's see if		 *	it makes us go over our configured		 *	bounds.		 */		if (request_count > root->max_requests) {			radlog(L_ERR, "Dropping request (%d is too many): "			       "from client %s port %d - ID: %d", request_count,			       client->shortname,			       packet->src_port, packet->id);			radlog(L_INFO, "WARNING: Please check the configuration file.\n"			       "\tThe value for 'max_requests' is probably set too low.\n");			return 0;		} /* else there were a small number of requests */	} /* else there was no configured limit for requests */	/*	 *	FIXME: Add per-client checks.  If one client is sending	 *	too many packets, start discarding them.	 *	 *	We increment the counters here, and decrement them	 *	when the response is sent... somewhere in this file.	 */	/*	 *	FUTURE: Add checks for system load.  If the system is	 *	busy, start dropping requests...	 *	 *	We can probably keep some statistics ourselves...  if	 *	there are more requests coming in than we can handle,	 *	start dropping some.	 */	return 1;}int received_request(rad_listen_t *listener,		     RADIUS_PACKET *packet, REQUEST **prequest,		     RADCLIENT *client){	RADIUS_PACKET **packet_p;	REQUEST *request = NULL;	struct main_config_t *root = &mainconfig;	packet_p = fr_packet_list_find(pl, packet);	if (packet_p) {		request = fr_packet2myptr(REQUEST, packet, packet_p);		rad_assert(request->in_request_hash);		if ((request->packet->data_len == packet->data_len) &&		    (memcmp(request->packet->vector, packet->vector,			    sizeof(packet->vector)) == 0)) {			received_retransmit(request, client);			return 0;		}		/*		 *	The new request is different from the old one,		 *	but maybe the old is finished.  If so, delete		 *	the old one.		 */		switch (request->child_state) {			struct timeval when;		default:			gettimeofday(&when, NULL);			when.tv_sec -= 1;			/*			 *	If the cached request was received			 *	within the last second, then we			 *	discard the NEW request instead of the			 *	old one.  This will happen ONLY when			 *	the client is severely broken, and is			 *	sending conflicting packets very			 *	quickly.			 */			if (timercmp(&when, &request->received, <)) {				radlog(L_ERR, "Discarding conflicting packet from "				       "client %s port %d - ID: %d due to recent request %d.",				       client->shortname,				       packet->src_port, packet->id,				       request->number);				return 0;			}			received_conflicting_request(request, client);			request = NULL;			break;		case REQUEST_REJECT_DELAY:		case REQUEST_CLEANUP_DELAY:			request->child_state = REQUEST_DONE;		case REQUEST_DONE:			cleanup_delay(request);			request = NULL;			break;		}	}	/*	 *	We may want to quench the new request.	 */	if ((listener->type != RAD_LISTEN_DETAIL) &&	    !can_handle_new_request(packet, client, root)) {		return 0;	}	/*	 *	Create and initialize the new request.	 */	request = request_alloc(); /* never fails */	if ((request->reply = rad_alloc(0)) == NULL) {		radlog(L_ERR, "No memory");		exit(1);	}	request->listener = listener;	request->client = client;	request->packet = packet;	request->packet->timestamp = request->timestamp;	request->number = request_num_counter++;	request->priority = listener->type;	/*	 *	Set virtual server identity	 */	if (client->server) {		request->server = client->server;	} else if (listener->server) {		request->server = listener->server;	} else {		request->server = NULL;	}	/*	 *	Remember the request in the list.	 */	if (!fr_packet_list_insert(pl, &request->packet)) {		radlog(L_ERR, "Failed to insert request %d in the list of live requests: discarding", request->number);		request_free(&request);		return 0;	}	request->in_request_hash = TRUE;	request->root = root;	root->refcount++;	/*	 *	The request passes many of our sanity checks.	 *	From here on in, if anything goes wrong, we	 *	send a reject message, instead of dropping the	 *	packet.	 */	/*	 *	Build the reply template from the request.	 */	request->reply->sockfd = request->packet->sockfd;	request->reply->dst_ipaddr = request->packet->src_ipaddr;	request->reply->src_ipaddr = request->packet->dst_ipaddr;	request->reply->dst_port = request->packet->src_port;	request->reply->src_port = request->packet->dst_port;	request->reply->id = request->packet->id;	request->reply->code = 0; /* UNKNOWN code */	memcpy(request->reply->vector, request->packet->vector,	       sizeof(request->reply->vector));	request->reply->vps = NULL;	request->reply->data = NULL;	request->reply->data_len = 0;	request->master_state = REQUEST_ACTIVE;	request->child_state = REQUEST_QUEUED;	request->next_callback = NULL;	gettimeofday(&request->received, NULL);	request->timestamp = request->received.tv_sec;	request->when = request->received;	request->delay = USEC;	tv_add(&request->when, request->delay);	INSERT_EVENT(wait_a_bit, request);	*prequest = request;	return 1;}REQUEST *received_proxy_response(RADIUS_PACKET *packet){	char		buffer[128];	home_server	*home;	REQUEST		*request;	if (!home_server_find(&packet->src_ipaddr, packet->src_port)) {		radlog(L_ERR, "Ignoring request from unknown home server %s port %d",		       inet_ntop(packet->src_ipaddr.af,				 &packet->src_ipaddr.ipaddr,				 buffer, sizeof(buffer)),			       packet->src_port);		rad_free(&packet);		return NULL;	}	/*	 *	Also removes from the proxy hash if responses == requests	 */	request = lookup_in_proxy_hash(packet);	if (!request) {		radlog(L_PROXY, "No outstanding request was found for proxy reply from home server %s port %d - ID %d",		       inet_ntop(packet->src_ipaddr.af,				 &packet->src_ipaddr.ipaddr,				 buffer, sizeof(buffer)),		       packet->src_port, packet->id);		rad_free(&packet);		return NULL;	}	home = request->home_server;	gettimeofday(&now, NULL);	home->state = HOME_STATE_ALIVE;	if (request->reply && request->reply->code != 0) {		DEBUG2("We already replied to this request.  Discarding response from home server.");		rad_free(&packet);		return NULL;	}

⌨️ 快捷键说明

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