#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 "emem.h"
+#include "wmem/wmem.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. */
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
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);
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);
proto_tree_set_eui64(field_info *fi, const guint64 value);
static void
proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
-static gboolean
-proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
- const int len, const gint ett, const gint **fields,
- const guint encoding, const int flags,
- gboolean first);
+
+/* Handle type length mismatch (now filterable) expert info */
+static int proto_type_length_mismatch = -1;
+static expert_field ei_type_length_mismatch_error = EI_INIT;
+static expert_field ei_type_length_mismatch_warn = EI_INIT;
+static void register_type_length_mismatch(void);
static int proto_register_field_init(header_field_info *hfinfo, const int parent);
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 */
/* List of all protocols */
static GList *protocols = NULL;
-#define INITIAL_NUM_PROTOCOL_HFINFO 1500
-
/* Contains information about a field when a dissector calls
* proto_tree_add_item. */
-#define FIELD_INFO_NEW(fi) fi = g_slice_new(field_info)
-#define FIELD_INFO_FREE(fi) g_slice_free(field_info, fi)
+#define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
+#define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
/* Contains the space for proto_nodes. */
-#define PROTO_NODE_NEW(node) \
- node = g_slice_new(proto_node); \
- node->first_child = NULL; \
- node->last_child = NULL; \
+#define PROTO_NODE_INIT(node) \
+ node->first_child = NULL; \
+ node->last_child = NULL; \
node->next = NULL;
-#define PROTO_NODE_FREE(node) \
- g_slice_free(proto_node, node)
+#define PROTO_NODE_FREE(pool, node) \
+ wmem_free(pool, node)
/* String space for protocol and field items for the GUI */
-#define ITEM_LABEL_NEW(il) \
- il = g_slice_new(item_label_t);
-#define ITEM_LABEL_FREE(il) \
- g_slice_free(item_label_t, il);
+#define ITEM_LABEL_NEW(pool, il) \
+ il = wmem_new(pool, item_label_t);
+#define ITEM_LABEL_FREE(pool, il) \
+ wmem_free(pool, il);
#define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
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
/* Register the pseudo-protocols used for exceptions. */
register_show_exception();
+ register_type_length_mismatch();
/* Have each built-in dissector register its protocols, fields,
dissector tables, and dissectors to be called through a
#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
/* 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 */
}
static void
-free_node_tree_data(tree_data_t *tree_data)
+proto_tree_free_node(proto_node *node, gpointer data _U_)
+{
+ field_info *finfo = PNODE_FINFO(node);
+
+ proto_tree_children_foreach(node, proto_tree_free_node, NULL);
+
+ FVALUE_CLEANUP(&finfo->value);
+}
+
+void
+proto_tree_reset(proto_tree *tree)
{
+ tree_data_t *tree_data = PTREE_DATA(tree);
+
+ proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
+
+ /* free tree data */
if (tree_data->interesting_hfids) {
/* Free all the GPtrArray's in the interesting_hfids hash. */
g_hash_table_foreach(tree_data->interesting_hfids,
/* And then destroy the hash. */
g_hash_table_destroy(tree_data->interesting_hfids);
- }
- if (tree_data->fi_tmp)
- FIELD_INFO_FREE(tree_data->fi_tmp);
- /* And finally the tree_data_t itself. */
- g_free(tree_data);
-}
-
-#define FREE_NODE_FIELD_INFO(finfo) \
- if (finfo->rep) { \
- ITEM_LABEL_FREE(finfo->rep); \
- } \
- FVALUE_CLEANUP(&finfo->value); \
- FIELD_INFO_FREE(finfo);
-
-static void
-proto_tree_free_node(proto_node *node, gpointer data _U_)
-{
- field_info *finfo = PNODE_FINFO(node);
-
- proto_tree_children_foreach(node, proto_tree_free_node, NULL);
+ tree_data->interesting_hfids = NULL;
+ }
- /* free the field_info data. */
- FREE_NODE_FIELD_INFO(finfo);
- node->finfo = NULL;
+ /* Reset track of the number of children */
+ tree_data->count = 0;
- /* Free the proto_node. */
- PROTO_NODE_FREE(node);
+ PROTO_NODE_INIT(tree);
}
/* frees the resources that the dissection a proto_tree uses */
proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
- /* free root node */
- PROTO_NODE_FREE(tree);
-
/* free tree data */
- free_node_tree_data(tree_data);
+ if (tree_data->interesting_hfids) {
+ /* Free all the GPtrArray's in the interesting_hfids hash. */
+ g_hash_table_foreach(tree_data->interesting_hfids,
+ free_GPtrArray_value, NULL);
+
+ /* And then destroy the hash. */
+ g_hash_table_destroy(tree_data->interesting_hfids);
+ }
+
+ g_slice_free(tree_data_t, tree_data);
+
+ g_slice_free(proto_tree, tree);
}
/* Is the parsing being done for a visible proto_tree or an invisible one?
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 == '.') {
}
}
- 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? */
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) {
- if (tree) {
- tree_data_t *tree_data = PTREE_DATA(tree);
- field_info *fi_save = tree_data->fi_tmp;
-
- /* Keep the current item from getting freed by proto_tree_new_item. */
- tree_data->fi_tmp = NULL;
-
- expert_add_info_format_internal(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
- tree_data->fi_tmp = fi_save;
+ if (is_error) {
+ expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
+ } else {
+ expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
}
if (is_error) {
tvbuff_t *tvb, gint start, gint length,
guint encoding)
{
- tree_data_t *tree_data = PTREE_DATA(tree);
proto_item *pi;
guint32 value, n;
float floatval;
guint64 todsecs;
gboolean length_error;
- /* there is a possibility here that we might raise an exception
- * and thus would lose track of the field_info.
- * store it in a temp so that if we come here again we can reclaim
- * the field_info without leaking memory.
- */
- if (tree_data->fi_tmp) {
- /* oops, last one we got must have been lost due
- * to an exception.
- * good thing we saved it, now we can reverse the
- * memory leak and reclaim it.
- */
- FIELD_INFO_FREE(tree_data->fi_tmp);
- }
- /* we might throw an exception, keep track of this one
- * across the "dangerous" section below.
- */
- tree_data->fi_tmp = new_fi;
-
switch (new_fi->hfinfo->type) {
case FT_NONE:
/* no value to set for FT_NONE */
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? */
break;
case FT_OID:
+ case FT_REL_OID:
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
*/
if (length == -1) {
/* This can throw an exception */
- string = tvb_get_stringz_enc(tvb, start, &length, encoding);
+ string = tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
} else if (length == 0) {
string = "[Empty]";
} else {
* we made string values counted
* rather than null-terminated.)
*/
- string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
+ string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
}
new_fi->length = length;
proto_tree_set_string(new_fi, string);
* 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
* 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
* 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);
*/
/* 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
*/
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 */
*/
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 */
default:
DISSECTOR_ASSERT_NOT_REACHED();
- time_stamp.secs = 0;
+ time_stamp.secs = (time_t)0;
time_stamp.nsecs = 0;
break;
}
* 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
* 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
* to know which item caused exception? */
pi = proto_tree_add_node(tree, new_fi);
- /* we did not raise an exception so we dont have to remember this
- * field_info struct any more.
- */
- tree_data->fi_tmp = NULL;
-
return pi;
}
* start (pos/neg). Throws an exception if they aren't.
*/
static void
-test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
- gint start, gint length, const guint encoding)
+test_length(header_field_info *hfinfo, tvbuff_t *tvb,
+ gint start, gint length)
{
gint size = length;
if (!tvb)
return;
- if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
- guint32 n;
-
- n = get_uint_value(tree, tvb, start, length, encoding);
- if (n > size + n) {
- /* If n > size + n then we have an integer overflow, so
- * set size to -1, which will force the
- * tvb_ensure_bytes_exist call below to throw a
- * ReportedBoundsError
- */
- size = -1;
- }
- else {
- size += n;
- }
- } else if (hfinfo->type == FT_STRINGZ) {
+ if (hfinfo->type == FT_STRINGZ) {
/* If we're fetching until the end of the TVB, only validate
* that the offset is within range.
*/
DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
get_hfi_length(hfinfo, tvb, start, &length, &item_length);
- test_length(hfinfo, tree, tvb, start, item_length, encoding);
+ test_length(hfinfo, tvb, start, item_length);
TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
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 */
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 */
{
GByteArray *bytes;
+ DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
+
bytes = g_byte_array_new();
if (length > 0) {
g_byte_array_append(bytes, start_ptr, length);
}
- fvalue_set(&fi->value, bytes, TRUE);
+ fvalue_set_byte_array(&fi->value, bytes);
}
/* 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;
/* 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 */
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
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
{
GByteArray *bytes;
- DISSECTOR_ASSERT(value_ptr != NULL);
+ 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(&fi->value, bytes, TRUE);
+ fvalue_set_byte_array(&fi->value, bytes);
}
static void
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)
{
guint length, const guint encoding)
{
guint64 value = 0;
- guint8* b = (guint8 *)ep_tvb_memdup(tvb, start, length);
+ guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
if (encoding) {
b += length;
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 *
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);
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,
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 */
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 ]");
}
}
length = tvb_ensure_length_remaining(tvb, start);
}
- string = tvb_get_ephemeral_string_enc(tvb, start, length, encoding);
+ string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
proto_tree_set_string(fi, string);
}
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
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
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
/* 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);
/* XXX - is it safe to continue here? */
}
- PROTO_NODE_NEW(pnode);
+ pnode = wmem_new(PNODE_POOL(tree), proto_node);
+ PROTO_NODE_INIT(pnode);
pnode->parent = tnode;
PNODE_FINFO(pnode) = fi;
pnode->tree_data = PTREE_DATA(tree);
{
field_info *fi;
- FIELD_INFO_NEW(fi);
+ FIELD_INFO_NEW(PNODE_POOL(tree), fi);
fi->hfinfo = hfinfo;
fi->start = start;
hf = fi->hfinfo;
- ITEM_LABEL_NEW(fi->rep);
+ ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
guint32 val;
char *p;
DISSECTOR_ASSERT(fi);
if (!PROTO_ITEM_IS_HIDDEN(pi)) {
- ITEM_LABEL_NEW(fi->rep);
+ ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
format, ap);
if (ret >= ITEM_LABEL_LENGTH) {
}
}
+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)
{
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;
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;
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);
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;
+ case FT_REL_OID:
+ bytes = (guint8 *)fvalue_get(&finfo->value);
+ offset_r += protoo_strlcpy(result+offset_r,
+ rel_oid_resolved_from_encoded(bytes,
+ fvalue_length(&finfo->value)),
+ size-offset_r);
+ offset_e += protoo_strlcpy(expr+offset_e,
+ rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)),
+ size-offset_e);
+ break;
+
case FT_OID:
bytes = (guint8 *)fvalue_get(&finfo->value);
offset_r += protoo_strlcpy(result+offset_r,
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;
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;
case FT_INT24:
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;
return;
if (fi->rep) {
- ITEM_LABEL_FREE(fi->rep);
+ ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
fi->rep = NULL;
}
* generate the default representation.
*/
if (fi->rep == NULL) {
- ITEM_LABEL_NEW(fi->rep);
+ ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
proto_item_fill_label(fi, fi->rep->representation);
}
* generate the default representation.
*/
if (fi->rep == NULL) {
- ITEM_LABEL_NEW(fi->rep);
+ ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
proto_item_fill_label(fi, representation);
} else
g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
proto_node *pnode;
/* Initialize the proto_node */
- PROTO_NODE_NEW(pnode);
+ pnode = g_slice_new(proto_tree);
+ PROTO_NODE_INIT(pnode);
pnode->parent = NULL;
PNODE_FINFO(pnode) = NULL;
- pnode->tree_data = g_new(tree_data_t, 1);
+ pnode->tree_data = g_slice_new(tree_data_t);
/* Make sure we can access pinfo everywhere */
pnode->tree_data->pinfo = pinfo;
/* Keep track of the number of children */
pnode->tree_data->count = 0;
- pnode->tree_data->fi_tmp = NULL;
-
return (proto_tree *)pnode;
}
}
proto_tree *
-proto_item_get_subtree(const proto_item *pi) {
+proto_item_get_subtree(proto_item *pi) {
field_info *fi;
if (!pi)
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;
const char *filter_name)
{
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;
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\"!"
}
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);
" Allowed are lower characters, digits, '-', '_' and '.'."
" This might be caused by an inappropriate plugin or a development error.", filter_name);
}
- existing_name = (char *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
- if (existing_name != NULL) {
+ 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);
}
- 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. */
protocol->is_private = FALSE;
/* list will be sorted later by name, when all protocols completed registering */
protocols = g_list_prepend(protocols, protocol);
+ g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
/* Here we allocate a new header_field_info struct */
hfinfo = g_slice_new(header_field_info);
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)
{
int proto_get_id_by_filter_name(const gchar* filter_name)
{
- GList *list_entry;
- protocol_t *protocol;
+ const protocol_t *protocol = NULL;
if(!filter_name){
fprintf(stderr, "No filter name present");
DISSECTOR_ASSERT(filter_name);
}
- list_entry = g_list_find_custom(protocols, filter_name,
- compare_filter_name);
+ protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
- if (list_entry == NULL)
+ if (protocol == NULL)
return -1;
- protocol = (protocol_t *)list_entry->data;
return protocol->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)
{
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++) {
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;
*/
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);
}
}
{ FT_PCRE, "FT_PCR" },
{ 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[] = {
{ 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" },
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) ||
* 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:
* 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:
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",
}
}
-#define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM)
+static void
+register_type_length_mismatch(void)
+{
+ static ei_register_info ei[] = {
+ { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
+ { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
+ };
+
+ expert_module_t* expert_type_length_mismatch;
+
+ proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
+
+ expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
+ expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
+
+ /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
+ disabling them makes no sense. */
+ proto_set_cant_toggle(proto_type_length_mismatch);
+}
+
+#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)
{
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:
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:
g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s", hfinfo->name,
- address_to_str( &addr ));
+ ep_address_to_str( &addr ));
break;
case FT_ETHER:
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:
oid_encoded2string(bytes, fvalue_length(&fi->value)));
}
break;
+
+ case FT_REL_OID:
+ bytes = (guint8 *)fvalue_get(&fi->value);
+ name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
+ if (name) {
+ label_fill_descr(label_str, 0, hfinfo,
+ rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
+ } else {
+ label_fill(label_str, 0, hfinfo,
+ rel_oid_encoded2string(bytes, fvalue_length(&fi->value)));
+ }
+ 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,
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:
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 {
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
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)
{
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) {
/*
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;
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;
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;
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 ||
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,
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;
{
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;
}
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) {
proto_item *
proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
const guint offset, const guint len, const int hf_hdr,
- const gint ett, const int **fields,
+ const gint ett, const int **fields, struct expert_field* exp,
const guint encoding)
{
proto_item *item = NULL;
header_field_info *hf;
+ guint decodable_len;
+ guint decodable_offset;
+ guint32 decodable_value;
hf = proto_registrar_get_nth(hf_hdr);
DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
- if (parent_tree) {
- guint decodable_len;
- guint decodable_offset;
- guint32 decodable_value;
-
- decodable_offset = offset;
- decodable_len = MIN(len, (guint) ftype_length(hf->type));
+ decodable_offset = offset;
+ decodable_len = MIN(len, (guint) ftype_length(hf->type));
- /* If we are ftype_length-limited,
- * make sure we decode as many LSBs as possible.
- */
- if (encoding == ENC_BIG_ENDIAN) {
- decodable_offset += (len - decodable_len);
- }
+ /* If we are ftype_length-limited,
+ * make sure we decode as many LSBs as possible.
+ */
+ if (encoding == ENC_BIG_ENDIAN) {
+ decodable_offset += (len - decodable_len);
+ }
+ if (parent_tree) {
decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
decodable_len, encoding);
/* The root item covers all the bytes even if we can't decode them all */
item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
decodable_value);
+ }
- if (decodable_len < len) {
- /* Dissector likely requires updating for new protocol revision */
- expert_add_info_format_internal(NULL, item, PI_UNDECODED, PI_WARN,
- "Only least-significant %d of %d bytes decoded",
- decodable_len, len);
- }
+ if (decodable_len < len) {
+ /* Dissector likely requires updating for new protocol revision */
+ expert_add_info_format(NULL, item, exp,
+ "Only least-significant %d of %d bytes decoded",
+ decodable_len, len);
+ }
+ if (item) {
proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
}
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);
octet_length = (no_of_bits + 7) >> 3;
octet_offset = bit_offset >> 3;
- test_length(hfinfo, tree, tvb, octet_offset, octet_length, encoding);
+ test_length(hfinfo, tvb, octet_offset, octet_length);
/* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
* but only after doing a bunch more work (which we can, in the common
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:
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;
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)
{