#include <ctype.h>
#include <glib.h>
#include <float.h>
+#include <wsutil/swar.h>
#include "packet.h"
#include "ptvcursor.h"
gint offset;
};
-/* Candidates for assembler */
-static int
-wrs_count_bitshift(const guint32 bitmask)
-{
- int bitshift = 0;
-
- while ((bitmask & (1 << bitshift)) == 0)
- bitshift++;
- return bitshift;
-}
-
#define cVALS(x) (const value_string*)(x)
/** See inlined comments.
static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
static void fill_label_boolean(field_info *fi, gchar *label_str);
-static void fill_label_bitfield(field_info *fi, gchar *label_str);
+static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
static proto_item *
proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
- gint start, gint *length, field_info **pfi);
+ gint start, gint *length);
static void
proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
static void
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);
+static void
+proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
+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);
const char *short_name; /* short description */
const char *filter_name; /* name of this protocol in filters */
int proto_id; /* field ID for this protocol */
- GList *fields; /* fields for this protocol */
- GList *last_field; /* pointer to end of list of fields */
+ GSList *fields; /* fields for this protocol */
+ GSList *last_field; /* pointer to end of list of fields */
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 */
guint32 allocated_len;
header_field_info **hfi;
} gpa_hfinfo_t;
-gpa_hfinfo_t gpa_hfinfo;
+
+static gpa_hfinfo_t gpa_hfinfo;
/* Balanced tree of abbreviations and IDs */
static GTree *gpa_name_tree = NULL;
DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
g_slice_free(header_field_info, hfinfo);
- g_list_free(protocol->fields);
+ g_slist_free(protocol->fields);
protocols = g_list_remove(protocols, protocol);
g_free(protocol);
}
proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
{
proto_item *pi;
- field_info *new_fi;
if (tree == NULL)
return NULL;
- pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length, &new_fi);
+ pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
return pi;
}
/* 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) {
- tree_data_t *tree_data = PTREE_DATA(tree);
- field_info *fi_save = tree_data->fi_tmp;
+ 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;
+ /* Keep the current item from getting freed by proto_tree_new_item. */
+ tree_data->fi_tmp = NULL;
- expert_add_info_format(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length);
+ expert_add_info_format(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;
+ tree_data->fi_tmp = fi_save;
+ }
if (is_error) {
THROW(ReportedBoundsError);
proto_tree_set_ax25_tvb(new_fi, tvb, start);
break;
+ case FT_VINES:
+ if (length != VINES_ADDR_LEN) {
+ length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
+ report_type_length_mismatch(tree, "a Vines address", length, length_error);
+ }
+ proto_tree_set_vines_tvb(new_fi, tvb, start);
+ break;
+
case FT_ETHER:
if (length != FT_ETHER_LEN) {
length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
/* Add an item to a proto_tree, using the text label registered to that item;
the item is extracted from the tvbuff handed to it. */
proto_item *
-proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
+proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
const gint start, gint length, const guint encoding)
{
field_info *new_fi;
- header_field_info *hfinfo;
gint item_length;
- PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ 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);
- TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
+ TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
}
+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);
+}
+
/* Add a FT_NONE to a proto_tree */
proto_item *
proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
proto_item *pi;
va_list ap;
header_field_info *hfinfo;
- field_info *new_fi;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
TRY_TO_FAKE_THIS_REPR(pi);
{
proto_item *pi;
va_list ap;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
- proto_tree_set_protocol_tvb(new_fi, (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
+ proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
TRY_TO_FAKE_THIS_REPR(pi);
gint length, const guint8 *start_ptr)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_bytes(new_fi, start_ptr, length);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
return pi;
}
gint length, nstime_t *value_ptr)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
hfinfo->type == FT_RELATIVE_TIME);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_time(new_fi, value_ptr);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
return pi;
}
gint length, guint32 value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_ipxnet(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
return pi;
}
gint length, guint32 value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_ipv4(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_ipv4(PNODE_FINFO(pi), value);
return pi;
}
gint length, const guint8* value_ptr)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_ipv6(new_fi, value_ptr);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
return pi;
}
gint length, const e_guid_t *value_ptr)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_guid(new_fi, value_ptr);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
return pi;
}
gint length, const guint8* value_ptr)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_OID);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_oid(new_fi, value_ptr, length);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
return pi;
}
gint length, const char* value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
DISSECTOR_ASSERT(length >= 0);
- proto_tree_set_string(new_fi, value);
+ proto_tree_set_string(PNODE_FINFO(pi), value);
return pi;
}
const guint8* value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_ax25(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_ax25(PNODE_FINFO(pi), value);
return pi;
}
proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
}
+/* Set the FT_VINES value */
+static void
+proto_tree_set_vines(field_info *fi, const guint8* value)
+{
+ fvalue_set(&fi->value, (gpointer) value, FALSE);
+}
+
+static void
+proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
+{
+ proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
+}
/* Add a FT_ETHER to a proto_tree */
proto_item *
gint length, const guint8* value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_ether(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_ether(PNODE_FINFO(pi), value);
return pi;
}
gint length, guint32 value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_boolean(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_boolean(PNODE_FINFO(pi), value);
return pi;
}
gint length, float value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_float(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_float(PNODE_FINFO(pi), value);
return pi;
}
gint length, double value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_double(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_double(PNODE_FINFO(pi), value);
return pi;
}
gint length, guint32 value)
{
proto_item *pi = NULL;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
case FT_UINT24:
case FT_UINT32:
case FT_FRAMENUM:
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length,
- &new_fi);
- proto_tree_set_uint(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_uint(PNODE_FINFO(pi), value);
break;
default:
integer &= hfinfo->bitmask;
/* Shift bits */
- if (hfinfo->bitshift > 0) {
- integer >>= hfinfo->bitshift;
- }
+ integer >>= hfinfo_bitshift(hfinfo);
}
fvalue_set_uinteger(&fi->value, integer);
proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
gint length, guint64 value)
{
- proto_item *pi = NULL;
- field_info *new_fi;
+ proto_item *pi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_uint64(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_uint64(PNODE_FINFO(pi), value);
return pi;
}
gint length, gint32 value)
{
proto_item *pi = NULL;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
case FT_INT16:
case FT_INT24:
case FT_INT32:
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length,
- &new_fi);
- proto_tree_set_int(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_int(PNODE_FINFO(pi), value);
break;
default:
{
header_field_info *hfinfo;
guint32 integer;
+ gint no_of_bits;
hfinfo = fi->hfinfo;
integer = (guint32) value;
integer &= hfinfo->bitmask;
/* Shift bits */
- if (hfinfo->bitshift > 0) {
- integer >>= hfinfo->bitshift;
- }
+ integer >>= hfinfo_bitshift(hfinfo);
+
+ no_of_bits = swar_count_bits(hfinfo->bitmask);
+ if (integer & (1 << (no_of_bits-1)))
+ integer |= (-1 << no_of_bits);
}
fvalue_set_sinteger(&fi->value, integer);
proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
gint length, gint64 value)
{
- proto_item *pi = NULL;
- field_info *new_fi;
+ proto_item *pi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_uint64(new_fi, (guint64)value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
return pi;
}
gint length, const guint64 value)
{
proto_item *pi;
- field_info *new_fi;
header_field_info *hfinfo;
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
- pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length, &new_fi);
- proto_tree_set_eui64(new_fi, value);
+ pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
+ proto_tree_set_eui64(PNODE_FINFO(pi), value);
return pi;
}
* Sets *pfi to address of newly-allocated field_info struct */
static proto_item *
proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
- gint *length, field_info **pfi)
+ gint *length)
{
proto_item *pi;
field_info *fi;
fi = alloc_field_info(tree, hfinfo, tvb, start, length);
pi = proto_tree_add_node(tree, fi);
- *pfi = fi;
-
return pi;
}
return new_field_info(tree, hfinfo, tvb, start, item_length);
}
+static void
+label_mark_truncated_start(char *label_str)
+{
+ static const char trunc_str[] = "[truncated] ";
+ const size_t trunc_len = sizeof(trunc_str)-1;
+
+ memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
+ memcpy(label_str, trunc_str, trunc_len);
+ label_str[ITEM_LABEL_LENGTH-1] = '\0';
+}
+
/* If the protocol tree is to be visible, set the representation of a
proto_tree entry with the name of the field for the item and with
the value formatted with the supplied printf-style format and
char *p;
val = fvalue_get_uinteger(&fi->value);
- if (hf->bitshift > 0)
- val <<= hf->bitshift;
+ val <<= hfinfo_bitshift(hf);
p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
ret = (int) (p - fi->rep->representation);
/* Uh oh, we don't have enough room. Tell the user
* that the field is truncated.
*/
- char *oldrep;
-
- /* Argh, we cannot reuse 'ap' here. So make a copy
- * of what we formatted for (re)use below.
- */
- oldrep = g_strdup(fi->rep->representation);
-
- g_snprintf(fi->rep->representation,
- ITEM_LABEL_LENGTH,
- "[truncated] %s",
- oldrep);
- g_free(oldrep);
+ /* XXX, label_mark_truncated() ? */
+ label_mark_truncated_start(fi->rep->representation);
}
}
}
/* Uh oh, we don't have enough room. Tell the user
* that the field is truncated.
*/
- char *oldrep;
-
- /* Argh, we cannot reuse 'ap' here. So make a copy
- * of what we formatted for (re)use below.
- */
- oldrep = g_strdup(fi->rep->representation);
-
- g_snprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
- "[truncated] %s", oldrep);
- g_free(oldrep);
+ label_mark_truncated_start(fi->rep->representation);
}
}
}
return (int) res;
}
+static header_field_info *
+hfinfo_same_name_get_prev(const header_field_info *hfinfo)
+{
+ if (hfinfo->same_name_prev_id == -1)
+ return NULL;
+ return proto_registrar_get_nth(hfinfo->same_name_prev_id);
+}
+
/* -------------------------- */
const gchar *
proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
if (occurrence < 0) {
/* Search other direction */
- while (hfinfo->same_name_prev) {
- hfinfo = hfinfo->same_name_prev;
+ while (hfinfo->same_name_prev_id != -1) {
+ hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
}
}
if (occurrence < 0) {
hfinfo = hfinfo->same_name_next;
} else {
- hfinfo = hfinfo->same_name_prev;
+ hfinfo = hfinfo_same_name_get_prev(hfinfo);
}
continue;
}
if (occurrence < 0) {
hfinfo = hfinfo->same_name_next;
} else {
- hfinfo = hfinfo->same_name_prev;
+ hfinfo = hfinfo_same_name_get_prev(hfinfo);
}
prev_len += len;
continue;
if (occurrence == 0) {
/* Fetch next hfinfo with same name (abbrev) */
- hfinfo = hfinfo->same_name_prev;
+ hfinfo = hfinfo_same_name_get_prev(hfinfo);
} else {
hfinfo = NULL;
}
return fi ? fi->length : -1;
}
-
-/** clear flags according to the mask and set new flag values */
-#define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
- (fi->flags = (fi)->flags & ~(mask)); \
- (fi->flags = (fi)->flags | (flags_in)); \
-}
-
-gboolean
-proto_item_set_expert_flags(proto_item *pi, const int group, const guint severity)
-{
- if (pi == NULL || PITEM_FINFO(pi) == NULL)
- return FALSE;
-
- /* only change things if severity is worse or at least equal than before */
- if (severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK)) {
- FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_GROUP_MASK, group);
- FI_REPLACE_FLAGS(PITEM_FINFO(pi), PI_SEVERITY_MASK, severity);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
proto_tree *
proto_tree_create_root(packet_info *pinfo)
{
hfinfo->display = BASE_NONE;
hfinfo->strings = protocol;
hfinfo->bitmask = 0;
- hfinfo->bitshift = 0;
hfinfo->ref_type = HF_REF_TYPE_NONE;
hfinfo->blurb = NULL;
hfinfo->parent = -1; /* this field differentiates protos and fields */
proto_get_first_protocol_field(const int proto_id, void **cookie)
{
protocol_t *protocol = find_protocol_by_id(proto_id);
- hf_register_info *ptr;
if ((protocol == NULL) || (protocol->fields == NULL))
return NULL;
*cookie = protocol->fields;
- ptr = (hf_register_info *)protocol->fields->data;
- return &ptr->hfinfo;
+ return (header_field_info *)protocol->fields->data;
}
header_field_info *
proto_get_next_protocol_field(void **cookie)
{
- GList *list_item = (GList *)*cookie;
- hf_register_info *ptr;
+ GSList *list_item = (GSList *)*cookie;
- list_item = g_list_next(list_item);
+ list_item = g_slist_next(list_item);
if (list_item == NULL)
return NULL;
*cookie = list_item;
- ptr = (hf_register_info *)list_item->data;
- return &ptr->hfinfo;
+ return (header_field_info *)list_item->data;
}
protocol_t *
if (proto != NULL) {
if (proto->fields == NULL) {
- proto->fields = g_list_append(NULL, ptr);
+ proto->fields = g_slist_append(NULL, &ptr->hfinfo);
proto->last_field = proto->fields;
} else {
proto->last_field =
- g_list_append(proto->last_field, ptr)->next;
+ g_slist_append(proto->last_field, &ptr->hfinfo)->next;
}
}
field_id = proto_register_field_init(&ptr->hfinfo, parent);
}
}
+void
+proto_register_fields(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_field_array: %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);
+ }
+}
+
/* unregister already registered fields */
void
proto_unregister_field (const int parent, gint hf_id)
{
hf_register_info *hf;
protocol_t *proto;
- GList *field;
+ GSList *field;
if (hf_id == -1 || hf_id == 0)
return;
return;
}
- for (field = g_list_first (proto->fields); field; field = g_list_next (field)) {
+ for (field = proto->fields; field; field = field->next) {
hf = (hf_register_info *)field->data;
if (*hf->p_id == hf_id) {
/* Found the hf_id in this protocol */
g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
- proto->fields = g_list_remove_link (proto->fields, field);
- proto->last_field = g_list_last (proto->fields);
+ /* XXX, memleak? g_slist_delete_link() */
+ proto->fields = g_slist_remove_link (proto->fields, field);
+ proto->last_field = g_slist_last (proto->fields);
break;
}
}
tmp_fld_check_assert(hfinfo);
- /* if this is a bitfield, compute bitshift */
- if (hfinfo->bitmask) {
- hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
- }
-
hfinfo->parent = parent;
hfinfo->same_name_next = NULL;
- hfinfo->same_name_prev = NULL;
+ hfinfo->same_name_prev_id = -1;
/* if we always add and never delete, then id == len - 1 is correct */
if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
hfinfo->same_name_next = same_name_next_hfinfo;
if (same_name_next_hfinfo)
- same_name_next_hfinfo->same_name_prev = hfinfo;
+ same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
same_name_hfinfo->same_name_next = hfinfo;
- hfinfo->same_name_prev = same_name_hfinfo;
+ hfinfo->same_name_prev_id = same_name_hfinfo->id;
}
}
e_guid_t *guid;
guint32 n_addr; /* network-order IPv4 address */
const gchar *name;
+ address addr;
if (!fi) {
if (label_str)
case FT_UINT24:
case FT_UINT32:
if (hfinfo->bitmask) {
- fill_label_bitfield(fi, label_str);
+ fill_label_bitfield(fi, label_str, FALSE);
} else {
fill_label_number(fi, label_str, FALSE);
}
case FT_INT16:
case FT_INT24:
case FT_INT32:
- DISSECTOR_ASSERT(!hfinfo->bitmask);
- fill_label_number(fi, label_str, TRUE);
+ if (hfinfo->bitmask) {
+ fill_label_bitfield(fi, label_str, TRUE);
+ } else {
+ fill_label_number(fi, label_str, TRUE);
+ }
break;
case FT_INT64:
ax25_to_str(bytes));
break;
+ case FT_VINES:
+ addr.type = AT_VINES;
+ addr.len = VINES_ADDR_LEN;
+ addr.data = (guint8 *)fvalue_get(&fi->value);
+
+ g_snprintf(label_str, ITEM_LABEL_LENGTH,
+ "%s: %s", hfinfo->name,
+ address_to_str( &addr ));
+ break;
+
case FT_ETHER:
bytes = (guint8 *)fvalue_get(&fi->value);
label_fill_descr(label_str, 0, hfinfo,
/* Un-shift bits */
unshifted_value = value;
- if (hfinfo->bitshift > 0) {
- unshifted_value <<= hfinfo->bitshift;
- }
+ unshifted_value <<= hfinfo_bitshift(hfinfo);
/* Create the bitfield first */
p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
/* Fills data for bitfield ints with val_strings */
static void
-fill_label_bitfield(field_info *fi, gchar *label_str)
+fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
{
char *p;
int bitfield_byte_length, bitwidth;
bitwidth = hfinfo_bitwidth(hfinfo);
/* Un-shift bits */
- unshifted_value = fvalue_get_uinteger(&fi->value);
+ if (is_signed)
+ unshifted_value = fvalue_get_sinteger(&fi->value);
+ else
+ unshifted_value = fvalue_get_uinteger(&fi->value);
+
value = unshifted_value;
- if (hfinfo->bitshift > 0) {
- unshifted_value <<= hfinfo->bitshift;
+ if (hfinfo->bitmask) {
+ unshifted_value <<= hfinfo_bitshift(hfinfo);
}
/* Create the bitfield first */
const char *format = NULL;
header_field_info *hfinfo = fi->hfinfo;
guint64 value;
+ char tmp[ITEM_LABEL_LENGTH+1];
/* Pick the proper format string */
if (is_signed)
value = fvalue_get_integer64(&fi->value);
+ /* Format the temporary string */
+ if (IS_BASE_DUAL(hfinfo->display))
+ g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
+ else
+ g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
+
if (hfinfo->strings) {
const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
- char tmp[ITEM_LABEL_LENGTH+1];
-
- if (IS_BASE_DUAL(hfinfo->display)) {
- g_snprintf(tmp, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value, value);
- }
- else {
- g_snprintf(tmp, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value);
- }
-
if ((hfinfo->display & BASE_DISPLAY_E_MASK) == BASE_NONE) {
label_fill(label_str, 0, hfinfo, val_str);
label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
}
}
- else if (IS_BASE_DUAL(hfinfo->display)) {
- g_snprintf(label_str, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value, value);
- }
else {
- g_snprintf(label_str, ITEM_LABEL_LENGTH,
- format, hfinfo->name, value);
+ label_fill(label_str, 0, hfinfo, tmp);
}
}
+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
+}
+
int
hfinfo_bitwidth(const header_field_info *hfinfo)
{
/* Pick the proper format string */
switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
case BASE_DEC:
- format = "%s: %" G_GINT64_MODIFIER "u";
+ format = "%" G_GINT64_MODIFIER "u";
break;
case BASE_DEC_HEX:
- format = "%s: %" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
+ format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
break;
case BASE_OCT: /* I'm lazy */
- format = "%s: %#" G_GINT64_MODIFIER "o";
+ format = "%#" G_GINT64_MODIFIER "o";
break;
case BASE_HEX:
- format = "%s: 0x%016" G_GINT64_MODIFIER "x";
+ format = "0x%016" G_GINT64_MODIFIER "x";
break;
case BASE_HEX_DEC:
- format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
+ format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
break;
default:
DISSECTOR_ASSERT_NOT_REACHED();
/* Pick the proper format string */
switch (hfinfo->display & BASE_DISPLAY_E_MASK) {
case BASE_DEC:
- format = "%s: %" G_GINT64_MODIFIER "d";
+ format = "%" G_GINT64_MODIFIER "d";
break;
case BASE_DEC_HEX:
- format = "%s: %" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
+ format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
break;
case BASE_OCT: /* I'm lazy */
- format = "%s: %#" G_GINT64_MODIFIER "o";
+ format = "%#" G_GINT64_MODIFIER "o";
break;
case BASE_HEX:
- format = "%s: 0x%016" G_GINT64_MODIFIER "x";
+ format = "0x%016" G_GINT64_MODIFIER "x";
break;
case BASE_HEX_DEC:
- format = "%s: 0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
+ format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
break;
default:
DISSECTOR_ASSERT_NOT_REACHED();
* *maximum* length is 2 bytes, and be used
* for all lengths.)
*/
- if (hfinfo->same_name_prev != NULL)
+ if (hfinfo->same_name_prev_id != -1)
continue;
vals = NULL;
* *maximum* length is 2 bytes, and be used
* for all lengths.)
*/
- if (hfinfo->same_name_prev != NULL)
+ if (hfinfo->same_name_prev_id != -1)
continue;
PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
fields++;
continue;
}
- tmpval = (value & hf->bitmask) >> hf->bitshift;
+ tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
switch (hf->type) {
case FT_INT8: