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 <stdlib.h>
12 #include <errno.h>
13 #include "ftypes-int.h"
14 #include <epan/addr_resolv.h>
15 #include <epan/strutil.h>
16 #include <epan/to_str.h>
17 
18 #include <wsutil/pint.h>
19 
20 static void
int_fvalue_new(fvalue_t * fv)21 int_fvalue_new(fvalue_t *fv)
22 {
23 	fv->value.uinteger = 0;
24 }
25 
26 static void
set_uinteger(fvalue_t * fv,guint32 value)27 set_uinteger(fvalue_t *fv, guint32 value)
28 {
29 	fv->value.uinteger = value;
30 }
31 
32 static void
set_sinteger(fvalue_t * fv,gint32 value)33 set_sinteger(fvalue_t *fv, gint32 value)
34 {
35 	fv->value.sinteger = value;
36 }
37 
38 
39 static guint32
get_uinteger(fvalue_t * fv)40 get_uinteger(fvalue_t *fv)
41 {
42 	return fv->value.uinteger;
43 }
44 
45 static gint32
get_sinteger(fvalue_t * fv)46 get_sinteger(fvalue_t *fv)
47 {
48 	return fv->value.sinteger;
49 }
50 
51 static gboolean
parse_charconst(const char * s,unsigned long * valuep,gchar ** err_msg)52 parse_charconst(const char *s, unsigned long *valuep, gchar **err_msg)
53 {
54 	const char *cp;
55 	unsigned long value;
56 
57 	cp = s + 1;	/* skip the leading ' */
58 	if (*cp == '\\') {
59 		/*
60 		 * C escape sequence.
61 		 * An escape sequence is an octal number \NNN,
62 		 * an hex number \xNN, or one of \' \" \? \\ \a \b \f \n \r
63 		 * \t \v that stands for the byte value of the equivalent
64 		 * C-escape in ASCII encoding.
65 		 */
66 		cp++;
67 		switch (*cp) {
68 
69 		case '\0':
70 			if (err_msg != NULL)
71 				*err_msg = g_strdup_printf("\"%s\" isn't a valid character constant.", s);
72 			return FALSE;
73 
74 		case 'a':
75 			value = '\a';
76 			break;
77 
78 		case 'b':
79 			value = '\b';
80 			break;
81 
82 		case 'f':
83 			value = '\f';
84 			break;
85 
86 		case 'n':
87 			value = '\n';
88 			break;
89 
90 		case 'r':
91 			value = '\r';
92 			break;
93 
94 		case 't':
95 			value = '\t';
96 			break;
97 
98 		case 'v':
99 			value = '\v';
100 			break;
101 
102 		case '\'':
103 			value = '\'';
104 			break;
105 
106 		case '\\':
107 			value = '\\';
108 			break;
109 
110 		case '"':
111 			value = '"';
112 			break;
113 
114 		case 'x':
115 			cp++;
116 			if (*cp >= '0' && *cp <= '9')
117 				value = *cp - '0';
118 			else if (*cp >= 'A' && *cp <= 'F')
119 				value = 10 + (*cp - 'A');
120 			else if (*cp >= 'a' && *cp <= 'f')
121 				value = 10 + (*cp - 'a');
122 			else {
123 				if (err_msg != NULL)
124 					*err_msg = g_strdup_printf("\"%s\" isn't a valid character constant.", s);
125 				return FALSE;
126 			}
127 			cp++;
128 			if (*cp != '\'') {
129 				value <<= 4;
130 				if (*cp >= '0' && *cp <= '9')
131 					value |= *cp - '0';
132 				else if (*cp >= 'A' && *cp <= 'F')
133 					value |= 10 + (*cp - 'A');
134 				else if (*cp >= 'a' && *cp <= 'f')
135 					value |= 10 + (*cp - 'a');
136 				else {
137 					if (err_msg != NULL)
138 						*err_msg = g_strdup_printf("\"%s\" isn't a valid character constant.", s);
139 					return FALSE;
140 				}
141 			}
142 			break;
143 
144 		default:
145 			/* Octal */
146 			if (*cp >= '0' && *cp <= '7')
147 				value = *cp - '0';
148 			else {
149 				if (err_msg != NULL)
150 					*err_msg = g_strdup_printf("\"%s\" isn't a valid character constant.", s);
151 				return FALSE;
152 			}
153 			if (*(cp + 1) != '\'') {
154 				cp++;
155 				value <<= 3;
156 				if (*cp >= '0' && *cp <= '7')
157 					value |= *cp - '0';
158 				else {
159 					if (err_msg != NULL)
160 						*err_msg = g_strdup_printf("\"%s\" isn't a valid character constant.", s);
161 					return FALSE;
162 				}
163 				if (*(cp + 1) != '\'') {
164 					cp++;
165 					value <<= 3;
166 					if (*cp >= '0' && *cp <= '7')
167 						value |= *cp - '0';
168 					else {
169 						if (err_msg != NULL)
170 							*err_msg = g_strdup_printf("\"%s\" isn't a valid character constant.", s);
171 						return FALSE;
172 					}
173 				}
174 			}
175 			if (value > 0xFF) {
176 				if (err_msg != NULL)
177 					*err_msg = g_strdup_printf("\"%s\" is too large to be a valid character constant.", s);
178 				return FALSE;
179 			}
180 		}
181 	} else {
182 		value = *cp;
183 		if (!g_ascii_isprint(value)) {
184 			if (err_msg != NULL)
185 				*err_msg = g_strdup_printf("Non-printable character '\\x%02lx' in character constant.", value);
186 			return FALSE;
187 		}
188 	}
189 	cp++;
190 	if ((*cp != '\'') || (*(cp + 1) != '\0')){
191 		if (err_msg != NULL)
192 			*err_msg = g_strdup_printf("\"%s\" is too long to be a valid character constant.", s);
193 		return FALSE;
194 	}
195 
196 	*valuep = value;
197 	return TRUE;
198 }
199 
200 static gboolean
uint_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg,guint32 max)201 uint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg,
202 		   guint32 max)
203 {
204 	unsigned long value;
205 	char	*endptr;
206 
207 	if (s[0] == '\'') {
208 		/*
209 		 * Represented as a C-style character constant.
210 		 */
211 		if (!parse_charconst(s, &value, err_msg))
212 			return FALSE;
213 	} else {
214 		/*
215 		 * Try to parse it as a number.
216 		 */
217 		if (strchr (s, '-') && strtol(s, NULL, 0) < 0) {
218 			/*
219 			 * Probably a negative integer, but will be
220 			 * "converted in the obvious manner" by strtoul().
221 			 */
222 			if (err_msg != NULL)
223 				*err_msg = g_strdup_printf("\"%s\" too small for this field, minimum 0.", s);
224 			return FALSE;
225 		}
226 
227 		errno = 0;
228 		value = strtoul(s, &endptr, 0);
229 
230 		if (errno == EINVAL || endptr == s || *endptr != '\0') {
231 			/* This isn't a valid number. */
232 			if (err_msg != NULL)
233 				*err_msg = g_strdup_printf("\"%s\" is not a valid number.", s);
234 			return FALSE;
235 		}
236 		if (errno == ERANGE) {
237 			if (err_msg != NULL) {
238 				if (value == ULONG_MAX) {
239 					*err_msg = g_strdup_printf("\"%s\" causes an integer overflow.",
240 					    s);
241 				}
242 				else {
243 					/*
244 					 * XXX - can "strtoul()" set errno to
245 					 * ERANGE without returning ULONG_MAX?
246 					 */
247 					*err_msg = g_strdup_printf("\"%s\" is not an integer.", s);
248 				}
249 			}
250 			return FALSE;
251 		}
252 	}
253 
254 	if (value > max) {
255 		if (err_msg != NULL)
256 			*err_msg = g_strdup_printf("\"%s\" too big for this field, maximum %u.", s, max);
257 		return FALSE;
258 	}
259 
260 	fv->value.uinteger = (guint32)value;
261 	return TRUE;
262 }
263 
264 static gboolean
uint32_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)265 uint32_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
266 {
267 	return uint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT32);
268 }
269 
270 static gboolean
uint24_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)271 uint24_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
272 {
273 	return uint_from_unparsed (fv, s, allow_partial_value, err_msg, 0xFFFFFF);
274 }
275 
276 static gboolean
uint16_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)277 uint16_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
278 {
279 	return uint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT16);
280 }
281 
282 static gboolean
uint8_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)283 uint8_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
284 {
285 	return uint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT8);
286 }
287 
288 static gboolean
sint_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg,gint32 max,gint32 min)289 sint_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg,
290 		   gint32 max, gint32 min)
291 {
292 	long value;
293 	unsigned long charvalue;
294 	char *endptr;
295 
296 	if (s[0] == '\'') {
297 		/*
298 		 * Represented as a C-style character constant.
299 		 */
300 		if (!parse_charconst(s, &charvalue, err_msg))
301 			return FALSE;
302 
303 		/*
304 		 * The FT_CHAR type is defined to be signed, regardless
305 		 * of whether char is signed or unsigned, so cast the value
306 		 * to "signed char".
307 		 */
308 		value = (signed char)charvalue;
309 	} else {
310 		/*
311 		 * Try to parse it as a number.
312 		 */
313 		if (!strchr (s, '-') && strtoul(s, NULL, 0) > G_MAXINT32) {
314 			/*
315 			 * Probably a positive integer > G_MAXINT32, but
316 			 * will be "converted in the obvious manner" by
317 			 * strtol().
318 			 */
319 			if (err_msg != NULL)
320 				*err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s);
321 			return FALSE;
322 		}
323 
324 		errno = 0;
325 		value = strtol(s, &endptr, 0);
326 
327 		if (errno == EINVAL || endptr == s || *endptr != '\0') {
328 			/* This isn't a valid number. */
329 			if (err_msg != NULL)
330 				*err_msg = g_strdup_printf("\"%s\" is not a valid number.", s);
331 			return FALSE;
332 		}
333 		if (errno == ERANGE) {
334 			if (err_msg != NULL) {
335 				if (value == LONG_MAX) {
336 					*err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s);
337 				}
338 				else if (value == LONG_MIN) {
339 					*err_msg = g_strdup_printf("\"%s\" causes an integer underflow.", s);
340 				}
341 				else {
342 					/*
343 					 * XXX - can "strtol()" set errno to
344 					 * ERANGE without returning ULONG_MAX?
345 					 */
346 					*err_msg = g_strdup_printf("\"%s\" is not an integer.", s);
347 				}
348 			}
349 			return FALSE;
350 		}
351 	}
352 
353 	if (value > max) {
354 		if (err_msg != NULL)
355 			*err_msg = g_strdup_printf("\"%s\" too big for this field, maximum %d.",
356 				s, max);
357 		return FALSE;
358 	} else if (value < min) {
359 		if (err_msg != NULL)
360 			*err_msg = g_strdup_printf("\"%s\" too small for this field, minimum %d.",
361 				s, min);
362 		return FALSE;
363 	}
364 
365 	fv->value.sinteger = (gint32)value;
366 	return TRUE;
367 }
368 
369 static gboolean
sint32_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)370 sint32_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
371 {
372 	return sint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT32, G_MININT32);
373 }
374 
375 static gboolean
sint24_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)376 sint24_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
377 {
378 	return sint_from_unparsed (fv, s, allow_partial_value, err_msg, 0x7FFFFF, -0x800000);
379 }
380 
381 static gboolean
sint16_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)382 sint16_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
383 {
384 	return sint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT16, G_MININT16);
385 }
386 
387 static gboolean
sint8_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)388 sint8_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
389 {
390 	return sint_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT8, G_MININT8);
391 }
392 
393 static int
integer_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)394 integer_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
395 {
396 	return 11;	/* enough for 2^31-1, in decimal */
397 }
398 
399 static void
integer_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size)400 integer_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
401 {
402 	guint32 val;
403 
404 	if (fv->value.sinteger < 0) {
405 		*buf++ = '-';
406 		val = -fv->value.sinteger;
407 	} else
408 		val = fv->value.sinteger;
409 
410 	guint32_to_str_buf(val, buf, size);
411 }
412 
413 static int
uinteger_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)414 uinteger_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
415 {
416 	return 10;	/* enough for 2^32-1, in decimal or 0xXXXXXXXX */
417 }
418 
419 static int
char_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)420 char_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
421 {
422 	return 7;	/* enough for '\OOO' or '\xXX' */
423 }
424 
425 static void
uinteger_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display,char * buf,unsigned int size)426 uinteger_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display, char *buf, unsigned int size)
427 {
428 	if (((field_display & 0xff) == BASE_HEX) || ((field_display & 0xff) == BASE_HEX_DEC))
429 	{
430 		/* This format perfectly fits into 11 bytes. */
431 		*buf++ = '0';
432 		*buf++ = 'x';
433 
434 		switch (fv->ftype->ftype) {
435 
436 		case FT_UINT8:
437 			buf = guint8_to_hex(buf, fv->value.uinteger);
438 			break;
439 
440 		case FT_UINT16:
441 			buf = word_to_hex(buf, fv->value.uinteger);
442 			break;
443 
444 		case FT_UINT24:
445 			buf = guint8_to_hex(buf, (fv->value.uinteger & 0x00ff0000) >> 16);
446 			buf = word_to_hex(buf, (fv->value.uinteger & 0x0000ffff));
447 			break;
448 
449 		default:
450 			buf = dword_to_hex(buf, fv->value.uinteger);
451 			break;
452 		}
453 
454 		*buf++ = '\0';
455 	}
456 	else
457 	{
458 		guint32_to_str_buf(fv->value.uinteger, buf, size);
459 	}
460 }
461 
462 static void
char_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display,char * buf,unsigned int size _U_)463 char_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display, char *buf, unsigned int size _U_)
464 {
465 	/*
466 	 * The longest possible strings are "'\OOO'" and "'\xXX'", which
467 	 * take 7 bytes, including the terminating '\0'.
468 	 */
469 	*buf++ = '\'';
470 	if (g_ascii_isprint(fv->value.uinteger)) {
471 		/* This perfectly fits into 4 or 5 bytes. */
472 		if (fv->value.uinteger == '\\' || fv->value.uinteger == '\'')
473 			*buf++ = '\\';
474 		*buf++ = (char)fv->value.uinteger;
475 	} else {
476 		*buf++ = '\\';
477 		switch (fv->value.uinteger) {
478 
479 		case '\0':
480 			*buf++ = '0';
481 			break;
482 
483 		case '\a':
484 			*buf++ = 'a';
485 			break;
486 
487 		case '\b':
488 			*buf++ = 'b';
489 			break;
490 
491 		case '\f':
492 			*buf++ = 'f';
493 			break;
494 
495 		case '\n':
496 			*buf++ = 'n';
497 			break;
498 
499 		case '\r':
500 			*buf++ = 'r';
501 			break;
502 
503 		case '\t':
504 			*buf++ = 't';
505 			break;
506 
507 		case '\v':
508 			*buf++ = 'v';
509 			break;
510 
511 		default:
512 			if (field_display == BASE_HEX) {
513 				*buf++ = 'x';
514 				buf = guint8_to_hex(buf, fv->value.uinteger);
515 			}
516 			else
517 			{
518 				*buf++ = ((fv->value.uinteger >> 6) & 0x7) + '0';
519 				*buf++ = ((fv->value.uinteger >> 3) & 0x7) + '0';
520 				*buf++ = ((fv->value.uinteger >> 0) & 0x7) + '0';
521 			}
522 			break;
523 		}
524 	}
525 	*buf++ = '\'';
526 	*buf++ = '\0';
527 }
528 
529 static gboolean
ipxnet_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)530 ipxnet_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
531 {
532 	/*
533 	 * Don't request an error message if bytes_from_unparsed fails;
534 	 * if it does, we'll report an error specific to this address
535 	 * type.
536 	 */
537 	if (uint32_from_unparsed(fv, s, TRUE, NULL)) {
538 		return TRUE;
539 	}
540 
541 	/* XXX - Try resolving as an IPX host name and parse that? */
542 
543 	if (err_msg != NULL)
544 		*err_msg = g_strdup_printf("\"%s\" is not a valid IPX network address.", s);
545 	return FALSE;
546 }
547 
548 static int
ipxnet_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)549 ipxnet_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
550 {
551 	return 2+8;	/* 0xXXXXXXXX */
552 }
553 
554 static void
ipxnet_to_repr(fvalue_t * fv,ftrepr_t rtype,int field_display _U_,char * buf,unsigned int size)555 ipxnet_to_repr(fvalue_t *fv, ftrepr_t rtype, int field_display _U_, char *buf, unsigned int size)
556 {
557 	uinteger_to_repr(fv, rtype, BASE_HEX, buf, size);
558 }
559 
560 static gboolean
cmp_eq(const fvalue_t * a,const fvalue_t * b)561 cmp_eq(const fvalue_t *a, const fvalue_t *b)
562 {
563 	return a->value.uinteger == b->value.uinteger;
564 }
565 
566 static gboolean
cmp_ne(const fvalue_t * a,const fvalue_t * b)567 cmp_ne(const fvalue_t *a, const fvalue_t *b)
568 {
569 	return a->value.uinteger != b->value.uinteger;
570 }
571 
572 static gboolean
u_cmp_gt(const fvalue_t * a,const fvalue_t * b)573 u_cmp_gt(const fvalue_t *a, const fvalue_t *b)
574 {
575 	return a->value.uinteger > b->value.uinteger;
576 }
577 
578 static gboolean
u_cmp_ge(const fvalue_t * a,const fvalue_t * b)579 u_cmp_ge(const fvalue_t *a, const fvalue_t *b)
580 {
581 	return a->value.uinteger >= b->value.uinteger;
582 }
583 
584 static gboolean
u_cmp_lt(const fvalue_t * a,const fvalue_t * b)585 u_cmp_lt(const fvalue_t *a, const fvalue_t *b)
586 {
587 	return a->value.uinteger < b->value.uinteger;
588 }
589 
590 static gboolean
u_cmp_le(const fvalue_t * a,const fvalue_t * b)591 u_cmp_le(const fvalue_t *a, const fvalue_t *b)
592 {
593 	return a->value.uinteger <= b->value.uinteger;
594 }
595 
596 static gboolean
s_cmp_gt(const fvalue_t * a,const fvalue_t * b)597 s_cmp_gt(const fvalue_t *a, const fvalue_t *b)
598 {
599 	return a->value.sinteger > b->value.sinteger;
600 }
601 
602 static gboolean
s_cmp_ge(const fvalue_t * a,const fvalue_t * b)603 s_cmp_ge(const fvalue_t *a, const fvalue_t *b)
604 {
605 	return a->value.sinteger >= b->value.sinteger;
606 }
607 
608 static gboolean
s_cmp_lt(const fvalue_t * a,const fvalue_t * b)609 s_cmp_lt(const fvalue_t *a, const fvalue_t *b)
610 {
611 	return a->value.sinteger < b->value.sinteger;
612 }
613 
614 static gboolean
s_cmp_le(const fvalue_t * a,const fvalue_t * b)615 s_cmp_le(const fvalue_t *a, const fvalue_t *b)
616 {
617 	return a->value.sinteger <= b->value.sinteger;
618 }
619 
620 static gboolean
cmp_bitwise_and(const fvalue_t * a,const fvalue_t * b)621 cmp_bitwise_and(const fvalue_t *a, const fvalue_t *b)
622 {
623 	return ((a->value.uinteger & b->value.uinteger) != 0);
624 }
625 
626 static void
int64_fvalue_new(fvalue_t * fv)627 int64_fvalue_new(fvalue_t *fv)
628 {
629 	fv->value.sinteger64 = 0;
630 }
631 
632 static void
set_uinteger64(fvalue_t * fv,guint64 value)633 set_uinteger64(fvalue_t *fv, guint64 value)
634 {
635 	fv->value.uinteger64 = value;
636 }
637 
638 static void
set_sinteger64(fvalue_t * fv,gint64 value)639 set_sinteger64(fvalue_t *fv, gint64 value)
640 {
641 	fv->value.sinteger64 = value;
642 }
643 
644 static guint64
get_uinteger64(fvalue_t * fv)645 get_uinteger64(fvalue_t *fv)
646 {
647 	return fv->value.uinteger64;
648 }
649 
650 static gint64
get_sinteger64(fvalue_t * fv)651 get_sinteger64(fvalue_t *fv)
652 {
653 	return fv->value.sinteger64;
654 }
655 
656 static gboolean
_uint64_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg,guint64 max)657 _uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg,
658 		   guint64 max)
659 {
660 	guint64 value;
661 	char	*endptr;
662 
663 	if (strchr (s, '-') && g_ascii_strtoll(s, NULL, 0) < 0) {
664 		/*
665 		 * Probably a negative integer, but will be
666 		 * "converted in the obvious manner" by g_ascii_strtoull().
667 		 */
668 		if (err_msg != NULL)
669 			*err_msg = g_strdup_printf("\"%s\" causes an integer underflow.", s);
670 		return FALSE;
671 	}
672 
673 	errno = 0;
674 	value = g_ascii_strtoull(s, &endptr, 0);
675 
676 	if (errno == EINVAL || endptr == s || *endptr != '\0') {
677 		/* This isn't a valid number. */
678 		if (err_msg != NULL)
679 			*err_msg = g_strdup_printf("\"%s\" is not a valid number.", s);
680 		return FALSE;
681 	}
682 	if (errno == ERANGE) {
683 		if (err_msg != NULL) {
684 			if (value == G_MAXUINT64) {
685 				*err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s);
686 			}
687 			else {
688 				/*
689 				 * XXX - can "strtoul()" set errno to
690 				 * ERANGE without returning ULONG_MAX?
691 				 */
692 				*err_msg = g_strdup_printf("\"%s\" is not an integer.", s);
693 			}
694 		}
695 		return FALSE;
696 	}
697 
698 	if (value > max) {
699 		if (err_msg != NULL)
700 			*err_msg = g_strdup_printf("\"%s\" too big for this field, maximum %" G_GINT64_MODIFIER "u.", s, max);
701 		return FALSE;
702 	}
703 
704 	fv->value.uinteger64 = value;
705 	return TRUE;
706 }
707 
708 static gboolean
uint64_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)709 uint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
710 {
711 	return _uint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXUINT64);
712 }
713 
714 static gboolean
uint56_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)715 uint56_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
716 {
717 	return _uint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFF));
718 }
719 
720 static gboolean
uint48_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)721 uint48_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
722 {
723 	return _uint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_GUINT64_CONSTANT(0xFFFFFFFFFFFF));
724 }
725 
726 static gboolean
uint40_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)727 uint40_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
728 {
729 	return _uint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_GUINT64_CONSTANT(0xFFFFFFFFFF));
730 }
731 
732 static gboolean
_sint64_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg,gint64 max,gint64 min)733 _sint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg,
734 		   gint64 max, gint64 min)
735 {
736 	gint64 value;
737 	char   *endptr;
738 
739 	if (!strchr (s, '-') && g_ascii_strtoull(s, NULL, 0) > G_MAXINT64) {
740 		/*
741 		 * Probably a positive integer > G_MAXINT64, but will be
742 		 * "converted in the obvious manner" by g_ascii_strtoll().
743 		 */
744 		if (err_msg != NULL)
745 			*err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s);
746 		return FALSE;
747 	}
748 
749 	errno = 0;
750 	value = g_ascii_strtoll(s, &endptr, 0);
751 
752 	if (errno == EINVAL || endptr == s || *endptr != '\0') {
753 		/* This isn't a valid number. */
754 		if (err_msg != NULL)
755 			*err_msg = g_strdup_printf("\"%s\" is not a valid number.", s);
756 		return FALSE;
757 	}
758 	if (errno == ERANGE) {
759 		if (err_msg != NULL) {
760 			if (value == G_MAXINT64) {
761 				*err_msg = g_strdup_printf("\"%s\" causes an integer overflow.", s);
762 			}
763 			else if (value == G_MININT64) {
764 				*err_msg = g_strdup_printf("\"%s\" causes an integer underflow.", s);
765 			}
766 			else {
767 				/*
768 				 * XXX - can "strtol()" set errno to
769 				 * ERANGE without returning LONG_MAX?
770 				 */
771 				*err_msg = g_strdup_printf("\"%s\" is not an integer.", s);
772 			}
773 		}
774 		return FALSE;
775 	}
776 
777 	if (value > max) {
778 		if (err_msg != NULL)
779 			*err_msg = g_strdup_printf("\"%s\" too big for this field, maximum %" G_GINT64_MODIFIER "u.", s, max);
780 		return FALSE;
781 	} else if (value < min) {
782 		if (err_msg != NULL)
783 			*err_msg = g_strdup_printf("\"%s\" too small for this field, maximum %" G_GINT64_MODIFIER "u.", s, max);
784 		return FALSE;
785 	}
786 
787 	fv->value.sinteger64 = (guint64)value;
788 	return TRUE;
789 }
790 
791 static gboolean
sint64_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)792 sint64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
793 {
794 	return _sint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_MAXINT64, G_MININT64);
795 }
796 
797 static gboolean
sint56_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)798 sint56_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
799 {
800 	return _sint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_GINT64_CONSTANT(0x7FFFFFFFFFFFFF), G_GINT64_CONSTANT(-0x80000000000000));
801 }
802 
803 static gboolean
sint48_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)804 sint48_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
805 {
806 	return _sint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_GINT64_CONSTANT(0x7FFFFFFFFFFF), G_GINT64_CONSTANT(-0x800000000000));
807 }
808 
809 static gboolean
sint40_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value,gchar ** err_msg)810 sint40_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value, gchar **err_msg)
811 {
812 	return _sint64_from_unparsed (fv, s, allow_partial_value, err_msg, G_GINT64_CONSTANT(0x7FFFFFFFFF), G_GINT64_CONSTANT(-0x8000000000));
813 }
814 
815 static int
integer64_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)816 integer64_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
817 {
818 	return 20;	/* enough for -2^63-1, in decimal */
819 }
820 
821 static void
integer64_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size)822 integer64_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
823 {
824 	guint64 val;
825 
826 	if (fv->value.sinteger64 < 0) {
827 		*buf++ = '-';
828 		val = -fv->value.sinteger64;
829 	} else
830 		val = fv->value.sinteger64;
831 
832 	guint64_to_str_buf(val, buf, size);
833 }
834 
835 static int
uinteger64_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)836 uinteger64_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
837 {
838 	return 20;	/* enough for 2^64-1, in decimal or 0xXXXXXXXXXXXXXXXX */
839 }
840 
841 static void
uinteger64_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display,char * buf,unsigned int size)842 uinteger64_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display, char *buf, unsigned int size)
843 {
844 	if ((field_display == BASE_HEX) || (field_display == BASE_HEX_DEC))
845 	{
846 		/* This format perfectly fits into 19 bytes. */
847 		*buf++ = '0';
848 		*buf++ = 'x';
849 
850 		buf = qword_to_hex(buf, fv->value.uinteger64);
851 		*buf++ = '\0';
852 	}
853 	else
854 	{
855 		guint64_to_str_buf(fv->value.uinteger64, buf, size);
856 	}
857 }
858 
859 static gboolean
cmp_eq64(const fvalue_t * a,const fvalue_t * b)860 cmp_eq64(const fvalue_t *a, const fvalue_t *b)
861 {
862 	return a->value.uinteger64 == b->value.uinteger64;
863 }
864 
865 static gboolean
cmp_ne64(const fvalue_t * a,const fvalue_t * b)866 cmp_ne64(const fvalue_t *a, const fvalue_t *b)
867 {
868 	return a->value.uinteger64 != b->value.uinteger64;
869 }
870 
871 static gboolean
u_cmp_gt64(const fvalue_t * a,const fvalue_t * b)872 u_cmp_gt64(const fvalue_t *a, const fvalue_t *b)
873 {
874 	return a->value.uinteger64 > b->value.uinteger64;
875 }
876 
877 static gboolean
u_cmp_ge64(const fvalue_t * a,const fvalue_t * b)878 u_cmp_ge64(const fvalue_t *a, const fvalue_t *b)
879 {
880 	return a->value.uinteger64 >= b->value.uinteger64;
881 }
882 
883 static gboolean
u_cmp_lt64(const fvalue_t * a,const fvalue_t * b)884 u_cmp_lt64(const fvalue_t *a, const fvalue_t *b)
885 {
886 	return a->value.uinteger64 < b->value.uinteger64;
887 }
888 
889 static gboolean
u_cmp_le64(const fvalue_t * a,const fvalue_t * b)890 u_cmp_le64(const fvalue_t *a, const fvalue_t *b)
891 {
892 	return a->value.uinteger64 <= b->value.uinteger64;
893 }
894 
895 static gboolean
s_cmp_gt64(const fvalue_t * a,const fvalue_t * b)896 s_cmp_gt64(const fvalue_t *a, const fvalue_t *b)
897 {
898 	return (gint64)a->value.sinteger64 > (gint64)b->value.sinteger64;
899 }
900 
901 static gboolean
s_cmp_ge64(const fvalue_t * a,const fvalue_t * b)902 s_cmp_ge64(const fvalue_t *a, const fvalue_t *b)
903 {
904 	return (gint64)a->value.sinteger64 >= (gint64)b->value.sinteger64;
905 }
906 
907 static gboolean
s_cmp_lt64(const fvalue_t * a,const fvalue_t * b)908 s_cmp_lt64(const fvalue_t *a, const fvalue_t *b)
909 {
910 	return (gint64)a->value.sinteger64 < (gint64)b->value.sinteger64;
911 }
912 
913 static gboolean
s_cmp_le64(const fvalue_t * a,const fvalue_t * b)914 s_cmp_le64(const fvalue_t *a, const fvalue_t *b)
915 {
916 	return (gint64)a->value.sinteger64 <= (gint64)b->value.sinteger64;
917 }
918 
919 static gboolean
cmp_bitwise_and64(const fvalue_t * a,const fvalue_t * b)920 cmp_bitwise_and64(const fvalue_t *a, const fvalue_t *b)
921 {
922 	return ((a->value.uinteger64 & b->value.uinteger64) != 0);
923 }
924 
925 /* BOOLEAN-specific */
926 
927 static void
boolean_fvalue_new(fvalue_t * fv)928 boolean_fvalue_new(fvalue_t *fv)
929 {
930 	fv->value.uinteger64 = TRUE;
931 }
932 
933 static int
boolean_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)934 boolean_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
935 {
936 	return 1;
937 }
938 
939 static void
boolean_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size _U_)940 boolean_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size _U_)
941 {
942 	*buf++ = (fv->value.uinteger64) ? '1' : '0';
943 	*buf   = '\0';
944 }
945 
946 /* Checks for equality with zero or non-zero */
947 static gboolean
bool_eq(const fvalue_t * a,const fvalue_t * b)948 bool_eq(const fvalue_t *a, const fvalue_t *b)
949 {
950 	if (a->value.uinteger64) {
951 		if (b->value.uinteger64) {
952 			return TRUE;
953 		}
954 		else {
955 			return FALSE;
956 		}
957 	}
958 	else {
959 		if (b->value.uinteger64) {
960 			return FALSE;
961 		}
962 		else {
963 			return TRUE;
964 		}
965 	}
966 }
967 
968 /* Checks for inequality with zero or non-zero */
969 static gboolean
bool_ne(const fvalue_t * a,const fvalue_t * b)970 bool_ne(const fvalue_t *a, const fvalue_t *b)
971 {
972 	return (!bool_eq(a,b));
973 }
974 
975 /* EUI64-specific */
976 static gboolean
eui64_from_unparsed(fvalue_t * fv,const char * s,gboolean allow_partial_value _U_,gchar ** err_msg)977 eui64_from_unparsed(fvalue_t *fv, const char *s, gboolean allow_partial_value _U_, gchar **err_msg)
978 {
979 	GByteArray	*bytes;
980 	gboolean	res;
981 	union {
982 		guint64 value;
983 		guint8  bytes[8];
984 	} eui64;
985 
986 	/*
987 	 * Don't request an error message if uint64_from_unparsed fails;
988 	 * if it does, we'll try parsing it as a sequence of bytes, and
989 	 * report an error if *that* fails.
990 	 */
991 	if (uint64_from_unparsed(fv, s, TRUE, NULL)) {
992 		return TRUE;
993 	}
994 
995 	bytes = g_byte_array_new();
996 	res = hex_str_to_bytes(s, bytes, TRUE);
997 	if (!res || bytes->len != 8) {
998 		if (err_msg != NULL)
999 			*err_msg = g_strdup_printf("\"%s\" is not a valid EUI-64 address.", s);
1000 		g_byte_array_free(bytes, TRUE);
1001 		return FALSE;
1002 	}
1003 
1004 	memcpy(eui64.bytes, bytes->data, 8);
1005 	g_byte_array_free(bytes, TRUE);
1006 	fv->value.integer64 = GUINT64_FROM_BE(eui64.value);
1007 	return TRUE;
1008 }
1009 
1010 static int
eui64_repr_len(fvalue_t * fv _U_,ftrepr_t rtype _U_,int field_display _U_)1011 eui64_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_, int field_display _U_)
1012 {
1013 	return EUI64_STR_LEN;	/* XX:XX:XX:XX:XX:XX:XX:XX */
1014 }
1015 
1016 static void
eui64_to_repr(fvalue_t * fv,ftrepr_t rtype _U_,int field_display _U_,char * buf,unsigned int size)1017 eui64_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, int field_display _U_, char *buf, unsigned int size)
1018 {
1019 	union {
1020 		guint64 value;
1021 		guint8  bytes[8];
1022 	} eui64;
1023 
1024 	/* Copy and convert the address from host to network byte order. */
1025 	eui64.value = GUINT64_TO_BE(fv->value.integer64);
1026 
1027 	g_snprintf(buf, size, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
1028 	    eui64.bytes[0], eui64.bytes[1], eui64.bytes[2], eui64.bytes[3],
1029 	    eui64.bytes[4], eui64.bytes[5], eui64.bytes[6], eui64.bytes[7]);
1030 }
1031 
1032 void
ftype_register_integers(void)1033 ftype_register_integers(void)
1034 {
1035 	static ftype_t char_type = {
1036 		FT_CHAR,			/* ftype */
1037 		"FT_CHAR",			/* name */
1038 		"Character, 1 byte",		/* pretty name */
1039 		1,				/* wire_size */
1040 		int_fvalue_new,			/* new_value */
1041 		NULL,				/* free_value */
1042 		uint8_from_unparsed,		/* val_from_unparsed */
1043 		NULL,				/* val_from_string */
1044 		char_to_repr,			/* val_to_string_repr */
1045 		char_repr_len,			/* len_string_repr */
1046 
1047 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1048 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1049 
1050 		cmp_eq,
1051 		cmp_ne,
1052 		u_cmp_gt,
1053 		u_cmp_ge,
1054 		u_cmp_lt,
1055 		u_cmp_le,
1056 		cmp_bitwise_and,
1057 		NULL,				/* cmp_contains */
1058 		NULL,				/* cmp_matches */
1059 
1060 		NULL,				/* len */
1061 		NULL,				/* slice */
1062 	};
1063 	static ftype_t uint8_type = {
1064 		FT_UINT8,			/* ftype */
1065 		"FT_UINT8",			/* name */
1066 		"Unsigned integer, 1 byte",	/* pretty name */
1067 		1,				/* wire_size */
1068 		int_fvalue_new,			/* new_value */
1069 		NULL,				/* free_value */
1070 		uint8_from_unparsed,		/* val_from_unparsed */
1071 		NULL,				/* val_from_string */
1072 		uinteger_to_repr,		/* val_to_string_repr */
1073 		uinteger_repr_len,		/* len_string_repr */
1074 
1075 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1076 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1077 
1078 		cmp_eq,
1079 		cmp_ne,
1080 		u_cmp_gt,
1081 		u_cmp_ge,
1082 		u_cmp_lt,
1083 		u_cmp_le,
1084 		cmp_bitwise_and,
1085 		NULL,				/* cmp_contains */
1086 		NULL,				/* cmp_matches */
1087 
1088 		NULL,				/* len */
1089 		NULL,				/* slice */
1090 	};
1091 	static ftype_t uint16_type = {
1092 		FT_UINT16,			/* ftype */
1093 		"FT_UINT16",			/* name */
1094 		"Unsigned integer, 2 bytes",	/* pretty_name */
1095 		2,				/* wire_size */
1096 		int_fvalue_new,			/* new_value */
1097 		NULL,				/* free_value */
1098 		uint16_from_unparsed,		/* val_from_unparsed */
1099 		NULL,				/* val_from_string */
1100 		uinteger_to_repr,		/* val_to_string_repr */
1101 		uinteger_repr_len,		/* len_string_repr */
1102 
1103 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1104 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1105 
1106 		cmp_eq,
1107 		cmp_ne,
1108 		u_cmp_gt,
1109 		u_cmp_ge,
1110 		u_cmp_lt,
1111 		u_cmp_le,
1112 		cmp_bitwise_and,
1113 		NULL,				/* cmp_contains */
1114 		NULL,				/* cmp_matches */
1115 
1116 		NULL,				/* len */
1117 		NULL,				/* slice */
1118 	};
1119 	static ftype_t uint24_type = {
1120 		FT_UINT24,			/* ftype */
1121 		"FT_UINT24",			/* name */
1122 		"Unsigned integer, 3 bytes",	/* pretty_name */
1123 		3,				/* wire_size */
1124 		int_fvalue_new,			/* new_value */
1125 		NULL,				/* free_value */
1126 		uint24_from_unparsed,		/* val_from_unparsed */
1127 		NULL,				/* val_from_string */
1128 		uinteger_to_repr,		/* val_to_string_repr */
1129 		uinteger_repr_len,		/* len_string_repr */
1130 
1131 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1132 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1133 
1134 		cmp_eq,
1135 		cmp_ne,
1136 		u_cmp_gt,
1137 		u_cmp_ge,
1138 		u_cmp_lt,
1139 		u_cmp_le,
1140 		cmp_bitwise_and,
1141 		NULL,				/* cmp_contains */
1142 		NULL,				/* cmp_matches */
1143 
1144 		NULL,				/* len */
1145 		NULL,				/* slice */
1146 	};
1147 	static ftype_t uint32_type = {
1148 		FT_UINT32,			/* ftype */
1149 		"FT_UINT32",			/* name */
1150 		"Unsigned integer, 4 bytes",	/* pretty_name */
1151 		4,				/* wire_size */
1152 		int_fvalue_new,			/* new_value */
1153 		NULL,				/* free_value */
1154 		uint32_from_unparsed,		/* val_from_unparsed */
1155 		NULL,				/* val_from_string */
1156 		uinteger_to_repr,		/* val_to_string_repr */
1157 		uinteger_repr_len,		/* len_string_repr */
1158 
1159 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1160 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1161 
1162 		cmp_eq,
1163 		cmp_ne,
1164 		u_cmp_gt,
1165 		u_cmp_ge,
1166 		u_cmp_lt,
1167 		u_cmp_le,
1168 		cmp_bitwise_and,
1169 		NULL,				/* cmp_contains */
1170 		NULL,				/* cmp_matches */
1171 
1172 		NULL,				/* len */
1173 		NULL,				/* slice */
1174 	};
1175 	static ftype_t uint40_type = {
1176 		FT_UINT40,			/* ftype */
1177 		"FT_UINT40",			/* name */
1178 		"Unsigned integer, 5 bytes",	/* pretty_name */
1179 		5,				/* wire_size */
1180 		int64_fvalue_new,		/* new_value */
1181 		NULL,				/* free_value */
1182 		uint40_from_unparsed,		/* val_from_unparsed */
1183 		NULL,				/* val_from_string */
1184 		uinteger64_to_repr,		/* val_to_string_repr */
1185 		uinteger64_repr_len,		/* len_string_repr */
1186 
1187 		{ .set_value_uinteger64 = set_uinteger64 },	/* union set_value */
1188 		{ .get_value_uinteger64 = get_uinteger64 },	/* union get_value */
1189 
1190 		cmp_eq64,
1191 		cmp_ne64,
1192 		u_cmp_gt64,
1193 		u_cmp_ge64,
1194 		u_cmp_lt64,
1195 		u_cmp_le64,
1196 		cmp_bitwise_and64,
1197 		NULL,				/* cmp_contains */
1198 		NULL,				/* cmp_matches */
1199 
1200 		NULL,
1201 		NULL,
1202 	};
1203 	static ftype_t uint48_type = {
1204 		FT_UINT48,			/* ftype */
1205 		"FT_UINT48",			/* name */
1206 		"Unsigned integer, 6 bytes",	/* pretty_name */
1207 		6,				/* wire_size */
1208 		int64_fvalue_new,		/* new_value */
1209 		NULL,				/* free_value */
1210 		uint48_from_unparsed,		/* val_from_unparsed */
1211 		NULL,				/* val_from_string */
1212 		uinteger64_to_repr,		/* val_to_string_repr */
1213 		uinteger64_repr_len,		/* len_string_repr */
1214 
1215 		{ .set_value_uinteger64 = set_uinteger64 },	/* union set_value */
1216 		{ .get_value_uinteger64 = get_uinteger64 },	/* union get_value */
1217 
1218 		cmp_eq64,
1219 		cmp_ne64,
1220 		u_cmp_gt64,
1221 		u_cmp_ge64,
1222 		u_cmp_lt64,
1223 		u_cmp_le64,
1224 		cmp_bitwise_and64,
1225 		NULL,				/* cmp_contains */
1226 		NULL,				/* cmp_matches */
1227 
1228 		NULL,
1229 		NULL,
1230 	};
1231 	static ftype_t uint56_type = {
1232 		FT_UINT56,			/* ftype */
1233 		"FT_UINT56",			/* name */
1234 		"Unsigned integer, 7 bytes",	/* pretty_name */
1235 		7,				/* wire_size */
1236 		int64_fvalue_new,		/* new_value */
1237 		NULL,				/* free_value */
1238 		uint56_from_unparsed,		/* val_from_unparsed */
1239 		NULL,				/* val_from_string */
1240 		uinteger64_to_repr,		/* val_to_string_repr */
1241 		uinteger64_repr_len,		/* len_string_repr */
1242 
1243 		{ .set_value_uinteger64 = set_uinteger64 },	/* union set_value */
1244 		{ .get_value_uinteger64 = get_uinteger64 },	/* union get_value */
1245 
1246 		cmp_eq64,
1247 		cmp_ne64,
1248 		u_cmp_gt64,
1249 		u_cmp_ge64,
1250 		u_cmp_lt64,
1251 		u_cmp_le64,
1252 		cmp_bitwise_and64,
1253 		NULL,				/* cmp_contains */
1254 		NULL,				/* cmp_matches */
1255 
1256 		NULL,
1257 		NULL,
1258 	};
1259 	static ftype_t uint64_type = {
1260 		FT_UINT64,			/* ftype */
1261 		"FT_UINT64",			/* name */
1262 		"Unsigned integer, 8 bytes",	/* pretty_name */
1263 		8,				/* wire_size */
1264 		int64_fvalue_new,		/* new_value */
1265 		NULL,				/* free_value */
1266 		uint64_from_unparsed,		/* val_from_unparsed */
1267 		NULL,				/* val_from_string */
1268 		uinteger64_to_repr,		/* val_to_string_repr */
1269 		uinteger64_repr_len,		/* len_string_repr */
1270 
1271 		{ .set_value_uinteger64 = set_uinteger64 },	/* union set_value */
1272 		{ .get_value_uinteger64 = get_uinteger64 },	/* union get_value */
1273 
1274 		cmp_eq64,
1275 		cmp_ne64,
1276 		u_cmp_gt64,
1277 		u_cmp_ge64,
1278 		u_cmp_lt64,
1279 		u_cmp_le64,
1280 		cmp_bitwise_and64,
1281 		NULL,				/* cmp_contains */
1282 		NULL,				/* cmp_matches */
1283 
1284 		NULL,
1285 		NULL,
1286 	};
1287 	static ftype_t int8_type = {
1288 		FT_INT8,			/* ftype */
1289 		"FT_INT8",			/* name */
1290 		"Signed integer, 1 byte",	/* pretty_name */
1291 		1,				/* wire_size */
1292 		int_fvalue_new,			/* new_value */
1293 		NULL,				/* free_value */
1294 		sint8_from_unparsed,		/* val_from_unparsed */
1295 		NULL,				/* val_from_string */
1296 		integer_to_repr,		/* val_to_string_repr */
1297 		integer_repr_len,		/* len_string_repr */
1298 
1299 		{ .set_value_sinteger = set_sinteger },	/* union set_value */
1300 		{ .get_value_sinteger = get_sinteger },	/* union get_value */
1301 
1302 		cmp_eq,
1303 		cmp_ne,
1304 		s_cmp_gt,
1305 		s_cmp_ge,
1306 		s_cmp_lt,
1307 		s_cmp_le,
1308 		cmp_bitwise_and,
1309 		NULL,				/* cmp_contains */
1310 		NULL,				/* cmp_matches */
1311 
1312 		NULL,				/* len */
1313 		NULL,				/* slice */
1314 	};
1315 	static ftype_t int16_type = {
1316 		FT_INT16,			/* ftype */
1317 		"FT_INT16",			/* name */
1318 		"Signed integer, 2 bytes",	/* pretty_name */
1319 		2,				/* wire_size */
1320 		int_fvalue_new,			/* new_value */
1321 		NULL,				/* free_value */
1322 		sint16_from_unparsed,		/* val_from_unparsed */
1323 		NULL,				/* val_from_string */
1324 		integer_to_repr,		/* val_to_string_repr */
1325 		integer_repr_len,		/* len_string_repr */
1326 
1327 		{ .set_value_sinteger = set_sinteger },	/* union set_value */
1328 		{ .get_value_sinteger = get_sinteger },	/* union get_value */
1329 
1330 		cmp_eq,
1331 		cmp_ne,
1332 		s_cmp_gt,
1333 		s_cmp_ge,
1334 		s_cmp_lt,
1335 		s_cmp_le,
1336 		cmp_bitwise_and,
1337 		NULL,				/* cmp_contains */
1338 		NULL,				/* cmp_matches */
1339 
1340 		NULL,				/* len */
1341 		NULL,				/* slice */
1342 	};
1343 	static ftype_t int24_type = {
1344 		FT_INT24,			/* ftype */
1345 		"FT_INT24",			/* name */
1346 		"Signed integer, 3 bytes",	/* pretty_name */
1347 		3,				/* wire_size */
1348 		int_fvalue_new,			/* new_value */
1349 		NULL,				/* free_value */
1350 		sint24_from_unparsed,		/* val_from_unparsed */
1351 		NULL,				/* val_from_string */
1352 		integer_to_repr,		/* val_to_string_repr */
1353 		integer_repr_len,		/* len_string_repr */
1354 
1355 		{ .set_value_sinteger = set_sinteger },	/* union set_value */
1356 		{ .get_value_sinteger = get_sinteger },	/* union get_value */
1357 
1358 		cmp_eq,
1359 		cmp_ne,
1360 		s_cmp_gt,
1361 		s_cmp_ge,
1362 		s_cmp_lt,
1363 		s_cmp_le,
1364 		cmp_bitwise_and,
1365 		NULL,				/* cmp_contains */
1366 		NULL,				/* cmp_matches */
1367 
1368 		NULL,				/* len */
1369 		NULL,				/* slice */
1370 	};
1371 	static ftype_t int32_type = {
1372 		FT_INT32,			/* ftype */
1373 		"FT_INT32",			/* name */
1374 		"Signed integer, 4 bytes",	/* pretty_name */
1375 		4,				/* wire_size */
1376 		int_fvalue_new,			/* new_value */
1377 		NULL,				/* free_value */
1378 		sint32_from_unparsed,		/* val_from_unparsed */
1379 		NULL,				/* val_from_string */
1380 		integer_to_repr,		/* val_to_string_repr */
1381 		integer_repr_len,		/* len_string_repr */
1382 
1383 		{ .set_value_sinteger = set_sinteger },	/* union set_value */
1384 		{ .get_value_sinteger = get_sinteger },	/* union get_value */
1385 
1386 		cmp_eq,
1387 		cmp_ne,
1388 		s_cmp_gt,
1389 		s_cmp_ge,
1390 		s_cmp_lt,
1391 		s_cmp_le,
1392 		cmp_bitwise_and,
1393 		NULL,				/* cmp_contains */
1394 		NULL,				/* cmp_matches */
1395 
1396 		NULL,				/* len */
1397 		NULL,				/* slice */
1398 	};
1399 	static ftype_t int40_type = {
1400 		FT_INT40,			/* ftype */
1401 		"FT_INT40",			/* name */
1402 		"Signed integer, 5 bytes",	/* pretty_name */
1403 		5,				/* wire_size */
1404 		int64_fvalue_new,		/* new_value */
1405 		NULL,				/* free_value */
1406 		sint40_from_unparsed,		/* val_from_unparsed */
1407 		NULL,				/* val_from_string */
1408 		integer64_to_repr,		/* val_to_string_repr */
1409 		integer64_repr_len,		/* len_string_repr */
1410 
1411 		{ .set_value_sinteger64 = set_sinteger64 },	/* union set_value */
1412 		{ .get_value_sinteger64 = get_sinteger64 },	/* union get_value */
1413 
1414 		cmp_eq64,
1415 		cmp_ne64,
1416 		s_cmp_gt64,
1417 		s_cmp_ge64,
1418 		s_cmp_lt64,
1419 		s_cmp_le64,
1420 		cmp_bitwise_and64,
1421 		NULL,				/* cmp_contains */
1422 		NULL,				/* cmp_matches */
1423 
1424 		NULL,
1425 		NULL,
1426 	};
1427 	static ftype_t int48_type = {
1428 		FT_INT48,			/* ftype */
1429 		"FT_INT48",			/* name */
1430 		"Signed integer, 6 bytes",	/* pretty_name */
1431 		6,				/* wire_size */
1432 		int64_fvalue_new,		/* new_value */
1433 		NULL,				/* free_value */
1434 		sint48_from_unparsed,		/* val_from_unparsed */
1435 		NULL,				/* val_from_string */
1436 		integer64_to_repr,		/* val_to_string_repr */
1437 		integer64_repr_len,		/* len_string_repr */
1438 
1439 		{ .set_value_sinteger64 = set_sinteger64 },	/* union set_value */
1440 		{ .get_value_sinteger64 = get_sinteger64 },	/* union get_value */
1441 
1442 		cmp_eq64,
1443 		cmp_ne64,
1444 		s_cmp_gt64,
1445 		s_cmp_ge64,
1446 		s_cmp_lt64,
1447 		s_cmp_le64,
1448 		cmp_bitwise_and64,
1449 		NULL,				/* cmp_contains */
1450 		NULL,				/* cmp_matches */
1451 
1452 		NULL,
1453 		NULL,
1454 	};
1455 	static ftype_t int56_type = {
1456 		FT_INT56,			/* ftype */
1457 		"FT_INT56",			/* name */
1458 		"Signed integer, 7 bytes",	/* pretty_name */
1459 		7,				/* wire_size */
1460 		int64_fvalue_new,		/* new_value */
1461 		NULL,				/* free_value */
1462 		sint56_from_unparsed,		/* val_from_unparsed */
1463 		NULL,				/* val_from_string */
1464 		integer64_to_repr,		/* val_to_string_repr */
1465 		integer64_repr_len,		/* len_string_repr */
1466 
1467 		{ .set_value_sinteger64 = set_sinteger64 },	/* union set_value */
1468 		{ .get_value_sinteger64 = get_sinteger64 },	/* union get_value */
1469 
1470 		cmp_eq64,
1471 		cmp_ne64,
1472 		s_cmp_gt64,
1473 		s_cmp_ge64,
1474 		s_cmp_lt64,
1475 		s_cmp_le64,
1476 		cmp_bitwise_and64,
1477 		NULL,				/* cmp_contains */
1478 		NULL,				/* cmp_matches */
1479 
1480 		NULL,
1481 		NULL,
1482 	};
1483 	static ftype_t int64_type = {
1484 		FT_INT64,			/* ftype */
1485 		"FT_INT64",			/* name */
1486 		"Signed integer, 8 bytes",	/* pretty_name */
1487 		8,				/* wire_size */
1488 		int64_fvalue_new,		/* new_value */
1489 		NULL,				/* free_value */
1490 		sint64_from_unparsed,		/* val_from_unparsed */
1491 		NULL,				/* val_from_string */
1492 		integer64_to_repr,		/* val_to_string_repr */
1493 		integer64_repr_len,		/* len_string_repr */
1494 
1495 		{ .set_value_sinteger64 = set_sinteger64 },	/* union set_value */
1496 		{ .get_value_sinteger64 = get_sinteger64 },	/* union get_value */
1497 
1498 		cmp_eq64,
1499 		cmp_ne64,
1500 		s_cmp_gt64,
1501 		s_cmp_ge64,
1502 		s_cmp_lt64,
1503 		s_cmp_le64,
1504 		cmp_bitwise_and64,
1505 		NULL,				/* cmp_contains */
1506 		NULL,				/* cmp_matches */
1507 
1508 		NULL,
1509 		NULL,
1510 	};
1511 	static ftype_t boolean_type = {
1512 		FT_BOOLEAN,			/* ftype */
1513 		"FT_BOOLEAN",			/* name */
1514 		"Boolean",			/* pretty_name */
1515 		0,				/* wire_size */
1516 		boolean_fvalue_new,		/* new_value */
1517 		NULL,				/* free_value */
1518 		uint64_from_unparsed,		/* val_from_unparsed */
1519 		NULL,				/* val_from_string */
1520 		boolean_to_repr,		/* val_to_string_repr */
1521 		boolean_repr_len,		/* len_string_repr */
1522 
1523 		{ .set_value_uinteger64 = set_uinteger64 },	/* union set_value */
1524 		{ .get_value_uinteger64 = get_uinteger64 },	/* union get_value */
1525 
1526 		bool_eq,			/* cmp_eq */
1527 		bool_ne,			/* cmp_ne */
1528 		NULL,				/* cmp_gt */
1529 		NULL,				/* cmp_ge */
1530 		NULL,				/* cmp_lt */
1531 		NULL,				/* cmp_le */
1532 		NULL,				/* cmp_bitwise_and */
1533 		NULL,				/* cmp_contains */
1534 		NULL,				/* cmp_matches */
1535 
1536 		NULL,				/* len */
1537 		NULL,				/* slice */
1538 	};
1539 
1540 	static ftype_t ipxnet_type = {
1541 		FT_IPXNET,			/* ftype */
1542 		"FT_IPXNET",			/* name */
1543 		"IPX network number",		/* pretty_name */
1544 		4,				/* wire_size */
1545 		int_fvalue_new,			/* new_value */
1546 		NULL,				/* free_value */
1547 		ipxnet_from_unparsed,		/* val_from_unparsed */
1548 		NULL,				/* val_from_string */
1549 		ipxnet_to_repr,			/* val_to_string_repr */
1550 		ipxnet_repr_len,		/* len_string_repr */
1551 
1552 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1553 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1554 
1555 		cmp_eq,
1556 		cmp_ne,
1557 		u_cmp_gt,
1558 		u_cmp_ge,
1559 		u_cmp_lt,
1560 		u_cmp_le,
1561 		cmp_bitwise_and,
1562 		NULL,				/* cmp_contains */
1563 		NULL,				/* cmp_matches */
1564 
1565 		NULL,				/* len */
1566 		NULL,				/* slice */
1567 	};
1568 
1569 	static ftype_t framenum_type = {
1570 		FT_FRAMENUM,			/* ftype */
1571 		"FT_FRAMENUM",			/* name */
1572 		"Frame number",			/* pretty_name */
1573 		4,				/* wire_size */
1574 		int_fvalue_new,			/* new_value */
1575 		NULL,				/* free_value */
1576 		uint32_from_unparsed,		/* val_from_unparsed */
1577 		NULL,				/* val_from_string */
1578 		uinteger_to_repr,		/* val_to_string_repr */
1579 		uinteger_repr_len,		/* len_string_repr */
1580 
1581 		{ .set_value_uinteger = set_uinteger },	/* union set_value */
1582 		{ .get_value_uinteger = get_uinteger },	/* union get_value */
1583 
1584 		cmp_eq,
1585 		cmp_ne,
1586 		u_cmp_gt,
1587 		u_cmp_ge,
1588 		u_cmp_lt,
1589 		u_cmp_le,
1590 		NULL,				/* cmp_bitwise_and */
1591 		NULL,				/* cmp_contains */
1592 		NULL,				/* cmp_matches */
1593 
1594 		NULL,				/* len */
1595 		NULL,				/* slice */
1596 	};
1597 
1598 	static ftype_t eui64_type = {
1599 		FT_EUI64,			/* ftype */
1600 		"FT_EUI64",			/* name */
1601 		"EUI64 address",		/* pretty_name */
1602 		FT_EUI64_LEN,			/* wire_size */
1603 		int64_fvalue_new,		/* new_value */
1604 		NULL,				/* free_value */
1605 		eui64_from_unparsed,		/* val_from_unparsed */
1606 		NULL,				/* val_from_string */
1607 		eui64_to_repr,			/* val_to_string_repr */
1608 		eui64_repr_len,			/* len_string_repr */
1609 
1610 		{ .set_value_uinteger64 = set_uinteger64 },	/* union set_value */
1611 		{ .get_value_uinteger64 = get_uinteger64 },	/* union get_value */
1612 
1613 		cmp_eq64,
1614 		cmp_ne64,
1615 		u_cmp_gt64,
1616 		u_cmp_ge64,
1617 		u_cmp_lt64,
1618 		u_cmp_le64,
1619 		cmp_bitwise_and64,
1620 		NULL,				/* cmp_contains */
1621 		NULL,				/* cmp_matches */
1622 
1623 		NULL,
1624 		NULL,
1625 	};
1626 
1627 	ftype_register(FT_CHAR, &char_type);
1628 	ftype_register(FT_UINT8, &uint8_type);
1629 	ftype_register(FT_UINT16, &uint16_type);
1630 	ftype_register(FT_UINT24, &uint24_type);
1631 	ftype_register(FT_UINT32, &uint32_type);
1632 	ftype_register(FT_UINT40, &uint40_type);
1633 	ftype_register(FT_UINT48, &uint48_type);
1634 	ftype_register(FT_UINT56, &uint56_type);
1635 	ftype_register(FT_UINT64, &uint64_type);
1636 	ftype_register(FT_INT8, &int8_type);
1637 	ftype_register(FT_INT16, &int16_type);
1638 	ftype_register(FT_INT24, &int24_type);
1639 	ftype_register(FT_INT32, &int32_type);
1640 	ftype_register(FT_INT40, &int40_type);
1641 	ftype_register(FT_INT48, &int48_type);
1642 	ftype_register(FT_INT56, &int56_type);
1643 	ftype_register(FT_INT64, &int64_type);
1644 	ftype_register(FT_BOOLEAN, &boolean_type);
1645 	ftype_register(FT_IPXNET, &ipxnet_type);
1646 	ftype_register(FT_FRAMENUM, &framenum_type);
1647 	ftype_register(FT_EUI64, &eui64_type);
1648 }
1649 
1650 /*
1651  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1652  *
1653  * Local variables:
1654  * c-basic-offset: 8
1655  * tab-width: 8
1656  * indent-tabs-mode: t
1657  * End:
1658  *
1659  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1660  * :indentSize=8:tabSize=8:noTabs=false:
1661  */
1662