2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
33 #include <wsutil/bits_ctz.h>
34 #include <wsutil/bits_count_ones.h>
36 #include <ftypes/ftypes-int.h>
39 #include "exceptions.h"
40 #include "ptvcursor.h"
42 #include "addr_resolv.h"
46 #include "epan_dissect.h"
49 #include "wmem/wmem.h"
51 #include "asm_utils.h"
52 #include "column-utils.h"
53 #include "to_str-int.h"
56 #include "show_exception.h"
58 #include "wspython/wspy_register.h"
60 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
61 #define SUBTREE_MAX_LEVELS 256
62 /* Throw an exception if we exceed this many tree items. */
63 /* XXX - This should probably be a preference */
64 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
67 typedef struct __subtree_lvl
{
74 subtree_lvl
*pushed_tree
;
75 guint8 pushed_tree_index
;
76 guint8 pushed_tree_max
;
82 #define cVALS(x) (const value_string*)(x)
84 /** See inlined comments.
85 @param tree the tree to append this item to
86 @param hfindex field index
87 @param hfinfo header_field
88 @return the header field matching 'hfinfo' */
89 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
90 /* If this item is not referenced we dont have to do much work \
91 at all but we should still return a node so that field items \
92 below this node (think proto_item_add_subtree()) will still \
93 have somewhere to attach to or else filtering will not work \
94 (they would be ignored since tree would be NULL). \
95 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
96 since dissectors that want to do proto_item_set_len() or \
97 other operations that dereference this would crash. \
98 We fake FT_PROTOCOL unless some clients have requested us \
103 PTREE_DATA(tree)->count++; \
104 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
105 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
106 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
107 /* Let the exception handler add items to the tree */ \
108 PTREE_DATA(tree)->count = 0; \
109 THROW_MESSAGE(DissectorError, \
110 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
112 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
113 if (!(PTREE_DATA(tree)->visible)) { \
114 if (PTREE_FINFO(tree)) { \
115 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
116 && (hfinfo->type != FT_PROTOCOL || \
117 PTREE_DATA(tree)->fake_protocols)) { \
118 /* just return tree back to the caller */\
124 /** See inlined comments.
125 @param pi the created protocol item we're about to return */
126 #define TRY_TO_FAKE_THIS_REPR(pi) \
128 if (!(PTREE_DATA(pi)->visible)) { \
129 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
130 * items string representation */ \
134 static const char *hf_try_val_to_str(guint32 value
, const header_field_info
*hfinfo
);
136 static void fill_label_boolean(field_info
*fi
, gchar
*label_str
);
137 static void fill_label_bitfield(field_info
*fi
, gchar
*label_str
, gboolean is_signed
);
138 static void fill_label_number(field_info
*fi
, gchar
*label_str
, gboolean is_signed
);
139 static void fill_label_number64(field_info
*fi
, gchar
*label_str
, gboolean is_signed
);
141 static const char *hfinfo_number_value_format_display(const header_field_info
*hfinfo
, int display
, char buf
[32], guint32 value
);
142 static const char *hfinfo_number_vals_format(const header_field_info
*hfinfo
, char buf
[32], guint32 value
);
143 static const char *hfinfo_number_value_format(const header_field_info
*hfinfo
, char buf
[32], guint32 value
);
144 static const char *hfinfo_numeric_value_format(const header_field_info
*hfinfo
, char buf
[32], guint32 value
);
146 static const char* hfinfo_uint64_format(const header_field_info
*hfinfo
);
147 static const char* hfinfo_int64_format(const header_field_info
*hfinfo
);
150 proto_tree_add_node(proto_tree
*tree
, field_info
*fi
);
153 get_hfi_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const gint start
, gint
*length
,
157 new_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
158 const gint start
, const gint item_length
);
161 alloc_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
162 const gint start
, gint
*length
);
165 proto_tree_add_pi(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
166 gint start
, gint
*length
);
169 proto_tree_set_representation_value(proto_item
*pi
, const char *format
, va_list ap
);
171 proto_tree_set_representation(proto_item
*pi
, const char *format
, va_list ap
);
174 proto_tree_set_protocol_tvb(field_info
*fi
, tvbuff_t
*tvb
);
176 proto_tree_set_bytes(field_info
*fi
, const guint8
* start_ptr
, gint length
);
178 proto_tree_set_bytes_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint offset
, gint length
);
180 proto_tree_set_time(field_info
*fi
, nstime_t
*value_ptr
);
182 proto_tree_set_string(field_info
*fi
, const char* value
);
184 proto_tree_set_string_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, gint length
, gint encoding
);
186 proto_tree_set_ax25(field_info
*fi
, const guint8
* value
);
188 proto_tree_set_ax25_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
);
190 proto_tree_set_vines(field_info
*fi
, const guint8
* value
);
192 proto_tree_set_vines_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
);
194 proto_tree_set_ether(field_info
*fi
, const guint8
* value
);
196 proto_tree_set_ether_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
);
198 proto_tree_set_ipxnet(field_info
*fi
, guint32 value
);
200 proto_tree_set_ipv4(field_info
*fi
, guint32 value
);
202 proto_tree_set_ipv6(field_info
*fi
, const guint8
* value_ptr
);
204 proto_tree_set_ipv6_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, gint length
);
206 proto_tree_set_guid(field_info
*fi
, const e_guid_t
*value_ptr
);
208 proto_tree_set_guid_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, const guint encoding
);
210 proto_tree_set_oid(field_info
*fi
, const guint8
* value_ptr
, gint length
);
212 proto_tree_set_oid_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, gint length
);
214 proto_tree_set_boolean(field_info
*fi
, guint32 value
);
216 proto_tree_set_float(field_info
*fi
, float value
);
218 proto_tree_set_double(field_info
*fi
, double value
);
220 proto_tree_set_uint(field_info
*fi
, guint32 value
);
222 proto_tree_set_int(field_info
*fi
, gint32 value
);
224 proto_tree_set_uint64(field_info
*fi
, guint64 value
);
226 proto_tree_set_uint64_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, guint length
, const guint encoding
);
228 proto_tree_set_eui64(field_info
*fi
, const guint64 value
);
230 proto_tree_set_eui64_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, const guint encoding
);
232 /* Handle type length mismatch (now filterable) expert info */
233 static int proto_type_length_mismatch
= -1;
234 static expert_field ei_type_length_mismatch_error
= EI_INIT
;
235 static expert_field ei_type_length_mismatch_warn
= EI_INIT
;
236 static void register_type_length_mismatch(void);
238 static int proto_register_field_init(header_field_info
*hfinfo
, const int parent
);
240 /* special-case header field used within proto.c */
241 static header_field_info hfi_text_only
=
242 { "Text item", "text", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
};
243 int hf_text_only
= -1;
245 /* Structure for information about a protocol */
247 const char *name
; /* long description */
248 const char *short_name
; /* short description */
249 const char *filter_name
; /* name of this protocol in filters */
250 int proto_id
; /* field ID for this protocol */
251 GSList
*fields
; /* fields for this protocol */
252 GSList
*last_field
; /* pointer to end of list of fields */
253 gboolean is_enabled
; /* TRUE if protocol is enabled */
254 gboolean can_toggle
; /* TRUE if is_enabled can be changed */
255 gboolean is_private
; /* TRUE is protocol is private */
258 /* List of all protocols */
259 static GList
*protocols
= NULL
;
261 /* Contains information about a field when a dissector calls
262 * proto_tree_add_item. */
263 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
264 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
266 /* Contains the space for proto_nodes. */
267 #define PROTO_NODE_INIT(node) \
268 node->first_child = NULL; \
269 node->last_child = NULL; \
272 #define PROTO_NODE_FREE(pool, node) \
273 wmem_free(pool, node)
275 /* String space for protocol and field items for the GUI */
276 #define ITEM_LABEL_NEW(pool, il) \
277 il = wmem_new(pool, item_label_t);
278 #define ITEM_LABEL_FREE(pool, il) \
281 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
282 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
283 g_error("Unregistered hf! index=%d", hfindex); \
284 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
285 hfinfo = gpa_hfinfo.hfi[hfindex];
287 /* List which stores protocols and fields that have been registered */
288 typedef struct _gpa_hfinfo_t
{
290 guint32 allocated_len
;
291 header_field_info
**hfi
;
294 static gpa_hfinfo_t gpa_hfinfo
;
296 /* Balanced tree of abbreviations and IDs */
297 static GTree
*gpa_name_tree
= NULL
;
298 static header_field_info
*same_name_hfinfo
;
300 static void save_same_name_hfinfo(gpointer data
)
302 same_name_hfinfo
= (header_field_info
*)data
;
305 /* Points to the first element of an array of bits, indexed by
306 a subtree item type; that array element is TRUE if subtrees of
307 an item of that type are to be expanded. */
308 static guint32
*tree_is_expanded
;
310 /* Number of elements in that array. */
313 /* Name hashtables for fast detection of duplicate names */
314 static GHashTable
* proto_names
= NULL
;
315 static GHashTable
* proto_short_names
= NULL
;
316 static GHashTable
* proto_filter_names
= NULL
;
319 proto_compare_name(gconstpointer p1_arg
, gconstpointer p2_arg
)
321 const protocol_t
*p1
= (const protocol_t
*)p1_arg
;
322 const protocol_t
*p2
= (const protocol_t
*)p2_arg
;
324 return g_ascii_strcasecmp(p1
->short_name
, p2
->short_name
);
328 /* initialize data structures and register protocols and fields */
330 proto_init(void (register_all_protocols_func
)(register_cb cb
, gpointer client_data
),
331 void (register_all_handoffs_func
)(register_cb cb
, gpointer client_data
),
333 gpointer client_data
)
337 proto_names
= g_hash_table_new_full(g_int_hash
, g_int_equal
, g_free
, NULL
);
338 proto_short_names
= g_hash_table_new(wrs_str_hash
, g_str_equal
);
339 proto_filter_names
= g_hash_table_new(wrs_str_hash
, g_str_equal
);
342 gpa_hfinfo
.allocated_len
= 0;
343 gpa_hfinfo
.hfi
= NULL
;
344 gpa_name_tree
= g_tree_new_full(wrs_strcmp_with_data
, NULL
, NULL
, save_same_name_hfinfo
);
346 /* Initialize the ftype subsystem */
349 /* Register one special-case FT_TEXT_ONLY field for use when
350 converting wireshark to new-style proto_tree. These fields
351 are merely strings on the GUI tree; they are not filterable */
352 hf_text_only
= proto_register_field_init(&hfi_text_only
, -1);
354 /* Register the pseudo-protocols used for exceptions. */
355 register_show_exception();
356 register_type_length_mismatch();
358 /* Have each built-in dissector register its protocols, fields,
359 dissector tables, and dissectors to be called through a
360 handle, and do whatever one-time initialization it needs to
362 register_all_protocols_func(cb
, client_data
);
364 /* Now scan for python protocols */
366 (*cb
)(RA_PYTHON_REGISTER
, NULL
, client_data
);
367 register_all_py_protocols_func();
371 /* Now scan for plugins and load all the ones we find, calling
372 their register routines to do the stuff described above. */
374 (*cb
)(RA_PLUGIN_REGISTER
, NULL
, client_data
);
376 register_all_plugin_registrations();
379 /* Now call the "handoff registration" routines of all built-in
380 dissectors; those routines register the dissector in other
381 dissectors' handoff tables, and fetch any dissector handles
383 register_all_handoffs_func(cb
, client_data
);
386 /* Now do the same with python dissectors */
388 (*cb
)(RA_PYTHON_HANDOFF
, NULL
, client_data
);
389 register_all_py_handoffs_func();
393 /* Now do the same with plugins. */
395 (*cb
)(RA_PLUGIN_HANDOFF
, NULL
, client_data
);
396 register_all_plugin_handoffs();
399 /* sort the protocols by protocol name */
400 protocols
= g_list_sort(protocols
, proto_compare_name
);
402 /* We've assigned all the subtree type values; allocate the array
403 for them, and zero it out. */
404 tree_is_expanded
= g_new0(guint32
, (num_tree_types
/32)+1);
410 /* Free the abbrev/ID GTree */
412 g_tree_destroy(gpa_name_tree
);
413 gpa_name_tree
= NULL
;
417 protocol_t
*protocol
= (protocol_t
*)protocols
->data
;
418 header_field_info
*hfinfo
;
419 PROTO_REGISTRAR_GET_NTH(protocol
->proto_id
, hfinfo
);
420 DISSECTOR_ASSERT(protocol
->proto_id
== hfinfo
->id
);
422 g_slice_free(header_field_info
, hfinfo
);
423 g_slist_free(protocol
->fields
);
424 protocols
= g_list_remove(protocols
, protocol
);
429 g_hash_table_destroy(proto_names
);
433 if (proto_short_names
) {
434 g_hash_table_destroy(proto_short_names
);
435 proto_short_names
= NULL
;
438 if (proto_filter_names
) {
439 g_hash_table_destroy(proto_filter_names
);
440 proto_filter_names
= NULL
;
443 if (gpa_hfinfo
.allocated_len
) {
445 gpa_hfinfo
.allocated_len
= 0;
446 g_free(gpa_hfinfo
.hfi
);
447 gpa_hfinfo
.hfi
= NULL
;
449 g_free(tree_is_expanded
);
450 tree_is_expanded
= NULL
;
454 proto_tree_traverse_pre_order(proto_tree
*tree
, proto_tree_traverse_func func
,
457 proto_node
*pnode
= tree
;
461 if (func(pnode
, data
))
464 child
= pnode
->first_child
;
465 while (child
!= NULL
) {
467 * The routine we call might modify the child, e.g. by
468 * freeing it, so we get the child's successor before
469 * calling that routine.
472 child
= current
->next
;
473 if (proto_tree_traverse_pre_order((proto_tree
*)current
, func
, data
))
481 proto_tree_traverse_post_order(proto_tree
*tree
, proto_tree_traverse_func func
,
484 proto_node
*pnode
= tree
;
488 child
= pnode
->first_child
;
489 while (child
!= NULL
) {
491 * The routine we call might modify the child, e.g. by
492 * freeing it, so we get the child's successor before
493 * calling that routine.
496 child
= current
->next
;
497 if (proto_tree_traverse_post_order((proto_tree
*)current
, func
, data
))
500 if (func(pnode
, data
))
507 proto_tree_children_foreach(proto_tree
*tree
, proto_tree_foreach_func func
,
510 proto_node
*node
= tree
;
516 node
= node
->first_child
;
517 while (node
!= NULL
) {
519 node
= current
->next
;
520 func((proto_tree
*)current
, data
);
525 free_GPtrArray_value(gpointer key
, gpointer value
, gpointer user_data _U_
)
527 GPtrArray
*ptrs
= (GPtrArray
*)value
;
528 gint hfid
= (gint
)(long)key
;
529 header_field_info
*hfinfo
;
531 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
532 if (hfinfo
->ref_type
!= HF_REF_TYPE_NONE
) {
533 /* when a field is referenced by a filter this also
534 affects the refcount for the parent protocol so we need
535 to adjust the refcount for the parent as well
537 if (hfinfo
->parent
!= -1) {
538 header_field_info
*parent_hfinfo
;
539 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
540 parent_hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
542 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
545 g_ptr_array_free(ptrs
, TRUE
);
549 proto_tree_free_node(proto_node
*node
, gpointer data _U_
)
551 field_info
*finfo
= PNODE_FINFO(node
);
553 proto_tree_children_foreach(node
, proto_tree_free_node
, NULL
);
555 FVALUE_CLEANUP(&finfo
->value
);
559 proto_tree_reset(proto_tree
*tree
)
561 tree_data_t
*tree_data
= PTREE_DATA(tree
);
563 proto_tree_children_foreach(tree
, proto_tree_free_node
, NULL
);
566 if (tree_data
->interesting_hfids
) {
567 /* Free all the GPtrArray's in the interesting_hfids hash. */
568 g_hash_table_foreach(tree_data
->interesting_hfids
,
569 free_GPtrArray_value
, NULL
);
571 /* And then destroy the hash. */
572 g_hash_table_destroy(tree_data
->interesting_hfids
);
574 tree_data
->interesting_hfids
= NULL
;
577 /* Reset track of the number of children */
578 tree_data
->count
= 0;
580 PROTO_NODE_INIT(tree
);
583 /* frees the resources that the dissection a proto_tree uses */
585 proto_tree_free(proto_tree
*tree
)
587 tree_data_t
*tree_data
= PTREE_DATA(tree
);
589 proto_tree_children_foreach(tree
, proto_tree_free_node
, NULL
);
592 if (tree_data
->interesting_hfids
) {
593 /* Free all the GPtrArray's in the interesting_hfids hash. */
594 g_hash_table_foreach(tree_data
->interesting_hfids
,
595 free_GPtrArray_value
, NULL
);
597 /* And then destroy the hash. */
598 g_hash_table_destroy(tree_data
->interesting_hfids
);
601 g_slice_free(tree_data_t
, tree_data
);
603 g_slice_free(proto_tree
, tree
);
606 /* Is the parsing being done for a visible proto_tree or an invisible one?
607 * By setting this correctly, the proto_tree creation is sped up by not
608 * having to call g_vsnprintf and copy strings around.
611 proto_tree_set_visible(proto_tree
*tree
, gboolean visible
)
613 gboolean old_visible
= PTREE_DATA(tree
)->visible
;
615 PTREE_DATA(tree
)->visible
= visible
;
621 proto_tree_set_fake_protocols(proto_tree
*tree
, gboolean fake_protocols
)
623 PTREE_DATA(tree
)->fake_protocols
= fake_protocols
;
626 /* Assume dissector set only its protocol fields.
627 This function is called by dissectors and allows the speeding up of filtering
628 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
629 and thus skip calling most of the expensive proto_tree_add_...()
631 If the tree is visible we implicitly assume the field is referenced.
634 proto_field_is_referenced(proto_tree
*tree
, int proto_id
)
636 register header_field_info
*hfinfo
;
642 if (PTREE_DATA(tree
)->visible
)
645 PROTO_REGISTRAR_GET_NTH(proto_id
, hfinfo
);
646 if (hfinfo
->ref_type
!= HF_REF_TYPE_NONE
)
649 if (hfinfo
->type
== FT_PROTOCOL
&& !PTREE_DATA(tree
)->fake_protocols
)
656 /* Finds a record in the hfinfo array by id. */
658 proto_registrar_get_nth(guint hfindex
)
660 register header_field_info
*hfinfo
;
662 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
667 /* Prefix initialization
668 * this allows for a dissector to register a display filter name prefix
669 * so that it can delay the initialization of the hf array as long as
673 /* compute a hash for the part before the dot of a display filter */
675 prefix_hash (gconstpointer key
) {
676 /* end the string at the dot and compute its hash */
677 gchar
* copy
= ep_strdup((const gchar
*)key
);
687 return g_str_hash(copy
);
690 /* are both strings equal up to the end or the dot? */
692 prefix_equal (gconstpointer ap
, gconstpointer bp
) {
693 const gchar
* a
= (const gchar
*)ap
;
694 const gchar
* b
= (const gchar
*)bp
;
700 if ( (ac
== '.' || ac
== '\0') && (bc
== '.' || bc
== '\0') ) return TRUE
;
702 if ( (ac
== '.' || ac
== '\0') && ! (bc
== '.' || bc
== '\0') ) return FALSE
;
703 if ( (bc
== '.' || bc
== '\0') && ! (ac
== '.' || ac
== '\0') ) return FALSE
;
705 if (ac
!= bc
) return FALSE
;
712 /* indexed by prefix, contains initializers */
713 static GHashTable
* prefixes
= NULL
;
716 /* Register a new prefix for "delayed" initialization of field arrays */
718 proto_register_prefix(const char *prefix
, prefix_initializer_t pi
) {
720 prefixes
= g_hash_table_new(prefix_hash
, prefix_equal
);
723 g_hash_table_insert(prefixes
, (gpointer
)prefix
, pi
);
726 /* helper to call all prefix initializers */
728 initialize_prefix(gpointer k
, gpointer v
, gpointer u _U_
) {
729 ((prefix_initializer_t
)v
)((const char *)k
);
733 /** Initialize every remaining uninitialized prefix. */
735 proto_initialize_all_prefixes(void) {
736 g_hash_table_foreach_remove(prefixes
, initialize_prefix
, NULL
);
739 /* Finds a record in the hfinfo array by name.
740 * If it fails to find it in the already registered fields,
741 * it tries to find and call an initializer in the prefixes
742 * table and if so it looks again.
745 proto_registrar_get_byname(const char *field_name
)
747 header_field_info
*hfinfo
;
748 prefix_initializer_t pi
;
753 hfinfo
= (header_field_info
*)g_tree_lookup(gpa_name_tree
, field_name
);
761 if ((pi
= (prefix_initializer_t
)g_hash_table_lookup(prefixes
, field_name
) ) != NULL
) {
763 g_hash_table_remove(prefixes
, field_name
);
768 return (header_field_info
*)g_tree_lookup(gpa_name_tree
, field_name
);
772 proto_registrar_get_id_byname(const char *field_name
)
774 header_field_info
*hfinfo
;
776 hfinfo
= proto_registrar_get_byname(field_name
);
786 ptvcursor_new_subtree_levels(ptvcursor_t
*ptvc
)
788 subtree_lvl
*pushed_tree
;
790 DISSECTOR_ASSERT(ptvc
->pushed_tree_max
<= SUBTREE_MAX_LEVELS
-SUBTREE_ONCE_ALLOCATION_NUMBER
);
791 ptvc
->pushed_tree_max
+= SUBTREE_ONCE_ALLOCATION_NUMBER
;
793 pushed_tree
= (subtree_lvl
*)ep_alloc(sizeof(subtree_lvl
) * ptvc
->pushed_tree_max
);
794 DISSECTOR_ASSERT(pushed_tree
!= NULL
);
795 if (ptvc
->pushed_tree
)
796 memcpy(pushed_tree
, ptvc
->pushed_tree
, ptvc
->pushed_tree_max
- SUBTREE_ONCE_ALLOCATION_NUMBER
);
797 ptvc
->pushed_tree
= pushed_tree
;
801 ptvcursor_free_subtree_levels(ptvcursor_t
*ptvc
)
803 ptvc
->pushed_tree
= NULL
;
804 ptvc
->pushed_tree_max
= 0;
805 DISSECTOR_ASSERT(ptvc
->pushed_tree_index
== 0);
806 ptvc
->pushed_tree_index
= 0;
809 /* Allocates an initializes a ptvcursor_t with 3 variables:
810 * proto_tree, tvbuff, and offset. */
812 ptvcursor_new(proto_tree
*tree
, tvbuff_t
*tvb
, gint offset
)
816 ptvc
= (ptvcursor_t
*)ep_alloc(sizeof(ptvcursor_t
));
819 ptvc
->offset
= offset
;
820 ptvc
->pushed_tree
= NULL
;
821 ptvc
->pushed_tree_max
= 0;
822 ptvc
->pushed_tree_index
= 0;
827 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
829 ptvcursor_free(ptvcursor_t
*ptvc
)
831 ptvcursor_free_subtree_levels(ptvc
);
835 /* Returns tvbuff. */
837 ptvcursor_tvbuff(ptvcursor_t
*ptvc
)
842 /* Returns current offset. */
844 ptvcursor_current_offset(ptvcursor_t
*ptvc
)
850 ptvcursor_tree(ptvcursor_t
*ptvc
)
859 ptvcursor_set_tree(ptvcursor_t
*ptvc
, proto_tree
*tree
)
864 /* creates a subtree, sets it as the working tree and pushes the old working tree */
866 ptvcursor_push_subtree(ptvcursor_t
*ptvc
, proto_item
*it
, gint ett_subtree
)
868 subtree_lvl
*subtree
;
869 if (ptvc
->pushed_tree_index
>= ptvc
->pushed_tree_max
)
870 ptvcursor_new_subtree_levels(ptvc
);
872 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
;
873 subtree
->tree
= ptvc
->tree
;
875 ptvc
->pushed_tree_index
++;
876 return ptvcursor_set_subtree(ptvc
, it
, ett_subtree
);
881 ptvcursor_pop_subtree(ptvcursor_t
*ptvc
)
883 subtree_lvl
*subtree
;
885 if (ptvc
->pushed_tree_index
<= 0)
888 ptvc
->pushed_tree_index
--;
889 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
;
890 if (subtree
->it
!= NULL
)
891 proto_item_set_len(subtree
->it
, ptvcursor_current_offset(ptvc
) - subtree
->cursor_offset
);
893 ptvc
->tree
= subtree
->tree
;
896 /* saves the current tvb offset and the item in the current subtree level */
898 ptvcursor_subtree_set_item(ptvcursor_t
*ptvc
, proto_item
*it
)
900 subtree_lvl
*subtree
;
902 DISSECTOR_ASSERT(ptvc
->pushed_tree_index
> 0);
904 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
- 1;
906 subtree
->cursor_offset
= ptvcursor_current_offset(ptvc
);
909 /* Creates a subtree and adds it to the cursor as the working tree but does not
910 * save the old working tree */
912 ptvcursor_set_subtree(ptvcursor_t
*ptvc
, proto_item
*it
, gint ett_subtree
)
914 ptvc
->tree
= proto_item_add_subtree(it
, ett_subtree
);
919 ptvcursor_add_subtree_item(ptvcursor_t
*ptvc
, proto_item
*it
, gint ett_subtree
, gint length
)
921 ptvcursor_push_subtree(ptvc
, it
, ett_subtree
);
922 if (length
== SUBTREE_UNDEFINED_LENGTH
)
923 ptvcursor_subtree_set_item(ptvc
, it
);
924 return ptvcursor_tree(ptvc
);
927 /* Add an item to the tree and create a subtree
928 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
929 * In this case, when the subtree will be closed, the parent item length will
930 * be equal to the advancement of the cursor since the creation of the subtree.
933 ptvcursor_add_with_subtree(ptvcursor_t
*ptvc
, int hfindex
, gint length
,
934 const guint encoding
, gint ett_subtree
)
938 it
= ptvcursor_add_no_advance(ptvc
, hfindex
, length
, encoding
);
939 return ptvcursor_add_subtree_item(ptvc
, it
, ett_subtree
, length
);
943 proto_tree_add_text_node(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
, gint length
);
945 /* Add a text node to the tree and create a subtree
946 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
947 * In this case, when the subtree will be closed, the item length will be equal
948 * to the advancement of the cursor since the creation of the subtree.
951 ptvcursor_add_text_with_subtree(ptvcursor_t
*ptvc
, gint length
,
952 gint ett_subtree
, const char *format
, ...)
956 header_field_info
*hfinfo
;
959 tree
= ptvcursor_tree(ptvc
);
961 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
963 pi
= proto_tree_add_text_node(tree
, ptvcursor_tvbuff(ptvc
),
964 ptvcursor_current_offset(ptvc
), length
);
966 TRY_TO_FAKE_THIS_REPR(pi
);
968 va_start(ap
, format
);
969 proto_tree_set_representation(pi
, format
, ap
);
972 return ptvcursor_add_subtree_item(ptvc
, pi
, ett_subtree
, length
);
975 /* Add a text-only node, leaving it to our caller to fill the text in */
977 proto_tree_add_text_node(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
, gint length
)
984 pi
= proto_tree_add_pi(tree
, &hfi_text_only
, tvb
, start
, &length
);
989 /* Add a text-only node to the proto_tree */
991 proto_tree_add_text(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
, gint length
,
992 const char *format
, ...)
996 header_field_info
*hfinfo
;
998 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1000 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1002 TRY_TO_FAKE_THIS_REPR(pi
);
1004 va_start(ap
, format
);
1005 proto_tree_set_representation(pi
, format
, ap
);
1011 /* Add a text-only node to the proto_tree (va_list version) */
1013 proto_tree_add_text_valist(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
,
1014 gint length
, const char *format
, va_list ap
)
1017 header_field_info
*hfinfo
;
1019 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1021 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1023 TRY_TO_FAKE_THIS_REPR(pi
);
1025 proto_tree_set_representation(pi
, format
, ap
);
1030 /* Add a text-only node for debugging purposes. The caller doesn't need
1031 * to worry about tvbuff, start, or length. Debug message gets sent to
1034 proto_tree_add_debug_text(proto_tree
*tree
, const char *format
, ...)
1039 pi
= proto_tree_add_text_node(tree
, NULL
, 0, 0);
1042 va_start(ap
, format
);
1043 proto_tree_set_representation(pi
, format
, ap
);
1046 va_start(ap
, format
);
1047 vprintf(format
, ap
);
1054 void proto_report_dissector_bug(const char *message
)
1056 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL
)
1059 THROW_MESSAGE(DissectorError
, message
);
1062 /* We could probably get away with changing is_error to a minimum length value. */
1064 report_type_length_mismatch(proto_tree
*tree
, const gchar
*descr
, int length
, gboolean is_error
) {
1067 expert_add_info_format(NULL
, tree
, &ei_type_length_mismatch_error
, "Trying to fetch %s with length %d", descr
, length
);
1069 expert_add_info_format(NULL
, tree
, &ei_type_length_mismatch_warn
, "Trying to fetch %s with length %d", descr
, length
);
1073 THROW(ReportedBoundsError
);
1078 get_uint_value(proto_tree
*tree
, tvbuff_t
*tvb
, gint offset
, gint length
, const guint encoding
)
1081 gboolean length_error
;
1086 value
= tvb_get_guint8(tvb
, offset
);
1090 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohs(tvb
, offset
)
1091 : tvb_get_ntohs(tvb
, offset
);
1095 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh24(tvb
, offset
)
1096 : tvb_get_ntoh24(tvb
, offset
);
1100 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1101 : tvb_get_ntohl(tvb
, offset
);
1106 length_error
= TRUE
;
1109 length_error
= FALSE
;
1110 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1111 : tvb_get_ntohl(tvb
, offset
);
1113 report_type_length_mismatch(tree
, "an unsigned integer", length
, length_error
);
1120 * NOTE: to support code written when proto_tree_add_item() took a
1121 * gboolean as its last argument, with FALSE meaning "big-endian"
1122 * and TRUE meaning "little-endian", we treat any non-zero value of
1123 * "encoding" as meaning "little-endian".
1126 get_int_value(proto_tree
*tree
, tvbuff_t
*tvb
, gint offset
, gint length
, const guint encoding
)
1129 gboolean length_error
;
1134 value
= (gint8
)tvb_get_guint8(tvb
, offset
);
1138 value
= (gint16
) (encoding
? tvb_get_letohs(tvb
, offset
)
1139 : tvb_get_ntohs(tvb
, offset
));
1143 value
= encoding
? tvb_get_letoh24(tvb
, offset
)
1144 : tvb_get_ntoh24(tvb
, offset
);
1145 if (value
& 0x00800000) {
1146 /* Sign bit is set; sign-extend it. */
1147 value
|= 0xFF000000;
1152 value
= encoding
? tvb_get_letohl(tvb
, offset
)
1153 : tvb_get_ntohl(tvb
, offset
);
1158 length_error
= TRUE
;
1161 length_error
= FALSE
;
1162 value
= encoding
? tvb_get_letohl(tvb
, offset
)
1163 : tvb_get_ntohl(tvb
, offset
);
1165 report_type_length_mismatch(tree
, "a signed integer", length
, length_error
);
1172 tree_data_add_maybe_interesting_field(tree_data_t
*tree_data
, field_info
*fi
)
1174 const header_field_info
*hfinfo
= fi
->hfinfo
;
1176 if (hfinfo
->ref_type
== HF_REF_TYPE_DIRECT
) {
1177 GPtrArray
*ptrs
= NULL
;
1179 if (tree_data
->interesting_hfids
== NULL
) {
1180 /* Initialize the hash because we now know that it is needed */
1181 tree_data
->interesting_hfids
=
1182 g_hash_table_new(g_direct_hash
, NULL
/* g_direct_equal */);
1184 ptrs
= (GPtrArray
*)g_hash_table_lookup(tree_data
->interesting_hfids
,
1185 GINT_TO_POINTER(hfinfo
->id
));
1187 /* First element triggers the creation of pointer array */
1188 ptrs
= g_ptr_array_new();
1189 g_hash_table_insert(tree_data
->interesting_hfids
,
1190 GINT_TO_POINTER(hfinfo
->id
), ptrs
);
1193 g_ptr_array_add(ptrs
, fi
);
1197 /* Add an item to a proto_tree, using the text label registered to that item;
1198 the item is extracted from the tvbuff handed to it. */
1200 proto_tree_new_item(field_info
*new_fi
, proto_tree
*tree
,
1201 tvbuff_t
*tvb
, gint start
, gint length
,
1209 nstime_t time_stamp
;
1212 gboolean length_error
;
1214 switch (new_fi
->hfinfo
->type
) {
1216 /* no value to set for FT_NONE */
1220 proto_tree_set_protocol_tvb(new_fi
, tvb
);
1224 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
, length
);
1229 * Map all non-zero values to little-endian for
1230 * backwards compatibility.
1233 encoding
= ENC_LITTLE_ENDIAN
;
1234 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
1235 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
+ length
, n
);
1237 /* Instead of calling proto_item_set_len(), since we don't yet
1238 * have a proto_item, we set the field_info's length ourselves. */
1239 new_fi
->length
= n
+ length
;
1244 * Map all non-zero values to little-endian for
1245 * backwards compatibility.
1248 encoding
= ENC_LITTLE_ENDIAN
;
1249 proto_tree_set_boolean(new_fi
,
1250 get_uint_value(tree
, tvb
, start
, length
, encoding
));
1253 /* XXX - make these just FT_UINT? */
1259 * Map all non-zero values to little-endian for
1260 * backwards compatibility.
1263 encoding
= ENC_LITTLE_ENDIAN
;
1264 proto_tree_set_uint(new_fi
,
1265 get_uint_value(tree
, tvb
, start
, length
, encoding
));
1271 * Map all non-zero values to little-endian for
1272 * backwards compatibility.
1275 encoding
= ENC_LITTLE_ENDIAN
;
1276 if (length
< 1 || length
> 8) {
1277 length_error
= length
< 1 ? TRUE
: FALSE
;
1278 report_type_length_mismatch(tree
, "a 64-bit integer", length
, length_error
);
1280 proto_tree_set_uint64_tvb(new_fi
, tvb
, start
, length
, encoding
);
1283 /* XXX - make these just FT_INT? */
1289 * Map all non-zero values to little-endian for
1290 * backwards compatibility.
1293 encoding
= ENC_LITTLE_ENDIAN
;
1294 proto_tree_set_int(new_fi
,
1295 get_int_value(tree
, tvb
, start
, length
, encoding
));
1300 * Map all non-zero values to little-endian for
1301 * backwards compatibility.
1304 encoding
= ENC_LITTLE_ENDIAN
;
1305 if (length
!= FT_IPv4_LEN
) {
1306 length_error
= length
< FT_IPv4_LEN
? TRUE
: FALSE
;
1307 report_type_length_mismatch(tree
, "an IPv4 address", length
, length_error
);
1309 value
= tvb_get_ipv4(tvb
, start
);
1311 * NOTE: to support code written when
1312 * proto_tree_add_item() took a gboolean as its
1313 * last argument, with FALSE meaning "big-endian"
1314 * and TRUE meaning "little-endian", we treat any
1315 * non-zero value of "encoding" as meaning
1318 proto_tree_set_ipv4(new_fi
, encoding
? GUINT32_SWAP_LE_BE(value
) : value
);
1322 if (length
!= FT_IPXNET_LEN
) {
1323 length_error
= length
< FT_IPXNET_LEN
? TRUE
: FALSE
;
1324 report_type_length_mismatch(tree
, "an IPXNET address", length
, length_error
);
1326 proto_tree_set_ipxnet(new_fi
,
1327 get_uint_value(tree
, tvb
, start
, FT_IPXNET_LEN
, ENC_BIG_ENDIAN
));
1331 if (length
!= FT_IPv6_LEN
) {
1332 length_error
= length
< FT_IPv6_LEN
? TRUE
: FALSE
;
1333 report_type_length_mismatch(tree
, "an IPv6 address", length
, length_error
);
1335 proto_tree_set_ipv6_tvb(new_fi
, tvb
, start
, length
);
1340 length_error
= length
< 7 ? TRUE
: FALSE
;
1341 report_type_length_mismatch(tree
, "an AX.25 address", length
, length_error
);
1343 proto_tree_set_ax25_tvb(new_fi
, tvb
, start
);
1347 if (length
!= VINES_ADDR_LEN
) {
1348 length_error
= length
< VINES_ADDR_LEN
? TRUE
: FALSE
;
1349 report_type_length_mismatch(tree
, "a Vines address", length
, length_error
);
1351 proto_tree_set_vines_tvb(new_fi
, tvb
, start
);
1355 if (length
!= FT_ETHER_LEN
) {
1356 length_error
= length
< FT_ETHER_LEN
? TRUE
: FALSE
;
1357 report_type_length_mismatch(tree
, "an Ethernet", length
, length_error
);
1359 proto_tree_set_ether_tvb(new_fi
, tvb
, start
);
1364 * Map all non-zero values to little-endian for
1365 * backwards compatibility.
1368 encoding
= ENC_LITTLE_ENDIAN
;
1369 if (length
!= FT_EUI64_LEN
) {
1370 length_error
= length
< FT_EUI64_LEN
? TRUE
: FALSE
;
1371 report_type_length_mismatch(tree
, "an EUI-64 address", length
, length_error
);
1373 proto_tree_set_eui64_tvb(new_fi
, tvb
, start
, encoding
);
1377 * Map all non-zero values to little-endian for
1378 * backwards compatibility.
1381 encoding
= ENC_LITTLE_ENDIAN
;
1382 if (length
!= FT_GUID_LEN
) {
1383 length_error
= length
< FT_GUID_LEN
? TRUE
: FALSE
;
1384 report_type_length_mismatch(tree
, "a GUID", length
, length_error
);
1386 proto_tree_set_guid_tvb(new_fi
, tvb
, start
, encoding
);
1391 proto_tree_set_oid_tvb(new_fi
, tvb
, start
, length
);
1396 * NOTE: to support code written when
1397 * proto_tree_add_item() took a gboolean as its
1398 * last argument, with FALSE meaning "big-endian"
1399 * and TRUE meaning "little-endian", we treat any
1400 * non-zero value of "encoding" as meaning
1403 * At some point in the future, we might
1404 * support non-IEEE-binary floating-point
1405 * formats in the encoding as well
1406 * (IEEE decimal, System/3x0, VAX).
1409 encoding
= ENC_LITTLE_ENDIAN
;
1411 length_error
= length
< 4 ? TRUE
: FALSE
;
1412 report_type_length_mismatch(tree
, "a single-precision floating point number", length
, length_error
);
1415 floatval
= tvb_get_letohieee_float(tvb
, start
);
1417 floatval
= tvb_get_ntohieee_float(tvb
, start
);
1418 proto_tree_set_float(new_fi
, floatval
);
1423 * NOTE: to support code written when
1424 * proto_tree_add_item() took a gboolean as its
1425 * last argument, with FALSE meaning "big-endian"
1426 * and TRUE meaning "little-endian", we treat any
1427 * non-zero value of "encoding" as meaning
1430 * At some point in the future, we might
1431 * support non-IEEE-binary floating-point
1432 * formats in the encoding as well
1433 * (IEEE decimal, System/3x0, VAX).
1435 if (encoding
== TRUE
)
1436 encoding
= ENC_LITTLE_ENDIAN
;
1438 length_error
= length
< 8 ? TRUE
: FALSE
;
1439 report_type_length_mismatch(tree
, "a double-precision floating point number", length
, length_error
);
1442 doubleval
= tvb_get_letohieee_double(tvb
, start
);
1444 doubleval
= tvb_get_ntohieee_double(tvb
, start
);
1445 proto_tree_set_double(new_fi
, doubleval
);
1449 proto_tree_set_string_tvb(new_fi
, tvb
, start
, length
,
1455 report_type_length_mismatch(tree
, "a string", length
, TRUE
);
1457 /* Instead of calling proto_item_set_len(),
1458 * since we don't yet have a proto_item, we
1459 * set the field_info's length ourselves.
1461 * XXX - our caller can't use that length to
1462 * advance an offset unless they arrange that
1463 * there always be a protocol tree into which
1464 * we're putting this item.
1467 /* This can throw an exception */
1468 string
= tvb_get_stringz_enc(wmem_packet_scope(), tvb
, start
, &length
, encoding
);
1469 } else if (length
== 0) {
1472 /* In this case, length signifies
1473 * the length of the string.
1475 * This could either be a null-padded
1476 * string, which doesn't necessarily
1477 * have a '\0' at the end, or a
1478 * null-terminated string, with a
1479 * trailing '\0'. (Yes, there are
1480 * cases where you have a string
1481 * that's both counted and null-
1484 * In the first case, we must
1485 * allocate a buffer of length
1486 * "length+1", to make room for
1489 * In the second case, we don't
1490 * assume that there is a trailing
1491 * '\0' there, as the packet might
1492 * be malformed. (XXX - should we
1493 * throw an exception if there's no
1494 * trailing '\0'?) Therefore, we
1495 * allocate a buffer of length
1496 * "length+1", and put in a trailing
1497 * '\0', just to be safe.
1499 * (XXX - this would change if
1500 * we made string values counted
1501 * rather than null-terminated.)
1503 string
= tvb_get_string_enc(wmem_packet_scope(), tvb
, start
, length
, encoding
);
1505 new_fi
->length
= length
;
1506 proto_tree_set_string(new_fi
, string
);
1509 case FT_UINT_STRING
:
1511 * NOTE: to support code written when
1512 * proto_tree_add_item() took a gboolean as its
1513 * last argument, with FALSE meaning "big-endian"
1514 * and TRUE meaning "little-endian", if the
1515 * encoding value is TRUE, treat that as
1516 * ASCII with a little-endian length.
1518 * This won't work for code that passes
1519 * arbitrary non-zero values; that code
1520 * will need to be fixed.
1522 if (encoding
== TRUE
)
1523 encoding
= ENC_ASCII
|ENC_LITTLE_ENDIAN
;
1524 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
& ~ENC_CHARENCODING_MASK
);
1525 proto_tree_set_string_tvb(new_fi
, tvb
, start
+ length
, n
,
1528 /* Instead of calling proto_item_set_len(), since we
1529 * don't yet have a proto_item, we set the
1530 * field_info's length ourselves.
1532 * XXX - our caller can't use that length to
1533 * advance an offset unless they arrange that
1534 * there always be a protocol tree into which
1535 * we're putting this item.
1537 new_fi
->length
= n
+ length
;
1540 case FT_ABSOLUTE_TIME
:
1542 * Absolute times can be in any of a number of
1543 * formats, and they can be big-endian or
1546 * Historically FT_TIMEs were only timespecs;
1547 * the only question was whether they were stored
1548 * in big- or little-endian format.
1550 * For backwards compatibility, we interpret an
1551 * encoding of 1 as meaning "little-endian timespec",
1552 * so that passing TRUE is interpreted as that.
1554 if (encoding
== TRUE
)
1555 encoding
= ENC_TIME_TIMESPEC
|ENC_LITTLE_ENDIAN
;
1557 if (length
!= 8 && length
!= 4) {
1558 length_error
= length
< 4 ? TRUE
: FALSE
;
1559 report_type_length_mismatch(tree
, "an absolute time value", length
, length_error
);
1564 case ENC_TIME_TIMESPEC
|ENC_BIG_ENDIAN
:
1566 * 4-byte UNIX epoch, possibly followed by
1567 * 4-byte fractional time in nanoseconds,
1570 time_stamp
.secs
= tvb_get_ntohl(tvb
, start
);
1572 time_stamp
.nsecs
= tvb_get_ntohl(tvb
, start
+4);
1574 time_stamp
.nsecs
= 0;
1577 case ENC_TIME_TIMESPEC
|ENC_LITTLE_ENDIAN
:
1579 * 4-byte UNIX epoch, possibly followed by
1580 * 4-byte fractional time in nanoseconds,
1581 * both little-endian.
1583 time_stamp
.secs
= tvb_get_letohl(tvb
, start
);
1585 time_stamp
.nsecs
= tvb_get_letohl(tvb
, start
+4);
1587 time_stamp
.nsecs
= 0;
1590 case ENC_TIME_TOD
|ENC_BIG_ENDIAN
:
1592 * TOD time stamp, big-endian.
1594 /* XXX - where should this go? */
1595 #define TOD_BASETIME 2208988800ul
1597 todsecs
= tvb_get_ntoh64(tvb
, start
) >> 12;
1598 time_stamp
.secs
= (time_t)((todsecs
/ 1000000) - TOD_BASETIME
);
1599 time_stamp
.nsecs
= (int)((todsecs
% 1000000) * 1000);
1602 case ENC_TIME_TOD
|ENC_LITTLE_ENDIAN
:
1604 * TOD time stamp, big-endian.
1606 todsecs
= tvb_get_letoh64(tvb
, start
) >> 12 ;
1607 time_stamp
.secs
= (time_t)((todsecs
/ 1000000) - TOD_BASETIME
);
1608 time_stamp
.nsecs
= (int)((todsecs
% 1000000) * 1000);
1611 case ENC_TIME_NTP
|ENC_BIG_ENDIAN
:
1613 * NTP time stamp, big-endian.
1616 /* XXX - where should this go? */
1617 #define NTP_BASETIME 2208988800ul
1619 /* We need a temporary variable here so the unsigned math
1620 * works correctly (for years > 2036 according to RFC 2030
1623 tmpsecs
= tvb_get_ntohl(tvb
, start
);
1625 time_stamp
.secs
= tmpsecs
- (guint32
)NTP_BASETIME
;
1627 time_stamp
.secs
= tmpsecs
; /* 0 */
1631 * We're using nanoseconds here (and we will
1632 * display nanoseconds), but NTP's timestamps
1633 * have a precision in microseconds or greater.
1634 * Round to 1 microsecond.
1636 time_stamp
.nsecs
= (int)(1000000*(tvb_get_ntohl(tvb
, start
+4)/4294967296.0));
1637 time_stamp
.nsecs
*= 1000;
1639 time_stamp
.nsecs
= 0;
1643 case ENC_TIME_NTP
|ENC_LITTLE_ENDIAN
:
1645 * NTP time stamp, big-endian.
1647 tmpsecs
= tvb_get_letohl(tvb
, start
);
1649 time_stamp
.secs
= tmpsecs
- (guint32
)NTP_BASETIME
;
1651 time_stamp
.secs
= tmpsecs
; /* 0 */
1655 * We're using nanoseconds here (and we will
1656 * display nanoseconds), but NTP's timestamps
1657 * have a precision in microseconds or greater.
1658 * Round to 1 microsecond.
1660 time_stamp
.nsecs
= (int)(1000000*(tvb_get_letohl(tvb
, start
+4)/4294967296.0));
1661 time_stamp
.nsecs
*= 1000;
1663 time_stamp
.nsecs
= 0;
1668 DISSECTOR_ASSERT_NOT_REACHED();
1669 time_stamp
.secs
= 0;
1670 time_stamp
.nsecs
= 0;
1673 proto_tree_set_time(new_fi
, &time_stamp
);
1676 case FT_RELATIVE_TIME
:
1678 * Relative times can be in any of a number of
1679 * formats, and they can be big-endian or
1682 * Historically FT_TIMEs were only timespecs;
1683 * the only question was whether they were stored
1684 * in big- or little-endian format.
1686 * For backwards compatibility, we interpret an
1687 * encoding of 1 as meaning "little-endian timespec",
1688 * so that passing TRUE is interpreted as that.
1690 if (encoding
== TRUE
)
1691 encoding
= ENC_TIME_TIMESPEC
|ENC_LITTLE_ENDIAN
;
1694 if (length
!= 8 && length
!= 4) {
1695 length_error
= length
< 4 ? TRUE
: FALSE
;
1696 report_type_length_mismatch(tree
, "a relative time value", length
, length_error
);
1699 case ENC_TIME_TIMESPEC
|ENC_BIG_ENDIAN
:
1701 * 4-byte UNIX epoch, possibly followed by
1702 * 4-byte fractional time in nanoseconds,
1705 time_stamp
.secs
= tvb_get_ntohl(tvb
, start
);
1707 time_stamp
.nsecs
= tvb_get_ntohl(tvb
, start
+4);
1709 time_stamp
.nsecs
= 0;
1712 case ENC_TIME_TIMESPEC
|ENC_LITTLE_ENDIAN
:
1714 * 4-byte UNIX epoch, possibly followed by
1715 * 4-byte fractional time in nanoseconds,
1716 * both little-endian.
1718 time_stamp
.secs
= tvb_get_letohl(tvb
, start
);
1720 time_stamp
.nsecs
= tvb_get_letohl(tvb
, start
+4);
1722 time_stamp
.nsecs
= 0;
1725 proto_tree_set_time(new_fi
, &time_stamp
);
1729 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1730 new_fi
->hfinfo
->type
,
1731 ftype_name(new_fi
->hfinfo
->type
));
1732 DISSECTOR_ASSERT_NOT_REACHED();
1735 FI_SET_FLAG(new_fi
, (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
1737 /* Don't add new node to proto_tree until now so that any exceptions
1738 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1739 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1740 * to know which item caused exception? */
1741 pi
= proto_tree_add_node(tree
, new_fi
);
1746 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1747 and returns proto_item* */
1749 ptvcursor_add(ptvcursor_t
*ptvc
, int hfindex
, gint length
,
1750 const guint encoding
)
1753 header_field_info
*hfinfo
;
1758 /* We can't fake it just yet. We have to advance the cursor
1759 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1761 offset
= ptvc
->offset
;
1762 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
1763 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
);
1764 ptvc
->offset
+= length
;
1765 if (hfinfo
->type
== FT_UINT_BYTES
|| hfinfo
->type
== FT_UINT_STRING
) {
1767 * The length of the rest of the item is in the first N
1768 * bytes of the item.
1770 n
= get_uint_value(ptvc
->tree
, ptvc
->tvb
, offset
, length
, encoding
);
1774 /* Coast clear. Try and fake it */
1775 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
1777 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
1779 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
1780 offset
, length
, encoding
);
1784 * Validates that field length bytes are available starting from
1785 * start (pos/neg). Throws an exception if they aren't.
1788 test_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
,
1789 gint start
, gint length
)
1796 if (hfinfo
->type
== FT_STRINGZ
) {
1797 /* If we're fetching until the end of the TVB, only validate
1798 * that the offset is within range.
1804 tvb_ensure_bytes_exist(tvb
, start
, size
);
1807 /* Add an item to a proto_tree, using the text label registered to that item;
1808 the item is extracted from the tvbuff handed to it. */
1810 proto_tree_add_item_new(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
1811 const gint start
, gint length
, const guint encoding
)
1816 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
1818 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
);
1819 test_length(hfinfo
, tvb
, start
, item_length
);
1821 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
1823 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
1828 return proto_tree_new_item(new_fi
, tree
, tvb
, start
, length
, encoding
);
1832 proto_tree_add_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
1833 const gint start
, gint length
, const guint encoding
)
1835 return proto_tree_add_item_new(tree
, proto_registrar_get_nth(hfindex
), tvb
, start
, length
, encoding
);
1838 /* Add a FT_NONE to a proto_tree */
1840 proto_tree_add_none_format(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
1841 const gint start
, gint length
, const char *format
,
1846 header_field_info
*hfinfo
;
1848 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
1850 DISSECTOR_ASSERT(hfinfo
->type
== FT_NONE
);
1852 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
1854 TRY_TO_FAKE_THIS_REPR(pi
);
1856 va_start(ap
, format
);
1857 proto_tree_set_representation(pi
, format
, ap
);
1860 /* no value to set for FT_NONE */
1864 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1865 * offset, and returns proto_item* */
1867 ptvcursor_add_no_advance(ptvcursor_t
* ptvc
, int hf
, gint length
,
1868 const guint encoding
)
1872 item
= proto_tree_add_item(ptvc
->tree
, hf
, ptvc
->tvb
, ptvc
->offset
,
1878 /* Advance the ptvcursor's offset within its tvbuff without
1879 * adding anything to the proto_tree. */
1881 ptvcursor_advance(ptvcursor_t
* ptvc
, gint length
)
1883 ptvc
->offset
+= length
;
1888 proto_tree_set_protocol_tvb(field_info
*fi
, tvbuff_t
*tvb
)
1890 fvalue_set(&fi
->value
, tvb
, TRUE
);
1893 /* Add a FT_PROTOCOL to a proto_tree */
1895 proto_tree_add_protocol_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
1896 gint start
, gint length
, const char *format
, ...)
1900 header_field_info
*hfinfo
;
1902 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
1904 DISSECTOR_ASSERT(hfinfo
->type
== FT_PROTOCOL
);
1906 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
1908 proto_tree_set_protocol_tvb(PNODE_FINFO(pi
), (start
== 0 ? tvb
: tvb_new_subset(tvb
, start
, length
, length
)));
1910 TRY_TO_FAKE_THIS_REPR(pi
);
1912 va_start(ap
, format
);
1913 proto_tree_set_representation(pi
, format
, ap
);
1920 /* Add a FT_BYTES to a proto_tree */
1922 proto_tree_add_bytes(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
1923 gint length
, const guint8
*start_ptr
)
1926 header_field_info
*hfinfo
;
1928 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
1930 DISSECTOR_ASSERT(hfinfo
->type
== FT_BYTES
);
1932 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
1933 proto_tree_set_bytes(PNODE_FINFO(pi
), start_ptr
, length
);
1939 proto_tree_add_bytes_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
1940 gint start
, gint length
,
1941 const guint8
*start_ptr
,
1942 const char *format
, ...)
1946 header_field_info
*hfinfo
;
1948 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
1951 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
,
1954 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
,
1955 tvb_get_ptr(tvb
, start
, length
));
1957 va_start(ap
, format
);
1958 proto_tree_set_representation_value(pi
, format
, ap
);
1965 proto_tree_add_bytes_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
1966 gint start
, gint length
, const guint8
*start_ptr
,
1967 const char *format
, ...)
1971 header_field_info
*hfinfo
;
1973 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
1976 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
,
1979 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
,
1980 tvb_get_ptr(tvb
, start
, length
));
1982 TRY_TO_FAKE_THIS_REPR(pi
);
1984 va_start(ap
, format
);
1985 proto_tree_set_representation(pi
, format
, ap
);
1992 proto_tree_set_bytes(field_info
*fi
, const guint8
* start_ptr
, gint length
)
1996 DISSECTOR_ASSERT(start_ptr
!= NULL
|| length
== 0);
1998 bytes
= g_byte_array_new();
2000 g_byte_array_append(bytes
, start_ptr
, length
);
2002 fvalue_set(&fi
->value
, bytes
, TRUE
);
2007 proto_tree_set_bytes_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint offset
, gint length
)
2009 proto_tree_set_bytes(fi
, tvb_get_ptr(tvb
, offset
, length
), length
);
2012 /* Add a FT_*TIME to a proto_tree */
2014 proto_tree_add_time(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2015 gint length
, nstime_t
*value_ptr
)
2018 header_field_info
*hfinfo
;
2020 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2022 DISSECTOR_ASSERT(hfinfo
->type
== FT_ABSOLUTE_TIME
||
2023 hfinfo
->type
== FT_RELATIVE_TIME
);
2025 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2026 proto_tree_set_time(PNODE_FINFO(pi
), value_ptr
);
2032 proto_tree_add_time_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2033 gint start
, gint length
, nstime_t
*value_ptr
,
2034 const char *format
, ...)
2039 pi
= proto_tree_add_time(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2041 va_start(ap
, format
);
2042 proto_tree_set_representation_value(pi
, format
, ap
);
2050 proto_tree_add_time_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2051 gint start
, gint length
, nstime_t
*value_ptr
,
2052 const char *format
, ...)
2057 pi
= proto_tree_add_time(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2059 TRY_TO_FAKE_THIS_REPR(pi
);
2061 va_start(ap
, format
);
2062 proto_tree_set_representation(pi
, format
, ap
);
2069 /* Set the FT_*TIME value */
2071 proto_tree_set_time(field_info
*fi
, nstime_t
*value_ptr
)
2073 DISSECTOR_ASSERT(value_ptr
!= NULL
);
2075 fvalue_set(&fi
->value
, value_ptr
, FALSE
);
2078 /* Add a FT_IPXNET to a proto_tree */
2080 proto_tree_add_ipxnet(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2081 gint length
, guint32 value
)
2084 header_field_info
*hfinfo
;
2086 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2088 DISSECTOR_ASSERT(hfinfo
->type
== FT_IPXNET
);
2090 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2091 proto_tree_set_ipxnet(PNODE_FINFO(pi
), value
);
2097 proto_tree_add_ipxnet_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2098 gint start
, gint length
, guint32 value
,
2099 const char *format
, ...)
2104 pi
= proto_tree_add_ipxnet(tree
, hfindex
, tvb
, start
, length
, value
);
2106 va_start(ap
, format
);
2107 proto_tree_set_representation_value(pi
, format
, ap
);
2115 proto_tree_add_ipxnet_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2116 gint start
, gint length
, guint32 value
,
2117 const char *format
, ...)
2122 pi
= proto_tree_add_ipxnet(tree
, hfindex
, tvb
, start
, length
, value
);
2124 TRY_TO_FAKE_THIS_REPR(pi
);
2126 va_start(ap
, format
);
2127 proto_tree_set_representation(pi
, format
, ap
);
2134 /* Set the FT_IPXNET value */
2136 proto_tree_set_ipxnet(field_info
*fi
, guint32 value
)
2138 fvalue_set_uinteger(&fi
->value
, value
);
2141 /* Add a FT_IPv4 to a proto_tree */
2143 proto_tree_add_ipv4(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2144 gint length
, guint32 value
)
2147 header_field_info
*hfinfo
;
2149 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2151 DISSECTOR_ASSERT(hfinfo
->type
== FT_IPv4
);
2153 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2154 proto_tree_set_ipv4(PNODE_FINFO(pi
), value
);
2160 proto_tree_add_ipv4_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2161 gint start
, gint length
, guint32 value
,
2162 const char *format
, ...)
2167 pi
= proto_tree_add_ipv4(tree
, hfindex
, tvb
, start
, length
, value
);
2169 va_start(ap
, format
);
2170 proto_tree_set_representation_value(pi
, format
, ap
);
2178 proto_tree_add_ipv4_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2179 gint start
, gint length
, guint32 value
,
2180 const char *format
, ...)
2185 pi
= proto_tree_add_ipv4(tree
, hfindex
, tvb
, start
, length
, value
);
2187 TRY_TO_FAKE_THIS_REPR(pi
);
2189 va_start(ap
, format
);
2190 proto_tree_set_representation(pi
, format
, ap
);
2197 /* Set the FT_IPv4 value */
2199 proto_tree_set_ipv4(field_info
*fi
, guint32 value
)
2201 fvalue_set_uinteger(&fi
->value
, value
);
2204 /* Add a FT_IPv6 to a proto_tree */
2206 proto_tree_add_ipv6(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2207 gint length
, const guint8
* value_ptr
)
2210 header_field_info
*hfinfo
;
2212 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2214 DISSECTOR_ASSERT(hfinfo
->type
== FT_IPv6
);
2216 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2217 proto_tree_set_ipv6(PNODE_FINFO(pi
), value_ptr
);
2223 proto_tree_add_ipv6_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2224 gint start
, gint length
,
2225 const guint8
* value_ptr
,
2226 const char *format
, ...)
2231 pi
= proto_tree_add_ipv6(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2233 va_start(ap
, format
);
2234 proto_tree_set_representation_value(pi
, format
, ap
);
2242 proto_tree_add_ipv6_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2243 gint start
, gint length
, const guint8
* value_ptr
,
2244 const char *format
, ...)
2249 pi
= proto_tree_add_ipv6(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2251 TRY_TO_FAKE_THIS_REPR(pi
);
2253 va_start(ap
, format
);
2254 proto_tree_set_representation(pi
, format
, ap
);
2261 /* Set the FT_IPv6 value */
2263 proto_tree_set_ipv6(field_info
*fi
, const guint8
* value_ptr
)
2265 DISSECTOR_ASSERT(value_ptr
!= NULL
);
2266 fvalue_set(&fi
->value
, (gpointer
) value_ptr
, FALSE
);
2270 proto_tree_set_ipv6_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, gint length
)
2272 proto_tree_set_ipv6(fi
, tvb_get_ptr(tvb
, start
, length
));
2275 /* Add a FT_GUID to a proto_tree */
2277 proto_tree_add_guid(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2278 gint length
, const e_guid_t
*value_ptr
)
2281 header_field_info
*hfinfo
;
2283 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2285 DISSECTOR_ASSERT(hfinfo
->type
== FT_GUID
);
2287 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2288 proto_tree_set_guid(PNODE_FINFO(pi
), value_ptr
);
2294 proto_tree_add_guid_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2295 gint start
, gint length
,
2296 const e_guid_t
*value_ptr
,
2297 const char *format
, ...)
2302 pi
= proto_tree_add_guid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2304 va_start(ap
, format
);
2305 proto_tree_set_representation_value(pi
, format
, ap
);
2313 proto_tree_add_guid_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2314 gint start
, gint length
, const e_guid_t
*value_ptr
,
2315 const char *format
, ...)
2320 pi
= proto_tree_add_guid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2322 TRY_TO_FAKE_THIS_REPR(pi
);
2324 va_start(ap
, format
);
2325 proto_tree_set_representation(pi
, format
, ap
);
2332 /* Set the FT_GUID value */
2334 proto_tree_set_guid(field_info
*fi
, const e_guid_t
*value_ptr
)
2336 DISSECTOR_ASSERT(value_ptr
!= NULL
);
2337 fvalue_set(&fi
->value
, (gpointer
) value_ptr
, FALSE
);
2341 proto_tree_set_guid_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
,
2342 const guint encoding
)
2346 tvb_get_guid(tvb
, start
, &guid
, encoding
);
2347 proto_tree_set_guid(fi
, &guid
);
2350 /* Add a FT_OID to a proto_tree */
2352 proto_tree_add_oid(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2353 gint length
, const guint8
* value_ptr
)
2356 header_field_info
*hfinfo
;
2358 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2360 DISSECTOR_ASSERT(hfinfo
->type
== FT_OID
);
2362 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2363 proto_tree_set_oid(PNODE_FINFO(pi
), value_ptr
, length
);
2369 proto_tree_add_oid_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2370 gint start
, gint length
,
2371 const guint8
* value_ptr
,
2372 const char *format
, ...)
2377 pi
= proto_tree_add_oid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2379 va_start(ap
, format
);
2380 proto_tree_set_representation_value(pi
, format
, ap
);
2388 proto_tree_add_oid_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2389 gint start
, gint length
, const guint8
* value_ptr
,
2390 const char *format
, ...)
2395 pi
= proto_tree_add_oid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
2397 TRY_TO_FAKE_THIS_REPR(pi
);
2399 va_start(ap
, format
);
2400 proto_tree_set_representation(pi
, format
, ap
);
2407 /* Set the FT_OID value */
2409 proto_tree_set_oid(field_info
*fi
, const guint8
* value_ptr
, gint length
)
2413 DISSECTOR_ASSERT(value_ptr
!= NULL
|| length
== 0);
2415 bytes
= g_byte_array_new();
2417 g_byte_array_append(bytes
, value_ptr
, length
);
2419 fvalue_set(&fi
->value
, bytes
, TRUE
);
2423 proto_tree_set_oid_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, gint length
)
2425 proto_tree_set_oid(fi
, tvb_get_ptr(tvb
, start
, length
), length
);
2429 proto_tree_set_uint64(field_info
*fi
, guint64 value
)
2431 fvalue_set_integer64(&fi
->value
, value
);
2435 * NOTE: to support code written when proto_tree_add_item() took a
2436 * gboolean as its last argument, with FALSE meaning "big-endian"
2437 * and TRUE meaning "little-endian", we treat any non-zero value of
2438 * "encoding" as meaning "little-endian".
2441 proto_tree_set_uint64_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
,
2442 guint length
, const guint encoding
)
2445 guint8
* b
= (guint8
*)tvb_memdup(wmem_packet_scope(), tvb
, start
, length
);
2450 default: DISSECTOR_ASSERT_NOT_REACHED();
2451 case 8: value
<<= 8; value
+= *--b
;
2452 case 7: value
<<= 8; value
+= *--b
;
2453 case 6: value
<<= 8; value
+= *--b
;
2454 case 5: value
<<= 8; value
+= *--b
;
2455 case 4: value
<<= 8; value
+= *--b
;
2456 case 3: value
<<= 8; value
+= *--b
;
2457 case 2: value
<<= 8; value
+= *--b
;
2458 case 1: value
<<= 8; value
+= *--b
;
2463 default: DISSECTOR_ASSERT_NOT_REACHED();
2464 case 8: value
<<= 8; value
+= *b
++;
2465 case 7: value
<<= 8; value
+= *b
++;
2466 case 6: value
<<= 8; value
+= *b
++;
2467 case 5: value
<<= 8; value
+= *b
++;
2468 case 4: value
<<= 8; value
+= *b
++;
2469 case 3: value
<<= 8; value
+= *b
++;
2470 case 2: value
<<= 8; value
+= *b
++;
2471 case 1: value
<<= 8; value
+= *b
++;
2476 proto_tree_set_uint64(fi
, value
);
2479 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2480 * and frees it when the proto_tree is destroyed. */
2482 proto_tree_add_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2483 gint length
, const char* value
)
2486 header_field_info
*hfinfo
;
2488 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2490 DISSECTOR_ASSERT(hfinfo
->type
== FT_STRING
|| hfinfo
->type
== FT_STRINGZ
);
2492 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2493 DISSECTOR_ASSERT(length
>= 0);
2494 proto_tree_set_string(PNODE_FINFO(pi
), value
);
2500 proto_tree_add_unicode_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2501 gint length
, const char* value
)
2503 DISSECTOR_ASSERT(g_utf8_validate(value
, -1, NULL
));
2504 return proto_tree_add_string_format_value(tree
, hfindex
, tvb
, start
, length
, value
, "%s", value
);
2508 proto_tree_add_string_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2509 gint start
, gint length
, const char* value
,
2516 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
2518 va_start(ap
, format
);
2519 proto_tree_set_representation_value(pi
, format
, ap
);
2527 proto_tree_add_string_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2528 gint start
, gint length
, const char* value
,
2529 const char *format
, ...)
2534 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
2536 TRY_TO_FAKE_THIS_REPR(pi
);
2538 va_start(ap
, format
);
2539 proto_tree_set_representation(pi
, format
, ap
);
2546 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2547 * field info update instead of only updating the representation as does
2548 * proto_item_append_text()
2550 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2551 * speed optimization.
2552 * Currently only WSP use this function so it is not that bad but try to
2553 * avoid using this one if possible.
2554 * IF you must use this function you MUST also disable the
2555 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2556 * using proto_item_append_string().
2557 * Do that by faking that the tree is visible by calling
2558 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2559 * BEFORE you create the item you are later going to use
2560 * proto_item_append_string() on.
2563 proto_item_append_string(proto_item
*pi
, const char *str
)
2566 header_field_info
*hfinfo
;
2567 const gchar
*old_str
, *new_str
;
2574 fi
= PITEM_FINFO(pi
);
2575 DISSECTOR_ASSERT_HINT(fi
, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2577 hfinfo
= fi
->hfinfo
;
2578 if (hfinfo
->type
== FT_PROTOCOL
) {
2579 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2582 DISSECTOR_ASSERT(hfinfo
->type
== FT_STRING
|| hfinfo
->type
== FT_STRINGZ
);
2583 old_str
= (guint8
*)fvalue_get(&fi
->value
);
2584 if (old_str
&& old_str
[0])
2585 new_str
= ep_strconcat(old_str
, str
, NULL
);
2588 fvalue_set(&fi
->value
, (gpointer
) new_str
, FALSE
);
2591 /* Set the FT_STRING value */
2593 proto_tree_set_string(field_info
*fi
, const char* value
)
2596 fvalue_set(&fi
->value
, (gpointer
) value
, FALSE
);
2598 fvalue_set(&fi
->value
, (gpointer
) "[ Null ]", FALSE
);
2603 proto_tree_set_string_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, gint length
, gint encoding
)
2608 length
= tvb_ensure_length_remaining(tvb
, start
);
2611 string
= tvb_get_string_enc(wmem_packet_scope(), tvb
, start
, length
, encoding
);
2612 proto_tree_set_string(fi
, string
);
2616 /* Add a FT_AX25 to a proto_tree */
2618 proto_tree_add_ax25(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
, gint length
,
2619 const guint8
* value
)
2622 header_field_info
*hfinfo
;
2624 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2626 DISSECTOR_ASSERT(hfinfo
->type
== FT_AX25
);
2628 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2629 proto_tree_set_ax25(PNODE_FINFO(pi
), value
);
2634 /* Set the FT_AX25 value */
2636 proto_tree_set_ax25(field_info
*fi
, const guint8
* value
)
2638 fvalue_set(&fi
->value
, (gpointer
) value
, FALSE
);
2642 proto_tree_set_ax25_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
)
2644 proto_tree_set_ax25(fi
, tvb_get_ptr(tvb
, start
, 7));
2647 /* Set the FT_VINES value */
2649 proto_tree_set_vines(field_info
*fi
, const guint8
* value
)
2651 fvalue_set(&fi
->value
, (gpointer
) value
, FALSE
);
2655 proto_tree_set_vines_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
)
2657 proto_tree_set_vines(fi
, tvb_get_ptr(tvb
, start
, FT_VINES_ADDR_LEN
));
2660 /* Add a FT_ETHER to a proto_tree */
2662 proto_tree_add_ether(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2663 gint length
, const guint8
* value
)
2666 header_field_info
*hfinfo
;
2668 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2670 DISSECTOR_ASSERT(hfinfo
->type
== FT_ETHER
);
2672 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2673 proto_tree_set_ether(PNODE_FINFO(pi
), value
);
2679 proto_tree_add_ether_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2680 gint start
, gint length
, const guint8
* value
,
2681 const char *format
, ...)
2686 pi
= proto_tree_add_ether(tree
, hfindex
, tvb
, start
, length
, value
);
2688 va_start(ap
, format
);
2689 proto_tree_set_representation_value(pi
, format
, ap
);
2697 proto_tree_add_ether_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2698 gint start
, gint length
, const guint8
* value
,
2699 const char *format
, ...)
2704 pi
= proto_tree_add_ether(tree
, hfindex
, tvb
, start
, length
, value
);
2706 TRY_TO_FAKE_THIS_REPR(pi
);
2708 va_start(ap
, format
);
2709 proto_tree_set_representation(pi
, format
, ap
);
2716 /* Set the FT_ETHER value */
2718 proto_tree_set_ether(field_info
*fi
, const guint8
* value
)
2720 fvalue_set(&fi
->value
, (gpointer
) value
, FALSE
);
2724 proto_tree_set_ether_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
)
2726 proto_tree_set_ether(fi
, tvb_get_ptr(tvb
, start
, FT_ETHER_LEN
));
2729 /* Add a FT_BOOLEAN to a proto_tree */
2731 proto_tree_add_boolean(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2732 gint length
, guint32 value
)
2735 header_field_info
*hfinfo
;
2737 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2739 DISSECTOR_ASSERT(hfinfo
->type
== FT_BOOLEAN
);
2741 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2742 proto_tree_set_boolean(PNODE_FINFO(pi
), value
);
2748 proto_tree_add_boolean_format_value(proto_tree
*tree
, int hfindex
,
2749 tvbuff_t
*tvb
, gint start
, gint length
,
2750 guint32 value
, const char *format
, ...)
2755 pi
= proto_tree_add_boolean(tree
, hfindex
, tvb
, start
, length
, value
);
2757 va_start(ap
, format
);
2758 proto_tree_set_representation_value(pi
, format
, ap
);
2766 proto_tree_add_boolean_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2767 gint start
, gint length
, guint32 value
,
2768 const char *format
, ...)
2773 pi
= proto_tree_add_boolean(tree
, hfindex
, tvb
, start
, length
, value
);
2775 TRY_TO_FAKE_THIS_REPR(pi
);
2777 va_start(ap
, format
);
2778 proto_tree_set_representation(pi
, format
, ap
);
2785 /* Set the FT_BOOLEAN value */
2787 proto_tree_set_boolean(field_info
*fi
, guint32 value
)
2789 proto_tree_set_uint(fi
, value
);
2792 /* Add a FT_FLOAT to a proto_tree */
2794 proto_tree_add_float(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2795 gint length
, float value
)
2798 header_field_info
*hfinfo
;
2800 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2802 DISSECTOR_ASSERT(hfinfo
->type
== FT_FLOAT
);
2804 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2805 proto_tree_set_float(PNODE_FINFO(pi
), value
);
2811 proto_tree_add_float_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2812 gint start
, gint length
, float value
,
2813 const char *format
, ...)
2818 pi
= proto_tree_add_float(tree
, hfindex
, tvb
, start
, length
, value
);
2820 va_start(ap
, format
);
2821 proto_tree_set_representation_value(pi
, format
, ap
);
2829 proto_tree_add_float_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2830 gint start
, gint length
, float value
,
2831 const char *format
, ...)
2836 pi
= proto_tree_add_float(tree
, hfindex
, tvb
, start
, length
, value
);
2838 TRY_TO_FAKE_THIS_REPR(pi
);
2840 va_start(ap
, format
);
2841 proto_tree_set_representation(pi
, format
, ap
);
2848 /* Set the FT_FLOAT value */
2850 proto_tree_set_float(field_info
*fi
, float value
)
2852 fvalue_set_floating(&fi
->value
, value
);
2855 /* Add a FT_DOUBLE to a proto_tree */
2857 proto_tree_add_double(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2858 gint length
, double value
)
2861 header_field_info
*hfinfo
;
2863 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2865 DISSECTOR_ASSERT(hfinfo
->type
== FT_DOUBLE
);
2867 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2868 proto_tree_set_double(PNODE_FINFO(pi
), value
);
2874 proto_tree_add_double_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2875 gint start
, gint length
, double value
,
2876 const char *format
, ...)
2881 pi
= proto_tree_add_double(tree
, hfindex
, tvb
, start
, length
, value
);
2883 va_start(ap
, format
);
2884 proto_tree_set_representation_value(pi
, format
, ap
);
2892 proto_tree_add_double_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2893 gint start
, gint length
, double value
,
2894 const char *format
, ...)
2899 pi
= proto_tree_add_double(tree
, hfindex
, tvb
, start
, length
, value
);
2901 TRY_TO_FAKE_THIS_REPR(pi
);
2903 va_start(ap
, format
);
2904 proto_tree_set_representation(pi
, format
, ap
);
2911 /* Set the FT_DOUBLE value */
2913 proto_tree_set_double(field_info
*fi
, double value
)
2915 fvalue_set_floating(&fi
->value
, value
);
2918 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2920 proto_tree_add_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
2921 gint length
, guint32 value
)
2923 proto_item
*pi
= NULL
;
2924 header_field_info
*hfinfo
;
2926 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
2928 switch (hfinfo
->type
) {
2934 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
2935 proto_tree_set_uint(PNODE_FINFO(pi
), value
);
2939 DISSECTOR_ASSERT_NOT_REACHED();
2946 proto_tree_add_uint_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2947 gint start
, gint length
, guint32 value
,
2948 const char *format
, ...)
2953 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, value
);
2955 va_start(ap
, format
);
2956 proto_tree_set_representation_value(pi
, format
, ap
);
2964 proto_tree_add_uint_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
2965 gint start
, gint length
, guint32 value
,
2966 const char *format
, ...)
2971 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, value
);
2973 TRY_TO_FAKE_THIS_REPR(pi
);
2975 va_start(ap
, format
);
2976 proto_tree_set_representation(pi
, format
, ap
);
2983 /* Set the FT_UINT{8,16,24,32} value */
2985 proto_tree_set_uint(field_info
*fi
, guint32 value
)
2987 header_field_info
*hfinfo
;
2990 hfinfo
= fi
->hfinfo
;
2993 if (hfinfo
->bitmask
) {
2994 /* Mask out irrelevant portions */
2995 integer
&= hfinfo
->bitmask
;
2998 integer
>>= hfinfo_bitshift(hfinfo
);
3001 fvalue_set_uinteger(&fi
->value
, integer
);
3004 /* Add FT_UINT64 to a proto_tree */
3006 proto_tree_add_uint64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
3007 gint length
, guint64 value
)
3010 header_field_info
*hfinfo
;
3012 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
3014 DISSECTOR_ASSERT(hfinfo
->type
== FT_UINT64
);
3016 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
3017 proto_tree_set_uint64(PNODE_FINFO(pi
), value
);
3023 proto_tree_add_uint64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3024 gint start
, gint length
, guint64 value
,
3025 const char *format
, ...)
3030 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, start
, length
, value
);
3032 va_start(ap
, format
);
3033 proto_tree_set_representation_value(pi
, format
, ap
);
3041 proto_tree_add_uint64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3042 gint start
, gint length
, guint64 value
,
3043 const char *format
, ...)
3048 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, start
, length
, value
);
3050 TRY_TO_FAKE_THIS_REPR(pi
);
3052 va_start(ap
, format
);
3053 proto_tree_set_representation(pi
, format
, ap
);
3060 /* Add FT_INT{8,16,24,32} to a proto_tree */
3062 proto_tree_add_int(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
3063 gint length
, gint32 value
)
3065 proto_item
*pi
= NULL
;
3066 header_field_info
*hfinfo
;
3068 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
3070 switch (hfinfo
->type
) {
3075 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
3076 proto_tree_set_int(PNODE_FINFO(pi
), value
);
3080 DISSECTOR_ASSERT_NOT_REACHED();
3087 proto_tree_add_int_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3088 gint start
, gint length
, gint32 value
,
3089 const char *format
, ...)
3094 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, start
, length
, value
);
3096 va_start(ap
, format
);
3097 proto_tree_set_representation_value(pi
, format
, ap
);
3105 proto_tree_add_int_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3106 gint start
, gint length
, gint32 value
,
3107 const char *format
, ...)
3112 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, start
, length
, value
);
3114 TRY_TO_FAKE_THIS_REPR(pi
);
3116 va_start(ap
, format
);
3117 proto_tree_set_representation(pi
, format
, ap
);
3124 /* Set the FT_INT{8,16,24,32} value */
3126 proto_tree_set_int(field_info
*fi
, gint32 value
)
3128 header_field_info
*hfinfo
;
3132 hfinfo
= fi
->hfinfo
;
3133 integer
= (guint32
) value
;
3135 if (hfinfo
->bitmask
) {
3136 /* Mask out irrelevant portions */
3137 integer
&= hfinfo
->bitmask
;
3140 integer
>>= hfinfo_bitshift(hfinfo
);
3142 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
3143 if (integer
& (1 << (no_of_bits
-1)))
3144 integer
|= (-1 << no_of_bits
);
3147 fvalue_set_sinteger(&fi
->value
, integer
);
3150 /* Add FT_INT64 to a proto_tree */
3152 proto_tree_add_int64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
3153 gint length
, gint64 value
)
3156 header_field_info
*hfinfo
;
3158 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
3160 DISSECTOR_ASSERT(hfinfo
->type
== FT_INT64
);
3162 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
3163 proto_tree_set_uint64(PNODE_FINFO(pi
), (guint64
)value
);
3169 proto_tree_add_int64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3170 gint start
, gint length
, gint64 value
,
3171 const char *format
, ...)
3176 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, start
, length
, value
);
3178 va_start(ap
, format
);
3179 proto_tree_set_representation_value(pi
, format
, ap
);
3187 proto_tree_add_int64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3188 gint start
, gint length
, gint64 value
,
3189 const char *format
, ...)
3194 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, start
, length
, value
);
3196 TRY_TO_FAKE_THIS_REPR(pi
);
3198 va_start(ap
, format
);
3199 proto_tree_set_representation(pi
, format
, ap
);
3205 /* Add a FT_EUI64 to a proto_tree */
3207 proto_tree_add_eui64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, gint start
,
3208 gint length
, const guint64 value
)
3211 header_field_info
*hfinfo
;
3213 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
3215 DISSECTOR_ASSERT(hfinfo
->type
== FT_EUI64
);
3217 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
3218 proto_tree_set_eui64(PNODE_FINFO(pi
), value
);
3224 proto_tree_add_eui64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3225 gint start
, gint length
, const guint64 value
,
3226 const char *format
, ...)
3231 pi
= proto_tree_add_eui64(tree
, hfindex
, tvb
, start
, length
, value
);
3233 va_start(ap
, format
);
3234 proto_tree_set_representation_value(pi
, format
, ap
);
3242 proto_tree_add_eui64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3243 gint start
, gint length
, const guint64 value
,
3244 const char *format
, ...)
3249 pi
= proto_tree_add_eui64(tree
, hfindex
, tvb
, start
, length
, value
);
3251 TRY_TO_FAKE_THIS_REPR(pi
);
3253 va_start(ap
, format
);
3254 proto_tree_set_representation(pi
, format
, ap
);
3261 /* Set the FT_EUI64 value */
3263 proto_tree_set_eui64(field_info
*fi
, const guint64 value
)
3265 fvalue_set_integer64(&fi
->value
, value
);
3268 proto_tree_set_eui64_tvb(field_info
*fi
, tvbuff_t
*tvb
, gint start
, const guint encoding
)
3272 proto_tree_set_eui64(fi
, tvb_get_letoh64(tvb
, start
));
3274 proto_tree_set_eui64(fi
, tvb_get_ntoh64(tvb
, start
));
3278 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3280 proto_tree_add_node(proto_tree
*tree
, field_info
*fi
)
3282 proto_node
*pnode
, *tnode
, *sibling
;
3286 * Make sure "tree" is ready to have subtrees under it, by
3287 * checking whether it's been given an ett_ value.
3289 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3290 * node of the protocol tree. That node is not displayed,
3291 * so it doesn't need an ett_ value to remember whether it
3295 tfi
= PNODE_FINFO(tnode
);
3296 if (tfi
!= NULL
&& (tfi
->tree_type
< 0 || tfi
->tree_type
>= num_tree_types
)) {
3297 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3298 fi
->hfinfo
->name
, fi
->hfinfo
->abbrev
, tfi
->tree_type
, __FILE__
, __LINE__
));
3299 /* XXX - is it safe to continue here? */
3302 pnode
= wmem_new(PNODE_POOL(tree
), proto_node
);
3303 PROTO_NODE_INIT(pnode
);
3304 pnode
->parent
= tnode
;
3305 PNODE_FINFO(pnode
) = fi
;
3306 pnode
->tree_data
= PTREE_DATA(tree
);
3308 if (tnode
->last_child
!= NULL
) {
3309 sibling
= tnode
->last_child
;
3310 DISSECTOR_ASSERT(sibling
->next
== NULL
);
3311 sibling
->next
= pnode
;
3313 tnode
->first_child
= pnode
;
3314 tnode
->last_child
= pnode
;
3316 tree_data_add_maybe_interesting_field(pnode
->tree_data
, fi
);
3318 return (proto_item
*)pnode
;
3322 /* Generic way to allocate field_info and add to proto_tree.
3323 * Sets *pfi to address of newly-allocated field_info struct */
3325 proto_tree_add_pi(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
, gint start
,
3331 fi
= alloc_field_info(tree
, hfinfo
, tvb
, start
, length
);
3332 pi
= proto_tree_add_node(tree
, fi
);
3339 get_hfi_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const gint start
, gint
*length
,
3342 gint length_remaining
;
3345 * We only allow a null tvbuff if the item has a zero length,
3346 * i.e. if there's no data backing it.
3348 DISSECTOR_ASSERT(tvb
!= NULL
|| *length
== 0);
3351 * XXX - in some protocols, there are 32-bit unsigned length
3352 * fields, so lengths in protocol tree and tvbuff routines
3353 * should really be unsigned. We should have, for those
3354 * field types for which "to the end of the tvbuff" makes sense,
3355 * additional routines that take no length argument and
3356 * add fields that run to the end of the tvbuff.
3358 if (*length
== -1) {
3360 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3361 * a length of -1 means "set the length to what remains in
3364 * The assumption is either that
3366 * 1) the length of the item can only be determined
3367 * by dissection (typically true of items with
3368 * subitems, which are probably FT_NONE or
3373 * 2) if the tvbuff is "short" (either due to a short
3374 * snapshot length or due to lack of reassembly of
3375 * fragments/segments/whatever), we want to display
3376 * what's available in the field (probably FT_BYTES
3377 * or FT_STRING) and then throw an exception later
3381 * 3) the field is defined to be "what's left in the
3384 * so we set the length to what remains in the tvbuff so
3385 * that, if we throw an exception while dissecting, it
3386 * has what is probably the right value.
3388 * For FT_STRINGZ, it means "the string is null-terminated,
3389 * not null-padded; set the length to the actual length
3390 * of the string", and if the tvbuff if short, we just
3391 * throw an exception.
3393 * It's not valid for any other type of field.
3395 switch (hfinfo
->type
) {
3399 * We allow this to be zero-length - for
3400 * example, an ONC RPC NULL procedure has
3401 * neither arguments nor reply, so the
3402 * payload for that protocol is empty.
3404 * However, if the length is negative, the
3405 * start offset is *past* the byte past the
3406 * end of the tvbuff, so we throw an
3409 *length
= tvb_length_remaining(tvb
, start
);
3412 * Use "tvb_ensure_bytes_exist()"
3413 * to force the appropriate exception
3416 tvb_ensure_bytes_exist(tvb
, start
, 0);
3418 DISSECTOR_ASSERT(*length
>= 0);
3424 *length
= tvb_ensure_length_remaining(tvb
, start
);
3425 DISSECTOR_ASSERT(*length
>= 0);
3430 * Leave the length as -1, so our caller knows
3436 DISSECTOR_ASSERT_NOT_REACHED();
3438 *item_length
= *length
;
3440 *item_length
= *length
;
3441 if (hfinfo
->type
== FT_PROTOCOL
|| hfinfo
->type
== FT_NONE
) {
3443 * These types are for interior nodes of the
3444 * tree, and don't have data associated with
3445 * them; if the length is negative (XXX - see
3446 * above) or goes past the end of the tvbuff,
3447 * cut it short at the end of the tvbuff.
3448 * That way, if this field is selected in
3449 * Wireshark, we don't highlight stuff past
3450 * the end of the data.
3452 /* XXX - what to do, if we don't have a tvb? */
3454 length_remaining
= tvb_length_remaining(tvb
, start
);
3455 if (*item_length
< 0 ||
3456 (*item_length
> 0 &&
3457 (length_remaining
< *item_length
)))
3458 *item_length
= length_remaining
;
3461 if (*item_length
< 0) {
3462 THROW(ReportedBoundsError
);
3468 new_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
3469 const gint start
, const gint item_length
)
3473 FIELD_INFO_NEW(PNODE_POOL(tree
), fi
);
3475 fi
->hfinfo
= hfinfo
;
3477 fi
->start
+= (tvb
)?tvb_raw_offset(tvb
):0;
3478 fi
->length
= item_length
;
3481 if (!PTREE_DATA(tree
)->visible
)
3482 FI_SET_FLAG(fi
, FI_HIDDEN
);
3483 fvalue_init(&fi
->value
, fi
->hfinfo
->type
);
3486 /* add the data source tvbuff */
3487 fi
->ds_tvb
= tvb
? tvb_get_ds_tvb(tvb
) : NULL
;
3489 fi
->appendix_start
= 0;
3490 fi
->appendix_length
= 0;
3496 alloc_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
, const gint start
,
3501 get_hfi_length(hfinfo
, tvb
, start
, length
, &item_length
);
3502 return new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
3506 label_mark_truncated_start(char *label_str
)
3508 static const char trunc_str
[] = "[truncated] ";
3509 const size_t trunc_len
= sizeof(trunc_str
)-1;
3511 memmove(label_str
+ trunc_len
, label_str
, ITEM_LABEL_LENGTH
- trunc_len
);
3512 memcpy(label_str
, trunc_str
, trunc_len
);
3513 label_str
[ITEM_LABEL_LENGTH
-1] = '\0';
3516 /* If the protocol tree is to be visible, set the representation of a
3517 proto_tree entry with the name of the field for the item and with
3518 the value formatted with the supplied printf-style format and
3521 proto_tree_set_representation_value(proto_item
*pi
, const char *format
, va_list ap
)
3525 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3526 * items string representation */
3527 if (PTREE_DATA(pi
)->visible
&& !PROTO_ITEM_IS_HIDDEN(pi
)) {
3529 field_info
*fi
= PITEM_FINFO(pi
);
3530 header_field_info
*hf
;
3532 DISSECTOR_ASSERT(fi
);
3536 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
3537 if (hf
->bitmask
&& (hf
->type
== FT_BOOLEAN
|| IS_FT_UINT(hf
->type
))) {
3541 val
= fvalue_get_uinteger(&fi
->value
);
3542 val
<<= hfinfo_bitshift(hf
);
3544 p
= decode_bitfield_value(fi
->rep
->representation
, val
, hf
->bitmask
, hfinfo_bitwidth(hf
));
3545 ret
= (int) (p
- fi
->rep
->representation
);
3548 /* put in the hf name */
3549 ret
+= g_snprintf(fi
->rep
->representation
+ ret
, ITEM_LABEL_LENGTH
- ret
, "%s: ", hf
->name
);
3551 /* If possible, Put in the value of the string */
3552 if (ret
< ITEM_LABEL_LENGTH
) {
3553 ret
+= g_vsnprintf(fi
->rep
->representation
+ ret
,
3554 ITEM_LABEL_LENGTH
- ret
, format
, ap
);
3556 if (ret
>= ITEM_LABEL_LENGTH
) {
3557 /* Uh oh, we don't have enough room. Tell the user
3558 * that the field is truncated.
3560 /* XXX, label_mark_truncated() ? */
3561 label_mark_truncated_start(fi
->rep
->representation
);
3566 /* If the protocol tree is to be visible, set the representation of a
3567 proto_tree entry with the representation formatted with the supplied
3568 printf-style format and argument list. */
3570 proto_tree_set_representation(proto_item
*pi
, const char *format
, va_list ap
)
3572 int ret
; /*tmp return value */
3573 field_info
*fi
= PITEM_FINFO(pi
);
3575 DISSECTOR_ASSERT(fi
);
3577 if (!PROTO_ITEM_IS_HIDDEN(pi
)) {
3578 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
3579 ret
= g_vsnprintf(fi
->rep
->representation
, ITEM_LABEL_LENGTH
,
3581 if (ret
>= ITEM_LABEL_LENGTH
) {
3582 /* Uh oh, we don't have enough room. Tell the user
3583 * that the field is truncated.
3585 label_mark_truncated_start(fi
->rep
->representation
);
3591 protoo_strlcpy(gchar
*dest
, const gchar
*src
, gsize dest_size
)
3593 gsize res
= g_strlcpy(dest
, src
, dest_size
);
3595 if (res
> dest_size
)
3600 static header_field_info
*
3601 hfinfo_same_name_get_prev(const header_field_info
*hfinfo
)
3603 if (hfinfo
->same_name_prev_id
== -1)
3605 return proto_registrar_get_nth(hfinfo
->same_name_prev_id
);
3608 /* -------------------------- */
3610 proto_custom_set(proto_tree
* tree
, const int field_id
, gint occurrence
,
3611 gchar
*result
, gchar
*expr
, const int size
)
3616 struct e_in6_addr
*ipv6
;
3618 guint32 n_addr
; /* network-order IPv4 address */
3620 const true_false_string
*tfstring
;
3622 int len
, prev_len
= 0, last
, i
, offset_r
= 0, offset_e
= 0;
3624 field_info
*finfo
= NULL
;
3625 header_field_info
* hfinfo
;
3626 const gchar
*abbrev
= NULL
;
3628 const char *hf_str_val
;
3629 char number_buf
[32];
3630 const char *number_out
;
3632 g_assert(field_id
>= 0);
3634 hfinfo
= proto_registrar_get_nth((guint
)field_id
);
3636 /* do we need to rewind ? */
3640 if (occurrence
< 0) {
3641 /* Search other direction */
3642 while (hfinfo
->same_name_prev_id
!= -1) {
3643 hfinfo
= proto_registrar_get_nth(hfinfo
->same_name_prev_id
);
3648 finfos
= proto_get_finfo_ptr_array(tree
, hfinfo
->id
);
3650 if (!finfos
|| !(len
= g_ptr_array_len(finfos
))) {
3651 if (occurrence
< 0) {
3652 hfinfo
= hfinfo
->same_name_next
;
3654 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
3659 /* Are there enough occurrences of the field? */
3660 if (((occurrence
- prev_len
) > len
) || ((occurrence
+ prev_len
) < -len
)) {
3661 if (occurrence
< 0) {
3662 hfinfo
= hfinfo
->same_name_next
;
3664 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
3670 /* Calculate single index or set outer bounderies */
3671 if (occurrence
< 0) {
3672 i
= occurrence
+ len
+ prev_len
;
3674 } else if (occurrence
> 0) {
3675 i
= occurrence
- 1 - prev_len
;
3682 prev_len
+= len
; /* Count handled occurrences */
3685 finfo
= (field_info
*)g_ptr_array_index(finfos
, i
);
3687 if (offset_r
&& (offset_r
< (size
- 2)))
3688 result
[offset_r
++] = ',';
3690 if (offset_e
&& (offset_e
< (size
- 2)))
3691 expr
[offset_e
++] = ',';
3693 switch (hfinfo
->type
) {
3695 case FT_NONE
: /* Nothing to add */
3696 if (offset_r
== 0) {
3698 } else if (result
[offset_r
-1] == ',') {
3699 result
[offset_r
-1] = '\0';
3704 /* prevent multiple "yes" entries by setting result directly */
3705 g_strlcpy(result
, "Yes", size
);
3710 bytes
= (guint8
*)fvalue_get(&finfo
->value
);
3711 offset_r
+= protoo_strlcpy(result
+offset_r
,
3713 fvalue_length(&finfo
->value
)),
3717 case FT_ABSOLUTE_TIME
:
3718 offset_r
+= protoo_strlcpy(result
+offset_r
,
3719 abs_time_to_str((const nstime_t
*)fvalue_get(&finfo
->value
),
3720 (absolute_time_display_e
)hfinfo
->display
, TRUE
),
3724 case FT_RELATIVE_TIME
:
3725 offset_r
+= protoo_strlcpy(result
+offset_r
,
3726 rel_time_to_secs_str((const nstime_t
*)fvalue_get(&finfo
->value
)),
3731 number
= fvalue_get_uinteger(&finfo
->value
);
3732 tfstring
= (const true_false_string
*)&tfs_true_false
;
3733 if (hfinfo
->strings
) {
3734 tfstring
= (const struct true_false_string
*) hfinfo
->strings
;
3736 offset_r
+= protoo_strlcpy(result
+offset_r
,
3738 tfstring
->true_string
:
3739 tfstring
->false_string
, size
-offset_r
);
3741 offset_e
+= protoo_strlcpy(expr
+offset_e
,
3742 number
? "1" : "0", size
-offset_e
);
3745 /* XXX - make these just FT_NUMBER? */
3756 number
= IS_FT_INT(hfinfo
->type
) ?
3757 (guint32
) fvalue_get_sinteger(&finfo
->value
) :
3758 fvalue_get_uinteger(&finfo
->value
);
3760 if ((hfinfo
->display
& BASE_DISPLAY_E_MASK
) == BASE_CUSTOM
) {
3761 gchar tmp
[ITEM_LABEL_LENGTH
];
3762 custom_fmt_func_t fmtfunc
= (custom_fmt_func_t
)hfinfo
->strings
;
3764 DISSECTOR_ASSERT(fmtfunc
);
3765 fmtfunc(tmp
, number
);
3767 offset_r
+= protoo_strlcpy(result
+offset_r
, tmp
, size
-offset_r
);
3769 } else if (hfinfo
->strings
) {
3770 number_out
= hf_str_val
= hf_try_val_to_str(number
, hfinfo
);
3773 number_out
= hfinfo_number_value_format_display(hfinfo
, BASE_DEC
, number_buf
, number
);
3775 offset_r
+= protoo_strlcpy(result
+offset_r
, number_out
, size
-offset_r
);
3778 number_out
= hfinfo_number_value_format(hfinfo
, number_buf
, number
);
3780 offset_r
+= protoo_strlcpy(result
+offset_r
, number_out
, size
-offset_r
);
3783 if (hf_str_val
&& (hfinfo
->display
& BASE_DISPLAY_E_MASK
) == BASE_NONE
) {
3784 g_snprintf(expr
+offset_e
, size
-offset_e
, "\"%s\"", hf_str_val
);
3786 number_out
= hfinfo_numeric_value_format(hfinfo
, number_buf
, number
);
3788 g_strlcpy(expr
+offset_e
, number_out
, size
-offset_e
);
3791 offset_e
= (int)strlen(expr
);
3795 /* XXX: Should handle BASE_CUSTOM ? */
3796 g_snprintf(result
+offset_r
, size
-offset_r
,
3797 "%" G_GINT64_MODIFIER
"d",
3798 fvalue_get_integer64(&finfo
->value
));
3799 offset_r
= (int)strlen(result
);
3802 g_snprintf(result
+offset_r
, size
-offset_r
,
3803 /* XXX: Should handle BASE_CUSTOM ? */
3804 "%" G_GINT64_MODIFIER
"u",
3805 fvalue_get_integer64(&finfo
->value
));
3806 offset_r
= (int)strlen(result
);
3809 offset_r
+= protoo_strlcpy(result
+offset_r
,
3810 eui64_to_str(fvalue_get_integer64(&finfo
->value
)),
3815 ipv4
= (ipv4_addr
*)fvalue_get(&finfo
->value
);
3816 n_addr
= ipv4_get_net_order_addr(ipv4
);
3817 offset_r
+= protoo_strlcpy(result
+offset_r
,
3818 ip_to_str((guint8
*)&n_addr
),
3823 ipv6
= (struct e_in6_addr
*)fvalue_get(&finfo
->value
);
3824 SET_ADDRESS (&addr
, AT_IPv6
, sizeof(struct e_in6_addr
), ipv6
);
3825 address_to_str_buf(&addr
, result
+offset_r
, size
-offset_r
);
3826 offset_r
= (int)strlen(result
);
3830 offset_r
+= protoo_strlcpy(result
+offset_r
,
3831 bytes_to_str_punct((const guint8
*)fvalue_get(&finfo
->value
),
3837 offset_r
+= protoo_strlcpy(result
+offset_r
,
3838 guid_to_str((e_guid_t
*)fvalue_get(&finfo
->value
)),
3843 bytes
= (guint8
*)fvalue_get(&finfo
->value
);
3844 offset_r
+= protoo_strlcpy(result
+offset_r
,
3845 rel_oid_resolved_from_encoded(bytes
,
3846 fvalue_length(&finfo
->value
)),
3848 offset_e
+= protoo_strlcpy(expr
+offset_e
,
3849 rel_oid_encoded2string(bytes
, fvalue_length(&finfo
->value
)),
3854 bytes
= (guint8
*)fvalue_get(&finfo
->value
);
3855 offset_r
+= protoo_strlcpy(result
+offset_r
,
3856 oid_resolved_from_encoded(bytes
,
3857 fvalue_length(&finfo
->value
)),
3859 offset_e
+= protoo_strlcpy(expr
+offset_e
,
3860 oid_encoded2string(bytes
, fvalue_length(&finfo
->value
)),
3865 g_snprintf(result
+offset_r
, size
-offset_r
,
3866 "%." G_STRINGIFY(FLT_DIG
) "g", fvalue_get_floating(&finfo
->value
));
3867 offset_r
= (int)strlen(result
);
3871 g_snprintf(result
+offset_r
, size
-offset_r
,
3872 "%." G_STRINGIFY(DBL_DIG
) "g", fvalue_get_floating(&finfo
->value
));
3873 offset_r
= (int)strlen(result
);
3878 case FT_UINT_STRING
:
3879 bytes
= (guint8
*)fvalue_get(&finfo
->value
);
3880 offset_r
+= protoo_strlcpy(result
+offset_r
,
3881 format_text(bytes
, strlen(bytes
)),
3885 case FT_IPXNET
: /*XXX really No column custom ?*/
3888 g_error("hfinfo->type %d (%s) not handled\n",
3890 ftype_name(hfinfo
->type
));
3891 DISSECTOR_ASSERT_NOT_REACHED();
3897 switch (hfinfo
->type
) {
3911 /* for these types, "expr" is filled in the loop above */
3915 /* for all others, just copy "result" to "expr" */
3916 g_strlcpy(expr
, result
, size
);
3921 /* Store abbrev for return value */
3922 abbrev
= hfinfo
->abbrev
;
3925 if (occurrence
== 0) {
3926 /* Fetch next hfinfo with same name (abbrev) */
3927 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
3933 return abbrev
? abbrev
: "";
3937 /* Set text of proto_item after having already been created. */
3939 proto_item_set_text(proto_item
*pi
, const char *format
, ...)
3941 field_info
*fi
= NULL
;
3948 fi
= PITEM_FINFO(pi
);
3953 ITEM_LABEL_FREE(PNODE_POOL(pi
), fi
->rep
);
3957 va_start(ap
, format
);
3958 proto_tree_set_representation(pi
, format
, ap
);
3962 /* Append to text of proto_item after having already been created. */
3964 proto_item_append_text(proto_item
*pi
, const char *format
, ...)
3966 field_info
*fi
= NULL
;
3974 fi
= PITEM_FINFO(pi
);
3979 if (!PROTO_ITEM_IS_HIDDEN(pi
)) {
3981 * If we don't already have a representation,
3982 * generate the default representation.
3984 if (fi
->rep
== NULL
) {
3985 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
3986 proto_item_fill_label(fi
, fi
->rep
->representation
);
3989 curlen
= strlen(fi
->rep
->representation
);
3990 if (ITEM_LABEL_LENGTH
> curlen
) {
3991 va_start(ap
, format
);
3992 g_vsnprintf(fi
->rep
->representation
+ curlen
,
3993 ITEM_LABEL_LENGTH
- (gulong
) curlen
, format
, ap
);
3999 /* Prepend to text of proto_item after having already been created. */
4001 proto_item_prepend_text(proto_item
*pi
, const char *format
, ...)
4003 field_info
*fi
= NULL
;
4004 char representation
[ITEM_LABEL_LENGTH
];
4011 fi
= PITEM_FINFO(pi
);
4016 if (!PROTO_ITEM_IS_HIDDEN(pi
)) {
4018 * If we don't already have a representation,
4019 * generate the default representation.
4021 if (fi
->rep
== NULL
) {
4022 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
4023 proto_item_fill_label(fi
, representation
);
4025 g_strlcpy(representation
, fi
->rep
->representation
, ITEM_LABEL_LENGTH
);
4027 va_start(ap
, format
);
4028 g_vsnprintf(fi
->rep
->representation
,
4029 ITEM_LABEL_LENGTH
, format
, ap
);
4031 g_strlcat(fi
->rep
->representation
, representation
, ITEM_LABEL_LENGTH
);
4036 proto_item_set_len(proto_item
*pi
, const gint length
)
4043 fi
= PITEM_FINFO(pi
);
4047 DISSECTOR_ASSERT(length
>= 0);
4048 fi
->length
= length
;
4051 * You cannot just make the "len" field of a GByteArray
4052 * larger, if there's no data to back that length;
4053 * you can only make it smaller.
4055 if (fi
->value
.ftype
->ftype
== FT_BYTES
&& length
<= (gint
)fi
->value
.value
.bytes
->len
)
4056 fi
->value
.value
.bytes
->len
= length
;
4060 * Sets the length of the item based on its start and on the specified
4061 * offset, which is the offset past the end of the item; as the start
4062 * in the item is relative to the beginning of the data source tvbuff,
4063 * we need to pass in a tvbuff - the end offset is relative to the beginning
4067 proto_item_set_end(proto_item
*pi
, tvbuff_t
*tvb
, gint end
)
4074 fi
= PITEM_FINFO(pi
);
4078 end
+= tvb_raw_offset(tvb
);
4079 DISSECTOR_ASSERT(end
>= fi
->start
);
4080 fi
->length
= end
- fi
->start
;
4084 proto_item_get_len(const proto_item
*pi
)
4086 field_info
*fi
= PITEM_FINFO(pi
);
4087 return fi
? fi
->length
: -1;
4091 proto_tree_create_root(packet_info
*pinfo
)
4095 /* Initialize the proto_node */
4096 pnode
= g_slice_new(proto_tree
);
4097 PROTO_NODE_INIT(pnode
);
4098 pnode
->parent
= NULL
;
4099 PNODE_FINFO(pnode
) = NULL
;
4100 pnode
->tree_data
= g_slice_new(tree_data_t
);
4102 /* Make sure we can access pinfo everywhere */
4103 pnode
->tree_data
->pinfo
= pinfo
;
4105 /* Don't initialize the tree_data_t. Wait until we know we need it */
4106 pnode
->tree_data
->interesting_hfids
= NULL
;
4108 /* Set the default to FALSE so it's easier to
4109 * find errors; if we expect to see the protocol tree
4110 * but for some reason the default 'visible' is not
4111 * changed, then we'll find out very quickly. */
4112 pnode
->tree_data
->visible
= FALSE
;
4114 /* Make sure that we fake protocols (if possible) */
4115 pnode
->tree_data
->fake_protocols
= TRUE
;
4117 /* Keep track of the number of children */
4118 pnode
->tree_data
->count
= 0;
4120 return (proto_tree
*)pnode
;
4124 /* "prime" a proto_tree with a single hfid that a dfilter
4125 * is interested in. */
4127 proto_tree_prime_hfid(proto_tree
*tree _U_
, const gint hfid
)
4129 header_field_info
*hfinfo
;
4131 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
4132 /* this field is referenced by a filter so increase the refcount.
4133 also increase the refcount for the parent, i.e the protocol.
4135 hfinfo
->ref_type
= HF_REF_TYPE_DIRECT
;
4136 /* only increase the refcount if there is a parent.
4137 if this is a protocol and not a field then parent will be -1
4138 and there is no parent to add any refcounting for.
4140 if (hfinfo
->parent
!= -1) {
4141 header_field_info
*parent_hfinfo
;
4142 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
4144 /* Mark parent as indirectly referenced unless it is already directly
4145 * referenced, i.e. the user has specified the parent in a filter.
4147 if (parent_hfinfo
->ref_type
!= HF_REF_TYPE_DIRECT
)
4148 parent_hfinfo
->ref_type
= HF_REF_TYPE_INDIRECT
;
4153 proto_item_add_subtree(proto_item
*pi
, const gint idx
) {
4159 DISSECTOR_ASSERT(idx
>= 0 && idx
< num_tree_types
);
4161 fi
= PITEM_FINFO(pi
);
4163 return (proto_tree
*)pi
;
4165 fi
->tree_type
= idx
;
4167 return (proto_tree
*)pi
;
4171 proto_item_get_subtree(const proto_item
*pi
) {
4176 fi
= PITEM_FINFO(pi
);
4177 if ( (!fi
) || (fi
->tree_type
== -1) )
4179 return (proto_tree
*)pi
;
4183 proto_item_get_parent(const proto_item
*ti
) {
4190 proto_item_get_parent_nth(proto_item
*ti
, int gen
) {
4203 proto_tree_get_parent(const proto_tree
*tree
) {
4206 return (proto_item
*)tree
;
4210 proto_tree_get_root(proto_tree
*tree
) {
4213 while (tree
->parent
) {
4214 tree
= tree
->parent
;
4220 proto_tree_move_item(proto_tree
*tree
, proto_item
*fixed_item
,
4221 proto_item
*item_to_move
)
4224 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4225 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4227 /* This function doesn't generate any values. It only reorganizes the prococol tree
4228 * so we can bail out immediately if it isn't visible. */
4229 if (!tree
|| !PTREE_DATA(tree
)->visible
)
4232 DISSECTOR_ASSERT(item_to_move
->parent
== tree
);
4233 DISSECTOR_ASSERT(fixed_item
->parent
== tree
);
4235 /*** cut item_to_move out ***/
4237 /* is item_to_move the first? */
4238 if (tree
->first_child
== item_to_move
) {
4239 /* simply change first child to next */
4240 tree
->first_child
= item_to_move
->next
;
4242 DISSECTOR_ASSERT(tree
->last_child
!= item_to_move
);
4244 proto_item
*curr_item
;
4245 /* find previous and change it's next */
4246 for(curr_item
= tree
->first_child
; curr_item
!= NULL
; curr_item
= curr_item
->next
) {
4247 if (curr_item
->next
== item_to_move
) {
4252 DISSECTOR_ASSERT(curr_item
);
4254 curr_item
->next
= item_to_move
->next
;
4256 /* fix last_child if required */
4257 if (tree
->last_child
== item_to_move
) {
4258 tree
->last_child
= curr_item
;
4262 /*** insert to_move after fixed ***/
4263 item_to_move
->next
= fixed_item
->next
;
4264 fixed_item
->next
= item_to_move
;
4265 if (tree
->last_child
== fixed_item
) {
4266 tree
->last_child
= item_to_move
;
4271 proto_tree_set_appendix(proto_tree
*tree
, tvbuff_t
*tvb
, gint start
,
4279 fi
= PTREE_FINFO(tree
);
4283 start
+= tvb_raw_offset(tvb
);
4284 DISSECTOR_ASSERT(start
>= 0);
4285 DISSECTOR_ASSERT(length
>= 0);
4287 fi
->appendix_start
= start
;
4288 fi
->appendix_length
= length
;
4292 proto_register_protocol(const char *name
, const char *short_name
,
4293 const char *filter_name
)
4295 protocol_t
*protocol
, *existing_protocol
= NULL
;
4296 header_field_info
*hfinfo
;
4298 char *existing_name
;
4302 gboolean found_invalid
;
4305 * Make sure there's not already a protocol with any of those
4306 * names. Crash if there is, as that's an error in the code
4307 * or an inappropriate plugin.
4308 * This situation has to be fixed to not register more than one
4309 * protocol with the same name.
4311 * This is done by reducing the number of strcmp (and alike) calls
4312 * as much as possible, as this significally slows down startup time.
4314 * Drawback: As a hash value is used to reduce insert time,
4315 * this might lead to a hash collision.
4316 * However, although we have somewhat over 1000 protocols, we're using
4317 * a 32 bit int so this is very, very unlikely.
4320 key
= (gint
*)g_malloc (sizeof(gint
));
4321 *key
= wrs_str_hash(name
);
4323 existing_name
= (char *)g_hash_table_lookup(proto_names
, key
);
4324 if (existing_name
!= NULL
) {
4325 /* g_error will terminate the program */
4326 g_error("Duplicate protocol name \"%s\"!"
4327 " This might be caused by an inappropriate plugin or a development error.", name
);
4329 g_hash_table_insert(proto_names
, key
, (gpointer
)name
);
4331 existing_name
= (char *)g_hash_table_lookup(proto_short_names
, (gpointer
)short_name
);
4332 if (existing_name
!= NULL
) {
4333 g_error("Duplicate protocol short_name \"%s\"!"
4334 " This might be caused by an inappropriate plugin or a development error.", short_name
);
4336 g_hash_table_insert(proto_short_names
, (gpointer
)short_name
, (gpointer
)short_name
);
4338 found_invalid
= FALSE
;
4339 for (i
= 0; filter_name
[i
]; i
++) {
4341 if (!(islower(c
) || isdigit(c
) || c
== '-' || c
== '_' || c
== '.')) {
4342 found_invalid
= TRUE
;
4345 if (found_invalid
) {
4346 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4347 " Allowed are lower characters, digits, '-', '_' and '.'."
4348 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
4350 existing_protocol
= (protocol_t
*)g_hash_table_lookup(proto_filter_names
, (gpointer
)filter_name
);
4351 if (existing_protocol
!= NULL
) {
4352 g_error("Duplicate protocol filter_name \"%s\"!"
4353 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
4356 /* Add this protocol to the list of known protocols; the list
4357 is sorted by protocol short name. */
4358 protocol
= g_new(protocol_t
, 1);
4359 protocol
->name
= name
;
4360 protocol
->short_name
= short_name
;
4361 protocol
->filter_name
= filter_name
;
4362 protocol
->fields
= NULL
;
4363 protocol
->is_enabled
= TRUE
; /* protocol is enabled by default */
4364 protocol
->can_toggle
= TRUE
;
4365 protocol
->is_private
= FALSE
;
4366 /* list will be sorted later by name, when all protocols completed registering */
4367 protocols
= g_list_prepend(protocols
, protocol
);
4368 g_hash_table_insert(proto_filter_names
, (gpointer
)filter_name
, protocol
);
4370 /* Here we allocate a new header_field_info struct */
4371 hfinfo
= g_slice_new(header_field_info
);
4372 hfinfo
->name
= name
;
4373 hfinfo
->abbrev
= filter_name
;
4374 hfinfo
->type
= FT_PROTOCOL
;
4375 hfinfo
->display
= BASE_NONE
;
4376 hfinfo
->strings
= protocol
;
4377 hfinfo
->bitmask
= 0;
4378 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
4379 hfinfo
->blurb
= NULL
;
4380 hfinfo
->parent
= -1; /* this field differentiates protos and fields */
4382 proto_id
= proto_register_field_init(hfinfo
, hfinfo
->parent
);
4383 protocol
->proto_id
= proto_id
;
4388 proto_mark_private(const int proto_id
)
4390 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
4392 protocol
->is_private
= TRUE
;
4396 proto_is_private(const int proto_id
)
4398 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
4400 return protocol
->is_private
;
4406 * Routines to use to iterate over the protocols.
4407 * The argument passed to the iterator routines is an opaque cookie to
4408 * their callers; it's the GList pointer for the current element in
4410 * The ID of the protocol is returned, or -1 if there is no protocol.
4413 proto_get_first_protocol(void **cookie
)
4415 protocol_t
*protocol
;
4417 if (protocols
== NULL
)
4419 *cookie
= protocols
;
4420 protocol
= (protocol_t
*)protocols
->data
;
4421 return protocol
->proto_id
;
4425 proto_get_data_protocol(void *cookie
)
4427 GList
*list_item
= (GList
*)cookie
;
4429 protocol_t
*protocol
= (protocol_t
*)list_item
->data
;
4430 return protocol
->proto_id
;
4434 proto_get_next_protocol(void **cookie
)
4436 GList
*list_item
= (GList
*)*cookie
;
4437 protocol_t
*protocol
;
4439 list_item
= g_list_next(list_item
);
4440 if (list_item
== NULL
)
4442 *cookie
= list_item
;
4443 protocol
= (protocol_t
*)list_item
->data
;
4444 return protocol
->proto_id
;
4448 proto_get_first_protocol_field(const int proto_id
, void **cookie
)
4450 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
4452 if ((protocol
== NULL
) || (protocol
->fields
== NULL
))
4455 *cookie
= protocol
->fields
;
4456 return (header_field_info
*)protocol
->fields
->data
;
4460 proto_get_next_protocol_field(void **cookie
)
4462 GSList
*list_item
= (GSList
*)*cookie
;
4464 list_item
= g_slist_next(list_item
);
4465 if (list_item
== NULL
)
4468 *cookie
= list_item
;
4469 return (header_field_info
*)list_item
->data
;
4473 find_protocol_by_id(const int proto_id
)
4475 header_field_info
*hfinfo
;
4480 PROTO_REGISTRAR_GET_NTH(proto_id
, hfinfo
);
4481 DISSECTOR_ASSERT(hfinfo
->type
== FT_PROTOCOL
);
4482 return (protocol_t
*)hfinfo
->strings
;
4486 proto_get_id(const protocol_t
*protocol
)
4488 return protocol
->proto_id
;
4491 int proto_get_id_by_filter_name(const gchar
* filter_name
)
4493 protocol_t
*protocol
= NULL
;
4496 fprintf(stderr
, "No filter name present");
4497 DISSECTOR_ASSERT(filter_name
);
4500 protocol
= (protocol_t
*)g_hash_table_lookup(proto_filter_names
, (gpointer
)filter_name
);
4502 if (protocol
== NULL
)
4504 return protocol
->proto_id
;
4508 proto_get_protocol_name(const int proto_id
)
4510 protocol_t
*protocol
;
4512 protocol
= find_protocol_by_id(proto_id
);
4514 if (protocol
== NULL
)
4516 return protocol
->name
;
4520 proto_get_protocol_short_name(const protocol_t
*protocol
)
4522 if (protocol
== NULL
)
4524 return protocol
->short_name
;
4528 proto_get_protocol_long_name(const protocol_t
*protocol
)
4530 if (protocol
== NULL
)
4532 return protocol
->name
;
4536 proto_get_protocol_filter_name(const int proto_id
)
4538 protocol_t
*protocol
;
4540 protocol
= find_protocol_by_id(proto_id
);
4541 if (protocol
== NULL
)
4543 return protocol
->filter_name
;
4547 proto_is_protocol_enabled(const protocol_t
*protocol
)
4549 return protocol
->is_enabled
;
4553 proto_can_toggle_protocol(const int proto_id
)
4555 protocol_t
*protocol
;
4557 protocol
= find_protocol_by_id(proto_id
);
4558 return protocol
->can_toggle
;
4562 proto_set_decoding(const int proto_id
, const gboolean enabled
)
4564 protocol_t
*protocol
;
4566 protocol
= find_protocol_by_id(proto_id
);
4567 DISSECTOR_ASSERT(protocol
->can_toggle
);
4568 protocol
->is_enabled
= enabled
;
4572 proto_enable_all(void)
4574 protocol_t
*protocol
;
4575 GList
*list_item
= protocols
;
4577 if (protocols
== NULL
)
4581 protocol
= (protocol_t
*)list_item
->data
;
4582 if (protocol
->can_toggle
)
4583 protocol
->is_enabled
= TRUE
;
4584 list_item
= g_list_next(list_item
);
4589 proto_set_cant_toggle(const int proto_id
)
4591 protocol_t
*protocol
;
4593 protocol
= find_protocol_by_id(proto_id
);
4594 protocol
->can_toggle
= FALSE
;
4598 proto_register_field_common(protocol_t
*proto
, header_field_info
*hfi
, const int parent
)
4600 if (proto
!= NULL
) {
4601 if (proto
->fields
== NULL
) {
4602 proto
->fields
= g_slist_append(NULL
, hfi
);
4603 proto
->last_field
= proto
->fields
;
4606 g_slist_append(proto
->last_field
, hfi
)->next
;
4610 return proto_register_field_init(hfi
, parent
);
4613 /* for use with static arrays only, since we don't allocate our own copies
4614 of the header_field_info struct contained within the hf_register_info struct */
4616 proto_register_field_array(const int parent
, hf_register_info
*hf
, const int num_records
)
4618 hf_register_info
*ptr
= hf
;
4622 proto
= find_protocol_by_id(parent
);
4623 for (i
= 0; i
< num_records
; i
++, ptr
++) {
4625 * Make sure we haven't registered this yet.
4626 * Most fields have variables associated with them
4627 * that are initialized to -1; some have array elements,
4628 * or possibly uninitialized variables, so we also allow
4629 * 0 (which is unlikely to be the field ID we get back
4630 * from "proto_register_field_init()").
4632 if (*ptr
->p_id
!= -1 && *ptr
->p_id
!= 0) {
4634 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4635 ptr
->hfinfo
.abbrev
);
4639 *ptr
->p_id
= proto_register_field_common(proto
, &ptr
->hfinfo
, parent
);
4644 proto_register_fields_section(const int parent
, header_field_info
*hfi
, const int num_records
)
4649 proto
= find_protocol_by_id(parent
);
4650 for (i
= 0; i
< num_records
; i
++) {
4652 * Make sure we haven't registered this yet.
4654 if (hfi
[i
].id
!= -1) {
4656 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4661 proto_register_field_common(proto
, &hfi
[i
], parent
);
4666 proto_register_fields_manual(const int parent
, header_field_info
**hfi
, const int num_records
)
4671 proto
= find_protocol_by_id(parent
);
4672 for (i
= 0; i
< num_records
; i
++) {
4674 * Make sure we haven't registered this yet.
4676 if (hfi
[i
]->id
!= -1) {
4678 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4683 proto_register_field_common(proto
, hfi
[i
], parent
);
4687 /* unregister already registered fields */
4689 proto_unregister_field (const int parent
, gint hf_id
)
4691 hf_register_info
*hf
;
4695 if (hf_id
== -1 || hf_id
== 0)
4698 proto
= find_protocol_by_id (parent
);
4699 if (!proto
|| !proto
->fields
) {
4703 for (field
= proto
->fields
; field
; field
= field
->next
) {
4704 hf
= (hf_register_info
*)field
->data
;
4705 if (*hf
->p_id
== hf_id
) {
4706 /* Found the hf_id in this protocol */
4707 g_tree_steal (gpa_name_tree
, hf
->hfinfo
.abbrev
);
4708 /* XXX, memleak? g_slist_delete_link() */
4709 proto
->fields
= g_slist_remove_link (proto
->fields
, field
);
4710 proto
->last_field
= g_slist_last (proto
->fields
);
4716 /* chars allowed in field abbrev */
4718 const guchar fld_abbrev_chars
[256] = {
4719 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4722 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4723 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4724 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4725 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4726 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4727 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4728 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4729 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4730 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4731 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4732 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4733 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4734 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4737 static const value_string hf_types
[] = {
4738 { FT_NONE
, "FT_NONE" },
4739 { FT_PROTOCOL
, "FT_PROTOCOL" },
4740 { FT_BOOLEAN
, "FT_BOOLEAN" },
4741 { FT_UINT8
, "FT_UINT8" },
4742 { FT_UINT16
, "FT_UINT16" },
4743 { FT_UINT24
, "FT_UINT24" },
4744 { FT_UINT32
, "FT_UINT32" },
4745 { FT_UINT64
, "FT_UINT64" },
4746 { FT_INT8
, "FT_INT8" },
4747 { FT_INT16
, "FT_INT16" },
4748 { FT_INT24
, "FT_INT24" },
4749 { FT_INT32
, "FT_INT32" },
4750 { FT_INT64
, "FT_INT64" },
4751 { FT_EUI64
, "FT_EUI64" },
4752 { FT_FLOAT
, "FT_FLOAT" },
4753 { FT_DOUBLE
, "FT_DOUBLE" },
4754 { FT_ABSOLUTE_TIME
, "FT_ABSOLUTE_TIME" },
4755 { FT_RELATIVE_TIME
, "FT_RELATIVE_TIME" },
4756 { FT_STRING
, "FT_STRING" },
4757 { FT_STRINGZ
, "FT_STRINGZ" },
4758 { FT_UINT_STRING
, "FT_UINT_STRING" },
4759 { FT_ETHER
, "FT_ETHER" },
4760 { FT_BYTES
, "FT_BYTES" },
4761 { FT_UINT_BYTES
, "FT_UINT_BYTES" },
4762 { FT_IPv4
, "FT_IPv4" },
4763 { FT_IPv6
, "FT_IPv6" },
4764 { FT_IPXNET
, "FT_IPXNET" },
4765 { FT_FRAMENUM
, "FT_FRAMENUM" },
4766 { FT_PCRE
, "FT_PCR" },
4767 { FT_GUID
, "FT_GUID" },
4768 { FT_OID
, "FT_OID" },
4769 { FT_REL_OID
, "FT_REL_OID" },
4772 static const value_string hf_display
[] = {
4773 { BASE_NONE
, "BASE_NONE" },
4774 { BASE_DEC
, "BASE_DEC" },
4775 { BASE_HEX
, "BASE_HEX" },
4776 { BASE_OCT
, "BASE_OCT" },
4777 { BASE_DEC_HEX
, "BASE_DEC_HEX" },
4778 { BASE_HEX_DEC
, "BASE_HEX_DEC" },
4779 { BASE_CUSTOM
, "BASE_CUSTOM" },
4780 { BASE_NONE
|BASE_RANGE_STRING
, "BASE_NONE|BASE_RANGE_STRING" },
4781 { BASE_DEC
|BASE_RANGE_STRING
, "BASE_DEC|BASE_RANGE_STRING" },
4782 { BASE_HEX
|BASE_RANGE_STRING
, "BASE_HEX|BASE_RANGE_STRING" },
4783 { BASE_OCT
|BASE_RANGE_STRING
, "BASE_OCT|BASE_RANGE_STRING" },
4784 { BASE_DEC_HEX
|BASE_RANGE_STRING
, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4785 { BASE_HEX_DEC
|BASE_RANGE_STRING
, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4786 { BASE_CUSTOM
|BASE_RANGE_STRING
, "BASE_CUSTOM|BASE_RANGE_STRING" },
4787 { BASE_NONE
|BASE_VAL64_STRING
, "BASE_NONE|BASE_VAL64_STRING" },
4788 { BASE_DEC
|BASE_VAL64_STRING
, "BASE_DEC|BASE_VAL64_STRING" },
4789 { BASE_HEX
|BASE_VAL64_STRING
, "BASE_HEX|BASE_VAL64_STRING" },
4790 { BASE_OCT
|BASE_VAL64_STRING
, "BASE_OCT|BASE_VAL64_STRING" },
4791 { BASE_DEC_HEX
|BASE_VAL64_STRING
, "BASE_DEC_HEX|BASE_VAL64_STRING" },
4792 { BASE_HEX_DEC
|BASE_VAL64_STRING
, "BASE_HEX_DEC|BASE_VAL64_STRING" },
4793 { BASE_CUSTOM
|BASE_VAL64_STRING
, "BASE_CUSTOM|BASE_VAL64_STRING" },
4794 { ABSOLUTE_TIME_LOCAL
, "ABSOLUTE_TIME_LOCAL" },
4795 { ABSOLUTE_TIME_UTC
, "ABSOLUTE_TIME_UTC" },
4796 { ABSOLUTE_TIME_DOY_UTC
, "ABSOLUTE_TIME_DOY_UTC" },
4799 /* temporary function containing assert part for easier profiling */
4801 tmp_fld_check_assert(header_field_info
*hfinfo
)
4804 /* The field must have a name (with length > 0) */
4805 if (!hfinfo
->name
|| !hfinfo
->name
[0]) {
4807 /* Try to identify the field */
4808 g_error("Field (abbrev='%s') does not have a name\n",
4812 g_error("Field does not have a name (nor an abbreviation)\n");
4815 /* fields with an empty string for an abbreviation aren't filterable */
4816 if (!hfinfo
->abbrev
|| !hfinfo
->abbrev
[0])
4817 g_error("Field '%s' does not have an abbreviation\n", hfinfo
->name
);
4819 /* These types of fields are allowed to have value_strings,
4820 * true_false_strings or a protocol_t struct
4822 if (hfinfo
->strings
!= NULL
&& !(
4823 (hfinfo
->type
== FT_UINT8
) ||
4824 (hfinfo
->type
== FT_UINT16
) ||
4825 (hfinfo
->type
== FT_UINT24
) ||
4826 (hfinfo
->type
== FT_UINT32
) ||
4827 (hfinfo
->type
== FT_UINT64
) ||
4828 (hfinfo
->type
== FT_INT8
) ||
4829 (hfinfo
->type
== FT_INT16
) ||
4830 (hfinfo
->type
== FT_INT24
) ||
4831 (hfinfo
->type
== FT_INT32
) ||
4832 (hfinfo
->type
== FT_INT64
) ||
4833 (hfinfo
->type
== FT_BOOLEAN
) ||
4834 (hfinfo
->type
== FT_PROTOCOL
) ))
4835 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4836 " (which is not allowed to have strings)\n",
4837 hfinfo
->name
, hfinfo
->abbrev
,
4838 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"));
4840 /* TODO: This check may slow down startup, and output quite a few warnings.
4841 It would be good to be able to enable this (and possibly other checks?)
4842 in non-release builds. */
4844 /* Check for duplicate value_string values.
4845 There are lots that have the same value *and* string, so for now only
4846 report those that have same value but different string. */
4847 if ((hfinfo
->strings
!= NULL
) &&
4848 !(hfinfo
->display
& BASE_RANGE_STRING
) &&
4849 !((hfinfo
->display
& BASE_DISPLAY_E_MASK
) == BASE_CUSTOM
) &&
4851 (hfinfo
->type
== FT_UINT8
) ||
4852 (hfinfo
->type
== FT_UINT16
) ||
4853 (hfinfo
->type
== FT_UINT24
) ||
4854 (hfinfo
->type
== FT_UINT32
) ||
4855 (hfinfo
->type
== FT_INT8
) ||
4856 (hfinfo
->type
== FT_INT16
) ||
4857 (hfinfo
->type
== FT_INT24
) ||
4858 (hfinfo
->type
== FT_INT32
) ||
4859 (hfinfo
->type
== FT_FRAMENUM
) )) {
4862 const value_string
*start_values
;
4863 const value_string
*current
;
4865 if (hfinfo
->display
& BASE_EXT_STRING
)
4866 start_values
= VALUE_STRING_EXT_VS_P(((const value_string_ext
*)hfinfo
->strings
));
4868 start_values
= (const value_string
*)hfinfo
->strings
;
4869 current
= start_values
;
4871 for (n
=0; current
; n
++, current
++) {
4872 /* Drop out if we reached the end. */
4873 if ((current
->value
== 0) && (current
->strptr
== NULL
)) {
4877 /* Check value against all previous */
4878 for (m
=0; m
< n
; m
++) {
4879 /* There are lots of duplicates with the same string,
4880 so only report if different... */
4881 if ((start_values
[m
].value
== current
->value
) &&
4882 (strcmp(start_values
[m
].strptr
, current
->strptr
) != 0)) {
4883 g_warning("Field '%s' (%s) has a conflicting entry in its"
4884 " value_string: %u is at indices %u (%s) and %u (%s))\n",
4885 hfinfo
->name
, hfinfo
->abbrev
,
4886 current
->value
, m
, start_values
[m
].strptr
, n
, current
->strptr
);
4894 switch (hfinfo
->type
) {
4901 /* Hexadecimal and octal are, in printf() and everywhere
4902 * else, unsigned so don't allow dissectors to register a
4903 * signed field to be displayed unsigned. (Else how would
4904 * we display negative values?)
4906 switch (hfinfo
->display
& BASE_DISPLAY_E_MASK
) {
4911 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
4912 hfinfo
->name
, hfinfo
->abbrev
,
4913 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"),
4914 val_to_str(hfinfo
->display
, hf_display
, "(Bit count: %d)"));
4922 /* Require integral types (other than frame number,
4923 * which is always displayed in decimal) to have a
4925 * If there is a strings value then this base is not
4926 * normally used except when constructing a display
4927 * filter for a value not found in the strings lookup.
4929 switch (hfinfo
->display
& BASE_DISPLAY_E_MASK
) {
4935 case BASE_CUSTOM
: /* hfinfo_numeric_value_format() treats this as decimal */
4938 g_error("Field '%s' (%s) is an integral value (%s)"
4939 " but is being displayed as %s\n",
4940 hfinfo
->name
, hfinfo
->abbrev
,
4941 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"),
4942 val_to_str(hfinfo
->display
, hf_display
, "(Unknown: 0x%x)"));
4948 if (hfinfo
->display
!= BASE_NONE
)
4949 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4950 hfinfo
->name
, hfinfo
->abbrev
,
4951 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"),
4952 val_to_str(hfinfo
->display
, hf_display
, "(Bit count: %d)"));
4953 if (hfinfo
->bitmask
!= 0)
4954 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4955 hfinfo
->name
, hfinfo
->abbrev
,
4956 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"));
4962 case FT_ABSOLUTE_TIME
:
4963 if (!(hfinfo
->display
== ABSOLUTE_TIME_LOCAL
||
4964 hfinfo
->display
== ABSOLUTE_TIME_UTC
||
4965 hfinfo
->display
== ABSOLUTE_TIME_DOY_UTC
))
4966 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
4967 hfinfo
->name
, hfinfo
->abbrev
,
4968 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"),
4969 val_to_str(hfinfo
->display
, hf_display
, "(Bit count: %d)"));
4970 if (hfinfo
->bitmask
!= 0)
4971 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4972 hfinfo
->name
, hfinfo
->abbrev
,
4973 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"));
4977 if (hfinfo
->display
!= BASE_NONE
)
4978 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
4979 hfinfo
->name
, hfinfo
->abbrev
,
4980 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"),
4981 val_to_str(hfinfo
->display
, hf_display
, "(Bit count: %d)"));
4982 if (hfinfo
->bitmask
!= 0)
4983 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
4984 hfinfo
->name
, hfinfo
->abbrev
,
4985 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"));
4986 if (hfinfo
->strings
!= NULL
)
4987 g_error("Field '%s' (%s) is an %s but has a strings value\n",
4988 hfinfo
->name
, hfinfo
->abbrev
,
4989 val_to_str(hfinfo
->type
, hf_types
, "(Unknown: %d)"));
4995 register_type_length_mismatch(void)
4997 static ei_register_info ei
[] = {
4998 { &ei_type_length_mismatch_error
, { "_ws.type_length.mismatch", PI_MALFORMED
, PI_ERROR
, "Trying to fetch X with length Y", EXPFILL
}},
4999 { &ei_type_length_mismatch_warn
, { "_ws.type_length.mismatch", PI_MALFORMED
, PI_WARN
, "Trying to fetch X with length Y", EXPFILL
}},
5002 expert_module_t
* expert_type_length_mismatch
;
5004 proto_type_length_mismatch
= proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
5006 expert_type_length_mismatch
= expert_register_protocol(proto_type_length_mismatch
);
5007 expert_register_field_array(expert_type_length_mismatch
, ei
, array_length(ei
));
5009 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
5010 disabling them makes no sense. */
5011 proto_set_cant_toggle(proto_type_length_mismatch
);
5014 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (144000+PRE_ALLOC_EXPERT_FIELDS_MEM)
5016 proto_register_field_init(header_field_info
*hfinfo
, const int parent
)
5019 tmp_fld_check_assert(hfinfo
);
5021 hfinfo
->parent
= parent
;
5022 hfinfo
->same_name_next
= NULL
;
5023 hfinfo
->same_name_prev_id
= -1;
5025 /* if we always add and never delete, then id == len - 1 is correct */
5026 if (gpa_hfinfo
.len
>= gpa_hfinfo
.allocated_len
) {
5027 if (!gpa_hfinfo
.hfi
) {
5028 gpa_hfinfo
.allocated_len
= PROTO_PRE_ALLOC_HF_FIELDS_MEM
;
5029 gpa_hfinfo
.hfi
= (header_field_info
**)g_malloc(sizeof(header_field_info
*)*PROTO_PRE_ALLOC_HF_FIELDS_MEM
);
5031 gpa_hfinfo
.allocated_len
+= 1000;
5032 gpa_hfinfo
.hfi
= (header_field_info
**)g_realloc(gpa_hfinfo
.hfi
,
5033 sizeof(header_field_info
*)*gpa_hfinfo
.allocated_len
);
5034 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5037 gpa_hfinfo
.hfi
[gpa_hfinfo
.len
] = hfinfo
;
5039 hfinfo
->id
= gpa_hfinfo
.len
- 1;
5041 /* if we have real names, enter this field in the name tree */
5042 if ((hfinfo
->name
[0] != 0) && (hfinfo
->abbrev
[0] != 0 )) {
5044 header_field_info
*same_name_next_hfinfo
;
5047 /* Check that the filter name (abbreviation) is legal;
5048 * it must contain only alphanumerics, '-', "_", and ".". */
5049 c
= wrs_check_charset(fld_abbrev_chars
, hfinfo
->abbrev
);
5051 fprintf(stderr
, "Invalid character '%c' in filter name '%s'\n", c
, hfinfo
->abbrev
);
5052 DISSECTOR_ASSERT(!c
);
5055 /* We allow multiple hfinfo's to be registered under the same
5056 * abbreviation. This was done for X.25, as, depending
5057 * on whether it's modulo-8 or modulo-128 operation,
5058 * some bitfield fields may be in different bits of
5059 * a byte, and we want to be able to refer to that field
5060 * with one name regardless of whether the packets
5061 * are modulo-8 or modulo-128 packets. */
5063 same_name_hfinfo
= NULL
;
5065 g_tree_insert(gpa_name_tree
, (gpointer
) (hfinfo
->abbrev
), hfinfo
);
5066 /* GLIB 2.x - if it is already present
5067 * the previous hfinfo with the same name is saved
5068 * to same_name_hfinfo by value destroy callback */
5069 if (same_name_hfinfo
) {
5070 /* There's already a field with this name.
5071 * Put it after that field in the list of
5072 * fields with this name, then allow the code
5073 * after this if{} block to replace the old
5074 * hfinfo with the new hfinfo in the GTree. Thus,
5075 * we end up with a linked-list of same-named hfinfo's,
5076 * with the root of the list being the hfinfo in the GTree */
5077 same_name_next_hfinfo
=
5078 same_name_hfinfo
->same_name_next
;
5080 hfinfo
->same_name_next
= same_name_next_hfinfo
;
5081 if (same_name_next_hfinfo
)
5082 same_name_next_hfinfo
->same_name_prev_id
= hfinfo
->id
;
5084 same_name_hfinfo
->same_name_next
= hfinfo
;
5085 hfinfo
->same_name_prev_id
= same_name_hfinfo
->id
;
5093 proto_register_subtree_array(gint
*const *indices
, const int num_indices
)
5096 gint
*const *ptr
= indices
;
5099 * If we've already allocated the array of tree types, expand
5100 * it; this lets plugins such as mate add tree types after
5101 * the initial startup. (If we haven't already allocated it,
5102 * we don't allocate it; on the first pass, we just assign
5103 * ett values and keep track of how many we've assigned, and
5104 * when we're finished registering all dissectors we allocate
5105 * the array, so that we do only one allocation rather than
5106 * wasting CPU time and memory by growing the array for each
5107 * dissector that registers ett values.)
5109 if (tree_is_expanded
!= NULL
) {
5110 tree_is_expanded
= (guint32
*)g_realloc(tree_is_expanded
, (1+((num_tree_types
+ num_indices
)/32)) * sizeof(guint32
));
5112 /* set new items to 0 */
5113 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5114 for (i
= num_tree_types
; i
< num_tree_types
+ num_indices
; i
++)
5115 tree_is_expanded
[i
>> 5] &= ~(1 << (i
& 31));
5119 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5120 * returning the indices through the pointers in the array whose
5121 * first element is pointed to by "indices", and update
5122 * "num_tree_types" appropriately.
5124 for (i
= 0; i
< num_indices
; i
++, ptr
++, num_tree_types
++) {
5126 /* g_error will terminate the program */
5127 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5128 " This is a development error:"
5129 " Either the subtree item type has already been assigned or"
5130 " was not initialized to -1.");
5132 **ptr
= num_tree_types
;
5137 label_concat(char *label_str
, gsize pos
, const char *str
)
5139 if (pos
< ITEM_LABEL_LENGTH
)
5140 pos
+= g_strlcpy(label_str
+ pos
, str
, ITEM_LABEL_LENGTH
- pos
);
5146 label_mark_truncated(char *label_str
, gsize name_pos
)
5148 static const char trunc_str
[] = " [truncated]";
5149 const size_t trunc_len
= sizeof(trunc_str
)-1;
5151 /* ..... field_name: dataaaaaaaaaaaaa
5155 * ..... field_name [truncated]: dataaaaaaaaaaaaa */
5157 if (name_pos
< ITEM_LABEL_LENGTH
- trunc_len
) {
5158 memmove(label_str
+ name_pos
+ trunc_len
, label_str
+ name_pos
, ITEM_LABEL_LENGTH
- name_pos
- trunc_len
);
5159 memcpy(label_str
+ name_pos
, trunc_str
, trunc_len
);
5160 label_str
[ITEM_LABEL_LENGTH
-1] = '\0';
5162 } else if (name_pos
< ITEM_LABEL_LENGTH
)
5163 g_strlcpy(label_str
+ name_pos
, trunc_str
, ITEM_LABEL_LENGTH
- name_pos
);
5167 label_fill(char *label_str
, gsize pos
, const header_field_info
*hfinfo
, const char *text
)
5171 /* "%s: %s", hfinfo->name, text */
5172 name_pos
= pos
= label_concat(label_str
, pos
, hfinfo
->name
);
5173 pos
= label_concat(label_str
, pos
, ": ");
5174 pos
= label_concat(label_str
, pos
, text
? text
: "(null)");
5176 if (pos
>= ITEM_LABEL_LENGTH
) {
5177 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5178 label_mark_truncated(label_str
, name_pos
);
5185 label_fill_descr(char *label_str
, gsize pos
, const header_field_info
*hfinfo
, const char *text
, const char *descr
)
5189 /* "%s: %s (%s)", hfinfo->name, text, descr */
5190 name_pos
= pos
= label_concat(label_str
, pos
, hfinfo
->name
);
5191 pos
= label_concat(label_str
, pos
, ": ");
5192 pos
= label_concat(label_str
, pos
, text
? text
: "(null)");
5193 pos
= label_concat(label_str
, pos
, " (");
5194 pos
= label_concat(label_str
, pos
, descr
? descr
: "(null)");
5195 pos
= label_concat(label_str
, pos
, ")");
5197 if (pos
>= ITEM_LABEL_LENGTH
) {
5198 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5199 label_mark_truncated(label_str
, name_pos
);
5206 proto_item_fill_label(field_info
*fi
, gchar
*label_str
)
5208 header_field_info
*hfinfo
;
5214 guint32 n_addr
; /* network-order IPv4 address */
5221 /* XXX: Check validity of hfinfo->type */
5225 hfinfo
= fi
->hfinfo
;
5227 switch (hfinfo
->type
) {
5230 g_strlcpy(label_str
, hfinfo
->name
, ITEM_LABEL_LENGTH
);
5234 fill_label_boolean(fi
, label_str
);
5239 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5240 label_fill(label_str
, 0, hfinfo
,
5241 (bytes
) ? bytes_to_str(bytes
, fvalue_length(&fi
->value
)) : "<MISSING>");
5244 /* Four types of integers to take care of:
5245 * Bitfield, with val_string
5246 * Bitfield, w/o val_string
5247 * Non-bitfield, with val_string
5248 * Non-bitfield, w/o val_string
5254 if (hfinfo
->bitmask
) {
5255 fill_label_bitfield(fi
, label_str
, FALSE
);
5257 fill_label_number(fi
, label_str
, FALSE
);
5262 fill_label_number(fi
, label_str
, FALSE
);
5266 fill_label_number64(fi
, label_str
, FALSE
);
5273 if (hfinfo
->bitmask
) {
5274 fill_label_bitfield(fi
, label_str
, TRUE
);
5276 fill_label_number(fi
, label_str
, TRUE
);
5281 fill_label_number64(fi
, label_str
, TRUE
);
5285 g_snprintf(label_str
, ITEM_LABEL_LENGTH
,
5286 "%s: %." G_STRINGIFY(FLT_DIG
) "g",
5287 hfinfo
->name
, fvalue_get_floating(&fi
->value
));
5291 g_snprintf(label_str
, ITEM_LABEL_LENGTH
,
5292 "%s: %." G_STRINGIFY(DBL_DIG
) "g",
5293 hfinfo
->name
, fvalue_get_floating(&fi
->value
));
5296 case FT_ABSOLUTE_TIME
:
5297 label_fill(label_str
, 0, hfinfo
,
5298 abs_time_to_str((const nstime_t
*)fvalue_get(&fi
->value
),
5299 (absolute_time_display_e
)hfinfo
->display
, TRUE
));
5302 case FT_RELATIVE_TIME
:
5303 g_snprintf(label_str
, ITEM_LABEL_LENGTH
,
5304 "%s: %s seconds", hfinfo
->name
,
5305 rel_time_to_secs_str((const nstime_t
*)fvalue_get(&fi
->value
)));
5309 integer
= fvalue_get_uinteger(&fi
->value
);
5310 g_snprintf(label_str
, ITEM_LABEL_LENGTH
,
5311 "%s: %s (0x%08X)", hfinfo
->name
,
5312 get_ipxnet_name(integer
), integer
);
5316 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5317 label_fill_descr(label_str
, 0, hfinfo
,
5318 get_ax25_name(bytes
),
5319 ax25_to_str(bytes
));
5323 addr
.type
= AT_VINES
;
5324 addr
.len
= VINES_ADDR_LEN
;
5325 addr
.data
= (guint8
*)fvalue_get(&fi
->value
);
5327 g_snprintf(label_str
, ITEM_LABEL_LENGTH
,
5328 "%s: %s", hfinfo
->name
,
5329 address_to_str( &addr
));
5333 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5334 label_fill_descr(label_str
, 0, hfinfo
,
5335 get_ether_name(bytes
),
5336 ether_to_str(bytes
));
5340 ipv4
= (ipv4_addr
*)fvalue_get(&fi
->value
);
5341 n_addr
= ipv4_get_net_order_addr(ipv4
);
5342 label_fill_descr(label_str
, 0, hfinfo
,
5343 get_hostname(n_addr
),
5344 ip_to_str((guint8
*)&n_addr
));
5348 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5349 label_fill_descr(label_str
, 0, hfinfo
,
5350 get_hostname6((struct e_in6_addr
*)bytes
),
5351 ip6_to_str((struct e_in6_addr
*)bytes
));
5355 guid
= (e_guid_t
*)fvalue_get(&fi
->value
);
5356 label_fill(label_str
, 0, hfinfo
, guid_to_str(guid
));
5360 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5361 name
= oid_resolved_from_encoded(bytes
, fvalue_length(&fi
->value
));
5363 label_fill_descr(label_str
, 0, hfinfo
,
5364 oid_encoded2string(bytes
, fvalue_length(&fi
->value
)), name
);
5366 label_fill(label_str
, 0, hfinfo
,
5367 oid_encoded2string(bytes
, fvalue_length(&fi
->value
)));
5372 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5373 name
= rel_oid_resolved_from_encoded(bytes
, fvalue_length(&fi
->value
));
5375 label_fill_descr(label_str
, 0, hfinfo
,
5376 rel_oid_encoded2string(bytes
, fvalue_length(&fi
->value
)), name
);
5378 label_fill(label_str
, 0, hfinfo
,
5379 rel_oid_encoded2string(bytes
, fvalue_length(&fi
->value
)));
5384 integer64
= fvalue_get_integer64(&fi
->value
);
5385 label_fill_descr(label_str
, 0, hfinfo
,
5386 get_eui64_name(integer64
),
5387 eui64_to_str(integer64
));
5391 case FT_UINT_STRING
:
5392 bytes
= (guint8
*)fvalue_get(&fi
->value
);
5393 label_fill(label_str
, 0, hfinfo
, format_text(bytes
, strlen(bytes
)));
5397 g_error("hfinfo->type %d (%s) not handled\n",
5398 hfinfo
->type
, ftype_name(hfinfo
->type
));
5399 DISSECTOR_ASSERT_NOT_REACHED();
5405 fill_label_boolean(field_info
*fi
, gchar
*label_str
)
5407 char *p
= label_str
;
5408 int bitfield_byte_length
= 0, bitwidth
;
5409 guint32 unshifted_value
;
5412 header_field_info
*hfinfo
= fi
->hfinfo
;
5413 const true_false_string
*tfstring
= (const true_false_string
*)&tfs_true_false
;
5415 if (hfinfo
->strings
) {
5416 tfstring
= (const struct true_false_string
*) hfinfo
->strings
;
5419 value
= fvalue_get_uinteger(&fi
->value
);
5420 if (hfinfo
->bitmask
) {
5421 /* Figure out the bit width */
5422 bitwidth
= hfinfo_bitwidth(hfinfo
);
5425 unshifted_value
= value
;
5426 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
5428 /* Create the bitfield first */
5429 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
5430 bitfield_byte_length
= (int) (p
- label_str
);
5433 /* Fill in the textual info */
5434 label_fill(label_str
, bitfield_byte_length
, hfinfo
, value
? tfstring
->true_string
: tfstring
->false_string
);
5438 hf_try_val_to_str(guint32 value
, const header_field_info
*hfinfo
)
5440 if (hfinfo
->display
& BASE_RANGE_STRING
)
5441 return try_rval_to_str(value
, (const range_string
*) hfinfo
->strings
);
5443 if (hfinfo
->display
& BASE_EXT_STRING
)
5444 return try_val_to_str_ext(value
, (const value_string_ext
*) hfinfo
->strings
);
5446 if (hfinfo
->display
& BASE_VAL64_STRING
)
5447 return try_val64_to_str(value
, (const val64_string
*) hfinfo
->strings
);
5449 return try_val_to_str(value
, (const value_string
*) hfinfo
->strings
);
5453 hf_try_val64_to_str(guint64 value
, const header_field_info
*hfinfo
)
5455 if (hfinfo
->display
& BASE_VAL64_STRING
)
5456 return try_val64_to_str(value
, (const val64_string
*) hfinfo
->strings
);
5458 /* If this is reached somebody registered a 64-bit field with a 32-bit
5459 * value-string, which isn't right. */
5460 DISSECTOR_ASSERT_NOT_REACHED();
5462 /* This is necessary to squelch MSVC errors; is there
5463 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
5469 hf_try_val_to_str_const(guint32 value
, const header_field_info
*hfinfo
, const char *unknown_str
)
5471 const char *str
= hf_try_val_to_str(value
, hfinfo
);
5473 return (str
) ? str
: unknown_str
;
5477 hf_try_val64_to_str_const(guint64 value
, const header_field_info
*hfinfo
, const char *unknown_str
)
5479 const char *str
= hf_try_val64_to_str(value
, hfinfo
);
5481 return (str
) ? str
: unknown_str
;
5484 /* Fills data for bitfield ints with val_strings */
5486 fill_label_bitfield(field_info
*fi
, gchar
*label_str
, gboolean is_signed
)
5489 int bitfield_byte_length
, bitwidth
;
5490 guint32 unshifted_value
;
5496 header_field_info
*hfinfo
= fi
->hfinfo
;
5498 /* Figure out the bit width */
5499 bitwidth
= hfinfo_bitwidth(hfinfo
);
5503 unshifted_value
= fvalue_get_sinteger(&fi
->value
);
5505 unshifted_value
= fvalue_get_uinteger(&fi
->value
);
5507 value
= unshifted_value
;
5508 if (hfinfo
->bitmask
) {
5509 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
5512 /* Create the bitfield first */
5513 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
5514 bitfield_byte_length
= (int) (p
- label_str
);
5516 /* Fill in the textual info using stored (shifted) value */
5517 if (hfinfo
->display
== BASE_CUSTOM
) {
5518 gchar tmp
[ITEM_LABEL_LENGTH
];
5519 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
5521 DISSECTOR_ASSERT(fmtfunc
);
5522 fmtfunc(tmp
, value
);
5523 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
);
5525 else if (hfinfo
->strings
) {
5526 const char *val_str
= hf_try_val_to_str_const(value
, hfinfo
, "Unknown");
5528 out
= hfinfo_number_vals_format(hfinfo
, buf
, value
);
5529 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
5530 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
);
5532 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
);
5535 out
= hfinfo_number_value_format(hfinfo
, buf
, value
);
5537 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
);
5542 fill_label_number(field_info
*fi
, gchar
*label_str
, gboolean is_signed
)
5544 header_field_info
*hfinfo
= fi
->hfinfo
;
5551 value
= fvalue_get_sinteger(&fi
->value
);
5553 value
= fvalue_get_uinteger(&fi
->value
);
5555 /* Fill in the textual info */
5556 if (hfinfo
->display
== BASE_CUSTOM
) {
5557 gchar tmp
[ITEM_LABEL_LENGTH
];
5558 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
5560 DISSECTOR_ASSERT(fmtfunc
);
5561 fmtfunc(tmp
, value
);
5562 label_fill(label_str
, 0, hfinfo
, tmp
);
5564 else if (hfinfo
->strings
) {
5565 const char *val_str
= hf_try_val_to_str_const(value
, hfinfo
, "Unknown");
5567 out
= hfinfo_number_vals_format(hfinfo
, buf
, value
);
5568 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
5569 label_fill(label_str
, 0, hfinfo
, val_str
);
5571 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
);
5574 out
= hfinfo_number_value_format(hfinfo
, buf
, value
);
5576 label_fill(label_str
, 0, hfinfo
, out
);
5581 fill_label_number64(field_info
*fi
, gchar
*label_str
, gboolean is_signed
)
5583 const char *format
= NULL
;
5584 header_field_info
*hfinfo
= fi
->hfinfo
;
5586 char tmp
[ITEM_LABEL_LENGTH
+1];
5588 /* Pick the proper format string */
5590 format
= hfinfo_int64_format(hfinfo
);
5592 format
= hfinfo_uint64_format(hfinfo
);
5594 value
= fvalue_get_integer64(&fi
->value
);
5596 /* Format the temporary string */
5597 if (IS_BASE_DUAL(hfinfo
->display
))
5598 g_snprintf(tmp
, ITEM_LABEL_LENGTH
, format
, value
, value
);
5600 g_snprintf(tmp
, ITEM_LABEL_LENGTH
, format
, value
);
5602 if (hfinfo
->strings
) {
5603 const char *val_str
= hf_try_val64_to_str_const(value
, hfinfo
, "Unknown");
5605 if ((hfinfo
->display
& BASE_DISPLAY_E_MASK
) == BASE_NONE
) {
5606 label_fill(label_str
, 0, hfinfo
, val_str
);
5609 label_fill_descr(label_str
, 0, hfinfo
, val_str
, tmp
);
5613 label_fill(label_str
, 0, hfinfo
, tmp
);
5618 hfinfo_bitshift(const header_field_info
*hfinfo
)
5620 return ws_ctz(hfinfo
->bitmask
);
5624 hfinfo_bitwidth(const header_field_info
*hfinfo
)
5628 if (!hfinfo
->bitmask
) {
5632 switch (hfinfo
->type
) {
5650 bitwidth
= hfinfo
->display
; /* hacky? :) */
5653 DISSECTOR_ASSERT_NOT_REACHED();
5660 _hfinfo_type_hex_octet(int type
)
5680 DISSECTOR_ASSERT_NOT_REACHED();
5687 hfinfo_number_value_format_display(const header_field_info
*hfinfo
, int display
, char buf
[32], guint32 value
)
5689 char *ptr
= &buf
[31];
5690 gboolean isint
= IS_FT_INT(hfinfo
->type
);
5693 /* Properly format value */
5696 return isint
? int_to_str_back(ptr
, (gint32
) value
) : uint_to_str_back(ptr
, value
);
5700 ptr
= hex_to_str_back(ptr
, _hfinfo_type_hex_octet(hfinfo
->type
), value
);
5703 ptr
= isint
? int_to_str_back(ptr
, (gint32
) value
) : uint_to_str_back(ptr
, value
);
5707 return oct_to_str_back(ptr
, value
);
5710 return hex_to_str_back(ptr
, _hfinfo_type_hex_octet(hfinfo
->type
), value
);
5714 ptr
= isint
? int_to_str_back(ptr
, (gint32
) value
) : uint_to_str_back(ptr
, value
);
5717 ptr
= hex_to_str_back(ptr
, _hfinfo_type_hex_octet(hfinfo
->type
), value
);
5721 DISSECTOR_ASSERT_NOT_REACHED();
5728 hfinfo_number_value_format(const header_field_info
*hfinfo
, char buf
[32], guint32 value
)
5730 int display
= hfinfo
->display
;
5732 if (hfinfo
->type
== FT_FRAMENUM
) {
5734 * Frame numbers are always displayed in decimal.
5739 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
5743 hfinfo_numeric_value_format(const header_field_info
*hfinfo
, char buf
[32], guint32 value
)
5745 /* Get the underlying BASE_ value */
5746 int display
= hfinfo
->display
& BASE_DISPLAY_E_MASK
;
5748 if (hfinfo
->type
== FT_FRAMENUM
) {
5750 * Frame numbers are always displayed in decimal.
5757 /* case BASE_DEC: */
5759 case BASE_OCT
: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5764 /* case BASE_HEX: */
5770 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
5774 hfinfo_number_vals_format(const header_field_info
*hfinfo
, char buf
[32], guint32 value
)
5776 /* Get the underlying BASE_ value */
5777 int display
= hfinfo
->display
& BASE_DISPLAY_E_MASK
;
5779 if (display
== BASE_NONE
)
5782 if (display
== BASE_DEC_HEX
)
5784 if (display
== BASE_HEX_DEC
)
5787 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
5791 hfinfo_uint64_format(const header_field_info
*hfinfo
)
5793 const char *format
= NULL
;
5795 /* Pick the proper format string */
5796 switch (hfinfo
->display
& BASE_DISPLAY_E_MASK
) {
5798 format
= "%" G_GINT64_MODIFIER
"u";
5801 format
= "%" G_GINT64_MODIFIER
"u (0x%016" G_GINT64_MODIFIER
"x)";
5803 case BASE_OCT
: /* I'm lazy */
5804 format
= "%#" G_GINT64_MODIFIER
"o";
5807 format
= "0x%016" G_GINT64_MODIFIER
"x";
5810 format
= "0x%016" G_GINT64_MODIFIER
"x (%" G_GINT64_MODIFIER
"u)";
5813 DISSECTOR_ASSERT_NOT_REACHED();
5820 hfinfo_int64_format(const header_field_info
*hfinfo
)
5822 const char *format
= NULL
;
5824 /* Pick the proper format string */
5825 switch (hfinfo
->display
& BASE_DISPLAY_E_MASK
) {
5827 format
= "%" G_GINT64_MODIFIER
"d";
5830 format
= "%" G_GINT64_MODIFIER
"d (0x%016" G_GINT64_MODIFIER
"x)";
5832 case BASE_OCT
: /* I'm lazy */
5833 format
= "%#" G_GINT64_MODIFIER
"o";
5836 format
= "0x%016" G_GINT64_MODIFIER
"x";
5839 format
= "0x%016" G_GINT64_MODIFIER
"x (%" G_GINT64_MODIFIER
"d)";
5842 DISSECTOR_ASSERT_NOT_REACHED();
5849 proto_registrar_n(void)
5851 return gpa_hfinfo
.len
;
5855 proto_registrar_get_name(const int n
)
5857 header_field_info
*hfinfo
;
5859 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
5860 return hfinfo
->name
;
5864 proto_registrar_get_abbrev(const int n
)
5866 header_field_info
*hfinfo
;
5868 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
5869 return hfinfo
->abbrev
;
5873 proto_registrar_get_ftype(const int n
)
5875 header_field_info
*hfinfo
;
5877 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
5878 return hfinfo
->type
;
5882 proto_registrar_get_parent(const int n
)
5884 header_field_info
*hfinfo
;
5886 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
5887 return hfinfo
->parent
;
5891 proto_registrar_is_protocol(const int n
)
5893 header_field_info
*hfinfo
;
5895 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
5896 return (hfinfo
->parent
== -1 ? TRUE
: FALSE
);
5899 /* Returns length of field in packet (not necessarily the length
5900 * in our internal representation, as in the case of IPv4).
5901 * 0 means undeterminable at time of registration
5902 * -1 means the field is not registered. */
5904 proto_registrar_get_length(const int n
)
5906 header_field_info
*hfinfo
;
5908 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
5909 return ftype_length(hfinfo
->type
);
5912 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
5913 * it exists anywhere, or FALSE if it exists nowhere. */
5915 proto_check_for_protocol_or_field(const proto_tree
* tree
, const int id
)
5917 GPtrArray
*ptrs
= proto_get_finfo_ptr_array(tree
, id
);
5922 else if (g_ptr_array_len(ptrs
) > 0) {
5930 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
5931 * This only works if the hfindex was "primed" before the dissection
5932 * took place, as we just pass back the already-created GPtrArray*.
5933 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
5936 proto_get_finfo_ptr_array(const proto_tree
*tree
, const int id
)
5941 if (PTREE_DATA(tree
)->interesting_hfids
!= NULL
)
5942 return (GPtrArray
*)g_hash_table_lookup(PTREE_DATA(tree
)->interesting_hfids
,
5943 GINT_TO_POINTER(id
));
5949 proto_tracking_interesting_fields(const proto_tree
*tree
)
5954 return (PTREE_DATA(tree
)->interesting_hfids
!= NULL
);
5957 /* Helper struct for proto_find_info() and proto_all_finfos() */
5963 /* Helper function for proto_find_info() */
5965 find_finfo(proto_node
*node
, gpointer data
)
5967 field_info
*fi
= PNODE_FINFO(node
);
5968 if (fi
&& fi
->hfinfo
) {
5969 if (fi
->hfinfo
->id
== ((ffdata_t
*)data
)->id
) {
5970 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
5974 /* Don't stop traversing. */
5978 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
5979 * This works on any proto_tree, primed or unprimed, but actually searches
5980 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
5981 * The caller does need to free the returned GPtrArray with
5982 * g_ptr_array_free(<array>, TRUE).
5985 proto_find_finfo(proto_tree
*tree
, const int id
)
5989 ffdata
.array
= g_ptr_array_new();
5992 proto_tree_traverse_pre_order(tree
, find_finfo
, &ffdata
);
5994 return ffdata
.array
;
5997 /* Helper function for proto_all_finfos() */
5999 every_finfo(proto_node
*node
, gpointer data
)
6001 field_info
*fi
= PNODE_FINFO(node
);
6002 if (fi
&& fi
->hfinfo
) {
6003 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
6006 /* Don't stop traversing. */
6010 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6012 proto_all_finfos(proto_tree
*tree
)
6016 ffdata
.array
= g_ptr_array_new();
6019 proto_tree_traverse_pre_order(tree
, every_finfo
, &ffdata
);
6021 return ffdata
.array
;
6032 check_for_offset(proto_node
*node
, const gpointer data
)
6034 field_info
*fi
= PNODE_FINFO(node
);
6035 offset_search_t
*offsearch
= (offset_search_t
*)data
;
6037 /* !fi == the top most container node which holds nothing */
6038 if (fi
&& !PROTO_ITEM_IS_HIDDEN(node
) && fi
->ds_tvb
&& offsearch
->tvb
== fi
->ds_tvb
) {
6039 if (offsearch
->offset
>= (guint
) fi
->start
&&
6040 offsearch
->offset
< (guint
) (fi
->start
+ fi
->length
)) {
6042 offsearch
->finfo
= fi
;
6043 return FALSE
; /* keep traversing */
6046 return FALSE
; /* keep traversing */
6049 /* Search a proto_tree backwards (from leaves to root) looking for the field
6050 * whose start/length occupies 'offset' */
6051 /* XXX - I couldn't find an easy way to search backwards, so I search
6052 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6053 * the one I want to return to the user. This algorithm is inefficient
6054 * and could be re-done, but I'd have to handle all the children and
6055 * siblings of each node myself. When I have more time I'll do that.
6058 proto_find_field_from_offset(proto_tree
*tree
, guint offset
, tvbuff_t
*tvb
)
6060 offset_search_t offsearch
;
6062 offsearch
.offset
= offset
;
6063 offsearch
.finfo
= NULL
;
6064 offsearch
.tvb
= tvb
;
6066 proto_tree_traverse_pre_order(tree
, check_for_offset
, &offsearch
);
6068 return offsearch
.finfo
;
6071 /* Dumps the protocols in the registration database to stdout. An independent
6072 * program can take this output and format it into nice tables or HTML or
6075 * There is one record per line. The fields are tab-delimited.
6077 * Field 1 = protocol name
6078 * Field 2 = protocol short name
6079 * Field 3 = protocol filter name
6082 proto_registrar_dump_protocols(void)
6084 protocol_t
*protocol
;
6086 void *cookie
= NULL
;
6089 i
= proto_get_first_protocol(&cookie
);
6091 protocol
= find_protocol_by_id(i
);
6092 printf("%s\t%s\t%s\n", protocol
->name
, protocol
->short_name
,
6093 protocol
->filter_name
);
6094 i
= proto_get_next_protocol(&cookie
);
6098 /* Dumps the value_strings, extended value string headers, range_strings
6099 * or true/false strings for fields that have them.
6100 * There is one record per line. Fields are tab-delimited.
6101 * There are four types of records: Value String, Extended Value String Header,
6102 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6103 * the type of record.
6105 * Note that a record will be generated only if the value_string,... is referenced
6106 * in a registered hfinfo entry.
6112 * Field 2 = Field abbreviation to which this value string corresponds
6113 * Field 3 = Integer value
6116 * Extended Value String Headers
6117 * -----------------------------
6119 * Field 2 = Field abbreviation to which this extended value string header corresponds
6120 * Field 3 = Extended Value String "Name"
6121 * Field 4 = Number of entries in the associated value_string array
6122 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6127 * Field 2 = Field abbreviation to which this range string corresponds
6128 * Field 3 = Integer value: lower bound
6129 * Field 4 = Integer value: upper bound
6132 * True/False Strings
6133 * ------------------
6135 * Field 2 = Field abbreviation to which this true/false string corresponds
6136 * Field 3 = True String
6137 * Field 4 = False String
6140 proto_registrar_dump_values(void)
6142 header_field_info
*hfinfo
;
6144 const value_string
*vals
;
6145 const val64_string
*vals64
;
6146 const range_string
*range
;
6147 const true_false_string
*tfs
;
6149 len
= gpa_hfinfo
.len
;
6150 for (i
= 0; i
< len
; i
++) {
6151 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
6153 if (hfinfo
->id
== hf_text_only
) {
6157 /* ignore protocols */
6158 if (proto_registrar_is_protocol(i
)) {
6161 /* process header fields */
6164 * If this field isn't at the head of the list of
6165 * fields with this name, skip this field - all
6166 * fields with the same name are really just versions
6167 * of the same field stored in different bits, and
6168 * should have the same type/radix/value list, and
6169 * just differ in their bit masks. (If a field isn't
6170 * a bitfield, but can be, say, 1 or 2 bytes long,
6171 * it can just be made FT_UINT16, meaning the
6172 * *maximum* length is 2 bytes, and be used
6175 if (hfinfo
->same_name_prev_id
!= -1)
6183 if (hfinfo
->strings
!= NULL
) {
6184 if ((hfinfo
->display
& BASE_DISPLAY_E_MASK
) != BASE_CUSTOM
&&
6185 (hfinfo
->type
== FT_UINT8
||
6186 hfinfo
->type
== FT_UINT16
||
6187 hfinfo
->type
== FT_UINT24
||
6188 hfinfo
->type
== FT_UINT32
||
6189 hfinfo
->type
== FT_UINT64
||
6190 hfinfo
->type
== FT_INT8
||
6191 hfinfo
->type
== FT_INT16
||
6192 hfinfo
->type
== FT_INT24
||
6193 hfinfo
->type
== FT_INT32
||
6194 hfinfo
->type
== FT_INT64
)) {
6196 if (hfinfo
->display
& BASE_RANGE_STRING
) {
6197 range
= (const range_string
*)hfinfo
->strings
;
6198 } else if (hfinfo
->display
& BASE_EXT_STRING
) {
6199 vals
= VALUE_STRING_EXT_VS_P((const value_string_ext
*)hfinfo
->strings
);
6200 } else if (hfinfo
->display
& BASE_VAL64_STRING
) {
6201 vals64
= (const val64_string
*)hfinfo
->strings
;
6203 vals
= (const value_string
*)hfinfo
->strings
;
6206 else if (hfinfo
->type
== FT_BOOLEAN
) {
6207 tfs
= (const struct true_false_string
*)hfinfo
->strings
;
6211 /* Print value strings? */
6213 if (hfinfo
->display
& BASE_EXT_STRING
) {
6214 const value_string_ext
*vse_p
= (const value_string_ext
*)hfinfo
->strings
;
6215 if (!value_string_ext_validate(vse_p
)) {
6216 g_warning("Invalid value_string_ext ptr for: %s", hfinfo
->abbrev
);
6219 try_val_to_str_ext(0, vse_p
); /* "prime" the extended value_string */
6220 printf("E\t%s\t%d\t%s\t%s\n",
6222 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p
),
6223 VALUE_STRING_EXT_VS_NAME(vse_p
),
6224 value_string_ext_match_type_str(vse_p
));
6227 while (vals
[vi
].strptr
) {
6228 /* Print in the proper base */
6229 if (hfinfo
->display
== BASE_HEX
) {
6230 printf("V\t%s\t0x%x\t%s\n",
6236 printf("V\t%s\t%u\t%s\n",
6246 while (vals64
[vi
].strptr
) {
6247 printf("V64\t%s\t%" G_GINT64_MODIFIER
"u\t%s\n",
6255 /* print range strings? */
6258 while (range
[vi
].strptr
) {
6259 /* Print in the proper base */
6260 if ((hfinfo
->display
& BASE_DISPLAY_E_MASK
) == BASE_HEX
) {
6261 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6263 range
[vi
].value_min
,
6264 range
[vi
].value_max
,
6268 printf("R\t%s\t%u\t%u\t%s\n",
6270 range
[vi
].value_min
,
6271 range
[vi
].value_max
,
6278 /* Print true/false strings? */
6280 printf("T\t%s\t%s\t%s\n", hfinfo
->abbrev
,
6281 tfs
->true_string
, tfs
->false_string
);
6287 /* Dumps the contents of the registration database to stdout. An independent
6288 * program can take this output and format it into nice tables or HTML or
6291 * There is one record per line. Each record is either a protocol or a header
6292 * field, differentiated by the first field. The fields are tab-delimited.
6297 * Field 2 = descriptive protocol name
6298 * Field 3 = protocol abbreviation
6303 * Field 2 = descriptive field name
6304 * Field 3 = field abbreviation
6305 * Field 4 = type ( textual representation of the the ftenum type )
6306 * Field 5 = parent protocol abbreviation
6307 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6308 * Field 7 = bitmask: format: hex: 0x....
6309 * Field 8 = blurb describing field
6312 proto_registrar_dump_fields(void)
6314 header_field_info
*hfinfo
, *parent_hfinfo
;
6316 const char *enum_name
;
6317 const char *base_name
;
6321 len
= gpa_hfinfo
.len
;
6322 for (i
= 0; i
< len
; i
++) {
6323 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
6326 * Skip the pseudo-field for "proto_tree_add_text()" since
6327 * we don't want it in the list of filterable fields.
6329 if (hfinfo
->id
== hf_text_only
)
6332 /* format for protocols */
6333 if (proto_registrar_is_protocol(i
)) {
6334 printf("P\t%s\t%s\n", hfinfo
->name
, hfinfo
->abbrev
);
6336 /* format for header fields */
6339 * If this field isn't at the head of the list of
6340 * fields with this name, skip this field - all
6341 * fields with the same name are really just versions
6342 * of the same field stored in different bits, and
6343 * should have the same type/radix/value list, and
6344 * just differ in their bit masks. (If a field isn't
6345 * a bitfield, but can be, say, 1 or 2 bytes long,
6346 * it can just be made FT_UINT16, meaning the
6347 * *maximum* length is 2 bytes, and be used
6350 if (hfinfo
->same_name_prev_id
!= -1)
6353 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
6355 enum_name
= ftype_name(hfinfo
->type
);
6358 if (hfinfo
->type
== FT_UINT8
||
6359 hfinfo
->type
== FT_UINT16
||
6360 hfinfo
->type
== FT_UINT24
||
6361 hfinfo
->type
== FT_UINT32
||
6362 hfinfo
->type
== FT_UINT64
||
6363 hfinfo
->type
== FT_INT8
||
6364 hfinfo
->type
== FT_INT16
||
6365 hfinfo
->type
== FT_INT24
||
6366 hfinfo
->type
== FT_INT32
||
6367 hfinfo
->type
== FT_INT64
) {
6369 switch (hfinfo
->display
& BASE_DISPLAY_E_MASK
) {
6371 base_name
= "BASE_NONE";
6374 base_name
= "BASE_DEC";
6377 base_name
= "BASE_HEX";
6380 base_name
= "BASE_OCT";
6383 base_name
= "BASE_DEC_HEX";
6386 base_name
= "BASE_HEX_DEC";
6389 base_name
= "BASE_CUSTOM";
6395 } else if (hfinfo
->type
== FT_BOOLEAN
) {
6396 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6397 g_snprintf(width
, sizeof(width
), "%d", hfinfo
->display
);
6401 blurb
= hfinfo
->blurb
;
6404 else if (strlen(blurb
) == 0)
6407 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
6408 hfinfo
->name
, hfinfo
->abbrev
, enum_name
,
6409 parent_hfinfo
->abbrev
, base_name
, hfinfo
->bitmask
, blurb
);
6414 /* Dumps field types and descriptive names to stdout. An independent
6415 * program can take this output and format it into nice tables or HTML or
6418 * There is one record per line. The fields are tab-delimited.
6420 * Field 1 = field type name, e.g. FT_UINT8
6421 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6424 proto_registrar_dump_ftypes(void)
6428 for (fte
= 0; fte
< FT_NUM_TYPES
; fte
++) {
6429 printf("%s\t%s\n", ftype_name((ftenum_t
)fte
), ftype_pretty_name((ftenum_t
)fte
));
6434 hfinfo_numeric_format(const header_field_info
*hfinfo
)
6436 const char *format
= NULL
;
6438 /* Get the underlying BASE_ value */
6439 switch (hfinfo
->display
& BASE_DISPLAY_E_MASK
) {
6442 case BASE_OCT
: /* I'm lazy */
6444 switch (hfinfo
->type
) {
6446 format
= "%s == %" G_GINT64_MODIFIER
"u";
6449 format
= "%s == %" G_GINT64_MODIFIER
"d";
6452 DISSECTOR_ASSERT_NOT_REACHED();
6458 switch (hfinfo
->type
) {
6461 format
= "%s == 0x%016" G_GINT64_MODIFIER
"x";
6464 DISSECTOR_ASSERT_NOT_REACHED();
6469 DISSECTOR_ASSERT_NOT_REACHED();
6475 /* This function indicates whether it's possible to construct a
6476 * "match selected" display filter string for the specified field,
6477 * returns an indication of whether it's possible, and, if it's
6478 * possible and "filter" is non-null, constructs the filter and
6479 * sets "*filter" to point to it.
6480 * You do not need to [g_]free() this string since it will be automatically
6481 * freed once the next packet is dissected.
6484 construct_match_selected_string(field_info
*finfo
, epan_dissect_t
*edt
,
6487 header_field_info
*hfinfo
;
6492 gint start
, length
, length_remaining
;
6494 gchar is_signed_num
= FALSE
;
6499 hfinfo
= finfo
->hfinfo
;
6500 DISSECTOR_ASSERT(hfinfo
);
6501 abbrev_len
= (int) strlen(hfinfo
->abbrev
);
6503 if (hfinfo
->strings
&& (hfinfo
->display
& BASE_DISPLAY_E_MASK
) == BASE_NONE
) {
6504 const gchar
*str
= NULL
;
6506 switch (hfinfo
->type
) {
6512 str
= hf_try_val_to_str(fvalue_get_sinteger(&finfo
->value
), hfinfo
);
6519 str
= hf_try_val_to_str(fvalue_get_uinteger(&finfo
->value
), hfinfo
);
6526 if (str
!= NULL
&& filter
!= NULL
) {
6527 *filter
= ep_strdup_printf("%s == \"%s\"", hfinfo
->abbrev
, str
);
6533 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6534 * functions for FT_UINT and FT_INT types, as we choose the base in
6535 * the string expression based on the display base of the field.
6537 * Note that the base does matter, as this is also used for
6538 * the protocolinfo tap.
6540 * It might be nice to use them in "proto_item_fill_label()"
6541 * as well, although, there, you'd have to deal with the base
6542 * *and* with resolved values for addresses.
6544 * Perhaps we need two different val_to_string routines, one
6545 * to generate items for display filters and one to generate
6546 * strings for display, and pass to both of them the
6547 * "display" and "strings" values in the header_field_info
6548 * structure for the field, so they can get the base and,
6549 * if the field is Boolean or an enumerated integer type,
6550 * the tables used to generate human-readable values.
6552 switch (hfinfo
->type
) {
6558 is_signed_num
= TRUE
;
6565 if (filter
!= NULL
) {
6572 number
= fvalue_get_sinteger(&finfo
->value
);
6574 number
= fvalue_get_uinteger(&finfo
->value
);
6576 out
= hfinfo_numeric_value_format(hfinfo
, buf
, number
);
6578 *filter
= ep_strdup_printf("%s == %s", hfinfo
->abbrev
, out
);
6584 if (filter
!= NULL
) {
6585 const char *format
= hfinfo_numeric_format(hfinfo
);
6587 *filter
= ep_strdup_printf(format
,
6589 fvalue_get_integer64(&finfo
->value
));
6595 *filter
= ep_strdup(finfo
->hfinfo
->abbrev
);
6600 * If the length is 0, just match the name of the
6603 * (Also check for negative values, just in case,
6604 * as we'll cast it to an unsigned value later.)
6606 length
= finfo
->length
;
6609 *filter
= ep_strdup(finfo
->hfinfo
->abbrev
);
6616 * This doesn't have a value, so we'd match
6617 * on the raw bytes at this address.
6619 * Should we be allowed to access to the raw bytes?
6620 * If "edt" is NULL, the answer is "no".
6626 * Is this field part of the raw frame tvbuff?
6627 * If not, we can't use "frame[N:M]" to match
6630 * XXX - should this be frame-relative, or
6631 * protocol-relative?
6633 * XXX - does this fallback for non-registered
6634 * fields even make sense?
6636 if (finfo
->ds_tvb
!= edt
->tvb
)
6637 return FALSE
; /* you lose */
6640 * Don't go past the end of that tvbuff.
6642 length_remaining
= tvb_length_remaining(finfo
->ds_tvb
, finfo
->start
);
6643 if (length
> length_remaining
)
6644 length
= length_remaining
;
6648 if (filter
!= NULL
) {
6649 start
= finfo
->start
;
6650 buf_len
= 32 + length
* 3;
6651 *filter
= (char *)ep_alloc0(buf_len
);
6654 ptr
+= g_snprintf(ptr
, (gulong
) (buf_len
-(ptr
-*filter
)),
6655 "frame[%d:%d] == ", finfo
->start
, length
);
6656 for (i
=0; i
<length
; i
++) {
6657 c
= tvb_get_guint8(finfo
->ds_tvb
, start
);
6660 ptr
+= g_snprintf(ptr
, (gulong
) (buf_len
-(ptr
-*filter
)), "%02x", c
);
6663 ptr
+= g_snprintf(ptr
, (gulong
) (buf_len
-(ptr
-*filter
)), ":%02x", c
);
6670 /* FT_PCRE never appears as a type for a registered field. It is
6671 * only used internally. */
6672 DISSECTOR_ASSERT_NOT_REACHED();
6675 /* By default, use the fvalue's "to_string_repr" method. */
6677 /* Figure out the string length needed.
6678 * The ft_repr length.
6679 * 4 bytes for " == ".
6680 * 1 byte for trailing NUL.
6682 if (filter
!= NULL
) {
6683 dfilter_len
= fvalue_string_repr_len(&finfo
->value
,
6685 dfilter_len
+= abbrev_len
+ 4 + 1;
6686 *filter
= (char *)ep_alloc0(dfilter_len
);
6688 /* Create the string */
6689 g_snprintf(*filter
, dfilter_len
, "%s == ",
6691 fvalue_to_string_repr(&finfo
->value
,
6693 &(*filter
)[abbrev_len
+ 4]);
6702 * Returns TRUE if we can do a "match selected" on the field, FALSE
6706 proto_can_match_selected(field_info
*finfo
, epan_dissect_t
*edt
)
6708 return construct_match_selected_string(finfo
, edt
, NULL
);
6711 /* This function attempts to construct a "match selected" display filter
6712 * string for the specified field; if it can do so, it returns a pointer
6713 * to the string, otherwise it returns NULL.
6715 * The string is allocated with packet lifetime scope.
6716 * You do not need to [g_]free() this string since it will be automatically
6717 * freed once the next packet is dissected.
6720 proto_construct_match_selected_string(field_info
*finfo
, epan_dissect_t
*edt
)
6724 if (!construct_match_selected_string(finfo
, edt
, &filter
))
6729 /* This function is common code for both proto_tree_add_bitmask() and
6730 * proto_tree_add_bitmask_text() functions.
6733 /* NOTE: to support code written when proto_tree_add_bitmask() and
6734 * proto_tree_add_bitmask_text took a
6735 * gboolean as its last argument, with FALSE meaning "big-endian"
6736 * and TRUE meaning "little-endian", we treat any non-zero value of
6737 * "encoding" as meaning "little-endian".
6740 proto_item_add_bitmask_tree(proto_item
*item
, tvbuff_t
*tvb
, const int offset
,
6741 const int len
, const gint ett
, const int **fields
,
6742 const guint encoding
, const int flags
,
6746 guint32 available_bits
= 0;
6748 proto_tree
*tree
= NULL
;
6749 header_field_info
*hf
;
6753 value
= tvb_get_guint8(tvb
, offset
);
6754 available_bits
= 0xFF;
6757 value
= encoding
? tvb_get_letohs(tvb
, offset
) :
6758 tvb_get_ntohs(tvb
, offset
);
6759 available_bits
= 0xFFFF;
6762 value
= encoding
? tvb_get_letoh24(tvb
, offset
) :
6763 tvb_get_ntoh24(tvb
, offset
);
6764 available_bits
= 0xFFFFFF;
6767 value
= encoding
? tvb_get_letohl(tvb
, offset
) :
6768 tvb_get_ntohl(tvb
, offset
);
6769 available_bits
= 0xFFFFFFFF;
6772 g_assert_not_reached();
6775 tree
= proto_item_add_subtree(item
, ett
);
6777 guint32 present_bits
;
6778 hf
= proto_registrar_get_nth(**fields
);
6779 DISSECTOR_ASSERT(hf
->bitmask
!= 0);
6781 /* Skip fields that aren't fully present */
6782 present_bits
= available_bits
& hf
->bitmask
;
6783 if (present_bits
!= hf
->bitmask
) {
6788 proto_tree_add_item(tree
, **fields
, tvb
, offset
, len
, encoding
);
6789 if (flags
& BMT_NO_APPEND
) {
6793 tmpval
= (value
& hf
->bitmask
) >> hfinfo_bitshift(hf
);
6804 if (hf
->display
== BASE_CUSTOM
) {
6805 gchar lbl
[ITEM_LABEL_LENGTH
];
6806 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
6808 DISSECTOR_ASSERT(fmtfunc
);
6809 fmtfunc(lbl
, tmpval
);
6810 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
6814 else if (hf
->strings
) {
6815 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
6816 hf
->name
, hf_try_val_to_str_const(tmpval
, hf
, "Unknown"));
6819 else if (!(flags
& BMT_NO_INT
)) {
6824 proto_item_append_text(item
, ", ");
6827 out
= hfinfo_number_value_format(hf
, buf
, tmpval
);
6828 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
6834 if (hf
->strings
&& !(flags
& BMT_NO_TFS
)) {
6835 /* If we have true/false strings, emit full - otherwise messages
6837 const struct true_false_string
*tfs
=
6838 (const struct true_false_string
*)hf
->strings
;
6841 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
6842 hf
->name
, tfs
->true_string
);
6844 } else if (!(flags
& BMT_NO_FALSE
)) {
6845 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
6846 hf
->name
, tfs
->false_string
);
6849 } else if (hf
->bitmask
& value
) {
6850 /* If the flag is set, show the name */
6851 proto_item_append_text(item
, "%s%s", first
? "" : ", ", hf
->name
);
6856 g_assert_not_reached();
6865 /* This function will dissect a sequence of bytes that describe a
6867 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
6868 * This field will form an expansion under which the individual fields of the
6869 * bitmask is dissected and displayed.
6870 * This field must be of the type FT_[U]INT{8|16|24|32}.
6872 * fields is an array of pointers to int that lists all the fields of the
6873 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
6874 * or another integer of the same type/size as hf_hdr with a mask specified.
6875 * This array is terminated by a NULL entry.
6877 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
6878 * FT_integer fields that have a value_string attached will have the
6879 * matched string displayed on the expansion line.
6882 proto_tree_add_bitmask(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
6883 const guint offset
, const int hf_hdr
,
6884 const gint ett
, const int **fields
,
6885 const guint encoding
)
6887 proto_item
*item
= NULL
;
6888 header_field_info
*hf
;
6891 hf
= proto_registrar_get_nth(hf_hdr
);
6892 DISSECTOR_ASSERT(IS_FT_INT(hf
->type
) || IS_FT_UINT(hf
->type
));
6893 len
= ftype_length(hf
->type
);
6896 item
= proto_tree_add_item(parent_tree
, hf_hdr
, tvb
, offset
, len
, encoding
);
6897 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
, encoding
,
6898 BMT_NO_INT
|BMT_NO_TFS
, FALSE
);
6904 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
6905 * This is intended to support bitmask fields whose lengths can vary, perhaps
6906 * as the underlying standard evolves over time.
6907 * With this API there is the possibility of being called to display more or
6908 * less data than the dissector was coded to support.
6909 * In such cases, it is assumed that bitmasks are extended on the MSb end.
6910 * Thus when presented with "too much" or "too little" data, MSbits will be
6911 * ignored or MSfields sacrificed.
6913 * Only fields for which all defined bits are available are displayed.
6916 proto_tree_add_bitmask_len(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
6917 const guint offset
, const guint len
, const int hf_hdr
,
6918 const gint ett
, const int **fields
, struct expert_field
* exp
,
6919 const guint encoding
)
6921 proto_item
*item
= NULL
;
6922 header_field_info
*hf
;
6923 guint decodable_len
;
6924 guint decodable_offset
;
6925 guint32 decodable_value
;
6927 hf
= proto_registrar_get_nth(hf_hdr
);
6928 DISSECTOR_ASSERT(IS_FT_INT(hf
->type
) || IS_FT_UINT(hf
->type
));
6930 decodable_offset
= offset
;
6931 decodable_len
= MIN(len
, (guint
) ftype_length(hf
->type
));
6933 /* If we are ftype_length-limited,
6934 * make sure we decode as many LSBs as possible.
6936 if (encoding
== ENC_BIG_ENDIAN
) {
6937 decodable_offset
+= (len
- decodable_len
);
6941 decodable_value
= get_uint_value(parent_tree
, tvb
, decodable_offset
,
6942 decodable_len
, encoding
);
6944 /* The root item covers all the bytes even if we can't decode them all */
6945 item
= proto_tree_add_uint(parent_tree
, hf_hdr
, tvb
, offset
, len
,
6949 if (decodable_len
< len
) {
6950 /* Dissector likely requires updating for new protocol revision */
6951 expert_add_info_format(NULL
, item
, exp
,
6952 "Only least-significant %d of %d bytes decoded",
6953 decodable_len
, len
);
6957 proto_item_add_bitmask_tree(item
, tvb
, decodable_offset
, decodable_len
,
6958 ett
, fields
, encoding
, BMT_NO_INT
|BMT_NO_TFS
, FALSE
);
6964 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6966 proto_tree_add_bitmask_text(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
6967 const guint offset
, const guint len
,
6968 const char *name
, const char *fallback
,
6969 const gint ett
, const int **fields
,
6970 const guint encoding
, const int flags
)
6972 proto_item
*item
= NULL
;
6975 item
= proto_tree_add_text(parent_tree
, tvb
, offset
, len
, "%s", name
? name
: "");
6976 if (proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
, encoding
,
6977 flags
, TRUE
) && fallback
) {
6978 /* Still at first item - append 'fallback' text if any */
6979 proto_item_append_text(item
, "%s", fallback
);
6987 proto_tree_add_bits_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
6988 const guint bit_offset
, const gint no_of_bits
,
6989 const guint encoding
)
6991 header_field_info
*hfinfo
;
6995 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
6997 octet_length
= (no_of_bits
+ 7) >> 3;
6998 octet_offset
= bit_offset
>> 3;
6999 test_length(hfinfo
, tvb
, octet_offset
, octet_length
);
7001 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
7002 * but only after doing a bunch more work (which we can, in the common
7003 * case, shortcut here).
7005 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
7007 return proto_tree_add_bits_ret_val(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, NULL
, encoding
);
7011 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7012 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7013 * Offset should be given in bits from the start of the tvb.
7017 _proto_tree_add_bits_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
7018 const guint bit_offset
, const gint no_of_bits
,
7019 guint64
*return_value
, const guint encoding
)
7025 char lbl_str
[ITEM_LABEL_LENGTH
];
7029 header_field_info
*hf_field
;
7031 const true_false_string
*tfstring
;
7033 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7034 PROTO_REGISTRAR_GET_NTH(hfindex
, hf_field
);
7036 if (hf_field
->bitmask
!= 0) {
7037 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7038 " with field '%s' (%s) with bitmask != 0",
7039 hf_field
->abbrev
, hf_field
->name
));
7042 DISSECTOR_ASSERT(no_of_bits
> 0);
7044 /* Byte align offset */
7045 offset
= bit_offset
>>3;
7048 * Calculate the number of octets used to hold the bits
7050 tot_no_bits
= ((bit_offset
&0x7) + no_of_bits
);
7051 length
= (tot_no_bits
+ 7) >> 3;
7053 if (no_of_bits
< 65) {
7054 value
= tvb_get_bits64(tvb
, bit_offset
, no_of_bits
, encoding
);
7056 DISSECTOR_ASSERT_NOT_REACHED();
7060 /* Sign extend for signed types */
7061 switch (hf_field
->type
) {
7067 if (value
& (G_GINT64_CONSTANT(1) << (no_of_bits
-1)))
7068 value
|= (G_GINT64_CONSTANT(-1) << no_of_bits
);
7076 *return_value
= value
;
7079 /* Coast clear. Try and fake it */
7080 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7082 bf_str
= decode_bits_in_field(bit_offset
, no_of_bits
, value
);
7084 switch (hf_field
->type
) {
7087 tfstring
= (const true_false_string
*) &tfs_true_false
;
7088 if (hf_field
->strings
)
7089 tfstring
= (const true_false_string
*)hf_field
->strings
;
7090 return proto_tree_add_boolean_format(tree
, hfindex
, tvb
, offset
, length
, (guint32
)value
,
7092 bf_str
, hf_field
->name
,
7093 (guint32
)value
? tfstring
->true_string
: tfstring
->false_string
);
7100 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, offset
, length
, (guint32
)value
);
7101 fill_label_number(PITEM_FINFO(pi
), lbl_str
, FALSE
);
7108 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, offset
, length
, (gint32
)value
);
7109 fill_label_number(PITEM_FINFO(pi
), lbl_str
, TRUE
);
7113 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, offset
, length
, value
);
7114 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, FALSE
);
7118 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, offset
, length
, (gint64
)value
);
7119 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, TRUE
);
7123 DISSECTOR_ASSERT_NOT_REACHED();
7128 proto_item_set_text(pi
, "%s = %s", bf_str
, lbl_str
);
7133 proto_tree_add_split_bits_item_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
7134 const guint bit_offset
, const crumb_spec_t
*crumb_spec
,
7135 guint64
*return_value
)
7140 guint mask_initial_bit_offset
;
7141 guint mask_greatest_bit_offset
;
7145 char lbl_str
[ITEM_LABEL_LENGTH
];
7147 guint64 composite_bitmask
;
7148 guint64 composite_bitmap
;
7150 header_field_info
*hf_field
;
7151 const true_false_string
*tfstring
;
7153 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7154 PROTO_REGISTRAR_GET_NTH(hfindex
, hf_field
);
7156 if (hf_field
->bitmask
!= 0) {
7157 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7158 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7159 " with field '%s' (%s) with bitmask != 0",
7160 hf_field
->abbrev
, hf_field
->name
));
7163 mask_initial_bit_offset
= bit_offset
% 8;
7168 mask_greatest_bit_offset
= 0;
7169 composite_bitmask
= 0;
7170 composite_bitmap
= 0;
7172 while (crumb_spec
[i
].crumb_bit_length
!= 0) {
7173 guint64 crumb_mask
, crumb_value
;
7174 guint8 crumb_end_bit_offset
;
7176 DISSECTOR_ASSERT(i
< 64);
7177 crumb_value
= tvb_get_bits64(tvb
,
7178 bit_offset
+ crumb_spec
[i
].crumb_bit_offset
,
7179 crumb_spec
[i
].crumb_bit_length
,
7181 value
+= crumb_value
;
7182 no_of_bits
+= crumb_spec
[i
].crumb_bit_length
;
7184 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7185 octet containing the initial offset.
7186 If the mask is beyond 32 bits, then give up on bit map display.
7187 This could be improved in future, probably showing a table
7188 of 32 or 64 bits per row */
7189 if (mask_greatest_bit_offset
< 32) {
7190 crumb_end_bit_offset
= mask_initial_bit_offset
7191 + crumb_spec
[i
].crumb_bit_offset
7192 + crumb_spec
[i
].crumb_bit_length
;
7193 crumb_mask
= (G_GUINT64_CONSTANT(1) << crumb_spec
[i
].crumb_bit_length
) - 1;
7195 if (crumb_end_bit_offset
> mask_greatest_bit_offset
) {
7196 mask_greatest_bit_offset
= crumb_end_bit_offset
;
7198 composite_bitmask
|= (crumb_mask
<< (64 - crumb_end_bit_offset
));
7199 composite_bitmap
|= (crumb_value
<< (64 - crumb_end_bit_offset
));
7201 /* Shift left for the next segment */
7202 value
<<= crumb_spec
[++i
].crumb_bit_length
;
7205 /* Sign extend for signed types */
7206 switch (hf_field
->type
) {
7212 if (no_of_bits
&& (value
& (G_GINT64_CONSTANT(1) << (no_of_bits
-1))))
7213 value
|= (G_GINT64_CONSTANT(-1) << no_of_bits
);
7220 *return_value
= value
;
7223 /* Coast clear. Try and fake it */
7224 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7226 /* initialise the format string */
7227 bf_str
= (char *)ep_alloc(256);
7230 octet_offset
= bit_offset
>> 3;
7232 /* Round up mask length to nearest octet */
7233 octet_length
= ((mask_greatest_bit_offset
+ 7) >> 3);
7234 mask_greatest_bit_offset
= octet_length
<< 3;
7236 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7237 It would be a useful enhancement to eliminate this restriction. */
7238 if (mask_greatest_bit_offset
<= 32) {
7239 other_decode_bitfield_value(bf_str
,
7240 (guint32
)(composite_bitmap
>> (64 - mask_greatest_bit_offset
)),
7241 (guint32
)(composite_bitmask
>> (64 - mask_greatest_bit_offset
)),
7242 mask_greatest_bit_offset
);
7245 switch (hf_field
->type
) {
7246 case FT_BOOLEAN
: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7248 tfstring
= (const true_false_string
*) &tfs_true_false
;
7249 if (hf_field
->strings
)
7250 tfstring
= (const true_false_string
*) hf_field
->strings
;
7251 return proto_tree_add_boolean_format(tree
, hfindex
,
7252 tvb
, octet_offset
, octet_length
, (guint32
)value
,
7254 bf_str
, hf_field
->name
,
7255 (guint32
)value
? tfstring
->true_string
: tfstring
->false_string
);
7262 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (guint32
)value
);
7263 fill_label_number(PITEM_FINFO(pi
), lbl_str
, FALSE
);
7270 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (gint32
)value
);
7271 fill_label_number(PITEM_FINFO(pi
), lbl_str
, TRUE
);
7275 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, octet_offset
, octet_length
, value
);
7276 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, FALSE
);
7280 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (gint64
)value
);
7281 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, TRUE
);
7285 DISSECTOR_ASSERT_NOT_REACHED();
7289 proto_item_set_text(pi
, "%s = %s", bf_str
, lbl_str
);
7294 proto_tree_add_split_bits_crumb(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
, const guint bit_offset
,
7295 const crumb_spec_t
*crumb_spec
, guint16 crumb_index
)
7297 header_field_info
*hfinfo
;
7299 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
7300 proto_tree_add_text(tree
, tvb
,
7302 ((bit_offset
+ crumb_spec
[crumb_index
].crumb_bit_length
- 1) >> 3) - (bit_offset
>> 3) + 1,
7303 "%s crumb %d of %s (decoded above)",
7304 decode_bits_in_field(bit_offset
, crumb_spec
[crumb_index
].crumb_bit_length
,
7307 crumb_spec
[crumb_index
].crumb_bit_length
,
7314 proto_tree_add_bits_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
7315 const guint bit_offset
, const gint no_of_bits
,
7316 guint64
*return_value
, const guint encoding
)
7320 if ((item
= _proto_tree_add_bits_ret_val(tree
, hfindex
, tvb
,
7321 bit_offset
, no_of_bits
,
7322 return_value
, encoding
))) {
7323 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
7324 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
7330 _proto_tree_add_bits_format_value(proto_tree
*tree
, const int hfindex
,
7331 tvbuff_t
*tvb
, const guint bit_offset
,
7332 const gint no_of_bits
, void *value_ptr
,
7340 header_field_info
*hf_field
;
7342 /* We do not have to return a value, try to fake it as soon as possible */
7343 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7345 if (hf_field
->bitmask
!= 0) {
7346 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7347 "Incompatible use of proto_tree_add_bits_format_value"
7348 " with field '%s' (%s) with bitmask != 0",
7349 hf_field
->abbrev
, hf_field
->name
));
7352 DISSECTOR_ASSERT(no_of_bits
> 0);
7354 /* Byte align offset */
7355 offset
= bit_offset
>>3;
7358 * Calculate the number of octets used to hold the bits
7360 tot_no_bits
= ((bit_offset
&0x7) + no_of_bits
);
7361 length
= tot_no_bits
>>3;
7362 /* If we are using part of the next octet, increase length by 1 */
7363 if (tot_no_bits
& 0x07)
7366 if (no_of_bits
< 65) {
7367 value
= tvb_get_bits64(tvb
, bit_offset
, no_of_bits
, ENC_BIG_ENDIAN
);
7369 DISSECTOR_ASSERT_NOT_REACHED();
7373 str
= decode_bits_in_field(bit_offset
, no_of_bits
, value
);
7376 strcat(str
, hf_field
->name
);
7379 * This function does not receive an actual value but a dimensionless pointer to that value.
7380 * For this reason, the type of the header field is examined in order to determine
7381 * what kind of value we should read from this address.
7382 * The caller of this function must make sure that for the specific header field type the address of
7383 * a compatible value is provided.
7385 switch (hf_field
->type
) {
7387 return proto_tree_add_boolean_format(tree
, hfindex
, tvb
, offset
, length
, *(guint32
*)value_ptr
,
7388 "%s: %s", str
, value_str
);
7395 return proto_tree_add_uint_format(tree
, hfindex
, tvb
, offset
, length
, *(guint32
*)value_ptr
,
7396 "%s: %s", str
, value_str
);
7400 return proto_tree_add_uint64_format(tree
, hfindex
, tvb
, offset
, length
, *(guint64
*)value_ptr
,
7401 "%s: %s", str
, value_str
);
7408 return proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, length
, *(gint32
*)value_ptr
,
7409 "%s: %s", str
, value_str
);
7413 return proto_tree_add_int64_format(tree
, hfindex
, tvb
, offset
, length
, *(gint64
*)value_ptr
,
7414 "%s: %s", str
, value_str
);
7418 return proto_tree_add_float_format(tree
, hfindex
, tvb
, offset
, length
, *(float *)value_ptr
,
7419 "%s: %s", str
, value_str
);
7423 DISSECTOR_ASSERT_NOT_REACHED();
7430 proto_tree_add_bits_format_value(proto_tree
*tree
, const int hfindex
,
7431 tvbuff_t
*tvb
, const guint bit_offset
,
7432 const gint no_of_bits
, void *value_ptr
,
7437 if ((item
= _proto_tree_add_bits_format_value(tree
, hfindex
,
7438 tvb
, bit_offset
, no_of_bits
,
7439 value_ptr
, value_str
))) {
7440 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
7441 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
7446 #define CREATE_VALUE_STRING(dst,format,ap) \
7447 va_start(ap, format); \
7448 dst = ep_strdup_vprintf(format, ap); \
7452 proto_tree_add_uint_bits_format_value(proto_tree
*tree
, const int hfindex
,
7453 tvbuff_t
*tvb
, const guint bit_offset
,
7454 const gint no_of_bits
, guint32 value
,
7455 const char *format
, ...)
7459 header_field_info
*hf_field
;
7461 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7463 switch (hf_field
->type
) {
7471 DISSECTOR_ASSERT_NOT_REACHED();
7476 CREATE_VALUE_STRING(dst
, format
, ap
);
7478 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, dst
);
7482 proto_tree_add_float_bits_format_value(proto_tree
*tree
, const int hfindex
,
7483 tvbuff_t
*tvb
, const guint bit_offset
,
7484 const gint no_of_bits
, float value
,
7485 const char *format
, ...)
7489 header_field_info
*hf_field
;
7491 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7493 DISSECTOR_ASSERT(hf_field
->type
== FT_FLOAT
);
7495 CREATE_VALUE_STRING(dst
, format
, ap
);
7497 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, dst
);
7501 proto_tree_add_int_bits_format_value(proto_tree
*tree
, const int hfindex
,
7502 tvbuff_t
*tvb
, const guint bit_offset
,
7503 const gint no_of_bits
, gint32 value
,
7504 const char *format
, ...)
7508 header_field_info
*hf_field
;
7510 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7512 switch (hf_field
->type
) {
7520 DISSECTOR_ASSERT_NOT_REACHED();
7525 CREATE_VALUE_STRING(dst
, format
, ap
);
7527 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, dst
);
7531 proto_tree_add_boolean_bits_format_value(proto_tree
*tree
, const int hfindex
,
7532 tvbuff_t
*tvb
, const guint bit_offset
,
7533 const gint no_of_bits
, guint32 value
,
7534 const char *format
, ...)
7538 header_field_info
*hf_field
;
7540 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
7542 DISSECTOR_ASSERT(hf_field
->type
== FT_BOOLEAN
);
7544 CREATE_VALUE_STRING(dst
, format
, ap
);
7546 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, dst
);
7550 proto_check_field_name(const gchar
*field_name
)
7552 return wrs_check_charset(fld_abbrev_chars
, field_name
);
7556 tree_expanded(int tree_type
)
7558 g_assert(tree_type
>= 0 && tree_type
< num_tree_types
);
7559 return tree_is_expanded
[tree_type
>> 5] & (1 << (tree_type
& 31));
7563 tree_expanded_set(int tree_type
, gboolean value
)
7565 g_assert(tree_type
>= 0 && tree_type
< num_tree_types
);
7568 tree_is_expanded
[tree_type
>> 5] |= (1 << (tree_type
& 31));
7570 tree_is_expanded
[tree_type
>> 5] &= ~(1 << (tree_type
& 31));
7574 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7579 * indent-tabs-mode: t
7582 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7583 * :indentSize=8:tabSize=8:noTabs=false: