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