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.
27 #include "dfilter-int.h"
30 #include "syntax-tree.h"
31 #include "sttype-range.h"
32 #include "sttype-test.h"
33 #include "sttype-function.h"
34 #include "ftypes/ftypes.h"
37 gencode(dfwork_t *dfw, stnode_t *st_node);
40 gen_entity(dfwork_t *dfw, stnode_t *st_arg, dfvm_value_t **p_jmp);
43 dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
45 insn->id = dfw->next_insn_id;
47 g_ptr_array_add(dfw->insns, insn);
50 /* returns register number */
52 dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo)
55 dfvm_value_t *val1, *val2;
57 gboolean added_new_hfinfo = FALSE;
59 /* Rewind to find the first field of this name. */
60 while (hfinfo->same_name_prev) {
61 hfinfo = hfinfo->same_name_prev;
64 /* Keep track of which registers
65 * were used for which hfinfo's so that we
66 * can re-use registers. */
67 reg = GPOINTER_TO_UINT(
68 g_hash_table_lookup(dfw->loaded_fields, hfinfo));
70 /* Reg's are stored in has as reg+1, so
71 * that the non-existence of a hfinfo in
72 * the hash, or 0, can be differentiated from
73 * a hfinfo being loaded into register #0. */
77 reg = dfw->next_register++;
78 g_hash_table_insert(dfw->loaded_fields,
79 hfinfo, GUINT_TO_POINTER(reg + 1));
81 added_new_hfinfo = TRUE;
84 insn = dfvm_insn_new(READ_TREE);
85 val1 = dfvm_value_new(HFINFO);
86 val1->value.hfinfo = hfinfo;
87 val2 = dfvm_value_new(REGISTER);
88 val2->value.numeric = reg;
92 dfw_append_insn(dfw, insn);
94 if (added_new_hfinfo) {
96 /* Record the FIELD_ID in hash of interesting fields. */
97 g_hash_table_insert(dfw->interesting_fields,
98 GINT_TO_POINTER(hfinfo->id),
99 GUINT_TO_POINTER(TRUE));
100 hfinfo = hfinfo->same_name_next;
107 /* returns register number */
109 dfw_append_put_fvalue(dfwork_t *dfw, fvalue_t *fv)
112 dfvm_value_t *val1, *val2;
115 insn = dfvm_insn_new(PUT_FVALUE);
116 val1 = dfvm_value_new(FVALUE);
117 val1->value.fvalue = fv;
118 val2 = dfvm_value_new(REGISTER);
119 reg = dfw->next_register++;
120 val2->value.numeric = reg;
123 dfw_append_insn(dfw, insn);
128 /* returns register number */
130 dfw_append_mk_range(dfwork_t *dfw, stnode_t *node)
133 header_field_info *hfinfo;
137 hfinfo = sttype_range_hfinfo(node);
138 hf_reg = dfw_append_read_tree(dfw, hfinfo);
140 insn = dfvm_insn_new(MK_RANGE);
142 val = dfvm_value_new(REGISTER);
143 val->value.numeric = hf_reg;
146 val = dfvm_value_new(REGISTER);
147 reg =dfw->next_register++;
148 val->value.numeric = reg;
151 val = dfvm_value_new(DRANGE);
152 val->value.drange = sttype_range_drange(node);
155 sttype_range_remove_drange(node);
157 dfw_append_insn(dfw, insn);
162 /* returns register number that the functions's result will be in. */
164 dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp)
167 int i, num_params, reg;
170 dfvm_value_t *val1, *val2, *val;
172 params = sttype_function_params(node);
173 num_params = g_slist_length(params);
175 /* Array to hold the instructions that need to jump to
176 * an instruction if they fail. */
177 jmps = g_malloc(num_params * sizeof(dfvm_value_t*));
179 /* Create the new DFVM instruction */
180 insn = dfvm_insn_new(CALL_FUNCTION);
182 val1 = dfvm_value_new(FUNCTION_DEF);
183 val1->value.funcdef = sttype_function_funcdef(node);
185 val2 = dfvm_value_new(REGISTER);
186 val2->value.numeric = dfw->next_register++;
194 reg = gen_entity(dfw, params->data, &jmps[i]);
196 val = dfvm_value_new(REGISTER);
197 val->value.numeric = reg;
207 g_assert_not_reached();
210 params = params->next;
214 dfw_append_insn(dfw, insn);
216 /* If any of our parameters failed, send them to
217 * our own failure instruction. This *has* to be done
218 * after we caled dfw_append_insn above so that
219 * we know what the next DFVM insruction is, via
220 * dfw->next_insn_id */
221 for (i = 0; i < num_params; i++) {
223 jmps[i]->value.numeric = dfw->next_insn_id;
227 /* We need another instruction to jump to another exit
228 * place, if the call() of our function failed for some reaosn */
229 insn = dfvm_insn_new(IF_FALSE_GOTO);
231 *p_jmp = dfvm_value_new(INSN_NUMBER);
233 dfw_append_insn(dfw, insn);
237 return val2->value.numeric;
242 gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2)
245 dfvm_value_t *val1, *val2;
246 dfvm_value_t *jmp1 = NULL, *jmp2 = NULL;
247 int reg1 = -1, reg2 = -1;
249 /* Create code for the LHS and RHS of the relation */
250 reg1 = gen_entity(dfw, st_arg1, &jmp1);
251 reg2 = gen_entity(dfw, st_arg2, &jmp2);
253 /* Then combine them in a DFVM insruction */
254 insn = dfvm_insn_new(op);
255 val1 = dfvm_value_new(REGISTER);
256 val1->value.numeric = reg1;
257 val2 = dfvm_value_new(REGISTER);
258 val2->value.numeric = reg2;
261 dfw_append_insn(dfw, insn);
263 /* If either of the relation argumnents need an "exit" instruction
264 * to jump to (on failure), mark them */
266 jmp1->value.numeric = dfw->next_insn_id;
270 jmp2->value.numeric = dfw->next_insn_id;
274 /* Parse an entity, returning the reg that it gets put into.
275 * p_jmp will be set if it has to be set by the calling code; it should
276 * be set to the place to jump to, to return to the calling code,
277 * if the load of a field from the proto_tree fails. */
279 gen_entity(dfwork_t *dfw, stnode_t *st_arg, dfvm_value_t **p_jmp)
283 header_field_info *hfinfo;
285 e_type = stnode_type_id(st_arg);
287 if (e_type == STTYPE_FIELD) {
288 hfinfo = stnode_data(st_arg);
289 reg = dfw_append_read_tree(dfw, hfinfo);
291 insn = dfvm_insn_new(IF_FALSE_GOTO);
293 *p_jmp = dfvm_value_new(INSN_NUMBER);
295 dfw_append_insn(dfw, insn);
297 else if (e_type == STTYPE_FVALUE) {
298 reg = dfw_append_put_fvalue(dfw, stnode_data(st_arg));
300 else if (e_type == STTYPE_RANGE) {
301 reg = dfw_append_mk_range(dfw, st_arg);
303 else if (e_type == STTYPE_FUNCTION) {
304 reg = dfw_append_function(dfw, st_arg, p_jmp);
307 printf("sttype_id is %u\n", e_type);
308 g_assert_not_reached();
315 gen_test(dfwork_t *dfw, stnode_t *st_node)
318 stnode_t *st_arg1, *st_arg2;
322 header_field_info *hfinfo;
324 sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
327 case TEST_OP_UNINITIALIZED:
328 g_assert_not_reached();
332 val1 = dfvm_value_new(HFINFO);
333 hfinfo = stnode_data(st_arg1);
335 /* Rewind to find the first field of this name. */
336 while (hfinfo->same_name_prev) {
337 hfinfo = hfinfo->same_name_prev;
339 val1->value.hfinfo = hfinfo;
340 insn = dfvm_insn_new(CHECK_EXISTS);
342 dfw_append_insn(dfw, insn);
344 /* Record the FIELD_ID in hash of interesting fields. */
346 g_hash_table_insert(dfw->interesting_fields,
347 GINT_TO_POINTER(hfinfo->id),
348 GUINT_TO_POINTER(TRUE));
349 hfinfo = hfinfo->same_name_next;
355 gencode(dfw, st_arg1);
356 insn = dfvm_insn_new(NOT);
357 dfw_append_insn(dfw, insn);
361 gencode(dfw, st_arg1);
363 insn = dfvm_insn_new(IF_FALSE_GOTO);
364 val1 = dfvm_value_new(INSN_NUMBER);
366 dfw_append_insn(dfw, insn);
368 gencode(dfw, st_arg2);
369 val1->value.numeric = dfw->next_insn_id;
373 gencode(dfw, st_arg1);
375 insn = dfvm_insn_new(IF_TRUE_GOTO);
376 val1 = dfvm_value_new(INSN_NUMBER);
378 dfw_append_insn(dfw, insn);
380 gencode(dfw, st_arg2);
381 val1->value.numeric = dfw->next_insn_id;
385 gen_relation(dfw, ANY_EQ, st_arg1, st_arg2);
389 gen_relation(dfw, ANY_NE, st_arg1, st_arg2);
393 gen_relation(dfw, ANY_GT, st_arg1, st_arg2);
397 gen_relation(dfw, ANY_GE, st_arg1, st_arg2);
401 gen_relation(dfw, ANY_LT, st_arg1, st_arg2);
405 gen_relation(dfw, ANY_LE, st_arg1, st_arg2);
408 case TEST_OP_BITWISE_AND:
409 gen_relation(dfw, ANY_BITWISE_AND, st_arg1, st_arg2);
412 case TEST_OP_CONTAINS:
413 gen_relation(dfw, ANY_CONTAINS, st_arg1, st_arg2);
416 case TEST_OP_MATCHES:
417 gen_relation(dfw, ANY_MATCHES, st_arg1, st_arg2);
423 gencode(dfwork_t *dfw, stnode_t *st_node)
427 name = stnode_type_name(st_node);
429 switch (stnode_type_id(st_node)) {
431 gen_test(dfw, st_node);
434 g_assert_not_reached();
440 dfw_gencode(dfwork_t *dfw)
442 dfw->insns = g_ptr_array_new();
443 dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
444 dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
445 gencode(dfw, dfw->st_root);
446 dfw_append_insn(dfw, dfvm_insn_new(RETURN));
457 get_hash_key(gpointer key, gpointer value _U_, gpointer user_data)
459 int field_id = GPOINTER_TO_INT(key);
460 hash_key_iterator *hki = user_data;
462 hki->fields[hki->i] = field_id;
467 dfw_interesting_fields(dfwork_t *dfw, int *caller_num_fields)
469 int num_fields = g_hash_table_size(dfw->interesting_fields);
471 hash_key_iterator hki;
473 if (num_fields == 0) {
474 *caller_num_fields = 0;
478 hki.fields = g_new(int, num_fields);
481 g_hash_table_foreach(dfw->interesting_fields, get_hash_key, &hki);
482 *caller_num_fields = num_fields;