1 /*
2  * Wireshark - Network traffic analyzer
3  * By Gerald Combs <gerald@wireshark.org>
4  * Copyright 2001 Gerald Combs
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "config.h"
10 
11 #define WS_LOG_DOMAIN LOG_DOMAIN_DFILTER
12 
13 #include <string.h>
14 
15 #include "dfilter-int.h"
16 #include "semcheck.h"
17 #include "syntax-tree.h"
18 #include "sttype-range.h"
drange_node_new(void)19 #include "sttype-test.h"
20 #include "sttype-set.h"
21 #include "sttype-function.h"
22 
23 #include <epan/exceptions.h>
24 #include <epan/packet.h>
25 
26 #include <wsutil/ws_assert.h>
27 #include <wsutil/wslog.h>
28 
29 #include <ftypes/ftypes-int.h>
30 
31 
32 static void
33 semcheck(dfwork_t *dfw, stnode_t *st_node);
34 
35 static stnode_t*
36 check_param_entity(dfwork_t *dfw, stnode_t *st_node);
37 
38 static void
39 check_function(dfwork_t *dfw, stnode_t *st_node);
40 
41 typedef gboolean (*FtypeCanFunc)(enum ftenum);
42 
43 /* Compares to ftenum_t's and decides if they're
44  * compatible or not (if they're the same basic type) */
45 static gboolean
46 compatible_ftypes(ftenum_t a, ftenum_t b)
47 {
48 	switch (a) {
drange_node_free(drange_node * drnode)49 		case FT_NONE:
50 		case FT_PROTOCOL:
51 		case FT_FLOAT:		/* XXX - should be able to compare with INT */
52 		case FT_DOUBLE:		/* XXX - should be able to compare with INT */
53 		case FT_ABSOLUTE_TIME:
54 		case FT_RELATIVE_TIME:
55 		case FT_IEEE_11073_SFLOAT:
56 		case FT_IEEE_11073_FLOAT:
57 		case FT_IPv4:
58 		case FT_IPv6:
59 		case FT_IPXNET:
60 		case FT_INT40:		/* XXX - should be able to compare with INT */
61 		case FT_UINT40:		/* XXX - should be able to compare with INT */
62 		case FT_INT48:		/* XXX - should be able to compare with INT */
63 		case FT_UINT48:		/* XXX - should be able to compare with INT */
64 		case FT_INT56:		/* XXX - should be able to compare with INT */
65 		case FT_UINT56:		/* XXX - should be able to compare with INT */
66 		case FT_INT64:		/* XXX - should be able to compare with INT */
67 		case FT_UINT64:		/* XXX - should be able to compare with INT */
68 		case FT_EUI64:		/* XXX - should be able to compare with INT */
69 			return a == b;
drange_node_get_end_offset(drange_node * drnode)70 
71 		case FT_ETHER:
72 		case FT_BYTES:
73 		case FT_UINT_BYTES:
74 		case FT_GUID:
75 		case FT_OID:
76 		case FT_AX25:
77 		case FT_VINES:
78 		case FT_FCWWN:
79 		case FT_REL_OID:
80 		case FT_SYSTEM_ID:
81 
82 			return (b == FT_ETHER || b == FT_BYTES || b == FT_UINT_BYTES || b == FT_GUID || b == FT_OID || b == FT_AX25 || b == FT_VINES || b == FT_FCWWN || b == FT_REL_OID || b == FT_SYSTEM_ID);
83 
84 		case FT_BOOLEAN:
drange_node_set_start_offset(drange_node * drnode,gint offset)85 		case FT_FRAMENUM:
86 		case FT_CHAR:
87 		case FT_UINT8:
88 		case FT_UINT16:
89 		case FT_UINT24:
90 		case FT_UINT32:
91 		case FT_INT8:
92 		case FT_INT16:
93 		case FT_INT24:
94 		case FT_INT32:
95 			switch (b) {
96 				case FT_BOOLEAN:
97 				case FT_FRAMENUM:
98 				case FT_CHAR:
99 				case FT_UINT8:
100 				case FT_UINT16:
101 				case FT_UINT24:
102 				case FT_UINT32:
103 				case FT_INT8:
104 				case FT_INT16:
105 				case FT_INT24:
106 				case FT_INT32:
107 					return TRUE;
108 				default:
109 					return FALSE;
110 			}
111 
112 		case FT_STRING:
drange_new(void)113 		case FT_STRINGZ:
114 		case FT_UINT_STRING:
115 		case FT_STRINGZPAD:
116 		case FT_STRINGZTRUNC:
117 			switch (b) {
118 				case FT_STRING:
119 				case FT_STRINGZ:
120 				case FT_UINT_STRING:
121 				case FT_STRINGZPAD:
122 				case FT_STRINGZTRUNC:
123 					return TRUE;
124 				default:
125 					return FALSE;
126 			}
127 
128 		case FT_NUM_TYPES:
129 			ws_assert_not_reached();
130 	}
131 
132 	ws_assert_not_reached();
133 	return FALSE;
134 }
drange_new_from_list(GSList * list)135 
136 /* Gets an fvalue from a string, and sets the error message on failure. */
137 static fvalue_t*
138 dfilter_fvalue_from_unparsed(dfwork_t *dfw, ftenum_t ftype, const char *s, gboolean allow_partial_value)
139 {
140 	/*
141 	 * Don't set the error message if it's already set.
142 	 */
143 	return fvalue_from_unparsed(ftype, s, allow_partial_value,
144 	    dfw->error_message == NULL ? &dfw->error_message : NULL);
145 }
146 
147 /* Gets an fvalue from a string, and sets the error message on failure. */
148 static fvalue_t*
149 dfilter_fvalue_from_string(dfwork_t *dfw, ftenum_t ftype, const char *s)
150 {
151 	return fvalue_from_string(ftype, s,
152 	    dfw->error_message == NULL ? &dfw->error_message : NULL);
153 }
154 
155 /* Creates a FT_UINT32 fvalue with a given value. */
156 static fvalue_t*
157 mk_uint32_fvalue(guint32 val)
158 {
159 	fvalue_t *fv;
160 
161 	fv = fvalue_new(FT_UINT32);
162 	fvalue_set_uinteger(fv, val);
163 
drange_free(drange_t * dr)164 	return fv;
165 }
166 
167 /* Creates a FT_UINT64 fvalue with a given value. */
168 static fvalue_t*
169 mk_uint64_fvalue(guint64 val)
170 {
171 	fvalue_t *fv;
drange_node_free_list(GSList * list)172 
173 	fv = fvalue_new(FT_UINT64);
174 	fvalue_set_uinteger64(fv, val);
175 
176 	return fv;
177 }
drange_has_total_length(drange_t * dr)178 
179 /* Try to make an fvalue from a string using a value_string or true_false_string.
180  * This works only for ftypes that are integers. Returns the created fvalue_t*
181  * or NULL if impossible. */
182 static fvalue_t*
183 mk_fvalue_from_val_string(dfwork_t *dfw, header_field_info *hfinfo, char *s)
184 {
185 	static const true_false_string  default_tf = { "True", "False" };
186 	const true_false_string		*tf = &default_tf;
187 
188 	/* Early return? */
189 	switch(hfinfo->type) {
190 		case FT_NONE:
191 		case FT_PROTOCOL:
192 		case FT_FLOAT:
193 		case FT_DOUBLE:
194 		case FT_IEEE_11073_SFLOAT:
195 		case FT_IEEE_11073_FLOAT:
196 		case FT_ABSOLUTE_TIME:
197 		case FT_RELATIVE_TIME:
198 		case FT_IPv4:
199 		case FT_IPv6:
200 		case FT_IPXNET:
201 		case FT_AX25:
202 		case FT_VINES:
203 		case FT_FCWWN:
204 		case FT_ETHER:
205 		case FT_BYTES:
206 		case FT_UINT_BYTES:
207 		case FT_STRING:
208 		case FT_STRINGZ:
209 		case FT_UINT_STRING:
210 		case FT_STRINGZPAD:
211 		case FT_STRINGZTRUNC:
212 		case FT_EUI64:
213 		case FT_GUID:
214 		case FT_OID:
215 		case FT_REL_OID:
216 		case FT_SYSTEM_ID:
217 		case FT_FRAMENUM: /* hfinfo->strings contains ft_framenum_type_t, not strings */
218 			return NULL;
219 
220 		case FT_BOOLEAN:
221 		case FT_CHAR:
222 		case FT_UINT8:
223 		case FT_UINT16:
224 		case FT_UINT24:
225 		case FT_UINT32:
226 		case FT_UINT40:
227 		case FT_UINT48:
228 		case FT_UINT56:
229 		case FT_UINT64:
230 		case FT_INT8:
231 		case FT_INT16:
232 		case FT_INT24:
233 		case FT_INT32:
234 		case FT_INT40:
235 		case FT_INT48:
236 		case FT_INT56:
237 		case FT_INT64:
238 			break;
239 
240 		case FT_NUM_TYPES:
241 			ws_assert_not_reached();
242 	}
243 
244 	/* TRUE/FALSE *always* exist for FT_BOOLEAN. */
245 	if (hfinfo->type == FT_BOOLEAN) {
246 		if (hfinfo->strings) {
247 			tf = (const true_false_string *)hfinfo->strings;
248 		}
249 
250 		if (g_ascii_strcasecmp(s, tf->true_string) == 0) {
251 			return mk_uint64_fvalue(TRUE);
252 		}
253 		else if (g_ascii_strcasecmp(s, tf->false_string) == 0) {
254 			return mk_uint64_fvalue(FALSE);
255 		}
256 		else {
257 			/*
258 			 * Prefer this error message to whatever error message
259 			 * has already been set.
260 			 */
261 			g_free(dfw->error_message);
262 			dfw->error_message = NULL;
263 			dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.",
264 				s, hfinfo->abbrev);
265 			return NULL;
266 		}
267 	}
268 
269 	/* Do val_strings exist? */
270 	if (!hfinfo->strings) {
271 		dfilter_fail(dfw, "%s cannot accept strings as values.",
272 				hfinfo->abbrev);
273 		return NULL;
274 	}
275 
276 	/* Reset the error message, since *something* interesting will happen,
277 	 * and the error message will be more interesting than any error message
278 	 * I happen to have now. */
279 	g_free(dfw->error_message);
280 	dfw->error_message = NULL;
281 
282 	if (hfinfo->display & BASE_RANGE_STRING) {
283 		dfilter_fail(dfw, "\"%s\" cannot accept [range] strings as values.",
284 				hfinfo->abbrev);
285 	}
286 	else if (hfinfo->display & BASE_VAL64_STRING) {
287 		const val64_string *vals = (const val64_string *)hfinfo->strings;
288 
289 		while (vals->strptr != NULL) {
290 			if (g_ascii_strcasecmp(s, vals->strptr) == 0) {
291 				return mk_uint64_fvalue(vals->value);
292 			}
293 			vals++;
294 		}
295 		dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.",
296 				s, hfinfo->abbrev);
297 	}
298 	else if (hfinfo->display == BASE_CUSTOM) {
299 		/*  If a user wants to match against a custom string, we would
300 		 *  somehow have to have the integer value here to pass it in
301 		 *  to the custom-display function.  But we don't have an
302 		 *  integer, we have the string they're trying to match.
303 		 *  -><-
304 		 */
305 		dfilter_fail(dfw, "\"%s\" cannot accept [custom] strings as values.",
306 				hfinfo->abbrev);
307 	}
308 	else {
309 		const value_string *vals = (const value_string *)hfinfo->strings;
310 		if (hfinfo->display & BASE_EXT_STRING)
311 			vals = VALUE_STRING_EXT_VS_P((const value_string_ext *) vals);
312 
313 		while (vals->strptr != NULL) {
314 			if (g_ascii_strcasecmp(s, vals->strptr) == 0) {
315 				return mk_uint32_fvalue(vals->value);
316 			}
317 			vals++;
318 		}
319 		dfilter_fail(dfw, "\"%s\" cannot be found among the possible values for %s.",
320 				s, hfinfo->abbrev);
321 	}
322 	return NULL;
323 }
324 
325 static gboolean
326 is_bytes_type(enum ftenum type)
327 {
328 	switch(type) {
329 		case FT_AX25:
330 		case FT_VINES:
331 		case FT_FCWWN:
332 		case FT_ETHER:
333 		case FT_BYTES:
334 		case FT_UINT_BYTES:
335 		case FT_IPv6:
336 		case FT_GUID:
337 		case FT_OID:
338 		case FT_REL_OID:
339 		case FT_SYSTEM_ID:
340 			return TRUE;
341 
342 		case FT_NONE:
343 		case FT_PROTOCOL:
344 		case FT_FLOAT:
345 		case FT_DOUBLE:
346 		case FT_IEEE_11073_SFLOAT:
347 		case FT_IEEE_11073_FLOAT:
348 		case FT_ABSOLUTE_TIME:
349 		case FT_RELATIVE_TIME:
350 		case FT_IPv4:
351 		case FT_IPXNET:
352 		case FT_STRING:
353 		case FT_STRINGZ:
354 		case FT_UINT_STRING:
355 		case FT_STRINGZPAD:
356 		case FT_STRINGZTRUNC:
357 		case FT_BOOLEAN:
358 		case FT_FRAMENUM:
359 		case FT_CHAR:
360 		case FT_UINT8:
361 		case FT_UINT16:
362 		case FT_UINT24:
363 		case FT_UINT32:
364 		case FT_UINT40:
365 		case FT_UINT48:
366 		case FT_UINT56:
367 		case FT_UINT64:
368 		case FT_INT8:
369 		case FT_INT16:
370 		case FT_INT24:
371 		case FT_INT32:
372 		case FT_INT40:
373 		case FT_INT48:
374 		case FT_INT56:
375 		case FT_INT64:
376 		case FT_EUI64:
377 			return FALSE;
378 
379 		case FT_NUM_TYPES:
380 			ws_assert_not_reached();
381 	}
382 
383 	ws_assert_not_reached();
384 	return FALSE;
385 }
386 
387 /* Gets a GRegex from a string, and sets the error message on failure. */
388 static GRegex*
389 dfilter_g_regex_from_string(dfwork_t *dfw, const char *s)
390 {
391 	GError *regex_error = NULL;
392 	GRegexCompileFlags cflags = (GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_OPTIMIZE);
393 	GRegex *pcre;
394 
395 	/*
396 	 * As FT_BYTES and FT_PROTOCOL contain arbitrary binary data
397 	 * and FT_STRING is not guaranteed to contain valid UTF-8,
398 	 * we have to disable support for UTF-8 patterns and treat
399 	 * every pattern and subject as raw bytes.
400 	 *
401 	 * Should support for UTF-8 patterns be necessary, then we
402 	 * should compile a pattern without G_REGEX_RAW. Additionally,
403 	 * we MUST use g_utf8_validate() before calling g_regex_match_full()
404 	 * or risk crashes.
405 	 */
406 	cflags = (GRegexCompileFlags)(cflags | G_REGEX_RAW);
407 
408 	ws_debug("Compile regex pattern: %s", s);
409 
410 	pcre = g_regex_new(
411 			s,			/* pattern */
412 			cflags,			/* Compile options */
413 			(GRegexMatchFlags)0,	/* Match options */
414 			&regex_error		/* Compile / study errors */
415 			);
416 
417 	if (regex_error) {
418 		if (dfw->error_message == NULL)
419 			dfw->error_message = g_strdup(regex_error->message);
420 		g_error_free(regex_error);
421 		if (pcre) {
422 			g_regex_unref(pcre);
423 		}
424 		return NULL;
425 	}
426 	return pcre;
427 }
428 
429 /* Check the semantics of an existence test. */
430 static void
431 check_exists(dfwork_t *dfw, stnode_t *st_arg1)
432 {
433 	static guint i = 0;
434 
435 	ws_debug("4 check_exists() [%u]", i++);
436 	log_stnode(st_arg1);
437 
438 	switch (stnode_type_id(st_arg1)) {
439 		case STTYPE_FIELD:
440 			/* This is OK */
441 			break;
442 		case STTYPE_STRING:
443 		case STTYPE_CHARCONST:
444 		case STTYPE_UNPARSED:
445 			dfilter_fail(dfw, "\"%s\" is neither a field nor a protocol name.",
446 					(char *)stnode_data(st_arg1));
447 			THROW(TypeError);
448 			break;
449 
450 		case STTYPE_RANGE:
451 			/*
452 			 * XXX - why not?  Shouldn't "eth[3:2]" mean
453 			 * "check whether the 'eth' field is present and
454 			 * has at least 2 bytes starting at an offset of
455 			 * 3"?
456 			 */
457 			dfilter_fail(dfw, "You cannot test whether a range is present.");
458 			THROW(TypeError);
459 			break;
460 
461 		case STTYPE_FUNCTION:
462 			/* XXX - Maybe we should change functions so they can return fields,
463 			 * in which case the 'exist' should be fine. */
464 			dfilter_fail(dfw, "You cannot test whether a function is present.");
465 			THROW(TypeError);
466 			break;
467 
468 		case STTYPE_UNINITIALIZED:
469 		case STTYPE_TEST:
470 		case STTYPE_INTEGER:
471 		case STTYPE_FVALUE:
472 		case STTYPE_SET:
473 		case STTYPE_PCRE:
474 		case STTYPE_NUM_TYPES:
475 			ws_assert_not_reached();
476 	}
477 }
478 
479 struct check_drange_sanity_args {
480 	dfwork_t		*dfw;
481 	stnode_t		*st;
482 	gboolean		err;
483 };
484 
485 static void
486 check_drange_node_sanity(gpointer data, gpointer user_data)
487 {
488 	drange_node*		drnode = (drange_node*)data;
489 	struct check_drange_sanity_args *args = (struct check_drange_sanity_args*)user_data;
490 	gint			start_offset, end_offset, length;
491 	stnode_t                *entity;
492 	header_field_info	*hfinfo;
493 
494 	switch (drange_node_get_ending(drnode)) {
495 
496 	case DRANGE_NODE_END_T_LENGTH:
497 		length = drange_node_get_length(drnode);
498 		if (length <= 0) {
499 			if (!args->err) {
500 				args->err = TRUE;
501 				start_offset = drange_node_get_start_offset(drnode);
502 				entity = sttype_range_entity(args->st);
503 				if (entity && stnode_type_id(entity) == STTYPE_FIELD) {
504 					hfinfo = (header_field_info *)stnode_data(entity);
505 
506 					dfilter_fail(args->dfw, "Range %d:%d specified for \"%s\" isn't valid, "
507 						"as length %d isn't positive",
508 						start_offset, length,
509 						hfinfo->abbrev,
510 						length);
511 				} else
512 					dfilter_fail(args->dfw, "Range %d:%d isn't valid, "
513 						"as length %d isn't positive",
514 						start_offset, length,
515 						length);
516 			}
517 		}
518 		break;
519 
520 	case DRANGE_NODE_END_T_OFFSET:
521 		/*
522 		 * Make sure the start offset isn't beyond the end
523 		 * offset.  This applies to negative offsets too.
524 		 */
525 
526 		/* XXX - [-ve - +ve] is probably pathological, but isn't
527 		 * disallowed.
528 		 * [+ve - -ve] is probably pathological too, and happens to be
529 		 * disallowed.
530 		 */
531 		start_offset = drange_node_get_start_offset(drnode);
532 		end_offset = drange_node_get_end_offset(drnode);
533 		if (start_offset > end_offset) {
534 			if (!args->err) {
535 				args->err = TRUE;
536 				entity = sttype_range_entity(args->st);
537 				if (entity && stnode_type_id(entity) == STTYPE_FIELD) {
538 					hfinfo = (header_field_info *)stnode_data(entity);
539 
540 					dfilter_fail(args->dfw, "Range %d-%d specified for \"%s\" isn't valid, "
541 						"as %d is greater than %d",
542 						start_offset, end_offset,
543 						hfinfo->abbrev,
544 						start_offset, end_offset);
545 
546 				} else
547 					dfilter_fail(args->dfw, "Range %d-%d isn't valid, "
548 						"as %d is greater than %d",
549 						start_offset, end_offset,
550 						start_offset, end_offset);
551 			}
552 		}
553 		break;
554 
555 	case DRANGE_NODE_END_T_TO_THE_END:
556 		break;
557 
558 	case DRANGE_NODE_END_T_UNINITIALIZED:
559 	default:
560 		ws_assert_not_reached();
561 	}
562 }
563 
564 static void
565 check_drange_sanity(dfwork_t *dfw, stnode_t *st)
566 {
567 	stnode_t		*entity1;
568 	header_field_info	*hfinfo1;
569 	ftenum_t		ftype1;
570 	struct check_drange_sanity_args	args;
571 	char *s;
572 
573 	entity1 = sttype_range_entity(st);
574 	if (entity1 && stnode_type_id(entity1) == STTYPE_FIELD) {
575 		hfinfo1 = (header_field_info *)stnode_data(entity1);
576 		ftype1 = hfinfo1->type;
577 
578 		if (!ftype_can_slice(ftype1)) {
579 			dfilter_fail(dfw, "\"%s\" is a %s and cannot be sliced into a sequence of bytes.",
580 					hfinfo1->abbrev, ftype_pretty_name(ftype1));
581 			THROW(TypeError);
582 		}
583 	} else if (entity1 && stnode_type_id(entity1) == STTYPE_FUNCTION) {
584 		df_func_def_t *funcdef = sttype_function_funcdef(entity1);
585 		ftype1 = funcdef->retval_ftype;
586 
587 		if (!ftype_can_slice(ftype1)) {
588 			dfilter_fail(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
589 					funcdef->name, ftype_pretty_name(ftype1));
590 			THROW(TypeError);
591 		}
592 
593 		check_function(dfw, entity1);
594 	} else if (entity1 && stnode_type_id(entity1) == STTYPE_RANGE) {
595 		/* Should this be rejected instead? */
596 		check_drange_sanity(dfw, entity1);
597 	} else if (entity1) {
598 		s = stnode_tostr(entity1);
599 		dfilter_fail(dfw, "Range is not supported for entity %s of type %s",
600 					s, stnode_type_name(entity1));
601 		g_free(s);
602 		THROW(TypeError);
603 	} else {
604 		dfilter_fail(dfw, "Range is not supported, details: " G_STRLOC " entity: NULL");
605 		THROW(TypeError);
606 	}
607 
608 	args.dfw = dfw;
609 	args.st = st;
610 	args.err = FALSE;
611 
612 	drange_foreach_drange_node(sttype_range_drange(st),
613 	    check_drange_node_sanity, &args);
614 
615 	if (args.err) {
616 		THROW(TypeError);
617 	}
618 }
619 
620 static stnode_t *
621 convert_to_bytes(stnode_t *arg)
622 {
623 	stnode_t      *new_st;
624 	drange_node   *rn;
625 
626 	new_st = stnode_new(STTYPE_RANGE, NULL, arg->token_value);
627 
628 	rn = drange_node_new();
629 	drange_node_set_start_offset(rn, 0);
630 	drange_node_set_to_the_end(rn);
631 	/* new_st is owner of arg in this step */
632 	sttype_range_set1(new_st, arg, rn);
633 
634 	return new_st;
635 }
636 
637 static void
638 check_function(dfwork_t *dfw, stnode_t *st_node)
639 {
640 	df_func_def_t *funcdef;
641 	GSList        *params;
642 	guint          iparam;
643 	guint          nparams;
644 
645 	funcdef  = sttype_function_funcdef(st_node);
646 	params   = sttype_function_params(st_node);
647 	nparams  = g_slist_length(params);
648 
649 	if (nparams < funcdef->min_nargs) {
650 		dfilter_fail(dfw, "Function %s needs at least %u arguments.",
651 			funcdef->name, funcdef->min_nargs);
652 		THROW(TypeError);
653 	} else if (nparams > funcdef->max_nargs) {
654 		dfilter_fail(dfw, "Function %s can only accept %u arguments.",
655 			funcdef->name, funcdef->max_nargs);
656 		THROW(TypeError);
657 	}
658 
659 	iparam = 0;
660 	while (params) {
661 		params->data = check_param_entity(dfw, (stnode_t *)params->data);
662 		funcdef->semcheck_param_function(dfw, iparam, (stnode_t *)params->data);
663 		params = params->next;
664 		iparam++;
665 	}
666 }
667 
668 /* Convert a character constant to a 1-byte BYTE_STRING containing the
669  * character. */
670 static fvalue_t *
671 dfilter_fvalue_from_charconst_string(dfwork_t *dfw, ftenum_t ftype, char *s, gboolean allow_partial_value)
672 {
673 	fvalue_t *fvalue;
674 
675 	fvalue = dfilter_fvalue_from_unparsed(dfw, FT_CHAR, s, allow_partial_value);
676 	if (fvalue) {
677 		char *temp_string;
678 		/* It's valid. Create a 1-byte BYTE_STRING from its value. */
679 		temp_string = g_strdup_printf("%02x", fvalue->value.uinteger);
680 		FVALUE_FREE(fvalue);
681 		fvalue = dfilter_fvalue_from_unparsed(dfw, ftype, temp_string, allow_partial_value);
682 		g_free(temp_string);
683 	}
684 	return (fvalue);
685 }
686 
687 /* If the LHS of a relation test is a FIELD, run some checks
688  * and possibly some modifications of syntax tree nodes. */
689 static void
690 check_relation_LHS_FIELD(dfwork_t *dfw, const char *relation_string,
691 		FtypeCanFunc can_func, gboolean allow_partial_value,
692 		stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
693 {
694 	stnode_t		*new_st;
695 	sttype_id_t		type2;
696 	header_field_info	*hfinfo1, *hfinfo2;
697 	df_func_def_t		*funcdef;
698 	ftenum_t		ftype1, ftype2;
699 	fvalue_t		*fvalue;
700 	GRegex			*pcre;
701 	char			*s;
702 
703 	type2 = stnode_type_id(st_arg2);
704 
705 	hfinfo1 = (header_field_info*)stnode_data(st_arg1);
706 	ftype1 = hfinfo1->type;
707 
708 	if (stnode_type_id(st_node) == STTYPE_TEST) {
709 		ws_debug("5 check_relation_LHS_FIELD(%s)", relation_string);
710 	} else {
711 		ws_debug("6 check_relation_LHS_FIELD(%s)", relation_string);
712 	}
713 
714 	if (!can_func(ftype1)) {
715 		dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
716 				hfinfo1->abbrev, ftype_pretty_name(ftype1),
717 				relation_string);
718 		THROW(TypeError);
719 	}
720 
721 	if (type2 == STTYPE_FIELD) {
722 		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
723 		ftype2 = hfinfo2->type;
724 
725 		if (!compatible_ftypes(ftype1, ftype2)) {
726 			dfilter_fail(dfw, "%s and %s are not of compatible types.",
727 					hfinfo1->abbrev, hfinfo2->abbrev);
728 			THROW(TypeError);
729 		}
730 		/* Do this check even though you'd think that if
731 		 * they're compatible, then can_func() would pass. */
732 		if (!can_func(ftype2)) {
733 			dfilter_fail(dfw, "%s (type=%s) cannot participate in specified comparison.",
734 					hfinfo2->abbrev, ftype_pretty_name(ftype2));
735 			THROW(TypeError);
736 		}
737 	}
738 	else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
739 	         type2 == STTYPE_CHARCONST) {
740 		s = (char *)stnode_data(st_arg2);
741 		if (strcmp(relation_string, "matches") == 0) {
742 			/* Convert to a GRegex */
743 			pcre = dfilter_g_regex_from_string(dfw, s);
744 			if (!pcre) {
745 				THROW(TypeError);
746 			}
747 			stnode_replace(st_arg2, STTYPE_PCRE, pcre);
748 		} else {
749 			/* Skip incompatible fields */
750 			while (hfinfo1->same_name_prev_id != -1 &&
751 					((type2 == STTYPE_STRING && ftype1 != FT_STRING && ftype1!= FT_STRINGZ) ||
752 					(type2 != STTYPE_STRING && (ftype1 == FT_STRING || ftype1== FT_STRINGZ)))) {
753 				hfinfo1 = proto_registrar_get_nth(hfinfo1->same_name_prev_id);
754 				ftype1 = hfinfo1->type;
755 			}
756 
757 			if (type2 == STTYPE_STRING)
758 				fvalue = dfilter_fvalue_from_string(dfw, ftype1, s);
759 			else if (type2 == STTYPE_CHARCONST &&
760 			    strcmp(relation_string, "contains") == 0) {
761 				/* The RHS should be the same type as the LHS,
762 				 * but a character is just a one-byte byte
763 				 * string. */
764 				fvalue = dfilter_fvalue_from_charconst_string(dfw, ftype1, s, allow_partial_value);
765 			} else
766 				fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value);
767 
768 			/*
769 			 * If this is a character constant, just report the
770 			 * error, don't try to treat it as a string from
771 			 * a value_string table.
772 			 */
773 			if (!fvalue && type2 != STTYPE_CHARCONST) {
774 				/* check value_string */
775 				fvalue = mk_fvalue_from_val_string(dfw, hfinfo1, s);
776 
777 				/*
778 				 * Ignore previous errors if this can be mapped
779 				 * to an item from value_string.
780 				 */
781 				if (fvalue && dfw->error_message) {
782 					g_free(dfw->error_message);
783 					dfw->error_message = NULL;
784 				}
785 			}
786 			if (!fvalue) {
787 				THROW(TypeError);
788 			}
789 			stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
790 		}
791 	}
792 	else if (type2 == STTYPE_RANGE) {
793 		check_drange_sanity(dfw, st_arg2);
794 		if (!is_bytes_type(ftype1)) {
795 			if (!ftype_can_slice(ftype1)) {
796 				dfilter_fail(dfw, "\"%s\" is a %s and cannot be converted into a sequence of bytes.",
797 						hfinfo1->abbrev,
798 						ftype_pretty_name(ftype1));
799 				THROW(TypeError);
800 			}
801 
802 			/* Convert entire field to bytes */
803 			new_st = convert_to_bytes(st_arg1);
804 
805 			sttype_test_set2_args(st_node, new_st, st_arg2);
806 		}
807 	}
808 	else if (type2 == STTYPE_FUNCTION) {
809 		funcdef = sttype_function_funcdef(st_arg2);
810 		ftype2 = funcdef->retval_ftype;
811 
812 		if (!compatible_ftypes(ftype1, ftype2)) {
813 			dfilter_fail(dfw, "%s (type=%s) and return value of %s() (type=%s) are not of compatible types.",
814 					hfinfo1->abbrev, ftype_pretty_name(ftype1),
815 					funcdef->name, ftype_pretty_name(ftype2));
816 			THROW(TypeError);
817 		}
818 
819 		if (!can_func(ftype2)) {
820 			dfilter_fail(dfw, "return value of %s() (type=%s) cannot participate in specified comparison.",
821 					funcdef->name, ftype_pretty_name(ftype2));
822 			THROW(TypeError);
823 		}
824 
825 		check_function(dfw, st_arg2);
826 	}
827 	else if (type2 == STTYPE_SET) {
828 		GSList *nodelist;
829 		/* A set should only ever appear on RHS of 'in' operation */
830 		if (strcmp(relation_string, "in") != 0) {
831 			ws_assert_not_reached();
832 		}
833 		/* Attempt to interpret one element of the set at a time. Each
834 		 * element is represented by two items in the list, the element
835 		 * value and NULL. Both will be replaced by a lower and upper
836 		 * value if the element is a range. */
837 		nodelist = (GSList*)stnode_data(st_arg2);
838 		while (nodelist) {
839 			stnode_t *node = (stnode_t*)nodelist->data;
840 			/* Don't let a range on the RHS affect the LHS field. */
841 			if (stnode_type_id(node) == STTYPE_RANGE) {
842 				dfilter_fail(dfw, "A range may not appear inside a set.");
843 				THROW(TypeError);
844 				break;
845 			}
846 
847 			nodelist = g_slist_next(nodelist);
848 			ws_assert(nodelist);
849 			stnode_t *node_right = (stnode_t *)nodelist->data;
850 			if (node_right) {
851 				/* range type, check if comparison is possible. */
852 				if (!ftype_can_ge(ftype1)) {
853 					dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
854 							hfinfo1->abbrev, ftype_pretty_name(ftype1),
855 							">=");
856 					THROW(TypeError);
857 				}
858 				check_relation_LHS_FIELD(dfw, ">=", ftype_can_ge,
859 						allow_partial_value, st_arg2, st_arg1, node);
860 				check_relation_LHS_FIELD(dfw, "<=", ftype_can_le,
861 						allow_partial_value, st_arg2, st_arg1, node_right);
862 			} else {
863 				check_relation_LHS_FIELD(dfw, "==", can_func,
864 						allow_partial_value, st_arg2, st_arg1, node);
865 			}
866 			nodelist = g_slist_next(nodelist);
867 		}
868 	}
869 	else {
870 		ws_assert_not_reached();
871 	}
872 }
873 
874 static void
875 check_relation_LHS_STRING(dfwork_t *dfw, const char* relation_string,
876 		FtypeCanFunc can_func, gboolean allow_partial_value _U_,
877 		stnode_t *st_node _U_,
878 		stnode_t *st_arg1, stnode_t *st_arg2)
879 {
880 	sttype_id_t		type2;
881 	header_field_info	*hfinfo2;
882 	df_func_def_t		*funcdef;
883 	ftenum_t		ftype2;
884 	fvalue_t		*fvalue;
885 	char			*s;
886 
887 	type2 = stnode_type_id(st_arg2);
888 
889 	ws_debug("5 check_relation_LHS_STRING()");
890 
891 	if (type2 == STTYPE_FIELD) {
892 		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
893 		ftype2 = hfinfo2->type;
894 
895 		if (!can_func(ftype2)) {
896 			dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
897 					hfinfo2->abbrev, ftype_pretty_name(ftype2),
898 					relation_string);
899 			THROW(TypeError);
900 		}
901 
902 		s = (char*)stnode_data(st_arg1);
903 		fvalue = dfilter_fvalue_from_string(dfw, ftype2, s);
904 		if (!fvalue) {
905 			/* check value_string */
906 			fvalue = mk_fvalue_from_val_string(dfw, hfinfo2, s);
907 			if (!fvalue) {
908 				THROW(TypeError);
909 			}
910 		}
911 
912 		stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
913 	}
914 	else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
915 	         type2 == STTYPE_CHARCONST) {
916 		/* Well now that's silly... */
917 		dfilter_fail(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
918 				(char *)stnode_data(st_arg1),
919 				(char *)stnode_data(st_arg2));
920 		THROW(TypeError);
921 	}
922 	else if (type2 == STTYPE_RANGE) {
923 		check_drange_sanity(dfw, st_arg2);
924 		s = (char*)stnode_data(st_arg1);
925 		fvalue = dfilter_fvalue_from_string(dfw, FT_BYTES, s);
926 		if (!fvalue) {
927 			THROW(TypeError);
928 		}
929 		stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
930 	}
931 	else if (type2 == STTYPE_FUNCTION) {
932 		funcdef = sttype_function_funcdef(st_arg2);
933 		ftype2  = funcdef->retval_ftype;
934 
935 		if (!can_func(ftype2)) {
936 			dfilter_fail(dfw, "Return value of function %s (type=%s) cannot participate in '%s' comparison.",
937 				funcdef->name, ftype_pretty_name(ftype2),
938 				relation_string);
939 			THROW(TypeError);
940 		}
941 
942 		s = (char*)stnode_data(st_arg1);
943 		fvalue = dfilter_fvalue_from_string(dfw, ftype2, s);
944 		if (!fvalue) {
945 			THROW(TypeError);
946 		}
947 
948 		check_function(dfw, st_arg2);
949 
950 		stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
951 	}
952 	else if (type2 == STTYPE_SET) {
953 		dfilter_fail(dfw, "Only a field may be tested for membership in a set.");
954 		THROW(TypeError);
955 	}
956 	else {
957 		ws_assert_not_reached();
958 	}
959 }
960 
961 static void
962 check_relation_LHS_UNPARSED(dfwork_t *dfw, const char* relation_string,
963 		FtypeCanFunc can_func, gboolean allow_partial_value,
964 		stnode_t *st_node _U_,
965 		stnode_t *st_arg1, stnode_t *st_arg2)
966 {
967 	sttype_id_t		type2;
968 	header_field_info	*hfinfo2;
969 	df_func_def_t		*funcdef;
970 	ftenum_t		ftype2;
971 	fvalue_t		*fvalue;
972 	char			*s;
973 
974 	type2 = stnode_type_id(st_arg2);
975 
976 	ws_debug("5 check_relation_LHS_UNPARSED()");
977 
978 	if (type2 == STTYPE_FIELD) {
979 		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
980 		ftype2 = hfinfo2->type;
981 
982 		if (!can_func(ftype2)) {
983 			dfilter_fail(dfw, "%s (type=%s) cannot participate in '%s' comparison.",
984 					hfinfo2->abbrev, ftype_pretty_name(ftype2),
985 					relation_string);
986 			THROW(TypeError);
987 		}
988 
989 		s = (char*)stnode_data(st_arg1);
990 		fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, s, allow_partial_value);
991 		if (!fvalue) {
992 			/* check value_string */
993 			fvalue = mk_fvalue_from_val_string(dfw, hfinfo2, s);
994 			if (!fvalue) {
995 				THROW(TypeError);
996 			}
997 		}
998 
999 		stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
1000 	}
1001 	else if (type2 == STTYPE_STRING || type2 == STTYPE_UNPARSED ||
1002 	         type2 == STTYPE_CHARCONST) {
1003 		/* Well now that's silly... */
1004 		dfilter_fail(dfw, "Neither \"%s\" nor \"%s\" are field or protocol names.",
1005 				(char *)stnode_data(st_arg1),
1006 				(char *)stnode_data(st_arg2));
1007 		THROW(TypeError);
1008 	}
1009 	else if (type2 == STTYPE_RANGE) {
1010 		check_drange_sanity(dfw, st_arg2);
1011 		s = (char*)stnode_data(st_arg1);
1012 		fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, s, allow_partial_value);
1013 		if (!fvalue) {
1014 			THROW(TypeError);
1015 		}
1016 		stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
1017 	}
1018 	else if (type2 == STTYPE_FUNCTION) {
1019 		funcdef = sttype_function_funcdef(st_arg2);
1020 		ftype2  = funcdef->retval_ftype;
1021 
1022 		if (!can_func(ftype2)) {
1023 			dfilter_fail(dfw, "return value of function %s() (type=%s) cannot participate in '%s' comparison.",
1024 					funcdef->name, ftype_pretty_name(ftype2), relation_string);
1025 			THROW(TypeError);
1026 		}
1027 
1028 		s =  (char*)stnode_data(st_arg1);
1029 		fvalue = dfilter_fvalue_from_unparsed(dfw, ftype2, s, allow_partial_value);
1030 
1031 		if (!fvalue) {
1032 			THROW(TypeError);
1033 		}
1034 
1035 		check_function(dfw, st_arg2);
1036 
1037 		stnode_replace(st_arg1, STTYPE_FVALUE, fvalue);
1038 	}
1039 	else if (type2 == STTYPE_SET) {
1040 		dfilter_fail(dfw, "Only a field may be tested for membership in a set.");
1041 		THROW(TypeError);
1042 	}
1043 	else {
1044 		ws_assert_not_reached();
1045 	}
1046 }
1047 
1048 static void
1049 check_relation_LHS_RANGE(dfwork_t *dfw, const char *relation_string,
1050 		FtypeCanFunc can_func _U_,
1051 		gboolean allow_partial_value,
1052 		stnode_t *st_node,
1053 		stnode_t *st_arg1, stnode_t *st_arg2)
1054 {
1055 	stnode_t		*new_st;
1056 	sttype_id_t		type2;
1057 	header_field_info	*hfinfo2;
1058 	ftenum_t		ftype2;
1059 	fvalue_t		*fvalue;
1060 	GRegex			*pcre;
1061 	char			*s;
1062 
1063 	ws_debug("5 check_relation_LHS_RANGE(%s)", relation_string);
1064 
1065 	check_drange_sanity(dfw, st_arg1);
1066 
1067 	type2 = stnode_type_id(st_arg2);
1068 
1069 	if (type2 == STTYPE_FIELD) {
1070 		ws_debug("5 check_relation_LHS_RANGE(type2 = STTYPE_FIELD)");
1071 		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
1072 		ftype2 = hfinfo2->type;
1073 
1074 		if (!is_bytes_type(ftype2)) {
1075 			if (!ftype_can_slice(ftype2)) {
1076 				dfilter_fail(dfw, "\"%s\" is a %s and cannot be converted into a sequence of bytes.",
1077 						hfinfo2->abbrev,
1078 						ftype_pretty_name(ftype2));
1079 				THROW(TypeError);
1080 			}
1081 
1082 			/* Convert entire field to bytes */
1083 			new_st = convert_to_bytes(st_arg2);
1084 
1085 			sttype_test_set2_args(st_node, st_arg1, new_st);
1086 		}
1087 	}
1088 	else if (type2 == STTYPE_STRING) {
1089 		ws_debug("5 check_relation_LHS_RANGE(type2 = STTYPE_STRING)");
1090 		s = (char*)stnode_data(st_arg2);
1091 		if (strcmp(relation_string, "matches") == 0) {
1092 			/* Convert to a GRegex * */
1093 			pcre = dfilter_g_regex_from_string(dfw, s);
1094 			if (!pcre) {
1095 				THROW(TypeError);
1096 			}
1097 			stnode_replace(st_arg2, STTYPE_PCRE, pcre);
1098 		} else {
1099 			fvalue = dfilter_fvalue_from_string(dfw, FT_BYTES, s);
1100 			if (!fvalue) {
1101 				THROW(TypeError);
1102 			}
1103 			stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
1104 		}
1105 	}
1106 	else if (type2 == STTYPE_UNPARSED) {
1107 		ws_debug("5 check_relation_LHS_RANGE(type2 = STTYPE_UNPARSED)");
1108 		s = (char*)stnode_data(st_arg2);
1109 		if (strcmp(relation_string, "matches") == 0) {
1110 			/* Convert to a GRegex */
1111 			pcre = dfilter_g_regex_from_string(dfw, s);
1112 			if (!pcre) {
1113 				THROW(TypeError);
1114 			}
1115 			stnode_replace(st_arg2, STTYPE_PCRE, pcre);
1116 		} else {
1117 			fvalue = dfilter_fvalue_from_unparsed(dfw, FT_BYTES, s, allow_partial_value);
1118 			if (!fvalue) {
1119 				THROW(TypeError);
1120 			}
1121 			stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
1122 		}
1123 	}
1124 	else if (type2 == STTYPE_CHARCONST) {
1125 		ws_debug("5 check_relation_LHS_RANGE(type2 = STTYPE_CHARCONST)");
1126 		s = (char*)stnode_data(st_arg2);
1127 		if (strcmp(relation_string, "matches") == 0) {
1128 			/* Convert to a GRegex */
1129 			pcre = dfilter_g_regex_from_string(dfw, s);
1130 			if (!pcre) {
1131 				THROW(TypeError);
1132 			}
1133 			stnode_replace(st_arg2, STTYPE_PCRE, pcre);
1134 		} else {
1135 			/* The RHS should be FT_BYTES, but a character is just a
1136 			 * one-byte byte string. */
1137 			fvalue = dfilter_fvalue_from_charconst_string(dfw, FT_BYTES, s, allow_partial_value);
1138 			if (!fvalue) {
1139 				THROW(TypeError);
1140 			}
1141 			stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
1142 		}
1143 	}
1144 	else if (type2 == STTYPE_RANGE) {
1145 		ws_debug("5 check_relation_LHS_RANGE(type2 = STTYPE_RANGE)");
1146 		check_drange_sanity(dfw, st_arg2);
1147 	}
1148 	else if (type2 == STTYPE_FUNCTION) {
1149 		df_func_def_t *funcdef = sttype_function_funcdef(st_arg2);
1150 		ftype2  = funcdef->retval_ftype;
1151 
1152 		if (!is_bytes_type(ftype2)) {
1153 			if (!ftype_can_slice(ftype2)) {
1154 				dfilter_fail(dfw, "Return value of function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
1155 					funcdef->name,
1156 					ftype_pretty_name(ftype2));
1157 				THROW(TypeError);
1158 			}
1159 
1160 			/* Convert function result to bytes */
1161 			new_st = convert_to_bytes(st_arg2);
1162 
1163 			sttype_test_set2_args(st_node, st_arg1, new_st);
1164 		}
1165 
1166 		check_function(dfw, st_arg2);
1167 	}
1168 	else if (type2 == STTYPE_SET) {
1169 		dfilter_fail(dfw, "Only a field may be tested for membership in a set.");
1170 		THROW(TypeError);
1171 	}
1172 	else {
1173 		ws_assert_not_reached();
1174 	}
1175 }
1176 
1177 static stnode_t*
1178 check_param_entity(dfwork_t *dfw, stnode_t *st_node)
1179 {
1180 	sttype_id_t		e_type;
1181 	stnode_t		*new_st;
1182 	fvalue_t		*fvalue;
1183 	char *s;
1184 
1185 	e_type = stnode_type_id(st_node);
1186 	/* If there's an unparsed string, change it to an FT_STRING */
1187 	if (e_type == STTYPE_UNPARSED || e_type == STTYPE_CHARCONST) {
1188 		s = (char*)stnode_data(st_node);
1189 		fvalue = dfilter_fvalue_from_unparsed(dfw, FT_STRING, s, FALSE);
1190 		if (!fvalue) {
1191 			THROW(TypeError);
1192 		}
1193 
1194 		new_st = stnode_new(STTYPE_FVALUE, fvalue, st_node->token_value);
1195 		stnode_free(st_node);
1196 		return new_st;
1197 	}
1198 	return st_node;
1199 }
1200 
1201 
1202 /* If the LHS of a relation test is a FUNCTION, run some checks
1203  * and possibly some modifications of syntax tree nodes. */
1204 static void
1205 check_relation_LHS_FUNCTION(dfwork_t *dfw, const char *relation_string,
1206 		FtypeCanFunc can_func,
1207 		gboolean allow_partial_value,
1208 		stnode_t *st_node, stnode_t *st_arg1, stnode_t *st_arg2)
1209 {
1210 	stnode_t		*new_st;
1211 	sttype_id_t		type2;
1212 	header_field_info	*hfinfo2;
1213 	ftenum_t		ftype1, ftype2;
1214 	fvalue_t		*fvalue;
1215 	GRegex			*pcre;
1216 	char			*s;
1217 	df_func_def_t		*funcdef;
1218 	df_func_def_t		*funcdef2;
1219 	/* GSList          *params; */
1220 
1221 	check_function(dfw, st_arg1);
1222 	type2 = stnode_type_id(st_arg2);
1223 
1224 	funcdef = sttype_function_funcdef(st_arg1);
1225 	ftype1 = funcdef->retval_ftype;
1226 
1227 	/* params = */sttype_function_params(st_arg1);  /* XXX: is this done for the side-effect ? */
1228 
1229 	ws_debug("5 check_relation_LHS_FUNCTION(%s)", relation_string);
1230 
1231 	if (!can_func(ftype1)) {
1232 		dfilter_fail(dfw, "Function %s (type=%s) cannot participate in '%s' comparison.",
1233 				funcdef->name, ftype_pretty_name(ftype1),
1234 				relation_string);
1235 		THROW(TypeError);
1236 	}
1237 
1238 	if (type2 == STTYPE_FIELD) {
1239 		hfinfo2 = (header_field_info*)stnode_data(st_arg2);
1240 		ftype2 = hfinfo2->type;
1241 
1242 		if (!compatible_ftypes(ftype1, ftype2)) {
1243 			dfilter_fail(dfw, "Function %s and %s are not of compatible types.",
1244 					funcdef->name, hfinfo2->abbrev);
1245 			THROW(TypeError);
1246 		}
1247 		/* Do this check even though you'd think that if
1248 		 * they're compatible, then can_func() would pass. */
1249 		if (!can_func(ftype2)) {
1250 			dfilter_fail(dfw, "%s (type=%s) cannot participate in specified comparison.",
1251 					hfinfo2->abbrev, ftype_pretty_name(ftype2));
1252 			THROW(TypeError);
1253 		}
1254 	}
1255 	else if (type2 == STTYPE_STRING) {
1256 		s = (char*)stnode_data(st_arg2);
1257 		if (strcmp(relation_string, "matches") == 0) {
1258 			/* Convert to a GRegex */
1259 			pcre = dfilter_g_regex_from_string(dfw, s);
1260 			if (!pcre) {
1261 				THROW(TypeError);
1262 			}
1263 			stnode_replace(st_arg2, STTYPE_PCRE, pcre);
1264 		} else {
1265 			fvalue = dfilter_fvalue_from_string(dfw, ftype1, s);
1266 			if (!fvalue) {
1267 				THROW(TypeError);
1268 			}
1269 			stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
1270 		}
1271 	}
1272 	else if (type2 == STTYPE_UNPARSED || type2 == STTYPE_CHARCONST) {
1273 		s = (char*)stnode_data(st_arg2);
1274 		if (strcmp(relation_string, "matches") == 0) {
1275 			/* Convert to a GRegex */
1276 			pcre = dfilter_g_regex_from_string(dfw, s);
1277 			if (!pcre) {
1278 				THROW(TypeError);
1279 			}
1280 			stnode_replace(st_arg2, STTYPE_PCRE, pcre);
1281 		} else {
1282 			fvalue = dfilter_fvalue_from_unparsed(dfw, ftype1, s, allow_partial_value);
1283 			if (!fvalue) {
1284 				THROW(TypeError);
1285 			}
1286 			stnode_replace(st_arg2, STTYPE_FVALUE, fvalue);
1287 		}
1288 	}
1289 	else if (type2 == STTYPE_RANGE) {
1290 		check_drange_sanity(dfw, st_arg2);
1291 		if (!is_bytes_type(ftype1)) {
1292 			if (!ftype_can_slice(ftype1)) {
1293 				dfilter_fail(dfw, "Function \"%s\" is a %s and cannot be converted into a sequence of bytes.",
1294 						funcdef->name,
1295 						ftype_pretty_name(ftype1));
1296 				THROW(TypeError);
1297 			}
1298 
1299 			/* Convert function result to bytes */
1300 			new_st = convert_to_bytes(st_arg1);
1301 
1302 			sttype_test_set2_args(st_node, new_st, st_arg2);
1303 		}
1304 	}
1305 	else if (type2 == STTYPE_FUNCTION) {
1306 		funcdef2 = sttype_function_funcdef(st_arg2);
1307 		ftype2 = funcdef2->retval_ftype;
1308 
1309 		if (!compatible_ftypes(ftype1, ftype2)) {
1310 			dfilter_fail(dfw, "Return values of function %s (type=%s) and function %s (type=%s) are not of compatible types.",
1311 				     funcdef->name, ftype_pretty_name(ftype1), funcdef2->name, ftype_pretty_name(ftype2));
1312 			THROW(TypeError);
1313 		}
1314 
1315 		/* Do this check even though you'd think that if
1316 		 * they're compatible, then can_func() would pass. */
1317 		if (!can_func(ftype2)) {
1318 			dfilter_fail(dfw, "Return value of %s (type=%s) cannot participate in specified comparison.",
1319 				     funcdef2->name, ftype_pretty_name(ftype2));
1320 			THROW(TypeError);
1321 		}
1322 
1323 		check_function(dfw, st_arg2);
1324 	}
1325 	else if (type2 == STTYPE_SET) {
1326 		dfilter_fail(dfw, "Only a field may be tested for membership in a set.");
1327 		THROW(TypeError);
1328 	}
1329 	else {
1330 		ws_assert_not_reached();
1331 	}
1332 }
1333 
1334 
1335 /* Check the semantics of any relational test. */
1336 static void
1337 check_relation(dfwork_t *dfw, const char *relation_string,
1338 		gboolean allow_partial_value,
1339 		FtypeCanFunc can_func, stnode_t *st_node,
1340 		stnode_t *st_arg1, stnode_t *st_arg2)
1341 {
1342 	static guint i = 0;
1343 	header_field_info   *hfinfo;
1344 	char                *s;
1345 
1346 	ws_debug("4 check_relation(\"%s\") [%u]", relation_string, i++);
1347 	log_stnode(st_arg1);
1348 	log_stnode(st_arg2);
1349 
1350 	/* Protocol can only be on LHS (for "contains" or "matches" operators).
1351 	 * Check to see if protocol is on RHS, and re-interpret it as UNPARSED
1352 	 * instead. The subsequent functions will parse it according to the
1353 	 * existing rules for unparsed unquoted strings.
1354 	 *
1355 	 * This catches the case where the user has written "fc" on the RHS,
1356 	 * probably intending a byte value rather than the fibre channel
1357 	 * protocol, or similar for a number of other possibilities
1358 	 * ("dc", "ff", "fefd"), and also catches the case where the user
1359 	 * has written a generic string on the RHS for a "contains" or
1360 	 * "matches" relation. (XXX: There's still a bit of a confusing mess;
1361 	 * byte arrays take precedent over generic strings when unquoted, so
1362 	 * "field contains data" matches "\x64 \x61 \x74 \x61" but
1363 	 * "field contains dc" matches "\xdc" and not "\x64 \x43", but that's
1364 	 * an underlying issue.)
1365 	 *
1366 	 * XXX: Is there a better way to do this in the lex scanner or grammar
1367 	 * parser step instead?  Should the determination of whether something
1368 	 * is a field occur later than it does currently?  This is kind of a
1369 	 * hack.
1370 	 */
1371 
1372 	if (stnode_type_id(st_arg2) == STTYPE_FIELD) {
1373 		hfinfo = (header_field_info*)stnode_data(st_arg2);
1374 		if (hfinfo->type == FT_PROTOCOL) {
1375 			/* Discard const qualifier from hfinfo->abbrev
1376 			 * for sttnode_new, even though it duplicates the
1377 			 * string.
1378 			 */
1379 			s = (char *)hfinfo->abbrev;
1380 			/* Send it through as unparsed and all the other
1381 			 * functions will take care of it as if it didn't
1382 			 * match a protocol string.
1383 			 */
1384 			stnode_replace(st_arg2, STTYPE_UNPARSED, s);
1385 		}
1386 	}
1387 
1388 	switch (stnode_type_id(st_arg1)) {
1389 		case STTYPE_FIELD:
1390 			check_relation_LHS_FIELD(dfw, relation_string, can_func,
1391 					allow_partial_value, st_node, st_arg1, st_arg2);
1392 			break;
1393 		case STTYPE_STRING:
1394 			check_relation_LHS_STRING(dfw, relation_string, can_func,
1395 					allow_partial_value, st_node, st_arg1, st_arg2);
1396 			break;
1397 		case STTYPE_RANGE:
1398 			check_relation_LHS_RANGE(dfw, relation_string, can_func,
1399 					allow_partial_value, st_node, st_arg1, st_arg2);
1400 			break;
1401 		case STTYPE_UNPARSED:
1402 		case STTYPE_CHARCONST:
1403 			check_relation_LHS_UNPARSED(dfw, relation_string, can_func,
1404 					allow_partial_value, st_node, st_arg1, st_arg2);
1405 			break;
1406 		case STTYPE_FUNCTION:
1407 			check_relation_LHS_FUNCTION(dfw, relation_string, can_func,
1408 					allow_partial_value, st_node, st_arg1, st_arg2);
1409 			break;
1410 
1411 		case STTYPE_UNINITIALIZED:
1412 		case STTYPE_TEST:
1413 		case STTYPE_INTEGER:
1414 		case STTYPE_FVALUE:
1415 		case STTYPE_SET:
1416 		default:
1417 			ws_assert_not_reached();
1418 	}
1419 }
1420 
1421 /* Check the semantics of any type of TEST */
1422 static void
1423 check_test(dfwork_t *dfw, stnode_t *st_node)
1424 {
1425 	test_op_t		st_op, st_arg_op;
1426 	stnode_t		*st_arg1, *st_arg2;
1427 	static guint i = 0;
1428 
1429 	ws_debug("3 check_test(stnode_t *st_node = %p) [%u]\n", st_node, i++);
1430 	log_stnode(st_node);
1431 
1432 	sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);
1433 
1434 	switch (st_op) {
1435 		case TEST_OP_UNINITIALIZED:
1436 			ws_assert_not_reached();
1437 			break;
1438 
1439 		case TEST_OP_EXISTS:
1440 			check_exists(dfw, st_arg1);
1441 			break;
1442 
1443 		case TEST_OP_NOT:
1444 			semcheck(dfw, st_arg1);
1445 			break;
1446 
1447 		case TEST_OP_AND:
1448 		case TEST_OP_OR:
1449 			if (stnode_type_id(st_arg1) == STTYPE_TEST) {
1450 				sttype_test_get(st_arg1, &st_arg_op, NULL, NULL);
1451 				if (st_arg_op == TEST_OP_AND || st_arg_op == TEST_OP_OR) {
1452 					if (st_op != st_arg_op && !stnode_inside_parens(st_arg1))
1453 						add_deprecated_token(dfw, "suggest parentheses around '&&' within '||'");
1454 				}
1455 			}
1456 
1457 			if (stnode_type_id(st_arg2) == STTYPE_TEST) {
1458 				sttype_test_get(st_arg2, &st_arg_op, NULL, NULL);
1459 				if (st_arg_op == TEST_OP_AND || st_arg_op == TEST_OP_OR) {
1460 					if (st_op != st_arg_op && !stnode_inside_parens(st_arg2))
1461 						add_deprecated_token(dfw, "suggest parentheses around '&&' within '||'");
1462 				}
1463 			}
1464 
1465 			semcheck(dfw, st_arg1);
1466 			semcheck(dfw, st_arg2);
1467 			break;
1468 
1469 		case TEST_OP_ANY_EQ:
1470 			check_relation(dfw, "==", FALSE, ftype_can_eq, st_node, st_arg1, st_arg2);
1471 			break;
1472 		case TEST_OP_ALL_NE:
1473 			check_relation(dfw, "!=", FALSE, ftype_can_ne, st_node, st_arg1, st_arg2);
1474 			break;
1475 		case TEST_OP_ANY_NE:
1476 			check_relation(dfw, "~=", FALSE, ftype_can_ne, st_node, st_arg1, st_arg2);
1477 			break;
1478 		case TEST_OP_GT:
1479 			check_relation(dfw, ">", FALSE, ftype_can_gt, st_node, st_arg1, st_arg2);
1480 			break;
1481 		case TEST_OP_GE:
1482 			check_relation(dfw, ">=", FALSE, ftype_can_ge, st_node, st_arg1, st_arg2);
1483 			break;
1484 		case TEST_OP_LT:
1485 			check_relation(dfw, "<", FALSE, ftype_can_lt, st_node, st_arg1, st_arg2);
1486 			break;
1487 		case TEST_OP_LE:
1488 			check_relation(dfw, "<=", FALSE, ftype_can_le, st_node, st_arg1, st_arg2);
1489 			break;
1490 		case TEST_OP_BITWISE_AND:
1491 			check_relation(dfw, "&", FALSE, ftype_can_bitwise_and, st_node, st_arg1, st_arg2);
1492 			break;
1493 		case TEST_OP_CONTAINS:
1494 			check_relation(dfw, "contains", TRUE, ftype_can_contains, st_node, st_arg1, st_arg2);
1495 			break;
1496 		case TEST_OP_MATCHES:
1497 			check_relation(dfw, "matches", TRUE, ftype_can_matches, st_node, st_arg1, st_arg2);
1498 			break;
1499 		case TEST_OP_IN:
1500 			/* Use the ftype_can_eq as the items in the set are evaluated using the
1501 			 * semantics of equality. */
1502 			check_relation(dfw, "in", FALSE, ftype_can_eq, st_node, st_arg1, st_arg2);
1503 			break;
1504 
1505 		default:
1506 			ws_assert_not_reached();
1507 	}
1508 }
1509 
1510 
1511 /* Check the entire syntax tree. */
1512 static void
1513 semcheck(dfwork_t *dfw, stnode_t *st_node)
1514 {
1515 	static guint i = 0;
1516 
1517 	ws_debug("2 semcheck(stnode_t *st_node = %p) [%u]", st_node, i++);
1518 
1519 	/* The parser assures that the top-most syntax-tree
1520 	 * node will be a TEST node, no matter what. So assert that. */
1521 	switch (stnode_type_id(st_node)) {
1522 		case STTYPE_TEST:
1523 			check_test(dfw, st_node);
1524 			break;
1525 		default:
1526 			ws_assert_not_reached();
1527 	}
1528 }
1529 
1530 
1531 /* Check the syntax tree for semantic errors, and convert
1532  * some of the nodes into the form they need to be in order to
1533  * later generate the DFVM bytecode. */
1534 gboolean
1535 dfw_semcheck(dfwork_t *dfw)
1536 {
1537 	volatile gboolean ok_filter = TRUE;
1538 	static guint i = 0;
1539 
1540 	ws_debug("1 dfw_semcheck(dfwork_t *dfw = %p) [%u]", dfw, i);
1541 
1542 	/* Instead of having to check for errors at every stage of
1543 	 * the semantic-checking, the semantic-checking code will
1544 	 * throw an exception if a problem is found. */
1545 	TRY {
1546 		semcheck(dfw, dfw->st_root);
1547 	}
1548 	CATCH(TypeError) {
1549 		ok_filter = FALSE;
1550 	}
1551 	ENDTRY;
1552 
1553 	ws_debug("1 dfw_semcheck(dfwork_t *dfw = %p) [%u] - Returns %d",
1554 				dfw, i++, ok_filter);
1555 	return ok_filter;
1556 }
1557 
1558 /*
1559  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1560  *
1561  * Local variables:
1562  * c-basic-offset: 8
1563  * tab-width: 8
1564  * indent-tabs-mode: t
1565  * End:
1566  *
1567  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1568  * :indentSize=8:tabSize=8:noTabs=false:
1569  */
1570