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

📄 valuepair.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		return NULL;	}	size = strlen(value + 2);	/*	 *	We may be reading something like Attr-5.  i.e.	 *	who-ever wrote the text didn't understand it, but we	 *	do.	 */	switch (vp->type) {	default:		if (size == (vp->length * 2)) break;		vp->type = PW_TYPE_OCTETS;		/* FALL-THROUGH */			case PW_TYPE_STRING:	case PW_TYPE_OCTETS:	case PW_TYPE_ABINARY:		vp->length = size >> 1;		break;	}	if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {		librad_log("Invalid hex string");		free(vp);		return NULL;	}	/*	 *	Move contents around based on type.  This is	 *	to work around the historical use of "lvalue".	 */	switch (vp->type) {	case PW_TYPE_DATE:	case PW_TYPE_IPADDR:	case PW_TYPE_INTEGER:		memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));		vp->vp_strvalue[0] = '\0';		break;			default:		break;	}       	vp->operator = (operator == 0) ? T_OP_EQ : operator;	return vp;}/* *	Create a VALUE_PAIR from an ASCII attribute and value. */VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator){	DICT_ATTR	*da;	VALUE_PAIR	*vp;	char            *tc, *ts;	signed char     tag;	int             found_tag;#ifdef HAVE_REGEX_H	int		res;	regex_t		cre;#endif	char		buffer[64];	const char	*attrname = attribute;	/*	 *    Check for tags in 'Attribute:Tag' format.	 */	found_tag = 0;	tag = 0;	ts = strrchr(attribute, ':');	if (ts && !ts[1]) {		librad_log("Invalid tag for attribute %s", attribute);		return NULL;	}	if (ts && ts[1]) {		strlcpy(buffer, attribute, sizeof(buffer));		attrname = buffer;		ts = strrchr(attrname, ':');	         /* Colon found with something behind it */	         if (ts[1] == '*' && ts[2] == 0) {		         /* Wildcard tag for check items */		         tag = TAG_ANY;			 *ts = 0;		 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {		         /* It's not a wild card tag */		         tag = strtol(ts + 1, &tc, 0);			 if (tc && !*tc && TAG_VALID_ZERO(tag))				 *ts = 0;			 else tag = 0;		 } else {			 librad_log("Invalid tag for attribute %s", attribute);			 return NULL;		 }		 found_tag = 1;	}	/*	 *	It's not found in the dictionary, so we use	 *	another method to create the attribute.	 */	if ((da = dict_attrbyname(attrname)) == NULL) {		return pairmake_any(attrname, value, operator);	}	if ((vp = pairalloc(da)) == NULL) {		librad_log("out of memory");		return NULL;	}	vp->operator = (operator == 0) ? T_OP_EQ : operator;	/*      Check for a tag in the 'Merit' format of:	 *      :Tag:Value.  Print an error if we already found	 *      a tag in the Attribute.	 */	if (value && (*value == ':' && da->flags.has_tag)) {	        /* If we already found a tag, this is invalid */	        if(found_tag) {		        pairbasicfree(vp);			librad_log("Duplicate tag %s for attribute %s",				   value, vp->name);			DEBUG("Duplicate tag %s for attribute %s\n",				   value, vp->name);			return NULL;		}	        /* Colon found and attribute allows a tag */	        if (value[1] == '*' && value[2] == ':') {		       /* Wildcard tag for check items */		       tag = TAG_ANY;		       value += 3;		} else {	               /* Real tag */		       tag = strtol(value + 1, &tc, 0);		       if (tc && *tc==':' && TAG_VALID_ZERO(tag))			    value = tc + 1;		       else tag = 0;		}		found_tag = 1;	}	if (found_tag) {	  vp->flags.tag = tag;	}	switch (vp->operator) {	default:		break;		/*		 *      For =* and !* operators, the value is irrelevant		 *      so we return now.		 */	case T_OP_CMP_TRUE:	case T_OP_CMP_FALSE:		vp->vp_strvalue[0] = '\0';		vp->length = 0;	        return vp;		break;		/*		 *	Regular expression comparison of integer attributes		 *	does a STRING comparison of the names of their		 *	integer attributes.		 */	case T_OP_REG_EQ:	/* =~ */	case T_OP_REG_NE:	/* !~ */		if (vp->type == PW_TYPE_INTEGER) {			return vp;		}#ifdef HAVE_REGEX_H		/*		 *	Regular expression match with no regular		 *	expression is wrong.		 */		if (!value) {			pairfree(&vp);			return NULL;		}		res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB);		if (res != 0) {			char	msg[128];			regerror(res, &cre, msg, sizeof(msg));			librad_log("Illegal regular expression in attribute: %s: %s",				vp->name, msg);			pairbasicfree(vp);			return NULL;		}		regfree(&cre);#else		librad_log("Regular expressions not enabled in this build, error in attribute %s",				vp->name);		pairbasicfree(vp);		return NULL;#endif	}	/*	 *	FIXME: if (strcasecmp(attribute, vp->name) != 0)	 *	then the user MAY have typed in the attribute name	 *	as Vendor-%d-Attr-%d, and the value MAY be octets.	 *	 *	We probably want to fix pairparsevalue to accept	 *	octets as values for any attribute.	 */	if (value && (pairparsevalue(vp, value) == NULL)) {		pairbasicfree(vp);		return NULL;	}	return vp;}/* *	[a-zA-Z0-9_-:]+ */static const int valid_attr_name[256] = {	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* *	Read a valuepair from a buffer, and advance pointer. *	Sets *eol to T_EOL if end of line was encountered. */VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol){	char		buf[64];	char		attr[64];	char		value[512], *q;	const char	*p;	FR_TOKEN	token, t, xlat;	VALUE_PAIR	*vp;	size_t		len;	*eol = T_OP_INVALID;	p = *ptr;	while ((*p == ' ') || (*p == '\t')) p++;	if (!*p) {		*eol = T_OP_INVALID;		librad_log("No token read where we expected an attribute name");		return NULL;	}	if (*p == '#') {		*eol = T_HASH;		librad_log("Read a comment instead of a token");		return NULL;	}	q = attr;	for (len = 0; len < sizeof(attr); len++) {		if (valid_attr_name[(int)*p]) {			*q++ = *p++;			continue;		}		break;	}	if (len == sizeof(attr)) {		*eol = T_OP_INVALID;		librad_log("Attribute name is too long");		return NULL;	}	/*	 *	We may have Foo-Bar:= stuff, so back up.	 */	if (attr[len - 1] == ':') {		p--;		len--;	}	attr[len] = '\0';	*ptr = p;	/* Now we should have an operator here. */	token = gettoken(ptr, buf, sizeof(buf));	if (token < T_EQSTART || token > T_EQEND) {		librad_log("expecting operator");		return NULL;	}	/* Read value.  Note that empty string values are allowed */	xlat = gettoken(ptr, value, sizeof(value));	if (xlat == T_EOL) {		librad_log("failed to get value");		return NULL;	}	/*	 *	Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH	 */	p = *ptr;	t = gettoken(&p, buf, sizeof(buf));	if (t != T_EOL && t != T_COMMA && t != T_HASH) {		librad_log("Expected end of line or comma");		return NULL;	}	*eol = t;	if (t == T_COMMA) {		*ptr = p;	}	vp = NULL;	switch (xlat) {		/*		 *	Make the full pair now.		 */	default:		vp = pairmake(attr, value, token);		break;		/*		 *	Perhaps do xlat's		 */	case T_DOUBLE_QUOTED_STRING:		p = strchr(value, '%');		if (p && (p[1] == '{')) {			if (strlen(value) >= sizeof(vp->vp_strvalue)) {				librad_log("Value too long");				return NULL;			}			vp = pairmake(attr, NULL, token);			if (!vp) {				*eol = T_OP_INVALID;				return NULL;			}			strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));			vp->flags.do_xlat = 1;			vp->length = 0;		} else {			vp = pairmake(attr, value, token);		}		break;		/*		 *	Mark the pair to be allocated later.		 */	case T_BACK_QUOTED_STRING:		if (strlen(value) >= sizeof(vp->vp_strvalue)) {			librad_log("Value too long");			return NULL;		}		vp = pairmake(attr, NULL, token);		if (!vp) {			*eol = T_OP_INVALID;			return NULL;		}		vp->flags.do_xlat = 1;		strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));		vp->length = 0;		break;	}	/*	 *	If we didn't make a pair, return an error.	 */	if (!vp) {		*eol = T_OP_INVALID;		return NULL;	}	return vp;}/* *	Read one line of attribute/value pairs. This might contain *	multiple pairs seperated by comma's. */FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair){	VALUE_PAIR	*vp;	const char	*p;	FR_TOKEN	last_token = T_OP_INVALID;	FR_TOKEN	previous_token;	/*	 *	We allow an empty line.	 */	if (buffer[0] == 0)		return T_EOL;	p = buffer;	do {		previous_token = last_token;		if ((vp = pairread(&p, &last_token)) == NULL) {			return last_token;		}		pairadd(first_pair, vp);	} while (*p && (last_token == T_COMMA));	/*	 *	Don't tell the caller that there was a comment.	 */	if (last_token == T_HASH) {		return previous_token;	}	/*	 *	And return the last token which we read.	 */	return last_token;}/* *	Read valuepairs from the fp up to End-Of-File. * *	Hmm... this function is only used by radclient.. */VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix){	char buf[8192];	FR_TOKEN last_token = T_EOL;	VALUE_PAIR *vp;	VALUE_PAIR *list;	int error = 0;	list = NULL;	while (!error && fgets(buf, sizeof(buf), fp) != NULL) {		/*		 *      If we get a '\n' by itself, we assume that's		 *      the end of that VP		 */		if ((buf[0] == '\n') && (list)) {			return list;		}		if ((buf[0] == '\n') && (!list)) {			continue;		}		/*		 *	Comments get ignored		 */		if (buf[0] == '#') continue;		/*		 *	Read all of the attributes on the current line.		 */		vp = NULL;		last_token = userparse(buf, &vp);		if (!vp) {			if (last_token != T_EOL) {				librad_perror("%s", errprefix);				error = 1;				break;			}			break;		}		pairadd(&list, vp);		buf[0] = '\0';	}	if (error) pairfree(&list);	*pfiledone = 1;	return error ? NULL: list;}/* *	Compare two pairs, using the operator from "one". * *	i.e. given two attributes, it does: * *	(two->data) (one->operator) (one->data) * *	e.g. "foo" != "bar" * *	Returns true (comparison is true), or false (comparison is not true); */int paircmp(VALUE_PAIR *one, VALUE_PAIR *two){	int compare;	switch (one->operator) {	case T_OP_CMP_TRUE:		return (two != NULL);	case T_OP_CMP_FALSE:		return (two == NULL);		/*		 *	One is a regex, compile it, print two to a string,		 *	and then do string comparisons.		 */	case T_OP_REG_EQ:	case T_OP_REG_NE:#ifndef HAVE_REGEX_H		return -1;#else		{			regex_t reg;			char buffer[MAX_STRING_LEN * 4 + 1];			compare = regcomp(&reg, one->vp_strvalue,					  REG_EXTENDED);			if (compare != 0) {				regerror(compare, &reg, buffer, sizeof(buffer));				librad_log("Illegal regular expression in attribute: %s: %s",					   one->name, buffer);				return -1;			}			vp_prints_value(buffer, sizeof(buffer), two, 0);			/*			 *	Don't care about substring matches,			 *	oh well...			 */			compare = regexec(&reg, buffer, 0, NULL, 0);			regfree(&reg);			if (one->operator == T_OP_REG_EQ) return (compare == 0);			return (compare != 0);		}#endif	default:		/* we're OK */		break;	}	/*	 *	After doing the previous check for special comparisons,	 *	do the per-type comparison here.	 */	switch (one->type) {	case PW_TYPE_ABINARY:	case PW_TYPE_OCTETS:	{		size_t length;		if (one->length < two->length) {			length = one->length;		} else {			length = two->length;		}		if (length) {			compare = memcmp(two->vp_octets, one->vp_octets,					 length);			if (compare != 0) break;		}		/*		 *	Contents are the same.  The return code		 *	is therefore the difference in lengths.		 *		 *	i.e. "0x00" is smaller than "0x0000"		 */		compare = two->length - one->length;	}		break;	case PW_TYPE_STRING:		compare = strcmp(two->vp_strvalue, one->vp_strvalue);		break;	case PW_TYPE_BYTE:	case PW_TYPE_SHORT:	case PW_TYPE_INTEGER:	case PW_TYPE_DATE:		compare = two->vp_integer - one->vp_integer;		break;	case PW_TYPE_IPADDR:		compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);		break;	case PW_TYPE_IPV6ADDR:		compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,				 sizeof(two->vp_ipv6addr));		break;	case PW_TYPE_IPV6PREFIX:		compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,				 sizeof(two->vp_ipv6prefix));		break;	case PW_TYPE_IFID:		compare = memcmp(&two->vp_ifid, &one->vp_ifid,				 sizeof(two->vp_ifid));		break;	default:		return 0;	/* unknown type */	}	/*	 *	Now do the operator comparison.	 */	switch (one->operator) {	case T_OP_CMP_EQ:		return (compare == 0);	case T_OP_NE:		return (compare != 0);	case T_OP_LT:		return (compare < 0);	case T_OP_GT:		return (compare > 0);	case T_OP_LE:		return (compare <= 0);	case T_OP_GE:		return (compare >= 0);	default:		return 0;	}	return 0;}

⌨️ 快捷键说明

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