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

📄 flt_rule.c

📁 开源的防火墙代码
💻 C
字号:
/* Copyright (c) 2002-2005 Vladislav Goncharov.
*
* Redistribution and use in source forms, with and without modification,
* are permitted provided that this entire comment appears intact.
*
* Redistribution in binary form may occur without any restrictions.
*
* This software is provided ``AS IS'' without any warranties of any kind.
*/

// $Id: flt_rule.c,v 1.9 2003/09/04 15:20:10 dev Exp $

/*
* Rule parser
*/

#include <winsock.h>
#include <stdlib.h>

#include "flt_rule.h"
#include "ipc.h"
#include "tdifw_svc.h"

struct str_value
{
	const	char *str;
	int		value;
};

static BOOL		str_value(const struct str_value *sv, const char *str, int *result);
static int		get_amp(char *str, u_long *addr, u_long *mask, u_short *port, u_short *port2);

static char g_delim[] = " \t";

static struct str_value filter_sv[] =
{
	{"ALLOW",	FILTER_ALLOW},
	{"DENY",	FILTER_DENY},
	{NULL,		0}
};

static struct str_value proto_sv[] =
{
	{"TCP",		IPPROTO_TCP},
	{"UDP",		IPPROTO_UDP},
	{"RawIP",	IPPROTO_IP},
	{"*",		IPPROTO_ANY},
	{NULL,		0}
};

static struct str_value direction_sv[] =
{
	{"IN",		DIRECTION_IN},
	{"OUT",		DIRECTION_OUT},
	{"*",		DIRECTION_ANY},
	{NULL,		0}
};

