Cite the source of frequency allocation information.
[obnox/wireshark/wip.git] / epan / proto.c
index 79f70850308fdee4d70b46064e2132c3c51528cf..4197b5c1a948e16e95c5739d18d88d3cebd0e0b6 100644 (file)
 #include "ptvcursor.h"
 #include "strutil.h"
 #include "addr_resolv.h"
-#include "oid_resolv.h"
+#include "oids.h"
 #include "plugins.h"
 #include "proto.h"
 #include "epan_dissect.h"
 #include "slab.h"
 #include "tvbuff.h"
 #include "emem.h"
+#include "charsets.h"
+#include "asm_utils.h"
+#include "column-utils.h"
+
+#ifdef NEED_G_ASCII_STRCASECMP_H
+#include "g_ascii_strcasecmp.h"
+#endif
 
 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
 #define SUBTREE_MAX_LEVELS 256
@@ -63,10 +70,23 @@ struct ptvcursor {
        gint            offset;
 };
 
+/* Candidates for assembler */
+int
+wrs_count_bitshift(guint32 bitmask)
+{
+       int bitshift = 0;
+
+       while ((bitmask & (1 << bitshift)) == 0)
+               bitshift++;
+       return bitshift;
+}
+
+
+
 #if GLIB_MAJOR_VERSION < 2
 static void *discard_const(const void *const_ptr)
 {
-       union { 
+       union {
                const void *const_ptr;
                void *ptr;
        } stupid_const;
@@ -88,7 +108,7 @@ static void *discard_const(const void *const_ptr)
           or else filtering will not work (they would be ignored since tree\
           would be NULL).                                              \
           DONT try to fake a node where PITEM_FINFO(pi) is NULL        \
-          since dissectors that want to do proto_item_set_len() ot     \
+          since dissectors that want to do proto_item_set_len() or     \
           other operations that dereference this would crash.          \
           We dont fake FT_PROTOCOL either since these are cheap and    \
           some stuff (proto hier stat) assumes they always exist.      \
@@ -124,9 +144,11 @@ static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
 int hfinfo_bitwidth(header_field_info *hfinfo);
 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
 static const char* hfinfo_uint_format(header_field_info *hfinfo);
+static const char* hfinfo_uint_value_format(header_field_info *hfinfo);
 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
 static const char* hfinfo_int_format(header_field_info *hfinfo);
+static const char* hfinfo_int_value_format(header_field_info *hfinfo);
 static const char* hfinfo_int64_format(header_field_info *hfinfo);
 
 static proto_item*
@@ -166,6 +188,8 @@ proto_tree_set_string(field_info *fi, const char* value);
 static void
 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
 static void
+proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
+static void
 proto_tree_set_ether(field_info *fi, const guint8* value);
 static void
 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
@@ -198,13 +222,10 @@ proto_tree_set_int(field_info *fi, gint32 value);
 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, gboolean little_endian);
+proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
 
 static int proto_register_field_init(header_field_info *hfinfo, int parent);
 
-/* Comparision function for tree insertion. A wrapper around strcmp() */
-static int g_strcmp(gconstpointer a, gconstpointer b);
-
 /* special-case header field used within proto.c */
 int hf_text_only = -1;
 
@@ -280,6 +301,14 @@ gpa_hfinfo_t gpa_hfinfo;
 
 /* Balanced tree of abbreviations and IDs */
 static GTree *gpa_name_tree = NULL;
+static header_field_info *same_name_hfinfo;
+
+#if GLIB_MAJOR_VERSION >= 2
+static void save_same_name_hfinfo(gpointer data)
+{
+  same_name_hfinfo = (header_field_info*)data;
+}
+#endif
 
 /* Points to the first element of an array of Booleans, indexed by
    a subtree item type; that array element is TRUE if subtrees of
@@ -300,7 +329,7 @@ proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
        const protocol_t *p1 = p1_arg;
        const protocol_t *p2 = p2_arg;
 
-       return g_strcasecmp(p1->short_name, p2->short_name);
+       return g_ascii_strcasecmp(p1->short_name, p2->short_name);
 }
 
 
@@ -313,14 +342,14 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
 {
        static hf_register_info hf[] = {
                { &hf_text_only,
-               { "Proto Init", "", FT_NONE, BASE_NONE, NULL, 0x0,
+               { "Text item",  "", FT_NONE, BASE_NONE, NULL, 0x0,
                        NULL, HFILL }},
        };
 
 
        proto_names = g_hash_table_new(g_int_hash, g_int_equal);
-       proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
-       proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
+       proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
+       proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
 
        proto_cleanup();
 
@@ -332,7 +361,11 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
        gpa_hfinfo.len=0;
        gpa_hfinfo.allocated_len=0;
        gpa_hfinfo.hfi=NULL;
-       gpa_name_tree = g_tree_new(g_strcmp);
+#if GLIB_MAJOR_VERSION < 2
+       gpa_name_tree = g_tree_new(wrs_strcmp);
+#else
+       gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
+#endif
 
        /* Initialize the ftype subsystem */
        ftypes_initialize();
@@ -351,7 +384,7 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
 #ifdef HAVE_PLUGINS
        /* Now scan for plugins and load all the ones we find, calling
           their register routines to do the stuff described above. */
-       if(cb) 
+       if(cb)
          (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
        init_plugins();
        register_all_plugin_registrations();
@@ -365,7 +398,7 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
 
 #ifdef HAVE_PLUGINS
        /* Now do the same with plugins. */
-       if(cb) 
+       if(cb)
          (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
        register_all_plugin_handoffs();
 #endif
@@ -379,13 +412,6 @@ proto_init(void (register_all_protocols)(register_cb cb, gpointer client_data),
        memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
 }
 
-/* String comparison func for dfilter_token GTree */
-static int
-g_strcmp(gconstpointer a, gconstpointer b)
-{
-       return strcmp((const char*)a, (const char*)b);
-}
-
 void
 proto_cleanup(void)
 {
@@ -710,9 +736,9 @@ ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
        ptvc->tree = tree;
 }
 
-/* creates a subtree, sets it as the working tree and pushes the old working tree */ 
-proto_tree* 
-ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree) 
+/* creates a subtree, sets it as the working tree and pushes the old working tree */
+proto_tree*
+ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
 {
   subtree_lvl * subtree;
   if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
@@ -726,8 +752,8 @@ ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
 }
 
 /* pops a subtree */
-void 
-ptvcursor_pop_subtree(ptvcursor_t *ptvc) 
+void
+ptvcursor_pop_subtree(ptvcursor_t *ptvc)
 {
   subtree_lvl * subtree;
   if (ptvc->pushed_tree_index <= 0)
@@ -735,7 +761,7 @@ ptvcursor_pop_subtree(ptvcursor_t *ptvc)
 
   ptvc->pushed_tree_index--;
   subtree = ptvc->pushed_tree+ptvc->pushed_tree_index;
-  if (subtree->it != NULL) 
+  if (subtree->it != NULL)
     proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
   ptvc->tree = subtree->tree;
 }
@@ -754,8 +780,8 @@ void ptvcursor_subtree_set_item(ptvcursor_t * ptvc, proto_item * it)
 
 /* Creates a subtree and adds it to the cursor as the working tree but does not
  * save the old working tree */
-proto_tree* 
-ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree) 
+proto_tree*
+ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
 {
   ptvc->tree = proto_item_add_subtree(it, ett_subtree);
   return ptvc->tree;
@@ -774,7 +800,7 @@ proto_tree* ptvcursor_add_subtree_item(ptvcursor_t * ptvc, proto_item * it, gint
  * In this case, when the subtree will be closed, the parent item length will
  * be equal to the advancement of the cursor since the creation of the subtree.
  */
-proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,  
+proto_tree* ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
 gboolean little_endian, gint ett_subtree)
 {
   proto_item * it;
@@ -790,13 +816,13 @@ proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint lengt
  * In this case, when the subtree will be closed, the item length will be equal
  * to the advancement of the cursor since the creation of the subtree.
  */
-proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length, 
+proto_tree * ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc, gint length,
     gint ett_subtree, const char *format, ...)
 {
   proto_item * it;
   va_list      ap;
 
-  it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc), 
+  it = proto_tree_add_text_node(ptvcursor_tree(ptvc), ptvcursor_tvbuff(ptvc),
       ptvcursor_current_offset(ptvc), length);
 
   va_start(ap, format);
@@ -864,11 +890,10 @@ proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
        va_list         ap;
 
        pi = proto_tree_add_text_node(tree, NULL, 0, 0);
-       if (pi == NULL)
-               return(NULL);
 
        va_start(ap, format);
-       proto_tree_set_representation(pi, format, ap);
+       if (pi)
+               proto_tree_set_representation(pi, format, ap);
        vprintf(format, ap);
        va_end(ap);
        printf("\n");
@@ -1023,8 +1048,8 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
 
                case FT_INT64:
                case FT_UINT64:
-                       DISSECTOR_ASSERT(length == 8);
-                       proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
+                       DISSECTOR_ASSERT( length <= 8 && length >= 1);
+                       proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
                        break;
 
                /* XXX - make these just FT_INT? */
@@ -1149,6 +1174,10 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
                        proto_tree_set_string(new_fi, string);
                        break;
 
+               case FT_EBCDIC:
+                       proto_tree_set_ebcdic_string_tvb(new_fi, tvb, start, length);
+                       break;
+
                case FT_UINT_STRING:
                        n = get_uint_value(tvb, start, length, little_endian);
                        proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
@@ -1442,6 +1471,8 @@ proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
        if (length > 0) {
                g_byte_array_append(bytes, start_ptr, length);
        }
+       col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str(bytes->data,
+                                                                  length));
        fvalue_set(&fi->value, bytes, TRUE);
 }
 
