示例#1
0
static stnode_t *
convert_to_bytes(stnode_t *arg)
{
	stnode_t      *new_st;
	drange_node   *rn;

	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);
	/* new_st is owner of arg in this step */
	sttype_range_set1(new_st, arg, rn);

	return new_st;
}
示例#2
0
static stnode_t*
check_param_entity(stnode_t *st_node)
{
	sttype_id_t		e_type;
	stnode_t		*new_st;
	fvalue_t		*fvalue;
	char *s;

	e_type = stnode_type_id(st_node);
	/* If there's an unparsed string, change it to an FT_STRING */
	if (e_type == STTYPE_UNPARSED) {
		s = stnode_data(st_node);
		fvalue = fvalue_from_unparsed(FT_STRING, s, FALSE, dfilter_fail);
		if (!fvalue) {
			THROW(TypeError);
		}

		new_st = stnode_new(STTYPE_FVALUE, fvalue);
		stnode_free(st_node);
		return new_st;
	}
	return st_node;
}
示例#3
0
gboolean
dfilter_compile(const gchar *text, dfilter_t **dfp, gchar **err_msg)
{
	gchar		*expanded_text;
	int		token;
	dfilter_t	*dfilter;
	dfwork_t	*dfw;
	gboolean failure = FALSE;
	const char	*depr_test;
	guint		i;
	/* XXX, GHashTable */
	GPtrArray	*deprecated;

	g_assert(dfp);

	if (!text) {
		*dfp = NULL;
		if (err_msg != NULL)
			*err_msg = g_strdup("BUG: NULL text pointer passed to dfilter_compile()");
		return FALSE;
	}

	if ( !( expanded_text = dfilter_macro_apply(text, err_msg) ) ) {
		return FALSE;
	}

	dfw = dfwork_new();

	/*
	 * XXX - if we're using a version of Flex that supports reentrant lexical
	 * analyzers, we should put this into the lexical analyzer's state.
	 */
	global_dfw = dfw;

	df_scanner_text(expanded_text);

	deprecated = g_ptr_array_new();

	while (1) {
		df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL);
		token = df_lex();

		/* Check for scanner failure */
		if (token == SCAN_FAILED) {
			failure = TRUE;
			break;
		}

		/* Check for end-of-input */
		if (token == 0) {
			break;
		}

		/* See if the node is deprecated */
		depr_test = stnode_deprecated(df_lval);

		if (depr_test) {
			for (i = 0; i < deprecated->len; i++) {
				if (g_ascii_strcasecmp(depr_test, (const gchar *)g_ptr_array_index(deprecated, i)) == 0) {
					/* It's already in our list */
					depr_test = NULL;
				}
			}
		}

		if (depr_test) {
			g_ptr_array_add(deprecated, g_strdup(depr_test));
		}

		/* Give the token to the parser */
		Dfilter(ParserObj, token, df_lval, dfw);
		/* We've used the stnode_t, so we don't want to free it */
		df_lval = NULL;

		if (dfw->syntax_error) {
			failure = TRUE;
			break;
		}

	} /* while (1) */

	/* If we created an stnode_t but didn't use it, free it; the
	 * parser doesn't know about it and won't free it for us. */
	if (df_lval) {
		stnode_free(df_lval);
		df_lval = NULL;
	}

	/* Tell the parser that we have reached the end of input; that
	 * way, it'll reset its state for the next compile.  (We want
	 * to do that even if we got a syntax error, to make sure the
	 * parser state is cleaned up; we don't create a new parser
	 * object when we start a new parse, and don't destroy it when
	 * the parse finishes.) */
	Dfilter(ParserObj, 0, NULL, dfw);

	/* One last check for syntax error (after EOF) */
	if (dfw->syntax_error)
		failure = TRUE;

	/* Reset flex */
	df_scanner_cleanup();

	if (failure)
		goto FAILURE;

	/* Success, but was it an empty filter? If so, discard
	 * it and set *dfp to NULL */
	if (dfw->st_root == NULL) {
		*dfp = NULL;
		for (i = 0; i < deprecated->len; ++i) {
			gchar* depr = (gchar*)g_ptr_array_index(deprecated,i);
			g_free(depr);
		}
		g_ptr_array_free(deprecated, TRUE);
	}
	else {

		/* Check semantics and do necessary type conversion*/
		if (!dfw_semcheck(dfw, deprecated)) {
			goto FAILURE;
		}

		/* Create bytecode */
		dfw_gencode(dfw);

		/* Tuck away the bytecode in the dfilter_t */
		dfilter = dfilter_new();
		dfilter->insns = dfw->insns;
		dfilter->consts = dfw->consts;
		dfw->insns = NULL;
		dfw->consts = NULL;
		dfilter->interesting_fields = dfw_interesting_fields(dfw,
			&dfilter->num_interesting_fields);

		/* Initialize run-time space */
		dfilter->num_registers = dfw->first_constant;
		dfilter->max_registers = dfw->next_register;
		dfilter->registers = g_new0(GList*, dfilter->max_registers);
		dfilter->attempted_load = g_new0(gboolean, dfilter->max_registers);

		/* Initialize constants */
		dfvm_init_const(dfilter);

		/* Add any deprecated items */
		dfilter->deprecated = deprecated;

		/* And give it to the user. */
		*dfp = dfilter;
	}
	/* SUCCESS */
	global_dfw = NULL;
	dfwork_free(dfw);
	wmem_free(NULL, expanded_text);
	return TRUE;