/*
* rule is like this:
*
* [<name>:] ALLOW|DENY TCP|UDP|RawIP|* IN|OUT|* FROM <addr> TO <addr> [NOLOG|COUNT]
*/
int	parse_rule(char *str, struct flt_rule *rule)
{
	char *p = str, *p2;
	int v;
	
	memset(rule, 0, sizeof(*rule));
	
	// by default log using of all rules!
	rule->log = RULE_LOG_LOG;
	
	// skip whitespace
	while (strchr(g_delim, *p) != NULL)
	p++;
	
	/* ALLOW|DENY */
	
	if (*p == '\0')
		{
		error("PARSE\tparse_rule: filter ALLOW or DENY is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (p[strlen(p) - 1] == ':')
		{
		// got name!
		
		p[strlen(p) - 1] = '\0';	// kill ending ':'
		
		strncpy(rule->rule_id, p, RULE_ID_SIZE);
		// string can be not zero-terminated
		
		p = p2;
		
		/* ALLOW|DENY again */
		
		if (p == NULL)
			{
			error("PARSE\tparse_rule: filter ALLOW or DENY is missing");
			return 0;
			}
		
		p2 = strpbrk(p, g_delim);
		if (p2 != NULL)
			{
			*(p2++) = '\0';
			while (strchr(g_delim, *p2) != NULL)
			p2++;
			}
		
		}
	
	if (!str_value(filter_sv, p, &v))
		{
		error("PARSE\tparse_rule: \"%s\" is not ALLOW or DENY filter", p);
		return 0;
		}
	rule->result = v;
	
	p = p2;
	
	/* TCP|UDP|RawIP|* */
	
	if (p == NULL)
		{
		error("PARSE\tparse_rule: protocol TCP, UDP, RawIP or * is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (!str_value(proto_sv, p, &v))
		{
		error("PARSE\tparse_rule: \"%s\" is not TCP, UDP, RawIP protocol or *", p);
		return 0;
		}
	rule->proto = v;
	
	p = p2;
	
	/* IN|OUT|* */
	
	if (p == NULL)
		{
		error("PARSE\tparse_rule: direction IN, OUT or * is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (!str_value(direction_sv, p, &v))
		{
		error("PARSE\tparse_rule: \"%s\" is not IN, OUT or * direction", p);
		return 0;
		}
	rule->direction = v;
	
	p = p2;
	
	/* FROM */
	
	if (p == NULL)
		{
		error("PARSE\tparse_rule: keyword FROM is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (_stricmp(p, "FROM") != 0)
		{
		error("PARSE\tparse_rule: \"%s\" is not FROM keyword", p);
		return 0;
		}
	
	p = p2;
	
	/* <addr-from> */
	
	if (p == NULL)
		{
		error("PARSE\tparse_rule: from address is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (!get_amp(p, &rule->addr_from, &rule->mask_from, &rule->port_from, &rule->port2_from))
		{
		error("PARSE\tparse_rule: invalid from address \"%s\"", p);
		return 0;
		}
	
	p = p2;
	
	/* TO */
	
	if (p == NULL)
		{
		error("PARSE\tparse_rule: keyword TO is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (_stricmp(p, "TO") != 0)
		{
		error("PARSE\tparse_rule: \"%s\" is not TO keyword");
		return 0;
		}
	
	p = p2;
	
	/* <addr-to> */
	
	if (p == NULL)
		{
		error("PARSE\tparse_rule: to address is missing");
		return 0;
		}
	
	p2 = strpbrk(p, g_delim);
	if (p2 != NULL)
		{
		*(p2++) = '\0';
		while (strchr(g_delim, *p2) != NULL)
		p2++;
		}
	
	if (!get_amp(p, &rule->addr_to, &rule->mask_to, &rule->port_to, &rule->port2_to))
		{
		error("PARSE\tparse_rule: invalid to address \"%s\"", p);
		return 0;
		}
	
	p = p2;
	
	/* NOLOG|COUNT */
	if (p != NULL)
		{
		
		if (_stricmp(p, "NOLOG") == 0)
			rule->log = RULE_LOG_NOLOG;
		else if (_stricmp(p, "COUNT") == 0)
			rule->log = RULE_LOG_COUNT;
		else	{
			error("PARSE\tparse_rule: invalid to address \"%s\"", p);
			return 0;
			}
		
		}
	
	return 1;
}

BOOL	str_value(const struct str_value *sv, const char *str, int *result)
{
	while (sv->str != NULL)
		{
		if (_stricmp(sv->str, str) == 0)
			{
			*result = sv->value;
			return TRUE;
			}
		sv++;
		}
	return FALSE;
}

int	get_amp(char *string, u_long *addr, u_long *mask, u_short *port, u_short *port2)
{
	char *p, *addr_str = NULL, *mask_str = NULL, *port_str = NULL,
			     *port2_str = NULL, net_mask[10];
	int result = 0;
	
	addr_str = string;
	
	// "/mask"
	p = strchr(string, '/');
	if (p != NULL)
		{
		*(p++) = '\0';
		mask_str = p;
		}
	
	// ":port"
	p = strchr(mask_str ? mask_str : string, ':');
	if (p != NULL)
		{
		*(p++) = '\0';
		port_str = p;
		
		// "-port2"
		p = strchr(port_str, '-');
		if (p != NULL)
			{
			*(p++) = '\0';
			port2_str = p;
			}
		}
	
	// <address>[/<mask>]
	
	*addr = inet_addr(addr_str);
	if (*addr == INADDR_NONE && _stricmp(addr_str, "255.255.255.255") != 0)
		{
		
		*addr = get_host_by_name(addr_str, net_mask);
		if (*addr == INADDR_NONE)
			{
			// XXX try to resolve?
			error("PARSE\tInvalid address: %s", addr_str);
			return 0;
			}
		
		if (*net_mask != '\0')
			{
			// got mask in resolving
			mask_str = net_mask;
			}
		
		}
	
	if (mask_str != NULL)
		{
		// <mask>
		int n = atoi(mask_str);
		if ((n == 0 && _stricmp(mask_str, "0") != 0) || n < 0 || n > 32)
			{
			error("PARSE\tInvalid mask: %s", mask_str);
			return 0;
			}
		if (n == 0)
			*mask = 0;
		else	{
			int i;
			for (i = 1, *mask = 0x80000000; i < n; i++)
				*mask |= *mask >> 1;
			*mask = htonl(*mask);
			}
		}
	else
		*mask = INADDR_NONE;	// default mask 255.255.255.255
	
	if (port_str != NULL)
		{
		int n = atoi(port_str);
		if ((n == 0 && _stricmp(port_str, "0") != 0) || n < 0 || n > 0xffff)
			{
			error("PARSE\tInvalid port: %s", port_str);
			return 0;
			}
		*port = (USHORT)n;
		}
	else
		*port = 0;
	
	if (port2_str != NULL)
		{
		int n = atoi(port2_str);
		if ((n == 0 && _stricmp(port2_str, "0") != 0) || n < 0 || n > 0xffff)
			{
			error("PARSE\tInvalid port2: %s", port2_str);
			return 0;
			}
		*port2 = (USHORT)n;
		}
	else
		*port2 = 0;
	
	// make network order
	*port = htons(*port);
	*port2 = htons(*port2);
	
	return 1;
}

⌨️ 快捷键说明

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