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

📄 rlm_sqlhpwippool.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * rlm_sqlhpwippool.c * Chooses an IPv4 address from pools defined in ASN Netvim * * Version:	$Id: rlm_sqlhpwippool.c,v 1.7 2007/04/20 14:31:31 aland 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 (c) 2005-2006 Pawel Foremski <pjf@asn.pl>, *               2000-2006 The FreeRADIUS server project * * Current bugs/limits: * - probably works only with newer versions of MySQL (subqueries) * - requires FreeRADIUS' SQL user to have proper permissions on proper tables *   from Netvim database * - of course uses dirty hacks to get access to the database * - queries and table names are not configurable * - IPv4 only (I don't even care about IPv6 by now) * - pool names (fetched from database) are not "escaped" * - you have to set encoding of radius.acctuniqueid to same as *   netvim.ips.rsv_by */#include "config.h"#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/modpriv.h>#include <ctype.h>#include "rlm_sql.h"#define VENDOR_ASN 23782#define ASN_IP_POOL_NAME 1#define PW_ASN_IP_POOL_NAME (ASN_IP_POOL_NAME | (VENDOR_ASN << 16))#define RLM_NETVIM_LOG_FMT "rlm_sqlhpwippool(%s, line %u): %s"#define RLM_NETVIM_MAX_ROWS 1000000#define RLM_NETVIM_TMP_PREFIX "auth-tmp-"static const char rcsid[] = "$Id: rlm_sqlhpwippool.c,v 1.7 2007/04/20 14:31:31 aland Exp $";typedef struct rlm_sqlhpwippool_t {	const char *myname;         /* name of this instance */	SQL_INST *sqlinst;          /* SQL_INST for requested instance */	rlm_sql_module_t *db;       /* here the fun takes place ;-) */#ifdef HAVE_PTHREAD_D	pthread_mutex_t mutex;      /* used "with" syncafter */#endif	int sincesync;              /* req. done so far since last free IP sync. */	/* from config */	char *sqlinst_name;         /* rlm_sql instance to use */	char *db_name;              /* netvim database */	int nofreefail;             /* fail if no free IP addresses found */	int freeafter;              /* how many seconds an IP should not be used after	                               freeing */	int syncafter;              /* how often to sync with radacct */} rlm_sqlhpwippool_t;/* char *name, int type, * size_t offset, void *data, char *dflt */static CONF_PARSER module_config[] = {	{ "sqlinst_name",       PW_TYPE_STRING_PTR,	  offsetof(rlm_sqlhpwippool_t, sqlinst_name),       NULL, "sql" },	{ "db_name",            PW_TYPE_STRING_PTR,	  offsetof(rlm_sqlhpwippool_t, db_name),            NULL, "netvim" },	{ "nofreefail",         PW_TYPE_BOOLEAN,	  offsetof(rlm_sqlhpwippool_t, nofreefail),         NULL, "yes" },	{ "freeafter",          PW_TYPE_INTEGER,	  offsetof(rlm_sqlhpwippool_t, freeafter),          NULL, "300" },	{ "syncafter",          PW_TYPE_INTEGER,	  offsetof(rlm_sqlhpwippool_t, syncafter),          NULL, "25" },	{ NULL, -1, 0, NULL, NULL } /* end */};/* wrapper around radlog which adds prefix with module and instance name */static int nvp_log(unsigned int line, rlm_sqlhpwippool_t *data, int lvl,                   const char *fmt, ...){	va_list ap;	int r;	char pfmt[4096];	/* prefix log message with RLM_NETVIM_LOG_FMT */	snprintf(pfmt, sizeof(pfmt), RLM_NETVIM_LOG_FMT,	         data->myname, line, fmt);	va_start(ap, fmt);	r = vradlog(lvl, pfmt, ap);	va_end(ap);	return r;}/* handy SQL query tool */static int nvp_vquery(unsigned int line, rlm_sqlhpwippool_t *data,                      SQLSOCK *sqlsock, const char *fmt, va_list ap){	char query[MAX_QUERY_LEN];	vsnprintf(query, MAX_QUERY_LEN, fmt, ap);	if (rlm_sql_query(sqlsock, data->sqlinst, query)) {		nvp_log(__LINE__, data, L_ERR, "nvp_vquery(): query from line %u: %s",		        line, (char *)(data->db->sql_error)(sqlsock, data->sqlinst->config));		return 0;	}	return 1;}/* wrapper around nvp_vquery */static int nvp_query(unsigned int line, rlm_sqlhpwippool_t *data,                    SQLSOCK *sqlsock, const char *fmt, ...){	int r;	va_list ap;	va_start(ap, fmt);	r = nvp_vquery(line, data, sqlsock, fmt, ap);	va_end(ap);	return r;}/* handy wrapper around data->db->sql_finish_query() */static int nvp_finish(rlm_sqlhpwippool_t *data, SQLSOCK *sqlsock){	return (data->db->sql_finish_query)(sqlsock, data->sqlinst->config);}/* executes query and fetches first row * -1 on no results *  0 on db error *  1 on success */static int nvp_select(unsigned int line, rlm_sqlhpwippool_t *data,                      SQLSOCK *sqlsock, const char *fmt, ...){	va_list ap;	va_start(ap, fmt);	if (!nvp_vquery(line, data, sqlsock, fmt, ap)) {		va_end(ap);		return 0;	}	va_end(ap);	if ((data->db->sql_store_result)(sqlsock, data->sqlinst->config)) {		nvp_log(__LINE__, data, L_ERR,		        "nvp_select(): error while saving results of query from line %u",		        line);		return 0;	}	if ((data->db->sql_num_rows)(sqlsock, data->sqlinst->config) < 1) {		nvp_log(__LINE__, data, L_DBG,		        "nvp_select(): no results in query from line %u", line);		return -1;	}	if ((data->db->sql_fetch_row)(sqlsock, data->sqlinst->config)) {		nvp_log(__LINE__, data, L_ERR, "nvp_select(): couldn't fetch row "		                               "from results of query from line %u",		        line);		return 0;	}	return 1;}static int nvp_select_finish(rlm_sqlhpwippool_t *data, SQLSOCK *sqlsock){	return ((data->db->sql_free_result)(sqlsock, data->sqlinst->config) ||	        nvp_finish(data, sqlsock));}/* frees IPs of closed sessions (eg. by external modifications to db) */static int nvp_freeclosed(rlm_sqlhpwippool_t *data, SQLSOCK *sqlsock){	if (!nvp_query(__LINE__, data, sqlsock,	    "UPDATE `%s`.`ips`, `radacct` "	    	"SET "	    		"`ips`.`rsv_until` = `radacct`.`acctstoptime` + INTERVAL %u SECOND "	    	"WHERE "	    		"`radacct`.`acctstoptime` IS NOT NULL AND "   /* session is closed */	    		"("                                    /* address is being used */	    			"`ips`.`pid` IS NOT NULL AND "	    			"(`rsv_until` = 0 OR `rsv_until` > NOW())"	    		") AND "	    		"`radacct`.`acctuniqueid` = `ips`.`rsv_by`",	    data->db_name, data->freeafter)) {		return 0;	}	nvp_finish(data, sqlsock);	return 1;}/* updates number of free IP addresses in pools */static int nvp_syncfree(rlm_sqlhpwippool_t *data, SQLSOCK *sqlsock){	if (!nvp_query(__LINE__, data, sqlsock,	    "UPDATE `%s`.`ip_pools` "	    	"SET `ip_pools`.`free` = "	    		"(SELECT COUNT(*) "	    			"FROM `%1$s`.`ips` "	    			"WHERE "	    				"`ips`.`ip` BETWEEN "	    					"`ip_pools`.`ip_start` AND `ip_pools`.`ip_stop` AND "	    				"("	    					"`ips`.`pid` IS NULL OR "	    					"(`ips`.`rsv_until` > 0 AND `ips`.`rsv_until` < NOW())"	    				"))",	    data->db_name)) {		return 0;	}	nvp_finish(data, sqlsock);	return 1;}/* cleanup IP pools and sync them with radacct */static int nvp_cleanup(rlm_sqlhpwippool_t *data){	SQLSOCK *sqlsock;	/* initialize the SQL socket */	sqlsock = sql_get_socket(data->sqlinst);	if (!sqlsock) {		nvp_log(__LINE__, data, L_ERR, "nvp_cleanup(): error while "		                               "requesting new SQL connection");		return 0;	}	/* free IPs of closed sessions */	if (!nvp_freeclosed(data, sqlsock)) {		sql_release_socket(data->sqlinst, sqlsock);		return 0;	}	/* add sessions opened in the meantime */	if (!nvp_query(__LINE__, data, sqlsock,	    "UPDATE `%s`.`ips`, `radacct` "	    	"SET "	    		"`ips`.`pid` = 0, "	    		"`ips`.`rsv_by` = `radacct`.`acctuniqueid`, "	    		"`ips`.`rsv_since` = `radacct`.`acctstarttime`, "	    		"`ips`.`rsv_until` = 0 "	    	"WHERE "	    		"`radacct`.`acctstoptime` IS NULL AND "     /* session is opened */	    		"`ips`.`ip` = INET_ATON(`radacct`.`framedipaddress`) AND "	    		"("	    			"`ips`.`pid` IS NULL OR "/*	    			"(`ips`.`rsv_until` > 0 AND `ips.`rsv_until` < NOW()) " */	    			"`ips`.`rsv_until` != 0"   /* no acct pkt received yet */	    		")",	    data->db_name)) {		sql_release_socket(data->sqlinst, sqlsock);		return 0;	}	else {		nvp_finish(data, sqlsock);	}	/* count number of free IP addresses in IP pools */	if (!nvp_syncfree(data, sqlsock)) {		sql_release_socket(data->sqlinst, sqlsock);		return 0;	}	sql_release_socket(data->sqlinst, sqlsock);	return 1;}static int sqlhpwippool_detach(void *instance){	rlm_sqlhpwippool_t *data = (rlm_sqlhpwippool_t *) instance;	/* (*data) is zeroed on instantiation */	if (data->sqlinst_name) free(data->sqlinst_name);	if (data->db_name)      free(data->db_name);	free(data);	return 0;}/* standard foobar code */static int sqlhpwippool_instantiate(CONF_SECTION *conf, void **instance){	rlm_sqlhpwippool_t *data;	module_instance_t *modinst;	/* set up a storage area for instance data */	data = rad_malloc(sizeof(*data));	if (!data) return -1;	memset(data, 0, sizeof(*data)); /* so _detach will know what to free */	/* fail if the configuration parameters can't be parsed */	if (cf_section_parse(conf, data, module_config) < 0) {		sqlhpwippool_detach(*instance);		return -1;	}	/* save my name */	data->myname = cf_section_name2(conf);	if (!data->myname) {		data->myname = "(no name)";	}	data->sincesync = 0;	modinst = find_module_instance(cf_section_find("modules"), (data->sqlinst_name) );	if (!modinst) {		nvp_log(__LINE__, data, L_ERR,		        "sqlhpwippool_instantiate(): cannot find module instance "		        "named \"%s\"",		        data->sqlinst_name);		return -1;	}	/* check if the given instance is really a rlm_sql instance */	if (strcmp(modinst->entry->name, "rlm_sql") != 0) {		nvp_log(__LINE__, data, L_ERR,		        "sqlhpwippool_instantiate(): given instance (%s) is not "		        "an instance of the rlm_sql module",		        data->sqlinst_name);		return -1;	}	/* save pointers to useful "objects" */	data->sqlinst = (SQL_INST *) modinst->insthandle;	data->db = (rlm_sql_module_t *) data->sqlinst->module;	/* everything went ok, cleanup pool */	*instance = data;	return ((nvp_cleanup(data)) ? 0 : -1);}/* assign new IP address, if required */static int sqlhpwippool_postauth(void *instance, REQUEST *request){	VALUE_PAIR *vp;	unsigned char *pname;       /* name of requested IP pool */	uint32_t nasip;             /* NAS IP in host byte order */	struct in_addr ip = {0};    /* reserved IP for client (net. byte order) */	SQLSOCK *sqlsock;	unsigned long s_gid,        /* _s_elected in sql result set */	              s_prio,       /* as above */	              s_pid,        /* as above */	              gid,          /* real integer value */	              pid,          /* as above */	              weights_sum, used_sum, ip_start, ip_stop, connid;	long prio;	rlm_sqlhpwippool_t *data = (rlm_sqlhpwippool_t *) instance;	/* if IP is already there, then nothing to do */	vp = pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS);	if (vp) {		nvp_log(__LINE__, data, L_DBG,		        "sqlhpwippool_postauth(): IP address "		        "already in the reply packet - exiting");		return RLM_MODULE_NOOP;	}	/* if no pool name, we don't need to do anything */	vp = pairfind(request->reply->vps, PW_ASN_IP_POOL_NAME);	if (vp) {		pname = vp->vp_strvalue;		nvp_log(__LINE__, data, L_DBG,		        "sqlhpwippool_postauth(): pool name = '%s'",		        pname);	}	else {		nvp_log(__LINE__, data, L_DBG,		        "sqlhpwippool_postauth(): no IP pool name - exiting");		return RLM_MODULE_NOOP;	}	/* if no NAS IP address, assign 0 */	vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS);	if (vp) {		nasip = ntohl(vp->vp_ipaddr);	}	else {		nasip = 0;		nvp_log(__LINE__, data, L_DBG,		        "sqlhpwippool_postauth(): no NAS IP address in "		        "the request packet - using \"0.0.0.0/0\" (any)");	}	/* get our database connection */	sqlsock = sql_get_socket(data->sqlinst);

⌨️ 快捷键说明

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