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

📄 rlm_ippool.c

📁 RADIUS认证协议
💻 C
📖 第 1 页 / 共 2 页
字号:
		DEBUG("rlm_ippool: Entry not found");	}	return RLM_MODULE_OK;}static int ippool_postauth(void *instance, REQUEST *request){	rlm_ippool_t *data = (rlm_ippool_t *) instance;	unsigned int port = 0;	int delete = 0;	int found = 0;	int mppp = 0;	int extra = 0;	int rcode;	int num = 0;	char nas[MAX_NAS_NAME_SIZE];	datum key_datum;	datum nextkey;	datum data_datum;	datum save_datum;	ippool_key key;	ippool_info entry;	VALUE_PAIR *vp;	char *cli = NULL;	char str[32];	/* quiet the compiler */	instance = instance;	request = request;	/* Check if Pool-Name attribute exists. If it exists check our name and	 * run only if they match	 */	if ((vp = pairfind(request->config_items, PW_POOL_NAME)) != NULL){		if (data->name == NULL || strcmp(data->name,vp->strvalue))			return RLM_MODULE_NOOP;	} else {		DEBUG("rlm_ippool: Could not find Pool-Name attribute.");		return RLM_MODULE_NOOP;	}	/*	 * Get the nas ip address	 * If not fail	 */	if ((vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL)		strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);	else{		if ((vp = pairfind(request->packet->vps, PW_NAS_IDENTIFIER)) != NULL)			strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);		else{			DEBUG("rlm_ippool: Could not find nas information. Return NOOP.");			return RLM_MODULE_NOOP;		}	}	/*	 * Find the caller id	 */	if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)		cli = vp->strvalue;	/*	 * Find the port	 * If not fail	 */	if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)		port = vp->lvalue;	else{		DEBUG("rlm_ippool: Could not find nas port information. Return NOOP.");		return RLM_MODULE_NOOP;	}	memset(key.nas,0,MAX_NAS_NAME_SIZE);	strncpy(key.nas,nas,MAX_NAS_NAME_SIZE -1 );	key.port = port;	DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key.nas,key.port);	key_datum.dptr = (char *) &key;	key_datum.dsize = sizeof(ippool_key);	pthread_mutex_lock(&data->op_mutex);	data_datum = gdbm_fetch(data->gdbm, key_datum);	if (data_datum.dptr != NULL){		/*		 * If there is a corresponding entry in the database with active=1 it is stale.		 * Set active to zero		 */		found = 1;		memcpy(&entry, data_datum.dptr, sizeof(ippool_info));		free(data_datum.dptr);		if (entry.active){			DEBUG("rlm_ippool: Found a stale entry for ip/port: %s/%u",ip_ntoa(str,entry.ipaddr),port);			entry.active = 0;			entry.timestamp = 0;			entry.timeout = 0;			/*			 * Save the reference to the entry			 */			save_datum.dptr = key_datum.dptr;			save_datum.dsize = key_datum.dsize;			data_datum.dptr = (char *) &entry;			data_datum.dsize = sizeof(ippool_info);			rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);			if (rcode < 0) {				radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",					data->session_db, gdbm_strerror(gdbm_errno));				pthread_mutex_unlock(&data->op_mutex);				return RLM_MODULE_FAIL;			}			/* Decrease allocated count from the ip index */			key_datum.dptr = (char *) &entry.ipaddr;			key_datum.dsize = sizeof(uint32_t);			data_datum = gdbm_fetch(data->ip, key_datum);			if (data_datum.dptr != NULL){				memcpy(&num, data_datum.dptr, sizeof(int));				free(data_datum.dptr);				if (num >0){					num--;					DEBUG("rlm_ippool: num: %d",num);					data_datum.dptr = (char *) &num;					data_datum.dsize = sizeof(int);					rcode = gdbm_store(data->ip, key_datum, data_datum, GDBM_REPLACE);					if (rcode < 0) {						radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",								data->ip_index, gdbm_strerror(gdbm_errno));						pthread_mutex_unlock(&data->op_mutex);						return RLM_MODULE_FAIL;					}					if (num >0 && entry.extra == 1){						/*						 * We are doing MPPP and we still have nas/port entries referencing						 * this ip. Delete this entry so that eventually we only keep one						 * reference to this ip.						 */						gdbm_delete(data->gdbm,save_datum);					}				}			}		}	}	pthread_mutex_unlock(&data->op_mutex);	/*	 * If there is a Framed-IP-Address attribute in the reply, check for override	 */	if (pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS) != NULL) {		DEBUG("rlm_ippool: Found Framed-IP-Address attribute in reply attribute list.");		if (data->override)		{			/* Override supplied Framed-IP-Address */			DEBUG("rlm_ippool: override is set to yes. Override the existing Framed-IP-Address attribute.");			pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);		} else {			/* Abort */			DEBUG("rlm_ippool: override is set to no. Return NOOP.");			return RLM_MODULE_NOOP;		}	}	/*	 * Walk through the database searching for an active=0 entry.	 * We search twice. Once to see if we have an active entry with the same callerid	 * so that MPPP can work ok and then once again to find a free entry.	 */	pthread_mutex_lock(&data->op_mutex);	key_datum.dptr = NULL;	if (cli != NULL){		key_datum = gdbm_firstkey(data->gdbm);		while(key_datum.dptr){			data_datum = gdbm_fetch(data->gdbm, key_datum);			if (data_datum.dptr){				memcpy(&entry,data_datum.dptr, sizeof(ippool_info));				free(data_datum.dptr);				/*		 		* If we find an entry for the same caller-id and nas with active=1		 		* then we use that for multilink (MPPP) to work properly.		 		*/				if (strcmp(entry.cli,cli) == 0 && entry.active){					memcpy(&key,key_datum.dptr,sizeof(ippool_key));					if (!strcmp(key.nas,nas)){						mppp = 1;						break;					}				}			}			nextkey = gdbm_nextkey(data->gdbm, key_datum);			free(key_datum.dptr);			key_datum = nextkey;		}	}	if (key_datum.dptr == NULL){		key_datum = gdbm_firstkey(data->gdbm);		while(key_datum.dptr){			data_datum = gdbm_fetch(data->gdbm, key_datum);			if (data_datum.dptr){				memcpy(&entry,data_datum.dptr, sizeof(ippool_info));				free(data_datum.dptr);				/*				 * Find an entry with active == 0				 * or an entry that has expired				 */				if (entry.active == 0 || (entry.timestamp && ((entry.timeout && 				request->timestamp >= (entry.timestamp + entry.timeout)) ||				(data->max_timeout && request->timestamp >= (entry.timestamp + data->max_timeout))))){					datum tmp;					tmp.dptr = (char *) &entry.ipaddr;					tmp.dsize = sizeof(uint32_t);					data_datum = gdbm_fetch(data->ip, tmp);					/*					 * If we find an entry in the ip index and the number is zero (meaning					 * that we haven't allocated the same ip address to another nas/port pair)					 * or if we don't find an entry then delete the session entry so					 * that we can change the key (nas/port)					 * Else we don't delete the session entry since we haven't yet deallocated the					 * corresponding ip address and we continue our search.					 */					if (data_datum.dptr){						memcpy(&num,data_datum.dptr, sizeof(int));						free(data_datum.dptr);						if (num == 0){							delete = 1;							break;						}					}					else{						delete = 1;						break;					}				}			}			nextkey = gdbm_nextkey(data->gdbm, key_datum);			free(key_datum.dptr);			key_datum = nextkey;		}	}	/*	 * If we have found a free entry set active to 1 then add a Framed-IP-Address attribute to	 * the reply	 * We keep the operation mutex locked until after we have set the corresponding entry active	 */	if (key_datum.dptr){		if (found && !mppp){			/*			 * Found == 1 means we have the nas/port combination entry in our database			 * We exchange the ip address between the nas/port entry and the free entry			 * Afterwards we will save the free ip address to the nas/port entry.			 * That is:			 *  ---------------------------------------------			 *  - NAS/PORT Entry  |||| Free Entry  ||| Time			 *  -    IP1                 IP2(Free)    BEFORE			 *  -    IP2(Free)           IP1          AFTER			 *  ---------------------------------------------			 *			 * We only do this if we are NOT doing MPPP			 *			 */			datum key_datum_tmp;			datum data_datum_tmp;			ippool_key key_tmp;			memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);			strncpy(key_tmp.nas,nas,MAX_NAS_NAME_SIZE -1 );			key_tmp.port = port;			DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key_tmp.nas,key_tmp.port);			key_datum_tmp.dptr = (char *) &key_tmp;			key_datum_tmp.dsize = sizeof(ippool_key);			data_datum_tmp = gdbm_fetch(data->gdbm, key_datum_tmp);			if (data_datum_tmp.dptr != NULL){				rcode = gdbm_store(data->gdbm, key_datum, data_datum_tmp, GDBM_REPLACE);				if (rcode < 0) {					radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",						data->session_db, gdbm_strerror(gdbm_errno));						pthread_mutex_unlock(&data->op_mutex);					return RLM_MODULE_FAIL;				}				free(data_datum_tmp.dptr);			}		}		else{			/*			 * We have not found the nas/port combination			 */			if (delete){				/*		 	  	 * Delete the entry so that we can change the key			 	 * All is well. We delete one entry and we add one entry		 	 	 */				gdbm_delete(data->gdbm, key_datum);			}			else{				/*				 * We are doing MPPP. (mppp should be 1)				 * We don't do anything.				 * We will create an extra not needed entry in the database in this case				 * but we don't really care since we always also use the ip_index database				 * when we search for a free entry.				 * We will also delete that entry on the accounting section so that we only				 * have one nas/port entry referencing each ip				 */				if (mppp)					extra = 1;				if (!mppp)					radlog(L_ERR, "rlm_ippool: mppp is not one. Please report this behaviour.");			}		}		free(key_datum.dptr);		entry.active = 1;		entry.timestamp = request->timestamp;		if ((vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL)				entry.timeout = (time_t) vp->lvalue;		else			entry.timeout = 0;		if (extra)			entry.extra = 1;		data_datum.dptr = (char *) &entry;		data_datum.dsize = sizeof(ippool_info);		memset(key.nas,0,MAX_NAS_NAME_SIZE);		strncpy(key.nas,nas,MAX_NAS_NAME_SIZE - 1);		key.port = port;		key_datum.dptr = (char *) &key;		key_datum.dsize = sizeof(ippool_key);		DEBUG2("rlm_ippool: Allocating ip to nas/port: %s/%u",key.nas,key.port);		rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);		if (rcode < 0) {			radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",				data->session_db, gdbm_strerror(gdbm_errno));				pthread_mutex_unlock(&data->op_mutex);			return RLM_MODULE_FAIL;		}		/* Increase the ip index count */		key_datum.dptr = (char *) &entry.ipaddr;		key_datum.dsize = sizeof(uint32_t);		data_datum = gdbm_fetch(data->ip, key_datum);		if (data_datum.dptr){			memcpy(&num,data_datum.dptr,sizeof(int));			free(data_datum.dptr);		} else			num = 0;		num++;		DEBUG("rlm_ippool: num: %d",num);		data_datum.dptr = (char *) &num;		data_datum.dsize = sizeof(int);		rcode = gdbm_store(data->ip, key_datum, data_datum, GDBM_REPLACE);		if (rcode < 0) {			radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",				data->ip_index, gdbm_strerror(gdbm_errno));			pthread_mutex_unlock(&data->op_mutex);			return RLM_MODULE_FAIL;		}		pthread_mutex_unlock(&data->op_mutex);		DEBUG("rlm_ippool: Allocated ip %s to client on nas %s,port %u",ip_ntoa(str,entry.ipaddr),				key.nas,port);		if ((vp = paircreate(PW_FRAMED_IP_ADDRESS, PW_TYPE_IPADDR)) == NULL) {			radlog(L_ERR|L_CONS, "no memory");			return RLM_MODULE_FAIL;		}		vp->lvalue = entry.ipaddr;		ip_ntoa(vp->strvalue, vp->lvalue);		pairadd(&request->reply->vps, vp);		/*		 *	If there is no Framed-Netmask attribute in the		 *	reply, add one		 */		if (pairfind(request->reply->vps, PW_FRAMED_IP_NETMASK) == NULL) {			if ((vp = paircreate(PW_FRAMED_IP_NETMASK, PW_TYPE_IPADDR)) == NULL)				radlog(L_ERR|L_CONS, "no memory");			else {				vp->lvalue = ntohl(data->netmask);				ip_ntoa(vp->strvalue, vp->lvalue);				pairadd(&request->reply->vps, vp);			}		}	}	else{		pthread_mutex_unlock(&data->op_mutex);		DEBUG("rlm_ippool: No available ip addresses in pool.");		return RLM_MODULE_NOTFOUND;	}	return RLM_MODULE_OK;}static int ippool_detach(void *instance){	rlm_ippool_t *data = (rlm_ippool_t *) instance;	gdbm_close(data->gdbm);	gdbm_close(data->ip);	free(data->session_db);	free(data->ip_index);	pthread_mutex_destroy(&data->op_mutex);	free(instance);	return 0;}/* *	The module name should be the only globally exported symbol. *	That is, everything else should be 'static'. * *	If the module needs to temporarily modify it's instantiation *	data, the type should be changed to RLM_TYPE_THREAD_UNSAFE. *	The server will then take care of ensuring that the module *	is single-threaded. */module_t rlm_ippool = {	"IPPOOL",	RLM_TYPE_THREAD_SAFE,		/* type */	NULL,				/* initialization */	ippool_instantiate,		/* instantiation */	{		NULL,			/* authentication */		NULL,		 	/* authorization */		NULL,			/* preaccounting */		ippool_accounting,	/* accounting */		NULL,			/* checksimul */		NULL,			/* pre-proxy */		NULL,			/* post-proxy */		ippool_postauth		/* post-auth */	},	ippool_detach,			/* detach */	NULL,				/* destroy */};

⌨️ 快捷键说明

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