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

📄 xlat.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * xlat.c	Translate strings.  This is the first version of xlat * 		incorporated to RADIUS * * Version:	$Id: xlat.c,v 1.135 2008/03/16 17:59:29 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  Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: xlat.c,v 1.135 2008/03/16 17:59:29 aland Exp $")#include	<freeradius-devel/radiusd.h>#include	<freeradius-devel/rad_assert.h>#include	<ctype.h>typedef struct xlat_t {	char		module[MAX_STRING_LEN];	int		length;	void		*instance;	RAD_XLAT_FUNC	do_xlat;	int		internal;	/* not allowed to re-define these */} xlat_t;static rbtree_t *xlat_root = NULL;/* *	Define all xlat's in the structure. */static const char * const internal_xlat[] = {"check",					     "request",					     "reply",					     "proxy-request",					     "proxy-reply",					     "outer.request",					     "outer.reply",					     NULL};#if REQUEST_MAX_REGEX > 8#error Please fix the following line#endifstatic const int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };	/* up to 8 for regex *//* *	Convert the value on a VALUE_PAIR to string */static int valuepair2str(char * out,int outlen,VALUE_PAIR * pair,			 int type, RADIUS_ESCAPE_STRING func){	char buffer[MAX_STRING_LEN * 4];	if (pair != NULL) {		vp_prints_value(buffer, sizeof(buffer), pair, -1);		return func(out, outlen, buffer);	}	switch (type) {	case PW_TYPE_STRING :		strlcpy(out,"_",outlen);		break;	case PW_TYPE_INTEGER :		strlcpy(out,"0",outlen);		break;	case PW_TYPE_IPADDR :		strlcpy(out,"?.?.?.?",outlen);		break;	case PW_TYPE_IPV6ADDR :		strlcpy(out,":?:",outlen);		break;	case PW_TYPE_DATE :		strlcpy(out,"0",outlen);		break;	default :		strlcpy(out,"unknown_type",outlen);	}	return strlen(out);}/* *	Dynamically translate for check:, request:, reply:, etc. */static size_t xlat_packet(void *instance, REQUEST *request,			  char *fmt, char *out, size_t outlen,			  RADIUS_ESCAPE_STRING func){	DICT_ATTR	*da;	VALUE_PAIR	*vp;	VALUE_PAIR	*vps = NULL;	RADIUS_PACKET	*packet = NULL;	switch (*(int*) instance) {	case 0:		vps = request->config_items;		break;	case 1:		vps = request->packet->vps;		packet = request->packet;		break;	case 2:		vps = request->reply->vps;		packet = request->reply;		break;	case 3:		if (request->proxy) vps = request->proxy->vps;		packet = request->proxy;		break;	case 4:		if (request->proxy_reply) vps = request->proxy_reply->vps;		packet = request->proxy_reply;		break;	case 5:		if (request->parent) {			vps = request->parent->packet->vps;			packet = request->parent->packet;		}		break;				case 6:		if (request->parent && request->parent->reply) {			vps = request->parent->reply->vps;			packet = request->parent->reply;		}		break;				default:		/* WTF? */		return 0;	}	/*	 *	The "format" string is the attribute name.	 */	da = dict_attrbyname(fmt);	if (!da) {		size_t count;		const char *p = strchr(fmt, '[');		char buffer[256];		if (!p) return 0;		if (strlen(fmt) > sizeof(buffer)) return 0;		strlcpy(buffer, fmt, p - fmt + 1);		da = dict_attrbyname(buffer);		if (!da) return 0;		/*		 *	%{Attribute-Name[#]} returns the count of		 *	attributes of that name in the list.		 */		if ((p[1] == '#') && (p[2] == ']')) {			count = 0;			for (vp = pairfind(vps, da->attr);			     vp != NULL;			     vp = pairfind(vp->next, da->attr)) {				count++;			}			snprintf(out, outlen, "%d", count);			return strlen(out);		}		/*		 *	%{Attribute-Name[*]} returns ALL of the		 *	the attributes, separated by a newline.		 */		if ((p[1] == '*') && (p[2] == ']')) {			int total = 0;			for (vp = pairfind(vps, da->attr);			     vp != NULL;			     vp = pairfind(vp->next, da->attr)) {				count = valuepair2str(out, outlen - 1, vp, da->type, func);				rad_assert(count <= outlen);				total += count + 1;				outlen -= (count + 1);				out += count;				*(out++) = '\n';				if (outlen == 0) break;			}			return total;		}		count = atoi(p + 1);		/*		 *	Skip the numbers.		 */		p += 1 + strspn(p + 1, "0123456789");		if (*p != ']') {			DEBUG2("xlat: Invalid array reference in string at %s %s",			       fmt, p);			return 0;		}		/*		 *	Find the N'th value.		 */		for (vp = pairfind(vps, da->attr);		     vp != NULL;		     vp = pairfind(vp->next, da->attr)) {			if (count == 0) break;			count--;		}		/*		 *	Non-existent array reference.		 */		if (!vp) return 0;		return valuepair2str(out, outlen, vp, da->type, func);	}	vp = pairfind(vps, da->attr);	if (!vp) {		/*		 *	Some "magic" handlers, which are never in VP's, but		 *	which are in the packet.		 *		 *	FIXME: We should really do this in a more		 *	intelligent way...		 */		if (packet) {			VALUE_PAIR localvp;			memset(&localvp, 0, sizeof(localvp));			switch (da->attr) {			case PW_PACKET_TYPE:			{				DICT_VALUE *dval;				dval = dict_valbyattr(da->attr, packet->code);				if (dval) {					snprintf(out, outlen, "%s", dval->name);				} else {					snprintf(out, outlen, "%d", packet->code);				}				return strlen(out);			}			break;			case PW_CLIENT_SHORTNAME:				if (request->client && request->client->shortname) {					strlcpy(out, request->client->shortname, outlen);				} else {					strlcpy(out, "<UNKNOWN-CLIENT>", outlen);				}				return strlen(out);			case PW_CLIENT_IP_ADDRESS: /* the same as below */			case PW_PACKET_SRC_IP_ADDRESS:				if (packet->src_ipaddr.af != AF_INET) {					return 0;				}				localvp.attribute = da->attr;				localvp.vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;				break;			case PW_PACKET_DST_IP_ADDRESS:				if (packet->dst_ipaddr.af != AF_INET) {					return 0;				}				localvp.attribute = da->attr;				localvp.vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;				break;			case PW_PACKET_SRC_PORT:				localvp.attribute = da->attr;				localvp.vp_integer = packet->src_port;				break;			case PW_PACKET_DST_PORT:				localvp.attribute = da->attr;				localvp.vp_integer = packet->dst_port;				break;			case PW_PACKET_AUTHENTICATION_VECTOR:				localvp.attribute = da->attr;				memcpy(localvp.vp_strvalue, packet->vector,				       sizeof(packet->vector));				localvp.length = sizeof(packet->vector);				break;				/*				 *	Authorization, accounting, etc.				 */			case PW_REQUEST_PROCESSING_STAGE:				if (request->component) {					strlcpy(out, request->component, outlen);				} else {					strlcpy(out, "server_core", outlen);				}				return strlen(out);			case PW_PACKET_SRC_IPV6_ADDRESS:				if (packet->src_ipaddr.af != AF_INET6) {					return 0;				}				localvp.attribute = da->attr;				memcpy(localvp.vp_strvalue,				       &packet->src_ipaddr.ipaddr.ip6addr,				       sizeof(packet->src_ipaddr.ipaddr.ip6addr));				break;			case PW_PACKET_DST_IPV6_ADDRESS:				if (packet->dst_ipaddr.af != AF_INET6) {					return 0;				}				localvp.attribute = da->attr;				memcpy(localvp.vp_strvalue,				       &packet->dst_ipaddr.ipaddr.ip6addr,				       sizeof(packet->dst_ipaddr.ipaddr.ip6addr));				break;			case PW_VIRTUAL_SERVER:				if (!request->server) return 0;				snprintf(out, outlen, "%s", request->server);				return strlen(out);				break;			case PW_MODULE_RETURN_CODE:				localvp.attribute = da->attr;				/*				 *	See modcall.c for a bit of a hack.				 */				localvp.vp_integer = request->simul_max;				break;			default:				return 0; /* not found */				break;			}			localvp.type = da->type;			return valuepair2str(out, outlen, &localvp,					     da->type, func);		}		/*		 *	Not found, die.		 */		return 0;	}	if (!vps) return 0;	/* silently fail */	/*	 *	Convert the VP to a string, and return it.	 */	return valuepair2str(out, outlen, vp, da->type, func);}#ifdef HAVE_REGEX_H/* *	Pull %{0} to %{8} out of the packet. */static size_t xlat_regex(void *instance, REQUEST *request,			 char *fmt, char *out, size_t outlen,			 RADIUS_ESCAPE_STRING func){	char *regex;	/*	 *	We cheat: fmt is "0" to "8", but those numbers	 *	are already in the "instance".	 */	fmt = fmt;		/* -Wunused */	func = func;		/* -Wunused FIXME: do escaping? */	regex = request_data_reference(request, request,				 REQUEST_DATA_REGEX | *(int *)instance);	if (!regex) return 0;	/*	 *	Copy UP TO "freespace" bytes, including	 *	a zero byte.	 */	strlcpy(out, regex, outlen);	return strlen(out);}#endif				/* HAVE_REGEX_H *//* *	Compare two xlat_t structs, based ONLY on the module name. */static int xlat_cmp(const void *a, const void *b){	if (((const xlat_t *)a)->length != ((const xlat_t *)b)->length) {		return ((const xlat_t *)a)->length - ((const xlat_t *)b)->length;	}	return memcmp(((const xlat_t *)a)->module,		      ((const xlat_t *)b)->module,		      ((const xlat_t *)a)->length);}/* *	find the appropriate registered xlat function. */static xlat_t *xlat_find(const char *module){	xlat_t my_xlat;	/*	 *	Look for dictionary attributes first.	 */	if ((dict_attrbyname(module) != NULL) ||	    (strchr(module, '[') != NULL)) {		module = "request";	}	strlcpy(my_xlat.module, module, sizeof(my_xlat.module));	my_xlat.length = strlen(my_xlat.module);	return rbtree_finddata(xlat_root, &my_xlat);}/* *      Register an xlat function. */int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance){	xlat_t	*c;	xlat_t	my_xlat;	if ((module == NULL) || (strlen(module) == 0)) {		DEBUG("xlat_register: Invalid module name");		return -1;	}	/*	 *	First time around, build up the tree...	 *	 *	FIXME: This code should be hoisted out of this function,	 *	and into a global "initialization".  But it isn't critical...	 */	if (!xlat_root) {		int i;#ifdef HAVE_REGEX_H		char buffer[2];#endif		xlat_root = rbtree_create(xlat_cmp, free, 0);		if (!xlat_root) {			DEBUG("xlat_register: Failed to create tree.");			return -1;		}		/*		 *	Register the internal packet xlat's.		 */		for (i = 0; internal_xlat[i] != NULL; i++) {			xlat_register(internal_xlat[i], xlat_packet, &xlat_inst[i]);			c = xlat_find(internal_xlat[i]);			rad_assert(c != NULL);			c->internal = TRUE;		}		/*		 *	New name: "control"		 */		xlat_register("control", xlat_packet, &xlat_inst[0]);		c = xlat_find("control");		rad_assert(c != NULL);		c->internal = TRUE;#ifdef HAVE_REGEX_H		/*		 *	Register xlat's for regexes.		 */		buffer[1] = '\0';		for (i = 0; i <= REQUEST_MAX_REGEX; i++) {			buffer[0] = '0' + i;			xlat_register(buffer, xlat_regex, &xlat_inst[i]);			c = xlat_find(buffer);			rad_assert(c != NULL);			c->internal = TRUE;		}#endif /* HAVE_REGEX_H */	}	/*	 *	If it already exists, replace the instance.	 */	strlcpy(my_xlat.module, module, sizeof(my_xlat.module));	my_xlat.length = strlen(my_xlat.module);	c = rbtree_finddata(xlat_root, &my_xlat);	if (c) {		if (c->internal) {			DEBUG("xlat_register: Cannot re-define internal xlat");			return -1;		}		c->do_xlat = func;		c->instance = instance;		return 0;	}	/*	 *	Doesn't exist.  Create it.	 */	c = rad_malloc(sizeof(*c));	memset(c, 0, sizeof(*c));	c->do_xlat = func;	strlcpy(c->module, module, sizeof(c->module));	c->length = strlen(c->module);	c->instance = instance;	rbtree_insert(xlat_root, c);	return 0;}/* *      Unregister an xlat function. * *	We can only have one function to call per name, so the *	passing of "func" here is extraneous. */void xlat_unregister(const char *module, RAD_XLAT_FUNC func){	rbnode_t	*node;	xlat_t		my_xlat;	func = func;		/* -Wunused */	if (!module) return;	strlcpy(my_xlat.module, module, sizeof(my_xlat.module));	my_xlat.length = strlen(my_xlat.module);	node = rbtree_find(xlat_root, &my_xlat);	if (!node) return;	rbtree_delete(xlat_root, node);}/* *	De-register all xlat functions, *	used mainly for debugging. */void xlat_free(void){	rbtree_free(xlat_root);}/* *	Decode an attribute name into a string. */static void decode_attribute(const char **from, char **to, int freespace,			     int *open_p, REQUEST *request,			     RADIUS_ESCAPE_STRING func){	int	do_length = 0;	char	xlat_name[128];	char	*xlat_string = NULL; /* can be large */	int	free_xlat_string = FALSE;	const char *p;	char *q, *pa;	int found=0, retlen=0;	int openbraces = *open_p;	const xlat_t *c;

⌨️ 快捷键说明

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