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

📄 dict.c

📁 radius服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * dict.c	Routines to read the dictionary file. * * Version:	$Id: dict.c,v 1.50.2.3 2004/09/10 15:06:44 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * * Copyright 2000  The FreeRADIUS server project */static const char rcsid[] = "$Id: dict.c,v 1.50.2.3 2004/09/10 15:06:44 aland Exp $";#include	"autoconf.h"#include	<stdlib.h>#include	<ctype.h>#include	<string.h>#ifdef HAVE_MALLOC_H#include	<malloc.h>#endif#include	"libradius.h"#include	"missing.h"/* *	There are very few vendors, and they're looked up only when we *	read the dictionaries.  So it's OK to have a singly linked *	list here. */static DICT_VENDOR	*dictionary_vendors = NULL;static rbtree_t *attributes_byname = NULL;static rbtree_t *attributes_byvalue = NULL;static rbtree_t *values_byvalue = NULL;static rbtree_t *values_byname = 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 LRAD_NAME_NUMBER type_table[] = {	{ "string",	PW_TYPE_STRING },	{ "integer",	PW_TYPE_INTEGER },	{ "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 },	{ NULL, 0 }};/* *	Quick pointers to the base 0..255 attributes. * *	These attributes are referenced a LOT, especially during *	decoding of the on-the-wire packets.  It's useful to keep a *	cache of their dictionary entries, so looking them up is *	O(1), instead of O(log(N)).  (N==number of dictionary entries...) */static DICT_ATTR *base_attributes[256];/* *	Free the dictionary_attributes and dictionary_values lists. */void dict_free(void){	DICT_VENDOR	*dvend, *enext;	memset(base_attributes, 0, sizeof(base_attributes));	for (dvend = dictionary_vendors; dvend; dvend = enext) {		enext = dvend->next;		free(dvend);	}	dictionary_vendors = NULL;	/*	 *	Free the tree of attributes by name and value.	 */	rbtree_free(attributes_byname);	rbtree_free(attributes_byvalue);	attributes_byname = NULL;	attributes_byvalue = NULL;	rbtree_free(values_byname);	rbtree_free(values_byvalue);	values_byname = NULL;	values_byvalue = NULL;}/* *	Add vendor to the list. */int dict_addvendor(const char *name, int value){	DICT_VENDOR *vval;	if (value >= (1 << 16)) {	       	librad_log("dict_addvendor: Cannot handle vendor ID larger than 65535");		return -1;	}	if (strlen(name) > (sizeof(vval->name) -1)) {		librad_log("dict_addvendor: vendor name too long");		return -1;	}	if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) == NULL) {		librad_log("dict_addvendor: out of memory");		return -1;	}	strcpy(vval->name, name);	vval->vendorpec  = value;	/* Insert at front. */	vval->next = dictionary_vendors;	dictionary_vendors = vval;	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) {		attr = dict_attrbyname(name);		if (attr != NULL) {			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 >= 65536) {		librad_log("dict_addattr: ATTRIBUTE has invalid number.");		return -1;	}	/*	 *	Create a new attribute for the list	 */	if ((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) == NULL) {		librad_log("dict_addattr: out of memory");		return -1;	}	strcpy(attr->name, name);	attr->attr = value;	attr->type = type;	attr->flags = flags;	if (vendor) attr->attr |= (vendor << 16);	/*	 *	Insert the attribute, only if it's not a duplicate.	 */	if (rbtree_insert(attributes_byname, attr) == 0) {		DICT_ATTR	*a;		/*		 *	If the attribute has identical number, then		 *	ignore the duplicate.		 */		a = rbtree_finddata(attributes_byname, attr);		if (a && (strcasecmp(a->name, attr->name) == 0)) {			if (a->attr != attr->attr) {				librad_log("dict_addattr: Duplicate attribute name %s", name);				return -1;			}			/*			 *	Same name, same attr, maybe the			 *	flags and/or type is different.			 *	Let the new value over-ride the			 *	old one.			 */		}	}	if ((attr->attr >= 0) && (attr->attr < 256)) {		/*		 *	If it's an on-the-wire base attribute,		 *	then keep a quick reference to it, for speed.		 */		base_attributes[attr->attr] = attr;	}	/*	 *	Insert the SAME pointer (not free'd when this tree is	 *	deleted), into another tree.	 *	 *	If the newly inserted entry is a duplicate of an existing	 *	entry, then the old entry is tossed, and the new one	 *	replaces it.  This behaviour is configured in the	 *	rbtree_create() function.	 *	 *	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.	 */	rbtree_insert(attributes_byvalue, attr);	return 0;}/* *	Add a value for an attribute to the dictionary. */int dict_addvalue(const char *namestr, char *attrstr, int value){	DICT_ATTR	*dattr;	DICT_VALUE	*dval;	if (strlen(namestr) > (sizeof(dval->name) -1)) {		librad_log("dict_addvalue: value name too long");		return -1;	}	if ((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) == NULL) {		librad_log("dict_addvalue: out of memory");		return -1;	}	memset(dval, 0, sizeof(*dval));	strcpy(dval->name, namestr);	dval->value = value;	/*	 *	Remember which attribute is associated with this	 *	value, if possible.	 */	dattr = dict_attrbyname(attrstr);	if (dattr) {		dval->attr = dattr->attr;	} else {		value_fixup_t *fixup;				fixup = (value_fixup_t *) malloc(sizeof(*fixup));		if (!fixup) {			librad_log("dict_addvalue: out of memory");			return -1;		}		memset(fixup, 0, sizeof(*fixup));		strNcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr));		fixup->dval = dval;				/*		 *	Insert to the head of the list.		 */		fixup->next = value_fixup;		value_fixup = fixup;		return 0;	}	/*	 *	Add the value into the dictionary.	 */	if (rbtree_insert(values_byname, dval) == 0) {		if (dattr) {			DICT_VALUE *dup;						/*			 *	Suppress duplicates with the same			 *	name and value.  There are lots in			 *	dictionary.ascend.			 */			dup = dict_valbyname(dattr->attr, namestr);			if (dup && (dup->value == dval->value)) {				free(dval);				return 0;			}		}		librad_log("dict_addvalue: Duplicate value name %s for attribute %s", namestr, attrstr);		return -1;	}	rbtree_insert(values_byvalue, dval);	return 0;}/* *	Process the ATTRIBUTE command */static int process_attribute(const char* fn, const int line,			     const int block_vendor, const char* data){	int		vendor;	char		namestr[256];	char		valstr[256];	char		typestr[256];	char		optstr[256];	int		value;	int		type;	char		*s, *c;	ATTR_FLAGS	flags;	vendor = 0;	optstr[0] = 0;	if(sscanf(data, "%s%s%s%s", namestr, valstr, typestr, optstr) < 3) {		librad_log("dict_init: %s[%d]: invalid ATTRIBUTE line",			fn, line);		return -1;	}	/*	 *	Validate all entries	 */	if (!isdigit((int) *valstr)) {		librad_log("dict_init: %s[%d]: invalid value", fn, line);		return -1;	}	if (valstr[0] != '0')		value = atoi(valstr);	else		sscanf(valstr, "%i", &value);	/*	 *	find the type of the attribute.	 */	type = lrad_str2int(type_table, typestr, -1);	if (type < 0) {		librad_log("dict_init: %s[%d]: invalid type \"%s\"",			fn, line, typestr);		return -1;	}	/*	 *	Ignore comments	 */	if (optstr[0] == '#') optstr[0] = '\0';	/*	 *	Only look up the vendor if the string	 *	is non-empty.	 */	memset(&flags, 0, sizeof(flags));	s = strtok(optstr, ",");	while(s) {		if (strcmp(s, "has_tag") == 0 ||		    strcmp(s, "has_tag=1") == 0) {			 /* Boolean flag, means this is a			    tagged attribute */			 flags.has_tag = 1;		}		else if (strncmp(s, "len+=", 5) == 0 ||			 strncmp(s, "len-=", 5) == 0) {			  /* Length difference, to accomodate			     braindead NASes & their vendors */			  flags.len_disp = strtol(s + 5, &c, 0);			  if (*c) {				librad_log("dict_init: %s[%d] invalid option %s",					   fn, line, s);				return -1;			  }			  if (s[3] == '-') {				flags.len_disp = -flags.len_disp;			  }		}		else if (strncmp(s, "encrypt=", 8) == 0) {			  /* Encryption method, defaults to 0 (none).			     Currently valid is just type 2,			     Tunnel-Password style, which can only			     be applied to strings. */			  flags.encrypt = strtol(s + 8, &c, 0);			  if (*c) {				librad_log( "dict_init: %s[%d] invalid option %s",					   fn, line, s);				return -1;			  }		}		else {			  /* Must be a vendor 'flag'... */			  if (strncmp(s, "vendor=", 5) == 0) {				/* New format */				s += 5;			  }			  vendor = dict_vendorbyname(s);			  if (!vendor) {				librad_log( "dict_init: %s[%d]: unknown vendor %s",					   fn, line, optstr);				return -1;			  }			  if (block_vendor && optstr[0] &&			      (block_vendor != vendor)) {				librad_log("dict_init: %s[%d]: mismatched vendor %s within BEGIN-VENDOR/END-VENDOR block",					   fn, line, optstr);				return -1;			  }		}		s = strtok(NULL, ",");	}	if (block_vendor) vendor = block_vendor;	if (dict_addattr(namestr, vendor, type, value, flags) < 0) {		librad_log("dict_init: %s[%d]: %s",			   fn, line, librad_errstr);		return -1;	}	return 0;}/* *	Process the VALUE command */static int process_value(const char* fn, const int line, const char* data){	char	namestr[256];	char	valstr[256];	char	attrstr[256];	int	value;	if (sscanf(data, "%s%s%s", attrstr, namestr, valstr) != 3) {		librad_log("dict_init: %s[%d]: invalid VALUE line",			fn, line);		return -1;	}	/*	 *	For Compatibility, skip "Server-Config"	 */	if (strcasecmp(attrstr, "Server-Config") == 0)		return 0;	/*	 *	Validate all entries	 */	if (!isdigit((int) *valstr)) {

⌨️ 快捷键说明

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