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

📄 filters.c

📁 radius服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * filters.c	Routines to parse Ascend's filter attributes. * * Version:	$Id: filters.c,v 1.36 2004/02/26 19:04:20 aland Exp $ * *   This library is free software; you can redistribute it and/or *   modify it under the terms of the GNU Lesser General Public *   License as published by the Free Software Foundation; either *   version 2.1 of the License, or (at your option) any later version. * *   This library 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 *   Lesser General Public License for more details. * *   You should have received a copy of the GNU Lesser General Public *   License along with this library; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * * Copyright 2003  The FreeRADIUS server project */static const char rcsid[] = "$Id: filters.c,v 1.36 2004/02/26 19:04:20 aland Exp $";#include <string.h>#include <ctype.h>#include <stdlib.h>#include "libradius.h"#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif/* * Two types of filters are supported, GENERIC and IP.  The identifiers * are: */#define RAD_FILTER_GENERIC	0#define RAD_FILTER_IP		1#define RAD_FILTER_IPX		2/* * Generic filters mask and match up to RAD_MAX_FILTER_LEN bytes * starting at some offset.  The length is: */#define RAD_MAX_FILTER_LEN	6/* * ASCEND extensions for ABINARY filters */#define IPX_NODE_ADDR_LEN		6#if ! defined( FALSE )# define FALSE		0# define TRUE		(! FALSE)#endif/* *	ascend_ip_filter_t * *	The binary format of an IP filter.  ALL fields are stored in *	network byte order. * *	srcip:		The source IP address. * *	dstip:		The destination IP address. * *	srcmask:	The number of leading one bits in the source address *			mask.  Specifies the bits of interest. * *	dstmask:	The number of leading one bits in the destination *			address mask. Specifies the bits of interest. * *	proto:		The IP protocol number * *	established:	A boolean value.  TRUE when we care about the *			established state of a TCP connection.  FALSE when *			we dont care. * *	srcport:	TCP or UDP source port number. * *	dstport:	TCP or UDP destination port number. * *	srcPortCmp:	One of the values of the RadFilterComparison *			enumeration, specifying how to compare the *			srcport value. * *	dstPortCmp:	One of the values of the RadFilterComparison *			enumeration, specifying how to compare the *			dstport value. * *	fill:		Round things out to a int16_t boundary. */typedef struct ascend_ip_filter_t {	uint32_t	srcip;	uint32_t	dstip;	uint8_t 	srcmask;	uint8_t 	dstmask;	uint8_t		proto;	uint8_t		established;	uint16_t	srcport;	uint16_t	dstport;	uint8_t		srcPortComp;	uint8_t		dstPortComp;	unsigned char   fill[4];        /* used to be fill[2] */} ascend_ip_filter_t;/* *	ascend_ipx_net_t * *	net:      IPX Net address * *	node:     IPX Node address * *	socket:      IPX socket address */typedef struct ascend_ipx_net_t {	uint32_t	net;	uint8_t		node[IPX_NODE_ADDR_LEN];	uint16_t	socket;} ascend_ipx_net_t;/* *	ascend_ipx_filter_t * *	The binary format of an IPX filter.  ALL fields are stored in *	network byte order. * *	src:		Source net, node, and socket. * *	dst:		Destination net, node, and socket. * *	srcSocComp:     Source socket compare value * *	dstSocComp:     Destination socket compare value */typedef struct ascend_ipx_filter_t {	ascend_ipx_net_t src;	ascend_ipx_net_t dst;	uint8_t		srcSocComp;	uint8_t		dstSocComp;} ascend_ipx_filter_t;/* *	ascend_generic_filter_t * *	The binary format of a GENERIC filter.  ALL fields are stored in *	network byte order. * *	offset:		Number of bytes into packet to start comparison. * *	len:		Number of bytes to mask and compare.  May not *			exceed RAD_MAX_FILTER_LEN. * *	more:		Boolean.  If non-zero the next filter entry is *			also to be applied to a packet. * *	mask:		A bit mask specifying the bits to compare. * *	value:		A value to compare against the masked bits at *			offset in a users packet. * *	compNeq:	Defines type of comarison (Equal or Notequal) *			default is Equal. * *	fill:		Round things out to a dword boundary */typedef struct ascend_generic_filter_t {	uint16_t	offset;	uint16_t	len;	uint16_t	more;	uint8_t		mask[ RAD_MAX_FILTER_LEN ];	uint8_t		value[ RAD_MAX_FILTER_LEN ];	uint8_t		compNeq;	uint8_t		fill[3];        /* used to be fill[1] */} ascend_generic_filter_t;/* *	ascend_filter_t * *	A binary filter element.  Contains one of ascend_ip_filter_t, *	ascend_ipx_filter_t, or ascend_generic_filter_t. * *	All fields are stored in network byte order. * *	type:		Either RAD_FILTER_GENERIC or RAD_FILTER_IP. * *	forward:	TRUE if we should forward packets that match this *			filter, FALSE if we should drop packets that match *			this filter. * *	direction:	TRUE if this is an input filter, FALSE if this is *			an output filter. * *	fill:		Round things out to a dword boundary. * *	u:		A union of *			ip:		An ip filter entry *			generic:	A generic filter entry */typedef struct ascend_filter_t {	uint8_t 	type;	uint8_t		forward;	uint8_t		direction;	uint8_t		fill;	union {		ascend_ip_filter_t   	 ip;		ascend_ipx_filter_t   	 ipx;		ascend_generic_filter_t	generic;	} u;} ascend_filter_t;#define SIZEOF_RADFILTER 32/* * FilterPortType: * * Ascii names of some well known tcp/udp services. * Used for filtering on a port type. * * ??? What the heck is wrong with getservbyname? */static const LRAD_NAME_NUMBER filterPortType[] = {	{ "ftp-data",   20 },	{ "ftp",	21 },	{ "telnet",	23 },	{ "smtp",	25 },	{ "nameserver", 42 },	{ "domain",	53 },	{ "tftp",	69 },	{ "gopher",	70 },	{ "finger",	79 },	{ "www",	80 },	{ "kerberos",	88 },	{ "hostname",	101 },	{ "nntp",	119 },	{ "ntp",	123 },	{ "exec",	512 },	{ "login",	513 },	{ "cmd",	514 },	{ "talk",	517 },	{  NULL ,	0},};static const LRAD_NAME_NUMBER filterType[] = {	{ "generic",	RAD_FILTER_GENERIC},	{ "ip", 	RAD_FILTER_IP},	{ "ipx", 	RAD_FILTER_IPX},	{ NULL, 	0},};typedef enum {    FILTER_GENERIC_TYPE,    FILTER_IP_TYPE,    FILTER_IN,    FILTER_OUT,    FILTER_FORWARD,    FILTER_DROP,    FILTER_GENERIC_OFFSET,    FILTER_GENERIC_MASK,    FILTER_GENERIC_VALUE,    FILTER_GENERIC_COMPNEQ,    FILTER_GENERIC_COMPEQ,    FILTER_MORE,    FILTER_IP_DST,    FILTER_IP_SRC,    FILTER_IP_PROTO,    FILTER_IP_DST_PORT,    FILTER_IP_SRC_PORT,    FILTER_EST,    FILTER_IPX_TYPE,    FILTER_IPX_DST_IPXNET,    FILTER_IPX_DST_IPXNODE,    FILTER_IPX_DST_IPXSOCK,    FILTER_IPX_SRC_IPXNET,    FILTER_IPX_SRC_IPXNODE,    FILTER_IPX_SRC_IPXSOCK} FilterTokens;static const LRAD_NAME_NUMBER filterKeywords[] = {	{ "ip", 	FILTER_IP_TYPE },	{ "generic",	FILTER_GENERIC_TYPE },	{ "in", 	FILTER_IN },	{ "out",	FILTER_OUT },	{ "forward",	FILTER_FORWARD },	{ "drop",	FILTER_DROP },	{ "dstip",  	FILTER_IP_DST },	{ "srcip",  	FILTER_IP_SRC },	{ "dstport",	FILTER_IP_DST_PORT },	{ "srcport",	FILTER_IP_SRC_PORT },	{ "est",	FILTER_EST },	{ "more",	FILTER_MORE },	{ "!=",		FILTER_GENERIC_COMPNEQ },	{ "==",		FILTER_GENERIC_COMPEQ  },	{ "ipx",	FILTER_IPX_TYPE  },	{ "dstipxnet",	FILTER_IPX_DST_IPXNET  },	{ "dstipxnode",	FILTER_IPX_DST_IPXNODE  },	{ "dstipxsock",	FILTER_IPX_DST_IPXSOCK  },	{ "srcipxnet",	FILTER_IPX_SRC_IPXNET  },	{ "srcipxnode",	FILTER_IPX_SRC_IPXNODE  },	{ "srcipxsock",	FILTER_IPX_SRC_IPXSOCK  },	{  NULL , 	-1},};/* * FilterProtoName: * * Ascii name of protocols used for filtering. * *  ??? What the heck is wrong with getprotobyname? */static const LRAD_NAME_NUMBER filterProtoName[] = {	{ "tcp",  6 },	{ "udp",  17 },	{ "ospf", 89 },	{ "icmp", 1 },	{ "0",	  0 },	{  NULL , -1 },};/* * RadFilterComparison: * * An enumerated values for the IP filter port comparisons. */typedef enum {	RAD_NO_COMPARE = 0,	RAD_COMPARE_LESS,	RAD_COMPARE_EQUAL,	RAD_COMPARE_GREATER,	RAD_COMPARE_NOT_EQUAL} RadFilterComparison;static const LRAD_NAME_NUMBER filterCompare[] = {	{ "<",	RAD_COMPARE_LESS },	{ "=",	RAD_COMPARE_EQUAL },	{ ">",	RAD_COMPARE_GREATER },	{ "!=", RAD_COMPARE_NOT_EQUAL },	{ NULL, 0 },};/* *	String split routine.  Splits an input string IN PLACE *	into pieces, based on spaces. */static int str2argv(char *str, char **argv, int max_argc){	int argc = 0;	while (*str) {		if (argc >= max_argc) return argc;		while (*str == ' ') *(str++) = '\0';		if (!*str) return argc;		argv[argc] = str;		argc++;		while (*str && (*str != ' ')) str++;	}	return argc;}/* *	hex2bin converts hexadecimal strings into binary * *	Hmm... there are a number of such functions in the source. *	maybe we want to make a library function? */static int hex2bin(const char *str, uint8_t *bin, size_t length){	unsigned int		len;	const		char *letters = "0123456789ABCDEFabcdef";	/*	 *	Must be byte aligned, not nibble aligned.	 */	len = strlen(str);	if ((len & 0x01) != 0) return -1;	/*	 *	Input string is too long to fit.  Don't even bother	 *	trying.	 */	if ((len / 2) > length) return -1;	/*	 *	Input string contains non-hex characters, die.	 */	if (strspn(str, letters) != len) return -1;	len = 0;	while (*str) {		char	*c1, *c2;		c1 = memchr(letters, toupper((int) *(str++)), 16);		c2 = memchr(letters, toupper((int) *(str++)), 16);		*(bin++) = ((c1-letters)<<4) + (c2-letters);		len++;	}        return len;}/* *	ascend_parse_ipx_net * *	srcipxnet nnnn srcipxnode mmmmm [srcipxsoc cmd value ] */static int ascend_parse_ipx_net(int argc, char **argv,				ascend_ipx_net_t *net, uint8_t *comp){	int		token;	const char	*p;	if (argc < 3) return -1;	/*	 *	Parse the net, which is a hex number.	 */	net->net = htonl(strtol(argv[0], NULL, 16));	/*	 *	Parse the node.	 */	token = lrad_str2int(filterKeywords, argv[1], -1);	switch (token) {	case FILTER_IPX_SRC_IPXNODE:	case FILTER_IPX_DST_IPXNODE:		break;	default:		return -1;	}	/*	 *	Can have a leading "0x" or "0X"	 */	p = argv[2];	if ((memcmp(p, "0X", 2) == 0) ||	    (memcmp(p, "0x", 2) == 0)) p += 2;	/*	 *	Node must be 6 octets long.	 */	token = hex2bin(p, net->node, IPX_NODE_ADDR_LEN);	if (token != IPX_NODE_ADDR_LEN) return -1;	/*	 *	Nothing more, die.	 */	if (argc == 3) return 3;	/*	 *	Can't be too little or too much.	 */	if (argc != 6) return -1;	/*	 *	Parse the socket.	 */	token = lrad_str2int(filterKeywords, argv[3], -1);	switch (token) {	case FILTER_IPX_SRC_IPXSOCK:	case FILTER_IPX_DST_IPXSOCK:		break;	default:		return -1;	}	/*	 *	Parse the command "<", ">", "=" or "!="	 */	token = lrad_str2int(filterCompare, argv[4], -1);	switch (token) {	case RAD_COMPARE_LESS:	case RAD_COMPARE_EQUAL:	case RAD_COMPARE_GREATER:	case RAD_COMPARE_NOT_EQUAL:		*comp = token;		break;	default:		return -1;	}	/*	 *	Parse the value.	 */	token = strtoul(argv[5], NULL, 16);	if (token > 65535) return -1;	net->socket = token;	net->socket = htons(net->socket);	/*	 *	Everything's OK, we parsed 6 entries.	 */	return 6;}/* *	ascend_parse_ipx_filter * *	This routine parses an IPX filter string from a string. *	The format of the string is: * *	[ srcipxnet nnnn srcipxnode mmmmm [srcipxsoc cmd value ]] * 	[ dstipxnet nnnn dstipxnode mmmmm [dstipxsoc cmd value ]] * * Fields in [...] are optional. *	where: * *  srcipxnet:      Keyword for source IPX address. *                  nnnn = IPX Node address. * *  srcipxnode:     Keyword for source IPX Node address. *                  mmmmm = IPX Node Address, could be FFFFFF. *                  A vlid ipx node number should accompany ipx net number. * *	srcipxsoc:      Keyword for source IPX socket address. * *	cmd:            One of ">" or "<" or "=" or "!=". * *	value:          Socket value to be compared against, in hex. * *	dstipxnet:	Keyword for destination IPX address. *			nnnn = IPX Node address. * *	dstipxnode:	Keyword for destination IPX Node address. *  		mmmmm = IPX Node Address, could be FFFFFF. *		       A valid ipx node number should accompany ipx net number. * *	dstipxsoc:	Keyword for destination IPX socket address. * *	cmd:		One of ">" or "<" or "=" or "!=". * *	value:		Socket value to be compared against, in hex. */static int ascend_parse_ipx(int argc, char **argv, ascend_ipx_filter_t *filter){	int rcode;	int token;	int flags = 0;	/*	 *	We may have nothing, in which case we simply return.	 */	if (argc == 0) return 0;	/*	 *	Must have "net N node M"	 */	if (argc < 4) return -1;	while ((argc > 0) && (flags != 0x03)) {		token = lrad_str2int(filterKeywords, argv[0], -1);		switch (token) {		case FILTER_IPX_SRC_IPXNET:			if (flags & 0x01) return -1;			rcode = ascend_parse_ipx_net(argc - 1, argv + 1,						     &(filter->src),						     &(filter->srcSocComp));			if (rcode < 0) return -1;			argc -= (rcode + 1);			argv += rcode + 1;			flags |= 0x01;			break;		case FILTER_IPX_DST_IPXNET:			if (flags & 0x02) return -1;			rcode = ascend_parse_ipx_net(argc - 1, argv + 1,						     &(filter->dst),						     &(filter->dstSocComp));			if (rcode < 0) return -1;			argc -= (rcode + 1);			argv += rcode + 1;			flags |= 0x02;			break;		default:			librad_log("Unknown string \"%s\" in IPX data filter",				   argv[0]);			return -1;		}	}	/*	 *	Arguments left over: die.	 */	if (argc != 0) return -1;	/*	 *	Everything's OK.	 */	return 0;}/* *	Parse an IP address and optionally a netmask, to a uint32_t. * *	ipaddr should already be initialized to zero. *	ipaddr is in network byte order. * *	Returns -1 on error, or the number of bits in the netmask, otherwise. */static int ascend_parse_ipaddr(uint32_t *ipaddr, char *str){	int		count = 0;	int		ip[4];	int             masklen;	uint32_t	netmask = 0;	/*	 *	Look for IP's.	 */	count = 0;	while (*str && (count < 4) && (netmask == 0)) {	next:		ip[count] = 0;		while (*str) {			switch (*str) {			case '0': case '1': case '2': case '3':			case '4': case '5': case '6': case '7':			case '8': case '9':				ip[count] *= 10;				ip[count] += (*str) - '0';				str++;				break;			case '.': /* dot between IP numbers. */				str++;				if (ip[count] > 255) return -1;				/*				 *	24, 16, 8, 0, done.				 */				*ipaddr |= (ip[count] << (8 * (3 - count)));				count++;				goto next;			case '/': /* netmask  */				str++;				masklen = atoi(str);				if ((masklen < 0) || (masklen > 32)) return -1;				str += strspn(str, "0123456789");				netmask = masklen;				goto finalize;				break;			default:				librad_log("Invalid character in IP address");				return -1;			}		} /* loop over one character */	} /* loop until the count hits 4 */	if (count == 3) {	finalize:		/*		 *	Do the last one, too.		 */		if (ip[count] > 255) return -1;		/*		 *	24, 16, 8, 0, done.

⌨️ 快捷键说明

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