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

📄 conffile.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * conffile.c	Read the radiusd.conf file. * *		Yep I should learn to use lex & yacc, or at least *		write a decent parser. I know how to do that, really :) *		miquels@cistron.nl * * Version:	$Id: conffile.c,v 1.199 2008/04/18 13:51:12 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006  The FreeRADIUS server project * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000  Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: conffile.c,v 1.199 2008/04/18 13:51:12 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/rad_assert.h>#ifdef HAVE_DIRENT_H#include <dirent.h>#endif#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#include <ctype.h>typedef enum conf_type {	CONF_ITEM_INVALID = 0,	CONF_ITEM_PAIR,	CONF_ITEM_SECTION,	CONF_ITEM_DATA} CONF_ITEM_TYPE;struct conf_item {	struct conf_item *next;	struct conf_part *parent;	int lineno;	const char *filename;	CONF_ITEM_TYPE type;};struct conf_pair {	CONF_ITEM item;	const char *attr;	const char *value;	FR_TOKEN operator;	FR_TOKEN value_type;};struct conf_part {	CONF_ITEM item;	const char *name1;	const char *name2;	struct conf_item *children;	struct conf_item *tail;	/* for speed */	CONF_SECTION	*template;	rbtree_t	*pair_tree; /* and a partridge.. */	rbtree_t	*section_tree; /* no jokes here */	rbtree_t	*name2_tree; /* for sections of the same name2 */	rbtree_t	*data_tree;	void		*base;	int depth;	const CONF_PARSER *variables;};/* *	Internal data that is associated with a configuration section, *	so that we don't have to track it separately. */struct conf_data {	CONF_ITEM  item;	const char *name;	int	   flag;	void	   *data;	/* user data */	void       (*free)(void *); /* free user data function */};static int cf_data_add_internal(CONF_SECTION *cs, const char *name,				void *data, void (*data_free)(void *),				int flag);static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,				   int flag);int cf_log_config = 1;int cf_log_modules = 1;/* *	Isolate the scary casts in these tiny provably-safe functions */CONF_PAIR *cf_itemtopair(CONF_ITEM *ci){	if (ci == NULL)		return NULL;	rad_assert(ci->type == CONF_ITEM_PAIR);	return (CONF_PAIR *)ci;}CONF_SECTION *cf_itemtosection(CONF_ITEM *ci){	if (ci == NULL)		return NULL;	rad_assert(ci->type == CONF_ITEM_SECTION);	return (CONF_SECTION *)ci;}CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp){	if (cp == NULL)		return NULL;	return (CONF_ITEM *)cp;}CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs){	if (cs == NULL)		return NULL;	return (CONF_ITEM *)cs;}static CONF_DATA *cf_itemtodata(CONF_ITEM *ci){	if (ci == NULL)		return NULL;	rad_assert(ci->type == CONF_ITEM_DATA);	return (CONF_DATA *)ci;}static CONF_ITEM *cf_datatoitem(CONF_DATA *cd){	if (cd == NULL)		return NULL;	return (CONF_ITEM *)cd;}/* *	Create a new CONF_PAIR */static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,				FR_TOKEN operator, FR_TOKEN value_type,				CONF_SECTION *parent){	char *p;	size_t attr_len, value_len = 0;	CONF_PAIR *cp;	if (!attr) return NULL;	attr_len = strlen(attr) + 1;	if (value) value_len = strlen(value) + 1;	p = rad_malloc(sizeof(*cp) + attr_len + value_len);	cp = (CONF_PAIR *) p;	memset(cp, 0, sizeof(*cp));	cp->item.type = CONF_ITEM_PAIR;	cp->item.parent = parent;	p += sizeof(*cp);	memcpy(p, attr, attr_len);	cp->attr = p;	if (value) {		p += attr_len;		memcpy(p, value, value_len);		cp->value = p;	}	cp->value_type = value_type;	cp->operator = operator;	return cp;}/* *	Free a CONF_PAIR */void cf_pair_free(CONF_PAIR **cp){	if (!cp || !*cp) return;	/*	 *	attr && value are allocated contiguous with cp.	 */#ifndef NDEBUG	memset(*cp, 0, sizeof(*cp));#endif	free(*cp);	*cp = NULL;}static void cf_data_free(CONF_DATA **cd){	if (!cd || !*cd) return;	/* name is allocated contiguous with cd */	if (!(*cd)->free) {		free((*cd)->data);	} else {		((*cd)->free)((*cd)->data);	}#ifndef NDEBUG	memset(*cd, 0, sizeof(*cd));#endif	free(*cd);	*cd = NULL;}/* *	rbtree callback function */static int pair_cmp(const void *a, const void *b){	const CONF_PAIR *one = a;	const CONF_PAIR *two = b;	return strcmp(one->attr, two->attr);}/* *	rbtree callback function */static int section_cmp(const void *a, const void *b){	const CONF_SECTION *one = a;	const CONF_SECTION *two = b;	return strcmp(one->name1, two->name1);}/* *	rbtree callback function */static int name2_cmp(const void *a, const void *b){	const CONF_SECTION *one = a;	const CONF_SECTION *two = b;	rad_assert(strcmp(one->name1, two->name1) == 0);	if (!one->name2 && !two->name2) return 0;	if (!one->name2) return -1;	if (!two->name2) return +1;	return strcmp(one->name2, two->name2);}/* *	rbtree callback function */static int data_cmp(const void *a, const void *b){	int rcode;	const CONF_DATA *one = a;	const CONF_DATA *two = b;	rcode = one->flag - two->flag;	if (rcode != 0) return rcode;	return strcmp(one->name, two->name);}/* *	Free strings we've parsed into data structures. */void cf_section_parse_free(CONF_SECTION *cs, void *base){	int i;	const CONF_PARSER *variables = cs->variables;	/*	 *	Don't automatically free the strings if we're being	 *	called from a module.  This is also for clients.c,	 *	where client_free() expects to be able to free the	 *	client structure.  If we moved everything to key off	 *	of the config files, we might solve some problems...	 */	if (!variables) return;	/*	 *	Free up dynamically allocated string pointers.	 */	for (i = 0; variables[i].name != NULL; i++) {		char **p;		if ((variables[i].type != PW_TYPE_STRING_PTR) &&		    (variables[i].type != PW_TYPE_FILENAME)) {			continue;		}		/*		 *	No base struct offset, data must be the pointer.		 *	If data doesn't exist, ignore the entry, there		 *	must be something wrong.		 */		if (!base) {			if (!variables[i].data) {				continue;			}			p = (char **) variables[i].data;;		} else if (variables[i].data) {			p = (char **) variables[i].data;;		} else {			p = (char **) (((char *)base) + variables[i].offset);		}		free(*p);		*p = NULL;	}}/* *	Free a CONF_SECTION */void cf_section_free(CONF_SECTION **cs){	CONF_ITEM	*ci, *next;	if (!cs || !*cs) return;	cf_section_parse_free(*cs, (*cs)->base);	for (ci = (*cs)->children; ci; ci = next) {		next = ci->next;		switch (ci->type) {		case CONF_ITEM_PAIR: {				CONF_PAIR *pair = cf_itemtopair(ci);				cf_pair_free(&pair);			}			break;		case CONF_ITEM_SECTION: {				CONF_SECTION *section = cf_itemtosection(ci);				cf_section_free(&section);			}			break;		case CONF_ITEM_DATA: {				CONF_DATA *data = cf_itemtodata(ci);				cf_data_free(&data);			}			break;		default:	/* should really be an error. */			break;		}	}	/*	 *	Name1 and name2 are allocated contiguous with	 *	cs.	 */	if ((*cs)->pair_tree)		rbtree_free((*cs)->pair_tree);	if ((*cs)->section_tree)		rbtree_free((*cs)->section_tree);	if ((*cs)->name2_tree)		rbtree_free((*cs)->name2_tree);	if ((*cs)->data_tree)		rbtree_free((*cs)->data_tree);	/*	 * And free the section	 */#ifndef NDEBUG	memset(*cs, 0, sizeof(*cs));#endif	free(*cs);	*cs = NULL;}/* *	Allocate a CONF_SECTION */static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,				      CONF_SECTION *parent){	size_t name1_len, name2_len = 0;	char *p;	CONF_SECTION	*cs;	if (!name1) return NULL;	name1_len = strlen(name1) + 1;	if (name2) name2_len = strlen(name2) + 1;	p = rad_malloc(sizeof(*cs) + name1_len + name2_len);	cs = (CONF_SECTION *) p;	memset(cs, 0, sizeof(*cs));	cs->item.type = CONF_ITEM_SECTION;	cs->item.parent = parent;	p += sizeof(*cs);	memcpy(p, name1, name1_len);	cs->name1 = p;	if (name2 && *name2) {		p += name1_len;		memcpy(p, name2, name2_len);		cs->name2 = p;	}	cs->pair_tree = rbtree_create(pair_cmp, NULL, 0);	if (!cs->pair_tree) {		cf_section_free(&cs);		return NULL;	}	/*	 *	Don't create a data tree, it may not be needed.	 */	/*	 *	Don't create the section tree here, it may not	 *	be needed.	 */	if (parent) cs->depth = parent->depth + 1;	return cs;}/* *	Add an item to a configuration section. */static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci){	if (!cs->children) {		rad_assert(cs->tail == NULL);		cs->children = ci;	} else {		rad_assert(cs->tail != NULL);		cs->tail->next = ci;	}	/*	 *	Update the trees (and tail) for each item added.	 */	for (/* nothing */; ci != NULL; ci = ci->next) {		cs->tail = ci;		/*		 *	For fast lookups, pair's and sections get		 *	added to rbtree's.		 */		switch (ci->type) {			case CONF_ITEM_PAIR:				rbtree_insert(cs->pair_tree, ci);				break;			case CONF_ITEM_SECTION: {				CONF_SECTION *cs_new = cf_itemtosection(ci);				if (!cs->section_tree) {					cs->section_tree = rbtree_create(section_cmp, NULL, 0);					/* ignore any errors */				}				if (cs->section_tree) {					rbtree_insert(cs->section_tree, cs_new);				}				/*				 *	Two names: find the named instance.				 */				{					CONF_SECTION *old_cs;					/*					 *	Find the FIRST					 *	CONF_SECTION having					 *	the given name1, and					 *	create a new tree					 *	under it.					 */					old_cs = rbtree_finddata(cs->section_tree, cs_new);					if (!old_cs) return; /* this is a bad error! */					if (!old_cs->name2_tree) {						old_cs->name2_tree = rbtree_create(name2_cmp,										   NULL, 0);					}					if (old_cs->name2_tree) {						rbtree_insert(old_cs->name2_tree, cs_new);					}				} /* had a name2 */				break;			} /* was a section */			case CONF_ITEM_DATA:				if (!cs->data_tree) {					cs->data_tree = rbtree_create(data_cmp, NULL, 0);				}				if (cs->data_tree) {					rbtree_insert(cs->data_tree, ci);				}				break;			default: /* FIXME: assert & error! */				break;		} /* switch over conf types */	} /* loop over ci */}CONF_ITEM *cf_reference_item(const CONF_SECTION *parentcs,			     CONF_SECTION *outercs,			     const char *ptr){	CONF_PAIR *cp;	CONF_SECTION *next;	const CONF_SECTION *cs = outercs;	char name[8192];	char *p;	strlcpy(name, ptr, sizeof(name));	p = name;	/*	 *	".foo" means "foo from the current section"	 */	if (*p == '.') {		p++;				/*		 *	..foo means "foo from the section		 *	enclosing this section" (etc.)		 */		while (*p == '.') {			if (cs->item.parent)				cs = cs->item.parent;			p++;		}		/*		 *	"foo.bar.baz" means "from the root"		 */	} else if (strchr(p, '.') != NULL) {		cs = parentcs;	}	while (*p) {		char *q, *r;		r = strchr(p, '[');		q = strchr(p, '.');		if (!r && !q) break;		if (r && q > r) q = NULL;		if (q && q < r) r = NULL;		/*		 *	Split off name2.		 */		if (r) {			q = strchr(r + 1, ']');			if (!q) return NULL; /* parse error */			/*			 *	Points to foo[bar]xx: parse error,			 *	it should be foo[bar] or foo[bar].baz			 */			if (q[1] && q[1] != '.') goto no_such_item;			*r = '\0';			*q = '\0';			next = cf_section_sub_find_name2(cs, p, r + 1);			*r = '[';			*q = ']';			/*			 *	Points to a named instance of a section.			 */			if (!q[1]) {				if (!next) goto no_such_item;				return cf_sectiontoitem(next);			}			q++;	/* ensure we skip the ']' and '.' */		} else {

⌨️ 快捷键说明

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