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

📄 conffile.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			*q = '\0';			next = cf_section_sub_find(cs, p);			*q = '.';		}		if (!next) break; /* it MAY be a pair in this section! */		cs = next;		p = q + 1;	}	if (!*p) goto no_such_item; retry:	/*	 *	Find it in the current referenced	 *	section.	 */	cp = cf_pair_find(cs, p);	if (cp) return cf_pairtoitem(cp);	next = cf_section_sub_find(cs, p);	if (next) return cf_sectiontoitem(next);		/*	 *	"foo" is "in the current section, OR in main".	 */	if ((p == name) && (cs != parentcs)) {		cs = parentcs;		goto retry;	}no_such_item:	DEBUG2("WARNING: No such configuration item %s", ptr);	return NULL;}CONF_SECTION *cf_top_section(CONF_SECTION *cs){	while (cs->item.parent != NULL) {		cs = cs->item.parent;	}	return cs;}/* *	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;	const CONF_SECTION *parentcs;	char name[8192];	/*	 *	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...	 */	parentcs = cf_top_section(outercs);	p = output;	ptr = input;	while (*ptr) {		/*		 *	Ignore anything other than "${"		 */		if ((*ptr == '$') && (ptr[1] == '{')) {			CONF_ITEM *ci;			CONF_PAIR *cp;			/*			 *	FIXME: Add support for ${foo:-bar},			 *	like in xlat.c			 */			/*			 *	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;			/*			 *	Can't really happen because input lines are			 *	capped at 8k, which is sizeof(name)			 */			if ((size_t) (end - ptr) >= sizeof(name)) {				radlog(L_ERR, "%s[%d]: Reference string is too large",				       cf, *lineno);				return NULL;			}			memcpy(name, ptr, end - ptr);			name[end - ptr] = '\0';			ci = cf_reference_item(parentcs, outercs, name);			if (!ci || (ci->type != CONF_ITEM_PAIR)) {				radlog(L_ERR, "%s[%d]: Reference \"%s\" not found",				       cf, *lineno, input);				return NULL;			}			/*			 *  Substitute the value of the variable.			 */			cp = cf_itemtopair(ci);			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;			}			/*			 *	Can't really happen because input lines are			 *	capped at 8k, which is sizeof(name)			 */			if ((size_t) (end - ptr) >= sizeof(name)) {				radlog(L_ERR, "%s[%d]: Environment variable name is too large",				       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;}/* *	Parses an item (not a CONF_ITEM) into the specified format, *	with a default value. * *	Returns -1 on error, 0 for correctly parsed, and 1 if the *	default value was used.  Note that the default value will be *	used ONLY if the CONF_PAIR is NULL. */int cf_item_parse(CONF_SECTION *cs, const char *name,		  int type, void *data, const char *dflt){	int rcode = 0;	char **q;	const char *value;	fr_ipaddr_t ipaddr;	const CONF_PAIR *cp;	char ipbuf[128];	cp = cf_pair_find(cs, name);	if (cp) {		value = cp->value;	} else if (!dflt) {		return 1;	/* nothing to parse, return default value */	} else {		rcode = 1;		value = dflt;	}	if (!value) {		return 0;	}	switch (type) {	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, name);			return -1;		}		cf_log_info(cs, "\t%s = %s", name, value);		break;	case PW_TYPE_INTEGER:		*(int *)data = strtol(value, 0, 0);		cf_log_info(cs, "\t%s = %d", name, *(int *)data);		break;	case PW_TYPE_STRING_PTR:		q = (char **) data;		if (*q != NULL) {			free(*q);		}		/*		 *	Expand variables which haven't already been		 *	expanded automagically when the configuration		 *	file was read.		 */		if (value == dflt) {			char buffer[8192];			int lineno = cs->item.lineno;			/*			 *	FIXME: sizeof(buffer)?			 */			value = cf_expand_variables("?",						    &lineno,						    cs, buffer, value);			if (!value) return -1;		}		cf_log_info(cs, "\t%s = \"%s\"", name, value ? value : "(null)");		*q = value ? strdup(value) : NULL;		break;		/*		 *	This is the same as PW_TYPE_STRING_PTR,		 *	except that we also "stat" the file, and		 *	cache the result.		 */	case PW_TYPE_FILENAME:		q = (char **) data;		if (*q != NULL) {			free(*q);		}		/*		 *	Expand variables which haven't already been		 *	expanded automagically when the configuration		 *	file was read.		 */		if (value == dflt) {			char buffer[8192];			int lineno = cs->item.lineno;			/*			 *	FIXME: sizeof(buffer)?			 */			value = cf_expand_variables("?",						    &lineno,						    cs, buffer, value);			if (!value) return -1;		}		cf_log_info(cs, "\t%s = \"%s\"", name, value ? value : "(null)");		*q = value ? strdup(value) : NULL;		/*		 *	And now we "stat" the file.		 *		 *	FIXME: This appears to leak memory on exit,		 *	and we don't use this information.  So it's		 *	commented out for now.		 */		if (0 && *q) {			struct stat buf;			if (stat(*q, &buf) == 0) {				time_t *mtime;				mtime = rad_malloc(sizeof(*mtime));				*mtime = buf.st_mtime;				/* FIXME: error? */				cf_data_add_internal(cs, *q, mtime, free,						     PW_TYPE_FILENAME);			}		}		break;	case PW_TYPE_IPADDR:		/*		 *	Allow '*' as any address		 */		if (strcmp(value, "*") == 0) {			*(uint32_t *) data = htonl(INADDR_ANY);			cf_log_info(cs, "\t%s = *", name);			break;		}		if (ip_hton(value, AF_INET, &ipaddr) < 0) {			radlog(L_ERR, "Can't find IP address for host %s", value);			return -1;		}				if (strspn(value, "0123456789.") == strlen(value)) {			cf_log_info(cs, "\t%s = %s", name, value);		} else {			cf_log_info(cs, "\t%s = %s IP address [%s]", name, value,			       ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));		}		*(uint32_t *) data = ipaddr.ipaddr.ip4addr.s_addr;		break;	case PW_TYPE_IPV6ADDR:		if (ip_hton(value, AF_INET6, &ipaddr) < 0) {			radlog(L_ERR, "Can't find IPv6 address for host %s", value);			return -1;		}		cf_log_info(cs, "\t%s = %s IPv6 address [%s]", name, value,			       ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));		memcpy(data, &ipaddr.ipaddr.ip6addr,		       sizeof(ipaddr.ipaddr.ip6addr));		break;	default:		radlog(L_ERR, "type %d not supported yet", type);		return -1;		break;	} /* switch over variable type */	return rcode;}static const char *parse_spaces = "                                                                                                                                                                                                                                                                ";/* *	Parse a configuration section into user-supplied variables. */int cf_section_parse(CONF_SECTION *cs, void *base,		     const CONF_PARSER *variables){	int i;	void *data;	cs->variables = variables; /* this doesn't hurt anything */	if (!cs->name2) {		cf_log_info(cs, "%.*s%s {", cs->depth, parse_spaces,		       cs->name1);	} else {		cf_log_info(cs, "%.*s%s %s {", cs->depth, parse_spaces,		       cs->name1, cs->name2);	}	/*	 *	Handle the known configuration parameters.	 */	for (i = 0; variables[i].name != NULL; i++) {		/*		 *	Handle subsections specially		 */		if (variables[i].type == PW_TYPE_SUBSECTION) {			CONF_SECTION *subcs;			subcs = 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 (!subcs) continue;			if (!variables[i].dflt) {				DEBUG2("Internal sanity check 1 failed in cf_section_parse");				goto error;			}			if (cf_section_parse(subcs, base,					     (const CONF_PARSER *) variables[i].dflt) < 0) {				goto error;			}			continue;		} /* else it's a CONF_PAIR */		if (variables[i].data) {			data = variables[i].data; /* prefer this. */		} else if (base) {			data = ((char *)base) + variables[i].offset;		} else {			DEBUG2("Internal sanity check 2 failed in cf_section_parse");			goto error;		}		/*		 *	Parse the pair we found, or a default value.		 */		if (cf_item_parse(cs, variables[i].name, variables[i].type,				  data, variables[i].dflt) < 0) {			goto error;		}	} /* for all variables in the configuration section */	cf_log_info(cs, "%.*s}", cs->depth, parse_spaces);	cs->base = base;	return 0; error:	cf_log_info(cs, "%.*s}", cs->depth, parse_spaces);	cf_section_parse_free(cs, base);	return -1;}/* *	Sanity check the "if" or "elsif", presuming that the first '(' *	has already been eaten. * *	We're not really parsing it here, just checking if it's mostly *	well-formed. */static int condition_looks_ok(const char **ptr){	int num_braces = 1;	int quote = 0;	const char *p = *ptr;	while (*p) {		if (quote) {			if (*p == quote) {				p++;				quote = 0;				continue;			}			if (*p == '\\') {				if (!p[1]) {					return 0; /* no trailing slash */				}				p += 2;				continue;			}			p++;			continue;		}		switch (*p) {		case '\\':			if (!p[1]) {				return 0; /* no trailing slash */			}			p += 2;			continue;		case '(':			num_braces++;			p++;			continue;		case ')':			if (num_braces == 1) {				const char *q = p + 1;				/*				 *	Validate that there isn't much				 *	else after the closing brace.				 */				while ((*q == ' ') || (*q == '\t')) q++;				/*				 *	Parse error.				 */				if (*q != '{') {					return 0;				}				*ptr = p + 1; /* include the trailing ')' */				return 1;			}			num_braces--;			p++;			continue;		case '"':		case '\'':		case '/':		case '`':			quote = *p;			/* FALL-THROUGH */		default:			p++;			break;		}	}	return 0;}static const char *cf_local_file(CONF_SECTION *cs, const char *local,				 char *buffer, size_t bufsize){	size_t dirsize;	const char *p;	CONF_SECTION *parentcs = cf_top_section(cs);	p = strrchr(parentcs->item.filename, FR_DIR_SEP);	if (!p) return local;	dirsize = (p - parentcs->item.filename) + 1;	if ((dirsize + strlen(local)) >= bufsize) {		return NULL;	}	memcpy(buffer, parentcs->item.filename, dirsize);	strlcpy(buffer + dirsize, local, bufsize - dirsize);	return buffer;}/* *	Read a part of the config file. */static int cf_section_read(const char *filename, int *lineno, FILE *fp,			   CONF_SECTION *current){	CONF_SECTION *this, *css;	CONF_PAIR *cpn;	const char *ptr;	const char *value;	char buf[8192];	char buf1[8192];	char buf2[8192];	char buf3[8192];	int t1, t2, t3;	char *cbuf = buf;	size_t len;	this = current;		/* add items here */	/*	 *	Read, checking for line continuations ('\\' at EOL)	 */	for (;;) {		int eof;		/*		 *	Get data, and remember if we are at EOF.		 */		eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL);		(*lineno)++;		/*		 *	We read the entire 8k worth of data: complain.		 *	Note that we don't care if the last character		 *	is \n: it's still forbidden.  This means that		 *	the maximum allowed length of text is 8k-1, which		 *	should be plenty.		 */		len = strlen(cbuf);		if ((cbuf + len + 1) >= (buf + sizeof(buf))) {			radlog(L_ERR, "%s[%d]: Line too long",			       filename, *lineno);			return -1;		}

⌨️ 快捷键说明

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