aboutsummaryrefslogtreecommitdiffstats
path: root/epan/ftypes
diff options
context:
space:
mode:
Diffstat (limited to 'epan/ftypes')
-rw-r--r--epan/ftypes/.cvsignore4
-rw-r--r--epan/ftypes/Makefile.am52
-rw-r--r--epan/ftypes/ftype-bytes.c386
-rw-r--r--epan/ftypes/ftype-double.c133
-rw-r--r--epan/ftypes/ftype-integer.c417
-rw-r--r--epan/ftypes/ftype-ipv4.c114
-rw-r--r--epan/ftypes/ftype-none.c20
-rw-r--r--epan/ftypes/ftype-string.c198
-rw-r--r--epan/ftypes/ftype-time.c78
-rw-r--r--epan/ftypes/ftype-tvbuff.c84
-rw-r--r--epan/ftypes/ftypes-int.h60
-rw-r--r--epan/ftypes/ftypes.c410
-rw-r--r--epan/ftypes/ftypes.h197
13 files changed, 2153 insertions, 0 deletions
diff --git a/epan/ftypes/.cvsignore b/epan/ftypes/.cvsignore
new file mode 100644
index 0000000000..601c4fbff4
--- /dev/null
+++ b/epan/ftypes/.cvsignore
@@ -0,0 +1,4 @@
+.cvsignore
+.deps
+Makefile
+Makefile.in
diff --git a/epan/ftypes/Makefile.am b/epan/ftypes/Makefile.am
new file mode 100644
index 0000000000..3af23be17c
--- /dev/null
+++ b/epan/ftypes/Makefile.am
@@ -0,0 +1,52 @@
+# Makefile.am
+# Automake file for the GTK interface routines for Ethereal
+#
+# $Id: Makefile.am,v 1.1 2001/02/01 20:21:19 gram Exp $
+#
+# Ethereal - Network traffic analyzer
+# By Gerald Combs <gerald@zing.org>
+# Copyright 1998 Gerald Combs
+#
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# We produce an archive library. In the future, when libethereal is a
+# shared library, this will be linked into libethereal. While libethereal
+# is an archive library, any executable linking against libethereal will
+# also need to link against libftypes.
+noinst_LIBRARIES = libftypes.a
+
+CLEANFILES = \
+ libftypes.a \
+ *~
+
+INCLUDES = -I$(srcdir)/../..
+
+libftypes_a_SOURCES = \
+ ftypes.c \
+ ftypes.h \
+ ftypes-int.h \
+ ftype-bytes.c \
+ ftype-double.c \
+ ftype-integer.c \
+ ftype-ipv4.c \
+ ftype-none.c \
+ ftype-string.c \
+ ftype-time.c \
+ ftype-tvbuff.c
+
+#EXTRA_DIST = \
+# Makefile.nmake
+
diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c
new file mode 100644
index 0000000000..726bbbd707
--- /dev/null
+++ b/epan/ftypes/ftype-bytes.c
@@ -0,0 +1,386 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+#include <string.h>
+#include <ctype.h>
+#include "resolv.h"
+
+#define ETHER_LEN 6
+#define IPv6_LEN 16
+
+static void
+ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length,
+ gboolean little_endian)
+{
+ /* XXX */
+ g_assert_not_reached();
+}
+
+
+static void
+bytes_fvalue_new(fvalue_t *fv)
+{
+ fv->value.bytes = NULL;
+}
+
+void
+bytes_fvalue_free(fvalue_t *fv)
+{
+ if (fv->value.bytes) {
+ g_byte_array_free(fv->value.bytes, TRUE);
+ }
+}
+
+
+static void
+bytes_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ g_assert(already_copied);
+ fv->value.bytes = value;
+}
+
+static void
+common_fvalue_set(fvalue_t *fv, guint8* data, guint len)
+{
+ fv->value.bytes = g_byte_array_new();
+ g_byte_array_append(fv->value.bytes, data, len);
+}
+
+static void
+ether_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ g_assert(!already_copied);
+ common_fvalue_set(fv, value, ETHER_LEN);
+}
+
+static void
+ipv6_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ g_assert(!already_copied);
+ common_fvalue_set(fv, value, IPv6_LEN);
+}
+
+static gpointer
+value_get(fvalue_t *fv)
+{
+ return fv->value.bytes->data;
+}
+
+static gboolean
+is_byte_sep(guint8 c)
+{
+ return (c == '-' || c == ':' || c == '.');
+}
+
+static gboolean
+val_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ GByteArray *bytes;
+ guint8 val;
+ char *p, *q, *punct;
+ char two_digits[3];
+ char one_digit[2];
+ gboolean fail = FALSE;
+
+ bytes = g_byte_array_new();
+
+ p = s;
+ while (*p) {
+ q = p+1;
+ if (*q && isxdigit(*p) && isxdigit(*q)) {
+ two_digits[0] = *p;
+ two_digits[1] = *q;
+ two_digits[2] = '\0';
+
+ val = (guint8) strtoul(two_digits, NULL, 16);
+ g_byte_array_append(bytes, &val, 1);
+ punct = q + 1;
+ if (*punct) {
+ if (is_byte_sep(*punct)) {
+ p = punct + 1;
+ continue;
+ }
+ else {
+ fail = TRUE;
+ break;
+ }
+ }
+ else {
+ p = punct;
+ continue;
+ }
+ }
+ else if (*q && isxdigit(*p) && is_byte_sep(*q)) {
+ one_digit[0] = *p;
+ one_digit[1] = '\0';
+
+ val = (guint8) strtoul(one_digit, NULL, 16);
+ g_byte_array_append(bytes, &val, 1);
+ p = q + 1;
+ continue;
+ }
+ else if (!*q && isxdigit(*p)) {
+ one_digit[0] = *p;
+ one_digit[1] = '\0';
+
+ val = (guint8) strtoul(one_digit, NULL, 16);
+ g_byte_array_append(bytes, &val, 1);
+ p = q;
+ continue;
+ }
+ else {
+ fail = TRUE;
+ break;
+ }
+ }
+
+ if (fail) {
+ g_byte_array_free(bytes, TRUE);
+ return FALSE;
+ }
+
+ fv->value.bytes = bytes;
+
+
+ return TRUE;
+}
+
+static gboolean
+ether_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ guint8 *mac;
+
+ if (val_from_string(fv, s, log)) {
+ return TRUE;
+ }
+
+ mac = get_ether_addr(s);
+ if (!mac) {
+ return FALSE;
+ }
+
+ ether_fvalue_set(fv, mac, FALSE);
+ return TRUE;
+}
+
+static gboolean
+ipv6_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ guint8 buffer[16];
+
+ if (!get_host_ipaddr6(s, (struct e_in6_addr*)buffer)) {
+ return FALSE;
+ }
+
+ ipv6_fvalue_set(fv, buffer, FALSE);
+ return TRUE;
+}
+
+static guint
+len(fvalue_t *fv)
+{
+ return fv->value.bytes->len;
+}
+
+static void
+slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
+{
+ guint8* data;
+
+ data = fv->value.bytes->data + offset;
+
+ g_byte_array_append(bytes, data, length);
+}
+
+
+static gboolean
+cmp_eq(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (a->len != b->len) {
+ return FALSE;
+ }
+
+ return (memcmp(a->data, b->data, a->len) == 0);
+}
+
+
+static gboolean
+cmp_ne(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (a->len != b->len) {
+ return FALSE;
+ }
+
+ return (memcmp(a->data, b->data, a->len) != 0);
+}
+
+
+static gboolean
+cmp_gt(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (a->len > b->len) {
+ return TRUE;
+ }
+
+ if (a->len < b->len) {
+ return FALSE;
+ }
+
+ return (memcmp(a->data, b->data, a->len) > 0);
+}
+
+static gboolean
+cmp_ge(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (a->len > b->len) {
+ return TRUE;
+ }
+
+ if (a->len < b->len) {
+ return FALSE;
+ }
+
+ return (memcmp(a->data, b->data, a->len) >= 0);
+}
+
+static gboolean
+cmp_lt(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (a->len < b->len) {
+ return TRUE;
+ }
+
+ if (a->len > b->len) {
+ return FALSE;
+ }
+
+ return (memcmp(a->data, b->data, a->len) < 0);
+}
+
+static gboolean
+cmp_le(fvalue_t *fv_a, fvalue_t *fv_b)
+{
+ GByteArray *a = fv_a->value.bytes;
+ GByteArray *b = fv_b->value.bytes;
+
+ if (a->len < b->len) {
+ return TRUE;
+ }
+
+ if (a->len > b->len) {
+ return FALSE;
+ }
+
+ return (memcmp(a->data, b->data, a->len) <= 0);
+}
+
+void
+ftype_register_bytes(void)
+{
+
+ static ftype_t bytes_type = {
+ "FT_BYTES",
+ "sequence of bytes",
+ 0,
+ bytes_fvalue_new,
+ bytes_fvalue_free,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ bytes_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+
+ len,
+ slice,
+ };
+
+ static ftype_t ether_type = {
+ "FT_ETHER",
+ "Ethernet or other MAC address",
+ ETHER_LEN,
+ bytes_fvalue_new,
+ bytes_fvalue_free,
+ ftype_from_tvbuff,
+ ether_from_string,
+
+ ether_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+
+ len,
+ slice,
+ };
+
+ static ftype_t ipv6_type = {
+ "FT_IPv6",
+ "IPv6 address",
+ IPv6_LEN,
+ bytes_fvalue_new,
+ bytes_fvalue_free,
+ ftype_from_tvbuff,
+ ipv6_from_string,
+
+ ipv6_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+
+ len,
+ slice,
+ };
+
+ ftype_register(FT_BYTES, &bytes_type);
+ ftype_register(FT_ETHER, &ether_type);
+ ftype_register(FT_IPv6, &ipv6_type);
+}
diff --git a/epan/ftypes/ftype-double.c b/epan/ftypes/ftype-double.c
new file mode 100644
index 0000000000..146794a597
--- /dev/null
+++ b/epan/ftypes/ftype-double.c
@@ -0,0 +1,133 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+#include <stdlib.h>
+#include <math.h>
+#include <errno.h>
+
+static void
+ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length,
+ gboolean little_endian)
+{
+ /* XXX */
+ g_assert_not_reached();
+}
+
+
+static void
+double_fvalue_new(fvalue_t *fv)
+{
+ fv->value.floating = 0.0;
+}
+
+static void
+double_fvalue_set_floating(fvalue_t *fv, gdouble value)
+{
+ fv->value.floating = value;
+}
+
+static double
+value_get_floating(fvalue_t *fv)
+{
+ return fv->value.floating;
+}
+
+static gboolean
+val_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ char *endptr = NULL;
+
+ fv->value.floating = strtod(s, &endptr);
+
+ if (endptr == s || *endptr != '\0') {
+ /* This isn't a valid number. */
+ log("\"%s\" is not a valid number.", s);
+ return FALSE;
+ }
+ if (errno == ERANGE) {
+ if (fv->value.floating == 0) {
+ log("\"%s\" causes floating-point underflow.", s);
+ }
+ else if (fv->value.floating == HUGE_VAL) {
+ log("\"%s\" causes floating-point overflow.", s);
+ }
+ else {
+ log("\"%s\" is not a valid floating-point number.", s);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+cmp_eq(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.floating == b->value.floating;
+}
+
+static gboolean
+cmp_ne(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.floating != b->value.floating;
+}
+
+static gboolean
+cmp_gt(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.floating > b->value.floating;
+}
+
+static gboolean
+cmp_ge(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.floating >= b->value.floating;
+}
+
+static gboolean
+cmp_lt(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.floating < b->value.floating;
+}
+
+static gboolean
+cmp_le(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.floating <= b->value.floating;
+}
+
+void
+ftype_register_double(void)
+{
+
+ static ftype_t double_type = {
+ "FT_DOUBLE",
+ "floating point",
+ 0,
+ double_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ NULL,
+ double_fvalue_set_floating,
+
+ NULL,
+ NULL,
+ value_get_floating,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+ };
+
+ ftype_register(FT_DOUBLE, &double_type);
+}
diff --git a/epan/ftypes/ftype-integer.c b/epan/ftypes/ftype-integer.c
new file mode 100644
index 0000000000..cef237c7ed
--- /dev/null
+++ b/epan/ftypes/ftype-integer.c
@@ -0,0 +1,417 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include "ftypes-int.h"
+#include "resolv.h"
+
+
+static void
+ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length,
+ gboolean little_endian)
+{
+ /* XXX */
+ g_assert_not_reached();
+}
+
+
+static void
+int_fvalue_new(fvalue_t *fv)
+{
+ fv->value.integer = 0;
+}
+
+static void
+set_integer(fvalue_t *fv, guint32 value)
+{
+ fv->value.integer = value;
+}
+
+static guint32
+get_integer(fvalue_t *fv)
+{
+ return fv->value.integer;
+}
+
+static gboolean
+val_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ char *endptr;
+
+ fv->value.integer = strtoul(s, &endptr, 0);
+
+ if (endptr == s || *endptr != '\0') {
+ /* This isn't a valid number. */
+ log("\"%s\" is not a valid number.", s);
+ return FALSE;
+ }
+ if (errno == ERANGE) {
+ if (fv->value.integer == ULONG_MAX) {
+ log("\"%s\" causes an integer overflow.", s);
+ }
+ else {
+ log("\"%s\" is not an integer.", s);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+ipxnet_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ guint32 val;
+ gboolean known;
+
+ if (val_from_string(fv, s, log)) {
+ return TRUE;
+ }
+
+ val = get_ipxnet_addr(s, &known);
+ if (known) {
+ fv->value.integer = val;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+cmp_eq(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.integer == b->value.integer;
+}
+
+static gboolean
+cmp_ne(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.integer != b->value.integer;
+}
+
+static gboolean
+u_cmp_gt(fvalue_t *a, fvalue_t *b)
+{
+ return (int)a->value.integer > (int)b->value.integer;
+}
+
+static gboolean
+u_cmp_ge(fvalue_t *a, fvalue_t *b)
+{
+ return (int)a->value.integer >= (int)b->value.integer;
+}
+
+static gboolean
+u_cmp_lt(fvalue_t *a, fvalue_t *b)
+{
+ return (int)a->value.integer < (int)b->value.integer;
+}
+
+static gboolean
+u_cmp_le(fvalue_t *a, fvalue_t *b)
+{
+ return (int)a->value.integer <= (int)b->value.integer;
+}
+
+static gboolean
+s_cmp_gt(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.integer > b->value.integer;
+}
+
+static gboolean
+s_cmp_ge(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.integer >= b->value.integer;
+}
+
+static gboolean
+s_cmp_lt(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.integer < b->value.integer;
+}
+
+static gboolean
+s_cmp_le(fvalue_t *a, fvalue_t *b)
+{
+ return a->value.integer <= b->value.integer;
+}
+
+/* BOOLEAN-specific */
+
+static void
+boolean_fvalue_new(fvalue_t *fv)
+{
+ fv->value.integer = TRUE;
+}
+
+
+
+
+
+void
+ftype_register_integers(void)
+{
+
+ static ftype_t uint8_type = {
+ "FT_UINT8",
+ "unsigned, 1 byte",
+ 1,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ u_cmp_gt,
+ u_cmp_ge,
+ u_cmp_lt,
+ u_cmp_le,
+ };
+ static ftype_t uint16_type = {
+ "FT_UINT16",
+ "unsigned, 2 bytes",
+ 2,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ u_cmp_gt,
+ u_cmp_ge,
+ u_cmp_lt,
+ u_cmp_le,
+ };
+ static ftype_t uint24_type = {
+ "FT_UINT24",
+ "unsigned, 3 bytes",
+ 3,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ u_cmp_gt,
+ u_cmp_ge,
+ u_cmp_lt,
+ u_cmp_le,
+ };
+ static ftype_t uint32_type = {
+ "FT_UINT32",
+ "unsigned, 4 bytes",
+ 4,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ u_cmp_gt,
+ u_cmp_ge,
+ u_cmp_lt,
+ u_cmp_le,
+ };
+ static ftype_t int8_type = {
+ "FT_INT8",
+ "signed, 1 byte",
+ 1,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ s_cmp_gt,
+ s_cmp_ge,
+ s_cmp_lt,
+ s_cmp_le,
+ };
+ static ftype_t int16_type = {
+ "FT_INT16",
+ "signed, 2 bytes",
+ 2,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ s_cmp_gt,
+ s_cmp_ge,
+ s_cmp_lt,
+ s_cmp_le,
+ };
+ static ftype_t int24_type = {
+ "FT_INT24",
+ "signed, 3 bytes",
+ 3,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ s_cmp_gt,
+ s_cmp_ge,
+ s_cmp_lt,
+ s_cmp_le,
+ };
+ static ftype_t int32_type = {
+ "FT_INT32",
+ "signed, 4 bytes",
+ 4,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ s_cmp_gt,
+ s_cmp_ge,
+ s_cmp_lt,
+ s_cmp_le,
+ };
+ static ftype_t boolean_type = {
+ "FT_BOOLEAN",
+ "Boolean",
+ 0,
+ boolean_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ u_cmp_gt,
+ u_cmp_ge,
+ u_cmp_lt,
+ u_cmp_le,
+ };
+
+ static ftype_t ipxnet_type = {
+ "FT_IPXNET",
+ "IPX network number",
+ 4,
+ int_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ ipxnet_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ NULL,
+ get_integer,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ u_cmp_gt,
+ u_cmp_ge,
+ u_cmp_lt,
+ u_cmp_le,
+ };
+
+
+ ftype_register(FT_UINT8, &uint8_type);
+ ftype_register(FT_UINT16, &uint16_type);
+ ftype_register(FT_UINT24, &uint24_type);
+ ftype_register(FT_UINT32, &uint32_type);
+ ftype_register(FT_INT8, &int8_type);
+ ftype_register(FT_INT16, &int16_type);
+ ftype_register(FT_INT24, &int24_type);
+ ftype_register(FT_INT32, &int32_type);
+ ftype_register(FT_BOOLEAN, &boolean_type);
+ ftype_register(FT_IPXNET, &ipxnet_type);
+}
diff --git a/epan/ftypes/ftype-ipv4.c b/epan/ftypes/ftype-ipv4.c
new file mode 100644
index 0000000000..eae5677a25
--- /dev/null
+++ b/epan/ftypes/ftype-ipv4.c
@@ -0,0 +1,114 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+#include "ipv4.h"
+#include "resolv.h"
+
+static void
+ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length,
+ gboolean little_endian)
+{
+ /* XXX */
+ g_assert_not_reached();
+}
+
+
+
+static void
+set_integer(fvalue_t *fv, guint32 value)
+{
+ ipv4_addr_set_net_order_addr(&(fv->value.ipv4), value);
+ ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32);
+}
+
+static gpointer
+value_get(fvalue_t *fv)
+{
+ return &(fv->value.ipv4);
+}
+
+static gboolean
+val_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ guint32 addr;
+
+ if (!get_host_ipaddr(s, &addr)) {
+ log("\"%s\" is not a valid hostname or IPv4 address.", s);
+ return FALSE;
+ }
+ ipv4_addr_set_host_order_addr(&(fv->value.ipv4), addr);
+ /*ipv4_addr_set_netmask_bits(&node->value.ipv4, nmask_bits);*/
+ ipv4_addr_set_netmask_bits(&(fv->value.ipv4), 32);
+ return TRUE;
+}
+
+static gboolean
+cmp_eq(fvalue_t *a, fvalue_t *b)
+{
+ return ipv4_addr_eq(&a->value.ipv4, &b->value.ipv4);
+}
+
+static gboolean
+cmp_ne(fvalue_t *a, fvalue_t *b)
+{
+ return ipv4_addr_ne(&a->value.ipv4, &b->value.ipv4);
+}
+
+static gboolean
+cmp_gt(fvalue_t *a, fvalue_t *b)
+{
+ return ipv4_addr_gt(&a->value.ipv4, &b->value.ipv4);
+}
+
+static gboolean
+cmp_ge(fvalue_t *a, fvalue_t *b)
+{
+ return ipv4_addr_ge(&a->value.ipv4, &b->value.ipv4);
+}
+
+static gboolean
+cmp_lt(fvalue_t *a, fvalue_t *b)
+{
+ return ipv4_addr_lt(&a->value.ipv4, &b->value.ipv4);
+}
+
+static gboolean
+cmp_le(fvalue_t *a, fvalue_t *b)
+{
+ return ipv4_addr_le(&a->value.ipv4, &b->value.ipv4);
+}
+
+void
+ftype_register_ipv4(void)
+{
+
+ static ftype_t ipv4_type = {
+ "FT_IPv4",
+ "IPv4 address",
+ 4,
+ NULL,
+ NULL,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ NULL,
+ set_integer,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+ };
+
+ ftype_register(FT_IPv4, &ipv4_type);
+}
diff --git a/epan/ftypes/ftype-none.c b/epan/ftypes/ftype-none.c
new file mode 100644
index 0000000000..1bb64a3759
--- /dev/null
+++ b/epan/ftypes/ftype-none.c
@@ -0,0 +1,20 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+
+
+void
+ftype_register_none(void)
+{
+
+ static ftype_t none_type = {
+ "FT_NONE",
+ "label",
+ 0,
+ };
+
+ ftype_register(FT_NONE, &none_type);
+}
diff --git a/epan/ftypes/ftype-string.c b/epan/ftypes/ftype-string.c
new file mode 100644
index 0000000000..38ce87faa0
--- /dev/null
+++ b/epan/ftypes/ftype-string.c
@@ -0,0 +1,198 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+#include <string.h>
+
+static void
+ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length,
+ gboolean little_endian)
+{
+ /* XXX */
+ g_assert_not_reached();
+}
+
+
+static void
+string_fvalue_new(fvalue_t *fv)
+{
+ fv->value.string = NULL;
+}
+
+static void
+string_fvalue_free(fvalue_t *fv)
+{
+ if (fv->value.string) {
+ g_free(fv->value.string);
+ }
+}
+
+static void
+string_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ if (already_copied) {
+ fv->value.string = value;
+ }
+ else {
+ fv->value.string = g_strdup(value);
+ }
+}
+
+static gpointer
+value_get(fvalue_t *fv)
+{
+ return fv->value.string;
+}
+
+static gboolean
+val_from_string(fvalue_t *fv, char *s, LogFunc log)
+{
+ fv->value.string = g_strdup(s);
+ return TRUE;
+}
+
+static guint
+len(fvalue_t *fv)
+{
+ return strlen(fv->value.string);
+}
+
+static void
+slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
+{
+ guint8* data;
+
+ data = fv->value.string + offset;
+
+ g_byte_array_append(bytes, data, length);
+}
+
+
+static gboolean
+cmp_eq(fvalue_t *a, fvalue_t *b)
+{
+ return (strcmp(a->value.string, b->value.string) == 0);
+}
+
+static gboolean
+cmp_ne(fvalue_t *a, fvalue_t *b)
+{
+ return (strcmp(a->value.string, b->value.string) != 0);
+}
+
+static gboolean
+cmp_gt(fvalue_t *a, fvalue_t *b)
+{
+ return (strcmp(a->value.string, b->value.string) > 0);
+}
+
+static gboolean
+cmp_ge(fvalue_t *a, fvalue_t *b)
+{
+ return (strcmp(a->value.string, b->value.string) >= 0);
+}
+
+static gboolean
+cmp_lt(fvalue_t *a, fvalue_t *b)
+{
+ return (strcmp(a->value.string, b->value.string) < 0);
+}
+
+static gboolean
+cmp_le(fvalue_t *a, fvalue_t *b)
+{
+ return (strcmp(a->value.string, b->value.string) <= 0);
+}
+
+void
+ftype_register_string(void)
+{
+
+ static ftype_t string_type = {
+ "FT_STRING",
+ "character string",
+ 0,
+ string_fvalue_new,
+ string_fvalue_free,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ string_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+
+ len,
+ slice,
+ };
+ static ftype_t stringz_type = {
+ "FT_STRINGZ",
+ "character string",
+ 0,
+ string_fvalue_new,
+ string_fvalue_free,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ string_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+
+ len,
+ slice,
+ };
+ static ftype_t uint_string_type = {
+ "FT_UINT_STRING",
+ "character string",
+ 0,
+ string_fvalue_new,
+ string_fvalue_free,
+ ftype_from_tvbuff,
+ val_from_string,
+
+ string_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ cmp_eq,
+ cmp_ne,
+ cmp_gt,
+ cmp_ge,
+ cmp_lt,
+ cmp_le,
+
+ len,
+ slice,
+ };
+
+ ftype_register(FT_STRING, &string_type);
+ ftype_register(FT_STRINGZ, &stringz_type);
+ ftype_register(FT_UINT_STRING, &uint_string_type);
+}
diff --git a/epan/ftypes/ftype-time.c b/epan/ftypes/ftype-time.c
new file mode 100644
index 0000000000..6eb2a3d4cb
--- /dev/null
+++ b/epan/ftypes/ftype-time.c
@@ -0,0 +1,78 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+
+static void
+ftype_from_tvbuff(field_info *fi, tvbuff_t *tvb, int start, int length,
+ gboolean little_endian)
+{
+ /* XXX */
+ g_assert_not_reached();
+}
+
+
+static void
+time_fvalue_new(fvalue_t *fv)
+{
+ fv->value.time.tv_sec = 0;
+ fv->value.time.tv_usec = 0;
+}
+
+static void
+time_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ g_assert(!already_copied);
+ memcpy(&(fv->value.time), value, sizeof(struct timeval));
+}
+
+static gpointer
+value_get(fvalue_t *fv)
+{
+ return &(fv->value.time);
+}
+
+void
+ftype_register_time(void)
+{
+
+ static ftype_t abstime_type = {
+ "FT_ABSOLUTE_TIME",
+ "date/time",
+ 0,
+ time_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ NULL,
+
+ time_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL
+ };
+ static ftype_t reltime_type = {
+ "FT_RELATIVE_TIME",
+ "time offset",
+ 0,
+ time_fvalue_new,
+ NULL,
+ ftype_from_tvbuff,
+ NULL,
+
+ time_fvalue_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL
+ };
+
+ ftype_register(FT_ABSOLUTE_TIME, &abstime_type);
+ ftype_register(FT_RELATIVE_TIME, &reltime_type);
+}
diff --git a/epan/ftypes/ftype-tvbuff.c b/epan/ftypes/ftype-tvbuff.c
new file mode 100644
index 0000000000..e9617ca607
--- /dev/null
+++ b/epan/ftypes/ftype-tvbuff.c
@@ -0,0 +1,84 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+#include "gdebug.h"
+
+static void
+value_new(fvalue_t *fv)
+{
+ fv->value.tvb = NULL;
+}
+
+
+static void
+value_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ g_assert(already_copied);
+ fv->value.tvb = value;
+}
+
+static gpointer
+value_get(fvalue_t *fv)
+{
+ return fv->value.tvb;
+}
+
+static guint
+len(fvalue_t *fv)
+{
+ if (fv->value.tvb)
+ return tvb_length(fv->value.tvb);
+ else
+ return 0;
+}
+
+static void
+slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
+{
+ guint8* data;
+
+ if (fv->value.tvb) {
+ data = tvb_get_ptr(fv->value.tvb, offset, length);
+ g_byte_array_append(bytes, data, length);
+ }
+}
+
+void
+ftype_register_tvbuff(void)
+{
+
+ static ftype_t protocol_type = {
+ "FT_PROTOCOL",
+ "protocol",
+ 0,
+ value_new,
+ NULL,
+ NULL,
+ NULL,
+
+ value_set,
+ NULL,
+ NULL,
+
+ value_get,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ len,
+ slice,
+
+ };
+
+
+ ftype_register(FT_PROTOCOL, &protocol_type);
+}
diff --git a/epan/ftypes/ftypes-int.h b/epan/ftypes/ftypes-int.h
new file mode 100644
index 0000000000..4e6ce75bee
--- /dev/null
+++ b/epan/ftypes/ftypes-int.h
@@ -0,0 +1,60 @@
+#ifndef FTYPES_INT_H
+#define FTYPES_INT_H
+
+#include "packet.h"
+#include "ftypes.h"
+
+typedef void (*FtypeFromTvbuffFunc)(field_info*, tvbuff_t*, int, int, gboolean);
+typedef void (*FvalueNewFunc)(fvalue_t*);
+typedef void (*FvalueFreeFunc)(fvalue_t*);
+
+typedef gboolean (*FvalueFromString)(fvalue_t*, char*, LogFunc);
+
+typedef void (*FvalueSetFunc)(fvalue_t*, gpointer, gboolean);
+typedef void (*FvalueSetIntegerFunc)(fvalue_t*, guint32);
+typedef void (*FvalueSetFloatingFunc)(fvalue_t*, gdouble);
+
+typedef gpointer (*FvalueGetFunc)(fvalue_t*);
+typedef guint32 (*FvalueGetIntegerFunc)(fvalue_t*);
+typedef double (*FvalueGetFloatingFunc)(fvalue_t*);
+
+typedef gboolean (*FvalueCmp)(fvalue_t*, fvalue_t*);
+
+typedef guint (*FvalueLen)(fvalue_t*);
+typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint, guint);
+
+struct _ftype_t {
+ const char *name;
+ const char *pretty_name;
+ int wire_size;
+ FvalueNewFunc new_value;
+ FvalueFreeFunc free_value;
+ FtypeFromTvbuffFunc from_tvbuff;
+ FvalueFromString val_from_string;
+
+ /* could be union */
+ FvalueSetFunc set_value;
+ FvalueSetIntegerFunc set_value_integer;
+ FvalueSetFloatingFunc set_value_floating;
+
+ /* could be union */
+ FvalueGetFunc get_value;
+ FvalueGetIntegerFunc get_value_integer;
+ FvalueGetFloatingFunc get_value_floating;
+
+ FvalueCmp cmp_eq;
+ FvalueCmp cmp_ne;
+ FvalueCmp cmp_gt;
+ FvalueCmp cmp_ge;
+ FvalueCmp cmp_lt;
+ FvalueCmp cmp_le;
+
+ FvalueLen len;
+ FvalueSlice slice;
+};
+
+
+void
+ftype_register(enum ftenum ftype, ftype_t *ft);
+
+#endif
diff --git a/epan/ftypes/ftypes.c b/epan/ftypes/ftypes.c
new file mode 100644
index 0000000000..7234008d53
--- /dev/null
+++ b/epan/ftypes/ftypes.c
@@ -0,0 +1,410 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ftypes-int.h>
+
+/* Keep track of ftype_t's via their ftenum number */
+static ftype_t* type_list[FT_NUM_TYPES];
+
+/* Space for quickly allocating/de-allocating fvalue_t's */
+static GMemChunk *gmc_fvalue = NULL;
+
+/* These are the ftype registration functions that need to be called.
+ * This list and the initialization function could be produced
+ * via a script, like the dissector registration, but there's so few
+ * that I don't mind doing it by hand for now. */
+void ftype_register_bytes(void);
+void ftype_register_double(void);
+void ftype_register_integers(void);
+void ftype_register_ipv4(void);
+void ftype_register_none(void);
+void ftype_register_string(void);
+void ftype_register_time(void);
+void ftype_register_tvbuff(void);
+
+/* Initialize the ftype module. */
+void
+ftypes_initialize(void)
+{
+ ftype_register_bytes();
+ ftype_register_double();
+ ftype_register_integers();
+ ftype_register_ipv4();
+ ftype_register_none();
+ ftype_register_string();
+ ftype_register_time();
+ ftype_register_tvbuff();
+
+ if (gmc_fvalue)
+ g_mem_chunk_destroy(gmc_fvalue);
+
+ gmc_fvalue = g_mem_chunk_new("gmc_fvalue", sizeof(fvalue_t),
+ 200 * sizeof(fvalue_t), G_ALLOC_AND_FREE);
+}
+
+void
+ftypes_cleanup(void)
+{
+ if (gmc_fvalue)
+ g_mem_chunk_destroy(gmc_fvalue);
+}
+
+
+
+/* Each ftype_t is registered via this function */
+void
+ftype_register(enum ftenum ftype, ftype_t *ft)
+{
+ /* Check input */
+ g_assert(ftype >= 0);
+ g_assert(ftype < FT_NUM_TYPES);
+
+ /* Don't re-register. */
+ g_assert(type_list[ftype] == NULL);
+
+ type_list[ftype] = ft;
+}
+
+/* Given an ftenum number, return an ftype_t* */
+static ftype_t*
+ftype_lookup(enum ftenum ftype)
+{
+ ftype_t* result;
+
+ /* Check input */
+ g_assert(ftype >= 0);
+ g_assert(ftype < FT_NUM_TYPES);
+
+ result = type_list[ftype];
+
+ /* Check output. */
+ g_assert(result != NULL);
+
+ return result;
+}
+
+
+/* Returns a string representing the name of the type. Useful
+ * for glossary production. */
+const char*
+ftype_name(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->name;
+}
+
+const char*
+ftype_pretty_name(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->pretty_name;
+}
+
+int
+ftype_length(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->wire_size;
+}
+
+gboolean
+ftype_can_slice(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->slice ? TRUE : FALSE;
+}
+
+gboolean
+ftype_can_eq(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_eq ? TRUE : FALSE;
+}
+
+gboolean
+ftype_can_ne(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_ne ? TRUE : FALSE;
+}
+
+gboolean
+ftype_can_gt(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_gt ? TRUE : FALSE;
+}
+
+gboolean
+ftype_can_ge(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_ge ? TRUE : FALSE;
+}
+
+gboolean
+ftype_can_lt(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_lt ? TRUE : FALSE;
+}
+
+gboolean
+ftype_can_le(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ ft = ftype_lookup(ftype);
+ return ft->cmp_le ? TRUE : FALSE;
+}
+
+/* ---------------------------------------------------------- */
+
+/* Allocate and initialize an fvalue_t, given an ftype */
+fvalue_t*
+fvalue_new(ftenum_t ftype)
+{
+ fvalue_t *fv;
+ ftype_t *ft;
+ FvalueNewFunc new_value;
+
+ fv = g_mem_chunk_alloc(gmc_fvalue);
+
+ ft = ftype_lookup(ftype);
+ fv->ftype = ft;
+
+ new_value = ft->new_value;
+ if (new_value) {
+ new_value(fv);
+ }
+
+ return fv;
+}
+
+/* Free all memory used by an fvalue_t */
+void
+fvalue_free(fvalue_t *fv)
+{
+ FvalueFreeFunc free_value;
+
+ free_value = fv->ftype->free_value;
+ if (free_value) {
+ free_value(fv);
+ }
+
+ g_mem_chunk_free(gmc_fvalue, fv);
+}
+
+
+
+fvalue_t*
+fvalue_from_string(ftenum_t ftype, char *s, LogFunc log)
+{
+ fvalue_t *fv;
+
+ fv = fvalue_new(ftype);
+ if (fv->ftype->val_from_string) {
+ if (fv->ftype->val_from_string(fv, s, log)) {
+ return fv;
+ }
+ }
+ else {
+ log("\"%s\" cannot be converted to %s.",
+ s, ftype_pretty_name(ftype));
+ }
+ fvalue_free(fv);
+ return NULL;
+}
+
+const char*
+fvalue_type_name(fvalue_t *fv)
+{
+ return fv->ftype->name;
+}
+
+
+guint
+fvalue_length(fvalue_t *fv)
+{
+ if (fv->ftype->len)
+ return fv->ftype->len(fv);
+ else
+ return fv->ftype->wire_size;
+}
+
+/* Returns a new FT_BYTES fvalue_t* if possible, otherwise NULL */
+fvalue_t*
+fvalue_slice(fvalue_t *fv, gint start, gint end)
+{
+ GByteArray *bytes;
+ guint data_length, abs_end;
+ guint offset=0, length=0;
+ fvalue_t *new_fv;
+
+ if (!fv->ftype->slice) {
+ return NULL;
+ }
+
+ data_length = fvalue_length(fv);
+ bytes = g_byte_array_new();
+
+ /* Find absolute start position (offset) */
+ if (start < 0) {
+ start = data_length + start;
+ if (start < 0) {
+ offset = 0;
+ }
+ else {
+ offset = start;
+ }
+ }
+ else {
+ offset = start;
+ }
+
+ /* Limit the offset value */
+ if (offset > data_length) {
+ offset = data_length;
+ }
+
+ /* Find absolute end position (abs_end) */
+ if (end < 0) {
+ end = data_length + end;
+ if (end < 0) {
+ abs_end = 0;
+ }
+ else {
+ abs_end = end;
+ }
+ }
+ else {
+ abs_end = end;
+ }
+
+ /* Limit the abs_end value */
+ if (abs_end > data_length) {
+ abs_end = data_length;
+ }
+
+ /* Does end position occur *after* start position? */
+ if (abs_end > offset) {
+ length = abs_end - offset;
+ fv->ftype->slice(fv, bytes, offset, length);
+ }
+
+ new_fv = fvalue_new(FT_BYTES);
+ fvalue_set(new_fv, bytes, TRUE);
+ return new_fv;
+}
+
+
+void
+fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+ g_assert(fv->ftype->set_value);
+ fv->ftype->set_value(fv, value, already_copied);
+}
+
+void
+fvalue_set_integer(fvalue_t *fv, guint32 value)
+{
+ g_assert(fv->ftype->set_value_integer);
+ fv->ftype->set_value_integer(fv, value);
+}
+
+void
+fvalue_set_floating(fvalue_t *fv, gdouble value)
+{
+ g_assert(fv->ftype->set_value_floating);
+ fv->ftype->set_value_floating(fv, value);
+}
+
+
+gpointer
+fvalue_get(fvalue_t *fv)
+{
+ g_assert(fv->ftype->get_value);
+ return fv->ftype->get_value(fv);
+}
+
+guint32
+fvalue_get_integer(fvalue_t *fv)
+{
+ g_assert(fv->ftype->get_value_integer);
+ return fv->ftype->get_value_integer(fv);
+}
+
+double
+fvalue_get_floating(fvalue_t *fv)
+{
+ g_assert(fv->ftype->get_value_floating);
+ return fv->ftype->get_value_floating(fv);
+}
+
+gboolean
+fvalue_eq(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_eq);
+ return a->ftype->cmp_eq(a, b);
+}
+
+gboolean
+fvalue_ne(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_ne);
+ return a->ftype->cmp_ne(a, b);
+}
+
+gboolean
+fvalue_gt(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_gt);
+ return a->ftype->cmp_gt(a, b);
+}
+
+gboolean
+fvalue_ge(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_ge);
+ return a->ftype->cmp_ge(a, b);
+}
+
+gboolean
+fvalue_lt(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_lt);
+ return a->ftype->cmp_lt(a, b);
+}
+
+gboolean
+fvalue_le(fvalue_t *a, fvalue_t *b)
+{
+ /* XXX - check compatibility of a and b */
+ g_assert(a->ftype->cmp_le);
+ return a->ftype->cmp_le(a, b);
+}
diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h
new file mode 100644
index 0000000000..1431f35427
--- /dev/null
+++ b/epan/ftypes/ftypes.h
@@ -0,0 +1,197 @@
+/* ftypes.h
+ * Definitions for field types
+ *
+ * $Id: ftypes.h,v 1.1 2001/02/01 20:21:19 gram Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 2001 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef FTYPES_H
+#define FTYPES_H
+
+#include <glib.h>
+
+
+/* field types */
+enum ftenum {
+ FT_NONE, /* used for text labels with no value */
+ FT_PROTOCOL,
+ FT_BOOLEAN, /* TRUE and FALSE come from <glib.h> */
+ FT_UINT8,
+ FT_UINT16,
+ FT_UINT24, /* really a UINT32, but displayed as 3 hex-digits if FD_HEX*/
+ FT_UINT32,
+ FT_INT8,
+ FT_INT16,
+ FT_INT24,
+ FT_INT32,
+ FT_DOUBLE,
+ FT_ABSOLUTE_TIME,
+ FT_RELATIVE_TIME,
+ FT_STRING,
+ FT_STRINGZ, /* for use with proto_tree_add_item() */
+ FT_UINT_STRING, /* for use with proto_tree_add_item() */
+ FT_ETHER,
+ FT_BYTES,
+ FT_IPv4,
+ FT_IPv6,
+ FT_IPXNET,
+/* FT_TEXT_ONLY,*/ /* non-filterable, used when converting ethereal
+ from old-style proto_tree to new-style proto_tree */
+ FT_NUM_TYPES /* last item number plus one */
+};
+
+typedef enum ftenum ftenum_t;
+typedef struct _ftype_t ftype_t;
+
+/* Initialize the ftypes subsytem. Called once. */
+void
+ftypes_initialize(void);
+
+/* Cleanup the ftypes subsystem. Called once. */
+void
+ftypes_cleanup(void);
+
+
+/* ---------------- FTYPE ----------------- */
+
+/* Return a string representing the name of the type */
+const char*
+ftype_name(ftenum_t ftype);
+
+/* Return a string presenting a "pretty" representation of the
+ * name of the type. The pretty name means more to the user than
+ * that "FT_*" name. */
+const char*
+ftype_pretty_name(ftenum_t ftype);
+
+/* Returns length of field in packet, or 0 if not determinable/defined. */
+int
+ftype_length(ftenum_t ftype);
+
+gboolean
+ftype_can_slice(enum ftenum ftype);
+
+gboolean
+ftype_can_eq(enum ftenum ftype);
+
+gboolean
+ftype_can_ne(enum ftenum ftype);
+
+gboolean
+ftype_can_gt(enum ftenum ftype);
+
+gboolean
+ftype_can_ge(enum ftenum ftype);
+
+gboolean
+ftype_can_lt(enum ftenum ftype);
+
+gboolean
+ftype_can_le(enum ftenum ftype);
+
+/* ---------------- FVALUE ----------------- */
+
+#include "ipv4.h"
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+
+#include "tvbuff.h"
+
+typedef struct {
+ ftype_t *ftype;
+ union {
+ /* Put a few basic types in here */
+ gpointer pointer;
+ guint32 integer;
+ gdouble floating;
+ gchar *string;
+ GByteArray *bytes;
+ ipv4_addr ipv4;
+ guint8 ipv6[16];
+ struct timeval time;
+ tvbuff_t *tvb;
+ } value;
+} fvalue_t;
+
+fvalue_t*
+fvalue_new(ftenum_t ftype);
+
+void
+fvalue_free(fvalue_t *fv);
+
+typedef void (*LogFunc)(char*,...);
+
+fvalue_t*
+fvalue_from_string(ftenum_t ftype, char *s, LogFunc log);
+
+const char*
+fvalue_type_name(fvalue_t *fv);
+
+void
+fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied);
+
+void
+fvalue_set_integer(fvalue_t *fv, guint32 value);
+
+void
+fvalue_set_floating(fvalue_t *fv, gdouble value);
+
+gpointer
+fvalue_get(fvalue_t *fv);
+
+guint32
+fvalue_get_integer(fvalue_t *fv);
+
+double
+fvalue_get_floating(fvalue_t *fv);
+
+gboolean
+fvalue_eq(fvalue_t *a, fvalue_t *b);
+
+gboolean
+fvalue_ne(fvalue_t *a, fvalue_t *b);
+
+gboolean
+fvalue_gt(fvalue_t *a, fvalue_t *b);
+
+gboolean
+fvalue_ge(fvalue_t *a, fvalue_t *b);
+
+gboolean
+fvalue_lt(fvalue_t *a, fvalue_t *b);
+
+gboolean
+fvalue_le(fvalue_t *a, fvalue_t *b);
+
+guint
+fvalue_length(fvalue_t *fv);
+
+fvalue_t*
+fvalue_slice(fvalue_t *fv, gint start, gint end);
+
+#endif /* ftypes.h */