FAILURE:
	if (dfw) {
		if (err_msg != NULL)
			*err_msg = dfw->error_message;
		else
			g_free(dfw->error_message);
		global_dfw = NULL;
		dfwork_free(dfw);
	}
	for (i = 0; i < deprecated->len; ++i) {
		gchar* depr = (gchar*)g_ptr_array_index(deprecated,i);
		g_free(depr);
	}
	g_ptr_array_free(deprecated, TRUE);
	if (err_msg != NULL) {
		/*
		 * Default error message.
		 *
		 * XXX - we should really make sure that this is never the
		 * case for any error.
		 */
		if (*err_msg == NULL)
			*err_msg = g_strdup_printf("Unable to parse filter string \"%s\".", expanded_text);
	}
	*dfp = NULL;
	return FALSE;
}
示例#4
0
/* If the LHS of a relation test is a FUNCTION, run some checks
 * and possibly some modifications of syntax tree nodes. */
static void
check_relation_LHS_FUNCTION(const char *relation_string, FtypeCanFunc can_func,
		gboolean allow_partial_value,
		stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
	stnode_t		*new_st;
	sttype_id_t		type2;
	header_field_info	*hfinfo2;
	ftenum_t		ftype1, ftype2;
	fvalue_t		*fvalue;
	char			*s;
	drange_node		*rn;
	df_func_def_t   *funcdef;
	df_func_def_t   *funcdef2;
	GSList          *params;

	check_function(st_arg1);
	type2 = stnode_type_id(st_arg2);

	funcdef = sttype_function_funcdef(st_arg1);
	ftype1 = funcdef->retval_ftype;

	params = sttype_function_params(st_arg1);

	DebugLog(("    5 check_relation_LHS_FUNCTION(%s)\n", relation_string));

	if (!can_func(ftype1)) {
		dfilter_fail("Function %s (type=%s) cannot participate in '%s' comparison.",
				funcdef->name, ftype_pretty_name(ftype1),
				relation_string);
		THROW(TypeError);
	}

	if (type2 == STTYPE_FIELD) {
		hfinfo2 = stnode_data(st_arg2);
		ftype2 = hfinfo2->type;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail("Function %s and %s are not of compatible types.",
					funcdef->name, 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);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail);
		} else {
			fvalue = fvalue_from_string(ftype1, 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_UNPARSED) {
		s = stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail);
		} else {
			fvalue = fvalue_from_unparsed(ftype1, s, allow_partial_value, 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) {
		check_drange_sanity(st_arg2);
		if (!is_bytes_type(ftype1)) {
			if (!ftype_can_slice(ftype1)) {
				dfilter_fail("Function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
						funcdef->name,
						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 if (type2 == STTYPE_FUNCTION) {
		funcdef2 = sttype_function_funcdef(st_arg2);
		ftype2 = funcdef2->retval_ftype;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail("Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.",
				     funcdef->name, ftype_pretty_name(ftype1), funcdef2->name, ftype_pretty_name(ftype2));
			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("Return value of %s (type=%s) cannot participate in specified comparison.",
				     funcdef2->name, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}

		check_function(st_arg2);
	}
	else {
		g_assert_not_reached();
	}
}
示例#5
0
static void
check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_,
		gboolean allow_partial_value,
		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;
	df_func_def_t		*funcdef;
	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;

	DebugLog(("    5 check_relation_LHS_RANGE(%s)\n", relation_string));

	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);
	}

	check_drange_sanity(st_arg1);

	if (type2 == STTYPE_FIELD) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_FIELD)\n"));
		hfinfo2 = stnode_data(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) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_STRING)\n"));
		s = stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail);
		} else {
			fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail);
		}
		if (!fvalue) {
			DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_STRING): Could not convert from string!\n"));
			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_UNPARSED) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED)\n"));
		s = stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail);
		} else {
			fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail);
		}
		if (!fvalue) {
			DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED): Could not convert from string!\n"));
			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) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_RANGE)\n"));
		check_drange_sanity(st_arg2);
	}
	else if (type2 == STTYPE_FUNCTION) {
		funcdef = sttype_function_funcdef(st_arg2);
		ftype2  = funcdef->retval_ftype;
		
		if (!is_bytes_type(ftype2)) {
			if (!ftype_can_slice(ftype2)) {
				dfilter_fail("Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
					funcdef->name,
					ftype_pretty_name(ftype2));
				THROW(TypeError);
			}

			/* XXX should I add a new drange node? */
		}

		check_function(st_arg2);
	}
	else {
		g_assert_not_reached();
	}
}
示例#6
0
static void
check_relation_LHS_UNPARSED(const char* relation_string,
		FtypeCanFunc can_func, gboolean allow_partial_value,
		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;
	df_func_def_t		*funcdef;
	ftenum_t		ftype2;
	fvalue_t		*fvalue;
	char			*s;

	type1 = stnode_type_id(st_arg1);
	type2 = stnode_type_id(st_arg2);

	DebugLog(("    5 check_relation_LHS_UNPARSED()\n"));

	if (type2 == STTYPE_FIELD) {
		hfinfo2 = stnode_data(st_arg2);
		ftype2 = hfinfo2->type;

		if (!can_func(ftype2)) {
			dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.",
					hfinfo2->abbrev, ftype_pretty_name(ftype2),
					relation_string);
			THROW(TypeError);
		}

		s = stnode_data(st_arg1);
		fvalue = fvalue_from_unparsed(ftype2, s, allow_partial_value, 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 || type2 == STTYPE_UNPARSED) {
		/* 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) {
		check_drange_sanity(st_arg2);
		s = stnode_data(st_arg1);
		fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, 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 if (type2 == STTYPE_FUNCTION) {
		funcdef = sttype_function_funcdef(st_arg2);
		ftype2  = funcdef->retval_ftype;

		if (!can_func(ftype2)) {
			dfilter_fail("return value of function %s() (type=%s) cannot participate in '%s' comparison.",
					funcdef->name, ftype_pretty_name(ftype2), relation_string);
			THROW(TypeError);
		}

		s =  stnode_data(st_arg1);
		fvalue = fvalue_from_unparsed(ftype2, s, allow_partial_value, dfilter_fail);
		
		if (!fvalue) {
			THROW(TypeError);
		}

		check_function(st_arg2);

		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();
	}
}
示例#7
0
static void
check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_,
		gboolean allow_partial_value,
		stnode_t *st_node,
		stnode_t *st_arg1, stnode_t *st_arg2)
{
	stnode_t		*new_st;
	sttype_id_t		type2;
	header_field_info	*hfinfo1, *hfinfo2;
	df_func_def_t		*funcdef;
	ftenum_t		ftype1, ftype2;
	fvalue_t		*fvalue;
	char			*s;
	drange_node		*rn;
        int                     len_range;

	type2 = stnode_type_id(st_arg2);
	hfinfo1 = sttype_range_hfinfo(st_arg1);
	ftype1 = hfinfo1->type;

	DebugLog(("    5 check_relation_LHS_RANGE(%s)\n", relation_string));

	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);
	}

	check_drange_sanity(st_arg1);

	if (type2 == STTYPE_FIELD) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_FIELD)\n"));
		hfinfo2 = stnode_data(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) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_STRING)\n"));
		s = stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail);
		} else {
			fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail);
		}
		if (!fvalue) {
			DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_STRING): Could not convert from string!\n"));
			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_UNPARSED) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED)\n"));
		s = stnode_data(st_arg2);
                len_range = drange_get_total_length(sttype_range_drange(st_arg1));
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail);
		}

                /* The RHS should be FT_BYTES. However, there is a special case where
                 * the range slice on the LHS is one byte long. In that case, it is natural
                 * for the user to specify a normal hex integer on the RHS, with the "0x"
                 * notation, as in "slice[0] == 0x10". We can't allow this for any
                 * slices that are longer than one byte, because then we'd have to know
                 * which endianness the byte string should be in. */
                else if (len_range == 1 && strlen(s) == 4 && strncmp(s, "0x", 2) == 0) {
                    /* Even if the RHS string starts with "0x", it still could fail to
                     * be an integer.  Try converting it here. */
                    fvalue = fvalue_from_unparsed(FT_UINT8, s, allow_partial_value, dfilter_fail);
                    if (fvalue) {
                        FVALUE_FREE(fvalue);
                        /* The value doees indeed fit into 8 bits. Create a BYTE_STRING
                         * from it. Since we know that the last 2 characters are a valid
                         * hex string, just use those directly. */
                        fvalue = fvalue_from_unparsed(FT_BYTES, s+2, allow_partial_value, dfilter_fail);
                    }
                }
                else {
                    fvalue = fvalue_from_unparsed(FT_BYTES, s, allow_partial_value, dfilter_fail);
                }
		if (!fvalue) {
			DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED): Could not convert from string!\n"));
			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) {
		DebugLog(("    5 check_relation_LHS_RANGE(type2 = STTYPE_RANGE)\n"));
		check_drange_sanity(st_arg2);
	}
	else if (type2 == STTYPE_FUNCTION) {
		funcdef = sttype_function_funcdef(st_arg2);
		ftype2  = funcdef->retval_ftype;

		if (!is_bytes_type(ftype2)) {
			if (!ftype_can_slice(ftype2)) {
				dfilter_fail("Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
					funcdef->name,
					ftype_pretty_name(ftype2));
				THROW(TypeError);
			}

			/* XXX should I add a new drange node? */
		}

		check_function(st_arg2);
	}
	else {
		g_assert_not_reached();
	}
}
示例#8
0
/* If the LHS of a relation test is a FIELD, run some checks
 * and possibly some modifications of syntax tree nodes. */
