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

📄 semcheck.c

📁 ethereal公司开发的aodv路由协议代码
💻 C
字号:
/* * $Id: semcheck.c,v 1.10 2002/03/02 20:48:11 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> * Copyright 2001 Gerald Combs *  * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "dfilter-int.h"#include "syntax-tree.h"#include "sttype-range.h"#include "sttype-test.h"#include <epan/exceptions.h>#include <epan/packet.h>static voidsemcheck(stnode_t *st_node);typedef gboolean (*FtypeCanFunc)(enum ftenum);/* Compares to ftenum_t's and decides if they're * compatible or not (if they're the same basic type) */static gbooleancompatible_ftypes(ftenum_t a, ftenum_t b){	switch (a) {		case FT_NONE:		case FT_PROTOCOL:		case FT_DOUBLE:		case FT_ABSOLUTE_TIME:		case FT_RELATIVE_TIME:		case FT_IPv4:		case FT_IPv6:		case FT_IPXNET:		case FT_INT64:		case FT_UINT64:			return a == b;		case FT_ETHER:		case FT_BYTES:			return (b == FT_ETHER || b == FT_BYTES);		case FT_BOOLEAN:		case FT_UINT8:		case FT_UINT16:		case FT_UINT24:		case FT_UINT32:		case FT_INT8:		case FT_INT16:		case FT_INT24:		case FT_INT32:			switch (b) {				case FT_BOOLEAN:				case FT_UINT8:				case FT_UINT16:				case FT_UINT24:				case FT_UINT32:				case FT_INT8:				case FT_INT16:				case FT_INT24:				case FT_INT32:					return TRUE;				default:					return FALSE;			}					case FT_STRING:		case FT_STRINGZ:		case FT_UINT_STRING:			switch (b) {				case FT_STRING:				case FT_STRINGZ:				case FT_UINT_STRING:					return TRUE;				default:					return FALSE;			}		case FT_NUM_TYPES:			g_assert_not_reached();	}	g_assert_not_reached();	return FALSE;}/* Creates a FT_UINT32 fvalue with a given value. */static fvalue_t*mk_uint32_fvalue(guint32 val){	fvalue_t *fv;	fv = fvalue_new(FT_UINT32);	fvalue_set_integer(fv, val);	return fv;}/* Try to make an fvalue from a string using a value_string or true_false_string. * This works only for ftypes that are integers. Returns the created fvalue_t* * or NULL if impossible. */static fvalue_t*mk_fvalue_from_val_string(header_field_info *hfinfo, char *s){	static true_false_string        default_tf = { "True", "False" };	true_false_string		*tf = &default_tf;	value_string			*vals;	/* Early return? */	switch(hfinfo->type) {		case FT_NONE:		case FT_PROTOCOL:		case FT_DOUBLE:		case FT_ABSOLUTE_TIME:		case FT_RELATIVE_TIME:		case FT_IPv4:		case FT_IPv6:		case FT_IPXNET:		case FT_ETHER:		case FT_BYTES:		case FT_STRING:		case FT_STRINGZ:		case FT_UINT_STRING:		case FT_UINT64:		case FT_INT64:			return FALSE;		case FT_BOOLEAN:		case FT_UINT8:		case FT_UINT16:		case FT_UINT24:		case FT_UINT32:		case FT_INT8:		case FT_INT16:		case FT_INT24:		case FT_INT32:			break;					case FT_NUM_TYPES:			g_assert_not_reached();	}	/* Reset the dfilter error message, since *something* interesting	 * will happen, and the error message will be more interesting than	 * any error message I happen to have now. */	dfilter_error_msg = NULL;	/* TRUE/FALSE *always* exist for FT_BOOLEAN. */	if (hfinfo->type == FT_BOOLEAN) {		if (hfinfo->strings) {			tf = hfinfo->strings;		}		if (strcasecmp(s, tf->true_string) == 0) {			return mk_uint32_fvalue(TRUE);		}		else if (strcasecmp(s, tf->false_string) == 0) {			return mk_uint32_fvalue(FALSE);		}		else {		dfilter_fail("\"%s\" cannot be found among the possible values for %s.",				s, hfinfo->abbrev);			return NULL;		}	}	/* Do val_strings exist? */	if (!hfinfo->strings) {		dfilter_fail("%s cannot accept strings as values.",				hfinfo->abbrev);		return FALSE;	}	vals = hfinfo->strings;	while (vals->strptr != NULL) {		if (strcasecmp(s, vals->strptr) == 0) {			return mk_uint32_fvalue(vals->value);		}		vals++;	}	dfilter_fail("\"%s\" cannot be found among the possible values for %s.",			s, hfinfo->abbrev);	return FALSE;}static gbooleanis_bytes_type(enum ftenum type){	switch(type) {		case FT_ETHER:		case FT_BYTES:		case FT_IPv6:			return TRUE;		case FT_NONE:		case FT_PROTOCOL:		case FT_DOUBLE:		case FT_ABSOLUTE_TIME:		case FT_RELATIVE_TIME:		case FT_IPv4:		case FT_IPXNET:		case FT_STRING:		case FT_STRINGZ:		case FT_UINT_STRING:		case FT_BOOLEAN:		case FT_UINT8:		case FT_UINT16:		case FT_UINT24:		case FT_UINT32:		case FT_UINT64:		case FT_INT8:		case FT_INT16:		case FT_INT24:		case FT_INT32:		case FT_INT64:			return FALSE;					case FT_NUM_TYPES:			g_assert_not_reached();	}	g_assert_not_reached();	return FALSE;}static voidcheck_relation_LHS_FIELD(FtypeCanFunc can_func, stnode_t *st_node,		stnode_t *st_arg1, stnode_t *st_arg2){	stnode_t		*new_st;	sttype_id_t		type1, type2;	header_field_info	*hfinfo1, *hfinfo2;	ftenum_t		ftype1, ftype2;	fvalue_t		*fvalue;	char			*s;	drange_node		*rn;	type1 = stnode_type_id(st_arg1);	type2 = stnode_type_id(st_arg2);	hfinfo1 = stnode_data(st_arg1);	ftype1 = hfinfo1->type;	if (!can_func(ftype1)) {		dfilter_fail("%s (type=%s) cannot participate in specified comparison.",				hfinfo1->abbrev, ftype_pretty_name(ftype1));		THROW(TypeError);	}	if (type2 == STTYPE_FIELD) {		hfinfo2 = stnode_data(st_arg2);		ftype2 = hfinfo2->type;		if (!compatible_ftypes(ftype1, ftype2)) {			dfilter_fail("%s and %s are not of compatible types.",					hfinfo1->abbrev, hfinfo2->abbrev);			THROW(TypeError);		}		/* Do this check even though you'd think that if		 * they're compatible, then can_func() would pass. */		if (!can_func(ftype2)) {			dfilter_fail("%s (type=%s) cannot participate in specified comparison.",					hfinfo2->abbrev, ftype_pretty_name(ftype2));			THROW(TypeError);		}	}	else if (type2 == STTYPE_STRING) {		s = stnode_data(st_arg2);		fvalue = fvalue_from_string(ftype1, s, dfilter_fail);		if (!fvalue) {			/* check value_string */			fvalue = mk_fvalue_from_val_string(hfinfo1, s);			if (!fvalue) {				THROW(TypeError);			}		}		new_st = stnode_new(STTYPE_FVALUE, fvalue);		sttype_test_set2_args(st_node, st_arg1, new_st);		stnode_free(st_arg2);	}	else if (type2 == STTYPE_RANGE) {		if (!is_bytes_type(ftype1)) {			if (!ftype_can_slice(ftype1)) {				dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.",						hfinfo1->abbrev,						ftype_pretty_name(ftype1));				THROW(TypeError);			}			/* Convert entire field to bytes */			new_st = stnode_new(STTYPE_RANGE, NULL);			rn = drange_node_new();			drange_node_set_start_offset(rn, 0);			drange_node_set_to_the_end(rn);			/* st_arg1 is freed in this step */			sttype_range_set1(new_st, st_arg1, rn);			sttype_test_set2_args(st_node, new_st, st_arg2);		}	}	else {		g_assert_not_reached();	}}static voidcheck_relation_LHS_STRING(FtypeCanFunc can_func _U_, stnode_t *st_node,		stnode_t *st_arg1, stnode_t *st_arg2){	stnode_t		*new_st;	sttype_id_t		type1, type2;	header_field_info	*hfinfo2;	ftenum_t		ftype2;	fvalue_t		*fvalue;	char			*s;	type1 = stnode_type_id(st_arg1);	type2 = stnode_type_id(st_arg2);			if (type2 == STTYPE_FIELD) {		hfinfo2 = stnode_data(st_arg2);		ftype2 = hfinfo2->type;		s = stnode_data(st_arg1);		fvalue = fvalue_from_string(ftype2, s, dfilter_fail);		if (!fvalue) {			/* check value_string */			fvalue = mk_fvalue_from_val_string(hfinfo2, s);			if (!fvalue) {				THROW(TypeError);			}		}		new_st = stnode_new(STTYPE_FVALUE, fvalue);		sttype_test_set2_args(st_node, new_st, st_arg2);		stnode_free(st_arg1);	}	else if (type2 == STTYPE_STRING) {		/* Well now that's silly... */		dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.",				stnode_data(st_arg1),				stnode_data(st_arg2));		THROW(TypeError);	}	else if (type2 == STTYPE_RANGE) {		s = stnode_data(st_arg1);		fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail);		if (!fvalue) {			THROW(TypeError);		}		new_st = stnode_new(STTYPE_FVALUE, fvalue);		sttype_test_set2_args(st_node, new_st, st_arg2);		stnode_free(st_arg1);	}	else {		g_assert_not_reached();	}}static voidcheck_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,		stnode_t *st_arg1, stnode_t *st_arg2){	stnode_t		*new_st;	sttype_id_t		type1, type2;	header_field_info	*hfinfo1, *hfinfo2;	ftenum_t		ftype1, ftype2;	fvalue_t		*fvalue;	char			*s;	drange_node		*rn;	type1 = stnode_type_id(st_arg1);	type2 = stnode_type_id(st_arg2);	hfinfo1 = sttype_range_hfinfo(st_arg1);	ftype1 = hfinfo1->type;	if (!ftype_can_slice(ftype1)) {		dfilter_fail("\"%s\" is a %s and cannot be sliced into a sequence of bytes.",				hfinfo1->abbrev, ftype_pretty_name(ftype1));		THROW(TypeError);	}	if (type2 == STTYPE_FIELD) {		hfinfo2 = sttype_range_hfinfo(st_arg2);		ftype2 = hfinfo2->type;		if (!is_bytes_type(ftype2)) {			if (!ftype_can_slice(ftype2)) {				dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.",						hfinfo2->abbrev,						ftype_pretty_name(ftype2));				THROW(TypeError);			}			/* Convert entire field to bytes */			new_st = stnode_new(STTYPE_RANGE, NULL);			rn = drange_node_new();			drange_node_set_start_offset(rn, 0);			drange_node_set_to_the_end(rn);			/* st_arg2 is freed in this step */			sttype_range_set1(new_st, st_arg2, rn);			sttype_test_set2_args(st_node, st_arg1, new_st);		}	}	else if (type2 == STTYPE_STRING) {		s = stnode_data(st_arg2);		fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail);		if (!fvalue) {			THROW(TypeError);		}		new_st = stnode_new(STTYPE_FVALUE, fvalue);		sttype_test_set2_args(st_node, st_arg1, new_st);		stnode_free(st_arg2);	}	else if (type2 == STTYPE_RANGE) {		/* XXX - check lengths of both ranges */	}	else {		g_assert_not_reached();	}}static voidcheck_relation(FtypeCanFunc can_func, stnode_t *st_node,		stnode_t *st_arg1, stnode_t *st_arg2){	switch (stnode_type_id(st_arg1)) {		case STTYPE_FIELD:			check_relation_LHS_FIELD(can_func, st_node, st_arg1, st_arg2);			break;		case STTYPE_STRING:			check_relation_LHS_STRING(can_func, st_node, st_arg1, st_arg2);			break;		case STTYPE_RANGE:			check_relation_LHS_RANGE(can_func, st_node, st_arg1, st_arg2);			break;		case STTYPE_UNINITIALIZED:		case STTYPE_TEST:		case STTYPE_INTEGER:		case STTYPE_FVALUE:		case STTYPE_NUM_TYPES:			g_assert_not_reached();	}}static voidcheck_test(stnode_t *st_node){	test_op_t		st_op;	stnode_t		*st_arg1, *st_arg2;	sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);	switch (st_op) {		case TEST_OP_UNINITIALIZED:			g_assert_not_reached();			break;		case TEST_OP_EXISTS:			/* nothing */			break;		case TEST_OP_NOT:			semcheck(st_arg1);			break;		case TEST_OP_AND:		case TEST_OP_OR:			semcheck(st_arg1);			semcheck(st_arg2);			break;		case TEST_OP_EQ:			check_relation(ftype_can_eq, st_node, st_arg1, st_arg2);			break;		case TEST_OP_NE:			check_relation(ftype_can_ne, st_node, st_arg1, st_arg2);			break;		case TEST_OP_GT:			check_relation(ftype_can_gt, st_node, st_arg1, st_arg2);			break;		case TEST_OP_GE:			check_relation(ftype_can_ge, st_node, st_arg1, st_arg2);			break;		case TEST_OP_LT:			check_relation(ftype_can_lt, st_node, st_arg1, st_arg2);			break;		case TEST_OP_LE:			check_relation(ftype_can_le, st_node, st_arg1, st_arg2);			break;	}}static voidsemcheck(stnode_t *st_node){	const char	*name;	name = stnode_type_name(st_node);	switch (stnode_type_id(st_node)) {		case STTYPE_TEST:			check_test(st_node);			break;		default:			g_assert_not_reached();	}}gbooleandfw_semcheck(dfwork_t *dfw){	TRY {		semcheck(dfw->st_root);	}	CATCH(TypeError) {		return FALSE;	}	ENDTRY;	return TRUE;}

⌨️ 快捷键说明

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