Add back the fix from revision 54693.
[metze/wireshark/wip.git] / epan / proto.c
index 30568d7809e1b7d9bb2e96cf0f46f60c3fbe77b1..22842273453be55a9c4ae74924787ea8235fac04 100644 (file)
 #include <ctype.h>
 #include <glib.h>
 #include <float.h>
-#include <wsutil/swar.h>
+
+#include <wsutil/bits_ctz.h>
+#include <wsutil/bits_count_ones.h>
+#include <wsutil/sign_ext.h>
+
+#include <ftypes/ftypes-int.h>
 
 #include "packet.h"
+#include "exceptions.h"
 #include "ptvcursor.h"
 #include "strutil.h"
 #include "addr_resolv.h"
 #include "oids.h"
-#include "plugins.h"
 #include "proto.h"
 #include "epan_dissect.h"
 #include "tvbuff.h"
 #include "charsets.h"
 #include "asm_utils.h"
 #include "column-utils.h"
+#include "to_str-int.h"
 #include "to_str.h"
+#include "osi-utils.h"
 #include "expert.h"
 #include "show_exception.h"
 
 #include "wspython/wspy_register.h"
 
+#include <wsutil/plugins.h>
+
 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
 #define SUBTREE_MAX_LEVELS 256
 /* Throw an exception if we exceed this many tree items. */
@@ -171,7 +180,7 @@ proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
 static void
 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
 static void
-proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
+proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
 static void
 proto_tree_set_string(field_info *fi, const char* value);
 static void
@@ -205,6 +214,10 @@ proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
 static void
 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
 static void
+proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length);
+static void
+proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
+static void
 proto_tree_set_boolean(field_info *fi, guint32 value);
 static void
 proto_tree_set_float(field_info *fi, float value);
@@ -215,6 +228,8 @@ proto_tree_set_uint(field_info *fi, guint32 value);
 static void
 proto_tree_set_int(field_info *fi, gint32 value);
 static void
+proto_tree_set_int64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
+static void
 proto_tree_set_uint64(field_info *fi, guint64 value);
 static void
 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