static void
check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func,
		gboolean allow_partial_value,
		stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
	stnode_t		*new_st;
	sttype_id_t		type2;
	header_field_info	*hfinfo1, *hfinfo2;
	df_func_def_t		*funcdef;
	ftenum_t		ftype1, ftype2;
	fvalue_t		*fvalue;
	char			*s;

	type2 = stnode_type_id(st_arg2);

	hfinfo1 = (header_field_info*)stnode_data(st_arg1);
	ftype1 = hfinfo1->type;

	DebugLog(("    5 check_relation_LHS_FIELD(%s)\n", relation_string));

	if (!can_func(ftype1)) {
		dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.",
				hfinfo1->abbrev, ftype_pretty_name(ftype1),
				relation_string);
		THROW(TypeError);
	}

	if (type2 == STTYPE_FIELD) {
		hfinfo2 = (header_field_info*)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 = (char *)stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_string(FT_PCRE, s, dfilter_fail);
		} else {
			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_UNPARSED) {
		s = (char *)stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = fvalue_from_unparsed(FT_PCRE, s, FALSE, dfilter_fail);
		} else {
			do {
				fvalue = fvalue_from_unparsed(ftype1, s, allow_partial_value, dfilter_fail);
				if (!fvalue) {
					/* check value_string */
					fvalue = mk_fvalue_from_val_string(hfinfo1, s);
				}
				if (!fvalue) {
					/* Try another field with the same name */
					if (hfinfo1->same_name_prev_id != -1) {
						hfinfo1 = proto_registrar_get_nth(hfinfo1->same_name_prev_id);
						ftype1 = hfinfo1->type;
					} else {
						break;
					}
				}
			} while (!fvalue);
		}
		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) {
		check_drange_sanity(st_arg2);
		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 = convert_to_bytes(st_arg1);

			sttype_test_set2_args(st_node, new_st, st_arg2);
		}
	}
	else if (type2 == STTYPE_FUNCTION) {
		funcdef = sttype_function_funcdef(st_arg2);
		ftype2 = funcdef->retval_ftype;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail("%s (type=%s) and return value of %s() (type=%s) are not of compatible types.",
					hfinfo1->abbrev, ftype_pretty_name(ftype1),
					funcdef->name, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}

		if (!can_func(ftype2)) {
			dfilter_fail("return value of %s() (type=%s) cannot participate in specified comparison.",
					funcdef->name, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}

		check_function(st_arg2);
	}
	else {
		g_assert_not_reached();
	}
}
示例#9
0
/* If the LHS of a relation test is a FIELD, run some checks
 * and possibly some modifications of syntax tree nodes. */
