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

📄 request_list.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
void rl_add(REQUEST *request){	int id = request->packet->id;	REQNODE *node;	rad_assert(request->container == NULL);	request->container = rad_malloc(sizeof(REQNODE));	node = (REQNODE *) request->container;	node->req = request;	node->prev = NULL;	node->next = NULL;	if (!request_list[id].first_request) {		rad_assert(request_list[id].request_count == 0);		request_list[id].first_request = node;		request_list[id].last_request = node;	} else {		rad_assert(request_list[id].request_count != 0);		node->prev = request_list[id].last_request;		request_list[id].last_request->next = node;		request_list[id].last_request = node;	}	/*	 *	Insert the request into the tree.	 */	if (rbtree_insert(request_tree, request) == 0) {		rad_assert("FAIL" == NULL);	}	request_list[id].request_count++;}/* *	Look up a particular request, using: * *	Request ID, request code, source IP, source port, * *	Note that we do NOT use the request vector to look up requests. * *	We MUST NOT have two requests with identical (id/code/IP/port), and *	different vectors.  This is a serious error! */REQUEST *rl_find(RADIUS_PACKET *packet){	REQUEST myrequest;	myrequest.packet = packet;	return rbtree_finddata(request_tree, &myrequest);}/* *	See mainconfig.c */extern int proxy_new_listener(void);/* *	Add an entry to the proxy tree. * *	This is the ONLY function in this source file which may be called *	from a child thread.  It therefore needs mutexes... */int rl_add_proxy(REQUEST *request){	int		i, found, proxy;	uint32_t	mask;	proxy_id_t	myid, *entry;	myid.dst_ipaddr = request->proxy->dst_ipaddr;	myid.dst_port = request->proxy->dst_port;	/*	 *	Proxied requests get sent out the proxy FD ONLY.	 *	 *	FIXME: Once we allocate multiple proxy FD's, move this	 *	code to below, so we can have more than 256 requests	 *	outstanding.	 */	request->proxy_outstanding = 1;	pthread_mutex_lock(&proxy_mutex);	/*	 *	Assign a proxy ID.	 */	entry = rbtree_finddata(proxy_id_tree, &myid);	if (!entry) {	/* allocate it */		entry = rad_malloc(sizeof(*entry) + sizeof(entry->id) * 255);				entry->dst_ipaddr = request->proxy->dst_ipaddr;		entry->dst_port = request->proxy->dst_port;		entry->index = 0;		DEBUG3(" proxy: creating %08x:%d",		       entry->dst_ipaddr,		       entry->dst_port);				/*		 *	Insert the new home server entry into		 *	the tree.		 *		 *	FIXME: We don't (currently) delete the		 *	entries, so this is technically a		 *	memory leak.		 */		if (rbtree_insert(proxy_id_tree, entry) == 0) {			DEBUG2("ERROR: Failed to insert entry into proxy Id tree");			free(entry);			return 0;		}		/*		 *	Clear out bits in the array which DO have		 *	proxy Fd's associated with them.  We do this		 *	by getting the mask of bits which have proxy		 *	fd's...  */		mask = 0;		for (i = 0; i < 32; i++) {			if (proxy_fds[i] != -1) {				mask |= (1 << i);			}		}		rad_assert(mask != 0);		/*		 *	Set bits here indicate that the Fd is in use.		 */		entry->mask = mask;		mask = ~mask;		/*		 *	Set the bits which are unused (and therefore		 *	allocated).  The clear bits indicate that the Id		 *	for that FD is unused.		 */		for (i = 0; i < 256; i++) {			entry->id[i] = mask;		}	} /* else the entry already existed in the proxy Id tree */	 retry:	/*	 *	Try to find a free Id.	 */	found = -1;	for (i = 0; i < 256; i++) {		/*		 *	Some bits are still zero..		 */		if (entry->id[(i + entry->index) & 0xff] != (uint32_t) ~0) {			found = (i + entry->index) & 0xff;			break;		}		/*		 *	Hmm... do we want to re-use Id's, when we		 *	haven't seen all of the responses?		 */	}		/*	 *	No free Id, try to get a new FD.	 */	if (found < 0) {		/*		 *	First, see if there were FD's recently allocated,		 *	which we don't know about.		 */		mask = 0;		for (i = 0; i < 32; i++) {			if (proxy_fds[i] < 0) continue;			mask |= (1 << i);		}		/*		 *	There ARE more FD's than we know about.		 *	Update the masks for Id's, and re-try.		 */		if (entry->mask != mask) {			/*			 *	New mask always has more bits than			 *	the old one, but never fewer bits.			 */			rad_assert((entry->mask & mask) == entry->mask);			/*			 *	Clear the bits we already know about,			 *	and then or in those bits into the			 *	global mask.			 */			mask ^= entry->mask;			entry->mask |= mask;			mask = ~mask;						/*			 *	Clear the bits in the Id's for the new			 *	FD's.			 */			for (i = 0; i < 256; i++) {				entry->id[i] &= mask;			}						/*			 *	And try again to allocate an Id.			 */			goto retry;		} /* else no new Fd's were allocated. */		/*		 *	If all Fd's are allocated, die.		 */		if (~mask == 0) {			radlog(L_ERR|L_CONS, "ERROR: More than 8000 proxied requests outstanding for home server %08x:%d",			       ntohs(entry->dst_ipaddr), entry->dst_port);			return 0;		}				/*		 *	Allocate a new proxy Fd.  This function adds it		 *	into the list of listeners.		 */		proxy = proxy_new_listener();		if (proxy < 0) {			DEBUG2("ERROR: Failed to create a new socket for proxying requests.");			return 0;		}		/*		 *		 */		found = -1;		for (i = 0; i < 32; i++) {			/*			 *	Found a free entry.  Save the socket,			 *	and remember where we saved it.			 */			if (proxy_fds[(proxy + i) & 0x1f] == -1) {				proxy_fds[(proxy + i) & 0x1f] = proxy;				found = (proxy + i) & 0x1f;				break;			}		}		rad_assert(found >= 0);	/* i.e. the mask had free bits. */		mask = 1 << found;		entry->mask |= mask;		mask = ~mask;		/*		 *	Clear the relevant bits in the mask.		 */		for (i = 0; i < 256; i++) {			entry->id[i] &= mask;		}		/*		 *	Pick a random Id to start from, as we've		 *	just guaranteed that it's free.		 */		found = lrad_rand() & 0xff;	}		/*	 *	Mark next (hopefully unused) entry.	 */	entry->index = (found + 1) & 0xff;		/*	 *	We now have to find WHICH proxy fd to use.	 */	proxy = -1;	for (i = 0; i < 32; i++) {		/*		 *	FIXME: pick a random socket to use?		 */		if ((entry->id[found] & (1 << i)) == 0) {			proxy = i;			break;		}	}	/*	 *	There was no bit clear, which we had just checked above...	 */	rad_assert(proxy != -1);	/*	 *	Mark the Id as allocated, for thei Fd.	 */	entry->id[found] |= (1 << proxy);	request->proxy->id = found;	rad_assert(proxy_fds[proxy] != -1);	request->proxy->sockfd = proxy_fds[proxy];	DEBUG3(" proxy: allocating %08x:%d %d",	       entry->dst_ipaddr,	       entry->dst_port,	       request->proxy->id);		if (!rbtree_insert(proxy_tree, request)) {		DEBUG2("ERROR: Failed to insert entry into proxy tree");		return 0;	}		pthread_mutex_unlock(&proxy_mutex);	return 1;}/* *	Look up a particular request, using: * *	Request Id, request code, source IP, source port, * *	Note that we do NOT use the request vector to look up requests. * *	We MUST NOT have two requests with identical (id/code/IP/port), and *	different vectors.  This is a serious error! */REQUEST *rl_find_proxy(RADIUS_PACKET *packet){	rbnode_t	*node;	REQUEST		myrequest, *maybe = NULL;	RADIUS_PACKET	myproxy;	/*	 *	If we use the socket FD as an indicator,	 *	then that implicitely contains information	 *	as to our src ipaddr/port, so we don't need	 *	to use that in the comparisons.	 */	myproxy.sockfd = packet->sockfd;	myproxy.id = packet->id;	myproxy.dst_ipaddr = packet->src_ipaddr;	myproxy.dst_port = packet->src_port;#ifndef NDEBUG	myrequest.magic = REQUEST_MAGIC;#endif	myrequest.proxy = &myproxy;	pthread_mutex_lock(&proxy_mutex);        node = rbtree_find(proxy_tree, &myrequest);	if (node) {		maybe = rbtree_node2data(proxy_tree, node);		rad_assert(maybe->proxy_outstanding > 0);		maybe->proxy_outstanding--;				/*		 *	Received all of the replies we expect.		 *	delete it from both trees.		 */		if (maybe->proxy_outstanding == 0) {			rl_delete_proxy(&myrequest, node);		}	}	pthread_mutex_unlock(&proxy_mutex);	return maybe;}/* *	Walk over all requests, performing a callback for each request. */int rl_walk(RL_WALK_FUNC walker, void *data){	int id, rcode;	REQNODE *curreq, *next;	/*	 *	Walk over all 256 ID's.	 */	for (id = 0; id < 256; id++) {		/*		 *	Walk over the request list for each ID.		 */		for (curreq = request_list[id].first_request;				curreq != NULL ;				curreq = next) {			/*			 *	The callback MIGHT delete the current			 *	request, so we CANNOT depend on curreq->next			 *	to be there, when going to the next element			 *	in the 'for' loop.			 */			next = curreq->next;			rcode = walker(curreq->req, data);			if (rcode != RL_WALK_CONTINUE) {				return rcode;			}		}	}	return 0;}/* *	Walk from one request to the next. */REQUEST *rl_next(REQUEST *request){	int id, start_id;	int count;	/*	 *	If we were passed a request, then go to the "next" one.	 */	if (request != NULL) {		rad_assert(request->magic == REQUEST_MAGIC);		/*		 *	It has a "next", return it.		 */		if (((REQNODE *)request->container)->next != NULL) {			return ((REQNODE *)request->container)->next->req;		} else {			/*			 *	No "next", increment the ID, and look			 *	at that one.			 */			start_id = request->packet->id + 1;			start_id &= 0xff;			count = 255;		}	} else {		/*		 *	No input request, start looking at ID 0.		 */		start_id = 0;		count = 256;	}	/*	 *	Check all ID's, wrapping around at 255.	 */	for (id = start_id; id < (start_id + count); id++) {		/*		 *	This ID has a request, return it.		 */		if (request_list[id & 0xff].first_request != NULL) {			rad_assert(request_list[id&0xff].first_request->req != request);			return request_list[id & 0xff].first_request->req;		}	}	/*	 *	No requests at all in the list. Nothing to do.	 */	DEBUG3("rl_next:  returning NULL");	return NULL;}/* *	Return the number of requests in the request list. */int rl_num_requests(void){	int id;	int request_count = 0;	for (id = 0; id < 256; id++) {		request_count += request_list[id].request_count;	}	return request_count;}typedef struct rl_walk_t {	time_t	now;	time_t	smallest;} rl_walk_t;/* *  Refresh a request, by using proxy_retry_delay, cleanup_delay, *  max_request_time, etc. *

⌨️ 快捷键说明

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