@@ -1532,7 +1563,16 @@ proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 static void
 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
 {
+       header_field_info       *hfinfo;
+
        DISSECTOR_ASSERT(value_ptr != NULL);
+       hfinfo = fi->hfinfo;
+
+       if (hfinfo->type == FT_ABSOLUTE_TIME) {
+               col_custom_set_fstr(fi->hfinfo, "%s", abs_time_to_str(value_ptr));
+       } else if (hfinfo->type == FT_RELATIVE_TIME) {
+               col_custom_set_fstr(fi->hfinfo, "%s", rel_time_to_secs_str(value_ptr));
+       }
        fvalue_set(&fi->value, value_ptr, FALSE);
 }
 
@@ -1695,6 +1735,8 @@ proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint st
 static void
 proto_tree_set_ipv4(field_info *fi, guint32 value)
 {
+       col_custom_set_fstr(fi->hfinfo, "%s",
+                           ip_to_str((guint8 *)&value));
        fvalue_set_uinteger(&fi->value, value);
 }
 
@@ -1867,6 +1909,8 @@ static void
 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
 {
        DISSECTOR_ASSERT(value_ptr != NULL);
+       col_custom_set_fstr(fi->hfinfo, "%s",
+                           guid_to_str(value_ptr));
        fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
 }
 
