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

📄 conffile.c

📁 linux 下的radius 最新版。linux 下的radius 最新版.linux 下的radius 最新版
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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.100.2.1.2.5 2007/03/05 14:20:38 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 2000  The FreeRADIUS server project * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl> * Copyright 2000  Alan DeKok <aland@ox.org> */#include "autoconf.h"#include "libradius.h"#include <stdlib.h>#include <string.h>#ifdef HAVE_NETINET_IN_H#	include <netinet/in.h>#endif#ifdef HAVE_SYS_STAT_H#include	<sys/stat.h>#endif#include "radiusd.h"#include "rad_assert.h"#include "conffile.h"#include "token.h"#include "modules.h"static const char rcsid[] ="$Id: conffile.c,v 1.100.2.1.2.5 2007/03/05 14:20:38 aland Exp $";#define xstrdup strduptypedef enum conf_type {	CONF_ITEM_PAIR,	CONF_ITEM_SECTION} CONF_ITEM_TYPE;struct conf_item {	struct conf_item *next;	struct conf_part *parent;	int lineno;	CONF_ITEM_TYPE type;};struct conf_pair {	CONF_ITEM item;	char *attr;	char *value;	LRAD_TOKEN operator;};struct conf_part {	CONF_ITEM item;	char *name1;	char *name2;	void *base;	const CONF_PARSER *variables;	struct conf_item *children;};/* *	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;}/* *	Create a new CONF_PAIR */static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,		LRAD_TOKEN operator, CONF_SECTION *parent){	CONF_PAIR *cp;	cp = (CONF_PAIR *)rad_malloc(sizeof(CONF_PAIR));	memset(cp, 0, sizeof(CONF_PAIR));	cp->item.type = CONF_ITEM_PAIR;	cp->item.parent = parent;	cp->attr = xstrdup(attr);	cp->value = xstrdup(value);	cp->operator = operator;	return cp;}/* *	Free a CONF_PAIR */void cf_pair_free(CONF_PAIR **cp){	if (!cp || !*cp) return;	if ((*cp)->attr)		free((*cp)->attr);	if ((*cp)->value)		free((*cp)->value);#ifndef NDEBUG	memset(*cp, 0, sizeof(*cp));#endif	free(*cp);	*cp = NULL;}/* *	Free strings we've parsed into data structures. */static void cf_section_parse_free(void *base, const CONF_PARSER *variables){	int i;	/*	 *	Don't automatically free the strings if we're being	 *	called from a module.	 */	if (base || !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) {			continue;		}		/*		 *	Prefer the data, if it's there.		 *	Else use the base + offset.		 */		if (!variables[i].data) {			continue;		}		/*		 *	FIXME: Add base		 */		p = (char **) (variables[i].data);		free(*p);		*p = NULL;	}}/* *	Allocate a CONF_SECTION */static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,				      CONF_SECTION *parent, const char *cf){	CONF_SECTION	*cs;	if (name1 == NULL || !name1[0])		name1 = "main";	cs = (CONF_SECTION *)rad_malloc(sizeof(CONF_SECTION));	memset(cs, 0, sizeof(CONF_SECTION));	cs->item.type = CONF_ITEM_SECTION;	cs->item.parent = parent;	cs->name1 = strdup(name1);	cs->name2 = (name2 && *name2) ? xstrdup(name2) : NULL;	return cs;}/* *	Free a CONF_SECTION */void cf_section_free(CONF_SECTION **cs){	CONF_ITEM	*ci, *next;	if (!cs || !*cs) return;	if ((*cs)->variables) {		cf_section_parse_free((*cs)->base, (*cs)->variables);	}	for (ci = (*cs)->children; ci; ci = next) {		next = ci->next;		if (ci->type==CONF_ITEM_PAIR) {			CONF_PAIR *pair = cf_itemtopair(ci);			cf_pair_free(&pair);		} else {			CONF_SECTION *section = cf_itemtosection(ci);			cf_section_free(&section);		}	}	if ((*cs)->name1)		free((*cs)->name1);	if ((*cs)->name2)		free((*cs)->name2);	/*	 * And free the section	 */#ifndef NDEBUG	memset(*cs, 0, sizeof(*cs));#endif	free(*cs);	*cs = NULL;}/* *	Add an item to a configuration section. */static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci_new){	CONF_ITEM *ci;	for (ci = cs->children; ci && ci->next; ci = ci->next)		;	if (ci == NULL)		cs->children = ci_new;	else		ci->next = ci_new;}/* *	Expand the variables in an input string. */static const char *cf_expand_variables(const char *cf, int *lineno,				       CONF_SECTION *outercs,				       char *output, const char *input){	char *p;	const char *end, *ptr;	char name[8192];	CONF_SECTION *parentcs;	/*	 *	Find the master parent conf section.	 *	We can't use mainconfig.config, because we're in the	 *	process of re-building it, and it isn't set up yet...	 */	for (parentcs = outercs;	     parentcs->item.parent != NULL;	     parentcs = parentcs->item.parent) {		/* do nothing */	}	p = output;	ptr = input;	while (*ptr) {		/*		 *	Ignore anything other than "${"		 */		if ((*ptr == '$') && (ptr[1] == '{')) {			int up;			CONF_PAIR *cp;			CONF_SECTION *cs;			/*			 *	Look for trailing '}', and log a			 *	warning for anything that doesn't match,			 *	and exit with a fatal error.			 */			end = strchr(ptr, '}');			if (end == NULL) {				*p = '\0';				radlog(L_INFO, "%s[%d]: Variable expansion missing }",				       cf, *lineno);				return NULL;			}			ptr += 2;			cp = NULL;			up = 0;			/*			 *	${.foo} means "foo from the current section"			 */			if (*ptr == '.') {				up = 1;				cs = outercs;				ptr++;				/*				 *	${..foo} means "foo from the section				 *	enclosing this section" (etc.)				 */				while (*ptr == '.') {					if (cs->item.parent)						cs = cs->item.parent;					ptr++;				}			} else {				const char *q;				/*				 *	${foo} is local, with				 *	main as lower priority				 */				cs = outercs;				/*				 *	${foo.bar.baz} is always rooted				 *	from the top.				 */				for (q = ptr; *q && q != end; q++) {					if (*q == '.') {						cs = parentcs;						up = 1;						break;					}				}			}			while (cp == NULL) {				char *q;				/*				 *	Find the next section.				 */				for (q = name;				     (*ptr != 0) && (*ptr != '.') &&					     (ptr != end);				     q++, ptr++) {					*q = *ptr;				}				*q = '\0';				/*				 *	The character is a '.', find a				 *	section (as the user has given				 *	us a subsection to find)				 */				if (*ptr == '.') {					CONF_SECTION *next;					ptr++;	/* skip the period */					/*					 *	Find the sub-section.					 */					next = cf_section_sub_find(cs, name);					if (next == NULL) {						radlog(L_ERR, "config: No such section %s in variable %s", name, input);						return NULL;					}					cs = next;				} else { /* no period, must be a conf-part */					/*					 *	Find in the current referenced					 *	section.					 */					cp = cf_pair_find(cs, name);					if (cp == NULL) {						/*						 *	It it was NOT ${..foo}						 *	then look in the						 *	top-level config items.						 */						if (!up) cp = cf_pair_find(parentcs, name);					}					if (cp == NULL) {						radlog(L_ERR, "config: No such entry %s for string %s", name, input);						return NULL;					}				}			} /* until cp is non-NULL */			/*			 *  Substitute the value of the variable.			 */			strcpy(p, cp->value);			p += strlen(p);			ptr = end + 1;		} else if (memcmp(ptr, "$ENV{", 5) == 0) {			char *env;			ptr += 5;			/*			 *	Look for trailing '}', and log a			 *	warning for anything that doesn't match,			 *	and exit with a fatal error.			 */			end = strchr(ptr, '}');			if (end == NULL) {				*p = '\0';				radlog(L_INFO, "%s[%d]: Environment variable expansion missing }",				       cf, *lineno);				return NULL;			}			memcpy(name, ptr, end - ptr);			name[end - ptr] = '\0';			/*			 *	Get the environment variable.			 *	If none exists, then make it an empty string.			 */			env = getenv(name);			if (env == NULL) {				*name = '\0';				env = name;			}			strcpy(p, env);			p += strlen(p);			ptr = end + 1;		} else {			/*			 *	Copy it over verbatim.			 */			*(p++) = *(ptr++);		}	} /* loop over all of the input string. */	*p = '\0';	return output;}/* *	Parse a configuration section into user-supplied variables. */int cf_section_parse(CONF_SECTION *cs, void *base,		     const CONF_PARSER *variables){	int i;	int rcode;	char **q;	CONF_PAIR *cp;	CONF_SECTION *subsection;	uint32_t ipaddr;	char buffer[8192];	const char *value;	void *data;	/*	 *	Handle the user-supplied variables.	 */	for (i = 0; variables[i].name != NULL; i++) {		value = variables[i].dflt;		if (variables[i].data) {			data = variables[i].data; /* prefer this. */		} else if (base) {			data = ((char *)base) + variables[i].offset;		} else {			data = variables[i].data;		}		cp = cf_pair_find(cs, variables[i].name);		if (cp) {			value = cp->value;		}		switch (variables[i].type)		{		case PW_TYPE_SUBSECTION:			subsection = cf_section_sub_find(cs,variables[i].name);			/*			 *	If the configuration section is NOT there,			 *	then ignore it.			 *			 *	FIXME! This is probably wrong... we should			 *	probably set the items to their default values.			 */			if (subsection == NULL) {				break;			}			rcode = cf_section_parse(subsection, base,						 (CONF_PARSER *) data);			if (rcode < 0) {				cf_section_parse_free(base, variables);				return -1;			}			break;		case PW_TYPE_BOOLEAN:			/*			 *	Allow yes/no and on/off			 */			if ((strcasecmp(value, "yes") == 0) ||					(strcasecmp(value, "on") == 0)) {				*(int *)data = 1;			} else if ((strcasecmp(value, "no") == 0) ||						(strcasecmp(value, "off") == 0)) {				*(int *)data = 0;			} else {				*(int *)data = 0;				radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, variables[i].name);				cf_section_parse_free(base, variables);				return -1;			}			DEBUG2(" %s: %s = %s",					cs->name1,					variables[i].name,					value);			break;		case PW_TYPE_INTEGER:			*(int *)data = strtol(value, 0, 0);			DEBUG2(" %s: %s = %d",					cs->name1,					variables[i].name,					*(int *)data);			break;		case PW_TYPE_STRING_PTR:			q = (char **) data;			if (*q != NULL) {				free(*q);			}			/*			 *	Expand variables while parsing,			 *	but ONLY expand ones which haven't already			 *	been expanded.			 */			if (value && (value == variables[i].dflt)) {				value = cf_expand_variables("?",							    &cs->item.lineno,							    cs, buffer, value);				if (!value) {					cf_section_parse_free(base, variables);					return -1;				}			}			DEBUG2(" %s: %s = \"%s\"",					cs->name1,					variables[i].name,					value ? value : "(null)");			*q = value ? strdup(value) : NULL;

⌨️ 快捷键说明

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