www.pudn.com > tdi_fw.zip > flt_rule.c


// $Id: flt_rule.c,v 1.2 2002/11/12 10:49:11 dev Exp $ 
 
#include  
 
#include "flt_rule.h" 
#include "ipc.h" 
#include "tdi_fw_svc.h" 
 
struct str_value { 
	const	char *str; 
	int		value; 
}; 
 
static int	str_value(const struct str_value *sv, const char *str); 
static int	get_amp(char *str, u_long *addr, u_long *mask, u_short *port, u_short *port2); 
 
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}, 
	{NULL,		0} 
}; 
 
static struct str_value direction_sv[] = { 
	{"IN",		DIRECTION_IN}, 
	{"OUT",		DIRECTION_OUT}, 
	{NULL,		0} 
}; 
 
/* 
 * rule is like this: 
 * 
 * ALLOW|DENY TCP|UDP|RawIP IN|OUT FROM  TO  [NOLOG]|[CLIENT|SERVER ] 
 */ 
int 
parse_rule(char *str, struct flt_rule *rule) 
{ 
	static char delim[] = " \t"; 
	char *p = str, *p2; 
	int v; 
 
	memset(rule, 0, sizeof(*rule)); 
 
	// by default log using of all rules! 
	rule->log = 1; 
 
	/* ALLOW|DENY */ 
 
	if (*p == '\0') { 
		error("PARSE\tparse_rule: filter ALLOW or DENY is missing"); 
		return 0; 
	} 
 
	p2 = strpbrk(p, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	v = str_value(filter_sv, p); 
	if (v == -1) { 
		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 or RawIP is missing"); 
		return 0; 
	} 
 
	p2 = strpbrk(p, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	v = str_value(proto_sv, p); 
	if (v == -1) { 
		error("PARSE\tparse_rule: \"%s\" is not TCP, UDP or RawIP protocol", p); 
		return 0; 
	} 
	rule->proto = v; 
	 
	p = p2; 
 
	/* IN|OUT */ 
 
	if (p == NULL) { 
		error("PARSE\tparse_rule: direction IN or OUT is missing"); 
		return 0; 
	} 
 
	p2 = strpbrk(p, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	v = str_value(direction_sv, p); 
	if (v == -1) { 
		error("PARSE\tparse_rule: \"%s\" is not IN or OUT 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, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	if (strcmp(p, "FROM") != 0) { 
		error("PARSE\tparse_rule: \"%s\" is not FROM keyword", p); 
		return 0; 
	} 
 
	p = p2; 
 
	/*  */ 
 
	if (p == NULL) { 
		error("PARSE\tparse_rule: from address is missing"); 
		return 0; 
	} 
 
	p2 = strpbrk(p, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	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, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	if (strcmp(p, "TO") != 0) { 
		error("PARSE\tparse_rule: \"%s\" is not TO keyword"); 
		return 0; 
	} 
 
	p = p2; 
 
	/*  */ 
 
	if (p == NULL) { 
		error("PARSE\tparse_rule: to address is missing"); 
		return 0; 
	} 
 
	p2 = strpbrk(p, delim); 
	if (p2 != NULL) 
		*(p2++) = '\0'; 
 
	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 */ 
	if (p != NULL) { 
 
		if (strcmp(p, "NOLOG") == 0) 
			rule->log = 0; 
		else { 
			error("PARSE\tparse_rule: invalid to address \"%s\"", p); 
			return 0; 
		} 
 
	} 
 
	return 1; 
} 
 
int 
str_value(const struct str_value *sv, const char *str) 
{ 
	while (sv->str != NULL) { 
		if (strcmp(sv->str, str) == 0) 
			return sv->value; 
		sv++; 
	} 
	return -1; 
} 
 
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; 
	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; 
		} 
	} 
 
	// is it ANY? 
	if (strcmp(addr_str, "ANY") == 0) { 
		// 0.0.0.0/0 
		*addr = INADDR_ANY; 
		*mask = INADDR_ANY; 
	 
	} else { 
		// 
[/] *addr = inet_addr(addr_str); if (*addr == INADDR_NONE && strcmp(addr_str, "255.255.255.255") != 0) { if (g_rules_resolve_addr) { // try to resolve addr struct hostent *he = gethostbyname(addr_str); if (he == NULL) { error("PARSE\tUnable to resolve: %s", addr_str); return 0; } *addr = *(u_long *)he->h_addr; // ??? do we need to log it ??? } else { error("PARSE\tInvalid address: %s", addr_str); return 0; } } if (mask_str != NULL) { // int n = atoi(mask_str); if ((n == 0 && strcmp(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 = 1; i < n; i++) *mask |= *mask << 1; } } else *mask = INADDR_NONE; // default mask 255.255.255.255 } if (port_str) { int n = atoi(port_str); if ((n == 0 && strcmp(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) { int n = atoi(port2_str); if ((n == 0 && strcmp(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; }