@@ -1966,6 +2010,8 @@ proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
        if (length > 0) {
                g_byte_array_append(bytes, value_ptr, length);
        }
+       col_custom_set_fstr(fi->hfinfo, "%s",
+                           oid_resolved_from_encoded(value_ptr, length));
        fvalue_set(&fi->value, bytes, TRUE);
 }
 
@@ -1978,16 +2024,45 @@ proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
 static void
 proto_tree_set_uint64(field_info *fi, guint64 value)
 {
+       col_custom_set_fstr(fi->hfinfo, "%" G_GINT64_MODIFIER "u",
+                           value);
        fvalue_set_integer64(&fi->value, value);
 }
 
 static void
-proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
+proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,  guint length, gboolean little_endian)
 {
-       guint64 value;
-
-       value = little_endian ? tvb_get_letoh64(tvb, start)
-                             : tvb_get_ntoh64(tvb, start);
+       guint64 value = 0;
+       guint8* b = ep_tvb_memdup(tvb,start,length);
+
+       if(little_endian) {
+               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;
+               }
+       }
 
        proto_tree_set_uint64(fi, value);
 }
@@ -2080,8 +2155,8 @@ proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
  * IF you must use this function you MUST also disable the
  * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
  * using proto_item_append_string().
- * Do that by faking that the tree is visible by setting :
- *   PTREE_DATA(tree)->visible=1;  (see packet-wsp.c)
+ * Do that by faking that the tree is visible by calling
+ * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
  * BEFORE you create the item you are later going to use
  * proto_item_append_string() on.
  */
@@ -2113,10 +2188,14 @@ proto_item_append_string(proto_item *pi, const char *str)
 static void
 proto_tree_set_string(field_info *fi, const char* value)
 {
-       if (value)
+       if (value) {
+               col_custom_set_fstr(fi->hfinfo, "%s",
+                                   format_text(value, strlen(value)));
                fvalue_set(&fi->value, (gpointer) value, FALSE);
-       else
+       } else {
+               col_custom_set_fstr(fi->hfinfo, "[ Null ]");
                fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
+       }
 }
 
 static void
