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