Add to the fundamental types passed between the scanner and the parser.

Besides "STRING", there is now "UNPARSED_STRING", where the distinction
is that "STRING" was a double-quoted string and "UNPARSED_STRING" is just
a sequence of characters that the scanner didn't know how to scan/parse,
so it's up to the Ftype to parse it.

This gives us more flexibility and prepares the dfilter parsing engine
for the upcoming addition of the "contains" operator.

In the process of doing this, I also re-did the double-quoted string
support in the scanner, so that instead of the naively-simple support we
used to have, double-quoted strings now can have embedded dobule-quotes,
embedded octal sequences, and embedded hexadecimal sequences:
    "\""    embedded double-quote
    "\110"  embedded octal
    "\x48"  embedded hex

Enhance the dfilter unit test script to be able to run a single collection
of tests instead of having to run all of them all the time.

svn path=/trunk/; revision=8083
This commit is contained in:
Gilbert Ramirez 2003-07-25 03:44:05 +00:00
parent c2150d9d77
commit 086774b71f
21 changed files with 476 additions and 123 deletions

View File

@ -1,4 +1,4 @@
$Id: README.developer,v 1.76 2003/07/07 22:59:54 guy Exp $
$Id: README.developer,v 1.77 2003/07/25 03:43:59 gram Exp $
This file is a HOWTO for Ethereal developers. It describes how to start coding
a Ethereal protocol dissector and the use some of the important functions and
@ -208,7 +208,7 @@ code inside
is needed only if you are using the "snprintf()" function.
The "$Id: README.developer,v 1.76 2003/07/07 22:59:54 guy Exp $"
The "$Id: README.developer,v 1.77 2003/07/25 03:43:59 gram Exp $"
in the comment will be updated by CVS when the file is
checked in; it will allow the RCS "ident" command to report which
version of the file is currently checked out.
@ -218,7 +218,7 @@ version of the file is currently checked out.
* Routines for PROTONAME dissection
* Copyright 2000, YOUR_NAME <YOUR_EMAIL_ADDRESS>
*
* $Id: README.developer,v 1.76 2003/07/07 22:59:54 guy Exp $
* $Id: README.developer,v 1.77 2003/07/25 03:43:59 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -2136,7 +2136,55 @@ a dissector.
4.0 Extending Wiretap.
5.0 Adding new capabilities.
5.0 How the Display Filter Engine works
code:
epan/dfilter/* - the display filter engine, including
scanner, parser, syntax-tree semantics checker, DFVM bytecode
generator, and DFVM engine.
epan/ftypes/* - the definitions of the various FT_* field types.
epan/proto.c - proto_tree-related routines
5.1 Parsing text
The scanner/parser pair read the string representing the display filter and
convert it into a very simple syntax tree. The syntax tree is very simple in that
it is possible that many of the nodes contain unparsed chunks of text from the display
filter.
5.1 Enhancing the syntax tree.
The semantics of the simple syntax tree are checked to make sure that the fields
that are being compared are being compared to appropriate values. For example,
if a field is an integer, it can't be compared to a string, unless a value_string
has been defined for that field.
During the process of checking the semantics, the simple syntax tree is fleshed out
and no longer contains nodes with unparsed information. The syntax tree is no
longer in its simple form, but in its complete form.
5.2 Converting to DFVM bytecode
The syntax tree is analyzed to create a sequence of bytecodes in the "DFVM" language.
"DFVM" stands for Display Filter Virtual Machine. The DFVM is similar in spirit, but
not in definition, to the BPF VM that libpcap uses to analyze packets.
A virtual bytecode is created and used so that the actual process of filtering packets
will be fast. That is, it should be faster to process a list of VM bytecodes than
to attempt to filter packets directly from the syntax tree. (heh... no measurement
has been made to support this supposition)
5.3 Filtering
Once the DFVM bytecode has been produced, its a simple matter of running the
DFVM engine against the proto_tree from the packet dissection, using the DFVM bytecodes
as instructions. If the DFVM bytecode is known before packet dissection occurs,
the proto_tree-related code can be "primed" to store away pointers to field_info
structures that are interesting to the display filter. This makes lookup of those
field_info structures during the filtering process faster.
6.0 Adding new capabilities.

View File

@ -1332,6 +1332,23 @@ you will be using hexadecimal when testing for IPX network values:
ipx.srcnet == 0xc0a82c00
Strings are enclosed in double-quotes:
http.request.method == "POST"
Inside doulbe quotes, you may use the backslash to embed a double-quote,
or an arbitrary byte represented in either octal or hexadecimal.
browser.comment = "An embedded \" double-quote"
Use of hexadecimal to look for "HEAD":
http.request.method == "\x48EAD"
Use of octal to look for "HEAD":
http.request.method == "\x110EAD"
A slice operator also exists. You can check the substring
(byte-string) of any protocol or field. For example, you can filter on
the vendor portion of an ethernet address (the first three bytes) like

View File

@ -672,6 +672,23 @@ you will be using hexadecimal when testing for IPX network values:
ipx.srcnet == 0xc0a82c00
Strings are enclosed in double-quotes:
http.request.method == "POST"
Inside doulbe quotes, you may use the backslash to embed a double-quote,
or an arbitrary byte represented in either octal or hexadecimal.
browser.comment = "An embedded \" double-quote"
Use of hexadecimal to look for "HEAD":
http.request.method == "\x48EAD"
Use of octal to look for "HEAD":
http.request.method == "\x110EAD"
A slice operator also exists. You can check the substring
(byte-string) of any protocol or field. For example, you can filter on
the vendor portion of an ethernet address (the first three bytes) like

View File

@ -1,4 +1,4 @@
/* $Id: grammar.lemon,v 1.4 2001/06/22 16:29:13 gram Exp $ */
/* $Id: grammar.lemon,v 1.5 2003/07/25 03:44:01 gram Exp $ */
%include {
#ifdef HAVE_CONFIG_H
@ -71,6 +71,10 @@ any "error" symbols are shifted, if possible. */
dfilter_fail("The string \"%s\" was unexpected in this context.",
stnode_data(TOKEN));
break;
case STTYPE_UNPARSED:
dfilter_fail("\"%s\" was unexpected in this context.",
stnode_data(TOKEN));
break;
case STTYPE_INTEGER:
dfilter_fail("The integer %u was unexpected in this context.",
stnode_value(TOKEN));
@ -150,18 +154,9 @@ logical_test(T) ::= FIELD(F).
/* Entities, or things that can be compared/tested/checked */
entity(E) ::= FIELD(F). { E = F; }
entity(E) ::= STRING(S). { E = S; }
entity(E) ::= UNPARSED(U). { E = U; }
entity(E) ::= range(R). { E = R; }
/* CIDR: ADDRESS/NET */
entity(E) ::= STRING(A) SLASH STRING(N).
{
E = stnode_new(STTYPE_STRING, g_strjoin("/", stnode_data(A),
stnode_data(N), NULL));
stnode_free(A);
stnode_free(N);
}
/* Ranges */
range(R) ::= FIELD(F) LBRACKET drnode_list(L) RBRACKET.

View File

@ -1,6 +1,6 @@
%{
/*
* $Id: scanner.l,v 1.7 2002/04/29 07:55:32 guy Exp $
* $Id: scanner.l,v 1.8 2003/07/25 03:44:01 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -46,12 +46,15 @@ static int set_lval(int token, gpointer data);
static int set_lval_int(int token, char *s);
static int simple(int token);
static gboolean str_to_guint32(char *s, guint32* pint);
GString* quoted_string = NULL;
#define SCAN_FAILED 0
%}
%x RANGE_INT
%x RANGE_PUNCT
%x DQUOTE
%%
@ -61,7 +64,6 @@ static gboolean str_to_guint32(char *s, guint32* pint);
"(" return simple(TOKEN_LPAREN);
")" return simple(TOKEN_RPAREN);
"/" return simple(TOKEN_SLASH);
"==" return simple(TOKEN_TEST_EQ);
"eq" return simple(TOKEN_TEST_EQ);
@ -94,6 +96,7 @@ static gboolean str_to_guint32(char *s, guint32* pint);
BEGIN(RANGE_PUNCT);
return set_lval_int(TOKEN_INTEGER, yytext);
}
<RANGE_INT>[+-]?0x[[:xdigit:]]+ {
BEGIN(RANGE_PUNCT);
return set_lval_int(TOKEN_INTEGER, yytext);
@ -119,12 +122,64 @@ static gboolean str_to_guint32(char *s, guint32* pint);
return simple(TOKEN_RBRACKET);
}
\" {
/* start quote */
/* The example of how to scan for strings was taken from
the flex 2.5.4 manual, from the section "Start Conditions".
See:
http://www.gnu.org/manual/flex-2.5.4/html_node/flex_11.html */
\"[^"]*\" {
return set_lval(TOKEN_STRING, g_substrdup(yytext, 1, -2));
BEGIN(DQUOTE);
g_assert(!quoted_string);
quoted_string = g_string_new("");
}
<DQUOTE>\" {
/* end quote */
char *my_string = g_strdup(quoted_string->str);
BEGIN(INITIAL);
g_string_free(quoted_string, TRUE);
quoted_string = NULL;
return set_lval(TOKEN_STRING, my_string);
}
<DQUOTE>\\[0-7]{1,3} {
/* octal sequence */
unsigned int result;
sscanf(yytext + 1, "%o", &result);
if (result > 0xff) {
g_string_free(quoted_string, TRUE);
quoted_string = NULL;
dfilter_fail("%s is larger than 255.", yytext);
return SCAN_FAILED;
}
g_string_append_c(quoted_string, result);
}
<DQUOTE>\\x[[:xdigit:]]{1,2} {
/* hex sequence */
unsigned int result;
sscanf(yytext + 2, "%x", &result);
g_string_append_c(quoted_string, result);
}
<DQUOTE>\\. {
/* escaped character */
g_string_append_c(quoted_string, yytext[1]);
}
<DQUOTE>[^\\\"]+ {
/* non-escaped string */
g_string_append(quoted_string, yytext);
}
[-[:alnum:]_\.]+\/[[:digit:]]+ {
/* CIDR */
return set_lval(TOKEN_UNPARSED, g_strdup(yytext));
}
[-[:alnum:]_.:]+ {
/* Is it a field name? */
@ -136,14 +191,14 @@ static gboolean str_to_guint32(char *s, guint32* pint);
return set_lval(TOKEN_FIELD, hfinfo);
}
else {
/* No, so treat it as a string */
return set_lval(TOKEN_STRING, g_strdup(yytext));
/* No, so treat it as an unparsed string */
return set_lval(TOKEN_UNPARSED, g_strdup(yytext));
}
}
. {
/* Default */
return set_lval(TOKEN_STRING, g_strdup(yytext));
return set_lval(TOKEN_UNPARSED, g_strdup(yytext));
}
@ -160,7 +215,6 @@ simple(int token)
case TOKEN_COLON:
case TOKEN_COMMA:
case TOKEN_HYPHEN:
case TOKEN_SLASH:
case TOKEN_TEST_EQ:
case TOKEN_TEST_NE:
case TOKEN_TEST_GT:
@ -189,6 +243,9 @@ set_lval(int token, gpointer data)
case TOKEN_FIELD:
type_id = STTYPE_FIELD;
break;
case TOKEN_UNPARSED:
type_id = STTYPE_UNPARSED;
break;
default:
g_assert_not_reached();
}
@ -204,7 +261,7 @@ set_lval_int(int token, char *s)
guint32 val;
if (!str_to_guint32(s, &val)) {
return 0;
return SCAN_FAILED;
}
switch (token) {

View File

@ -1,5 +1,5 @@
/*
* $Id: semcheck.c,v 1.17 2003/06/13 07:39:26 guy Exp $
* $Id: semcheck.c,v 1.18 2003/07/25 03:44:01 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -47,15 +47,15 @@ compatible_ftypes(ftenum_t a, ftenum_t b)
switch (a) {
case FT_NONE:
case FT_PROTOCOL:
case FT_FLOAT:
case FT_DOUBLE:
case FT_FLOAT: /* XXX - should be able to compare with INT */
case FT_DOUBLE: /* XXX - should be able to compare with INT */
case FT_ABSOLUTE_TIME:
case FT_RELATIVE_TIME:
case FT_IPv4:
case FT_IPv6:
case FT_IPXNET:
case FT_INT64:
case FT_UINT64:
case FT_INT64: /* XXX - should be able to compare with INT */
case FT_UINT64: /* XXX - should be able to compare with INT */
return a == b;
case FT_ETHER:
@ -187,7 +187,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s)
return mk_uint32_fvalue(FALSE);
}
else {
dfilter_fail("\"%s\" cannot be found among the possible values for %s.",
dfilter_fail("\"%s\" cannot be found among the possible values for %s.",
s, hfinfo->abbrev);
return NULL;
}
@ -256,9 +256,11 @@ is_bytes_type(enum ftenum type)
return FALSE;
}
/* 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(FtypeCanFunc can_func, stnode_t *st_node,
stnode_t *st_arg1, stnode_t *st_arg2)
check_relation_LHS_FIELD(const char *relation_string, FtypeCanFunc can_func,
stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
{
stnode_t *new_st;
sttype_id_t type1, type2;
@ -275,8 +277,9 @@ check_relation_LHS_FIELD(FtypeCanFunc can_func, stnode_t *st_node,
ftype1 = hfinfo1->type;
if (!can_func(ftype1)) {
dfilter_fail("%s (type=%s) cannot participate in specified comparison.",
hfinfo1->abbrev, ftype_pretty_name(ftype1));
dfilter_fail("%s (type=%s) cannot participate in '%s' comparison.",
hfinfo1->abbrev, ftype_pretty_name(ftype1),
relation_string);
THROW(TypeError);
}
@ -313,6 +316,21 @@ check_relation_LHS_FIELD(FtypeCanFunc can_func, stnode_t *st_node,
sttype_test_set2_args(st_node, st_arg1, new_st);
stnode_free(st_arg2);
}
else if (type2 == STTYPE_UNPARSED) {
s = stnode_data(st_arg2);
fvalue = fvalue_from_unparsed(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)) {
@ -393,6 +411,60 @@ check_relation_LHS_STRING(FtypeCanFunc can_func _U_, stnode_t *st_node,
}
}
static void
check_relation_LHS_UNPARSED(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_unparsed(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_unparsed(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();
}
}
struct check_drange_sanity_args {
drange_node* err_node;
};
@ -515,6 +587,16 @@ check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
sttype_test_set2_args(st_node, st_arg1, new_st);
stnode_free(st_arg2);
}
else if (type2 == STTYPE_UNPARSED) {
s = stnode_data(st_arg2);
fvalue = fvalue_from_unparsed(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) {
check_drange_sanity(st_arg2);
/* XXX - check lengths of both ranges */
@ -525,13 +607,14 @@ check_relation_LHS_RANGE(FtypeCanFunc can_func _U_, stnode_t *st_node,
}
/* Check the semantics of any relational test. */
static void
check_relation(FtypeCanFunc can_func, stnode_t *st_node,
check_relation(const char *relation_string, 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);
check_relation_LHS_FIELD(relation_string, can_func, st_node, st_arg1, st_arg2);
break;
case STTYPE_STRING:
check_relation_LHS_STRING(can_func, st_node, st_arg1, st_arg2);
@ -539,6 +622,9 @@ check_relation(FtypeCanFunc can_func, stnode_t *st_node,
case STTYPE_RANGE:
check_relation_LHS_RANGE(can_func, st_node, st_arg1, st_arg2);
break;
case STTYPE_UNPARSED:
check_relation_LHS_UNPARSED(can_func, st_node, st_arg1, st_arg2);
break;
case STTYPE_UNINITIALIZED:
case STTYPE_TEST:
@ -549,6 +635,7 @@ check_relation(FtypeCanFunc can_func, stnode_t *st_node,
}
}
/* Check the semantics of any type of TEST */
static void
check_test(stnode_t *st_node)
{
@ -577,34 +664,33 @@ check_test(stnode_t *st_node)
break;
case TEST_OP_EQ:
check_relation(ftype_can_eq, st_node, st_arg1, st_arg2);
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);
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);
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);
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);
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);
check_relation("<=", ftype_can_le, st_node, st_arg1, st_arg2);
break;
}
}
/* Check the entire syntax tree. */
static void
semcheck(stnode_t *st_node)
{
const char *name;
name = stnode_type_name(st_node);
/* The parser assures that the top-most syntax-tree
* node will be a TEST node, no matter what. So assert that. */
switch (stnode_type_id(st_node)) {
case STTYPE_TEST:
check_test(st_node);
@ -615,9 +701,15 @@ semcheck(stnode_t *st_node)
}
/* Check the syntax tree for semantic errors, and convert
* some of the nodes into the form they need to be in order to
* later generate the DFVM bytecode. */
gboolean
dfw_semcheck(dfwork_t *dfw)
{
/* Instead of having to check for errors at every stage of
* the semantic-checking, the semantic-checking code will
* throw an exception if a problem is found. */
TRY {
semcheck(dfw->st_root);
}

View File

@ -1,5 +1,5 @@
/*
* $Id: sttype-string.c,v 1.3 2002/08/28 20:40:56 jmayer Exp $
* $Id: sttype-string.c,v 1.4 2003/07/25 03:44:01 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -46,5 +46,13 @@ sttype_register_string(void)
string_free,
};
static sttype_t unparsed_type = {
STTYPE_UNPARSED,
"UNPARSED",
string_new,
string_free,
};
sttype_register(&string_type);
sttype_register(&unparsed_type);
}

View File

@ -1,5 +1,5 @@
/*
* $Id: syntax-tree.h,v 1.4 2002/08/28 20:40:56 jmayer Exp $
* $Id: syntax-tree.h,v 1.5 2003/07/25 03:44:01 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -30,6 +30,7 @@
typedef enum {
STTYPE_UNINITIALIZED,
STTYPE_TEST,
STTYPE_UNPARSED,
STTYPE_STRING,
STTYPE_FIELD,
STTYPE_FVALUE,

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-bytes.c,v 1.15 2003/06/11 21:24:53 gram Exp $
* $Id: ftype-bytes.c,v 1.16 2003/07/25 03:44:02 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -129,7 +129,7 @@ is_byte_sep(guint8 c)
}
static gboolean
val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
GByteArray *bytes;
guint8 val;
@ -226,7 +226,7 @@ val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
}
static gboolean
ether_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
ether_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
guint8 *mac;
@ -235,7 +235,7 @@ ether_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
* up as an Ethernet host name if it does, and if that fails,
* we'll log a message.
*/
if (val_from_string(fv, s, NULL)) {
if (val_from_unparsed(fv, s, NULL)) {
return TRUE;
}
@ -251,7 +251,7 @@ ether_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
}
static gboolean
ipv6_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
ipv6_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
guint8 buffer[16];
@ -265,7 +265,7 @@ ipv6_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
}
static gboolean
u64_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
u64_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
guint8 buffer[8];
@ -279,7 +279,7 @@ u64_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
}
static gboolean
i64_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
i64_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
guint8 buffer[8];
@ -587,7 +587,8 @@ ftype_register_bytes(void)
0, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
bytes_to_repr, /* val_to_string_repr */
bytes_repr_len, /* len_string_repr */
@ -616,7 +617,8 @@ ftype_register_bytes(void)
0, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
bytes_to_repr, /* val_to_string_repr */
bytes_repr_len, /* len_string_repr */
@ -645,7 +647,8 @@ ftype_register_bytes(void)
ETHER_LEN, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
ether_from_string, /* val_from_string */
ether_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
bytes_to_repr, /* val_to_string_repr */
bytes_repr_len, /* len_string_repr */
@ -674,7 +677,8 @@ ftype_register_bytes(void)
IPv6_LEN, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
ipv6_from_string, /* val_from_string */
ipv6_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -703,7 +707,8 @@ ftype_register_bytes(void)
U64_LEN, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
u64_from_string, /* val_from_string */
u64_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -732,7 +737,8 @@ ftype_register_bytes(void)
U64_LEN, /* wire_size */
bytes_fvalue_new, /* new_value */
bytes_fvalue_free, /* free_value */
i64_from_string, /* val_from_string */
i64_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-double.c,v 1.8 2003/02/08 04:22:37 gram Exp $
* $Id: ftype-double.c,v 1.9 2003/07/25 03:44:02 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -48,7 +48,7 @@ value_get_floating(fvalue_t *fv)
}
static gboolean
val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
char *endptr = NULL;
@ -123,7 +123,8 @@ ftype_register_double(void)
0,
double_fvalue_new,
NULL,
val_from_string,
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -152,7 +153,8 @@ ftype_register_double(void)
0,
double_fvalue_new,
NULL,
val_from_string,
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-integer.c,v 1.13 2003/06/11 21:24:53 gram Exp $
* $Id: ftype-integer.c,v 1.14 2003/07/25 03:44:02 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -49,7 +49,7 @@ get_integer(fvalue_t *fv)
}
static gboolean
val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
char *endptr;
@ -78,7 +78,7 @@ val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
}
static gboolean
ipxnet_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
ipxnet_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
guint32 val;
gboolean known;
@ -88,7 +88,7 @@ ipxnet_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
* up as an IPX network name if it does, and if that fails,
* we'll log a message.
*/
if (val_from_string(fv, s, NULL)) {
if (val_from_unparsed(fv, s, NULL)) {
return TRUE;
}
@ -223,7 +223,8 @@ ftype_register_integers(void)
1, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -251,7 +252,8 @@ ftype_register_integers(void)
2, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -279,7 +281,8 @@ ftype_register_integers(void)
3, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -307,7 +310,8 @@ ftype_register_integers(void)
4, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -335,7 +339,8 @@ ftype_register_integers(void)
1, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -363,7 +368,8 @@ ftype_register_integers(void)
2, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -391,7 +397,8 @@ ftype_register_integers(void)
3, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -419,7 +426,8 @@ ftype_register_integers(void)
4, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -447,7 +455,8 @@ ftype_register_integers(void)
0, /* wire_size */
boolean_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
boolean_to_repr, /* val_to_string_repr */
boolean_repr_len, /* len_string_repr */
@ -476,7 +485,8 @@ ftype_register_integers(void)
4, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
ipxnet_from_string, /* val_from_string */
ipxnet_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -505,7 +515,8 @@ ftype_register_integers(void)
4, /* wire_size */
int_fvalue_new, /* new_value */
NULL, /* free_value */
val_from_string, /* val_from_string */
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-ipv4.c,v 1.10 2003/02/08 04:22:37 gram Exp $
* $Id: ftype-ipv4.c,v 1.11 2003/07/25 03:44:02 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -45,7 +45,7 @@ value_get(fvalue_t *fv)
}
static gboolean
val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
guint32 addr;
unsigned int nmask_bits;
@ -98,7 +98,8 @@ val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
return FALSE;
}
nmask_fvalue = fvalue_from_string(FT_UINT32, net_str, logfunc);
/* XXX - this is inefficient */
nmask_fvalue = fvalue_from_unparsed(FT_UINT32, net_str, logfunc);
g_free(s_copy);
if (!nmask_fvalue) {
return FALSE;
@ -167,7 +168,8 @@ ftype_register_ipv4(void)
4,
NULL,
NULL,
val_from_string,
val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-none.c,v 1.5 2003/02/08 04:22:37 gram Exp $
* $Id: ftype-none.c,v 1.6 2003/07/25 03:44:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -39,6 +39,7 @@ ftype_register_none(void)
NULL,
NULL,
NULL,
NULL,
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-string.c,v 1.9 2003/06/11 21:24:53 gram Exp $
* $Id: ftype-string.c,v 1.10 2003/07/25 03:44:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -154,6 +154,7 @@ ftype_register_string(void)
0, /* wire_size */
string_fvalue_new, /* new_value */
string_fvalue_free, /* free_value */
val_from_string, /* val_from_unparsed */
val_from_string, /* val_from_string */
string_to_repr, /* val_to_string_repr */
string_repr_len, /* len_string_repr */
@ -182,7 +183,8 @@ ftype_register_string(void)
0,
string_fvalue_new,
string_fvalue_free,
val_from_string,
val_from_string, /* val_from_unparsed */
val_from_string, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -210,7 +212,8 @@ ftype_register_string(void)
0,
string_fvalue_new,
string_fvalue_free,
val_from_string,
val_from_string, /* val_from_unparsed */
val_from_string, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-time.c,v 1.18 2003/02/08 04:22:37 gram Exp $
* $Id: ftype-time.c,v 1.19 2003/07/25 03:44:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -167,7 +167,7 @@ get_nsecs(char *startp, int *nsecs)
}
static gboolean
relative_val_from_string(fvalue_t *fv, char *s, LogFunc logfunc)
relative_val_from_unparsed(fvalue_t *fv, char *s, LogFunc logfunc)
{
char *curptr, *endptr;
@ -307,7 +307,8 @@ ftype_register_time(void)
0,
time_fvalue_new,
NULL,
absolute_val_from_string,
absolute_val_from_string, /* val_from_unparsed */
absolute_val_from_string, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */
@ -334,7 +335,8 @@ ftype_register_time(void)
0,
time_fvalue_new,
NULL,
relative_val_from_string,
relative_val_from_unparsed, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftype-tvbuff.c,v 1.8 2003/02/08 04:22:37 gram Exp $
* $Id: ftype-tvbuff.c,v 1.9 2003/07/25 03:44:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -84,7 +84,8 @@ ftype_register_tvbuff(void)
0,
value_new,
NULL,
NULL,
NULL, /* val_from_unparsed */
NULL, /* val_from_string */
NULL, /* val_to_string_repr */
NULL, /* len_string_repr */

View File

@ -1,5 +1,5 @@
/*
* $Id: ftypes-int.h,v 1.8 2003/06/11 21:24:54 gram Exp $
* $Id: ftypes-int.h,v 1.9 2003/07/25 03:44:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -29,6 +29,7 @@
typedef void (*FvalueNewFunc)(fvalue_t*);
typedef void (*FvalueFreeFunc)(fvalue_t*);
typedef gboolean (*FvalueFromUnparsed)(fvalue_t*, char*, LogFunc);
typedef gboolean (*FvalueFromString)(fvalue_t*, char*, LogFunc);
typedef void (*FvalueToStringRepr)(fvalue_t*, ftrepr_t, char*);
typedef int (*FvalueStringReprLen)(fvalue_t*, ftrepr_t);
@ -52,6 +53,7 @@ struct _ftype_t {
int wire_size;
FvalueNewFunc new_value;
FvalueFreeFunc free_value;
FvalueFromUnparsed val_from_unparsed;
FvalueFromString val_from_string;
FvalueToStringRepr val_to_string_repr;
FvalueStringReprLen len_string_repr;

View File

@ -1,5 +1,5 @@
/*
* $Id: ftypes.c,v 1.9 2003/06/11 21:24:54 gram Exp $
* $Id: ftypes.c,v 1.10 2003/07/25 03:44:03 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -235,7 +235,24 @@ fvalue_free(fvalue_t *fv)
g_mem_chunk_free(gmc_fvalue, fv);
}
fvalue_t*
fvalue_from_unparsed(ftenum_t ftype, char *s, LogFunc logfunc)
{
fvalue_t *fv;
fv = fvalue_new(ftype);
if (fv->ftype->val_from_unparsed) {
if (fv->ftype->val_from_unparsed(fv, s, logfunc)) {
return fv;
}
}
else {
logfunc("\"%s\" cannot be converted to %s.",
s, ftype_pretty_name(ftype));
}
fvalue_free(fv);
return NULL;
}
fvalue_t*
fvalue_from_string(ftenum_t ftype, char *s, LogFunc logfunc)

View File

@ -1,7 +1,7 @@
/* ftypes.h
* Definitions for field types
*
* $Id: ftypes.h,v 1.17 2003/06/11 21:24:54 gram Exp $
* $Id: ftypes.h,v 1.18 2003/07/25 03:44:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -73,6 +73,7 @@ enum ftrepr {
typedef enum ftrepr ftrepr_t;
/* Initialize the ftypes subsytem. Called once. */
void
ftypes_initialize(void);
@ -150,6 +151,9 @@ fvalue_free(fvalue_t *fv);
typedef void (*LogFunc)(char*,...);
fvalue_t*
fvalue_from_unparsed(ftenum_t ftype, char *s, LogFunc log);
fvalue_t*
fvalue_from_string(ftenum_t ftype, char *s, LogFunc log);

View File

@ -7,7 +7,7 @@
* Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com> and
* Guy Harris <guy@alum.mit.edu>
*
* $Id: dfilter_expr_dlg.c,v 1.33 2003/03/10 02:06:33 jmayer Exp $
* $Id: dfilter_expr_dlg.c,v 1.34 2003/07/25 03:44:04 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -928,7 +928,7 @@ dfilter_expr_dlg_accept_cb(GtkWidget *w, gpointer filter_te_arg)
* for the type of the field; if a range string was
* specified, must be valid for FT_BYTES.
*/
fvalue = fvalue_from_string(ftype, stripped_value_str,
fvalue = fvalue_from_unparsed(ftype, stripped_value_str,
dfilter_report_bad_value);
if (fvalue == NULL) {
/*

View File

@ -4,7 +4,7 @@ Test-suite to test ethereal's dfilter mechanism.
"""
#
# $Id: dfilter-test.py,v 1.1 2003/07/09 03:57:34 gram Exp $
# $Id: dfilter-test.py,v 1.2 2003/07/25 03:44:05 gram Exp $
#
# Copyright (C) 2003 by Gilbert Ramirez <gram@alumni.rice.edu>
#
@ -340,11 +340,11 @@ pkt_tftp.data = """
# Add tests here
################################################################################
class Ftype_Bytes(Test):
class Bytes(Test):
"""Tests routines in ftype-bytes.c"""
def __init__(self):
print "Note: Ftype_Bytes does not yet test FT_INT64."
print "Note: Bytes test does not yet test FT_INT64."
def ck_eq_1(self):
return self.DFilterCount(pkt_ipx_rip,
@ -485,7 +485,7 @@ class Ftype_Bytes(Test):
]
class Ftype_Double(Test):
class Double(Test):
"""Tests routines in ftype-double.c"""
def ck_eq_1(self):
@ -564,7 +564,7 @@ class Ftype_Double(Test):
ck_le_3,
]
class Ftype_Integer(Test):
class Integer(Test):
"""Tests routines in ftype-integer.c"""
def ck_eq_1(self):
@ -741,7 +741,7 @@ class Ftype_Integer(Test):
ck_ipx_2,
]
class Ftype_IPv4(Test):
class IPv4(Test):
"""Tests routines in ftype-ipv4.c"""
def ck_eq_1(self):
@ -867,7 +867,7 @@ class Ftype_IPv4(Test):
ck_cidr_ne_4,
]
class Ftype_String(Test):
class String(Test):
"""Tests routines in ftype-string.c"""
def ck_eq_1(self):
@ -998,7 +998,7 @@ class Ftype_String(Test):
]
class Ftype_Time(Test):
class Time(Test):
"""Tests routines in ftype-time.c"""
def ck_eq_1(self):
@ -1099,7 +1099,7 @@ class Ftype_Time(Test):
ck_relative_time_3,
]
class Ftype_TVB(Test):
class TVB(Test):
"""Tests routines in ftype-tvb.c"""
def ck_slice_1(self):
@ -1134,15 +1134,73 @@ class Ftype_TVB(Test):
# ck_slice_5,
]
class Scanner(Test):
"""Tests routines in scanner.l"""
def __init__(self):
print "Note: Scanner test does not yet test embedded double-quote."
def ck_dquote_1(self):
return self.DFilterCount(pkt_http,
'http.request.method == "HEAD"', 1)
def ck_dquote_2(self):
return self.DFilterCount(pkt_http,
'http.request.method == "\\x48EAD"', 1)
def ck_dquote_3(self):
return self.DFilterCount(pkt_http,
'http.request.method == "\\x58EAD"', 0)
def ck_dquote_4(self):
return self.DFilterCount(pkt_http,
'http.request.method == "\\110EAD"', 1)
def ck_dquote_5(self):
return self.DFilterCount(pkt_http,
'http.request.method == "\\111EAD"', 0)
def ck_dquote_6(self):
return self.DFilterCount(pkt_http,
'http.request.method == "\\HEAD"', 1)
tests = [
ck_dquote_1,
ck_dquote_2,
ck_dquote_3,
ck_dquote_4,
ck_dquote_5,
]
################################################################################
# These are the test objects to run.
# Keep these in alphabetical order so the help message
# shows them in order.
all_tests = [
Bytes(),
Double(),
Integer(),
IPv4(),
Scanner(),
String(),
Time(),
TVB(),
]
def usage():
print "usage: %s [OPTS]" % (sys.argv[0],)
print "usage: %s [OPTS] [TEST ...]" % (sys.argv[0],)
print "\t-p PATH : path to find both tethereal and text2pcap (DEFAULT: . )"
print "\t-t FILE : location of tethereal binary"
print "\t-x FILE : location of text2pcap binary"
print "\t-k : keep temporary files"
print "\t-v : verbose"
print
print "By not mentioning a test name, all tests are run."
print "Available tests are:"
for test in all_tests:
print "\t", test.__class__.__name__
sys.exit(1)
def main():
@ -1157,7 +1215,7 @@ def main():
longopts = []
try:
opts, args = getopt.getopt(sys.argv[1:], optstring, longopts)
opts, specific_tests = getopt.getopt(sys.argv[1:], optstring, longopts)
except getopt.GetoptError:
usage()
@ -1185,22 +1243,31 @@ def main():
sys.exit("text2pcap program '%s' does not exist." % (TEXT2PCAP,))
# These are the test objects to run.
tests = [
Ftype_Bytes(),
Ftype_Double(),
Ftype_Integer(),
Ftype_IPv4(),
Ftype_String(),
Ftype_Time(),
Ftype_TVB(),
]
# Determine which tests to run.
tests_to_run = []
if specific_tests:
# Go through the tests looking for the ones whose names
# match the command-line arguments.
all_ok = 1
for test_name in specific_tests:
for test in all_tests:
if test_name == test.__class__.__name__:
tests_to_run.append(test)
break
else:
print >> sys.stderr, "%s is unrecognized as a test." % \
(test_name,)
all_ok = 0
if not all_ok:
sys.exit(1)
else:
tests_to_run = all_tests
# Run the tests and keep score.
tot_run = 0
tot_succeeded = 0
for test in tests:
for test in tests_to_run:
print test.__class__.__name__
(run, succeeded) = test.Run()
tot_run += run