@@ -2132,6 +2211,20 @@ proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length
        proto_tree_set_string(fi, string);
 }
 
+static void
+proto_tree_set_ebcdic_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
+{
+       gchar   *string;
+
+       if (length == -1) {
+               length = tvb_ensure_length_remaining(tvb, start);
+       }
+
+       string = tvb_get_ephemeral_string(tvb, start, length);
+       EBCDIC_to_ASCII(string, length);
+       proto_tree_set_string(fi, string);
+}
+
 /* Add a FT_ETHER to a proto_tree */
 proto_item *
 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
@@ -2211,6 +2304,7 @@ proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 static void
 proto_tree_set_ether(field_info *fi, const guint8* value)
 {
+       col_custom_set_fstr(fi->hfinfo, "%s", bytes_to_str_punct(value, 6, ':'));
        fvalue_set(&fi->value, (gpointer) value, FALSE);
 }
 
@@ -2380,6 +2474,8 @@ proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint s
 static void
 proto_tree_set_float(field_info *fi, float value)
 {
+       col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(FLT_DIG) "f",
+                           value);
        fvalue_set_floating(&fi->value, value);
 }
 
@@ -2461,6 +2557,8 @@ proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint
 static void
 proto_tree_set_double(field_info *fi, double value)
 {
+       col_custom_set_fstr(fi->hfinfo, "%." STRINGIFY(DBL_DIG) "g",
+                           value);
        fvalue_set_floating(&fi->value, value);
 }
 
@@ -2567,6 +2665,20 @@ proto_tree_set_uint(field_info *fi, guint32 value)
                        integer >>= hfinfo->bitshift;
                }
        }
+
+       if (hfinfo->type == FT_BOOLEAN) {
+               const true_false_string  *tfstring = &tfs_true_false;
+               if (hfinfo->strings) {
+                       tfstring = (const struct true_false_string*) hfinfo->strings;
+               }
+               col_custom_set_fstr(fi->hfinfo, "%s", value ? tfstring->true_string : tfstring->false_string);
+       } else if (hfinfo->strings) {
+               col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
+       } else if (IS_BASE_DUAL(hfinfo->display)) {
+               col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer, integer);
+       } else {
+               col_custom_set_fstr(fi->hfinfo, hfinfo_uint_value_format(hfinfo), integer);
+       }
        fvalue_set_uinteger(&fi->value, integer);
 }
 
@@ -2731,6 +2843,14 @@ proto_tree_set_int(field_info *fi, gint32 value)
                        integer >>= hfinfo->bitshift;
                }
        }
+
+       if (hfinfo->strings) {
+               col_custom_set_fstr(fi->hfinfo, "%s", val_to_str(integer, cVALS(hfinfo->strings), "%d"));
+       } else if (IS_BASE_DUAL(hfinfo->display)) {
+               col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer, integer);
+       } else {
+               col_custom_set_fstr(fi->hfinfo, hfinfo_int_value_format(hfinfo), integer);
+       }
        fvalue_set_sinteger(&fi->value, integer);
 }
 
@@ -3042,6 +3162,9 @@ new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
        /* add the data source tvbuff */
        fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
 
+       fi->appendix_start = 0;
+       fi->appendix_length = 0;
+
        return fi;
 }
 
@@ -3175,6 +3298,9 @@ proto_item_set_len(proto_item *pi, gint length)
        fi = PITEM_FINFO(pi);
        DISSECTOR_ASSERT(length >= 0);
        fi->length = length;
+
+       if (fi->value.ftype->ftype == FT_BYTES)
+               fi->value.value.bytes->len = length;
 }
 
 /*
@@ -3212,7 +3338,7 @@ proto_item_get_len(proto_item *pi)
 }
 
 gboolean
-proto_item_set_expert_flags(proto_item *pi, int group, int severity)
+proto_item_set_expert_flags(proto_item *pi, int group, guint severity)
 {
        if(pi == NULL || pi->finfo == NULL)
                return FALSE;
@@ -3385,6 +3511,22 @@ proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_
     }
 }
 
+void
+proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
+{
+       field_info *fi;
+
+       if (tree == NULL)
+               return;
+
+       fi = tree->finfo;
+       start += TVB_RAW_OFFSET(tvb);
+       DISSECTOR_ASSERT(start >= 0);
+       DISSECTOR_ASSERT(length >= 0);
+
+       fi->appendix_start = start;
+       fi->appendix_length = length;
+}
 
 int
 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
@@ -3415,7 +3557,7 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi
      */
 
     key = g_malloc (sizeof(gint));
