name change
[obnox/wireshark/wip.git] / epan / dfilter / dfvm.c
1 /*
2  * $Id$
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2001 Gerald Combs
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "dfvm.h"
28
29 dfvm_insn_t*
30 dfvm_insn_new(dfvm_opcode_t op)
31 {
32         dfvm_insn_t     *insn;
33
34         insn = g_new(dfvm_insn_t, 1);
35         insn->op = op;
36         insn->arg1 = NULL;
37         insn->arg2 = NULL;
38         insn->arg3 = NULL;
39         return insn;
40 }
41
42 static void
43 dfvm_value_free(dfvm_value_t *v)
44 {
45         switch (v->type) {
46                 case FVALUE:
47                         FVALUE_FREE(v->value.fvalue);
48                         break;
49                 case DRANGE:
50                         drange_free(v->value.drange);
51                         break;
52                 default:
53                         /* nothing */
54                         ;
55         }
56         g_free(v);
57 }
58
59 void
60 dfvm_insn_free(dfvm_insn_t *insn)
61 {
62         if (insn->arg1) {
63                 dfvm_value_free(insn->arg1);
64         }
65         if (insn->arg2) {
66                 dfvm_value_free(insn->arg2);
67         }
68         if (insn->arg3) {
69                 dfvm_value_free(insn->arg3);
70         }
71         g_free(insn);
72 }
73
74
75 dfvm_value_t*
76 dfvm_value_new(dfvm_value_type_t type)
77 {
78         dfvm_value_t    *v;
79
80         v = g_new(dfvm_value_t, 1);
81         v->type = type;
82         return v;
83 }
84
85
86 void
87 dfvm_dump(FILE *f, GPtrArray *insns)
88 {
89         int             id, length;
90         dfvm_insn_t     *insn;
91         dfvm_value_t    *arg1;
92         dfvm_value_t    *arg2;
93         dfvm_value_t    *arg3;
94         dfvm_value_t    *arg4;
95         char            *value_str;
96         GSList          *range_list;
97         drange_node     *range_item;
98
99         length = insns->len;
100
101         for (id = 0; id < length; id++) {
102
103                 insn = g_ptr_array_index(insns, id);
104                 arg1 = insn->arg1;
105                 arg2 = insn->arg2;
106                 arg3 = insn->arg3;
107                 arg4 = insn->arg4;
108
109                 switch (insn->op) {
110                         case CHECK_EXISTS:
111                                 fprintf(f, "%05d CHECK_EXISTS\t%s\n",
112                                         id, arg1->value.hfinfo->abbrev);
113                                 break;
114
115                         case READ_TREE:
116                                 fprintf(f, "%05d READ_TREE\t\t%s -> reg#%u\n",
117                                         id, arg1->value.hfinfo->abbrev,
118                                         arg2->value.numeric);
119                                 break;
120
121             case CALL_FUNCTION:
122                 fprintf(f, "%05d CALL_FUNCTION\t%s (",
123                         id, arg1->value.funcdef->name);
124                 if (arg3) {
125                     fprintf(f, "reg#%u", arg3->value.numeric);
126                 }
127                 if (arg4) {
128                     fprintf(f, ", reg#%u", arg4->value.numeric);
129                 }
130                 fprintf(f, ") --> reg#%u\n", arg2->value.numeric);
131                 break;
132
133                         case PUT_FVALUE:
134                                 value_str = fvalue_to_string_repr(arg1->value.fvalue,
135                                         FTREPR_DFILTER, NULL);
136                                 fprintf(f, "%05d PUT_FVALUE\t%s <%s> -> reg#%u\n",
137                                         id, value_str,
138                                         fvalue_type_name(arg1->value.fvalue),
139                                         arg2->value.numeric);
140                                 g_free(value_str);
141                                 break;
142
143                         case MK_RANGE:
144                                 arg3 = insn->arg3;
145                                 fprintf(f, "%05d MK_RANGE\t\treg#%u[",
146                                         id,
147                                         arg1->value.numeric);
148                                 for (range_list = arg3->value.drange->range_list;
149                                      range_list != NULL;
150                                      range_list = range_list->next) {
151                                         range_item = range_list->data;
152                                         switch (range_item->ending) {
153
154                                         case UNINITIALIZED:
155                                                 fprintf(f, "?");
156                                                 break;
157
158                                         case LENGTH:
159                                                 fprintf(f, "%d:%d",
160                                                     range_item->start_offset,
161                                                     range_item->length);
162                                                 break;
163
164                                         case OFFSET:
165                                                 fprintf(f, "%d-%d",
166                                                     range_item->start_offset,
167                                                     range_item->end_offset);
168                                                 break;
169
170                                         case TO_THE_END:
171                                                 fprintf(f, "%d:",
172                                                     range_item->start_offset);
173                                                 break;
174                                         }
175                                         if (range_list->next != NULL)
176                                                 fprintf(f, ",");
177                                 }
178                                 fprintf(f, "] -> reg#%u\n",
179                                         arg2->value.numeric);
180                                 break;
181
182                         case ANY_EQ:
183                                 fprintf(f, "%05d ANY_EQ\t\treg#%u == reg#%u\n",
184                                         id, arg1->value.numeric, arg2->value.numeric);
185                                 break;
186
187                         case ANY_NE:
188                                 fprintf(f, "%05d ANY_NE\t\treg#%u == reg#%u\n",
189                                         id, arg1->value.numeric, arg2->value.numeric);
190                                 break;
191
192                         case ANY_GT:
193                                 fprintf(f, "%05d ANY_GT\t\treg#%u == reg#%u\n",
194                                         id, arg1->value.numeric, arg2->value.numeric);
195                                 break;
196
197                         case ANY_GE:
198                                 fprintf(f, "%05d ANY_GE\t\treg#%u == reg#%u\n",
199                                         id, arg1->value.numeric, arg2->value.numeric);
200                                 break;
201
202                         case ANY_LT:
203                                 fprintf(f, "%05d ANY_LT\t\treg#%u == reg#%u\n",
204                                         id, arg1->value.numeric, arg2->value.numeric);
205                                 break;
206
207                         case ANY_LE:
208                                 fprintf(f, "%05d ANY_LE\t\treg#%u == reg#%u\n",
209                                         id, arg1->value.numeric, arg2->value.numeric);
210                                 break;
211
212                         case ANY_BITWISE_AND:
213                                 fprintf(f, "%05d ANY_BITWISE_AND\t\treg#%u == reg#%u\n",
214                                         id, arg1->value.numeric, arg2->value.numeric);
215                                 break;
216
217                         case ANY_CONTAINS:
218                                 fprintf(f, "%05d ANY_CONTAINS\treg#%u contains reg#%u\n",
219                                         id, arg1->value.numeric, arg2->value.numeric);
220                                 break;
221
222                         case ANY_MATCHES:
223                                 fprintf(f, "%05d ANY_MATCHES\treg#%u matches reg#%u\n",
224                                         id, arg1->value.numeric, arg2->value.numeric);
225                                 break;
226
227                         case NOT:
228                                 fprintf(f, "%05d NOT\n", id);
229                                 break;
230
231                         case RETURN:
232                                 fprintf(f, "%05d RETURN\n", id);
233                                 break;
234
235                         case IF_TRUE_GOTO:
236                                 fprintf(f, "%05d IF-TRUE-GOTO\t%d\n",
237                                                 id, arg1->value.numeric);
238                                 break;
239
240                         case IF_FALSE_GOTO:
241                                 fprintf(f, "%05d IF-FALSE-GOTO\t%d\n",
242                                                 id, arg1->value.numeric);
243                                 break;
244
245                         default:
246                                 g_assert_not_reached();
247                                 break;
248                 }
249         }
250 }
251
252 /* Reads a field from the proto_tree and loads the fvalues into a register,
253  * if that field has not already been read. */
254 static gboolean
255 read_tree(dfilter_t *df, proto_tree *tree, header_field_info *hfinfo, int reg)
256 {
257         GPtrArray       *finfos;
258         field_info      *finfo;
259         int             i, len;
260         GList           *fvalues = NULL;
261         gboolean        found_something = FALSE;
262
263         /* Already loaded in this run of the dfilter? */
264         if (df->attempted_load[reg]) {
265                 if (df->registers[reg]) {
266                         return TRUE;
267                 }
268                 else {
269                         return FALSE;
270                 }
271         }
272
273         df->attempted_load[reg] = TRUE;
274
275         while (hfinfo) {
276                 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
277                 if (!finfos) {
278                         hfinfo = hfinfo->same_name_next;
279                         continue;
280                 }
281                 else if (g_ptr_array_len(finfos) == 0) {
282                         hfinfo = hfinfo->same_name_next;
283                         continue;
284                 }
285                 else {
286                         found_something = TRUE;
287                 }
288
289                 len = finfos->len;
290                 for (i = 0; i < len; i++) {
291                         finfo = g_ptr_array_index(finfos, i);
292                         fvalues = g_list_prepend(fvalues, &finfo->value);
293                 }
294
295                 hfinfo = hfinfo->same_name_next;
296         }
297
298         if (!found_something) {
299                 return FALSE;
300         }
301
302         df->registers[reg] = fvalues;
303         return TRUE;
304 }
305
306
307 static gboolean
308 put_fvalue(dfilter_t *df, fvalue_t *fv, int reg)
309 {
310         df->registers[reg] = g_list_append(NULL, fv);
311         return TRUE;
312 }
313
314 typedef gboolean (*FvalueCmpFunc)(fvalue_t*, fvalue_t*);
315
316 static gboolean
317 any_test(dfilter_t *df, FvalueCmpFunc cmp, int reg1, int reg2)
318 {
319         GList   *list_a, *list_b;
320
321         list_a = df->registers[reg1];
322
323         while (list_a) {
324                 list_b = df->registers[reg2];
325                 while (list_b) {
326                         if (cmp(list_a->data, list_b->data)) {
327                                 return TRUE;
328                         }
329                         list_b = g_list_next(list_b);
330                 }
331                 list_a = g_list_next(list_a);
332         }
333         return FALSE;
334 }
335
336
337 /* Free the list nodes w/o freeing the memory that each
338  * list node points to. */
339 static void
340 free_register_overhead(dfilter_t* df)
341 {
342         int i;
343
344         for (i = 0; i < df->num_registers; i++) {
345                 if (df->registers[i]) {
346                         g_list_free(df->registers[i]);
347                 }
348         }
349 }
350
351 /* Takes the list of fvalue_t's in a register, uses fvalue_slice()
352  * to make a new list of fvalue_t's (which are ranges, or byte-slices),
353  * and puts the new list into a new register. */
354 static void
355 mk_range(dfilter_t *df, int from_reg, int to_reg, drange *drange)
356 {
357         GList           *from_list, *to_list;
358         fvalue_t        *old_fv, *new_fv;
359
360         to_list = NULL;
361         from_list = df->registers[from_reg];
362
363         while (from_list) {
364                 old_fv = from_list->data;
365                 new_fv = fvalue_slice(old_fv, drange);
366                 /* Assert here because semcheck.c should have
367                  * already caught the cases in which a slice
368                  * cannot be made. */
369                 g_assert(new_fv);
370                 to_list = g_list_append(to_list, new_fv);
371
372                 from_list = g_list_next(from_list);
373         }
374
375         df->registers[to_reg] = to_list;
376 }
377
378
379
380 gboolean
381 dfvm_apply(dfilter_t *df, proto_tree *tree)
382 {
383         int             i, id, length;
384         gboolean        accum = TRUE;
385         dfvm_insn_t     *insn;
386         dfvm_value_t    *arg1;
387         dfvm_value_t    *arg2;
388         dfvm_value_t    *arg3 = NULL;
389         dfvm_value_t    *arg4 = NULL;
390         header_field_info       *hfinfo;
391     GList           *param1;
392     GList           *param2;
393
394         g_assert(tree);
395
396
397         /* Clear registers */
398         for (i = 0; i < df->num_registers; i++) {
399                 df->registers[i] = NULL;
400                 df->attempted_load[i] = FALSE;
401         }
402
403         length = df->insns->len;
404
405         for (id = 0; id < length; id++) {
406
407           AGAIN:
408                 insn = g_ptr_array_index(df->insns, id);
409                 arg1 = insn->arg1;
410                 arg2 = insn->arg2;
411
412                 switch (insn->op) {
413                         case CHECK_EXISTS:
414                                 hfinfo = arg1->value.hfinfo;
415                                 while(hfinfo) {
416                                         accum = proto_check_for_protocol_or_field(tree,
417                                                         arg1->value.hfinfo->id);
418                                         if (accum) {
419                                                 break;
420                                         }
421                                         else {
422                                                 hfinfo = hfinfo->same_name_next;
423                                         }
424                                 }
425                                 break;
426
427                         case READ_TREE:
428                                 accum = read_tree(df, tree,
429                                                 arg1->value.hfinfo, arg2->value.numeric);
430                                 break;
431
432                         case CALL_FUNCTION:
433                                 arg3 = insn->arg3;
434                                 arg4 = insn->arg4;
435                 param1 = NULL;
436                 param2 = NULL;
437                 if (arg3) {
438                     param1 = df->registers[arg3->value.numeric];
439                 }
440                 if (arg4) {
441                     param2 = df->registers[arg4->value.numeric];
442                 }
443                 accum = arg1->value.funcdef->function(param1, param2,
444                     &df->registers[arg2->value.numeric]); 
445                                 break;
446
447                         case PUT_FVALUE:
448                                 accum = put_fvalue(df,
449                                                 arg1->value.fvalue, arg2->value.numeric);
450                                 break;
451
452                         case MK_RANGE:
453                                 arg3 = insn->arg3;
454                                 mk_range(df,
455                                                 arg1->value.numeric, arg2->value.numeric,
456                                                 arg3->value.drange);
457                                 break;
458
459                         case ANY_EQ:
460                                 accum = any_test(df, fvalue_eq,
461                                                 arg1->value.numeric, arg2->value.numeric);
462                                 break;
463
464                         case ANY_NE:
465                                 accum = any_test(df, fvalue_ne,
466                                                 arg1->value.numeric, arg2->value.numeric);
467                                 break;
468
469                         case ANY_GT:
470                                 accum = any_test(df, fvalue_gt,
471                                                 arg1->value.numeric, arg2->value.numeric);
472                                 break;
473
474                         case ANY_GE:
475                                 accum = any_test(df, fvalue_ge,
476                                                 arg1->value.numeric, arg2->value.numeric);
477                                 break;
478
479                         case ANY_LT:
480                                 accum = any_test(df, fvalue_lt,
481                                                 arg1->value.numeric, arg2->value.numeric);
482                                 break;
483
484                         case ANY_LE:
485                                 accum = any_test(df, fvalue_le,
486                                                 arg1->value.numeric, arg2->value.numeric);
487                                 break;
488
489                         case ANY_BITWISE_AND:
490                                 accum = any_test(df, fvalue_bitwise_and,
491                                                 arg1->value.numeric, arg2->value.numeric);
492                                 break;
493
494                         case ANY_CONTAINS:
495                                 accum = any_test(df, fvalue_contains,
496                                                 arg1->value.numeric, arg2->value.numeric);
497                                 break;
498
499                         case ANY_MATCHES:
500                                 accum = any_test(df, fvalue_matches,
501                                                 arg1->value.numeric, arg2->value.numeric);
502                                 break;
503
504                         case NOT:
505                                 accum = !accum;
506                                 break;
507
508                         case RETURN:
509                                 free_register_overhead(df);
510                                 return accum;
511
512                         case IF_TRUE_GOTO:
513                                 if (accum) {
514                                         id = arg1->value.numeric;
515                                         goto AGAIN;
516                                 }
517                                 break;
518
519                         case IF_FALSE_GOTO:
520                                 if (!accum) {
521                                         id = arg1->value.numeric;
522                                         goto AGAIN;
523                                 }
524                                 break;
525
526
527                         default:
528                                 g_assert_not_reached();
529                                 break;
530                 }
531         }
532
533         g_assert_not_reached();
534         return FALSE; /* to appease the compiler */
535 }