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

📄 dict.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * dict.c	Routines to read the dictionary file. * * Version:	$Id: dict.c,v 1.111 2007/12/17 12:29:30 aland Exp $ * *   This library is free software; you can redistribute it and/or *   modify it under the terms of the GNU Lesser General Public *   License as published by the Free Software Foundation; either *   version 2.1 of the License, or (at your option) any later version. * *   This library 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 *   Lesser General Public License for more details. * *   You should have received a copy of the GNU Lesser General Public *   License along with this library; if not, write to the Free Software *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006  The FreeRADIUS server project */#include	<freeradius-devel/ident.h>RCSID("$Id: dict.c,v 1.111 2007/12/17 12:29:30 aland Exp $")#include	<freeradius-devel/libradius.h>#include	<ctype.h>#ifdef HAVE_MALLOC_H#include	<malloc.h>#endif#ifdef HAVE_SYS_STAT_H#include	<sys/stat.h>#endif#define DICT_VALUE_MAX_NAME_LEN (128)#define DICT_VENDOR_MAX_NAME_LEN (128)static fr_hash_table_t *vendors_byname = NULL;static fr_hash_table_t *vendors_byvalue = NULL;static fr_hash_table_t *attributes_byname = NULL;static fr_hash_table_t *attributes_byvalue = NULL;static fr_hash_table_t *values_byvalue = NULL;static fr_hash_table_t *values_byname = NULL;static DICT_ATTR *dict_base_attrs[256];/* *	For faster HUP's, we cache the stat information for *	files we've $INCLUDEd */typedef struct dict_stat_t {	struct dict_stat_t *next;	char	   	   *name;	time_t		   mtime;} dict_stat_t;static char *stat_root_dir = NULL;static char *stat_root_file = NULL;static dict_stat_t *stat_head = NULL;static dict_stat_t *stat_tail = NULL;typedef struct value_fixup_t {	char		attrstr[40];	DICT_VALUE	*dval;	struct value_fixup_t *next;} value_fixup_t;/* *	So VALUEs in the dictionary can have forward references. */static value_fixup_t *value_fixup = NULL;static const FR_NAME_NUMBER type_table[] = {	{ "integer",	PW_TYPE_INTEGER },	{ "string",	PW_TYPE_STRING },	{ "ipaddr",	PW_TYPE_IPADDR },	{ "date",	PW_TYPE_DATE },	{ "abinary",	PW_TYPE_ABINARY },	{ "octets",	PW_TYPE_OCTETS },	{ "ifid",	PW_TYPE_IFID },	{ "ipv6addr",	PW_TYPE_IPV6ADDR },	{ "ipv6prefix", PW_TYPE_IPV6PREFIX },	{ "byte",	PW_TYPE_BYTE },	{ "short",	PW_TYPE_SHORT },	{ "ether",	PW_TYPE_ETHERNET },	{ NULL, 0 }};/* *	Create the hash of the name. * *	We copy the hash function here because it's substantially faster. */#define FNV_MAGIC_INIT (0x811c9dc5)#define FNV_MAGIC_PRIME (0x01000193)static uint32_t dict_hashname(const char *name){	uint32_t hash = FNV_MAGIC_INIT;	const char *p;	for (p = name; *p != '\0'; p++) {		int c = *(const unsigned char *) p;		if (isalpha(c)) c = tolower(c);		hash *= FNV_MAGIC_PRIME;		hash ^= (uint32_t ) (c & 0xff);	}	return hash;}/* *	Hash callback functions. */static uint32_t dict_attr_name_hash(const void *data){	return dict_hashname(((const DICT_ATTR *)data)->name);}static int dict_attr_name_cmp(const void *one, const void *two){	const DICT_ATTR *a = one;	const DICT_ATTR *b = two;	return strcasecmp(a->name, b->name);}static uint32_t dict_attr_value_hash(const void *data){	uint32_t hash;	const DICT_ATTR *attr = data;	hash = fr_hash(&attr->vendor, sizeof(attr->vendor));	return fr_hash_update(&attr->attr, sizeof(attr->attr), hash);}static int dict_attr_value_cmp(const void *one, const void *two){	const DICT_ATTR *a = one;	const DICT_ATTR *b = two;	if (a->vendor < b->vendor) return -1;	if (a->vendor > b->vendor) return +1;	return a->attr - b->attr;}static uint32_t dict_vendor_name_hash(const void *data){	return dict_hashname(((const DICT_VENDOR *)data)->name);}static int dict_vendor_name_cmp(const void *one, const void *two){	const DICT_VENDOR *a = one;	const DICT_VENDOR *b = two;	return strcasecmp(a->name, b->name);}static uint32_t dict_vendor_value_hash(const void *data){	return fr_hash(&(((const DICT_VENDOR *)data)->vendorpec),			 sizeof(((const DICT_VENDOR *)data)->vendorpec));}static int dict_vendor_value_cmp(const void *one, const void *two){	const DICT_VENDOR *a = one;	const DICT_VENDOR *b = two;	return a->vendorpec - b->vendorpec;}static uint32_t dict_value_name_hash(const void *data){	uint32_t hash;	const DICT_VALUE *dval = data;	hash = dict_hashname(dval->name);	return fr_hash_update(&dval->attr, sizeof(dval->attr), hash);}static int dict_value_name_cmp(const void *one, const void *two){	int rcode;	const DICT_VALUE *a = one;	const DICT_VALUE *b = two;	rcode = a->attr - b->attr;	if (rcode != 0) return rcode;	return strcasecmp(a->name, b->name);}static uint32_t dict_value_value_hash(const void *data){	uint32_t hash;	const DICT_VALUE *dval = data;	hash = fr_hash(&dval->attr, sizeof(dval->attr));	return fr_hash_update(&dval->value, sizeof(dval->value), hash);}static int dict_value_value_cmp(const void *one, const void *two){	int rcode;	const DICT_VALUE *a = one;	const DICT_VALUE *b = two;	rcode = a->attr - b->attr;	if (rcode != 0) return rcode;	return a->value - b->value;}/* *	Free the list of stat buffers */static void dict_stat_free(void){	dict_stat_t *this, *next;	free(stat_root_dir);	stat_root_dir = NULL;	free(stat_root_file);	stat_root_file = NULL;	if (!stat_head) {		stat_tail = NULL;		return;	}	for (this = stat_head; this != NULL; this = next) {		next = this->next;		free(this->name);		free(this);	}	stat_head = stat_tail = NULL;}/* *	Add an entry to the list of stat buffers. */static void dict_stat_add(const char *name, const struct stat *stat_buf){	dict_stat_t *this;	this = malloc(sizeof(*this));	if (!this) return;	memset(this, 0, sizeof(*this));	this->name = strdup(name);	this->mtime = stat_buf->st_mtime;	if (!stat_head) {		stat_head = stat_tail = this;	} else {		stat_tail->next = this;		stat_tail = this;	}}/* *	See if any dictionaries have changed.  If not, don't *	do anything. */static int dict_stat_check(const char *root_dir, const char *root_file){	struct stat buf;	dict_stat_t *this;	if (!stat_root_dir) return 0;	if (!stat_root_file) return 0;	if (strcmp(root_dir, stat_root_dir) != 0) return 0;	if (strcmp(root_file, stat_root_file) != 0) return 0;	if (!stat_head) return 0; /* changed, reload */	for (this = stat_head; this != NULL; this = this->next) {		if (stat(this->name, &buf) < 0) return 0;		if (buf.st_mtime != this->mtime) return 0;	}	return 1;}typedef struct fr_pool_t {	void	*page_end;	void	*free_ptr;	struct fr_pool_t *page_free;	struct fr_pool_t *page_next;} fr_pool_t;#define FR_POOL_SIZE (32768)#define FR_ALLOC_ALIGN (8)static fr_pool_t *dict_pool = NULL;static fr_pool_t *fr_pool_create(void){	fr_pool_t *fp = malloc(FR_POOL_SIZE);	if (!fp) return NULL;	fp->page_end = ((uint8_t *) fp) + FR_POOL_SIZE;	fp->free_ptr = ((uint8_t *) fp) + sizeof(*fp);	fp->page_free = fp;	fp->page_next = NULL;	return fp;}static void fr_pool_delete(fr_pool_t **pfp){	fr_pool_t *fp, *next;	if (!pfp || !*pfp) return;	for (fp = *pfp; fp != NULL; fp = next) {		next = fp->page_next;		free(fp);	}}static void *fr_pool_alloc(size_t size){	void *ptr;	if (size == 0) return NULL;	if (size > 256) return NULL; /* shouldn't happen */	if (!dict_pool) {		dict_pool = fr_pool_create();		if (!dict_pool) return NULL;	}	if ((size & (FR_ALLOC_ALIGN - 1)) != 0) {		size += FR_ALLOC_ALIGN - (size & (FR_ALLOC_ALIGN - 1));	}	if ((((uint8_t *) dict_pool->page_free->free_ptr) + size) > (uint8_t *) dict_pool->page_free->page_end) {		dict_pool->page_free->page_next = fr_pool_create();		if (!dict_pool->page_free->page_next) return NULL;		dict_pool->page_free = dict_pool->page_free->page_next;	}	ptr = dict_pool->page_free->free_ptr;	dict_pool->page_free->free_ptr = ((uint8_t *) dict_pool->page_free->free_ptr) + size;	return ptr;}static void fr_pool_free(UNUSED void *ptr){	/*	 *	Place-holder for later code.	 */}/* *	Free the dictionary_attributes and dictionary_values lists. */void dict_free(void){	/*	 *	Free the tables	 */	fr_hash_table_free(vendors_byname);	fr_hash_table_free(vendors_byvalue);	vendors_byname = NULL;	vendors_byvalue = NULL;	fr_hash_table_free(attributes_byname);	fr_hash_table_free(attributes_byvalue);	attributes_byname = NULL;	attributes_byvalue = NULL;	fr_hash_table_free(values_byname);	fr_hash_table_free(values_byvalue);	values_byname = NULL;	values_byvalue = NULL;	memset(dict_base_attrs, 0, sizeof(dict_base_attrs));	fr_pool_delete(&dict_pool);	dict_stat_free();}/* *	Add vendor to the list. */int dict_addvendor(const char *name, int value){	size_t length;	DICT_VENDOR *dv;	if (value >= 32767) {	       	librad_log("dict_addvendor: Cannot handle vendor ID larger than 65535");		return -1;	}	if ((length = strlen(name)) >= DICT_VENDOR_MAX_NAME_LEN) {		librad_log("dict_addvendor: vendor name too long");		return -1;	}	if ((dv = fr_pool_alloc(sizeof(*dv) + length)) == NULL) {		librad_log("dict_addvendor: out of memory");		return -1;	}	strcpy(dv->name, name);	dv->vendorpec  = value;	dv->type = dv->length = 1; /* defaults */	if (!fr_hash_table_insert(vendors_byname, dv)) {		DICT_VENDOR *old_dv;		old_dv = fr_hash_table_finddata(vendors_byname, dv);		if (!old_dv) {			librad_log("dict_addvendor: Failed inserting vendor name %s", name);			return -1;		}		if (old_dv->vendorpec != dv->vendorpec) {			librad_log("dict_addvendor: Duplicate vendor name %s", name);			return -1;		}		/*		 *	Already inserted.  Discard the duplicate entry.		 */		fr_pool_free(dv);		return 0;	}	/*	 *	Insert the SAME pointer (not free'd when this table is	 *	deleted), into another table.	 *	 *	We want this behaviour because we want OLD names for	 *	the attributes to be read from the configuration	 *	files, but when we're printing them, (and looking up	 *	by value) we want to use the NEW name.	 */	if (!fr_hash_table_replace(vendors_byvalue, dv)) {		librad_log("dict_addvendor: Failed inserting vendor %s",			   name);		return -1;	}	return 0;}/* *	Add an attribute to the dictionary. */int dict_addattr(const char *name, int vendor, int type, int value,		 ATTR_FLAGS flags){	static int      max_attr = 0;	DICT_ATTR	*attr;	if (strlen(name) > (sizeof(attr->name) -1)) {		librad_log("dict_addattr: attribute name too long");		return -1;	}	/*	 *	If the value is '-1', that means use a pre-existing	 *	one (if it already exists).  If one does NOT already exist,	 *	then create a new attribute, with a non-conflicting value,	 *	and use that.	 */	if (value == -1) {		if (dict_attrbyname(name)) {			return 0; /* exists, don't add it again */		}		value = ++max_attr;	} else if (vendor == 0) {		/*		 *  Update 'max_attr'		 */		if (value > max_attr) {			max_attr = value;		}	}	if (value < 0) {		librad_log("dict_addattr: ATTRIBUTE has invalid number (less than zero)");		return -1;	}	if (value >= 65536) {		librad_log("dict_addattr: ATTRIBUTE has invalid number (larger than 65535).");		return -1;	}	if (vendor) {		DICT_VENDOR *dv;		static DICT_VENDOR *last_vendor = NULL;		/*		 *	Most ATTRIBUTEs are bunched together by		 *	VENDOR.  We can save a lot of lookups on		 *	dictionary initialization by caching the last		 *	vendor.		 */		if (last_vendor && (vendor == last_vendor->vendorpec)) {			dv = last_vendor;		} else {			dv = dict_vendorbyvalue(vendor);			last_vendor = dv;		}		/*		 *	If the vendor isn't defined, die.		 */		if (!dv) {			librad_log("dict_addattr: Unknown vendor");			return -1;		}		/*		 *	FIXME: Switch over dv->type, and limit things		 *	properly.		 */		if ((dv->type == 1) && (value >= 256)) {			librad_log("dict_addattr: ATTRIBUTE has invalid number (larger than 255).");			return -1;		} /* else 256..65535 are allowed */	}	/*	 *	Create a new attribute for the list	 */	if ((attr = fr_pool_alloc(sizeof(*attr))) == NULL) {		librad_log("dict_addattr: out of memory");		return -1;	}	strcpy(attr->name, name);	attr->attr = value;	attr->attr |= (vendor << 16); /* FIXME: hack */	attr->vendor = vendor;	attr->type = type;	attr->flags = flags;	attr->vendor = vendor;	/*	 *	Insert the attribute, only if it's not a duplicate.	 */

⌨️ 快捷键说明

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