-    *key = g_str_hash(name);
+    *key = wrs_str_hash(name);
     existing_name = g_hash_table_lookup(proto_names, key);
     if (existing_name != NULL) {
         /* g_error will terminate the program */
@@ -3424,14 +3566,12 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi
     }
     g_hash_table_insert(proto_names, key, (gpointer)name);
 
-    key = g_malloc (sizeof(gint));
-    *key = g_str_hash(short_name);
-    existing_name = g_hash_table_lookup(proto_short_names, key);
+    existing_name = 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);
     }
-    g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
+    g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
 
     found_invalid = FALSE;
     for (i = 0; i < strlen(filter_name); i++) {
@@ -3445,14 +3585,12 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi
             " Allowed are lower characters, digits, '-', '_' and '.'."
             " This might be caused by an inappropriate plugin or a development error.", filter_name);
     }
-    key = g_malloc (sizeof(gint));
-    *key = g_str_hash(filter_name);
-    existing_name = g_hash_table_lookup(proto_filter_names, key);
+    existing_name = g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
     if (existing_name != NULL) {
         g_error("Duplicate protocol filter_name \"%s\"!"
             " This might be caused by an inappropriate plugin or a development error.", filter_name);
     }
-    g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
+    g_hash_table_insert(proto_filter_names, (gpointer)filter_name, (gpointer)filter_name);
 
     /* Add this protocol to the list of known protocols; the list
        is sorted by protocol short name. */
@@ -3464,7 +3602,7 @@ proto_register_protocol(const char *name, const char *short_name, const char *fi
     protocol->is_enabled = TRUE; /* protocol is enabled by default */
     protocol->can_toggle = TRUE;
     /* list will be sorted later by name, when all protocols completed registering */
-    protocols = g_list_append(protocols, protocol);
+    protocols = g_list_prepend(protocols, protocol);
 
     /* Here we do allocate a new header_field_info struct */
     hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
@@ -3614,6 +3752,8 @@ proto_get_protocol_filter_name(int proto_id)
        protocol_t *protocol;
 
        protocol = find_protocol_by_id(proto_id);
+       if (protocol == NULL)
+               return "(none)";
        return protocol->filter_name;
 }
 
@@ -3642,6 +3782,23 @@ proto_set_decoding(int proto_id, gboolean enabled)
        protocol->is_enabled = enabled;
 }
 
+void
+proto_enable_all(void)
+{
+       protocol_t *protocol;
+       GList *list_item = protocols;
+
+       if (protocols == NULL)
+               return;
+
+       while (list_item) {
+               protocol = list_item->data;
+               if (protocol->can_toggle)
+                       protocol->is_enabled = TRUE;
+               list_item = g_list_next(list_item);
+       }
+}
+
 void
 proto_set_cant_toggle(int proto_id)
 {
@@ -3691,9 +3848,29 @@ proto_register_field_array(int parent, hf_register_info *hf, int num_records)
        }
 }
 
-static int
-proto_register_field_init(header_field_info *hfinfo, int parent)
-{
+/* chars allowed in field abbrev */
+static
+const guchar fld_abbrev_chars[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.'     */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9'      */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O'      */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o'      */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z'      */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
+};
+
+/* temporary function containing assert part for easier profiling */
+static void tmp_fld_check_assert(header_field_info *hfinfo) {
        /* The field must have a name (with length > 0) */
        DISSECTOR_ASSERT(hfinfo->name && hfinfo->name[0]);
 
@@ -3738,10 +3915,17 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
        default:
                break;
        }
+}
+
+static int
+proto_register_field_init(header_field_info *hfinfo, int parent)
+{
+
+       tmp_fld_check_assert(hfinfo);
+
        /* if this is a bitfield, compute bitshift */
        if (hfinfo->bitmask) {
-               while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
-                       hfinfo->bitshift++;
+               hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
        }
 
        hfinfo->parent = parent;
@@ -3765,19 +3949,17 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
        /* if we have real names, enter this field in the name tree */
        if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
 
-               header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
-               const char *p;
+               header_field_info *same_name_next_hfinfo;
                guchar c;
 
                /* Check that the filter name (abbreviation) is legal;
                 * it must contain only alphanumerics, '-', "_", and ".". */
-               for (p = hfinfo->abbrev; (c = *p) != '\0'; p++) {
-                       if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) {
-                               fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
-                               DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
-                                       c == '.');
-                       }
+               c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
+               if (c) {
+                       fprintf(stderr, "OOPS: '%c' in '%s'\n", c, hfinfo->abbrev);
+                       DISSECTOR_ASSERT(!c);
                }
