/* dfilter-grammar.y
* Parser for display filters
*
- * $Id: dfilter-grammar.y,v 1.8 1999/08/12 21:16:31 guy Exp $
+ * $Id: dfilter-grammar.y,v 1.9 1999/08/13 23:47:39 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#include "resolv.h"
#endif
-void dfilter_yacc_init(void);
static GNode* dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2);
static GNode* dfilter_mknode_unary(int operand, GNode *n2);
static GNode* dfilter_mknode_numeric_variable(gint id);
static guint32 string_to_value(char *s);
-/* space for dfilter_nodes */
-GMemChunk *gmc_dfilter_nodes = NULL;
-
-/* this is how we pass display filter tree (dfcode) back to calling routine */
-GNode *dfilter_tree = NULL;
-
-/* list of byte arrays we allocate during parse. We can traverse this list
- * faster than the tree when we go back and free the byte arrays */
-GSList *dfilter_list_byte_arrays = NULL;
+/* This is the dfilter we're currently processing. It's how
+ * dfilter_compile communicates with us.
+ */
+dfilter *global_df = NULL;;
%}
statement: expression
{
- dfilter_tree = $1;
+ global_df->dftree = $1;
}
- | /* NULL */ { dfilter_tree = NULL; }
+ | /* NULL */ { global_df->dftree = NULL; }
;
expression: '(' expression ')' { $$ = $2; }
{ /* one or 4 bytes */
GByteArray *barray;
- /* the next function appends to dfilter_list_byte_arrays for me */
+ /* the next function appends to list_of_byte_arrays for me */
barray = byte_str_to_guint8_array($1);
$$ = dfilter_mknode_bytes_value(barray);
g_free($1);
{ /* 6 bytes */
GByteArray *barray = g_byte_array_new();
- dfilter_list_byte_arrays = g_slist_append(dfilter_list_byte_arrays, barray);
+ global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
g_byte_array_append(barray, $1, 6);
$$ = dfilter_mknode_bytes_value(barray);
}
%%
-void
-dfilter_yacc_init(void)
-{
- if (gmc_dfilter_nodes)
- g_mem_chunk_destroy(gmc_dfilter_nodes);
-
- gmc_dfilter_nodes = g_mem_chunk_new("gmc_dfilter_nodes",
- sizeof(dfilter_node), 50 * sizeof(dfilter_node),
- G_ALLOC_ONLY);
-
- if (dfilter_list_byte_arrays) {
- /* clear the byte arrays */
- g_slist_free(dfilter_list_byte_arrays);
- }
-
-}
-
-void
-dfilter_yacc_cleanup(void)
-{
- if (gmc_dfilter_nodes)
- g_mem_chunk_destroy(gmc_dfilter_nodes);
-}
-
-
static GNode*
dfilter_mknode_join(GNode *n1, enum node_type ntype, int operand, GNode *n2)
{
dfilter_node *node_root;
GNode *gnode_root;
- node_root = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node_root = g_mem_chunk_alloc(global_df->node_memchunk);
node_root->ntype = ntype;
node_root->elem_size = 0;
node_root->fill_array_func = NULL;
dfilter_node *node_root;
GNode *gnode_root;
- node_root = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node_root = g_mem_chunk_alloc(global_df->node_memchunk);
node_root->ntype = logical;
node_root->value.logical = operand;
node_root->elem_size = 0;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_numeric_variable;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint8) * 6;
node->fill_array_func = fill_array_ether_variable;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint8) * 4;
node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_numeric_variable; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(GByteArray*);
node->fill_array_func = fill_array_bytes_variable;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = variable;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_boolean_variable; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = numeric;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_numeric_value;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = ether;
node->elem_size = sizeof(guint8) * 6;
node->fill_array_func = fill_array_ether_value;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = ipxnet;
node->elem_size = sizeof(guint8) * 4;
node->fill_array_func = fill_array_numeric_value; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = numeric;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_numeric_value; /* cheating ! */
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = bytes;
node->elem_size = sizeof(GByteArray*);
node->fill_array_func = fill_array_bytes_value;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = numeric;
node->elem_size = sizeof(guint32);
node->fill_array_func = fill_array_boolean_value;
dfilter_node *node;
GNode *gnode;
- node = g_mem_chunk_alloc(gmc_dfilter_nodes);
+ node = g_mem_chunk_alloc(global_df->node_memchunk);
node->ntype = existence;
node->elem_size = sizeof(guint32);
node->fill_array_func = NULL;
* Definitions for routines common to multiple modules in the display
* filter code, but not used outside that code.
*
- * $Id: dfilter-int.h,v 1.1 1999/08/12 21:16:31 guy Exp $
+ * $Id: dfilter-int.h,v 1.2 1999/08/13 23:47:40 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
/* in dfilter-scanner.l */
GByteArray *byte_str_to_guint8_array(const char *s);
+void dfilter_scanner_text(char*);
+void dfilter_scanner_cleanup(void);
/* in dfilter-grammar.y */
-extern GSList *dfilter_list_byte_arrays;
+extern dfilter *global_df;
/* Here we provide interfaces to make our scanner act and look like lex */
int yylex(void);
gboolean fill_array_boolean_value(GNode *gnode, gpointer data);
gboolean fill_array_boolean_variable(GNode *gnode, gpointer data);
+#ifdef WIN32
+#define boolean truth_value
+#endif
+
enum node_type {
relation, /* eq, ne, gt, ge, lt, le */
logical, /* and, or, not, xor */
/* dfilter-scanner.l
* Scanner for display filters
*
- * $Id: dfilter-scanner.l,v 1.6 1999/08/12 21:16:31 guy Exp $
+ * $Id: dfilter-scanner.l,v 1.7 1999/08/13 23:47:40 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
char *p, *str;
barray = g_byte_array_new();
- dfilter_list_byte_arrays = g_slist_append(dfilter_list_byte_arrays, barray);
+ /* XXX - don't use global_df, but pass in pointer to GSList* */
+ global_df->list_of_byte_arrays = g_slist_append(global_df->list_of_byte_arrays, barray);
byte_str = g_strdup(s);
str = byte_str;
/* dfilter.c
* Routines for display filters
*
- * $Id: dfilter.c,v 1.8 1999/08/12 21:16:30 guy Exp $
+ * $Id: dfilter.c,v 1.9 1999/08/13 23:47:40 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
YYSTYPE yylval;
-/* in dfilter-grammar.y */
-extern GMemChunk *gmc_dfilter_nodes;
-extern GNode *dfilter_tree;
-extern GSList *dfilter_list_byte_arrays;
-
-/* in dfilter-scanner.l */
-void dfilter_scanner_text(char*);
-void dfilter_scanner_cleanup(void);
-
static gboolean dfilter_apply_node(GNode *gnode, proto_tree *ptree, const guint8 *pd);
static gboolean check_relation(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd);
static gboolean check_logical(gint operand, GNode *a, GNode *b, proto_tree *ptree, const guint8 *pd);
}
}
}
-/* I should eventually g_tree_destroy(dfilter_tokens), when ethereal shuts down */
+/* XXX - I should eventually g_tree_destroy(dfilter_tokens), when ethereal shuts down */
/* Compiles the textual representation of the display filter into a tree
- * of operations to perform.
+ * of operations to perform. Can be called multiple times, compiling a new
+ * display filter each time, without having to clear any memory used, since
+ * dfilter_compile will take care of that automatically.
*/
int
-dfilter_compile(char *dfilter_text, GNode **p_dfcode)
+dfilter_compile(dfilter *df, gchar *dfilter_text)
{
int retval;
g_assert(dfilter_text != NULL);
- dfilter_scanner_text(dfilter_text);
- if (dfilter_tree) {
- /* clear tree */
- dfilter_tree = NULL;
- }
- /* clear the memory that the tree was using for nodes */
- g_mem_chunk_reset(gmc_dfilter_nodes);
+ dfilter_clear_filter(df);
+ df->dftext = g_strdup(dfilter_text);
- /* clear the memory that the tree was using for byte arrays */
- if (dfilter_list_byte_arrays) {
- g_slist_foreach(dfilter_list_byte_arrays, clear_byte_array, NULL);
- g_slist_free(dfilter_list_byte_arrays);
- dfilter_list_byte_arrays = NULL;
- }
+ /* tell the scanner to use this string as input */
+ dfilter_scanner_text(df->dftext);
- if (*p_dfcode != NULL)
- g_node_destroy(*p_dfcode);
+ /* Assign global variable so yyparse knows which dfilter we're talking about */
+ global_df = df;
+ /* The magic happens right here. */
retval = yyparse();
+
+ /* clean up lex */
dfilter_scanner_cleanup();
- *p_dfcode = dfilter_tree;
return retval;
}
+/* clear the current filter, w/o clearing memchunk area which is where we'll
+ * put new nodes in a future filter */
+void
+dfilter_clear_filter(dfilter *df)
+{
+ if (!df)
+ return;
+
+ if (df->dftext)
+ g_free(df->dftext);
+
+ if (df->dftree != NULL)
+ g_node_destroy(df->dftree);
+
+ /* clear the memory that the tree was using for nodes */
+ if (df->node_memchunk)
+ g_mem_chunk_reset(df->node_memchunk);
+
+ /* clear the memory that the tree was using for byte arrays */
+ if (df->list_of_byte_arrays) {
+ g_slist_foreach(df->list_of_byte_arrays, clear_byte_array, NULL);
+ g_slist_free(df->list_of_byte_arrays);
+ }
+
+ df->dftext = NULL;
+ df->dftree = NULL;
+ df->list_of_byte_arrays = NULL;
+}
+
+/* Allocates new dfilter, initializes values, and returns pointer to dfilter */
+dfilter*
+dfilter_new(void)
+{
+ dfilter *df;
+
+ df = g_malloc(sizeof(dfilter));
+
+ df->dftext = NULL;
+ df->dftree = NULL;
+ df->node_memchunk = g_mem_chunk_new("df->node_memchunk",
+ sizeof(dfilter_node), 20 * sizeof(dfilter_node), G_ALLOC_ONLY);
+ df->list_of_byte_arrays = NULL;
+
+ return df;
+}
+
+/* Frees all memory used by dfilter, and frees dfilter itself */
+void
+dfilter_destroy(dfilter *df)
+{
+ if (!df)
+ return;
+
+ dfilter_clear_filter(df);
+
+ /* Git rid of memchunk */
+ if (df->node_memchunk)
+ g_mem_chunk_destroy(df->node_memchunk);
+
+ g_free(df);
+}
+
+
+
+
+
static void
clear_byte_array(gpointer data, gpointer user_data)
{
void
dfilter_yyerror(char *fmt, ...)
{
- dfilter_tree = NULL;
+ global_df->dftree = NULL;
yyerror(fmt);
}
gboolean
-dfilter_apply(GNode *dfcode, proto_tree *ptree, const guint8* pd)
+dfilter_apply(dfilter *dfcode, proto_tree *ptree, const guint8* pd)
{
gboolean retval;
- retval = dfilter_apply_node(dfcode, ptree, pd);
+ retval = dfilter_apply_node(dfcode->dftree, ptree, pd);
return retval;
}
if (fi->hfinfo->id == sinfo->target_field) {
barray = g_byte_array_new();
- /*dfilter_list_byte_arrays = g_slist_append(dfilter_list_byte_arrays, barray);*/
+ /*list_of_byte_arrays = g_slist_append(list_of_byte_arrays, barray);*/
g_byte_array_append(barray, sinfo->packet_data + fi->start + bytes_offset, bytes_length);
g_array_append_val(sinfo->result_array, barray);
}
/* dfilter.h
* Definitions for display filters
*
- * $Id: dfilter.h,v 1.6 1999/08/12 21:16:32 guy Exp $
+ * $Id: dfilter.h,v 1.7 1999/08/13 23:47:41 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#ifndef __DFILTER_H__
#define __DFILTER_H__
+#define DFILTER_CONTAINS_FILTER(x) ((x)->dftree)
+
+typedef struct {
+
+ GNode *dftree;
+ gchar *dftext;
+
+ /* space for dfilter_nodes */
+ GMemChunk *node_memchunk;
+
+ /* list of byte arrays we allocate during parse. We can traverse this list
+ * faster than the tree when we go back and free the byte arrays */
+ GSList *list_of_byte_arrays;
+
+} dfilter;
+
+/* Initialization of the symbol table. Called once during program startup */
void dfilter_init(void);
-int dfilter_compile(char* dfilter_text, GNode** p_dfcode);
-gboolean dfilter_apply(GNode *dfcode, proto_tree *ptree, const guint8* pd);
-#ifdef WIN32
-#define boolean truth_value
-#endif
+/* Allocate and initialize new dfilter struct. Returns pointer to new dfilter */
+dfilter* dfilter_new(void);
+
+/* Frees all memory used by dfilter, and frees dfilter itself */
+void dfilter_destroy(dfilter *df);
+
+/* Compile display filter text */
+int dfilter_compile(dfilter* df, gchar* dfilter_text);
+
+/* Apply compiled dfilter to a proto_tree */
+gboolean dfilter_apply(dfilter *df, proto_tree *ptree, const guint8* pd);
+
+/* Clears the current filter int the dfilter */
+void dfilter_clear_filter(dfilter *df);
+
#endif /* ! __DFILTER_H__ */
/* ethereal.c
*
- * $Id: ethereal.c,v 1.82 1999/08/12 07:36:41 guy Exp $
+ * $Id: ethereal.c,v 1.83 1999/08/13 23:47:41 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
/* Run the current display filter on the current packet set, and
redisplay. */
static void
-filter_activate_cb(GtkWidget *w, gpointer data) {
- if (cf.dfilter) g_free(cf.dfilter);
- cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(w)));
+filter_activate_cb(GtkWidget *w, gpointer data)
+{
+ char *s = gtk_entry_get_text(GTK_ENTRY(w));
+
+ if (cf.dfilter)
+ g_free(cf.dfilter);
+
+ /* simple check for empty string. XXX - need to modify to search for /^\s+$/ */
+ if (s[0] == '\0' ) {
+ cf.dfilter = NULL;
+ }
+ else {
+ cf.dfilter = g_strdup(s);
+ }
+
filter_packets(&cf);
}
cf.plist_end = NULL;
cf.wth = NULL;
cf.fh = NULL;
+ cf.rfilter = NULL;
cf.dfilter = NULL;
- cf.dfcode = NULL;
+ cf.dfcode = dfilter_new();
#ifdef HAVE_LIBPCAP
cf.cfilter = NULL;
#endif
/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.61 1999/08/10 07:12:52 guy Exp $
+ * $Id: file.c,v 1.62 1999/08/13 23:47:42 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
static guint32 firstsec, firstusec;
static guint32 lastsec, lastusec;
-static GNode *rfcode;
+static dfilter *rfcode = NULL;
static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
const u_char *);
else
name_ptr++;
- rfcode = NULL;
- if (rfilter)
- if (dfilter_compile(rfilter, &rfcode) != 0) {
+ if (rfilter) {
+ rfcode = dfilter_new();
+ if (dfilter_compile(rfcode, rfilter) != 0) {
simple_dialog(ESD_TYPE_WARN, NULL,
"Unable to parse filter string \"%s\".", rfilter);
goto fail;
+ }
}
err = open_cap_file(fname, cf);
if (check_col(fdata, COL_NUMBER))
col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
/* Apply the display filter */
- if (cf->dfcode) {
+ if (DFILTER_CONTAINS_FILTER(cf->dfcode)) {
protocol_tree = proto_tree_create_root();
dissect_packet(buf, fdata, protocol_tree);
fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
/* gint timeout;*/
frame_data *fd;
- if (cf->dfilter != NULL) {
+ if (cf->dfilter == NULL) {
+ dfilter_clear_filter(cf->dfcode);
+ }
+ else {
/*
* Compile the filter.
*/
- if (dfilter_compile(cf->dfilter, &cf->dfcode) != 0) {
+ if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
simple_dialog(ESD_TYPE_WARN, NULL,
"Unable to parse filter string \"%s\".", cf->dfilter);
return;
/* file.h
* Definitions for file structures and routines
*
- * $Id: file.h,v 1.31 1999/08/11 17:02:27 gram Exp $
+ * $Id: file.h,v 1.32 1999/08/13 23:47:42 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#endif
#endif
+#ifndef __DFILTER_H__
+#include "dfilter.h"
+#endif
+
typedef struct bpf_program bpf_prog;
typedef struct _capture_file {
wtap *wth; /* Wiretap session */
gchar *rfilter; /* Read filter string */
gchar *dfilter; /* Display filter string */
- GNode *dfcode; /* Compiled display filter program */
+ dfilter *dfcode; /* Compiled display filter program */
#ifdef HAVE_LIBPCAP
gchar *cfilter; /* Capture filter string */
bpf_prog fcode; /* Compiled capture filter program */
/* proto.c
* Routines for protocol tree
*
- * $Id: proto.c,v 1.13 1999/08/10 20:05:40 guy Exp $
+ * $Id: proto.c,v 1.14 1999/08/13 23:47:43 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
/* ftype */ FT_TEXT_ONLY,
/* parent */ -1,
/* vals[] */ NULL );
-
- dfilter_yacc_init();
}
/* frees the resources that the dissection a proto_tree uses */
/* summary.c
* Routines for capture file summary window
*
- * $Id: summary.c,v 1.8 1999/08/10 04:13:36 guy Exp $
+ * $Id: summary.c,v 1.9 1999/08/13 23:47:43 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
}
add_string_to_box(string_buff, capture_box);
- /* Display filter. The situation where cf.dfilter="" and cf.dfcode=NULL can exist,
- so I'll check for both */
- if (cf.dfilter && cf.dfcode) {
- snprintf(string_buff, SUM_STR_MAX, "Display filter: %s", cf.dfilter);
+ /* Display filter */
+ if (DFILTER_CONTAINS_FILTER(cf.dfcode)) {
+ snprintf(string_buff, SUM_STR_MAX, "Display filter: %s", cf.dfcode->dftext);
} else {
sprintf(string_buff, "Display filter: none");
}