@@ -241,9 +256,9 @@ struct _protocol {
        const char *name;         /* long description */
        const char *short_name;   /* short description */
        const char *filter_name;  /* name of this protocol in filters */
-       int         proto_id;     /* field ID for this protocol */
        GSList     *fields;       /* fields for this protocol */
        GSList     *last_field;   /* pointer to end of list of fields */
+       int         proto_id;     /* field ID for this protocol */
        gboolean    is_enabled;   /* TRUE if protocol is enabled */
        gboolean    can_toggle;   /* TRUE if is_enabled can be changed */
        gboolean    is_private;   /* TRUE is protocol is private */
@@ -252,8 +267,6 @@ struct _protocol {
 /* List of all protocols */
 static GList *protocols = NULL;
 
-static wmem_allocator_t *tree_pool_cache = NULL;
-
 /* Contains information about a field when a dissector calls
  * proto_tree_add_item.  */
 #define FIELD_INFO_NEW(pool, fi)  fi = wmem_new(pool, field_info)
@@ -320,6 +333,87 @@ proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
        return g_ascii_strcasecmp(p1->short_name, p2->short_name);
 }
 
+#ifdef HAVE_PLUGINS
+/*
+ * List of dissector plugins.
+ */
+typedef struct {
+       void (*register_protoinfo)(void);       /* routine to call to register protocol information */
+       void (*reg_handoff)(void);              /* routine to call to register dissector handoff */
+} dissector_plugin;
+
+static GSList *dissector_plugins = NULL;
+
+/*
+ * Callback for each plugin found.
+ */
+static gboolean
+check_for_dissector_plugin(GModule *handle)
+{
+       gpointer gp;
+       void (*register_protoinfo)(void);
+       void (*reg_handoff)(void);
+       dissector_plugin *plugin;
+
+       /*
+        * Do we have a register routine?
+        */
+       if (g_module_symbol(handle, "plugin_register", &gp))
+               register_protoinfo = (void (*)(void))gp;
+       else
+               register_protoinfo = NULL;
+
+       /*
+        * Do we have a reg_handoff routine?
+        */
+       if (g_module_symbol(handle, "plugin_reg_handoff", &gp))
+               reg_handoff = (void (*)(void))gp;
+       else
+               reg_handoff = NULL;
+
+       /*
+        * If we have neither, we're not a dissector plugin.
+        */
+       if (register_protoinfo == NULL && reg_handoff == NULL)
+               return FALSE;
+
+       /*
+        * Add this one to the list of dissector plugins.
+        */
+       plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
+       plugin->register_protoinfo = register_protoinfo;
+       plugin->reg_handoff = reg_handoff;
+       dissector_plugins = g_slist_append(dissector_plugins, plugin);
+       return TRUE;
+}
+
+static void
+register_dissector_plugin(gpointer data, gpointer user_data _U_)
+{
+       dissector_plugin *plugin = (dissector_plugin *)data;
+
+       if (plugin->register_protoinfo)
+               (plugin->register_protoinfo)();
+}
+
+static void
+reg_handoff_dissector_plugin(gpointer data, gpointer user_data _U_)
+{
+       dissector_plugin *plugin = (dissector_plugin *)data;
+
+       if (plugin->reg_handoff)
+               (plugin->reg_handoff)();
+}
+
+/*
+ * Register dissector plugin type.
+ */
+void
+register_dissector_plugin_type(void)
+{
+       add_plugin_type("dissector", check_for_dissector_plugin);
+}
+#endif /* HAVE_PLUGINS */
 
 /* initialize data structures and register protocols and fields */
 void
@@ -364,12 +458,11 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
 #endif
 
 #ifdef HAVE_PLUGINS
-       /* Now scan for plugins and load all the ones we find, calling
-          their register routines to do the stuff described above. */
+       /* Now call the registration routines for all disssector
+          plugins. */
        if (cb)
                (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
-       init_plugins();
-       register_all_plugin_registrations();
+       g_slist_foreach(dissector_plugins, register_dissector_plugin, NULL);
 #endif
 
        /* Now call the "handoff registration" routines of all built-in
@@ -389,7 +482,7 @@ proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_da
        /* Now do the same with plugins. */
        if (cb)
                (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
-       register_all_plugin_handoffs();
+       g_slist_foreach(dissector_plugins, reg_handoff_dissector_plugin, NULL);
 #endif
 
        /* sort the protocols by protocol name */
@@ -573,8 +666,6 @@ proto_tree_reset(proto_tree *tree)
        /* Reset track of the number of children */
        tree_data->count = 0;
 
-       wmem_free_all(tree_data->mem_pool);
-
        PROTO_NODE_INIT(tree);
 }
 
@@ -582,7 +673,6 @@ proto_tree_reset(proto_tree *tree)
 void
 proto_tree_free(proto_tree *tree)
 {
-       wmem_allocator_t *pool = PNODE_POOL(tree);
        tree_data_t *tree_data = PTREE_DATA(tree);
 
        proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
@@ -597,15 +687,6 @@ proto_tree_free(proto_tree *tree)
                g_hash_table_destroy(tree_data->interesting_hfids);
        }
 
-       if (tree_pool_cache) {
-               /* if we already have one cached then just destroy it */
-               wmem_destroy_allocator(pool);
-       }
-       else {
-               wmem_free_all(pool);
-               tree_pool_cache = pool;
-       }
-
        g_slice_free(tree_data_t, tree_data);
 
        g_slice_free(proto_tree, tree);
@@ -682,8 +763,9 @@ proto_registrar_get_nth(guint hfindex)
 static guint
 prefix_hash (gconstpointer key) {
        /* end the string at the dot and compute its hash */
-       gchar* copy = ep_strdup((const gchar *)key);
+       gchar* copy = g_strdup((const gchar *)key);
        gchar* c    = copy;
+       guint tmp;
 
        for (; *c; c++) {
                if (*c == '.') {
@@ -692,7 +774,9 @@ prefix_hash (gconstpointer key) {
                }
        }
 
-       return g_str_hash(copy);
+       tmp = g_str_hash(copy);
+       g_free(copy);
+       return tmp;
 }
 
 /* are both strings equal up to the end or the dot? */
@@ -1059,6 +1143,14 @@ proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
        return pi;
 }
 
+void proto_report_dissector_bug(const char *message)
+{
+       if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
+               abort();
+       else
+               THROW_MESSAGE(DissectorError, message);
+}
+
 /* We could probably get away with changing is_error to a minimum length value. */
 static void
 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
@@ -1277,7 +1369,14 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                length_error = length < 1 ? TRUE : FALSE;
                                report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
                        }
-                       proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
+                       if (new_fi->hfinfo->type == FT_INT64)
+                       {
+                               proto_tree_set_int64_tvb(new_fi, tvb, start, length, encoding);
+                       }
+                       else
+                       {
+                               proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
+                       }
                        break;
 
                /* XXX - make these just FT_INT? */
@@ -1391,6 +1490,10 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                        proto_tree_set_oid_tvb(new_fi, tvb, start, length);
                        break;
 
+               case FT_SYSTEM_ID:
+                       proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
+                       break;
+
                case FT_FLOAT:
                        /*
                         * NOTE: to support code written when
@@ -1567,7 +1670,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 * 4-byte fractional time in nanoseconds,
                                 * both big-endian.
                                 */
-                               time_stamp.secs  = tvb_get_ntohl(tvb, start);
+                               time_stamp.secs  = (time_t)tvb_get_ntohl(tvb, start);
                                if (length == 8)
                                        time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
                                else
@@ -1580,7 +1683,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 * 4-byte fractional time in nanoseconds,
                                 * both little-endian.
                                 */
-                               time_stamp.secs  = tvb_get_letohl(tvb, start);
+                               time_stamp.secs  = (time_t)tvb_get_letohl(tvb, start);
                                if (length == 8)
                                        time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
                                else
@@ -1592,7 +1695,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 * TOD time stamp, big-endian.
                                 */
 /* XXX - where should this go? */
-#define TOD_BASETIME 2208988800ul
+#define TOD_BASETIME G_GUINT64_CONSTANT(2208988800)
 
                                todsecs  = tvb_get_ntoh64(tvb, start) >> 12;
                                time_stamp.secs = (time_t)((todsecs  / 1000000) - TOD_BASETIME);
@@ -1614,7 +1717,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 */
 
 /* XXX - where should this go? */
-#define NTP_BASETIME 2208988800ul
+#define NTP_BASETIME G_GUINT64_CONSTANT(2208988800)
 
                                /* We need a temporary variable here so the unsigned math
                                 * works correctly (for years > 2036 according to RFC 2030
@@ -1622,7 +1725,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 */
                                tmpsecs  = tvb_get_ntohl(tvb, start);
                                if (tmpsecs)
-                                       time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
+                                       time_stamp.secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
                                else
                                        time_stamp.secs = tmpsecs; /* 0 */
 
@@ -1646,7 +1749,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 */
                                tmpsecs  = tvb_get_letohl(tvb, start);
                                if (tmpsecs)
-                                       time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
+                                       time_stamp.secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
                                else
                                        time_stamp.secs = tmpsecs; /* 0 */
 
@@ -1666,7 +1769,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
 
                        default:
                                DISSECTOR_ASSERT_NOT_REACHED();
-                               time_stamp.secs = 0;
+                               time_stamp.secs = (time_t)0;
                                time_stamp.nsecs = 0;
                                break;
                        }
@@ -1702,7 +1805,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 * 4-byte fractional time in nanoseconds,
                                 * both big-endian.
                                 */
-                               time_stamp.secs  = tvb_get_ntohl(tvb, start);
+                               time_stamp.secs  = (time_t)tvb_get_ntohl(tvb, start);
                                if (length == 8)
                                        time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
                                else