+
                /* We allow multiple hfinfo's to be registered under the same
                 * abbreviation. This was done for X.25, as, depending
                 * on whether it's modulo-8 or modulo-128 operation,
@@ -3788,8 +3970,12 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
 #if GLIB_MAJOR_VERSION < 2
                same_name_hfinfo = g_tree_lookup(gpa_name_tree, discard_const(hfinfo->abbrev));
 #else
-               same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
+               same_name_hfinfo = NULL;
 #endif
+               g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
+               /* GLIB 2.x - if it is already present
+         * the previous hfinfo with the same name is saved
+         * to same_name_hfinfo by value destroy callback */
                if (same_name_hfinfo) {
                        /* There's already a field with this name.
                         * Put it after that field in the list of
@@ -3808,7 +3994,6 @@ proto_register_field_init(header_field_info *hfinfo, int parent)
                        same_name_hfinfo->same_name_next = hfinfo;
                        hfinfo->same_name_prev = same_name_hfinfo;
                }
-               g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
        }
 
        return hfinfo->id;
@@ -4026,15 +4211,15 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                case FT_OID:
                        bytes = fvalue_get(&fi->value);
-                       name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
+                       name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
                        if (name) {
                                ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                        "%s: %s (%s)", hfinfo->name,
-                                        oid_to_str(bytes, fvalue_length(&fi->value)), name);
+                                        oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
                        } else {
                                ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                        "%s: %s", hfinfo->name,
-                                        oid_to_str(bytes, fvalue_length(&fi->value)));
+                                        oid_encoded2string(bytes, fvalue_length(&fi->value)));
                        }
                        if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
                                label_str[ITEM_LABEL_LENGTH - 1] = '\0';
@@ -4042,6 +4227,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
 
                case FT_STRING:
                case FT_STRINGZ:
+               case FT_EBCDIC:
                case FT_UINT_STRING:
                        bytes = fvalue_get(&fi->value);
            if(strlen(bytes) > ITEM_LABEL_LENGTH) {
@@ -4498,6 +4684,90 @@ hfinfo_uint_format(header_field_info *hfinfo)
        return format;
 }
 
+static const char*
+hfinfo_uint_value_format(header_field_info *hfinfo)
+{
+       const char *format = NULL;
+
+       /* Pick the proper format string */
+       if (hfinfo->type == FT_FRAMENUM) {
+               /*
+                * Frame numbers are always displayed in decimal.
+                */
+               format = "%u";
+       } else {
+               switch(hfinfo->display) {
+                       case BASE_DEC:
+                               format = "%u";
+                               break;
+                       case BASE_DEC_HEX:
+                               switch(hfinfo->type) {
+                                       case FT_UINT8:
+                                               format = "%u (0x%02x)";
+                                               break;
+                                       case FT_UINT16:
+                                               format = "%u (0x%04x)";
+                                               break;
+                                       case FT_UINT24:
+                                               format = "%u (0x%06x)";
+                                               break;
+                                       case FT_UINT32:
+                                               format = "%u (0x%08x)";
+                                               break;
+                                       default:
+                                               DISSECTOR_ASSERT_NOT_REACHED();
+                                               ;
+                               }
+                               break;
+                       case BASE_OCT:
+                               format = "%o";
+                               break;
+                       case BASE_HEX:
+                               switch(hfinfo->type) {
+                                       case FT_UINT8:
+                                               format = "0x%02x";
+                                               break;
+                                       case FT_UINT16:
+                                               format = "0x%04x";
+                                               break;
+                                       case FT_UINT24:
+                                               format = "0x%06x";
+                                               break;
+                                       case FT_UINT32:
+                                               format = "0x%08x";
+                                               break;
+                                       default:
+                                               DISSECTOR_ASSERT_NOT_REACHED();
+                                               ;
+                               }
+                               break;
+                       case BASE_HEX_DEC:
+                               switch(hfinfo->type) {
+                                       case FT_UINT8:
+                                               format = "0x%02x (%u)";
+                                               break;
+                                       case FT_UINT16:
+                                               format = "0x%04x (%u)";
+                                               break;
+                                       case FT_UINT24:
+                                               format = "0x%06x (%u)";
+                                               break;
+                                       case FT_UINT32:
+                                               format = "0x%08x (%u)";
+                                               break;
+                                       default:
+                                               DISSECTOR_ASSERT_NOT_REACHED();
+                                               ;
+                               }
+                               break;
+                       default:
+                               DISSECTOR_ASSERT_NOT_REACHED();
+                               ;
+               }
+       }
+       return format;
+}
+
 static const char*
 hfinfo_int_vals_format(header_field_info *hfinfo)
 {
@@ -4597,6 +4867,7 @@ hfinfo_int_format(header_field_info *hfinfo)
                                        DISSECTOR_ASSERT_NOT_REACHED();
                                        ;
                        }
