4 * Ethereal - Network traffic analyzer
5 * By Gerald Combs <gerald@ethereal.com>
6 * Copyright 2001 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include <ftypes-int.h>
30 #include <epan/addr_resolv.h>
31 #include <epan/strutil.h>
35 #define CMP_MATCHES cmp_matches
37 #define CMP_MATCHES NULL
44 bytes_fvalue_new(fvalue_t *fv)
46 fv->value.bytes = NULL;
50 bytes_fvalue_free(fvalue_t *fv)
52 if (fv->value.bytes) {
53 g_byte_array_free(fv->value.bytes, TRUE);
60 bytes_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
62 g_assert(already_copied);
64 /* Free up the old value, if we have one */
65 bytes_fvalue_free(fv);
67 fv->value.bytes = value;
71 bytes_repr_len(fvalue_t *fv, ftrepr_t rtype _U_)
73 /* 3 bytes for each byte of the byte "NN:" minus 1 byte
74 * as there's no trailing ":". */
75 return fv->value.bytes->len * 3 - 1;
79 oid_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_)
81 /* more exact computation will come later */
82 return fv->value.bytes->len * 3 + 16;
86 oid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
88 oid_to_str_buf(fv->value.bytes->data, fv->value.bytes->len, buf, oid_repr_len(fv, rtype));
92 bytes_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
98 c = fv->value.bytes->data;
101 for (i = 0; i < fv->value.bytes->len; i++) {
103 sprintf(write_cursor, "%02x", *c++);
107 sprintf(write_cursor, ":%02x", *c++);
114 common_fvalue_set(fvalue_t *fv, guint8* data, guint len)
116 /* Free up the old value, if we have one */
117 bytes_fvalue_free(fv);
119 fv->value.bytes = g_byte_array_new();
120 g_byte_array_append(fv->value.bytes, data, len);
124 ether_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
126 g_assert(!already_copied);
127 common_fvalue_set(fv, value, ETHER_LEN);
131 ipv6_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
133 g_assert(!already_copied);
134 common_fvalue_set(fv, value, IPv6_LEN);
138 oid_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
140 g_assert(already_copied);
142 /* Free up the old value, if we have one */
143 bytes_fvalue_free(fv);
145 fv->value.bytes = value;
150 value_get(fvalue_t *fv)
152 return fv->value.bytes->data;
156 bytes_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
160 bytes = g_byte_array_new();
162 g_byte_array_append(bytes, (guint8 *)s, strlen(s));
164 /* Free up the old value, if we have one */
165 bytes_fvalue_free(fv);
166 fv->value.bytes = bytes;
172 bytes_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
177 bytes = g_byte_array_new();
179 res = hex_str_to_bytes(s, bytes, TRUE);
183 logfunc("\"%s\" is not a valid byte string.", s);
184 g_byte_array_free(bytes, TRUE);
188 /* Free up the old value, if we have one */
189 bytes_fvalue_free(fv);
191 fv->value.bytes = bytes;
197 ether_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value, LogFunc logfunc)
202 * Don't log a message if this fails; we'll try looking it
203 * up as an Ethernet host name if it does, and if that fails,
204 * we'll log a message.
206 if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
207 if (fv->value.bytes->len > ETHER_LEN) {
208 logfunc("\"%s\" contains too many bytes to be a valid Ethernet address.",
212 else if (fv->value.bytes->len < ETHER_LEN && !allow_partial_value) {
213 logfunc("\"%s\" contains too few bytes to be a valid Ethernet address.",
221 mac = get_ether_addr(s);
223 logfunc("\"%s\" is not a valid hostname or Ethernet address.",
228 ether_fvalue_set(fv, mac, FALSE);
233 ipv6_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
237 if (!get_host_ipaddr6(s, (struct e_in6_addr*)buffer)) {
238 logfunc("\"%s\" is not a valid hostname or IPv6 address.", s);
242 ipv6_fvalue_set(fv, buffer, FALSE);
247 ipv6_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_)
250 * 39 characters for "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX".
256 ipv6_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
258 ip6_to_str_buf((struct e_in6_addr *)fv->value.bytes->data, buf);
262 oid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
269 * Don't log a message if this fails; we'll try looking it
270 * up as an OID if it does, and if that fails,
271 * we'll log a message.
273 if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
277 bytes = g_byte_array_new();
278 res = oid_str_to_bytes(s, bytes);
281 logfunc("\"%s\" is not a valid OBJECT IDENTIFIER.", s);
282 g_byte_array_free(bytes, TRUE);
286 /* Free up the old value, if we have one */
287 bytes_fvalue_free(fv);
288 fv->value.bytes = bytes;
296 return fv->value.bytes->len;
300 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
304 data = fv->value.bytes->data + offset;
306 g_byte_array_append(bytes, data, length);
311 cmp_eq(fvalue_t *fv_a, fvalue_t *fv_b)
313 GByteArray *a = fv_a->value.bytes;
314 GByteArray *b = fv_b->value.bytes;
316 if (a->len != b->len) {
320 return (memcmp(a->data, b->data, a->len) == 0);
325 cmp_ne(fvalue_t *fv_a, fvalue_t *fv_b)
327 GByteArray *a = fv_a->value.bytes;
328 GByteArray *b = fv_b->value.bytes;
330 if (a->len != b->len) {
334 return (memcmp(a->data, b->data, a->len) != 0);
339 cmp_gt(fvalue_t *fv_a, fvalue_t *fv_b)
341 GByteArray *a = fv_a->value.bytes;
342 GByteArray *b = fv_b->value.bytes;
344 if (a->len > b->len) {
348 if (a->len < b->len) {
352 return (memcmp(a->data, b->data, a->len) > 0);
356 cmp_ge(fvalue_t *fv_a, fvalue_t *fv_b)
358 GByteArray *a = fv_a->value.bytes;
359 GByteArray *b = fv_b->value.bytes;
361 if (a->len > b->len) {
365 if (a->len < b->len) {
369 return (memcmp(a->data, b->data, a->len) >= 0);
373 cmp_lt(fvalue_t *fv_a, fvalue_t *fv_b)
375 GByteArray *a = fv_a->value.bytes;
376 GByteArray *b = fv_b->value.bytes;
378 if (a->len < b->len) {
382 if (a->len > b->len) {
386 return (memcmp(a->data, b->data, a->len) < 0);
390 cmp_le(fvalue_t *fv_a, fvalue_t *fv_b)
392 GByteArray *a = fv_a->value.bytes;
393 GByteArray *b = fv_b->value.bytes;
395 if (a->len < b->len) {
399 if (a->len > b->len) {
403 return (memcmp(a->data, b->data, a->len) <= 0);
406 static gboolean cmp_bytes_bitwise_and(fvalue_t *fv_a, fvalue_t *fv_b)
408 GByteArray *a = fv_a->value.bytes;
409 GByteArray *b = fv_b->value.bytes;
411 unsigned char *p_a, *p_b;
413 if (b->len != a->len) {
428 cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
430 GByteArray *a = fv_a->value.bytes;
431 GByteArray *b = fv_b->value.bytes;
433 if (epan_memmem(a->data, a->len, b->data, b->len)) {
443 cmp_matches(fvalue_t *fv_a, fvalue_t *fv_b)
445 GString *a = fv_a->value.gstring;
446 pcre_tuple_t *pcre = fv_b->value.re;
450 /* fv_b is always a FT_PCRE, otherwise the dfilter semcheck() would have
451 * warned us. For the same reason (and because we're using g_malloc()),
452 * fv_b->value.re is not NULL.
454 if (strcmp(fv_b->ftype->name, "FT_PCRE") != 0) {
461 pcre->re, /* Compiled PCRE */
462 pcre->ex, /* PCRE extra from pcre_study() */
463 a->str, /* The data to check for the pattern... */
464 a->len, /* ... and its length */
465 0, /* Start offset within data */
466 options, /* PCRE options */
467 NULL, /* We are not interested in the matched string */
468 0 /* of the pattern; only in success or failure. */
470 /* NOTE - DO NOT g_free(data) */
479 ftype_register_bytes(void)
482 static ftype_t bytes_type = {
483 FT_BYTES, /* ftype */
484 "FT_BYTES", /* name */
485 "sequence of bytes", /* pretty_name */
487 bytes_fvalue_new, /* new_value */
488 bytes_fvalue_free, /* free_value */
489 bytes_from_unparsed, /* val_from_unparsed */
490 bytes_from_string, /* val_from_string */
491 bytes_to_repr, /* val_to_string_repr */
492 bytes_repr_len, /* len_string_repr */
494 bytes_fvalue_set, /* set_value */
495 NULL, /* set_value_integer */
496 NULL, /* set_value_integer64 */
497 NULL, /* set_value_floating */
499 value_get, /* get_value */
500 NULL, /* get_value_integer */
501 NULL, /* get_value_integer64 */
502 NULL, /* get_value_floating */
510 cmp_bytes_bitwise_and,
518 static ftype_t uint_bytes_type = {
519 FT_UINT_BYTES, /* ftype */
520 "FT_UINT_BYTES", /* name */
521 "sequence of bytes", /* pretty_name */
523 bytes_fvalue_new, /* new_value */
524 bytes_fvalue_free, /* free_value */
525 bytes_from_unparsed, /* val_from_unparsed */
526 NULL, /* val_from_string */
527 bytes_to_repr, /* val_to_string_repr */
528 bytes_repr_len, /* len_string_repr */
530 bytes_fvalue_set, /* set_value */
531 NULL, /* set_value_integer */
532 NULL, /* set_value_integer64 */
533 NULL, /* set_value_floating */
535 value_get, /* get_value */
536 NULL, /* get_value_integer */
537 NULL, /* get_value_integer64 */
538 NULL, /* get_value_floating */
546 cmp_bytes_bitwise_and,
548 NULL, /* cmp_matches */
554 static ftype_t ether_type = {
555 FT_ETHER, /* ftype */
556 "FT_ETHER", /* name */
557 "Ethernet or other MAC address",/* pretty_name */
558 ETHER_LEN, /* wire_size */
559 bytes_fvalue_new, /* new_value */
560 bytes_fvalue_free, /* free_value */
561 ether_from_unparsed, /* val_from_unparsed */
562 NULL, /* val_from_string */
563 bytes_to_repr, /* val_to_string_repr */
564 bytes_repr_len, /* len_string_repr */
566 ether_fvalue_set, /* set_value */
567 NULL, /* set_value_integer */
568 NULL, /* set_value_integer64 */
569 NULL, /* set_value_floating */
571 value_get, /* get_value */
572 NULL, /* get_value_integer */
573 NULL, /* get_value_integer64 */
574 NULL, /* get_value_floating */
582 cmp_bytes_bitwise_and,
590 static ftype_t ipv6_type = {
592 "FT_IPv6", /* name */
593 "IPv6 address", /* pretty_name */
594 IPv6_LEN, /* wire_size */
595 bytes_fvalue_new, /* new_value */
596 bytes_fvalue_free, /* free_value */
597 ipv6_from_unparsed, /* val_from_unparsed */
598 NULL, /* val_from_string */
599 ipv6_to_repr, /* val_to_string_repr */
600 ipv6_repr_len, /* len_string_repr */
602 ipv6_fvalue_set, /* set_value */
603 NULL, /* set_value_integer */
604 NULL, /* set_value_integer64 */
605 NULL, /* set_value_floating */
607 value_get, /* get_value */
608 NULL, /* get_value_integer */
609 NULL, /* get_value_integer64 */
610 NULL, /* get_value_floating */
618 cmp_bytes_bitwise_and,
620 NULL, /* cmp_matches */
626 static ftype_t oid_type = {
629 "OBJECT IDENTIFIER", /* pretty_name */
631 bytes_fvalue_new, /* new_value */
632 bytes_fvalue_free, /* free_value */
633 oid_from_unparsed, /* val_from_unparsed */
634 NULL, /* val_from_string */
635 oid_to_repr, /* val_to_string_repr */
636 oid_repr_len, /* len_string_repr */
638 oid_fvalue_set, /* set_value */
639 NULL, /* set_value_integer */
640 NULL, /* set_value_integer64 */
641 NULL, /* set_value_floating */
643 value_get, /* get_value */
644 NULL, /* get_value_integer */
645 NULL, /* get_value_integer64 */
646 NULL, /* get_value_floating */
654 cmp_bytes_bitwise_and,
656 NULL, /* cmp_matches */
662 ftype_register(FT_BYTES, &bytes_type);
663 ftype_register(FT_UINT_BYTES, &uint_bytes_type);
664 ftype_register(FT_ETHER, ðer_type);
665 ftype_register(FT_IPv6, &ipv6_type);
666 ftype_register(FT_OID, &oid_type);