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

📄 rlm_ippool.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * rlm_ippool.c * * Version:  $Id: rlm_ippool.c,v 1.20 2003/06/20 17:50:10 phampson Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2001  The FreeRADIUS server project * Copyright 2002  Kostas Kalevras <kkalev@noc.ntua.gr> *  * March 2002, Kostas Kalevras <kkalev@noc.ntua.gr> * - Initial release * April 2002, Kostas Kalevras <kkalev@noc.ntua.gr> * - Add support for the Pool-Name attribute * May 2002, Kostas Kalevras <kkalev@noc.ntua.gr> * - Check the return value of a gdbm_fetch() we didn't check * - Change the nas entry in the ippool_key structure from uint32 to string[64] *   That should allow us to also use the NAS-Identifier attribute * Sep 2002, Kostas Kalevras <kkalev@noc.ntua.gr> * - Move from authorize to post-auth * - Use mutex locks when accessing the gdbm files * - Fail if we don't find nas port information * Oct 2002, Kostas Kalevras <kkalev@noc.ntua.gr> * - Do a memset(0) on the key.nas before doing searches. Nusty bug */#include "config.h"#include "autoconf.h"#include "libradius.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "radiusd.h"#include "modules.h"#include "conffile.h"#include <gdbm.h>#include <time.h>#include <netinet/in.h>#ifdef NEEDS_GDBM_SYNC#	define GDBM_SYNCOPT GDBM_SYNC#else#	define GDBM_SYNCOPT 0#endif#ifdef GDBM_NOLOCK#define GDBM_IPPOOL_OPTS (GDBM_SYNCOPT | GDBM_NOLOCK)#else#define GDBM_IPPOOL_OPTS (GDBM_SYNCOPT)#endif#define MAX_NAS_NAME_SIZE 64static const char rcsid[] = "$Id: rlm_ippool.c,v 1.20 2003/06/20 17:50:10 phampson Exp $";/* *	Define a structure for our module configuration. * *	These variables do not need to be in a structure, but it's *	a lot cleaner to do so, and a pointer to the structure can *	be used as the instance handle. */typedef struct rlm_ippool_t {	char *session_db;	char *ip_index;	char *name;	uint32_t range_start;	uint32_t range_stop;	uint32_t netmask;	int cache_size;	int override;	GDBM_FILE gdbm;	GDBM_FILE ip;	pthread_mutex_t session_mutex;	pthread_mutex_t ip_mutex;} rlm_ippool_t;typedef struct ippool_info {	uint32_t	ipaddr;	char		active;	char		cli[32];} ippool_info;typedef struct ippool_key {	char nas[MAX_NAS_NAME_SIZE];	unsigned int port;} ippool_key;/* *	A mapping of configuration file names to internal variables. * *	Note that the string is dynamically allocated, so it MUST *	be freed.  When the configuration file parse re-reads the string, *	it free's the old one, and strdup's the new one, placing the pointer *	to the strdup'd string into 'config.string'.  This gets around *	buffer over-flows. */static CONF_PARSER module_config[] = {  { "session-db", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,session_db), NULL, NULL },  { "ip-index", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,ip_index), NULL, NULL },  { "range-start", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,range_start), NULL, "0" },  { "range-stop", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,range_stop), NULL, "0" },  { "netmask", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,netmask), NULL, "0" },  { "cache-size", PW_TYPE_INTEGER, offsetof(rlm_ippool_t,cache_size), NULL, "1000" },  { "override", PW_TYPE_BOOLEAN, offsetof(rlm_ippool_t,override), NULL, "no" },  { NULL, -1, 0, NULL, NULL }};/* *	Do any per-module initialization that is separate to each *	configured instance of the module.  e.g. set up connections *	to external databases, read configuration files, set up *	dictionary entries, etc. * *	If configuration information is given in the config section *	that must be referenced in later calls, store a handle to it *	in *instance otherwise put a null pointer there. */static int ippool_instantiate(CONF_SECTION *conf, void **instance){	rlm_ippool_t *data;	int cache_size;	ippool_info entry;	ippool_key key;	datum key_datum;	datum data_datum;	int i;	unsigned j;	const char *cli = "0";	char *pool_name = NULL;		/*	 *	Set up a storage area for instance data	 */	data = rad_malloc(sizeof(*data));	/*	 *	If the configuration parameters can't be parsed, then	 *	fail.	 */	if (cf_section_parse(conf, data, module_config) < 0) {		free(data);		return -1;	}	cache_size = data->cache_size;	if (data->session_db == NULL) {		radlog(L_ERR, "rlm_ippool: 'session-db' must be set.");		free(data);		return -1;	}	if (data->ip_index == NULL) {		radlog(L_ERR, "rlm_ippool: 'ip-index' must be set.");		free(data);		return -1;	}	data->range_start = htonl(data->range_start);	data->range_stop = htonl(data->range_stop);	data->netmask = htonl(data->netmask);	if (data->range_start == 0 || data->range_stop == 0 || \			 data->range_start >= data->range_stop ) {		radlog(L_ERR, "rlm_ippool: Invalid configuration data given.");		free(data);		return -1;	}		data->gdbm = gdbm_open(data->session_db, sizeof(int),			GDBM_WRCREAT | GDBM_IPPOOL_OPTS, 0600, NULL);	if (data->gdbm == NULL) {		radlog(L_ERR, "rlm_ippool: Failed to open file %s: %s",				data->session_db, strerror(errno));		return -1;	}	data->ip = gdbm_open(data->ip_index, sizeof(int),			GDBM_WRCREAT | GDBM_IPPOOL_OPTS, 0600, NULL);	if (data->ip == NULL) {		radlog(L_ERR, "rlm_ippool: Failed to open file %s: %s",				data->ip_index, strerror(errno));		return -1;	}	if (gdbm_setopt(data->gdbm, GDBM_CACHESIZE, &cache_size, sizeof(int)) == -1)		radlog(L_ERR, "rlm_ippool: Failed to set cache size");	if (gdbm_setopt(data->ip, GDBM_CACHESIZE, &cache_size, sizeof(int)) == -1)		radlog(L_ERR, "rlm_ippool: Failed to set cache size");	key_datum = gdbm_firstkey(data->gdbm);	if (key_datum.dptr == NULL){			/*			 * If the database does not exist initialize it.			 * We set the nas/port pairs to not existent values and			 * active = 0			 */		int rcode;		uint32_t or_result;		char str[32];		const char *nas_init = "NOT_EXIST";		DEBUG("rlm_ippool: Initializing database");		for(i=data->range_start,j=~0;i<=data->range_stop;i++,j--){			/*			 * Net and Broadcast addresses are excluded			 */			or_result = i | data->netmask;			if (~data->netmask != 0 &&				(or_result == data->netmask ||			    (~or_result == 0))) {				DEBUG("rlm_ippool: IP %s excluded",				      ip_ntoa(str, ntohl(i)));				continue;			}						strcpy(key.nas, nas_init);			key.port = j;			key_datum.dptr = (char *) &key;			key_datum.dsize = sizeof(ippool_key);			entry.ipaddr = ntohl(i);			entry.active = 0;			strcpy(entry.cli,cli);			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));				free(data);				gdbm_close(data->gdbm);				gdbm_close(data->ip);				return -1;			}		}	}	else		free(key_datum.dptr);	/* Add the ip pool name */	data->name = NULL;	pool_name = cf_section_name2(conf);	if (pool_name != NULL)		data->name = strdup(pool_name);	pthread_mutex_init(&data->session_mutex, NULL);	pthread_mutex_init(&data->ip_mutex, NULL);	*instance = data;		return 0;}/* *	Check for an Accounting-Stop *	If we find one and we have allocated an IP to this nas/port combination, deallocate it.	 */static int ippool_accounting(void *instance, REQUEST *request){	rlm_ippool_t *data = (rlm_ippool_t *)instance;	datum key_datum;	datum data_datum;	int acctstatustype = 0;	unsigned int port = ~0;	int rcode;	char nas[MAX_NAS_NAME_SIZE];	ippool_info entry;	ippool_key key;	int num = 0;	VALUE_PAIR *vp;	char str[32];	if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL)		acctstatustype = vp->lvalue;	else {		DEBUG("rlm_ippool: Could not find account status type in packet.");		return RLM_MODULE_NOOP;	}	switch(acctstatustype){		case PW_STATUS_STOP:			if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)				port = vp->lvalue;			else {				DEBUG("rlm_ippool: Could not find port number in packet.");				return RLM_MODULE_NOOP;			}			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 in packet.");					return RLM_MODULE_NOOP;				}			}			break;		default:			/* We don't care about any other accounting packet */			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->session_mutex);	data_datum = gdbm_fetch(data->gdbm, key_datum);	pthread_mutex_unlock(&data->session_mutex);	if (data_datum.dptr != NULL){		/*		 * If the entry was found set active to zero		 */		memcpy(&entry, data_datum.dptr, sizeof(ippool_info));		free(data_datum.dptr);		DEBUG("rlm_ippool: Deallocated entry for ip/port: %s/%u",ip_ntoa(str,entry.ipaddr),port);		entry.active = 0;		data_datum.dptr = (char *) &entry;		data_datum.dsize = sizeof(ippool_info);		pthread_mutex_lock(&data->session_mutex);		rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);		pthread_mutex_unlock(&data->session_mutex);		if (rcode < 0) {			radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",					data->session_db, gdbm_strerror(gdbm_errno));			return RLM_MODULE_FAIL;		}		/*		 * Decrease allocated count from the ip index		 */		key_datum.dptr = (char *) &entry.ipaddr;		key_datum.dsize = sizeof(uint32_t);

⌨️ 快捷键说明

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