+                       break;
                case BASE_OCT: /* I'm lazy */
                        format = "%s: %o";
                        break;
@@ -4645,6 +4916,83 @@ hfinfo_int_format(header_field_info *hfinfo)
        return format;
 }
 
+static const char*
+hfinfo_int_value_format(header_field_info *hfinfo)
+{
+       const char *format = NULL;
+
+       /* Pick the proper format string */
+       switch(hfinfo->display) {
+               case BASE_DEC:
+                       format = "%d";
+                       break;
+               case BASE_DEC_HEX:
+                       switch(hfinfo->type) {
+                               case FT_INT8:
+                                       format = "%d (0x%02x)";
+                                       break;
+                               case FT_INT16:
+                                       format = "%d (0x%04x)";
+                                       break;
+                               case FT_INT24:
+                                       format = "%d (0x%06x)";
+                                       break;
+                               case FT_INT32:
+                                       format = "%d (0x%08x)";
+                                       break;
+                               default:
+                                       DISSECTOR_ASSERT_NOT_REACHED();
+                                       ;
+                       }
+                       break;
+               case BASE_OCT:
+                       format = "%o";
+                       break;
+               case BASE_HEX:
+                       switch(hfinfo->type) {
+                               case FT_INT8:
+                                       format = "0x%02x";
+                                       break;
+                               case FT_INT16:
+                                       format = "0x%04x";
+                                       break;
+                               case FT_INT24:
+                                       format = "0x%06x";
+                                       break;
+                               case FT_INT32:
+                                       format = "0x%08x";
+                                       break;
+                               default:
+                                       DISSECTOR_ASSERT_NOT_REACHED();
+                                       ;
+                       }
+                       break;
+               case BASE_HEX_DEC:
+                       switch(hfinfo->type) {
+                               case FT_INT8:
+                                       format = "0x%02x (%d)";
+                                       break;
+                               case FT_INT16:
+                                       format = "0x%04x (%d)";
+                                       break;
+                               case FT_INT24:
+                                       format = "0x%06x (%d)";
+                                       break;
+                               case FT_INT32:
+                                       format = "0x%08x (%d)";
+                                       break;
+                               default:
+                                       DISSECTOR_ASSERT_NOT_REACHED();
+                                       ;
+                       }
+                       break;
+               default:
+                       DISSECTOR_ASSERT_NOT_REACHED();
+                       ;
+       }
+       return format;
+}
+
 static const char*
 hfinfo_int64_format(header_field_info *hfinfo)
 {
@@ -5618,7 +5966,7 @@ proto_tree_add_bits_item(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint bit
        return proto_tree_add_bits_ret_val(tree, hf_index, tvb, bit_offset, no_of_bits, NULL, little_endian);
 
 }
-/* 
+/*
  * This function will dissect a sequence of bits that does not need to be byte aligned the bits
  * set vill be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
  * Offset should be given in bits from the start of the tvb.
@@ -5644,7 +5992,7 @@ proto_tree_add_bits_ret_val(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint
        offset = bit_offset>>3;
 
 
-       /*  
+       /*
         * Calculate the number of octets used to hold the bits
         */
        tot_no_bits = ((bit_offset&0x7)+no_of_bits);