@@ -1715,7 +1818,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
                                 * 4-byte fractional time in nanoseconds,
                                 * both little-endian.
                                 */
-                               time_stamp.secs  = tvb_get_letohl(tvb, start);
+                               time_stamp.secs  = (time_t)tvb_get_letohl(tvb, start);
                                if (length == 8)
                                        time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
                                else
@@ -1832,7 +1935,7 @@ proto_item *
 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                    const gint start, gint length, const guint encoding)
 {
-        return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
+       return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
 }
 
 /* Add a FT_NONE to a proto_tree */
@@ -1887,7 +1990,7 @@ ptvcursor_advance(ptvcursor_t* ptvc, gint length)
 static void
 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
 {
-       fvalue_set(&fi->value, tvb, TRUE);
+       fvalue_set_tvbuff(&fi->value, tvb);
 }
 
 /* Add a FT_PROTOCOL to a proto_tree */
@@ -1999,7 +2102,7 @@ proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
        if (length > 0) {
                g_byte_array_append(bytes, start_ptr, length);
        }
-       fvalue_set(&fi->value, bytes, TRUE);
+       fvalue_set_byte_array(&fi->value, bytes);
 }
 
 
@@ -2012,7 +2115,7 @@ proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length
 /* Add a FT_*TIME to a proto_tree */
 proto_item *
 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
-                   gint length, nstime_t *value_ptr)
+                   gint length, const nstime_t *value_ptr)
 {
        proto_item        *pi;
        header_field_info *hfinfo;
@@ -2068,11 +2171,11 @@ proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 
 /* Set the FT_*TIME value */
 static void
-proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
+proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
 {
        DISSECTOR_ASSERT(value_ptr != NULL);
 
-       fvalue_set(&fi->value, value_ptr, FALSE);
+       fvalue_set_time(&fi->value, value_ptr);
 }
 
 /* Add a FT_IPXNET to a proto_tree */
@@ -2263,7 +2366,7 @@ static void
 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
 {
        DISSECTOR_ASSERT(value_ptr != NULL);
-       fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
+       fvalue_set_bytes(&fi->value, value_ptr);
 }
 
 static void
@@ -2334,7 +2437,7 @@ static void
 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
 {
        DISSECTOR_ASSERT(value_ptr != NULL);
-       fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
+       fvalue_set_guid(&fi->value, value_ptr);
 }
 
 static void
@@ -2416,7 +2519,7 @@ proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
        if (length > 0) {
                g_byte_array_append(bytes, value_ptr, length);
        }
-       fvalue_set(&fi->value, bytes, TRUE);
+       fvalue_set_byte_array(&fi->value, bytes);
 }
 
 static void
@@ -2425,6 +2528,27 @@ proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
        proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
 }
 
+/* Set the FT_SYSTEM_ID value */
+static void
+proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length)
+{
+       GByteArray *bytes;
+
+       DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
+
+       bytes = g_byte_array_new();
+       if (length > 0) {
+               g_byte_array_append(bytes, value_ptr, length);
+       }
+       fvalue_set_byte_array(&fi->value, bytes);
+}
+
+static void
+proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
+{
+       proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
+}
+
 static void
 proto_tree_set_uint64(field_info *fi, guint64 value)
 {
@@ -2476,6 +2600,70 @@ proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
        proto_tree_set_uint64(fi, value);
 }
 
+static void
+proto_tree_set_int64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
+                         guint length, const guint encoding)
+{
+       guint64 value = 0;
+       guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
+
+       if (encoding) {
+               b += length;
+               switch (length) {
+                       default: DISSECTOR_ASSERT_NOT_REACHED();
+                       case 8: value <<= 8; value += *--b;
+                       case 7: value <<= 8; value += *--b;
+                       case 6: value <<= 8; value += *--b;
+                       case 5: value <<= 8; value += *--b;
+                       case 4: value <<= 8; value += *--b;
+                       case 3: value <<= 8; value += *--b;
+                       case 2: value <<= 8; value += *--b;
+                       case 1: value <<= 8; value += *--b;
+                               break;
+               }
+       } else {
+               switch (length) {
+                       default: DISSECTOR_ASSERT_NOT_REACHED();
+                       case 8: value <<= 8; value += *b++;
+                       case 7: value <<= 8; value += *b++;
+                       case 6: value <<= 8; value += *b++;
+                       case 5: value <<= 8; value += *b++;
+                       case 4: value <<= 8; value += *b++;
+                       case 3: value <<= 8; value += *b++;
+                       case 2: value <<= 8; value += *b++;
+                       case 1: value <<= 8; value += *b++;
+                               break;
+               }
+       }
+
+       switch(length)
+       {
+               case 7:
+                       value = ws_sign_ext64(value, 56);
+                       break;
+               case 6:
+                       value = ws_sign_ext64(value, 48);
+                       break;
+               case 5:
+                       value = ws_sign_ext64(value, 40);
+                       break;
+               case 4:
+                       value = ws_sign_ext64(value, 32);
+                       break;
+               case 3:
+                       value = ws_sign_ext64(value, 24);
+                       break;
+               case 2:
+                       value = ws_sign_ext64(value, 16);
+                       break;
+               case 1:
+                       value = ws_sign_ext64(value, 8);
+                       break;
+       }
+
+       proto_tree_set_uint64(fi, value);
+}
+
 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
  * and frees it when the proto_tree is destroyed. */
 proto_item *
@@ -2489,6 +2677,10 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
 
        DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
 
+       if (hfinfo->display == STR_UNICODE) {
+               DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
+       }
+
        pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
        DISSECTOR_ASSERT(length >= 0);
        proto_tree_set_string(PNODE_FINFO(pi), value);
@@ -2496,14 +2688,6 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
        return pi;
 }
 
-proto_item *
-proto_tree_add_unicode_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
-                     gint length, const char* value)
-{
-       DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
-       return proto_tree_add_string_format_value(tree, hfindex, tvb, start, length, value, "%s", value);
-}
-
 proto_item *
 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                                   gint start, gint length, const char* value,
