4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 2001 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include "dfilter-int.h"
31 #include "syntax-tree.h"
35 #include <epan/epan_dissect.h>
37 #include "dfilter-macro.h"
38 #include <epan/report_err.h>
40 #define DFILTER_TOKEN_ID_OFFSET 1
42 /* Global error message space for dfilter_compile errors */
43 static gchar dfilter_error_msg_buf[1024];
44 gchar *dfilter_error_msg; /* NULL when no error resulted */
47 void df_scanner_text(const char *text);
48 void df_scanner_cleanup(void);
51 /* Holds the singular instance of our Lemon parser object */
52 static void* ParserObj = NULL;
55 dfilter_fail(const char *format, ...)
59 /* If we've already reported one error, don't overwite it */
60 if (dfilter_error_msg != NULL)
63 va_start(args, format);
65 g_vsnprintf(dfilter_error_msg_buf, sizeof(dfilter_error_msg_buf),
67 dfilter_error_msg = dfilter_error_msg_buf;
72 /* Initialize the dfilter module */
77 g_message("I expected ParserObj to be NULL\n");
78 /* Free the Lemon Parser object */
79 DfilterFree(ParserObj, g_free);
81 /* Allocate an instance of our Lemon-based parser */
82 ParserObj = DfilterAlloc(g_malloc);
84 /* Enable parser tracing by defining AM_CFLAGS
85 * so that it contains "-DDFTRACE".
89 DfilterTrace(stdout, "lemon> ");
92 /* Initialize the syntax-tree sub-sub-system */
98 /* Clean-up the dfilter module */
100 dfilter_cleanup(void)
102 /* Free the Lemon Parser object */
104 DfilterFree(ParserObj, g_free);
107 /* Clean up the syntax-tree sub-sub-system */
116 df = g_new(dfilter_t, 1);
122 /* Given a GPtrArray of instructions (dfvm_insn_t),
125 free_insns(GPtrArray *insns)
130 for (i = 0; i < insns->len; i++) {
131 insn = g_ptr_array_index(insns, i);
132 dfvm_insn_free(insn);
137 dfilter_free(dfilter_t *df)
140 free_insns(df->insns);
143 if (df->interesting_fields) {
144 g_free(df->interesting_fields);
147 g_free(df->registers);
148 g_free(df->attempted_load);
158 dfw = g_new(dfwork_t, 1);
161 dfw->syntax_error = FALSE;
163 dfw->loaded_fields = NULL;
164 dfw->interesting_fields = NULL;
165 dfw->next_insn_id = 0;
166 dfw->next_register = 0;
172 dfwork_free(dfwork_t *dfw)
175 stnode_free(dfw->st_root);
178 if (dfw->loaded_fields) {
179 g_hash_table_destroy(dfw->loaded_fields);
182 if (dfw->interesting_fields) {
183 g_hash_table_destroy(dfw->interesting_fields);
187 free_insns(dfw->insns);
195 dfilter_compile(const gchar *text, dfilter_t **dfp)
200 gboolean failure = FALSE;
202 dfilter_error_msg = NULL;
204 if ( !( text = dfilter_macro_apply(text, 0, &dfilter_error_msg) ) ) {
210 df_scanner_text(text);
213 df_lval = stnode_new(STTYPE_UNINITIALIZED, NULL);
216 /* Check for scanner failure */
217 if (token == SCAN_FAILED) {
222 /* Check for end-of-input */
227 /* Give the token to the parser */
228 Dfilter(ParserObj, token, df_lval, dfw);
229 /* We've used the stnode_t, so we don't want to free it */
232 if (dfw->syntax_error) {
238 /* If we created an stnode_t but didn't use it, free it; the
239 * parser doesn't know about it and won't free it for us. */
241 stnode_free(df_lval);
245 /* Tell the parser that we have reached the end of input; that
246 * way, it'll reset its state for the next compile. (We want
247 * to do that even if we got a syntax error, to make sure the
248 * parser state is cleaned up; we don't create a new parser
249 * object when we start a new parse, and don't destroy it when
250 * the parse finishes.) */
251 Dfilter(ParserObj, 0, NULL, dfw);
253 /* One last check for syntax error (after EOF) */
254 if (dfw->syntax_error)
258 df_scanner_cleanup();
263 /* Success, but was it an empty filter? If so, discard
264 * it and set *dfp to NULL */
265 if (dfw->st_root == NULL) {
270 /* Check semantics and do necessary type conversion*/
271 if (!dfw_semcheck(dfw)) {
275 /* Create bytecode */
278 /* Tuck away the bytecode in the dfilter_t */
279 dfilter = dfilter_new();
280 dfilter->insns = dfw->insns;
282 dfilter->interesting_fields = dfw_interesting_fields(dfw,
283 &dfilter->num_interesting_fields);
285 /* Initialize run-time space */
286 dfilter->num_registers = dfw->next_register;
287 dfilter->registers = g_new0(GList*, dfilter->num_registers);
288 dfilter->attempted_load = g_new0(gboolean, dfilter->num_registers);
290 /* And give it to the user. */
301 dfilter_fail("Unable to parse filter string \"%s\".", text);
309 dfilter_apply(dfilter_t *df, proto_tree *tree)
311 return dfvm_apply(df, tree);
315 dfilter_apply_edt(dfilter_t *df, epan_dissect_t* edt)
317 return dfvm_apply(df, edt->tree);
322 dfilter_prime_proto_tree(const dfilter_t *df, proto_tree *tree)
326 for (i = 0; i < df->num_interesting_fields; i++) {
327 proto_tree_prime_hfid(tree, df->interesting_fields[i]);
333 dfilter_dump(dfilter_t *df)
335 dfvm_dump(stdout, df->insns);