Provide for per-protocol-tree data in the proto_tree code.
[obnox/wireshark/wip.git] / epan / dfilter / semcheck.c
1 /*
2  * $Id: semcheck.c,v 1.7 2001/12/18 19:09:06 gram Exp $
3  *
4  * Ethereal - Network traffic analyzer
5  * By Gerald Combs <gerald@ethereal.com>
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 <string.h>
28
29 #include "dfilter-int.h"
30 #include "syntax-tree.h"
31 #include "sttype-range.h"
32 #include "sttype-test.h"
33
34 #include "exceptions.h"
35 #include "packet.h"
36
37 static void
38 semcheck(dfwork_t *dfw, stnode_t *st_node);
39
40 typedef gboolean (*FtypeCanFunc)(enum ftenum);
41
42 /* Compares to ftenum_t's and decides if they're
43  * compatible or not (if they're the same basic type) */
44 static gboolean
45 compatible_ftypes(ftenum_t a, ftenum_t b)
46 {
47         switch (a) {
48                 case FT_NONE:
49                 case FT_PROTOCOL:
50                 case FT_DOUBLE:
51                 case FT_ABSOLUTE_TIME:
52                 case FT_RELATIVE_TIME:
53                 case FT_IPv4:
54                 case FT_IPv6:
55                 case FT_IPXNET:
56                 case FT_INT64:
57                 case FT_UINT64:
58                         return a == b;
59
60                 case FT_ETHER:
61                 case FT_BYTES:
62                         return (b == FT_ETHER || b == FT_BYTES);
63
64                 case FT_BOOLEAN:
65                 case FT_UINT8:
66                 case FT_UINT16:
67                 case FT_UINT24:
68                 case FT_UINT32:
69                 case FT_INT8:
70                 case FT_INT16:
71                 case FT_INT24:
72                 case FT_INT32:
73                         switch (b) {
74                                 case FT_BOOLEAN:
75                                 case FT_UINT8:
76                                 case FT_UINT16:
77                                 case FT_UINT24:
78                                 case FT_UINT32:
79                                 case FT_INT8:
80                                 case FT_INT16:
81                                 case FT_INT24:
82                                 case FT_INT32:
83                                         return TRUE;
84                                 default:
85                                         return FALSE;
86                         }
87                         
88                 case FT_STRING:
89                 case FT_STRINGZ:
90                 case FT_UINT_STRING:
91                         switch (b) {
92                                 case FT_STRING:
93                                 case FT_STRINGZ:
94                                 case FT_UINT_STRING:
95                                         return TRUE;
96                                 default:
97                                         return FALSE;
98                         }
99
100                 case FT_NUM_TYPES:
101                         g_assert_not_reached();
102         }
103
104         g_assert_not_reached();
105         return FALSE;
106 }
107
108 /* Creates a FT_UINT32 fvalue with a given value. */
109 static fvalue_t*
110 mk_uint32_fvalue(guint32 val)
111 {
112         fvalue_t *fv;
113
114         fv = fvalue_new(FT_UINT32);
115         fvalue_set_integer(fv, val);
116
117         return fv;
118 }
119
120
121 /* Try to make an fvalue from a string using a value_string or true_false_string.
122  * This works only for ftypes that are integers. Returns the created fvalue_t*
123  * or NULL if impossible. */
124 static fvalue_t*
125 mk_fvalue_from_val_string(header_field_info *hfinfo, char *s)
126 {
127         static true_false_string        default_tf = { "True", "False" };
128         true_false_string               *tf = &default_tf;
129         value_string                    *vals;
130
131         /* Early return? */
132         switch(hfinfo->type) {
133                 case FT_NONE:
134                 case FT_PROTOCOL:
135                 case FT_DOUBLE:
136                 case FT_ABSOLUTE_TIME:
137                 case FT_RELATIVE_TIME:
138                 case FT_IPv4:
139                 case FT_IPv6:
140                 case FT_IPXNET:
141                 case FT_ETHER:
142                 case FT_BYTES:
143                 case FT_STRING:
144                 case FT_STRINGZ:
145                 case FT_UINT_STRING:
146                 case FT_UINT64:
147                 case FT_INT64:
148                         return FALSE;
149
150                 case FT_BOOLEAN:
151                 case FT_UINT8:
152                 case FT_UINT16:
153                 case FT_UINT24:
154                 case FT_UINT32:
155                 case FT_INT8:
156                 case FT_INT16:
157                 case FT_INT24:
158                 case FT_INT32:
159                         break;
160                         
161                 case FT_NUM_TYPES:
162                         g_assert_not_reached();
163         }
164
165         /* Reset the dfilter error message, since *something* interesting
166          * will happen, and the error message will be more interesting than
167          * any error message I happen to have now. */
168         dfilter_error_msg = NULL;
169
170         /* TRUE/FALSE *always* exist for FT_BOOLEAN. */
171         if (hfinfo->type == FT_BOOLEAN) {
172                 if (hfinfo->strings) {
173                         tf = hfinfo->strings;
174                 }
175
176                 if (strcasecmp(s, tf->true_string) == 0) {
177                         return mk_uint32_fvalue(TRUE);
178                 }
179                 else if (strcasecmp(s, tf->false_string) == 0) {
180                         return mk_uint32_fvalue(FALSE);
181                 }
182                 else {
183                 dfilter_fail("\"%s\" cannot be found among the possible values for %s.",
184                                 s, hfinfo->abbrev);
185                         return NULL;
186                 }
187         }
188
189         /* Do val_strings exist? */
190         if (!hfinfo->strings) {
191                 dfilter_fail("%s cannot accept strings as values.",
192                                 hfinfo->abbrev);
193                 return FALSE;
194         }
195
196         vals = hfinfo->strings;
197         while (vals->strptr != NULL) {
198                 if (strcasecmp(s, vals->strptr) == 0) {
199                         return mk_uint32_fvalue(vals->value);
200                 }
201                 vals++;
202         }
203         dfilter_fail("\"%s\" cannot be found among the possible values for %s.",
204                         s, hfinfo->abbrev);
205         return FALSE;
206 }
207
208
209 static gboolean
210 is_bytes_type(enum ftenum type)
211 {
212         switch(type) {
213                 case FT_ETHER:
214                 case FT_BYTES:
215                 case FT_IPv6:
216                         return TRUE;
217
218                 case FT_NONE:
219                 case FT_PROTOCOL:
220                 case FT_DOUBLE:
221                 case FT_ABSOLUTE_TIME:
222                 case FT_RELATIVE_TIME:
223                 case FT_IPv4:
224                 case FT_IPXNET:
225                 case FT_STRING:
226                 case FT_STRINGZ:
227                 case FT_UINT_STRING:
228                 case FT_BOOLEAN:
229                 case FT_UINT8:
230                 case FT_UINT16:
231                 case FT_UINT24:
232                 case FT_UINT32:
233                 case FT_UINT64:
234                 case FT_INT8:
235                 case FT_INT16:
236                 case FT_INT24:
237                 case FT_INT32:
238                 case FT_INT64:
239                         return FALSE;
240                         
241                 case FT_NUM_TYPES:
242                         g_assert_not_reached();
243         }
244
245         g_assert_not_reached();
246         return FALSE;
247 }
248
249 static void
250 check_relation_LHS_FIELD(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node,
251                 stnode_t *st_arg1, stnode_t *st_arg2)
252 {
253         stnode_t                *new_st;
254         sttype_id_t             type1, type2;
255         header_field_info       *hfinfo1, *hfinfo2;
256         ftenum_t                ftype1, ftype2;
257         fvalue_t                *fvalue;
258         char                    *s;
259         drange_node             *rn;
260
261         type1 = stnode_type_id(st_arg1);
262         type2 = stnode_type_id(st_arg2);
263
264         hfinfo1 = stnode_data(st_arg1);
265         ftype1 = hfinfo1->type;
266
267         if (!can_func(ftype1)) {
268                 dfilter_fail("%s (type=%s) cannot participate in specified comparison.",
269                                 hfinfo1->abbrev, ftype_pretty_name(ftype1));
270                 THROW(TypeError);
271         }
272
273
274         if (type2 == STTYPE_FIELD) {
275                 hfinfo2 = stnode_data(st_arg2);
276                 ftype2 = hfinfo2->type;
277
278                 if (!compatible_ftypes(ftype1, ftype2)) {
279                         dfilter_fail("%s and %s are not of compatible types.",
280                                         hfinfo1->abbrev, hfinfo2->abbrev);
281                         THROW(TypeError);
282                 }
283                 /* Do this check even though you'd think that if
284                  * they're compatible, then can_func() would pass. */
285                 if (!can_func(ftype2)) {
286                         dfilter_fail("%s (type=%s) cannot participate in specified comparison.",
287                                         hfinfo2->abbrev, ftype_pretty_name(ftype2));
288                         THROW(TypeError);
289                 }
290         }
291         else if (type2 == STTYPE_STRING) {
292                 s = stnode_data(st_arg2);
293                 fvalue = fvalue_from_string(ftype1, s, dfilter_fail);
294                 if (!fvalue) {
295                         /* check value_string */
296                         fvalue = mk_fvalue_from_val_string(hfinfo1, s);
297                         if (!fvalue) {
298                                 THROW(TypeError);
299                         }
300                 }
301
302                 new_st = stnode_new(STTYPE_FVALUE, fvalue);
303                 sttype_test_set2_args(st_node, st_arg1, new_st);
304                 stnode_free(st_arg2);
305         }
306         else if (type2 == STTYPE_RANGE) {
307                 if (!is_bytes_type(ftype1)) {
308                         if (!ftype_can_slice(ftype1)) {
309                                 dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.",
310                                                 hfinfo1->abbrev,
311                                                 ftype_pretty_name(ftype1));
312                                 THROW(TypeError);
313                         }
314
315                         /* Convert entire field to bytes */
316                         new_st = stnode_new(STTYPE_RANGE, NULL);
317
318                         rn = drange_node_new();
319                         drange_node_set_start_offset(rn, 0);
320                         drange_node_set_to_the_end(rn);
321                         /* st_arg1 is freed in this step */
322                         sttype_range_set1(new_st, st_arg1, rn);
323
324                         sttype_test_set2_args(st_node, new_st, st_arg2);
325                 }
326         }
327         else {
328                 g_assert_not_reached();
329         }
330 }
331
332 static void
333 check_relation_LHS_STRING(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node,
334                 stnode_t *st_arg1, stnode_t *st_arg2)
335 {
336         stnode_t                *new_st;
337         sttype_id_t             type1, type2;
338         header_field_info       *hfinfo2;
339         ftenum_t                ftype2;
340         fvalue_t                *fvalue;
341         char                    *s;
342
343         type1 = stnode_type_id(st_arg1);
344         type2 = stnode_type_id(st_arg2);
345                 
346         if (type2 == STTYPE_FIELD) {
347                 hfinfo2 = stnode_data(st_arg2);
348                 ftype2 = hfinfo2->type;
349
350                 s = stnode_data(st_arg1);
351                 fvalue = fvalue_from_string(ftype2, s, dfilter_fail);
352                 if (!fvalue) {
353                         /* check value_string */
354                         fvalue = mk_fvalue_from_val_string(hfinfo2, s);
355                         if (!fvalue) {
356                                 THROW(TypeError);
357                         }
358                 }
359
360                 new_st = stnode_new(STTYPE_FVALUE, fvalue);
361                 sttype_test_set2_args(st_node, new_st, st_arg2);
362                 stnode_free(st_arg1);
363         }
364         else if (type2 == STTYPE_STRING) {
365                 /* Well now that's silly... */
366                 dfilter_fail("Neither \"%s\" nor \"%s\" are field or protocol names.",
367                                 stnode_data(st_arg1),
368                                 stnode_data(st_arg2));
369                 THROW(TypeError);
370         }
371         else if (type2 == STTYPE_RANGE) {
372                 s = stnode_data(st_arg1);
373                 fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail);
374                 if (!fvalue) {
375                         THROW(TypeError);
376                 }
377                 new_st = stnode_new(STTYPE_FVALUE, fvalue);
378                 sttype_test_set2_args(st_node, new_st, st_arg2);
379                 stnode_free(st_arg1);
380         }
381         else {
382                 g_assert_not_reached();
383         }
384 }
385
386 static void
387 check_relation_LHS_RANGE(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node,
388                 stnode_t *st_arg1, stnode_t *st_arg2)
389 {
390         stnode_t                *new_st;
391         sttype_id_t             type1, type2;
392         header_field_info       *hfinfo1, *hfinfo2;
393         ftenum_t                ftype1, ftype2;
394         fvalue_t                *fvalue;
395         char                    *s;
396         drange_node             *rn;
397
398         type1 = stnode_type_id(st_arg1);
399         type2 = stnode_type_id(st_arg2);
400         hfinfo1 = sttype_range_hfinfo(st_arg1);
401         ftype1 = hfinfo1->type;
402
403         if (!ftype_can_slice(ftype1)) {
404                 dfilter_fail("\"%s\" is a %s and cannot be sliced into a sequence of bytes.",
405                                 hfinfo1->abbrev, ftype_pretty_name(ftype1));
406                 THROW(TypeError);
407         }
408
409
410         if (type2 == STTYPE_FIELD) {
411                 hfinfo2 = sttype_range_hfinfo(st_arg2);
412                 ftype2 = hfinfo2->type;
413
414                 if (!is_bytes_type(ftype2)) {
415                         if (!ftype_can_slice(ftype2)) {
416                                 dfilter_fail("\"%s\" is a %s and cannot be converted into a sequence of bytes.",
417                                                 hfinfo2->abbrev,
418                                                 ftype_pretty_name(ftype2));
419                                 THROW(TypeError);
420                         }
421
422                         /* Convert entire field to bytes */
423                         new_st = stnode_new(STTYPE_RANGE, NULL);
424
425                         rn = drange_node_new();
426                         drange_node_set_start_offset(rn, 0);
427                         drange_node_set_to_the_end(rn);
428                         /* st_arg2 is freed in this step */
429                         sttype_range_set1(new_st, st_arg2, rn);
430
431                         sttype_test_set2_args(st_node, st_arg1, new_st);
432                 }
433         }
434         else if (type2 == STTYPE_STRING) {
435                 s = stnode_data(st_arg2);
436                 fvalue = fvalue_from_string(FT_BYTES, s, dfilter_fail);
437                 if (!fvalue) {
438                         THROW(TypeError);
439                 }
440                 new_st = stnode_new(STTYPE_FVALUE, fvalue);
441                 sttype_test_set2_args(st_node, st_arg1, new_st);
442                 stnode_free(st_arg2);
443         }
444         else if (type2 == STTYPE_RANGE) {
445                 /* XXX - check lengths of both ranges */
446         }
447         else {
448                 g_assert_not_reached();
449         }
450 }
451
452
453 static void
454 check_relation(dfwork_t *dfw, FtypeCanFunc can_func, stnode_t *st_node,
455                 stnode_t *st_arg1, stnode_t *st_arg2)
456 {
457         switch (stnode_type_id(st_arg1)) {
458                 case STTYPE_FIELD:
459                         check_relation_LHS_FIELD(dfw, can_func, st_node, st_arg1, st_arg2);
460                         break;
461                 case STTYPE_STRING:
462                         check_relation_LHS_STRING(dfw, can_func, st_node, st_arg1, st_arg2);
463                         break;
464                 case STTYPE_RANGE:
465                         check_relation_LHS_RANGE(dfw, can_func, st_node, st_arg1, st_arg2);
466                         break;
467
468                 case STTYPE_UNINITIALIZED:
469                 case STTYPE_TEST:
470                 case STTYPE_INTEGER:
471                 case STTYPE_FVALUE:
472                 case STTYPE_NUM_TYPES:
473                         g_assert_not_reached();
474         }
475 }
476
477 static void
478 check_test(dfwork_t *dfw, stnode_t *st_node)
479 {
480         test_op_t               st_op;
481         stnode_t                *st_arg1, *st_arg2;
482
483         sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
484
485         switch (st_op) {
486                 case TEST_OP_UNINITIALIZED:
487                         g_assert_not_reached();
488                         break;
489
490                 case TEST_OP_EXISTS:
491                         /* nothing */
492                         break;
493
494                 case TEST_OP_NOT:
495                         semcheck(dfw, st_arg1);
496                         break;
497
498                 case TEST_OP_AND:
499                 case TEST_OP_OR:
500                         semcheck(dfw, st_arg1);
501                         semcheck(dfw, st_arg2);
502                         break;
503
504                 case TEST_OP_EQ:
505                         check_relation(dfw, ftype_can_eq, st_node, st_arg1, st_arg2);
506                         break;
507                 case TEST_OP_NE:
508                         check_relation(dfw, ftype_can_ne, st_node, st_arg1, st_arg2);
509                         break;
510                 case TEST_OP_GT:
511                         check_relation(dfw, ftype_can_gt, st_node, st_arg1, st_arg2);
512                         break;
513                 case TEST_OP_GE:
514                         check_relation(dfw, ftype_can_ge, st_node, st_arg1, st_arg2);
515                         break;
516                 case TEST_OP_LT:
517                         check_relation(dfw, ftype_can_lt, st_node, st_arg1, st_arg2);
518                         break;
519                 case TEST_OP_LE:
520                         check_relation(dfw, ftype_can_le, st_node, st_arg1, st_arg2);
521                         break;
522         }
523 }
524
525
526 static void
527 semcheck(dfwork_t *dfw, stnode_t *st_node)
528 {
529         const char      *name;
530
531         name = stnode_type_name(st_node);
532
533         switch (stnode_type_id(st_node)) {
534                 case STTYPE_TEST:
535                         check_test(dfw, st_node);
536                         break;
537                 default:
538                         g_assert_not_reached();
539         }
540 }
541
542
543 gboolean
544 dfw_semcheck(dfwork_t *dfw)
545 {
546         TRY {
547                 semcheck(dfw, dfw->st_root);
548         }
549         CATCH(TypeError) {
550                 return FALSE;
551         }
552         ENDTRY;
553
554         return TRUE;
555 }