@@ -2585,7 +2769,7 @@ proto_item_append_string(proto_item *pi, const char *str)
                new_str = ep_strconcat(old_str, str, NULL);
        else
                new_str = str;
-       fvalue_set(&fi->value, (gpointer) new_str, FALSE);
+       fvalue_set_string(&fi->value, new_str);
 }
 
 /* Set the FT_STRING value */
@@ -2593,9 +2777,9 @@ static void
 proto_tree_set_string(field_info *fi, const char* value)
 {
        if (value) {
-               fvalue_set(&fi->value, (gpointer) value, FALSE);
+               fvalue_set_string(&fi->value, value);
        } else {
-               fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
+               fvalue_set_string(&fi->value, "[ Null ]");
        }
 }
 
@@ -2635,7 +2819,7 @@ proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gi
 static void
 proto_tree_set_ax25(field_info *fi, const guint8* value)
 {
-       fvalue_set(&fi->value, (gpointer) value, FALSE);
+       fvalue_set_bytes(&fi->value, value);
 }
 
 static void
@@ -2648,7 +2832,7 @@ proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
 static void
 proto_tree_set_vines(field_info *fi, const guint8* value)
 {
-       fvalue_set(&fi->value, (gpointer) value, FALSE);
+       fvalue_set_bytes(&fi->value, value);
 }
 
 static void
@@ -2717,7 +2901,7 @@ proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
 static void
 proto_tree_set_ether(field_info *fi, const guint8* value)
 {
-       fvalue_set(&fi->value, (gpointer) value, FALSE);
+       fvalue_set_bytes(&fi->value, value);
 }
 
 static void
@@ -3139,9 +3323,8 @@ proto_tree_set_int(field_info *fi, gint32 value)
                /* Shift bits */
                integer >>= hfinfo_bitshift(hfinfo);
 
-               no_of_bits = swar_count_bits(hfinfo->bitmask);
-               if (integer & (1 << (no_of_bits-1)))
-                       integer |= (-1 << no_of_bits);
+               no_of_bits = ws_count_ones(hfinfo->bitmask);
+               integer = ws_sign_ext32(integer, no_of_bits);
        }
 
        fvalue_set_sinteger(&fi->value, integer);
@@ -3587,6 +3770,24 @@ proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
        }
 }
 
+static const char *
+hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
+{
+       switch (hfinfo->display) {
+               case STR_ASCII:
+                       return format_text(string, strlen(string));
+/*
+               case STR_ASCII_WSP
+                       return format_text_wsp(string, strlen(string));
+ */
+               case STR_UNICODE:
+                       /* XXX, format_unicode_text() */
+                       return string;
+       }
+
+       return format_text(string, strlen(string));
+}
+
 static int
 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
 {
@@ -3709,21 +3910,20 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                        case FT_BYTES:
                                bytes = (guint8 *)fvalue_get(&finfo->value);
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          bytes_to_str(bytes,
-                                                                       fvalue_length(&finfo->value)),
-                                                          size-offset_r);
+                                               bytes ?  bytes_to_ep_str(bytes, fvalue_length(&finfo->value)) : "<MISSING>",
+                                               size-offset_r);
                                break;
 
                        case FT_ABSOLUTE_TIME:
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
+                                                          abs_time_to_ep_str((const nstime_t *)fvalue_get(&finfo->value),
                                                                           (absolute_time_display_e)hfinfo->display, TRUE),
                                                           size-offset_r);
                                break;
 
                        case FT_RELATIVE_TIME:
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
+                                                          rel_time_to_secs_ep_str((const nstime_t *)fvalue_get(&finfo->value)),
                                                           size-offset_r);
                                break;
 
@@ -3753,11 +3953,11 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                        case FT_UINT32:
                        case FT_FRAMENUM:
                                hf_str_val = NULL;
-                               number = IS_FT_INT(hfinfo->type) ? 
+                               number = IS_FT_INT(hfinfo->type) ?
                                                (guint32) fvalue_get_sinteger(&finfo->value) :
                                                fvalue_get_uinteger(&finfo->value);
 
-                               if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) {
+                               if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
                                        gchar tmp[ITEM_LABEL_LENGTH];
                                        custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
 
@@ -3780,7 +3980,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                                        offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
                                }
 
-                               if (hf_str_val && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
+                               if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
                                        g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
                                } else {
                                        number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
@@ -3828,14 +4028,14 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
 
                        case FT_ETHER:
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
+                                                          bytes_to_ep_str_punct((const guint8 *)fvalue_get(&finfo->value),
                                                                              FT_ETHER_LEN, ':'),
                                                           size-offset_r);
                                break;
 
                        case FT_GUID:
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
+                                                          guid_to_ep_str((e_guid_t *)fvalue_get(&finfo->value)),
                                                           size-offset_r);
                                break;
 
@@ -3861,15 +4061,25 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                                                           size-offset_e);
                                break;
 
