forked from osmocom/wireshark
Add infrastructure for display filter functions.
Add upper() and lower() display filter functions for string fields. svn path=/trunk/; revision=18071
This commit is contained in:
parent
7edd136c88
commit
e3899ed4a4
|
@ -3209,6 +3209,70 @@ field_info structures that are interesting to the display filter. This
|
||||||
makes lookup of those field_info structures during the filtering process
|
makes lookup of those field_info structures during the filtering process
|
||||||
faster.
|
faster.
|
||||||
|
|
||||||
|
5.4 Display Filter Functions
|
||||||
|
|
||||||
|
You define a desplay filte function by adding an entry to
|
||||||
|
the df_functions table in epan/dfilter/dfunctions.c. The record struct
|
||||||
|
is defined in defunctions.h, and shown here:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
DFFuncType function;
|
||||||
|
ftenum_t retval_ftype;
|
||||||
|
guint min_nargs;
|
||||||
|
guint max_nargs;
|
||||||
|
DFSemCheckType semcheck_param_function;
|
||||||
|
} df_func_def_t;
|
||||||
|
|
||||||
|
name - the name of the function; this is how the user will call your
|
||||||
|
function in the display filter language
|
||||||
|
|
||||||
|
function - this is the run-time processing of your function.
|
||||||
|
|
||||||
|
retval_ftype - what type of FT_* type does your function return?
|
||||||
|
|
||||||
|
min_nargs - minimum number of arguments your function accepts
|
||||||
|
max_nargs - maximum number of arguments your function accepts
|
||||||
|
|
||||||
|
semcheck_param_function - called during the semantic check of the
|
||||||
|
display filter string.
|
||||||
|
|
||||||
|
DFFuncType function
|
||||||
|
-------------------
|
||||||
|
typedef gboolean (*DFFuncType)(GList *arg1list, GList *arg2list, GList **retval);
|
||||||
|
|
||||||
|
The return value of your function is a gboolean; TRUE if processing went fine,
|
||||||
|
or FALSE if there was some sort of exception.
|
||||||
|
|
||||||
|
For now, display filter functions can accept a maximum of 2 arguments.
|
||||||
|
The "arg1list" parameter is the GList for the first argument. The
|
||||||
|
'arg2list" parameter is the GList for the second argument. All arguments
|
||||||
|
to display filter functions are lists. This is because in the display
|
||||||
|
filter language a protocol field may have multiple instances. For example,
|
||||||
|
a field like "ip.addr" will exist more than once in a single frame. So
|
||||||
|
when the user invokes this display filter:
|
||||||
|
|
||||||
|
somefunc(ip.addr) == TRUE
|
||||||
|
|
||||||
|
even though "ip.addr" is a single argument, the "somefunc" function will
|
||||||
|
receive a GList of *all* the values of "ip.addr" in the frame.
|
||||||
|
|
||||||
|
Similarly, the return value of the function needs to be a GList, since all
|
||||||
|
values in the display filter language are lists. The GList** retval argument
|
||||||
|
is passed to your function so you can set the pointer to your return value.
|
||||||
|
|
||||||
|
DFSemCheckType
|
||||||
|
--------------
|
||||||
|
typedef void (*DFSemCheckType)(int param_num, stnode_t *st_node);
|
||||||
|
|
||||||
|
For each parameter in the syntax tree, this function will be called.
|
||||||
|
"param_num" will indicate the number of the parameter, starting with 0.
|
||||||
|
The "stnode_t" is the syntax-tree node representing that parameter.
|
||||||
|
If everything is okay with the value of that stnode_t, your function
|
||||||
|
does nothing --- it merely returns. If something is wrong, however,
|
||||||
|
it should THROW a TypeError exception.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
6.0 Adding new capabilities.
|
6.0 Adding new capabilities.
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,19 @@ have been compiled with the PCRE library. This can be checked by running:
|
||||||
|
|
||||||
or selecting the "About Ethereal" item from the "Help" menu in B<Ethereal>.
|
or selecting the "About Ethereal" item from the "Help" menu in B<Ethereal>.
|
||||||
|
|
||||||
|
=head2 Functions
|
||||||
|
|
||||||
|
The filter language has the following functions:
|
||||||
|
|
||||||
|
upper(string-field) - converts a string field to uppercase
|
||||||
|
lower(string-field) - converts a string field to lowercase
|
||||||
|
|
||||||
|
upper() and lower() are useful for performing case-insensitive string
|
||||||
|
comparisons. For example:
|
||||||
|
|
||||||
|
upper(ncp.nds_stream_name) contains "MACRO"
|
||||||
|
lower(mount.dump.hostname) == "angel"
|
||||||
|
|
||||||
=head2 Protocol field types
|
=head2 Protocol field types
|
||||||
|
|
||||||
Each protocol field is typed. The types are:
|
Each protocol field is typed. The types are:
|
||||||
|
|
|
@ -46,6 +46,8 @@ libdfilter_la_SOURCES = \
|
||||||
dfilter.c \
|
dfilter.c \
|
||||||
dfilter.h \
|
dfilter.h \
|
||||||
dfilter-int.h \
|
dfilter-int.h \
|
||||||
|
dfunctions.c \
|
||||||
|
dfunctions.h \
|
||||||
dfvm.c \
|
dfvm.c \
|
||||||
dfvm.h \
|
dfvm.h \
|
||||||
drange.c \
|
drange.c \
|
||||||
|
@ -59,6 +61,8 @@ libdfilter_la_SOURCES = \
|
||||||
scanner.c \
|
scanner.c \
|
||||||
semcheck.c \
|
semcheck.c \
|
||||||
semcheck.h \
|
semcheck.h \
|
||||||
|
sttype-function.c \
|
||||||
|
sttype-function.h \
|
||||||
sttype-integer.c \
|
sttype-integer.c \
|
||||||
sttype-pointer.c \
|
sttype-pointer.c \
|
||||||
sttype-range.c \
|
sttype-range.c \
|
||||||
|
|
|
@ -20,6 +20,7 @@ CVARSDLL=-DWIN32 -DNULL=0 -D_MT -D_DLL
|
||||||
|
|
||||||
OBJECTS = \
|
OBJECTS = \
|
||||||
dfilter.obj \
|
dfilter.obj \
|
||||||
|
dfunctions.obj \
|
||||||
dfvm.obj \
|
dfvm.obj \
|
||||||
drange.obj \
|
drange.obj \
|
||||||
gencode.obj \
|
gencode.obj \
|
||||||
|
@ -27,6 +28,7 @@ OBJECTS = \
|
||||||
grammar.obj \
|
grammar.obj \
|
||||||
scanner.obj \
|
scanner.obj \
|
||||||
semcheck.obj \
|
semcheck.obj \
|
||||||
|
sttype-function.obj \
|
||||||
sttype-integer.obj \
|
sttype-integer.obj \
|
||||||
sttype-pointer.obj \
|
sttype-pointer.obj \
|
||||||
sttype-range.obj \
|
sttype-range.obj \
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
*
|
||||||
|
* Copyright 2006 Gilbert Ramirez <gram@alumni.rice.edu>
|
||||||
|
*
|
||||||
|
* 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 <glib.h>
|
||||||
|
|
||||||
|
#include "dfunctions.h"
|
||||||
|
#include "dfilter-int.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <ftypes/ftypes.h>
|
||||||
|
#include <epan/exceptions.h>
|
||||||
|
|
||||||
|
/* lowercase an ASCII character.
|
||||||
|
* (thanks to Guy Harris for the function) */
|
||||||
|
static gchar
|
||||||
|
string_ascii_to_lower(gchar c)
|
||||||
|
{
|
||||||
|
return ((c & 0x80) ? c : tolower(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* uppercase an ASCII character. */
|
||||||
|
static gchar
|
||||||
|
string_ascii_to_upper(gchar c)
|
||||||
|
{
|
||||||
|
return ((c & 0x80) ? c : toupper(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert an FT_STRING using a callback function */
|
||||||
|
static gboolean
|
||||||
|
string_walk(GList* arg1list, GList **retval, gchar(*conv_func)(gchar))
|
||||||
|
{
|
||||||
|
GList *arg1;
|
||||||
|
fvalue_t *arg_fvalue;
|
||||||
|
fvalue_t *new_ft_string;
|
||||||
|
char *s, *c;
|
||||||
|
|
||||||
|
arg1 = arg1list;
|
||||||
|
while (arg1) {
|
||||||
|
arg_fvalue = arg1->data;
|
||||||
|
switch (fvalue_ftype(arg_fvalue)->ftype) {
|
||||||
|
case FT_STRING:
|
||||||
|
s = g_strdup(fvalue_get(arg1->data));
|
||||||
|
for (c = s; *c; c++) {
|
||||||
|
/**c = string_ascii_to_lower(*c);*/
|
||||||
|
*c = conv_func(*c);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_ft_string = fvalue_new(FT_STRING);
|
||||||
|
fvalue_set(new_ft_string, s, TRUE);
|
||||||
|
*retval = g_list_append(*retval, new_ft_string);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* XXX - it would be nice to handle FT_TVBUFF, too */
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arg1 = arg1->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dfilter function: lower() */
|
||||||
|
static gboolean
|
||||||
|
df_func_lower(GList* arg1list, GList *arg2junk _U_, GList **retval)
|
||||||
|
{
|
||||||
|
return string_walk(arg1list, retval, string_ascii_to_lower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dfilter function: upper() */
|
||||||
|
static gboolean
|
||||||
|
df_func_upper(GList* arg1list, GList *arg2junk _U_, GList **retval)
|
||||||
|
{
|
||||||
|
return string_walk(arg1list, retval, string_ascii_to_upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For upper() and lower(), checks that the parameter passed to
|
||||||
|
* it is an FT_STRING */
|
||||||
|
static void
|
||||||
|
ul_semcheck_params(int param_num, stnode_t *st_node)
|
||||||
|
{
|
||||||
|
sttype_id_t type;
|
||||||
|
ftenum_t ftype;
|
||||||
|
header_field_info *hfinfo;
|
||||||
|
|
||||||
|
type = stnode_type_id(st_node);
|
||||||
|
|
||||||
|
if (param_num == 0) {
|
||||||
|
switch(type) {
|
||||||
|
case STTYPE_FIELD:
|
||||||
|
hfinfo = stnode_data(st_node);
|
||||||
|
ftype = hfinfo->type;
|
||||||
|
if (ftype != FT_STRING && ftype != FT_STRINGZ
|
||||||
|
&& ftype != FT_UINT_STRING) {
|
||||||
|
dfilter_fail("Only strings can be used in upper() or lower()");
|
||||||
|
THROW(TypeError);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dfilter_fail("Only string-type fields can be used in upper() or lower()");
|
||||||
|
THROW(TypeError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The table of all display-filter functions */
|
||||||
|
static df_func_def_t
|
||||||
|
df_functions[] = {
|
||||||
|
{ "lower", df_func_lower, FT_STRING, 1, 1, ul_semcheck_params },
|
||||||
|
{ "upper", df_func_upper, FT_STRING, 1, 1, ul_semcheck_params },
|
||||||
|
{ NULL, NULL, 0, 0, 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Lookup a display filter function record by name */
|
||||||
|
df_func_def_t*
|
||||||
|
df_func_lookup(char *name)
|
||||||
|
{
|
||||||
|
df_func_def_t *func_def;
|
||||||
|
|
||||||
|
func_def = df_functions;
|
||||||
|
while (func_def->function != NULL) {
|
||||||
|
if (strcmp(func_def->name, name) == 0) {
|
||||||
|
return func_def;
|
||||||
|
}
|
||||||
|
func_def++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
*
|
||||||
|
* Copyright 2006 Gilbert Ramirez <gram@alumni.rice.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DFUNCTIONS_H
|
||||||
|
#define DFUNCTIONS_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <ftypes/ftypes.h>
|
||||||
|
#include "syntax-tree.h"
|
||||||
|
|
||||||
|
/* The run-time logic of the dfilter function */
|
||||||
|
typedef gboolean (*DFFuncType)(GList *arg1list, GList *arg2list, GList **retval);
|
||||||
|
|
||||||
|
/* The semantic check for the dfilter function */
|
||||||
|
typedef void (*DFSemCheckType)(int param_num, stnode_t *st_node);
|
||||||
|
|
||||||
|
/* If a function needs more args than this, increase
|
||||||
|
* this macro and add more arg members to the dfvm_insn_t
|
||||||
|
* struct in dfvm.h, and add some logic to dfw_append_function()
|
||||||
|
* and dfvm_apply() */
|
||||||
|
#define DFUNCTION_MAX_NARGS 2
|
||||||
|
|
||||||
|
/* This is a "function definition" record, holding everything
|
||||||
|
* we need to know about a function */
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
DFFuncType function;
|
||||||
|
ftenum_t retval_ftype;
|
||||||
|
guint min_nargs;
|
||||||
|
guint max_nargs;
|
||||||
|
DFSemCheckType semcheck_param_function;
|
||||||
|
} df_func_def_t;
|
||||||
|
|
||||||
|
/* Return the function definition record for a function of named "name" */
|
||||||
|
df_func_def_t* df_func_lookup(char *name);
|
||||||
|
|
||||||
|
#endif
|
|
@ -118,6 +118,18 @@ dfvm_dump(FILE *f, GPtrArray *insns)
|
||||||
arg2->value.numeric);
|
arg2->value.numeric);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CALL_FUNCTION:
|
||||||
|
fprintf(f, "%05d CALL_FUNCTION\t%s (",
|
||||||
|
id, arg1->value.funcdef->name);
|
||||||
|
if (arg3) {
|
||||||
|
fprintf(f, "reg#%u", arg3->value.numeric);
|
||||||
|
}
|
||||||
|
if (arg4) {
|
||||||
|
fprintf(f, ", reg#%u", arg4->value.numeric);
|
||||||
|
}
|
||||||
|
fprintf(f, ") --> reg#%u\n", arg2->value.numeric);
|
||||||
|
break;
|
||||||
|
|
||||||
case PUT_FVALUE:
|
case PUT_FVALUE:
|
||||||
value_str = fvalue_to_string_repr(arg1->value.fvalue,
|
value_str = fvalue_to_string_repr(arg1->value.fvalue,
|
||||||
FTREPR_DFILTER, NULL);
|
FTREPR_DFILTER, NULL);
|
||||||
|
@ -373,8 +385,11 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
|
||||||
dfvm_insn_t *insn;
|
dfvm_insn_t *insn;
|
||||||
dfvm_value_t *arg1;
|
dfvm_value_t *arg1;
|
||||||
dfvm_value_t *arg2;
|
dfvm_value_t *arg2;
|
||||||
dfvm_value_t *arg3;
|
dfvm_value_t *arg3 = NULL;
|
||||||
|
dfvm_value_t *arg4 = NULL;
|
||||||
header_field_info *hfinfo;
|
header_field_info *hfinfo;
|
||||||
|
GList *param1;
|
||||||
|
GList *param2;
|
||||||
|
|
||||||
g_assert(tree);
|
g_assert(tree);
|
||||||
|
|
||||||
|
@ -414,6 +429,21 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
|
||||||
arg1->value.hfinfo, arg2->value.numeric);
|
arg1->value.hfinfo, arg2->value.numeric);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CALL_FUNCTION:
|
||||||
|
arg3 = insn->arg3;
|
||||||
|
arg4 = insn->arg4;
|
||||||
|
param1 = NULL;
|
||||||
|
param2 = NULL;
|
||||||
|
if (arg3) {
|
||||||
|
param1 = df->registers[arg3->value.numeric];
|
||||||
|
}
|
||||||
|
if (arg4) {
|
||||||
|
param2 = df->registers[arg4->value.numeric];
|
||||||
|
}
|
||||||
|
accum = arg1->value.funcdef->function(param1, param2,
|
||||||
|
&df->registers[arg2->value.numeric]);
|
||||||
|
break;
|
||||||
|
|
||||||
case PUT_FVALUE:
|
case PUT_FVALUE:
|
||||||
accum = put_fvalue(df,
|
accum = put_fvalue(df,
|
||||||
arg1->value.fvalue, arg2->value.numeric);
|
arg1->value.fvalue, arg2->value.numeric);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "dfilter-int.h"
|
#include "dfilter-int.h"
|
||||||
#include "syntax-tree.h"
|
#include "syntax-tree.h"
|
||||||
#include "drange.h"
|
#include "drange.h"
|
||||||
|
#include "dfunctions.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EMPTY,
|
EMPTY,
|
||||||
|
@ -36,7 +37,8 @@ typedef enum {
|
||||||
INSN_NUMBER,
|
INSN_NUMBER,
|
||||||
REGISTER,
|
REGISTER,
|
||||||
INTEGER,
|
INTEGER,
|
||||||
DRANGE
|
DRANGE,
|
||||||
|
FUNCTION_DEF
|
||||||
} dfvm_value_type_t;
|
} dfvm_value_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -47,6 +49,7 @@ typedef struct {
|
||||||
guint32 numeric;
|
guint32 numeric;
|
||||||
drange *drange;
|
drange *drange;
|
||||||
header_field_info *hfinfo;
|
header_field_info *hfinfo;
|
||||||
|
df_func_def_t *funcdef;
|
||||||
} value;
|
} value;
|
||||||
|
|
||||||
} dfvm_value_t;
|
} dfvm_value_t;
|
||||||
|
@ -70,13 +73,13 @@ typedef enum {
|
||||||
ANY_BITWISE_AND,
|
ANY_BITWISE_AND,
|
||||||
ANY_CONTAINS,
|
ANY_CONTAINS,
|
||||||
ANY_MATCHES,
|
ANY_MATCHES,
|
||||||
MK_RANGE
|
MK_RANGE,
|
||||||
|
CALL_FUNCTION
|
||||||
|
|
||||||
} dfvm_opcode_t;
|
} dfvm_opcode_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int id;
|
int id;
|
||||||
int LHS;
|
|
||||||
dfvm_opcode_t op;
|
dfvm_opcode_t op;
|
||||||
dfvm_value_t *arg1;
|
dfvm_value_t *arg1;
|
||||||
dfvm_value_t *arg2;
|
dfvm_value_t *arg2;
|
||||||
|
|
|
@ -30,11 +30,15 @@
|
||||||
#include "syntax-tree.h"
|
#include "syntax-tree.h"
|
||||||
#include "sttype-range.h"
|
#include "sttype-range.h"
|
||||||
#include "sttype-test.h"
|
#include "sttype-test.h"
|
||||||
|
#include "sttype-function.h"
|
||||||
#include "ftypes/ftypes.h"
|
#include "ftypes/ftypes.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gencode(dfwork_t *dfw, stnode_t *st_node);
|
gencode(dfwork_t *dfw, stnode_t *st_node);
|
||||||
|
|
||||||
|
static int
|
||||||
|
gen_entity(dfwork_t *dfw, stnode_t *st_arg, dfvm_value_t **p_jmp);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
|
dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
|
||||||
{
|
{
|
||||||
|
@ -155,58 +159,98 @@ dfw_append_mk_range(dfwork_t *dfw, stnode_t *node)
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns register number that the functions's result will be in. */
|
||||||
|
static int
|
||||||
|
dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp)
|
||||||
|
{
|
||||||
|
GSList *params;
|
||||||
|
int i, num_params, reg;
|
||||||
|
dfvm_value_t **jmps;
|
||||||
|
dfvm_insn_t *insn;
|
||||||
|
dfvm_value_t *val1, *val2, *val;
|
||||||
|
|
||||||
|
params = sttype_function_params(node);
|
||||||
|
num_params = g_slist_length(params);
|
||||||
|
|
||||||
|
/* Array to hold the instructions that need to jump to
|
||||||
|
* an instruction if they fail. */
|
||||||
|
jmps = g_malloc(num_params * sizeof(dfvm_value_t*));
|
||||||
|
|
||||||
|
/* Create the new DFVM instruction */
|
||||||
|
insn = dfvm_insn_new(CALL_FUNCTION);
|
||||||
|
|
||||||
|
val1 = dfvm_value_new(FUNCTION_DEF);
|
||||||
|
val1->value.funcdef = sttype_function_funcdef(node);
|
||||||
|
insn->arg1 = val1;
|
||||||
|
val2 = dfvm_value_new(REGISTER);
|
||||||
|
val2->value.numeric = dfw->next_register++;
|
||||||
|
insn->arg2 = val2;
|
||||||
|
insn->arg3 = NULL;
|
||||||
|
insn->arg4 = NULL;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (params) {
|
||||||
|
jmps[i] = NULL;
|
||||||
|
reg = gen_entity(dfw, params->data, &jmps[i]);
|
||||||
|
|
||||||
|
val = dfvm_value_new(REGISTER);
|
||||||
|
val->value.numeric = reg;
|
||||||
|
|
||||||
|
switch(i) {
|
||||||
|
case 0:
|
||||||
|
insn->arg3 = val;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
insn->arg4 = val;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
params = params->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfw_append_insn(dfw, insn);
|
||||||
|
|
||||||
|
/* If any of our parameters failed, send them to
|
||||||
|
* our own failure instruction. This *has* to be done
|
||||||
|
* after we caled dfw_append_insn above so that
|
||||||
|
* we know what the next DFVM insruction is, via
|
||||||
|
* dfw->next_insn_id */
|
||||||
|
for (i = 0; i < num_params; i++) {
|
||||||
|
if (jmps[i]) {
|
||||||
|
jmps[i]->value.numeric = dfw->next_insn_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need another instruction to jump to another exit
|
||||||
|
* place, if the call() of our function failed for some reaosn */
|
||||||
|
insn = dfvm_insn_new(IF_FALSE_GOTO);
|
||||||
|
g_assert(p_jmp);
|
||||||
|
*p_jmp = dfvm_value_new(INSN_NUMBER);
|
||||||
|
insn->arg1 = *p_jmp;
|
||||||
|
dfw_append_insn(dfw, insn);
|
||||||
|
|
||||||
|
g_free(jmps);
|
||||||
|
|
||||||
|
return val2->value.numeric;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2)
|
gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2)
|
||||||
{
|
{
|
||||||
sttype_id_t type1, type2;
|
|
||||||
dfvm_insn_t *insn;
|
dfvm_insn_t *insn;
|
||||||
dfvm_value_t *val1, *val2;
|
dfvm_value_t *val1, *val2;
|
||||||
dfvm_value_t *jmp1 = NULL, *jmp2 = NULL;
|
dfvm_value_t *jmp1 = NULL, *jmp2 = NULL;
|
||||||
int reg1 = -1, reg2 = -1;
|
int reg1 = -1, reg2 = -1;
|
||||||
header_field_info *hfinfo;
|
|
||||||
|
|
||||||
type1 = stnode_type_id(st_arg1);
|
/* Create code for the LHS and RHS of the relation */
|
||||||
type2 = stnode_type_id(st_arg2);
|
reg1 = gen_entity(dfw, st_arg1, &jmp1);
|
||||||
|
reg2 = gen_entity(dfw, st_arg2, &jmp2);
|
||||||
if (type1 == STTYPE_FIELD) {
|
|
||||||
hfinfo = stnode_data(st_arg1);
|
|
||||||
reg1 = dfw_append_read_tree(dfw, hfinfo);
|
|
||||||
|
|
||||||
insn = dfvm_insn_new(IF_FALSE_GOTO);
|
|
||||||
jmp1 = dfvm_value_new(INSN_NUMBER);
|
|
||||||
insn->arg1 = jmp1;
|
|
||||||
dfw_append_insn(dfw, insn);
|
|
||||||
}
|
|
||||||
else if (type1 == STTYPE_FVALUE) {
|
|
||||||
reg1 = dfw_append_put_fvalue(dfw, stnode_data(st_arg1));
|
|
||||||
}
|
|
||||||
else if (type1 == STTYPE_RANGE) {
|
|
||||||
reg1 = dfw_append_mk_range(dfw, st_arg1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type2 == STTYPE_FIELD) {
|
|
||||||
hfinfo = stnode_data(st_arg2);
|
|
||||||
reg2 = dfw_append_read_tree(dfw, hfinfo);
|
|
||||||
|
|
||||||
insn = dfvm_insn_new(IF_FALSE_GOTO);
|
|
||||||
jmp2 = dfvm_value_new(INSN_NUMBER);
|
|
||||||
insn->arg1 = jmp2;
|
|
||||||
dfw_append_insn(dfw, insn);
|
|
||||||
}
|
|
||||||
else if (type2 == STTYPE_FVALUE) {
|
|
||||||
reg2 = dfw_append_put_fvalue(dfw, stnode_data(st_arg2));
|
|
||||||
}
|
|
||||||
else if (type2 == STTYPE_RANGE) {
|
|
||||||
reg2 = dfw_append_mk_range(dfw, st_arg2);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Then combine them in a DFVM insruction */
|
||||||
insn = dfvm_insn_new(op);
|
insn = dfvm_insn_new(op);
|
||||||
val1 = dfvm_value_new(REGISTER);
|
val1 = dfvm_value_new(REGISTER);
|
||||||
val1->value.numeric = reg1;
|
val1->value.numeric = reg1;
|
||||||
|
@ -216,6 +260,8 @@ gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_ar
|
||||||
insn->arg2 = val2;
|
insn->arg2 = val2;
|
||||||
dfw_append_insn(dfw, insn);
|
dfw_append_insn(dfw, insn);
|
||||||
|
|
||||||
|
/* If either of the relation argumnents need an "exit" instruction
|
||||||
|
* to jump to (on failure), mark them */
|
||||||
if (jmp1) {
|
if (jmp1) {
|
||||||
jmp1->value.numeric = dfw->next_insn_id;
|
jmp1->value.numeric = dfw->next_insn_id;
|
||||||
}
|
}
|
||||||
|
@ -225,6 +271,45 @@ gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_ar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse an entity, returning the reg that it gets put into.
|
||||||
|
* p_jmp will be set if it has to be set by the calling code; it should
|
||||||
|
* be set tothe place to jump to, to return to the calling code,
|
||||||
|
* if the load of a field from the proto_tree fails. */
|
||||||
|
static int
|
||||||
|
gen_entity(dfwork_t *dfw, stnode_t *st_arg, dfvm_value_t **p_jmp)
|
||||||
|
{
|
||||||
|
sttype_id_t e_type;
|
||||||
|
dfvm_insn_t *insn;
|
||||||
|
header_field_info *hfinfo;
|
||||||
|
e_type = stnode_type_id(st_arg);
|
||||||
|
int reg = -1;
|
||||||
|
|
||||||
|
if (e_type == STTYPE_FIELD) {
|
||||||
|
hfinfo = stnode_data(st_arg);
|
||||||
|
reg = dfw_append_read_tree(dfw, hfinfo);
|
||||||
|
|
||||||
|
insn = dfvm_insn_new(IF_FALSE_GOTO);
|
||||||
|
g_assert(p_jmp);
|
||||||
|
*p_jmp = dfvm_value_new(INSN_NUMBER);
|
||||||
|
insn->arg1 = *p_jmp;
|
||||||
|
dfw_append_insn(dfw, insn);
|
||||||
|
}
|
||||||
|
else if (e_type == STTYPE_FVALUE) {
|
||||||
|
reg = dfw_append_put_fvalue(dfw, stnode_data(st_arg));
|
||||||
|
}
|
||||||
|
else if (e_type == STTYPE_RANGE) {
|
||||||
|
reg = dfw_append_mk_range(dfw, st_arg);
|
||||||
|
}
|
||||||
|
else if (e_type == STTYPE_FUNCTION) {
|
||||||
|
reg = dfw_append_function(dfw, st_arg, p_jmp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("sttype_id is %u\n", e_type);
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gen_test(dfwork_t *dfw, stnode_t *st_node)
|
gen_test(dfwork_t *dfw, stnode_t *st_node)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "syntax-tree.h"
|
#include "syntax-tree.h"
|
||||||
#include "sttype-range.h"
|
#include "sttype-range.h"
|
||||||
#include "sttype-test.h"
|
#include "sttype-test.h"
|
||||||
|
#include "sttype-function.h"
|
||||||
#include "drange.h"
|
#include "drange.h"
|
||||||
|
|
||||||
#include "grammar.h"
|
#include "grammar.h"
|
||||||
|
@ -51,6 +52,9 @@
|
||||||
%type drnode_list {GSList*}
|
%type drnode_list {GSList*}
|
||||||
%destructor drnode_list {drange_node_free_list($$);}
|
%destructor drnode_list {drange_node_free_list($$);}
|
||||||
|
|
||||||
|
%type funcparams {GSList*}
|
||||||
|
%destructor funcparams {st_funcparams_free($$);}
|
||||||
|
|
||||||
/* This is called as soon as a syntax error happens. After that,
|
/* This is called as soon as a syntax error happens. After that,
|
||||||
any "error" symbols are shifted, if possible. */
|
any "error" symbols are shifted, if possible. */
|
||||||
%syntax_error {
|
%syntax_error {
|
||||||
|
@ -85,6 +89,9 @@ any "error" symbols are shifted, if possible. */
|
||||||
hfinfo = stnode_data(TOKEN);
|
hfinfo = stnode_data(TOKEN);
|
||||||
dfilter_fail("Syntax error near \"%s\".", hfinfo->abbrev);
|
dfilter_fail("Syntax error near \"%s\".", hfinfo->abbrev);
|
||||||
break;
|
break;
|
||||||
|
case STTYPE_FUNCTION:
|
||||||
|
dfilter_fail("The function s was unexpected in this context.");
|
||||||
|
break;
|
||||||
|
|
||||||
/* These aren't handed to use as terminal tokens from
|
/* These aren't handed to use as terminal tokens from
|
||||||
the scanner, so was can assert that we'll never
|
the scanner, so was can assert that we'll never
|
||||||
|
@ -120,11 +127,6 @@ sentence ::= . { dfw->st_root = NULL; }
|
||||||
expr(X) ::= relation_test(R). { X = R; }
|
expr(X) ::= relation_test(R). { X = R; }
|
||||||
expr(X) ::= logical_test(L). { X = L; }
|
expr(X) ::= logical_test(L). { X = L; }
|
||||||
|
|
||||||
expr(X) ::= LPAREN expr(Y) RPAREN.
|
|
||||||
{
|
|
||||||
X = Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Logical tests */
|
/* Logical tests */
|
||||||
logical_test(T) ::= expr(E) TEST_AND expr(F).
|
logical_test(T) ::= expr(E) TEST_AND expr(F).
|
||||||
|
@ -254,4 +256,35 @@ rel_op2(O) ::= TEST_CONTAINS. { O = TEST_OP_CONTAINS; }
|
||||||
rel_op2(O) ::= TEST_MATCHES. { O = TEST_OP_MATCHES; }
|
rel_op2(O) ::= TEST_MATCHES. { O = TEST_OP_MATCHES; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
|
||||||
|
/* A function can have one or more parameters */
|
||||||
|
entity(E) ::= FUNCTION(F) LPAREN funcparams(P) RPAREN.
|
||||||
|
{
|
||||||
|
E = F;
|
||||||
|
sttype_function_set_params(E, P);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A function can have zero parameters. */
|
||||||
|
entity(E) ::= FUNCTION(F) LPAREN RPAREN.
|
||||||
|
{
|
||||||
|
E = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcparams(P) ::= entity(E).
|
||||||
|
{
|
||||||
|
P = g_slist_append(NULL, E);
|
||||||
|
}
|
||||||
|
|
||||||
|
funcparams(P) ::= funcparams(L) COMMA entity(E).
|
||||||
|
{
|
||||||
|
P = g_slist_append(L, E);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Any expression inside parens is simply that expression */
|
||||||
|
expr(X) ::= LPAREN expr(Y) RPAREN.
|
||||||
|
{
|
||||||
|
X = Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "dfilter-int.h"
|
#include "dfilter-int.h"
|
||||||
#include "syntax-tree.h"
|
#include "syntax-tree.h"
|
||||||
#include "grammar.h"
|
#include "grammar.h"
|
||||||
|
#include "dfunctions.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GLib 1.2[.x] doesn't define G_MAXINT32 or G_MININT32; if they're not
|
* GLib 1.2[.x] doesn't define G_MAXINT32 or G_MININT32; if they're not
|
||||||
|
@ -75,6 +76,7 @@ GString* quoted_string = NULL;
|
||||||
|
|
||||||
"(" return simple(TOKEN_LPAREN);
|
"(" return simple(TOKEN_LPAREN);
|
||||||
")" return simple(TOKEN_RPAREN);
|
")" return simple(TOKEN_RPAREN);
|
||||||
|
"," return simple(TOKEN_COMMA);
|
||||||
|
|
||||||
"==" return simple(TOKEN_TEST_EQ);
|
"==" return simple(TOKEN_TEST_EQ);
|
||||||
"eq" return simple(TOKEN_TEST_EQ);
|
"eq" return simple(TOKEN_TEST_EQ);
|
||||||
|
@ -232,9 +234,10 @@ GString* quoted_string = NULL;
|
||||||
return set_lval(TOKEN_UNPARSED, yytext);
|
return set_lval(TOKEN_UNPARSED, yytext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[-\+[:alnum:]_.,:]+ {
|
[-\+[:alnum:]_.:]+ {
|
||||||
/* Is it a field name? */
|
/* Is it a field name? */
|
||||||
header_field_info *hfinfo;
|
header_field_info *hfinfo;
|
||||||
|
df_func_def_t *df_func_def;
|
||||||
|
|
||||||
hfinfo = proto_registrar_get_byname(yytext);
|
hfinfo = proto_registrar_get_byname(yytext);
|
||||||
if (hfinfo) {
|
if (hfinfo) {
|
||||||
|
@ -242,8 +245,16 @@ GString* quoted_string = NULL;
|
||||||
return set_lval(TOKEN_FIELD, hfinfo);
|
return set_lval(TOKEN_FIELD, hfinfo);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* No, so treat it as an unparsed string */
|
/* Is it a function name? */
|
||||||
return set_lval(TOKEN_UNPARSED, yytext);
|
df_func_def = df_func_lookup(yytext);
|
||||||
|
if (df_func_def) {
|
||||||
|
/* yes, it's a dfilter function */
|
||||||
|
return set_lval(TOKEN_FUNCTION, df_func_def);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* No, so treat it as an unparsed string */
|
||||||
|
return set_lval(TOKEN_UNPARSED, yytext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,10 +311,12 @@ set_lval(int token, gpointer data)
|
||||||
case TOKEN_UNPARSED:
|
case TOKEN_UNPARSED:
|
||||||
type_id = STTYPE_UNPARSED;
|
type_id = STTYPE_UNPARSED;
|
||||||
break;
|
break;
|
||||||
|
case TOKEN_FUNCTION:
|
||||||
|
type_id = STTYPE_FUNCTION;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
stnode_init(df_lval, type_id, data);
|
stnode_init(df_lval, type_id, data);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "syntax-tree.h"
|
#include "syntax-tree.h"
|
||||||
#include "sttype-range.h"
|
#include "sttype-range.h"
|
||||||
#include "sttype-test.h"
|
#include "sttype-test.h"
|
||||||
|
#include "sttype-function.h"
|
||||||
|
|
||||||
#include <epan/exceptions.h>
|
#include <epan/exceptions.h>
|
||||||
#include <epan/packet.h>
|
#include <epan/packet.h>
|
||||||
|
@ -307,6 +308,13 @@ check_exists(stnode_t *st_arg1)
|
||||||
THROW(TypeError);
|
THROW(TypeError);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STTYPE_FUNCTION:
|
||||||
|
/* XXX - Maybe we should change functions so they can return fields,
|
||||||
|
* in which case the 'exist' should be fine. */
|
||||||
|
dfilter_fail("You cannot test whether a function is present.");
|
||||||
|
THROW(TypeError);
|
||||||
|
break;
|
||||||
|
|
||||||
case STTYPE_UNINITIALIZED:
|
case STTYPE_UNINITIALIZED:
|
||||||
case STTYPE_TEST:
|
case STTYPE_TEST:
|
||||||
case STTYPE_INTEGER:
|
case STTYPE_INTEGER:
|
||||||
|
@ -751,6 +759,161 @@ check_relation_LHS_RANGE(const char *relation_string, FtypeCanFunc can_func _U_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
int param_i;
|
||||||
|
drange_node *rn;
|
||||||
|
df_func_def_t *funcdef;
|
||||||
|
guint num_params;
|
||||||
|
GSList *params;
|
||||||
|
|
||||||
|
type2 = stnode_type_id(st_arg2);
|
||||||
|
|
||||||
|
funcdef = sttype_function_funcdef(st_arg1);
|
||||||
|
ftype1 = funcdef->retval_ftype;
|
||||||
|
|
||||||
|
params = sttype_function_params(st_arg1);
|
||||||
|
num_params = g_slist_length(params);
|
||||||
|
if (num_params < funcdef->min_nargs) {
|
||||||
|
dfilter_fail("Function %s needs at least %u arguments.",
|
||||||
|
funcdef->name, funcdef->min_nargs);
|
||||||
|
THROW(TypeError);
|
||||||
|
}
|
||||||
|
else if (num_params > funcdef->max_nargs) {
|
||||||
|
dfilter_fail("Function %s can only accept %u arguments.",
|
||||||
|
funcdef->name, funcdef->max_nargs);
|
||||||
|
THROW(TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
param_i = 0;
|
||||||
|
while (params) {
|
||||||
|
params->data = check_param_entity(params->data);
|
||||||
|
funcdef->semcheck_param_function(param_i, params->data);
|
||||||
|
params = params->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check the semantics of any relational test. */
|
/* Check the semantics of any relational test. */
|
||||||
static void
|
static void
|
||||||
|
@ -795,12 +958,16 @@ header_field_info *hfinfo;
|
||||||
check_relation_LHS_UNPARSED(relation_string, can_func,
|
check_relation_LHS_UNPARSED(relation_string, can_func,
|
||||||
allow_partial_value, st_node, st_arg1, st_arg2);
|
allow_partial_value, st_node, st_arg1, st_arg2);
|
||||||
break;
|
break;
|
||||||
|
case STTYPE_FUNCTION:
|
||||||
|
check_relation_LHS_FUNCTION(relation_string, can_func,
|
||||||
|
allow_partial_value, st_node, st_arg1, st_arg2);
|
||||||
|
break;
|
||||||
|
|
||||||
case STTYPE_UNINITIALIZED:
|
case STTYPE_UNINITIALIZED:
|
||||||
case STTYPE_TEST:
|
case STTYPE_TEST:
|
||||||
case STTYPE_INTEGER:
|
case STTYPE_INTEGER:
|
||||||
case STTYPE_FVALUE:
|
case STTYPE_FVALUE:
|
||||||
case STTYPE_NUM_TYPES:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
*
|
||||||
|
* 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 "syntax-tree.h"
|
||||||
|
#include "sttype-function.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
guint32 magic;
|
||||||
|
df_func_def_t *funcdef;
|
||||||
|
GSList *params;
|
||||||
|
} function_t;
|
||||||
|
|
||||||
|
#define FUNCTION_MAGIC 0xe10f0f99
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
function_new(gpointer funcdef)
|
||||||
|
{
|
||||||
|
function_t *stfuncrec;
|
||||||
|
|
||||||
|
g_assert(funcdef != NULL);
|
||||||
|
|
||||||
|
stfuncrec = g_new(function_t, 1);
|
||||||
|
|
||||||
|
stfuncrec->magic = FUNCTION_MAGIC;
|
||||||
|
stfuncrec->funcdef = funcdef;
|
||||||
|
stfuncrec->params = NULL;
|
||||||
|
|
||||||
|
return (gpointer) stfuncrec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
slist_stnode_free(gpointer data, gpointer user_data _U_)
|
||||||
|
{
|
||||||
|
stnode_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
st_funcparams_free(GSList *params)
|
||||||
|
{
|
||||||
|
g_slist_foreach(params, slist_stnode_free, NULL);
|
||||||
|
g_slist_free(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
function_free(gpointer value)
|
||||||
|
{
|
||||||
|
function_t *stfuncrec = value;
|
||||||
|
assert_magic(stfuncrec, FUNCTION_MAGIC);
|
||||||
|
st_funcparams_free(stfuncrec->params);
|
||||||
|
g_free(stfuncrec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the parameters for a function stnode_t. */
|
||||||
|
void
|
||||||
|
sttype_function_set_params(stnode_t *node, GSList *params)
|
||||||
|
{
|
||||||
|
|
||||||
|
function_t *stfuncrec;
|
||||||
|
|
||||||
|
stfuncrec = stnode_data(node);
|
||||||
|
assert_magic(stfuncrec, FUNCTION_MAGIC);
|
||||||
|
|
||||||
|
stfuncrec->params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the function-definition record for a function stnode_t. */
|
||||||
|
df_func_def_t*
|
||||||
|
sttype_function_funcdef(stnode_t *node)
|
||||||
|
{
|
||||||
|
function_t *stfuncrec;
|
||||||
|
|
||||||
|
stfuncrec = stnode_data(node);
|
||||||
|
assert_magic(stfuncrec, FUNCTION_MAGIC);
|
||||||
|
return stfuncrec->funcdef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the parameters for a function stnode_t. */
|
||||||
|
GSList*
|
||||||
|
sttype_function_params(stnode_t *node)
|
||||||
|
{
|
||||||
|
function_t *stfuncrec;
|
||||||
|
|
||||||
|
stfuncrec = stnode_data(node);
|
||||||
|
assert_magic(stfuncrec, FUNCTION_MAGIC);
|
||||||
|
return stfuncrec->params;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sttype_register_function(void)
|
||||||
|
{
|
||||||
|
static sttype_t function_type = {
|
||||||
|
STTYPE_FUNCTION,
|
||||||
|
"FUNCTION",
|
||||||
|
function_new,
|
||||||
|
function_free,
|
||||||
|
};
|
||||||
|
|
||||||
|
sttype_register(&function_type);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* $Id: sttype-test.h 11400 2004-07-18 00:24:25Z guy $
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@zing.org>
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STTYPE_FUNCTION_H
|
||||||
|
#define STTYPE_FUNCTION_H
|
||||||
|
|
||||||
|
#include "dfunctions.h"
|
||||||
|
|
||||||
|
/* Set the parameters for a function stnode_t. */
|
||||||
|
void
|
||||||
|
sttype_function_set_params(stnode_t *node, GSList *params);
|
||||||
|
|
||||||
|
/* Get the function-definition record for a function stnode_t. */
|
||||||
|
df_func_def_t* sttype_function_funcdef(stnode_t *node);
|
||||||
|
|
||||||
|
/* Get the parameters for a function stnode_t. */
|
||||||
|
GSList* sttype_function_params(stnode_t *node);
|
||||||
|
|
||||||
|
/* Free the memory of a param list */
|
||||||
|
void st_funcparams_free(GSList *params);
|
||||||
|
|
||||||
|
#endif
|
|
@ -36,6 +36,7 @@ static sttype_t* type_list[STTYPE_NUM_TYPES];
|
||||||
void
|
void
|
||||||
sttype_init(void)
|
sttype_init(void)
|
||||||
{
|
{
|
||||||
|
sttype_register_function();
|
||||||
sttype_register_integer();
|
sttype_register_integer();
|
||||||
sttype_register_pointer();
|
sttype_register_pointer();
|
||||||
sttype_register_range();
|
sttype_register_range();
|
||||||
|
|
|
@ -35,6 +35,7 @@ typedef enum {
|
||||||
STTYPE_FVALUE,
|
STTYPE_FVALUE,
|
||||||
STTYPE_INTEGER,
|
STTYPE_INTEGER,
|
||||||
STTYPE_RANGE,
|
STTYPE_RANGE,
|
||||||
|
STTYPE_FUNCTION,
|
||||||
STTYPE_NUM_TYPES
|
STTYPE_NUM_TYPES
|
||||||
} sttype_id_t;
|
} sttype_id_t;
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ typedef struct {
|
||||||
} stnode_t;
|
} stnode_t;
|
||||||
|
|
||||||
/* These are the sttype_t registration function prototypes. */
|
/* These are the sttype_t registration function prototypes. */
|
||||||
|
void sttype_register_function(void);
|
||||||
void sttype_register_integer(void);
|
void sttype_register_integer(void);
|
||||||
void sttype_register_pointer(void);
|
void sttype_register_pointer(void);
|
||||||
void sttype_register_range(void);
|
void sttype_register_range(void);
|
||||||
|
|
|
@ -480,6 +480,7 @@ ftype_register_bytes(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t bytes_type = {
|
static ftype_t bytes_type = {
|
||||||
|
FT_BYTES, /* ftype */
|
||||||
"FT_BYTES", /* name */
|
"FT_BYTES", /* name */
|
||||||
"sequence of bytes", /* pretty_name */
|
"sequence of bytes", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -515,6 +516,7 @@ ftype_register_bytes(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t uint_bytes_type = {
|
static ftype_t uint_bytes_type = {
|
||||||
|
FT_UINT_BYTES, /* ftype */
|
||||||
"FT_UINT_BYTES", /* name */
|
"FT_UINT_BYTES", /* name */
|
||||||
"sequence of bytes", /* pretty_name */
|
"sequence of bytes", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -550,6 +552,7 @@ ftype_register_bytes(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t ether_type = {
|
static ftype_t ether_type = {
|
||||||
|
FT_ETHER, /* ftype */
|
||||||
"FT_ETHER", /* name */
|
"FT_ETHER", /* name */
|
||||||
"Ethernet or other MAC address",/* pretty_name */
|
"Ethernet or other MAC address",/* pretty_name */
|
||||||
ETHER_LEN, /* wire_size */
|
ETHER_LEN, /* wire_size */
|
||||||
|
@ -585,6 +588,7 @@ ftype_register_bytes(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t ipv6_type = {
|
static ftype_t ipv6_type = {
|
||||||
|
FT_IPv6, /* ftype */
|
||||||
"FT_IPv6", /* name */
|
"FT_IPv6", /* name */
|
||||||
"IPv6 address", /* pretty_name */
|
"IPv6 address", /* pretty_name */
|
||||||
IPv6_LEN, /* wire_size */
|
IPv6_LEN, /* wire_size */
|
||||||
|
@ -620,6 +624,7 @@ ftype_register_bytes(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t oid_type = {
|
static ftype_t oid_type = {
|
||||||
|
FT_OID, /* ftype */
|
||||||
"OID", /* name */
|
"OID", /* name */
|
||||||
"OBJECT IDENTIFIER", /* pretty_name */
|
"OBJECT IDENTIFIER", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -157,6 +157,7 @@ ftype_register_double(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t float_type = {
|
static ftype_t float_type = {
|
||||||
|
FT_FLOAT, /* ftype */
|
||||||
"FT_FLOAT", /* name */
|
"FT_FLOAT", /* name */
|
||||||
"floating point (single-precision)", /* pretty_name */
|
"floating point (single-precision)", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -192,6 +193,7 @@ ftype_register_double(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t double_type = {
|
static ftype_t double_type = {
|
||||||
|
FT_DOUBLE, /* ftype */
|
||||||
"FT_DOUBLE", /* name */
|
"FT_DOUBLE", /* name */
|
||||||
"floating point (double-precision)", /* pretty_name */
|
"floating point (double-precision)", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -129,6 +129,7 @@ ftype_register_guid(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t guid_type = {
|
static ftype_t guid_type = {
|
||||||
|
FT_GUID, /* ftype */
|
||||||
"GUID", /* name */
|
"GUID", /* name */
|
||||||
"Globally Unique Identifier", /* pretty_name */
|
"Globally Unique Identifier", /* pretty_name */
|
||||||
GUID_LEN, /* wire_size */
|
GUID_LEN, /* wire_size */
|
||||||
|
|
|
@ -444,6 +444,7 @@ ftype_register_integers(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t uint8_type = {
|
static ftype_t uint8_type = {
|
||||||
|
FT_UINT8, /* ftype */
|
||||||
"FT_UINT8", /* name */
|
"FT_UINT8", /* name */
|
||||||
"unsigned, 1 byte", /* pretty name */
|
"unsigned, 1 byte", /* pretty name */
|
||||||
1, /* wire_size */
|
1, /* wire_size */
|
||||||
|
@ -478,6 +479,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t uint16_type = {
|
static ftype_t uint16_type = {
|
||||||
|
FT_UINT16, /* ftype */
|
||||||
"FT_UINT16", /* name */
|
"FT_UINT16", /* name */
|
||||||
"unsigned, 2 bytes", /* pretty_name */
|
"unsigned, 2 bytes", /* pretty_name */
|
||||||
2, /* wire_size */
|
2, /* wire_size */
|
||||||
|
@ -512,6 +514,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t uint24_type = {
|
static ftype_t uint24_type = {
|
||||||
|
FT_UINT24, /* ftype */
|
||||||
"FT_UINT24", /* name */
|
"FT_UINT24", /* name */
|
||||||
"unsigned, 3 bytes", /* pretty_name */
|
"unsigned, 3 bytes", /* pretty_name */
|
||||||
3, /* wire_size */
|
3, /* wire_size */
|
||||||
|
@ -546,6 +549,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t uint32_type = {
|
static ftype_t uint32_type = {
|
||||||
|
FT_UINT32, /* ftype */
|
||||||
"FT_UINT32", /* name */
|
"FT_UINT32", /* name */
|
||||||
"unsigned, 4 bytes", /* pretty_name */
|
"unsigned, 4 bytes", /* pretty_name */
|
||||||
4, /* wire_size */
|
4, /* wire_size */
|
||||||
|
@ -580,6 +584,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t uint64_type = {
|
static ftype_t uint64_type = {
|
||||||
|
FT_UINT64, /* ftype */
|
||||||
"FT_UINT64", /* name */
|
"FT_UINT64", /* name */
|
||||||
"unsigned, 8 bytes", /* pretty_name */
|
"unsigned, 8 bytes", /* pretty_name */
|
||||||
8, /* wire_size */
|
8, /* wire_size */
|
||||||
|
@ -614,6 +619,7 @@ ftype_register_integers(void)
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static ftype_t int8_type = {
|
static ftype_t int8_type = {
|
||||||
|
FT_INT8, /* ftype */
|
||||||
"FT_INT8", /* name */
|
"FT_INT8", /* name */
|
||||||
"signed, 1 byte", /* pretty_name */
|
"signed, 1 byte", /* pretty_name */
|
||||||
1, /* wire_size */
|
1, /* wire_size */
|
||||||
|
@ -648,6 +654,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t int16_type = {
|
static ftype_t int16_type = {
|
||||||
|
FT_INT16, /* ftype */
|
||||||
"FT_INT16", /* name */
|
"FT_INT16", /* name */
|
||||||
"signed, 2 bytes", /* pretty_name */
|
"signed, 2 bytes", /* pretty_name */
|
||||||
2, /* wire_size */
|
2, /* wire_size */
|
||||||
|
@ -682,6 +689,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t int24_type = {
|
static ftype_t int24_type = {
|
||||||
|
FT_INT24, /* ftype */
|
||||||
"FT_INT24", /* name */
|
"FT_INT24", /* name */
|
||||||
"signed, 3 bytes", /* pretty_name */
|
"signed, 3 bytes", /* pretty_name */
|
||||||
3, /* wire_size */
|
3, /* wire_size */
|
||||||
|
@ -716,6 +724,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t int32_type = {
|
static ftype_t int32_type = {
|
||||||
|
FT_INT32, /* ftype */
|
||||||
"FT_INT32", /* name */
|
"FT_INT32", /* name */
|
||||||
"signed, 4 bytes", /* pretty_name */
|
"signed, 4 bytes", /* pretty_name */
|
||||||
4, /* wire_size */
|
4, /* wire_size */
|
||||||
|
@ -750,6 +759,7 @@ ftype_register_integers(void)
|
||||||
NULL, /* slice */
|
NULL, /* slice */
|
||||||
};
|
};
|
||||||
static ftype_t int64_type = {
|
static ftype_t int64_type = {
|
||||||
|
FT_INT64, /* ftype */
|
||||||
"FT_INT64", /* name */
|
"FT_INT64", /* name */
|
||||||
"signed, 8 bytes", /* pretty_name */
|
"signed, 8 bytes", /* pretty_name */
|
||||||
8, /* wire_size */
|
8, /* wire_size */
|
||||||
|
@ -784,6 +794,7 @@ ftype_register_integers(void)
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static ftype_t boolean_type = {
|
static ftype_t boolean_type = {
|
||||||
|
FT_BOOLEAN, /* ftype */
|
||||||
"FT_BOOLEAN", /* name */
|
"FT_BOOLEAN", /* name */
|
||||||
"Boolean", /* pretty_name */
|
"Boolean", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -819,6 +830,7 @@ ftype_register_integers(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t ipxnet_type = {
|
static ftype_t ipxnet_type = {
|
||||||
|
FT_IPXNET, /* ftype */
|
||||||
"FT_IPXNET", /* name */
|
"FT_IPXNET", /* name */
|
||||||
"IPX network number", /* pretty_name */
|
"IPX network number", /* pretty_name */
|
||||||
4, /* wire_size */
|
4, /* wire_size */
|
||||||
|
@ -854,6 +866,7 @@ ftype_register_integers(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ftype_t framenum_type = {
|
static ftype_t framenum_type = {
|
||||||
|
FT_FRAMENUM, /* ftype */
|
||||||
"FT_FRAMENUM", /* name */
|
"FT_FRAMENUM", /* name */
|
||||||
"frame number", /* pretty_name */
|
"frame number", /* pretty_name */
|
||||||
4, /* wire_size */
|
4, /* wire_size */
|
||||||
|
|
|
@ -199,6 +199,7 @@ ftype_register_ipv4(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t ipv4_type = {
|
static ftype_t ipv4_type = {
|
||||||
|
FT_IPv4, /* ftype */
|
||||||
"FT_IPv4", /* name */
|
"FT_IPv4", /* name */
|
||||||
"IPv4 address", /* pretty_name */
|
"IPv4 address", /* pretty_name */
|
||||||
4, /* wire_size */
|
4, /* wire_size */
|
||||||
|
|
|
@ -32,6 +32,7 @@ ftype_register_none(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t none_type = {
|
static ftype_t none_type = {
|
||||||
|
FT_NONE, /* ftype */
|
||||||
"FT_NONE", /* name */
|
"FT_NONE", /* name */
|
||||||
"label", /* pretty_name */
|
"label", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -177,6 +177,7 @@ void
|
||||||
ftype_register_pcre(void)
|
ftype_register_pcre(void)
|
||||||
{
|
{
|
||||||
static ftype_t pcre_type = {
|
static ftype_t pcre_type = {
|
||||||
|
FT_PCRE, /* ftype */
|
||||||
"FT_PCRE", /* name */
|
"FT_PCRE", /* name */
|
||||||
"Compiled Perl-Compatible Regular Expression object", /* pretty_name */
|
"Compiled Perl-Compatible Regular Expression object", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -219,6 +220,7 @@ void
|
||||||
ftype_register_pcre(void)
|
ftype_register_pcre(void)
|
||||||
{
|
{
|
||||||
static ftype_t pcre_type = {
|
static ftype_t pcre_type = {
|
||||||
|
FT_PCRE, /* ftype */
|
||||||
"FT_PCRE", /* name */
|
"FT_PCRE", /* name */
|
||||||
"Compiled Perl-Compatible Regular Expression object", /* pretty_name */
|
"Compiled Perl-Compatible Regular Expression object", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -301,6 +301,7 @@ ftype_register_string(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t string_type = {
|
static ftype_t string_type = {
|
||||||
|
FT_STRING, /* ftype */
|
||||||
"FT_STRING", /* name */
|
"FT_STRING", /* name */
|
||||||
"character string", /* pretty_name */
|
"character string", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -335,6 +336,7 @@ ftype_register_string(void)
|
||||||
slice,
|
slice,
|
||||||
};
|
};
|
||||||
static ftype_t stringz_type = {
|
static ftype_t stringz_type = {
|
||||||
|
FT_STRINGZ, /* ftype */
|
||||||
"FT_STRINGZ", /* name */
|
"FT_STRINGZ", /* name */
|
||||||
"character string", /* pretty name */
|
"character string", /* pretty name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -369,6 +371,7 @@ ftype_register_string(void)
|
||||||
slice,
|
slice,
|
||||||
};
|
};
|
||||||
static ftype_t uint_string_type = {
|
static ftype_t uint_string_type = {
|
||||||
|
FT_UINT_STRING, /* ftype */
|
||||||
"FT_UINT_STRING", /* name */
|
"FT_UINT_STRING", /* name */
|
||||||
"character string", /* pretty_name */
|
"character string", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -345,6 +345,7 @@ ftype_register_time(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t abstime_type = {
|
static ftype_t abstime_type = {
|
||||||
|
FT_ABSOLUTE_TIME, /* ftype */
|
||||||
"FT_ABSOLUTE_TIME", /* name */
|
"FT_ABSOLUTE_TIME", /* name */
|
||||||
"date/time", /* pretty_name */
|
"date/time", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
@ -379,6 +380,7 @@ ftype_register_time(void)
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static ftype_t reltime_type = {
|
static ftype_t reltime_type = {
|
||||||
|
FT_RELATIVE_TIME, /* ftype */
|
||||||
"FT_RELATIVE_TIME", /* name */
|
"FT_RELATIVE_TIME", /* name */
|
||||||
"time offset", /* pretty_name */
|
"time offset", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -260,6 +260,7 @@ ftype_register_tvbuff(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
static ftype_t protocol_type = {
|
static ftype_t protocol_type = {
|
||||||
|
FT_PROTOCOL, /* ftype */
|
||||||
"FT_PROTOCOL", /* name */
|
"FT_PROTOCOL", /* name */
|
||||||
"protocol", /* pretty_name */
|
"protocol", /* pretty_name */
|
||||||
0, /* wire_size */
|
0, /* wire_size */
|
||||||
|
|
|
@ -58,6 +58,7 @@ ftype_register(enum ftenum ftype, ftype_t *ft)
|
||||||
{
|
{
|
||||||
/* Check input */
|
/* Check input */
|
||||||
g_assert(ftype < FT_NUM_TYPES);
|
g_assert(ftype < FT_NUM_TYPES);
|
||||||
|
g_assert(ftype == ft->ftype);
|
||||||
|
|
||||||
/* Don't re-register. */
|
/* Don't re-register. */
|
||||||
g_assert(type_list[ftype] == NULL);
|
g_assert(type_list[ftype] == NULL);
|
||||||
|
@ -268,6 +269,12 @@ fvalue_from_string(ftenum_t ftype, char *s, LogFunc logfunc)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftype_t*
|
||||||
|
fvalue_ftype(fvalue_t *fv)
|
||||||
|
{
|
||||||
|
return fv->ftype;
|
||||||
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
fvalue_type_name(fvalue_t *fv)
|
fvalue_type_name(fvalue_t *fv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -196,6 +196,7 @@ typedef guint (*FvalueLen)(fvalue_t*);
|
||||||
typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint offset, guint length);
|
typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint offset, guint length);
|
||||||
|
|
||||||
struct _ftype_t {
|
struct _ftype_t {
|
||||||
|
ftenum_t ftype;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *pretty_name;
|
const char *pretty_name;
|
||||||
int wire_size;
|
int wire_size;
|
||||||
|
@ -288,6 +289,9 @@ fvalue_string_repr_len(fvalue_t *fv, ftrepr_t rtype);
|
||||||
extern char *
|
extern char *
|
||||||
fvalue_to_string_repr(fvalue_t *fv, ftrepr_t rtype, char *buf);
|
fvalue_to_string_repr(fvalue_t *fv, ftrepr_t rtype, char *buf);
|
||||||
|
|
||||||
|
ftype_t*
|
||||||
|
fvalue_ftype(fvalue_t *fv);
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
fvalue_type_name(fvalue_t *fv);
|
fvalue_type_name(fvalue_t *fv);
|
||||||
|
|
||||||
|
|
|
@ -1015,6 +1015,38 @@ class String(Test):
|
||||||
return self.DFilterCount(pkt_http,
|
return self.DFilterCount(pkt_http,
|
||||||
'http.request.method contains 48:45:41:44"', 1) # "HEAD"
|
'http.request.method contains 48:45:41:44"', 1) # "HEAD"
|
||||||
|
|
||||||
|
def ck_contains_fail_0(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'http.user_agent contains "update"', 0)
|
||||||
|
|
||||||
|
def ck_contains_fail_1(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'http.user_agent contains "UPDATE"', 0)
|
||||||
|
|
||||||
|
def ck_contains_upper_0(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'upper(http.user_agent) contains "UPDATE"', 1)
|
||||||
|
|
||||||
|
def ck_contains_upper_1(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'upper(http.user_agent) contains "update"', 0)
|
||||||
|
|
||||||
|
def ck_contains_upper_2(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'upper(tcp.seq) == 4', None)
|
||||||
|
|
||||||
|
def ck_contains_lower_0(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'lower(http.user_agent) contains "UPDATE"', 0)
|
||||||
|
|
||||||
|
def ck_contains_lower_1(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'lower(http.user_agent) contains "update"', 1)
|
||||||
|
|
||||||
|
def ck_contains_lower_2(self):
|
||||||
|
return self.DFilterCount(pkt_http,
|
||||||
|
'lower(tcp.seq) == 4', None)
|
||||||
|
|
||||||
|
|
||||||
tests = [
|
tests = [
|
||||||
ck_eq_1,
|
ck_eq_1,
|
||||||
|
@ -1047,6 +1079,14 @@ class String(Test):
|
||||||
ck_contains_3,
|
ck_contains_3,
|
||||||
ck_contains_4,
|
ck_contains_4,
|
||||||
ck_contains_5,
|
ck_contains_5,
|
||||||
|
ck_contains_fail_0,
|
||||||
|
ck_contains_fail_1,
|
||||||
|
ck_contains_upper_0,
|
||||||
|
ck_contains_upper_1,
|
||||||
|
ck_contains_upper_2,
|
||||||
|
ck_contains_lower_0,
|
||||||
|
ck_contains_lower_1,
|
||||||
|
ck_contains_lower_2,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue