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 #include <ftypes-int.h>
12 #include <string.h>
13 #include <epan/addr_resolv.h>
14 #include <epan/strutil.h>
15 #include <epan/oids.h>
16 #include <epan/osi-utils.h>
17 #include <epan/to_str.h>
18 
19 #define CMP_MATCHES cmp_matches
20 
21 static void
bytes_fvalue_new(fvalue_t * fv)22 bytes_fvalue_new(fvalue_t *fv)
23 {
24 	fv->value.bytes = NULL;
25 }
26 
27 static void
bytes_fvalue_free(fvalue_t * fv)28 bytes_fvalue_free(fvalue_t *fv)
29 {
30 	if (fv->value.bytes) {
31 		g_byte_array_free(fv->value.bytes, TRUE);
32 		fv->value.bytes=NULL;
33 	}
34 }
35 
36 
37 static void
bytes_fvalue_set(fvalue_t * fv,GByteArray * value)38 bytes_fvalue_set(fvalue_t *fv, GByteArray *value)
39 {
40 	/* Free up the old value, if we have one */
41 	bytes_fvalue_free(fv);
42 
43 	fv->value.bytes = value;
44 }
45 
46 static int
bytes_repr_len(fvalue_t * fv,ftrepr_t rtype,int field_display _U_)47 bytes_repr_len(fvalue_t *fv, ftrepr_t rtype, int field_display _U_)
48 {
49 	if (fv->value.bytes->len == 0) {
50 		/* An empty array of bytes is represented as "" in a
51 		   display filter and as an empty string otherwise. */
52 		return (rtype == FTREPR_DFILTER) ? 2 : 0;
53 	} else {
54 		/* 3 bytes for each byte of the byte "NN<separator character>" minus 1 byte
55 		 * as there's no trailing "<separator character>". */
56 		return fv->value.bytes->len * 3 - 1;
57 	}
58 }
59 
60 /*
61  * OID_REPR_LEN:
62  *
63  * 5 for the first byte ([0-2].[0-39].)
64  *
65  * REL_OID_REPR_LEN:
66  * for each extra byte if the sub-id is:
67  *   1 byte it can be at most "127." (4 bytes we give it 4)
68  *   2 bytes it can be at most "16383." (6 bytes we give it 8)
69  *   3 bytes it can be at most "2097151." (8 bytes we give it 12)
70  *   4 bytes it can be at most "268435456." (10 bytes we give it 16)
71  *   5 bytes it can be at most "34359738368." (12 bytes we give it 20)
72  *
73  *  a 5 bytes encoded subid can already overflow the guint32 that holds a sub-id,
74  *  making it a completely different issue!
75  */
76 #define REL_OID_REPR_LEN(fv) (4 * ((fv)->value.bytes->len))
77 #define OID_REPR_LEN(fv) (1 + REL_OID_REPR_LEN(fv))
78 
79 static int
oid_repr_len(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_)80 oid_repr_len(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_)
81 {
82 	return OID_REPR_LEN(fv);
83 }
84 
85 static void
oid_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size _U_)86 oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size _U_)
87 {
88 	char* oid_str = oid_encoded2string(NULL, fv->value.bytes->data,fv->value.bytes->len);
89 	/*
90 	 * XXX:
91 	 * I'm assuming that oid_repr_len is going to be called before to set buf's size.
92 	 * or else we might have a BO.
93 	 * I guess that is why this callback is not passed a length.
94 	 *    -- lego
95 	 */
96 	(void) g_strlcpy(buf,oid_str,OID_REPR_LEN(fv));
97 	wmem_free(NULL, oid_str);
98 }
99 
100 static int
rel_oid_repr_len(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_)101 rel_oid_repr_len(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_)
102 {
103 	return REL_OID_REPR_LEN(fv);
104 }
105 
106 static void
rel_oid_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size _U_)107 rel_oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size _U_)
108 {
109 	char* oid_str = rel_oid_encoded2string(NULL, fv->value.bytes->data,fv->value.bytes->len);
110 	/*
111 	 * XXX:
112 	 * I'm assuming that oid_repr_len is going to be called before to set buf's size.
113 	 * or else we might have a BO.
114 	 * I guess that is why this callback is not passed a length.
115 	 *    -- lego
116 	 */
117 	*buf++ = '.';
118 	(void) g_strlcpy(buf,oid_str,REL_OID_REPR_LEN(fv));
119 	wmem_free(NULL, oid_str);
120 }
121 
122 static void
system_id_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size)123 system_id_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
124 {
125 	print_system_id_buf(fv->value.bytes->data,fv->value.bytes->len, buf, size);
126 }
127 
128 static void
bytes_to_repr(fvalue_t * fv,ftrepr_t rtype,int field_display,char * buf,unsigned int size _U_)129 bytes_to_repr(fvalue_t *fv, ftrepr_t rtype, int field_display, char *buf, unsigned int size _U_)
130 {
131 	char separator;
132 
133 	switch(FIELD_DISPLAY(field_display))
134 	{
135 	case SEP_DOT:
136 		separator = '.';
137 		break;
138 	case SEP_DASH:
139 		separator = '-';
140 		break;
141 	case SEP_SPACE:
142 	case SEP_COLON:
143 	case BASE_NONE:
144 	default:
145 		separator = ':';
146 		break;
147 	}
148 
149 	if (fv->value.bytes->len) {
150 		buf = bytes_to_hexstr_punct(buf, fv->value.bytes->data, fv->value.bytes->len, separator);
151 	}
152 	else {
153 		if (rtype == FTREPR_DFILTER) {
154 			/* An empty byte array in a display filter is represented as "" */
155 			*buf++ = '"';
156 			*buf++ = '"';
157 		}
158 	}
159 	*buf = '\0';
160 }
161 
162 static void
common_fvalue_set(fvalue_t * fv,const guint8 * data,guint len)163 common_fvalue_set(fvalue_t *fv, const guint8* data, guint len)
164 {
165 	/* Free up the old value, if we have one */
166 	bytes_fvalue_free(fv);
167 
168 	fv->value.bytes = g_byte_array_new();
169 	g_byte_array_append(fv->value.bytes, data, len);
170 }
171 
172 static void
ax25_fvalue_set(fvalue_t * fv,const guint8 * value)173 ax25_fvalue_set(fvalue_t *fv, const guint8 *value)
174 {
175 	common_fvalue_set(fv, value, FT_AX25_ADDR_LEN);
176 }
177 
178 static void
vines_fvalue_set(fvalue_t * fv,const guint8 * value)179 vines_fvalue_set(fvalue_t *fv, const guint8 *value)
180 {
181 	common_fvalue_set(fv, value, FT_VINES_ADDR_LEN);
182 }
183 
184 static void
ether_fvalue_set(fvalue_t * fv,const guint8 * value)185 ether_fvalue_set(fvalue_t *fv, const guint8 *value)
186 {
187 	common_fvalue_set(fv, value, FT_ETHER_LEN);
188 }
189 
190 static void
fcwwn_fvalue_set(fvalue_t * fv,const guint8 * value)191 fcwwn_fvalue_set(fvalue_t *fv, const guint8 *value)
192 {
193 	common_fvalue_set(fv, value, FT_FCWWN_LEN);
194 }
195 
196 static void
oid_fvalue_set(fvalue_t * fv,GByteArray * value)197 oid_fvalue_set(fvalue_t *fv, GByteArray *value)
198 {
199 	/* Free up the old value, if we have one */
200 	bytes_fvalue_free(fv);
201 
202 	fv->value.bytes = value;
203 }
204 
205 static void
system_id_fvalue_set(fvalue_t * fv,GByteArray * value)206 system_id_fvalue_set(fvalue_t *fv, GByteArray *value)
207 {
208 	/* Free up the old value, if we have one */
209 	bytes_fvalue_free(fv);
210 
211 	fv->value.bytes = value;
212 }
213 
214 static gpointer
value_get(fvalue_t * fv)215 value_get(fvalue_t *fv)
216 {
217 	return fv->value.bytes->data;
218 }
219 
220 static gboolean
bytes_from_string(fvalue_t * fv,const char * s,gchar ** err_msg _U_)221 bytes_from_string(fvalue_t *fv, const char *s, gchar **err_msg _U_)
222 {
223 	GByteArray	*bytes;
224 
225 	bytes = g_byte_array_new();
226 
227 	g_byte_array_append(bytes, (const guint8 *)s, (guint)strlen(s));
228 
229 	/* Free up the old value, if we have one */
230 	bytes_fvalue_free(fv);
231 	fv->value.bytes = bytes;
232 
233 	return TRUE;
234 }
235 
236 static gboolean
bytes_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)237 bytes_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
238 {
239 	GByteArray	*bytes;
240 	gboolean	res;
241 
242 	/*
243 	 * Special case where the byte string is specified using a one byte
244 	 * hex literal. We can't allow this for byte strings that are longer
245 	 * than one byte, because then we'd have to know which endianness the
246 	 * byte string should be in.
247 	 */
248 	if (strlen(s) == 4 && s[0] == '0' && s[1] == 'x')
249 		s = s + 2;
250 
251 	bytes = g_byte_array_new();
252 
253 	res = hex_str_to_bytes(s, bytes, TRUE);
254 
255 	if (!res) {
256 		if (err_msg != NULL)
257 			*err_msg = g_strdup_printf("\"%s\" is not a valid byte string.", s);
258 		g_byte_array_free(bytes, TRUE);
259 		return FALSE;
260 	}
261 
262 	/* Free up the old value, if we have one */
263 	bytes_fvalue_free(fv);
264 
265 	fv->value.bytes = bytes;
266 
267 	return TRUE;
268 }
269 
270 static gboolean
ax25_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)271 ax25_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
272 {
273 	/*
274 	 * Don't request an error message if bytes_from_unparsed fails;
275 	 * if it does, we'll report an error specific to this address
276 	 * type.
277 	 */
278 	if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
279 		if (fv->value.bytes->len > FT_AX25_ADDR_LEN) {
280 			if (err_msg != NULL) {
281 				*err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid AX.25 address.",
282 				    s);
283 			}
284 			return FALSE;
285 		}
286 		else if (fv->value.bytes->len < FT_AX25_ADDR_LEN && !allow_partial_value) {
287 			if (err_msg != NULL) {
288 				*err_msg = g_strdup_printf("\"%s\" contains too few bytes to be a valid AX.25 address.",
289 				    s);
290 			}
291 			return FALSE;
292 		}
293 
294 		return TRUE;
295 	}
296 
297 	/*
298 	 * XXX - what needs to be done here is something such as:
299 	 *
300 	 * Look for a "-" in the string.
301 	 *
302 	 * If we find it, make sure that there are 1-6 alphanumeric
303 	 * ASCII characters before it, and that there are 2 decimal
304 	 * digits after it, from 00 to 15; if we don't find it, make
305 	 * sure that there are 1-6 alphanumeric ASCII characters
306 	 * in the string.
307 	 *
308 	 * If so, make the first 6 octets of the address the ASCII
309 	 * characters, with lower-case letters mapped to upper-case
310 	 * letters, shifted left by 1 bit, padded to 6 octets with
311 	 * spaces, also shifted left by 1 bit, and, if we found a
312 	 * "-", convert what's after it to a number and make the 7th
313 	 * octet the number, shifted left by 1 bit, otherwise make the
314 	 * 7th octet zero.
315 	 *
316 	 * We should also change all the comparison functions for
317 	 * AX.25 addresses check the upper 7 bits of all but the last
318 	 * octet of the address, ignoring the "end of address" bit,
319 	 * and compare only the 4 bits above the low-order bit for
320 	 * the last octet, ignoring the "end of address" bit and
321 	 * various reserved bits and bits used for other purposes.
322 	 *
323 	 * See section 3.12 "Address-Field Encoding" of the AX.25
324 	 * spec and
325 	 *
326 	 *	http://www.itu.int/ITU-R/terrestrial/docs/fixedmobile/fxm-art19-sec3.pdf
327 	 */
328 	if (err_msg != NULL)
329 		*err_msg = g_strdup_printf("\"%s\" is not a valid AX.25 address.", s);
330 	return FALSE;
331 }
332 
333 static gboolean
vines_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)334 vines_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
335 {
336 	/*
337 	 * Don't request an error message if bytes_from_unparsed fails;
338 	 * if it does, we'll report an error specific to this address
339 	 * type.
340 	 */
341 	if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
342 		if (fv->value.bytes->len > FT_VINES_ADDR_LEN) {
343 			if (err_msg != NULL) {
344 				*err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid Vines address.",
345 				    s);
346 			}
347 			return FALSE;
348 		}
349 		else if (fv->value.bytes->len < FT_VINES_ADDR_LEN && !allow_partial_value) {
350 			if (err_msg != NULL) {
351 				*err_msg = g_strdup_printf("\"%s\" contains too few bytes to be a valid Vines address.",
352 				    s);
353 			}
354 			return FALSE;
355 		}
356 
357 		return TRUE;
358 	}
359 
360 	/* XXX - need better validation of Vines address */
361 
362 	if (err_msg != NULL)
363 		*err_msg = g_strdup_printf("\"%s\" is not a valid Vines address.", s);
364 	return FALSE;
365 }
366 
367 static gboolean
ether_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)368 ether_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
369 {
370 	/*
371 	 * Don't request an error message if bytes_from_unparsed fails;
372 	 * if it does, we'll report an error specific to this address
373 	 * type.
374 	 */
375 	if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
376 		if (fv->value.bytes->len > FT_ETHER_LEN) {
377 			if (err_msg != NULL) {
378 				*err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid Ethernet address.",
379 				    s);
380 			}
381 			return FALSE;
382 		}
383 		else if (fv->value.bytes->len < FT_ETHER_LEN && !allow_partial_value) {
384 			if (err_msg != NULL) {
385 				*err_msg = g_strdup_printf("\"%s\" contains too few bytes to be a valid Ethernet address.",
386 				    s);
387 			}
388 			return FALSE;
389 		}
390 
391 		return TRUE;
392 	}
393 
394 	/* XXX - Try resolving as an Ethernet host name and parse that? */
395 
396 	if (err_msg != NULL)
397 		*err_msg = g_strdup_printf("\"%s\" is not a valid Ethernet address.", s);
398 	return FALSE;
399 }
400 
401 static gboolean
oid_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)402 oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
403 {
404 	GByteArray	*bytes;
405 	gboolean	res;
406 
407 
408 #if 0
409 	/*
410 	 * Don't log a message if this fails; we'll try looking it
411 	 * up as an OID if it does, and if that fails,
412 	 * we'll log a message.
413 	 */
414 	/* do not try it as '.' is handled as valid separator for hexbytes :( */
415 	if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
416 		return TRUE;
417 	}
418 #endif
419 
420 	bytes = g_byte_array_new();
421 	res = oid_str_to_bytes(s, bytes);
422 	if (!res) {
423 		if (err_msg != NULL)
424 			*err_msg = g_strdup_printf("\"%s\" is not a valid OBJECT IDENTIFIER.", s);
425 		g_byte_array_free(bytes, TRUE);
426 		return FALSE;
427 	}
428 
429 	/* Free up the old value, if we have one */
430 	bytes_fvalue_free(fv);
431 	fv->value.bytes = bytes;
432 
433 	return TRUE;
434 }
435 
436 static gboolean
rel_oid_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)437 rel_oid_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
438 {
439 	GByteArray	*bytes;
440 	gboolean	res;
441 
442 	bytes = g_byte_array_new();
443 	res = rel_oid_str_to_bytes(s, bytes, FALSE);
444 	if (!res) {
445 		if (err_msg != NULL)
446 			*err_msg = g_strdup_printf("\"%s\" is not a valid RELATIVE-OID.", s);
447 		g_byte_array_free(bytes, TRUE);
448 		return FALSE;
449 	}
450 
451 	/* Free up the old value, if we have one */
452 	bytes_fvalue_free(fv);
453 	fv->value.bytes = bytes;
454 
455 	return TRUE;
456 }
457 
458 static gboolean
system_id_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)459 system_id_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
460 {
461 	/*
462 	 * Don't request an error message if bytes_from_unparsed fails;
463 	 * if it does, we'll report an error specific to this address
464 	 * type.
465 	 */
466 	if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
467 		if (fv->value.bytes->len > MAX_SYSTEMID_LEN) {
468 			if (err_msg != NULL) {
469 				*err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid OSI System-ID.",
470 				    s);
471 			}
472 			return FALSE;
473 		}
474 
475 		return TRUE;
476 	}
477 
478 	/* XXX - need better validation of OSI System-ID address */
479 
480 	if (err_msg != NULL)
481 		*err_msg = g_strdup_printf("\"%s\" is not a valid OSI System-ID.", s);
482 	return FALSE;
483 }
484 
485 static gboolean
fcwwn_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)486 fcwwn_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
487 {
488 	/*
489 	 * Don't request an error message if bytes_from_unparsed fails;
490 	 * if it does, we'll report an error specific to this address
491 	 * type.
492 	 */
493 	if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
494 		if (fv->value.bytes->len > FT_FCWWN_LEN) {
495 			if (err_msg != NULL) {
496 				*err_msg = g_strdup_printf("\"%s\" contains too many bytes to be a valid FCWWN.",
497 				    s);
498 			}
499 			return FALSE;
500 		}
501 
502 		return TRUE;
503 	}
504 
505 	/* XXX - need better validation of FCWWN address */
506 
507 	if (err_msg != NULL)
508 		*err_msg = g_strdup_printf("\"%s\" is not a valid FCWWN.", s);
509 	return FALSE;
510 }
511 
512 static guint
len(fvalue_t * fv)513 len(fvalue_t *fv)
514 {
515 	return fv->value.bytes->len;
516 }
517 
518 static void
slice(fvalue_t * fv,GByteArray * bytes,guint offset,guint length)519 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
520 {
521 	guint8* data;
522 
523 	data = fv->value.bytes->data + offset;
524 
525 	g_byte_array_append(bytes, data, length);
526 }
527 
528 
529 static gboolean
cmp_eq(const fvalue_t * fv_a,const fvalue_t * fv_b)530 cmp_eq(const fvalue_t *fv_a, const fvalue_t *fv_b)
531 {
532 	GByteArray	*a = fv_a->value.bytes;
533 	GByteArray	*b = fv_b->value.bytes;
534 
535 	if (a->len != b->len) {
536 		return FALSE;
537 	}
538 
539 	return (memcmp(a->data, b->data, a->len) == 0);
540 }
541 
542 
543 static gboolean
cmp_ne(const fvalue_t * fv_a,const fvalue_t * fv_b)544 cmp_ne(const fvalue_t *fv_a, const fvalue_t *fv_b)
545 {
546 	GByteArray	*a = fv_a->value.bytes;
547 	GByteArray	*b = fv_b->value.bytes;
548 
549 	if (a->len != b->len) {
550 		return TRUE;
551 	}
552 
553 	return (memcmp(a->data, b->data, a->len) != 0);
554 }
555 
556 
557 static gboolean
cmp_gt(const fvalue_t * fv_a,const fvalue_t * fv_b)558 cmp_gt(const fvalue_t *fv_a, const fvalue_t *fv_b)
559 {
560 	GByteArray	*a = fv_a->value.bytes;
561 	GByteArray	*b = fv_b->value.bytes;
562 
563 	if (a->len > b->len) {
564 		return TRUE;
565 	}
566 
567 	if (a->len < b->len) {
568 		return FALSE;
569 	}
570 
571 	return (memcmp(a->data, b->data, a->len) > 0);
572 }
573 
574 static gboolean
cmp_ge(const fvalue_t * fv_a,const fvalue_t * fv_b)575 cmp_ge(const fvalue_t *fv_a, const fvalue_t *fv_b)
576 {
577 	GByteArray	*a = fv_a->value.bytes;
578 	GByteArray	*b = fv_b->value.bytes;
579 
580 	if (a->len > b->len) {
581 		return TRUE;
582 	}
583 
584 	if (a->len < b->len) {
585 		return FALSE;
586 	}
587 
588 	return (memcmp(a->data, b->data, a->len) >= 0);
589 }
590 
591 static gboolean
cmp_lt(const fvalue_t * fv_a,const fvalue_t * fv_b)592 cmp_lt(const fvalue_t *fv_a, const fvalue_t *fv_b)
593 {
594 	GByteArray	*a = fv_a->value.bytes;
595 	GByteArray	*b = fv_b->value.bytes;
596 
597 	if (a->len < b->len) {
598 		return TRUE;
599 	}
600 
601 	if (a->len > b->len) {
602 		return FALSE;
603 	}
604 
605 	return (memcmp(a->data, b->data, a->len) < 0);
606 }
607 
608 static gboolean
cmp_le(const fvalue_t * fv_a,const fvalue_t * fv_b)609 cmp_le(const fvalue_t *fv_a, const fvalue_t *fv_b)
610 {
611 	GByteArray	*a = fv_a->value.bytes;
612 	GByteArray	*b = fv_b->value.bytes;
613 
614 	if (a->len < b->len) {
615 		return TRUE;
616 	}
617 
618 	if (a->len > b->len) {
619 		return FALSE;
620 	}
621 
622 	return (memcmp(a->data, b->data, a->len) <= 0);
623 }
624 
625 static gboolean
cmp_bitwise_and(const fvalue_t * fv_a,const fvalue_t * fv_b)626 cmp_bitwise_and(const fvalue_t *fv_a, const fvalue_t *fv_b)
627 {
628 	GByteArray	*a = fv_a->value.bytes;
629 	GByteArray	*b = fv_b->value.bytes;
630 	guint i = 0;
631 	unsigned char *p_a, *p_b;
632 
633 	if (b->len != a->len) {
634 		return FALSE;
635 	}
636 	p_a = a->data;
637 	p_b = b->data;
638 	while (i < b->len) {
639 		if (p_a[i] & p_b[i])
640 			return TRUE;
641 		else
642 			i++;
643 	}
644 	return FALSE;
645 }
646 
647 static gboolean
cmp_contains(const fvalue_t * fv_a,const fvalue_t * fv_b)648 cmp_contains(const fvalue_t *fv_a, const fvalue_t *fv_b)
649 {
650 	GByteArray	*a = fv_a->value.bytes;
651 	GByteArray	*b = fv_b->value.bytes;
652 
653 	if (epan_memmem(a->data, a->len, b->data, b->len)) {
654 		return TRUE;
655 	}
656 	else {
657 		return FALSE;
658 	}
659 }
660 
661 static gboolean
cmp_matches(const fvalue_t * fv,const GRegex * regex)662 cmp_matches(const fvalue_t *fv, const GRegex *regex)
663 {
664 	GByteArray *a = fv->value.bytes;
665 
666 	return g_regex_match_full(
667 		regex,			/* Compiled PCRE */
668 		(char *)a->data,	/* The data to check for the pattern... */
669 		(int)a->len,		/* ... and its length */
670 		0,			/* Start offset within data */
671 		(GRegexMatchFlags)0,	/* GRegexMatchFlags */
672 		NULL,			/* We are not interested in the match information */
673 		NULL			/* We don't want error information */
674 		);
675 	/* NOTE - DO NOT g_free(data) */
676 }
677 
678 void
ftype_register_bytes(void)679 ftype_register_bytes(void)
680 {
681 
682 	static ftype_t bytes_type = {
683 		FT_BYTES,			/* ftype */
684 		"FT_BYTES",			/* name */
685 		"Sequence of bytes",		/* pretty_name */
686 		0,				/* wire_size */
687 		bytes_fvalue_new,		/* new_value */
688 		bytes_fvalue_free,		/* free_value */
689 		bytes_from_unparsed,		/* val_from_unparsed */
690 		bytes_from_string,		/* val_from_string */
691 		bytes_to_repr,			/* val_to_string_repr */
692 		bytes_repr_len,			/* len_string_repr */
693 
694 		{ .set_value_byte_array = bytes_fvalue_set },	/* union set_value */
695 		{ .get_value_ptr = value_get },			/* union get_value */
696 
697 		cmp_eq,
698 		cmp_ne,
699 		cmp_gt,
700 		cmp_ge,
701 		cmp_lt,
702 		cmp_le,
703 		cmp_bitwise_and,
704 		cmp_contains,
705 		CMP_MATCHES,
706 
707 		len,
708 		slice,
709 	};
710 
711 	static ftype_t uint_bytes_type = {
712 		FT_UINT_BYTES,		/* ftype */
713 		"FT_UINT_BYTES",		/* name */
714 		"Sequence of bytes",		/* pretty_name */
715 		0,				/* wire_size */
716 		bytes_fvalue_new,		/* new_value */
717 		bytes_fvalue_free,		/* free_value */
718 		bytes_from_unparsed,		/* val_from_unparsed */
719 		NULL,				/* val_from_string */
720 		bytes_to_repr,			/* val_to_string_repr */
721 		bytes_repr_len,			/* len_string_repr */
722 
723 		{ .set_value_byte_array = bytes_fvalue_set },	/* union set_value */
724 		{ .get_value_ptr = value_get },			/* union get_value */
725 
726 		cmp_eq,
727 		cmp_ne,
728 		cmp_gt,
729 		cmp_ge,
730 		cmp_lt,
731 		cmp_le,
732 		cmp_bitwise_and,
733 		cmp_contains,
734 		NULL,				/* cmp_matches */
735 
736 		len,
737 		slice,
738 	};
739 
740 	static ftype_t ax25_type = {
741 		FT_AX25,			/* ftype */
742 		"FT_AX25",			/* name */
743 		"AX.25 address",		/* pretty_name */
744 		FT_AX25_ADDR_LEN,		/* wire_size */
745 		bytes_fvalue_new,		/* new_value */
746 		bytes_fvalue_free,		/* free_value */
747 		ax25_from_unparsed,		/* val_from_unparsed */
748 		NULL,				/* val_from_string */
749 		bytes_to_repr,			/* val_to_string_repr */
750 		bytes_repr_len,			/* len_string_repr */
751 
752 		{ .set_value_bytes = ax25_fvalue_set },	/* union set_value */
753 		{ .get_value_ptr = value_get },			/* union get_value */
754 
755 		cmp_eq,
756 		cmp_ne,
757 		cmp_gt,
758 		cmp_ge,
759 		cmp_lt,
760 		cmp_le,
761 		cmp_bitwise_and,
762 		cmp_contains,
763 		CMP_MATCHES,
764 
765 		len,
766 		slice,
767 	};
768 
769 	static ftype_t vines_type = {
770 		FT_VINES,			/* ftype */
771 		"FT_VINES",			/* name */
772 		"VINES address",		/* pretty_name */
773 		FT_VINES_ADDR_LEN,		/* wire_size */
774 		bytes_fvalue_new,		/* new_value */
775 		bytes_fvalue_free,		/* free_value */
776 		vines_from_unparsed,		/* val_from_unparsed */
777 		NULL,				/* val_from_string */
778 		bytes_to_repr,			/* val_to_string_repr */
779 		bytes_repr_len,			/* len_string_repr */
780 
781 		{ .set_value_bytes = vines_fvalue_set },	/* union set_value */
782 		{ .get_value_ptr = value_get },			/* union get_value */
783 
784 		cmp_eq,
785 		cmp_ne,
786 		cmp_gt,
787 		cmp_ge,
788 		cmp_lt,
789 		cmp_le,
790 		cmp_bitwise_and,
791 		cmp_contains,
792 		CMP_MATCHES,
793 
794 		len,
795 		slice,
796 	};
797 
798 	static ftype_t ether_type = {
799 		FT_ETHER,			/* ftype */
800 		"FT_ETHER",			/* name */
801 		"Ethernet or other MAC address",/* pretty_name */
802 		FT_ETHER_LEN,			/* wire_size */
803 		bytes_fvalue_new,		/* new_value */
804 		bytes_fvalue_free,		/* free_value */
805 		ether_from_unparsed,		/* val_from_unparsed */
806 		NULL,				/* val_from_string */
807 		bytes_to_repr,			/* val_to_string_repr */
808 		bytes_repr_len,			/* len_string_repr */
809 
810 		{ .set_value_bytes = ether_fvalue_set },	/* union set_value */
811 		{ .get_value_ptr = value_get },			/* union get_value */
812 
813 		cmp_eq,
814 		cmp_ne,
815 		cmp_gt,
816 		cmp_ge,
817 		cmp_lt,
818 		cmp_le,
819 		cmp_bitwise_and,
820 		cmp_contains,
821 		CMP_MATCHES,
822 
823 		len,
824 		slice,
825 	};
826 
827 	static ftype_t oid_type = {
828 		FT_OID,			/* ftype */
829 		"FT_OID",			/* name */
830 		"ASN.1 object identifier",	/* pretty_name */
831 		0,			/* wire_size */
832 		bytes_fvalue_new,		/* new_value */
833 		bytes_fvalue_free,		/* free_value */
834 		oid_from_unparsed,		/* val_from_unparsed */
835 		NULL,				/* val_from_string */
836 		oid_to_repr,			/* val_to_string_repr */
837 		oid_repr_len,			/* len_string_repr */
838 
839 		{ .set_value_byte_array = oid_fvalue_set },	/* union set_value */
840 		{ .get_value_ptr = value_get },			/* union get_value */
841 
842 		cmp_eq,
843 		cmp_ne,
844 		cmp_gt,
845 		cmp_ge,
846 		cmp_lt,
847 		cmp_le,
848 		cmp_bitwise_and,
849 		cmp_contains,
850 		NULL,				/* cmp_matches */
851 
852 		len,
853 		slice,
854 	};
855 
856 	static ftype_t rel_oid_type = {
857 		FT_REL_OID,			/* ftype */
858 		"FT_REL_OID",			/* name */
859 		"ASN.1 relative object identifier",	/* pretty_name */
860 		0,			/* wire_size */
861 		bytes_fvalue_new,		/* new_value */
862 		bytes_fvalue_free,		/* free_value */
863 		rel_oid_from_unparsed,		/* val_from_unparsed */
864 		NULL,				/* val_from_string */
865 		rel_oid_to_repr,		/* val_to_string_repr */
866 		rel_oid_repr_len,		/* len_string_repr */
867 
868 		{ .set_value_byte_array = oid_fvalue_set },	/* union set_value */
869 		{ .get_value_ptr = value_get },			/* union get_value */
870 
871 		cmp_eq,
872 		cmp_ne,
873 		cmp_gt,
874 		cmp_ge,
875 		cmp_lt,
876 		cmp_le,
877 		cmp_bitwise_and,
878 		cmp_contains,
879 		NULL,				/* cmp_matches */
880 
881 		len,
882 		slice,
883 	};
884 
885 	static ftype_t system_id_type = {
886 		FT_SYSTEM_ID,			/* ftype */
887 		"FT_SYSTEM_ID",			/* name */
888 		"OSI System-ID",		/* pretty_name */
889 		0,			/* wire_size */
890 		bytes_fvalue_new,		/* new_value */
891 		bytes_fvalue_free,		/* free_value */
892 		system_id_from_unparsed,	/* val_from_unparsed */
893 		NULL,				/* val_from_string */
894 		system_id_to_repr,		/* val_to_string_repr */
895 		bytes_repr_len,			/* len_string_repr */
896 
897 		{ .set_value_byte_array = system_id_fvalue_set }, /* union set_value */
898 		{ .get_value_ptr = value_get },			/* union get_value */
899 
900 		cmp_eq,
901 		cmp_ne,
902 		cmp_gt,
903 		cmp_ge,
904 		cmp_lt,
905 		cmp_le,
906 		cmp_bitwise_and,
907 		cmp_contains,
908 		NULL,				/* cmp_matches */
909 
910 		len,
911 		slice,
912 	};
913 
914 	static ftype_t fcwwn_type = {
915 		FT_FCWWN,			/* ftype */
916 		"FT_FCWWN",			/* name */
917 		"Fibre Channel WWN",	/* pretty_name */
918 		FT_FCWWN_LEN,			/* wire_size */
919 		bytes_fvalue_new,		/* new_value */
920 		bytes_fvalue_free,		/* free_value */
921 		fcwwn_from_unparsed,		/* val_from_unparsed */
922 		NULL,				/* val_from_string */
923 		bytes_to_repr,			/* val_to_string_repr */
924 		bytes_repr_len,			/* len_string_repr */
925 
926 		{ .set_value_bytes = fcwwn_fvalue_set },	/* union set_value */
927 		{ .get_value_ptr = value_get },			/* union get_value */
928 
929 		cmp_eq,
930 		cmp_ne,
931 		cmp_gt,
932 		cmp_ge,
933 		cmp_lt,
934 		cmp_le,
935 		cmp_bitwise_and,
936 		cmp_contains,
937 		CMP_MATCHES,
938 
939 		len,
940 		slice,
941 	};
942 
943 	ftype_register(FT_BYTES, &bytes_type);
944 	ftype_register(FT_UINT_BYTES, &uint_bytes_type);
945 	ftype_register(FT_AX25, &ax25_type);
946 	ftype_register(FT_VINES, &vines_type);
947 	ftype_register(FT_ETHER, &ether_type);
948 	ftype_register(FT_OID, &oid_type);
949 	ftype_register(FT_REL_OID, &rel_oid_type);
950 	ftype_register(FT_SYSTEM_ID, &system_id_type);
951 	ftype_register(FT_FCWWN, &fcwwn_type);
952 }
953 
954 /*
955  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
956  *
957  * Local variables:
958  * c-basic-offset: 8
959  * tab-width: 8
960  * indent-tabs-mode: t
961  * End:
962  *
963  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
964  * :indentSize=8:tabSize=8:noTabs=false:
965  */
966