+                       case FT_SYSTEM_ID:
+                               bytes = (guint8 *)fvalue_get(&finfo->value);
+                               offset_r += protoo_strlcpy(result+offset_r,
+                                                          print_system_id(bytes, fvalue_length(&finfo->value)),
+                                                          size-offset_r);
+                               offset_e += protoo_strlcpy(expr+offset_e,
+                                                          print_system_id(bytes, fvalue_length(&finfo->value)),
+                                                          size-offset_e);
+                               break;
+
                        case FT_FLOAT:
                                g_snprintf(result+offset_r, size-offset_r,
-                                          "%." STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
+                                          "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
                                offset_r = (int)strlen(result);
                                break;
 
                        case FT_DOUBLE:
                                g_snprintf(result+offset_r, size-offset_r,
-                                          "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
+                                          "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
                                offset_r = (int)strlen(result);
                                break;
 
@@ -3878,7 +4088,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                        case FT_UINT_STRING:
                                bytes = (guint8 *)fvalue_get(&finfo->value);
                                offset_r += protoo_strlcpy(result+offset_r,
-                                                          format_text(bytes, strlen(bytes)),
+                                                          hfinfo_format_text(hfinfo, bytes),
                                                           size-offset_r);
                                break;
 
@@ -3908,6 +4118,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
                case FT_INT32:
                case FT_OID:
                case FT_REL_OID:
+               case FT_SYSTEM_ID:
                        /* for these types, "expr" is filled in the loop above */
                        break;
 
@@ -4090,17 +4301,8 @@ proto_item_get_len(const proto_item *pi)
 proto_tree *
 proto_tree_create_root(packet_info *pinfo)
 {
-       wmem_allocator_t *pool;
        proto_node *pnode;
 
-       if (tree_pool_cache) {
-               pool = tree_pool_cache;
-               tree_pool_cache = NULL;
-       }
-       else {
-               pool = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
-       }
-
        /* Initialize the proto_node */
        pnode = g_slice_new(proto_tree);
        PROTO_NODE_INIT(pnode);
@@ -4111,8 +4313,6 @@ proto_tree_create_root(packet_info *pinfo)
        /* Make sure we can access pinfo everywhere */
        pnode->tree_data->pinfo = pinfo;
 
-       pnode->tree_data->mem_pool = pool;
-
        /* Don't initialize the tree_data_t. Wait until we know we need it */
        pnode->tree_data->interesting_hfids = NULL;
 
@@ -4179,7 +4379,7 @@ proto_item_add_subtree(proto_item *pi,    const gint idx) {
 }
 
 proto_tree *
-proto_item_get_subtree(const proto_item *pi) {
+proto_item_get_subtree(proto_item *pi) {
        field_info *fi;
 
        if (!pi)
@@ -4211,7 +4411,7 @@ proto_item_get_parent_nth(proto_item *ti, int gen) {
 
 
 proto_item *
-proto_tree_get_parent(const proto_tree *tree) {
+proto_tree_get_parent(proto_tree *tree) {
        if (!tree)
                return NULL;
        return (proto_item *)tree;
@@ -4303,10 +4503,11 @@ int
 proto_register_protocol(const char *name, const char *short_name,
                        const char *filter_name)
 {
-       protocol_t *protocol, *existing_protocol = NULL;
+       protocol_t *protocol;
+       const protocol_t *existing_protocol = NULL;
        header_field_info *hfinfo;
        int proto_id;
-       char *existing_name;
+       const char *existing_name;
        gint *key;
        guint i;
        guchar c;
@@ -4331,7 +4532,7 @@ proto_register_protocol(const char *name, const char *short_name,
        key  = (gint *)g_malloc (sizeof(gint));
        *key = wrs_str_hash(name);
 
-       existing_name = (char *)g_hash_table_lookup(proto_names, key);
+       existing_name = (const char *)g_hash_table_lookup(proto_names, key);
        if (existing_name != NULL) {
                /* g_error will terminate the program */
                g_error("Duplicate protocol name \"%s\"!"
@@ -4339,7 +4540,7 @@ proto_register_protocol(const char *name, const char *short_name,
        }
        g_hash_table_insert(proto_names, key, (gpointer)name);
 
-       existing_name = (char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
+       existing_name = (const char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
        if (existing_name != NULL) {
                g_error("Duplicate protocol short_name \"%s\"!"
                        " This might be caused by an inappropriate plugin or a development error.", short_name);
@@ -4358,7 +4559,7 @@ proto_register_protocol(const char *name, const char *short_name,
                        " Allowed are lower characters, digits, '-', '_' and '.'."
                        " This might be caused by an inappropriate plugin or a development error.", filter_name);
        }
-       existing_protocol = (protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
+       existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
        if (existing_protocol != NULL) {
                g_error("Duplicate protocol filter_name \"%s\"!"
                        " This might be caused by an inappropriate plugin or a development error.", filter_name);
@@ -4493,15 +4694,6 @@ find_protocol_by_id(const int proto_id)
        return (protocol_t *)hfinfo->strings;
 }
 
-static gint compare_filter_name(gconstpointer proto_arg,
-                               gconstpointer filter_name)
-{
-       const protocol_t *protocol = (const protocol_t *)proto_arg;
-       const gchar      *f_name   = (const gchar *)filter_name;
-
-       return (strcmp(protocol->filter_name, f_name));
-}
-
 int
 proto_get_id(const protocol_t *protocol)
 {
@@ -4510,14 +4702,14 @@ proto_get_id(const protocol_t *protocol)
 
 int proto_get_id_by_filter_name(const gchar* filter_name)
 {
-       protocol_t *protocol = NULL;
+       const protocol_t *protocol = NULL;
 
        if(!filter_name){
                fprintf(stderr, "No filter name present");
                DISSECTOR_ASSERT(filter_name);
        }
 
-       protocol = (protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
+       protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
 
        if (protocol == NULL)
                return -1;
@@ -4563,6 +4755,38 @@ proto_get_protocol_filter_name(const int proto_id)
        return protocol->filter_name;
 }
 
+void
+proto_get_frame_protocols(const wmem_list_t *layers,
+               gboolean *is_ip, gboolean *is_tcp, gboolean *is_udp, gboolean *is_sctp, gboolean *is_ssl) {
+       wmem_list_frame_t *protos = wmem_list_head(layers);
+       int         proto_id;
+       const char *proto_name;
+
+       /* Walk the list of a available protocols in the packet and
+          find "major" ones. */
+       /* It might make more sense to assemble and return a bitfield. */
+       while (protos != NULL)
+       {
+               proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
+               proto_name = proto_get_protocol_filter_name(proto_id);
+
+               if (is_ip && ((!strcmp(proto_name, "ip")) ||
+                             (!strcmp(proto_name, "ipv6")))) {
+                       *is_ip = TRUE;
+               } else if (is_tcp && !strcmp(proto_name, "tcp")) {
+                       *is_tcp = TRUE;
+               } else if (is_udp && !strcmp(proto_name, "udp")) {
+                       *is_udp = TRUE;
+               } else if (is_sctp && !strcmp(proto_name, "sctp")) {
+                       *is_sctp = TRUE;
+               } else if (is_ssl && !strcmp(proto_name, "ssl")) {
+                       *is_ssl = TRUE;
+               }
+
+               protos = wmem_list_frame_next(protos);
+       }
+}
+
 gboolean
 proto_is_protocol_enabled(const protocol_t *protocol)
 {
@@ -4614,14 +4838,30 @@ proto_set_cant_toggle(const int proto_id)
        protocol->can_toggle = FALSE;
 }
 
+static int
+proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
+{
+       if (proto != NULL) {
+               if (proto->fields == NULL) {
+                       proto->fields = g_slist_append(NULL, hfi);
+                       proto->last_field = proto->fields;
+               } else {
+                       proto->last_field =
+                               g_slist_append(proto->last_field, hfi)->next;
+               }
+       }
+
+       return proto_register_field_init(hfi, parent);
+}
+
 /* for use with static arrays only, since we don't allocate our own copies
 of the header_field_info struct contained within the hf_register_info struct */
 void
 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
 {
-       int               field_id, i;
        hf_register_info *ptr = hf;
        protocol_t       *proto;
+       int               i;
 
        proto = find_protocol_by_id(parent);
        for (i = 0; i < num_records; i++, ptr++) {
@@ -4640,22 +4880,34 @@ proto_register_field_array(const int parent, hf_register_info *hf, const int num
                        return;
                }
 
-               if (proto != NULL) {
-                       if (proto->fields == NULL) {
-                               proto->fields = g_slist_append(NULL, &ptr->hfinfo);
-                               proto->last_field = proto->fields;
-                       } else {
-                               proto->last_field =
-                                       g_slist_append(proto->last_field, &ptr->hfinfo)->next;
-                       }
+               *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
+       }
+}
+
+void
+proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
+{
+       int               i;
+       protocol_t       *proto;
+
+       proto = find_protocol_by_id(parent);
+       for (i = 0; i < num_records; i++) {
+               /*
+                * Make sure we haven't registered this yet.
+                */
+               if (hfi[i].id != -1) {
+                       fprintf(stderr,
+                               "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
+                               hfi[i].abbrev);
+                       return;
                }
-               field_id = proto_register_field_init(&ptr->hfinfo, parent);
-               *ptr->p_id = field_id;
+
+               proto_register_field_common(proto, &hfi[i], parent);
        }
 }
 
 void
-proto_register_fields(const int parent, header_field_info **hfi, const int num_records)
+proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
 {
        int               i;
        protocol_t       *proto;
@@ -4667,21 +4919,12 @@ proto_register_fields(const int parent, header_field_info **hfi, const int num_r
                 */
                if (hfi[i]->id != -1) {
                        fprintf(stderr,
-                               "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
+                               "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
                                hfi[i]->abbrev);
                        return;
                }
 
-               if (proto != NULL) {
-                       if (proto->fields == NULL) {
-                               proto->fields = g_slist_append(NULL, hfi[i]);
-                               proto->last_field = proto->fields;
-                       } else {
-                               proto->last_field =
-                                       g_slist_append(proto->last_field, hfi[i])->next;
-                       }
-               }
-               proto_register_field_init(hfi[i], parent);
+               proto_register_field_common(proto, hfi[i], parent);
        }
 }
 
@@ -4768,6 +5011,7 @@ static const value_string hf_types[] = {
        { FT_GUID,          "FT_GUID"          },
        { FT_OID,           "FT_OID"           },
        { FT_REL_OID,       "FT_REL_OID"       },
+       { FT_SYSTEM_ID,     "FT_SYSTEM_ID"       },
        { 0,                NULL } };
 
 static const value_string hf_display[] = {
@@ -4792,6 +5036,8 @@ static const value_string hf_display[] = {
        { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
        { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
        { BASE_CUSTOM|BASE_VAL64_STRING,  "BASE_CUSTOM|BASE_VAL64_STRING"  },
+       /* { STR_ASCII,                   "STR_ASCII" }, */
+       { STR_UNICODE,                    "STR_UNICODE" },
        { ABSOLUTE_TIME_LOCAL,            "ABSOLUTE_TIME_LOCAL"            },
        { ABSOLUTE_TIME_UTC,              "ABSOLUTE_TIME_UTC"              },
        { ABSOLUTE_TIME_DOY_UTC,          "ABSOLUTE_TIME_DOY_UTC"          },
@@ -4847,7 +5093,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
           report those that have same value but different string. */
        if ((hfinfo->strings != NULL) &&
            !(hfinfo->display & BASE_RANGE_STRING) &&
-           !((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_CUSTOM) &&
+           !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
            (
                    (hfinfo->type == FT_UINT8)  ||
                    (hfinfo->type == FT_UINT16) ||
@@ -4904,7 +5150,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
                         *      signed field to be displayed unsigned.  (Else how would
                         *      we display negative values?)
                         */
-                       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
+                       switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
                                case BASE_HEX:
                                case BASE_OCT:
                                case BASE_DEC_HEX:
@@ -4927,7 +5173,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
                         *  normally used except when constructing a display
                         *  filter for a value not found in the strings lookup.
                         */
-                       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
+                       switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
                                case BASE_DEC:
                                case BASE_HEX:
                                case BASE_OCT:
@@ -4974,6 +5220,32 @@ tmp_fld_check_assert(header_field_info *hfinfo)
                                        val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
                        break;
 
+               case FT_STRING:
+               case FT_STRINGZ:
+               case FT_UINT_STRING:
+                       switch (hfinfo->display) {
+                               case STR_ASCII:
+                               case STR_UNICODE:
+                                       break;
+
+                               default:
+                                       g_error("Field '%s' (%s) is an string value (%s)"
+                                               " but is being displayed as %s\n",
+                                               hfinfo->name, hfinfo->abbrev,
+                                               val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
+                                               val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
+                       }
+
+                       if (hfinfo->bitmask != 0)
+                               g_error("Field '%s' (%s) is an %s but has a bitmask\n",
+                                       hfinfo->name, hfinfo->abbrev,
+                                       val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
+                       if (hfinfo->strings != NULL)
+                               g_error("Field '%s' (%s) is an %s but has a strings value\n",
+                                       hfinfo->name, hfinfo->abbrev,
+                                       val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
+                       break;
+
                default:
                        if (hfinfo->display != BASE_NONE)
                                g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
@@ -5012,7 +5284,7 @@ register_type_length_mismatch(void)
        proto_set_cant_toggle(proto_type_length_mismatch);
 }
 
-#define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM)
+#define PROTO_PRE_ALLOC_HF_FIELDS_MEM (144000+PRE_ALLOC_EXPERT_FIELDS_MEM)
 static int
 proto_register_field_init(header_field_info *hfinfo, const int parent)
 {
@@ -5239,7 +5511,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_UINT_BYTES:
                        bytes = (guint8 *)fvalue_get(&fi->value);
                        label_fill(label_str, 0, hfinfo,
-                                       (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
+                                       (bytes) ? bytes_to_ep_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
                        break;
 
                /* Four types of integers to take care of:
@@ -5284,26 +5556,26 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                case FT_FLOAT:
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
-                                  "%s: %." STRINGIFY(FLT_DIG) "g",
+                                  "%s: %." G_STRINGIFY(FLT_DIG) "g",
                                   hfinfo->name, fvalue_get_floating(&fi->value));
                        break;
 
                case FT_DOUBLE:
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
-                                  "%s: %." STRINGIFY(DBL_DIG) "g",
+                                  "%s: %." G_STRINGIFY(DBL_DIG) "g",
                                   hfinfo->name, fvalue_get_floating(&fi->value));
                        break;
 
                case FT_ABSOLUTE_TIME:
                        label_fill(label_str, 0, hfinfo,
-                                  abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
+                                  abs_time_to_ep_str((const nstime_t *)fvalue_get(&fi->value),
                                                (absolute_time_display_e)hfinfo->display, TRUE));
                        break;
 
                case FT_RELATIVE_TIME:
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                   "%s: %s seconds", hfinfo->name,
-                                  rel_time_to_secs_str((const nstime_t *)fvalue_get(&fi->value)));
+                                  rel_time_to_secs_ep_str((const nstime_t *)fvalue_get(&fi->value)));
                        break;
 
                case FT_IPXNET:
@@ -5327,7 +5599,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                   "%s: %s", hfinfo->name,
-                                  address_to_str( &addr ));
+                                  ep_address_to_str( &addr ));
                        break;
 
                case FT_ETHER:
@@ -5354,7 +5626,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                case FT_GUID:
                        guid = (e_guid_t *)fvalue_get(&fi->value);
-                       label_fill(label_str, 0, hfinfo, guid_to_str(guid));
+                       label_fill(label_str, 0, hfinfo, guid_to_ep_str(guid));
                        break;
 
                case FT_OID:
@@ -5381,6 +5653,11 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                        }
                        break;
 
+               case FT_SYSTEM_ID:
+                       bytes = (guint8 *)fvalue_get(&fi->value);
+                       label_fill(label_str, 0, hfinfo, print_system_id(bytes, fvalue_length(&fi->value)));
+                       break;
+
                case FT_EUI64:
                        integer64 = fvalue_get_integer64(&fi->value);
                        label_fill_descr(label_str, 0, hfinfo,
@@ -5391,7 +5668,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
                case FT_STRINGZ:
                case FT_UINT_STRING:
                        bytes = (guint8 *)fvalue_get(&fi->value);
-                       label_fill(label_str, 0, hfinfo, format_text(bytes, strlen(bytes)));
+                       label_fill(label_str, 0, hfinfo, hfinfo_format_text(hfinfo, bytes));
                        break;
 
                default:
@@ -5603,7 +5880,7 @@ fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
        if (hfinfo->strings) {
                const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
 
-               if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
+               if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
                        label_fill(label_str, 0, hfinfo, val_str);
                }
                else {
@@ -5618,21 +5895,7 @@ fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
 int
 hfinfo_bitshift(const header_field_info *hfinfo)
 {
-       const guint32 bitmask = hfinfo->bitmask;
-
-#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-       g_assert(bitmask != 0);
-
-       return __builtin_ctz(bitmask);
-#else
-       /* From http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
-       static const int table[32] = {
-               0,   1, 28,  2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17,  4, 8,
-               31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18,  6, 11,  5, 10, 9
-       };
-
-       return table[((guint32)((bitmask & -(gint32)bitmask) * 0x077CB531U)) >> 27];
-#endif
+       return ws_ctz(hfinfo->bitmask);
 }
 
 int
@@ -5698,12 +5961,6 @@ _hfinfo_type_hex_octet(int type)
        return -1;
 }
 
-/* private to_str.c API don't export to .h! */
-char *oct_to_str_back(char *ptr, guint32 value);
-char *hex_to_str_back(char *ptr, int pad, guint32 value);
-char *uint_to_str_back(char *ptr, guint32 value);
-char *int_to_str_back(char *ptr, gint32 value);
-
 static const char *
 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
 {
@@ -5764,7 +6021,7 @@ static const char *
 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
 {
        /* Get the underlying BASE_ value */
-       int display = hfinfo->display & BASE_DISPLAY_E_MASK;
+       int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
 
        if (hfinfo->type == FT_FRAMENUM) {
                /*
@@ -5795,7 +6052,7 @@ static const char *
 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
 {
        /* Get the underlying BASE_ value */
-       int display = hfinfo->display & BASE_DISPLAY_E_MASK;
+       int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
 
        if (display == BASE_NONE)
                return NULL;
@@ -5814,7 +6071,7 @@ hfinfo_uint64_format(const header_field_info *hfinfo)
        const char *format = NULL;
 
        /* Pick the proper format string */
-       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
+       switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
                case BASE_DEC:
                        format = "%" G_GINT64_MODIFIER "u";
                        break;
@@ -5843,7 +6100,7 @@ hfinfo_int64_format(const header_field_info *hfinfo)
        const char *format = NULL;
 
        /* Pick the proper format string */
-       switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
+       switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
                case BASE_DEC:
                        format = "%" G_GINT64_MODIFIER "d";
                        break;
@@ -6202,7 +6459,7 @@ proto_registrar_dump_values(void)
                        tfs    = NULL;
 
                        if (hfinfo->strings != NULL) {
-                               if ((hfinfo->display & BASE_DISPLAY_E_MASK) != BASE_CUSTOM &&
+                               if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
                                    (hfinfo->type == FT_UINT8  ||
                                     hfinfo->type == FT_UINT16 ||
                                     hfinfo->type == FT_UINT24 ||
@@ -6278,7 +6535,7 @@ proto_registrar_dump_values(void)
                                vi = 0;
                                while (range[vi].strptr) {
                                        /* Print in the proper base */
-                                       if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_HEX) {
+                                       if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
                                                printf("R\t%s\t0x%x\t0x%x\t%s\n",
                                                       hfinfo->abbrev,
                                                       range[vi].value_min,
@@ -6387,7 +6644,7 @@ proto_registrar_dump_fields(void)
                            hfinfo->type == FT_INT32  ||
                            hfinfo->type == FT_INT64) {
 
-                               switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
+                               switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
                                        case BASE_NONE:
                                                base_name = "BASE_NONE";
                                                break;
@@ -6456,40 +6713,40 @@ hfinfo_numeric_format(const header_field_info *hfinfo)
 {
        const char *format = NULL;
 
-               /* Get the underlying BASE_ value */
-               switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
-                       case BASE_DEC:
-                       case BASE_DEC_HEX:
-                       case BASE_OCT: /* I'm lazy */
-                       case BASE_CUSTOM:
-                               switch (hfinfo->type) {
-                                       case FT_UINT64:
-                                               format = "%s == %" G_GINT64_MODIFIER "u";
-                                               break;
-                                       case FT_INT64:
-                                               format = "%s == %" G_GINT64_MODIFIER "d";
-                                               break;
-                                       default:
-                                               DISSECTOR_ASSERT_NOT_REACHED();
-                                               ;
-                               }
-                               break;
-                       case BASE_HEX:
-                       case BASE_HEX_DEC:
-                               switch (hfinfo->type) {
-                                       case FT_UINT64:
-                                       case FT_INT64:
-                                               format = "%s == 0x%016" G_GINT64_MODIFIER "x";
-                                               break;
-                                       default:
-                                               DISSECTOR_ASSERT_NOT_REACHED();
-                                               ;
-                               }
-                               break;
-                       default:
-                               DISSECTOR_ASSERT_NOT_REACHED();
-                               ;
-               }
+       /* Get the underlying BASE_ value */
+       switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
+               case BASE_DEC:
+               case BASE_DEC_HEX:
+               case BASE_OCT: /* I'm lazy */
+               case BASE_CUSTOM:
+                       switch (hfinfo->type) {
+                               case FT_UINT64:
+                                       format = "%s == %" G_GINT64_MODIFIER "u";
+                                       break;
+                               case FT_INT64:
+                                       format = "%s == %" G_GINT64_MODIFIER "d";
+                                       break;
+                               default:
+                                       DISSECTOR_ASSERT_NOT_REACHED();
+                                       ;
+                       }
+                       break;
+               case BASE_HEX:
+               case BASE_HEX_DEC:
+                       switch (hfinfo->type) {
+                               case FT_UINT64:
+                               case FT_INT64:
+                                       format = "%s == 0x%016" G_GINT64_MODIFIER "x";
+                                       break;
+                               default:
+                                       DISSECTOR_ASSERT_NOT_REACHED();
+                                       ;
+                       }
+                       break;
+               default:
+                       DISSECTOR_ASSERT_NOT_REACHED();
+                       ;
+       }
        return format;
 }
 
@@ -6514,14 +6771,14 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
        guint8             c;
        gchar              is_signed_num = FALSE;
 
-        if (!finfo)
-                return FALSE;
+       if (!finfo)
+               return FALSE;
 
        hfinfo     = finfo->hfinfo;
        DISSECTOR_ASSERT(hfinfo);
        abbrev_len = (int) strlen(hfinfo->abbrev);
 
-       if (hfinfo->strings && (hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
+       if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
                const gchar *str = NULL;
 
                switch (hfinfo->type) {
@@ -7010,8 +7267,8 @@ proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
                         const guint encoding)
 {
        header_field_info *hfinfo;
-       gint              octet_length;
-       gint              octet_offset;
+       gint               octet_length;
+       gint               octet_offset;
 
        PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
 
@@ -7085,8 +7342,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
                case FT_INT24:
                case FT_INT32:
                case FT_INT64:
-                       if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
-                               value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
+                       value = ws_sign_ext64(value, no_of_bits);
                        break;
 
                default:
@@ -7230,8 +7486,7 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbu
                case FT_INT24:
                case FT_INT32:
                case FT_INT64:
-                       if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
-                               value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
+                       value = ws_sign_ext64(value, no_of_bits);
                        break;
                default:
                        break;
@@ -7567,6 +7822,36 @@ proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
        return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
 }
 
+proto_item *
+proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
+       const guint bit_offset, const gint no_of_chars)
+{
+       proto_item        *pi;
+       header_field_info *hfinfo;
+       gint               byte_length;
+       gint               byte_offset;
+       gchar             *string;
+
+       TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
+
+       DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
+
+       byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
+       byte_offset = bit_offset >> 3;
+
+       string = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
+
+       if (hfinfo->display == STR_UNICODE) {
+               DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
+       }
+
+       pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
+       DISSECTOR_ASSERT(byte_length >= 0);
+       proto_tree_set_string(PNODE_FINFO(pi), string);
+
+       return pi;
+}
+
 guchar
 proto_check_field_name(const gchar *field_name)
 {