static void
check_relation_LHS_FIELD(dfwork_t *dfw, const char *relation_string,
		FtypeCanFunc can_func, gboolean allow_partial_value,
		stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
	stnode_t		*new_st;
	sttype_id_t		type2;
	header_field_info	*hfinfo1, *hfinfo2;
	df_func_def_t		*funcdef;
	ftenum_t		ftype1, ftype2;
	fvalue_t		*fvalue;
	char			*s;

	type2 = stnode_type_id(st_arg2);

	hfinfo1 = (header_field_info*)stnode_data(st_arg1);
	ftype1 = hfinfo1->type;

	if (stnode_type_id(st_node) == STTYPE_TEST) {
		DebugLog(("    5 check_relation_LHS_FIELD(%s)\n", relation_string));
	} else {
		DebugLog(("     6 check_relation_LHS_FIELD(%s)\n", relation_string));
	}

	if (!can_func(ftype1)) {
		dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
				hfinfo1->abbrev, ftype_pretty_name(ftype1),
				relation_string);
		THROW(TypeError);
	}

	if (type2 == STTYPE_FIELD) {
		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
		ftype2 = hfinfo2->type;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail(dfw, "%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(dfw, "%s (type=%s) cannot participate in specified comparison.",
					hfinfo2->abbrev, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}
	}
	else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED) {
		s = (char *)stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			if (type2 == STTYPE_STRING)
				fvalue = dfilter_fvalue_from_string(dfw, FT_PCRE, s);
			else
				fvalue = dfilter_fvalue_from_unparsed(dfw, FT_PCRE, s, FALSE);
		} else {
			/* Skip incompatible fields */
			while (hfinfo1->same_name_prev_id != -1 &&
					((type2 == STTYPE_STRING && ftype1 != FT_STRING && ftype1!= FT_STRINGZ) ||
					(type2 != STTYPE_STRING && (ftype1 == FT_STRING || ftype1== FT_STRINGZ)))) {
				hfinfo1 = proto_registrar_get_nth(hfinfo1->same_name_prev_id);
				ftype1 = hfinfo1->type;
			}

			if (type2 == STTYPE_STRING)
				fvalue = dfilter_fvalue_from_string(dfw, ftype1, s);
			else
				fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value);

			if (!fvalue) {
				/* check value_string */
				fvalue = mk_fvalue_from_val_string(dfw, hfinfo1, s);
			}
		}

		if (!fvalue) {
			THROW(TypeError);
		}

		new_st = stnode_new(STTYPE_FVALUE, fvalue);
		if (stnode_type_id(st_node) == STTYPE_TEST) {
			sttype_test_set2_args(st_node, st_arg1, new_st);
		} else {
			sttype_set_replace_element(st_node, st_arg2, new_st);
		}
		stnode_free(st_arg2);
	}
	else if (type2 == STTYPE_RANGE) {
		check_drange_sanity(dfw, st_arg2);
		if (!is_bytes_type(ftype1)) {
			if (!ftype_can_slice(ftype1)) {
				dfilter_fail(dfw, "\"%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 = convert_to_bytes(st_arg1);

			sttype_test_set2_args(st_node, new_st, st_arg2);
		}
	}
	else if (type2 == STTYPE_FUNCTION) {
		funcdef = sttype_function_funcdef(st_arg2);
		ftype2 = funcdef->retval_ftype;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail(dfw, "%s (type=%s) and return value of %s() (type=%s) are not of compatible types.",
					hfinfo1->abbrev, ftype_pretty_name(ftype1),
					funcdef->name, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}

		if (!can_func(ftype2)) {
			dfilter_fail(dfw, "return value of %s() (type=%s) cannot participate in specified comparison.",
					funcdef->name, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}

		check_function(dfw, st_arg2);
	}
	else if (type2 == STTYPE_SET) {
		GSList *nodelist;
		/* A set should only ever appear on RHS of 'in' operation */
		if (strcmp(relation_string, "in") != 0) {
			g_assert_not_reached();
		}
		/* Attempt to interpret one element of the set at a time */
		nodelist = (GSList*)stnode_data(st_arg2);
		while (nodelist) {
			stnode_t *node = (stnode_t*)nodelist->data;
			/* Don't let a range on the RHS affect the LHS field. */
			if (stnode_type_id(node) == STTYPE_RANGE) {
				dfilter_fail(dfw, "A range may not appear inside a set.");
				THROW(TypeError);
				break;
			}
			check_relation_LHS_FIELD(dfw, "==", can_func,
					allow_partial_value, st_arg2, st_arg1, node);
			nodelist = g_slist_next(nodelist);
		}
	}
	else {
		g_assert_not_reached();
	}
}
示例#10
0
/* If the LHS of a relation test is a FUNCTION, run some checks
 * and possibly some modifications of syntax tree nodes. */
static void
check_relation_LHS_FUNCTION(dfwork_t *dfw, const char *relation_string,
		FtypeCanFunc can_func,
		gboolean allow_partial_value,
		stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
	stnode_t		*new_st;
	sttype_id_t		type2;
	header_field_info	*hfinfo2;
	ftenum_t		ftype1, ftype2;
	fvalue_t		*fvalue;
	char			*s;
	df_func_def_t   *funcdef;
	df_func_def_t   *funcdef2;
	/* GSList          *params; */

	check_function(dfw, st_arg1);
	type2 = stnode_type_id(st_arg2);

	funcdef = sttype_function_funcdef(st_arg1);
	ftype1 = funcdef->retval_ftype;

	/* params = */sttype_function_params(st_arg1);  /* XXX: is this done for the side-effect ? */

	DebugLog(("    5 check_relation_LHS_FUNCTION(%s)\n", relation_string));

	if (!can_func(ftype1)) {
		dfilter_fail(dfw, "Function %s (type=%s) cannot participate in '%s' comparison.",
				funcdef->name, ftype_pretty_name(ftype1),
				relation_string);
		THROW(TypeError);
	}

	if (type2 == STTYPE_FIELD) {
		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
		ftype2 = hfinfo2->type;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail(dfw, "Function %s and %s are not of compatible types.",
					funcdef->name, 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(dfw, "%s (type=%s) cannot participate in specified comparison.",
					hfinfo2->abbrev, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}
	}
	else if (type2 == STTYPE_STRING) {
		s = (char*)stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = dfilter_fvalue_from_string(dfw, FT_PCRE, s);
		} else {
			fvalue = dfilter_fvalue_from_string(dfw, ftype1, 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_UNPARSED) {
		s = (char*)stnode_data(st_arg2);
		if (strcmp(relation_string, "matches") == 0) {
			/* Convert to a FT_PCRE */
			fvalue = dfilter_fvalue_from_unparsed(dfw, FT_PCRE, s, FALSE);
		} else {
			fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value);
		}
		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) {
		check_drange_sanity(dfw, st_arg2);
		if (!is_bytes_type(ftype1)) {
			if (!ftype_can_slice(ftype1)) {
				dfilter_fail(dfw, "Function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
						funcdef->name,
						ftype_pretty_name(ftype1));
				THROW(TypeError);
			}

			/* Convert function result to bytes */
			new_st = convert_to_bytes(st_arg1);

			sttype_test_set2_args(st_node, new_st, st_arg2);
		}
	}
	else if (type2 == STTYPE_FUNCTION) {
		funcdef2 = sttype_function_funcdef(st_arg2);
		ftype2 = funcdef2->retval_ftype;

		if (!compatible_ftypes(ftype1, ftype2)) {
			dfilter_fail(dfw, "Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.",
				     funcdef->name, ftype_pretty_name(ftype1), funcdef2->name, ftype_pretty_name(ftype2));
			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(dfw, "Return value of %s (type=%s) cannot participate in specified comparison.",
				     funcdef2->name, ftype_pretty_name(ftype2));
			THROW(TypeError);
		}

		check_function(dfw, st_arg2);
	}
	else if (type2 == STTYPE_SET) {
		dfilter_fail(dfw, "Only a field may be tested for membership in a set.");
		THROW(TypeError);
	}
	else {
		g_assert_not_reached();
	}
}