HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / proto.c
blobd150b01cdad4275c0268e7ccf2fbcb4c8e52f1ac
1 /* proto.c
2 * Routines for protocol tree
4 * $Id$
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.
25 #include "config.h"
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <glib.h>
31 #include <float.h>
33 #include <wsutil/bits_ctz.h>
34 #include <wsutil/bits_count_ones.h>
36 #include <ftypes/ftypes-int.h>
38 #include "packet.h"
39 #include "exceptions.h"
40 #include "ptvcursor.h"
41 #include "strutil.h"
42 #include "addr_resolv.h"
43 #include "oids.h"
44 #include "plugins.h"
45 #include "proto.h"
46 #include "epan_dissect.h"
47 #include "tvbuff.h"
48 #include "emem.h"
49 #include "wmem/wmem.h"
50 #include "charsets.h"
51 #include "asm_utils.h"
52 #include "column-utils.h"
53 #include "to_str-int.h"
54 #include "to_str.h"
55 #include "expert.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 {
68 gint cursor_offset;
69 proto_item *it;
70 proto_tree *tree;
71 } subtree_lvl;
73 struct ptvcursor {
74 subtree_lvl *pushed_tree;
75 guint8 pushed_tree_index;
76 guint8 pushed_tree_max;
77 proto_tree *tree;
78 tvbuff_t *tvb;
79 gint offset;
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 \
99 not to do so. \
100 */ \
101 if (!tree) \
102 return NULL; \
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 */\
119 return tree; \
124 /** See inlined comments.
125 @param pi the created protocol item we're about to return */
126 #define TRY_TO_FAKE_THIS_REPR(pi) \
127 g_assert(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 */ \
131 return pi; \
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);
149 static proto_item *
150 proto_tree_add_node(proto_tree *tree, field_info *fi);
152 static void
153 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
154 gint *item_length);
156 static field_info *
157 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
158 const gint start, const gint item_length);
160 static field_info *
161 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
162 const gint start, gint *length);
164 static proto_item *
165 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
166 gint start, gint *length);
168 static void
169 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
170 static void
171 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
173 static void
174 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
175 static void
176 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
177 static void
178 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
179 static void
180 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
181 static void
182 proto_tree_set_string(field_info *fi, const char* value);
183 static void
184 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
185 static void
186 proto_tree_set_ax25(field_info *fi, const guint8* value);
187 static void
188 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
189 static void
190 proto_tree_set_vines(field_info *fi, const guint8* value);
191 static void
192 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
193 static void
194 proto_tree_set_ether(field_info *fi, const guint8* value);
195 static void
196 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
197 static void
198 proto_tree_set_ipxnet(field_info *fi, guint32 value);
199 static void
200 proto_tree_set_ipv4(field_info *fi, guint32 value);
201 static void
202 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
203 static void
204 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
205 static void
206 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
207 static void
208 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
209 static void
210 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
211 static void
212 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
213 static void
214 proto_tree_set_boolean(field_info *fi, guint32 value);
215 static void
216 proto_tree_set_float(field_info *fi, float value);
217 static void
218 proto_tree_set_double(field_info *fi, double value);
219 static void
220 proto_tree_set_uint(field_info *fi, guint32 value);
221 static void
222 proto_tree_set_int(field_info *fi, gint32 value);
223 static void
224 proto_tree_set_uint64(field_info *fi, guint64 value);
225 static void
226 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
227 static void
228 proto_tree_set_eui64(field_info *fi, const guint64 value);
229 static void
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 */
246 struct _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; \
270 node->next = 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) \
279 wmem_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 {
289 guint32 len;
290 guint32 allocated_len;
291 header_field_info **hfi;
292 } gpa_hfinfo_t;
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. */
311 int num_tree_types;
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;
318 static gint
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 */
329 void
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),
332 register_cb cb,
333 gpointer client_data)
335 proto_cleanup();
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);
341 gpa_hfinfo.len = 0;
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 */
347 ftypes_initialize();
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
361 do. */
362 register_all_protocols_func(cb, client_data);
363 #ifdef HAVE_PYTHON
364 /* Now scan for python protocols */
365 if (cb)
366 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
367 register_all_py_protocols_func();
368 #endif
370 #ifdef HAVE_PLUGINS
371 /* Now scan for plugins and load all the ones we find, calling
372 their register routines to do the stuff described above. */
373 if (cb)
374 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
375 init_plugins();
376 register_all_plugin_registrations();
377 #endif
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
382 they need. */
383 register_all_handoffs_func(cb, client_data);
385 #ifdef HAVE_PYTHON
386 /* Now do the same with python dissectors */
387 if (cb)
388 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
389 register_all_py_handoffs_func();
390 #endif
392 #ifdef HAVE_PLUGINS
393 /* Now do the same with plugins. */
394 if (cb)
395 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
396 register_all_plugin_handoffs();
397 #endif
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);
407 void
408 proto_cleanup(void)
410 /* Free the abbrev/ID GTree */
411 if (gpa_name_tree) {
412 g_tree_destroy(gpa_name_tree);
413 gpa_name_tree = NULL;
416 while (protocols) {
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);
425 g_free(protocol);
428 if (proto_names) {
429 g_hash_table_destroy(proto_names);
430 proto_names = NULL;
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) {
444 gpa_hfinfo.len = 0;
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;
453 static gboolean
454 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
455 gpointer data)
457 proto_node *pnode = tree;
458 proto_node *child;
459 proto_node *current;
461 if (func(pnode, data))
462 return TRUE;
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.
471 current = child;
472 child = current->next;
473 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
474 return TRUE;
477 return FALSE;
480 gboolean
481 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
482 gpointer data)
484 proto_node *pnode = tree;
485 proto_node *child;
486 proto_node *current;
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.
495 current = child;
496 child = current->next;
497 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
498 return TRUE;
500 if (func(pnode, data))
501 return TRUE;
503 return FALSE;
506 void
507 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
508 gpointer data)
510 proto_node *node = tree;
511 proto_node *current;
513 if (!node)
514 return;
516 node = node->first_child;
517 while (node != NULL) {
518 current = node;
519 node = current->next;
520 func((proto_tree *)current, data);
524 static void
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);
548 static void
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);
558 void
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);
565 /* free tree data */
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 */
584 void
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);
591 /* free tree data */
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.
610 gboolean
611 proto_tree_set_visible(proto_tree *tree, gboolean visible)
613 gboolean old_visible = PTREE_DATA(tree)->visible;
615 PTREE_DATA(tree)->visible = visible;
617 return old_visible;
620 void
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_...()
630 functions.
631 If the tree is visible we implicitly assume the field is referenced.
633 gboolean
634 proto_field_is_referenced(proto_tree *tree, int proto_id)
636 register header_field_info *hfinfo;
639 if (!tree)
640 return FALSE;
642 if (PTREE_DATA(tree)->visible)
643 return TRUE;
645 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
646 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
647 return TRUE;
649 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
650 return TRUE;
652 return FALSE;
656 /* Finds a record in the hfinfo array by id. */
657 header_field_info *
658 proto_registrar_get_nth(guint hfindex)
660 register header_field_info *hfinfo;
662 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
663 return 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
670 * possible.
673 /* compute a hash for the part before the dot of a display filter */
674 static guint
675 prefix_hash (gconstpointer key) {
676 /* end the string at the dot and compute its hash */
677 gchar* copy = ep_strdup((const gchar *)key);
678 gchar* c = copy;
680 for (; *c; c++) {
681 if (*c == '.') {
682 *c = 0;
683 break;
687 return g_str_hash(copy);
690 /* are both strings equal up to the end or the dot? */
691 static gboolean
692 prefix_equal (gconstpointer ap, gconstpointer bp) {
693 const gchar* a = (const gchar *)ap;
694 const gchar* b = (const gchar *)bp;
696 do {
697 gchar ac = *a++;
698 gchar bc = *b++;
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;
706 } while (1);
708 return FALSE;
712 /* indexed by prefix, contains initializers */
713 static GHashTable* prefixes = NULL;
716 /* Register a new prefix for "delayed" initialization of field arrays */
717 void
718 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
719 if (! prefixes ) {
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 */
727 static gboolean
728 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
729 ((prefix_initializer_t)v)((const char *)k);
730 return TRUE;
733 /** Initialize every remaining uninitialized prefix. */
734 void
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.
744 header_field_info *
745 proto_registrar_get_byname(const char *field_name)
747 header_field_info *hfinfo;
748 prefix_initializer_t pi;
750 if (!field_name)
751 return NULL;
753 hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
755 if (hfinfo)
756 return hfinfo;
758 if (!prefixes)
759 return NULL;
761 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
762 pi(field_name);
763 g_hash_table_remove(prefixes, field_name);
764 } else {
765 return NULL;
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);
778 if (!hfinfo)
779 return -1;
781 return hfinfo->id;
785 static void
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;
800 static void
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. */
811 ptvcursor_t *
812 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
814 ptvcursor_t *ptvc;
816 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
817 ptvc->tree = tree;
818 ptvc->tvb = tvb;
819 ptvc->offset = offset;
820 ptvc->pushed_tree = NULL;
821 ptvc->pushed_tree_max = 0;
822 ptvc->pushed_tree_index = 0;
823 return ptvc;
827 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
828 void
829 ptvcursor_free(ptvcursor_t *ptvc)
831 ptvcursor_free_subtree_levels(ptvc);
832 /*g_free(ptvc);*/
835 /* Returns tvbuff. */
836 tvbuff_t *
837 ptvcursor_tvbuff(ptvcursor_t *ptvc)
839 return ptvc->tvb;
842 /* Returns current offset. */
843 gint
844 ptvcursor_current_offset(ptvcursor_t *ptvc)
846 return ptvc->offset;
849 proto_tree *
850 ptvcursor_tree(ptvcursor_t *ptvc)
852 if (!ptvc)
853 return NULL;
855 return ptvc->tree;
858 void
859 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
861 ptvc->tree = tree;
864 /* creates a subtree, sets it as the working tree and pushes the old working tree */
865 proto_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;
874 subtree->it= NULL;
875 ptvc->pushed_tree_index++;
876 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
879 /* pops a subtree */
880 void
881 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
883 subtree_lvl *subtree;
885 if (ptvc->pushed_tree_index <= 0)
886 return;
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 */
897 static void
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;
905 subtree->it = it;
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 */
911 proto_tree *
912 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
914 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
915 return ptvc->tree;
918 static proto_tree *
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.
932 proto_tree *
933 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
934 const guint encoding, gint ett_subtree)
936 proto_item *it;
938 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
939 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
942 static proto_item *
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.
950 proto_tree *
951 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
952 gint ett_subtree, const char *format, ...)
954 proto_item *pi;
955 va_list ap;
956 header_field_info *hfinfo;
957 proto_tree *tree;
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);
970 va_end(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 */
976 static proto_item *
977 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
979 proto_item *pi;
981 if (tree == NULL)
982 return NULL;
984 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
986 return pi;
989 /* Add a text-only node to the proto_tree */
990 proto_item *
991 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
992 const char *format, ...)
994 proto_item *pi;
995 va_list ap;
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);
1006 va_end(ap);
1008 return pi;
1011 /* Add a text-only node to the proto_tree (va_list version) */
1012 proto_item *
1013 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1014 gint length, const char *format, va_list ap)
1016 proto_item *pi;
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);
1027 return pi;
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
1032 * STDOUT, too */
1033 proto_item *
1034 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1036 proto_item *pi;
1037 va_list ap;
1039 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1041 if (pi) {
1042 va_start(ap, format);
1043 proto_tree_set_representation(pi, format, ap);
1044 va_end(ap);
1046 va_start(ap, format);
1047 vprintf(format, ap);
1048 va_end(ap);
1049 printf("\n");
1051 return pi;
1054 void proto_report_dissector_bug(const char *message)
1056 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1057 abort();
1058 else
1059 THROW_MESSAGE(DissectorError, message);
1062 /* We could probably get away with changing is_error to a minimum length value. */
1063 static void
1064 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1066 if (is_error) {
1067 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1068 } else {
1069 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1072 if (is_error) {
1073 THROW(ReportedBoundsError);
1077 static guint32
1078 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1080 guint32 value;
1081 gboolean length_error;
1083 switch (length) {
1085 case 1:
1086 value = tvb_get_guint8(tvb, offset);
1087 break;
1089 case 2:
1090 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1091 : tvb_get_ntohs(tvb, offset);
1092 break;
1094 case 3:
1095 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1096 : tvb_get_ntoh24(tvb, offset);
1097 break;
1099 case 4:
1100 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1101 : tvb_get_ntohl(tvb, offset);
1102 break;
1104 default:
1105 if (length < 1) {
1106 length_error = TRUE;
1107 value = 0;
1108 } else {
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);
1114 break;
1116 return value;
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".
1125 static gint32
1126 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1128 gint32 value;
1129 gboolean length_error;
1131 switch (length) {
1133 case 1:
1134 value = (gint8)tvb_get_guint8(tvb, offset);
1135 break;
1137 case 2:
1138 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1139 : tvb_get_ntohs(tvb, offset));
1140 break;
1142 case 3:
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;
1149 break;
1151 case 4:
1152 value = encoding ? tvb_get_letohl(tvb, offset)
1153 : tvb_get_ntohl(tvb, offset);
1154 break;
1156 default:
1157 if (length < 1) {
1158 length_error = TRUE;
1159 value = 0;
1160 } else {
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);
1166 break;
1168 return value;
1171 static void
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 */);
1183 } else
1184 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1185 GINT_TO_POINTER(hfinfo->id));
1186 if (!ptrs) {
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. */
1199 static proto_item *
1200 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1201 tvbuff_t *tvb, gint start, gint length,
1202 guint encoding)
1204 proto_item *pi;
1205 guint32 value, n;
1206 float floatval;
1207 double doubleval;
1208 const char *string;
1209 nstime_t time_stamp;
1210 guint32 tmpsecs;
1211 guint64 todsecs;
1212 gboolean length_error;
1214 switch (new_fi->hfinfo->type) {
1215 case FT_NONE:
1216 /* no value to set for FT_NONE */
1217 break;
1219 case FT_PROTOCOL:
1220 proto_tree_set_protocol_tvb(new_fi, tvb);
1221 break;
1223 case FT_BYTES:
1224 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1225 break;
1227 case FT_UINT_BYTES:
1229 * Map all non-zero values to little-endian for
1230 * backwards compatibility.
1232 if (encoding)
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;
1240 break;
1242 case FT_BOOLEAN:
1244 * Map all non-zero values to little-endian for
1245 * backwards compatibility.
1247 if (encoding)
1248 encoding = ENC_LITTLE_ENDIAN;
1249 proto_tree_set_boolean(new_fi,
1250 get_uint_value(tree, tvb, start, length, encoding));
1251 break;
1253 /* XXX - make these just FT_UINT? */
1254 case FT_UINT8:
1255 case FT_UINT16:
1256 case FT_UINT24:
1257 case FT_UINT32:
1259 * Map all non-zero values to little-endian for
1260 * backwards compatibility.
1262 if (encoding)
1263 encoding = ENC_LITTLE_ENDIAN;
1264 proto_tree_set_uint(new_fi,
1265 get_uint_value(tree, tvb, start, length, encoding));
1266 break;
1268 case FT_INT64:
1269 case FT_UINT64:
1271 * Map all non-zero values to little-endian for
1272 * backwards compatibility.
1274 if (encoding)
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);
1281 break;
1283 /* XXX - make these just FT_INT? */
1284 case FT_INT8:
1285 case FT_INT16:
1286 case FT_INT24:
1287 case FT_INT32:
1289 * Map all non-zero values to little-endian for
1290 * backwards compatibility.
1292 if (encoding)
1293 encoding = ENC_LITTLE_ENDIAN;
1294 proto_tree_set_int(new_fi,
1295 get_int_value(tree, tvb, start, length, encoding));
1296 break;
1298 case FT_IPv4:
1300 * Map all non-zero values to little-endian for
1301 * backwards compatibility.
1303 if (encoding)
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
1316 * "little-endian".
1318 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1319 break;
1321 case FT_IPXNET:
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));
1328 break;
1330 case FT_IPv6:
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);
1336 break;
1338 case FT_AX25:
1339 if (length != 7) {
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);
1344 break;
1346 case FT_VINES:
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);
1352 break;
1354 case FT_ETHER:
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);
1360 break;
1362 case FT_EUI64:
1364 * Map all non-zero values to little-endian for
1365 * backwards compatibility.
1367 if (encoding)
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);
1374 break;
1375 case FT_GUID:
1377 * Map all non-zero values to little-endian for
1378 * backwards compatibility.
1380 if (encoding)
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);
1387 break;
1389 case FT_OID:
1390 case FT_REL_OID:
1391 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1392 break;
1394 case FT_FLOAT:
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
1401 * "little-endian".
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).
1408 if (encoding)
1409 encoding = ENC_LITTLE_ENDIAN;
1410 if (length != 4) {
1411 length_error = length < 4 ? TRUE : FALSE;
1412 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1414 if (encoding)
1415 floatval = tvb_get_letohieee_float(tvb, start);
1416 else
1417 floatval = tvb_get_ntohieee_float(tvb, start);
1418 proto_tree_set_float(new_fi, floatval);
1419 break;
1421 case FT_DOUBLE:
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
1428 * "little-endian".
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;
1437 if (length != 8) {
1438 length_error = length < 8 ? TRUE : FALSE;
1439 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1441 if (encoding)
1442 doubleval = tvb_get_letohieee_double(tvb, start);
1443 else
1444 doubleval = tvb_get_ntohieee_double(tvb, start);
1445 proto_tree_set_double(new_fi, doubleval);
1446 break;
1448 case FT_STRING:
1449 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1450 encoding);
1451 break;
1453 case FT_STRINGZ:
1454 if (length < -1 ) {
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.
1466 if (length == -1) {
1467 /* This can throw an exception */
1468 string = tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
1469 } else if (length == 0) {
1470 string = "[Empty]";
1471 } else {
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-
1482 * terminated.)
1484 * In the first case, we must
1485 * allocate a buffer of length
1486 * "length+1", to make room for
1487 * a trailing '\0'.
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);
1507 break;
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,
1526 encoding);
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;
1538 break;
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
1544 * little-endian.
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);
1562 switch (encoding) {
1564 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1566 * 4-byte UNIX epoch, possibly followed by
1567 * 4-byte fractional time in nanoseconds,
1568 * both big-endian.
1570 time_stamp.secs = tvb_get_ntohl(tvb, start);
1571 if (length == 8)
1572 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1573 else
1574 time_stamp.nsecs = 0;
1575 break;
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);
1584 if (length == 8)
1585 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1586 else
1587 time_stamp.nsecs = 0;
1588 break;
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);
1600 break;
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);
1609 break;
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
1621 * chapter 3).
1623 tmpsecs = tvb_get_ntohl(tvb, start);
1624 if (tmpsecs)
1625 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1626 else
1627 time_stamp.secs = tmpsecs; /* 0 */
1629 if (length == 8) {
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;
1638 } else {
1639 time_stamp.nsecs = 0;
1641 break;
1643 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1645 * NTP time stamp, big-endian.
1647 tmpsecs = tvb_get_letohl(tvb, start);
1648 if (tmpsecs)
1649 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1650 else
1651 time_stamp.secs = tmpsecs; /* 0 */
1653 if (length == 8) {
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;
1662 } else {
1663 time_stamp.nsecs = 0;
1665 break;
1667 default:
1668 DISSECTOR_ASSERT_NOT_REACHED();
1669 time_stamp.secs = 0;
1670 time_stamp.nsecs = 0;
1671 break;
1673 proto_tree_set_time(new_fi, &time_stamp);
1674 break;
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
1680 * little-endian.
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;
1692 switch (encoding) {
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,
1703 * both big-endian.
1705 time_stamp.secs = tvb_get_ntohl(tvb, start);
1706 if (length == 8)
1707 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1708 else
1709 time_stamp.nsecs = 0;
1710 break;
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);
1719 if (length == 8)
1720 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1721 else
1722 time_stamp.nsecs = 0;
1723 break;
1725 proto_tree_set_time(new_fi, &time_stamp);
1726 break;
1728 default:
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();
1733 break;
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);
1743 return pi;
1746 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1747 and returns proto_item* */
1748 proto_item *
1749 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1750 const guint encoding)
1752 field_info *new_fi;
1753 header_field_info *hfinfo;
1754 gint item_length;
1755 guint32 n;
1756 int offset;
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);
1771 ptvc->offset += n;
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.
1787 static void
1788 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
1789 gint start, gint length)
1791 gint size = length;
1793 if (!tvb)
1794 return;
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.
1800 if (length == -1)
1801 size = 0;
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. */
1809 proto_item *
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)
1813 field_info *new_fi;
1814 gint item_length;
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);
1825 if (new_fi == NULL)
1826 return NULL;
1828 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1831 proto_item *
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 */
1839 proto_item *
1840 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1841 const gint start, gint length, const char *format,
1842 ...)
1844 proto_item *pi;
1845 va_list ap;
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);
1858 va_end(ap);
1860 /* no value to set for FT_NONE */
1861 return pi;
1864 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1865 * offset, and returns proto_item* */
1866 proto_item *
1867 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1868 const guint encoding)
1870 proto_item *item;
1872 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1873 length, encoding);
1875 return item;
1878 /* Advance the ptvcursor's offset within its tvbuff without
1879 * adding anything to the proto_tree. */
1880 void
1881 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1883 ptvc->offset += length;
1887 static void
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 */
1894 proto_item *
1895 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1896 gint start, gint length, const char *format, ...)
1898 proto_item *pi;
1899 va_list ap;
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);
1914 va_end(ap);
1916 return pi;
1920 /* Add a FT_BYTES to a proto_tree */
1921 proto_item *
1922 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1923 gint length, const guint8 *start_ptr)
1925 proto_item *pi;
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);
1935 return pi;
1938 proto_item *
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, ...)
1944 proto_item *pi;
1945 va_list ap;
1946 header_field_info *hfinfo;
1948 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1950 if (start_ptr)
1951 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1952 start_ptr);
1953 else
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);
1959 va_end(ap);
1961 return pi;
1964 proto_item *
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, ...)
1969 proto_item *pi;
1970 va_list ap;
1971 header_field_info *hfinfo;
1973 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1975 if (start_ptr)
1976 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
1977 start_ptr);
1978 else
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);
1986 va_end(ap);
1988 return pi;
1991 static void
1992 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1994 GByteArray *bytes;
1996 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
1998 bytes = g_byte_array_new();
1999 if (length > 0) {
2000 g_byte_array_append(bytes, start_ptr, length);
2002 fvalue_set(&fi->value, bytes, TRUE);
2006 static void
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 */
2013 proto_item *
2014 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2015 gint length, nstime_t *value_ptr)
2017 proto_item *pi;
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);
2028 return pi;
2031 proto_item *
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, ...)
2036 proto_item *pi;
2037 va_list ap;
2039 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2040 if (pi != tree) {
2041 va_start(ap, format);
2042 proto_tree_set_representation_value(pi, format, ap);
2043 va_end(ap);
2046 return pi;
2049 proto_item *
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, ...)
2054 proto_item *pi;
2055 va_list ap;
2057 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2058 if (pi != tree) {
2059 TRY_TO_FAKE_THIS_REPR(pi);
2061 va_start(ap, format);
2062 proto_tree_set_representation(pi, format, ap);
2063 va_end(ap);
2066 return pi;
2069 /* Set the FT_*TIME value */
2070 static void
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 */
2079 proto_item *
2080 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2081 gint length, guint32 value)
2083 proto_item *pi;
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);
2093 return pi;
2096 proto_item *
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, ...)
2101 proto_item *pi;
2102 va_list ap;
2104 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2105 if (pi != tree) {
2106 va_start(ap, format);
2107 proto_tree_set_representation_value(pi, format, ap);
2108 va_end(ap);
2111 return pi;
2114 proto_item *
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, ...)
2119 proto_item *pi;
2120 va_list ap;
2122 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2123 if (pi != tree) {
2124 TRY_TO_FAKE_THIS_REPR(pi);
2126 va_start(ap, format);
2127 proto_tree_set_representation(pi, format, ap);
2128 va_end(ap);
2131 return pi;
2134 /* Set the FT_IPXNET value */
2135 static void
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 */
2142 proto_item *
2143 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2144 gint length, guint32 value)
2146 proto_item *pi;
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);
2156 return pi;
2159 proto_item *
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, ...)
2164 proto_item *pi;
2165 va_list ap;
2167 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2168 if (pi != tree) {
2169 va_start(ap, format);
2170 proto_tree_set_representation_value(pi, format, ap);
2171 va_end(ap);
2174 return pi;
2177 proto_item *
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, ...)
2182 proto_item *pi;
2183 va_list ap;
2185 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2186 if (pi != tree) {
2187 TRY_TO_FAKE_THIS_REPR(pi);
2189 va_start(ap, format);
2190 proto_tree_set_representation(pi, format, ap);
2191 va_end(ap);
2194 return pi;
2197 /* Set the FT_IPv4 value */
2198 static void
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 */
2205 proto_item *
2206 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2207 gint length, const guint8* value_ptr)
2209 proto_item *pi;
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);
2219 return pi;
2222 proto_item *
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, ...)
2228 proto_item *pi;
2229 va_list ap;
2231 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2232 if (pi != tree) {
2233 va_start(ap, format);
2234 proto_tree_set_representation_value(pi, format, ap);
2235 va_end(ap);
2238 return pi;
2241 proto_item *
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, ...)
2246 proto_item *pi;
2247 va_list ap;
2249 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2250 if (pi != tree) {
2251 TRY_TO_FAKE_THIS_REPR(pi);
2253 va_start(ap, format);
2254 proto_tree_set_representation(pi, format, ap);
2255 va_end(ap);
2258 return pi;
2261 /* Set the FT_IPv6 value */
2262 static void
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);
2269 static void
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 */
2276 proto_item *
2277 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2278 gint length, const e_guid_t *value_ptr)
2280 proto_item *pi;
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);
2290 return pi;
2293 proto_item *
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, ...)
2299 proto_item *pi;
2300 va_list ap;
2302 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2303 if (pi != tree) {
2304 va_start(ap, format);
2305 proto_tree_set_representation_value(pi, format, ap);
2306 va_end(ap);
2309 return pi;
2312 proto_item *
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, ...)
2317 proto_item *pi;
2318 va_list ap;
2320 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2321 if (pi != tree) {
2322 TRY_TO_FAKE_THIS_REPR(pi);
2324 va_start(ap, format);
2325 proto_tree_set_representation(pi, format, ap);
2326 va_end(ap);
2329 return pi;
2332 /* Set the FT_GUID value */
2333 static void
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);
2340 static void
2341 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2342 const guint encoding)
2344 e_guid_t guid;
2346 tvb_get_guid(tvb, start, &guid, encoding);
2347 proto_tree_set_guid(fi, &guid);
2350 /* Add a FT_OID to a proto_tree */
2351 proto_item *
2352 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2353 gint length, const guint8* value_ptr)
2355 proto_item *pi;
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);
2365 return pi;
2368 proto_item *
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, ...)
2374 proto_item *pi;
2375 va_list ap;
2377 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2378 if (pi != tree) {
2379 va_start(ap, format);
2380 proto_tree_set_representation_value(pi, format, ap);
2381 va_end(ap);
2384 return pi;
2387 proto_item *
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, ...)
2392 proto_item *pi;
2393 va_list ap;
2395 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2396 if (pi != tree) {
2397 TRY_TO_FAKE_THIS_REPR(pi);
2399 va_start(ap, format);
2400 proto_tree_set_representation(pi, format, ap);
2401 va_end(ap);
2404 return pi;
2407 /* Set the FT_OID value */
2408 static void
2409 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2411 GByteArray *bytes;
2413 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
2415 bytes = g_byte_array_new();
2416 if (length > 0) {
2417 g_byte_array_append(bytes, value_ptr, length);
2419 fvalue_set(&fi->value, bytes, TRUE);
2422 static void
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);
2428 static void
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".
2440 static void
2441 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2442 guint length, const guint encoding)
2444 guint64 value = 0;
2445 guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
2447 if (encoding) {
2448 b += length;
2449 switch (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;
2459 break;
2461 } else {
2462 switch (length) {
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++;
2472 break;
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. */
2481 proto_item *
2482 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2483 gint length, const char* value)
2485 proto_item *pi;
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);
2496 return pi;
2499 proto_item *
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);
2507 proto_item *
2508 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2509 gint start, gint length, const char* value,
2510 const char *format,
2511 ...)
2513 proto_item *pi;
2514 va_list ap;
2516 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2517 if (pi != tree) {
2518 va_start(ap, format);
2519 proto_tree_set_representation_value(pi, format, ap);
2520 va_end(ap);
2523 return pi;
2526 proto_item *
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, ...)
2531 proto_item *pi;
2532 va_list ap;
2534 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2535 if (pi != tree) {
2536 TRY_TO_FAKE_THIS_REPR(pi);
2538 va_start(ap, format);
2539 proto_tree_set_representation(pi, format, ap);
2540 va_end(ap);
2543 return pi;
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.
2562 void
2563 proto_item_append_string(proto_item *pi, const char *str)
2565 field_info *fi;
2566 header_field_info *hfinfo;
2567 const gchar *old_str, *new_str;
2569 if (!pi)
2570 return;
2571 if (!*str)
2572 return;
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 */
2580 return;
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);
2586 else
2587 new_str = str;
2588 fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2591 /* Set the FT_STRING value */
2592 static void
2593 proto_tree_set_string(field_info *fi, const char* value)
2595 if (value) {
2596 fvalue_set(&fi->value, (gpointer) value, FALSE);
2597 } else {
2598 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2602 static void
2603 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2605 gchar *string;
2607 if (length == -1) {
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 */
2617 proto_item *
2618 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2619 const guint8* value)
2621 proto_item *pi;
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);
2631 return pi;
2634 /* Set the FT_AX25 value */
2635 static void
2636 proto_tree_set_ax25(field_info *fi, const guint8* value)
2638 fvalue_set(&fi->value, (gpointer) value, FALSE);
2641 static void
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 */
2648 static void
2649 proto_tree_set_vines(field_info *fi, const guint8* value)
2651 fvalue_set(&fi->value, (gpointer) value, FALSE);
2654 static void
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 */
2661 proto_item *
2662 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2663 gint length, const guint8* value)
2665 proto_item *pi;
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);
2675 return pi;
2678 proto_item *
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, ...)
2683 proto_item *pi;
2684 va_list ap;
2686 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2687 if (pi != tree) {
2688 va_start(ap, format);
2689 proto_tree_set_representation_value(pi, format, ap);
2690 va_end(ap);
2693 return pi;
2696 proto_item *
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, ...)
2701 proto_item *pi;
2702 va_list ap;
2704 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2705 if (pi != tree) {
2706 TRY_TO_FAKE_THIS_REPR(pi);
2708 va_start(ap, format);
2709 proto_tree_set_representation(pi, format, ap);
2710 va_end(ap);
2713 return pi;
2716 /* Set the FT_ETHER value */
2717 static void
2718 proto_tree_set_ether(field_info *fi, const guint8* value)
2720 fvalue_set(&fi->value, (gpointer) value, FALSE);
2723 static void
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 */
2730 proto_item *
2731 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2732 gint length, guint32 value)
2734 proto_item *pi;
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);
2744 return pi;
2747 proto_item *
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, ...)
2752 proto_item *pi;
2753 va_list ap;
2755 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2756 if (pi != tree) {
2757 va_start(ap, format);
2758 proto_tree_set_representation_value(pi, format, ap);
2759 va_end(ap);
2762 return pi;
2765 proto_item *
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, ...)
2770 proto_item *pi;
2771 va_list ap;
2773 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2774 if (pi != tree) {
2775 TRY_TO_FAKE_THIS_REPR(pi);
2777 va_start(ap, format);
2778 proto_tree_set_representation(pi, format, ap);
2779 va_end(ap);
2782 return pi;
2785 /* Set the FT_BOOLEAN value */
2786 static void
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 */
2793 proto_item *
2794 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2795 gint length, float value)
2797 proto_item *pi;
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);
2807 return pi;
2810 proto_item *
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, ...)
2815 proto_item *pi;
2816 va_list ap;
2818 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2819 if (pi != tree) {
2820 va_start(ap, format);
2821 proto_tree_set_representation_value(pi, format, ap);
2822 va_end(ap);
2825 return pi;
2828 proto_item *
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, ...)
2833 proto_item *pi;
2834 va_list ap;
2836 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2837 if (pi != tree) {
2838 TRY_TO_FAKE_THIS_REPR(pi);
2840 va_start(ap, format);
2841 proto_tree_set_representation(pi, format, ap);
2842 va_end(ap);
2845 return pi;
2848 /* Set the FT_FLOAT value */
2849 static void
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 */
2856 proto_item *
2857 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2858 gint length, double value)
2860 proto_item *pi;
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);
2870 return pi;
2873 proto_item *
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, ...)
2878 proto_item *pi;
2879 va_list ap;
2881 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2882 if (pi != tree) {
2883 va_start(ap, format);
2884 proto_tree_set_representation_value(pi, format, ap);
2885 va_end(ap);
2888 return pi;
2891 proto_item *
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, ...)
2896 proto_item *pi;
2897 va_list ap;
2899 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2900 if (pi != tree) {
2901 TRY_TO_FAKE_THIS_REPR(pi);
2903 va_start(ap, format);
2904 proto_tree_set_representation(pi, format, ap);
2905 va_end(ap);
2908 return pi;
2911 /* Set the FT_DOUBLE value */
2912 static void
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 */
2919 proto_item *
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) {
2929 case FT_UINT8:
2930 case FT_UINT16:
2931 case FT_UINT24:
2932 case FT_UINT32:
2933 case FT_FRAMENUM:
2934 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2935 proto_tree_set_uint(PNODE_FINFO(pi), value);
2936 break;
2938 default:
2939 DISSECTOR_ASSERT_NOT_REACHED();
2942 return pi;
2945 proto_item *
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, ...)
2950 proto_item *pi;
2951 va_list ap;
2953 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2954 if (pi != tree) {
2955 va_start(ap, format);
2956 proto_tree_set_representation_value(pi, format, ap);
2957 va_end(ap);
2960 return pi;
2963 proto_item *
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, ...)
2968 proto_item *pi;
2969 va_list ap;
2971 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2972 if (pi != tree) {
2973 TRY_TO_FAKE_THIS_REPR(pi);
2975 va_start(ap, format);
2976 proto_tree_set_representation(pi, format, ap);
2977 va_end(ap);
2980 return pi;
2983 /* Set the FT_UINT{8,16,24,32} value */
2984 static void
2985 proto_tree_set_uint(field_info *fi, guint32 value)
2987 header_field_info *hfinfo;
2988 guint32 integer;
2990 hfinfo = fi->hfinfo;
2991 integer = value;
2993 if (hfinfo->bitmask) {
2994 /* Mask out irrelevant portions */
2995 integer &= hfinfo->bitmask;
2997 /* Shift bits */
2998 integer >>= hfinfo_bitshift(hfinfo);
3001 fvalue_set_uinteger(&fi->value, integer);
3004 /* Add FT_UINT64 to a proto_tree */
3005 proto_item *
3006 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3007 gint length, guint64 value)
3009 proto_item *pi;
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);
3019 return pi;
3022 proto_item *
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, ...)
3027 proto_item *pi;
3028 va_list ap;
3030 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3031 if (pi != tree) {
3032 va_start(ap, format);
3033 proto_tree_set_representation_value(pi, format, ap);
3034 va_end(ap);
3037 return pi;
3040 proto_item *
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, ...)
3045 proto_item *pi;
3046 va_list ap;
3048 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3049 if (pi != tree) {
3050 TRY_TO_FAKE_THIS_REPR(pi);
3052 va_start(ap, format);
3053 proto_tree_set_representation(pi, format, ap);
3054 va_end(ap);
3057 return pi;
3060 /* Add FT_INT{8,16,24,32} to a proto_tree */
3061 proto_item *
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) {
3071 case FT_INT8:
3072 case FT_INT16:
3073 case FT_INT24:
3074 case FT_INT32:
3075 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3076 proto_tree_set_int(PNODE_FINFO(pi), value);
3077 break;
3079 default:
3080 DISSECTOR_ASSERT_NOT_REACHED();
3083 return pi;
3086 proto_item *
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, ...)
3091 proto_item *pi;
3092 va_list ap;
3094 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3095 if (pi != tree) {
3096 va_start(ap, format);
3097 proto_tree_set_representation_value(pi, format, ap);
3098 va_end(ap);
3101 return pi;
3104 proto_item *
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, ...)
3109 proto_item *pi;
3110 va_list ap;
3112 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3113 if (pi != tree) {
3114 TRY_TO_FAKE_THIS_REPR(pi);
3116 va_start(ap, format);
3117 proto_tree_set_representation(pi, format, ap);
3118 va_end(ap);
3121 return pi;
3124 /* Set the FT_INT{8,16,24,32} value */
3125 static void
3126 proto_tree_set_int(field_info *fi, gint32 value)
3128 header_field_info *hfinfo;
3129 guint32 integer;
3130 gint no_of_bits;
3132 hfinfo = fi->hfinfo;
3133 integer = (guint32) value;
3135 if (hfinfo->bitmask) {
3136 /* Mask out irrelevant portions */
3137 integer &= hfinfo->bitmask;
3139 /* Shift bits */
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 */
3151 proto_item *
3152 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3153 gint length, gint64 value)
3155 proto_item *pi;
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);
3165 return pi;
3168 proto_item *
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, ...)
3173 proto_item *pi;
3174 va_list ap;
3176 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3177 if (pi != tree) {
3178 va_start(ap, format);
3179 proto_tree_set_representation_value(pi, format, ap);
3180 va_end(ap);
3183 return pi;
3186 proto_item *
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, ...)
3191 proto_item *pi;
3192 va_list ap;
3194 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3195 if (pi != tree) {
3196 TRY_TO_FAKE_THIS_REPR(pi);
3198 va_start(ap, format);
3199 proto_tree_set_representation(pi, format, ap);
3200 va_end(ap);
3203 return pi;
3205 /* Add a FT_EUI64 to a proto_tree */
3206 proto_item *
3207 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3208 gint length, const guint64 value)
3210 proto_item *pi;
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);
3220 return pi;
3223 proto_item *
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, ...)
3228 proto_item *pi;
3229 va_list ap;
3231 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3232 if (pi != tree) {
3233 va_start(ap, format);
3234 proto_tree_set_representation_value(pi, format, ap);
3235 va_end(ap);
3238 return pi;
3241 proto_item *
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, ...)
3246 proto_item *pi;
3247 va_list ap;
3249 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3250 if (pi != tree) {
3251 TRY_TO_FAKE_THIS_REPR(pi);
3253 va_start(ap, format);
3254 proto_tree_set_representation(pi, format, ap);
3255 va_end(ap);
3258 return pi;
3261 /* Set the FT_EUI64 value */
3262 static void
3263 proto_tree_set_eui64(field_info *fi, const guint64 value)
3265 fvalue_set_integer64(&fi->value, value);
3267 static void
3268 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3270 if (encoding)
3272 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3273 } else {
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 */
3279 static proto_item *
3280 proto_tree_add_node(proto_tree *tree, field_info *fi)
3282 proto_node *pnode, *tnode, *sibling;
3283 field_info *tfi;
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
3292 * was expanded.
3294 tnode = tree;
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;
3312 } else
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 */
3324 static proto_item *
3325 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3326 gint *length)
3328 proto_item *pi;
3329 field_info *fi;
3331 fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3332 pi = proto_tree_add_node(tree, fi);
3334 return pi;
3338 static void
3339 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3340 gint *item_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
3362 * the tvbuff".
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
3369 * FT_PROTOCOL)
3371 * 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
3379 * or
3381 * 3) the field is defined to be "what's left in the
3382 * packet"
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) {
3397 case FT_PROTOCOL:
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
3407 * exception.
3409 *length = tvb_length_remaining(tvb, start);
3410 if (*length < 0) {
3412 * Use "tvb_ensure_bytes_exist()"
3413 * to force the appropriate exception
3414 * to be thrown.
3416 tvb_ensure_bytes_exist(tvb, start, 0);
3418 DISSECTOR_ASSERT(*length >= 0);
3419 break;
3421 case FT_NONE:
3422 case FT_BYTES:
3423 case FT_STRING:
3424 *length = tvb_ensure_length_remaining(tvb, start);
3425 DISSECTOR_ASSERT(*length >= 0);
3426 break;
3428 case FT_STRINGZ:
3430 * Leave the length as -1, so our caller knows
3431 * it was -1.
3433 break;
3435 default:
3436 DISSECTOR_ASSERT_NOT_REACHED();
3438 *item_length = *length;
3439 } else {
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? */
3453 if (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);
3467 static field_info *
3468 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3469 const gint start, const gint item_length)
3471 field_info *fi;
3473 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
3475 fi->hfinfo = hfinfo;
3476 fi->start = start;
3477 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3478 fi->length = item_length;
3479 fi->tree_type = -1;
3480 fi->flags = 0;
3481 if (!PTREE_DATA(tree)->visible)
3482 FI_SET_FLAG(fi, FI_HIDDEN);
3483 fvalue_init(&fi->value, fi->hfinfo->type);
3484 fi->rep = NULL;
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;
3492 return fi;
3495 static field_info *
3496 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3497 gint *length)
3499 gint item_length;
3501 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3502 return new_field_info(tree, hfinfo, tvb, start, item_length);
3505 static void
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
3519 argument list. */
3520 static void
3521 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3523 g_assert(pi);
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)) {
3528 int ret = 0;
3529 field_info *fi = PITEM_FINFO(pi);
3530 header_field_info *hf;
3532 DISSECTOR_ASSERT(fi);
3534 hf = fi->hfinfo;
3536 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3537 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3538 guint32 val;
3539 char *p;
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. */
3569 static void
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,
3580 format, ap);
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);
3590 static int
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)
3596 res = dest_size;
3597 return (int) res;
3600 static header_field_info *
3601 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
3603 if (hfinfo->same_name_prev_id == -1)
3604 return NULL;
3605 return proto_registrar_get_nth(hfinfo->same_name_prev_id);
3608 /* -------------------------- */
3609 const gchar *
3610 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3611 gchar *result, gchar *expr, const int size)
3613 guint32 number;
3614 guint8 *bytes;
3615 ipv4_addr *ipv4;
3616 struct e_in6_addr *ipv6;
3617 address addr;
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;
3623 GPtrArray *finfos;
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 ? */
3637 if (!hfinfo)
3638 return "";
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);
3647 while (hfinfo) {
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;
3653 } else {
3654 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3656 continue;
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;
3663 } else {
3664 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3666 prev_len += len;
3667 continue;
3670 /* Calculate single index or set outer bounderies */
3671 if (occurrence < 0) {
3672 i = occurrence + len + prev_len;
3673 last = i;
3674 } else if (occurrence > 0) {
3675 i = occurrence - 1 - prev_len;
3676 last = i;
3677 } else {
3678 i = 0;
3679 last = len - 1;
3682 prev_len += len; /* Count handled occurrences */
3684 while (i <= last) {
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) {
3697 result[0] = '\0';
3698 } else if (result[offset_r-1] == ',') {
3699 result[offset_r-1] = '\0';
3701 break;
3703 case FT_PROTOCOL:
3704 /* prevent multiple "yes" entries by setting result directly */
3705 g_strlcpy(result, "Yes", size);
3706 break;
3708 case FT_UINT_BYTES:
3709 case FT_BYTES:
3710 bytes = (guint8 *)fvalue_get(&finfo->value);
3711 offset_r += protoo_strlcpy(result+offset_r,
3712 bytes_to_str(bytes,
3713 fvalue_length(&finfo->value)),
3714 size-offset_r);
3715 break;
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),
3721 size-offset_r);
3722 break;
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)),
3727 size-offset_r);
3728 break;
3730 case FT_BOOLEAN:
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,
3737 number ?
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);
3743 break;
3745 /* XXX - make these just FT_NUMBER? */
3746 case FT_INT8:
3747 case FT_INT16:
3748 case FT_INT24:
3749 case FT_INT32:
3750 case FT_UINT8:
3751 case FT_UINT16:
3752 case FT_UINT24:
3753 case FT_UINT32:
3754 case FT_FRAMENUM:
3755 hf_str_val = NULL;
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);
3772 if (!number_out)
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);
3777 } else {
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);
3785 } else {
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);
3792 break;
3794 case FT_INT64:
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);
3800 break;
3801 case FT_UINT64:
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);
3807 break;
3808 case FT_EUI64:
3809 offset_r += protoo_strlcpy(result+offset_r,
3810 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3811 size-offset_r);
3812 break;
3814 case FT_IPv4:
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),
3819 size-offset_r);
3820 break;
3822 case FT_IPv6:
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);
3827 break;
3829 case FT_ETHER:
3830 offset_r += protoo_strlcpy(result+offset_r,
3831 bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
3832 FT_ETHER_LEN, ':'),
3833 size-offset_r);
3834 break;
3836 case FT_GUID:
3837 offset_r += protoo_strlcpy(result+offset_r,
3838 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3839 size-offset_r);
3840 break;
3842 case FT_REL_OID:
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)),
3847 size-offset_r);
3848 offset_e += protoo_strlcpy(expr+offset_e,
3849 rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3850 size-offset_e);
3851 break;
3853 case FT_OID:
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)),
3858 size-offset_r);
3859 offset_e += protoo_strlcpy(expr+offset_e,
3860 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3861 size-offset_e);
3862 break;
3864 case FT_FLOAT:
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);
3868 break;
3870 case FT_DOUBLE:
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);
3874 break;
3876 case FT_STRING:
3877 case FT_STRINGZ:
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)),
3882 size-offset_r);
3883 break;
3885 case FT_IPXNET: /*XXX really No column custom ?*/
3886 case FT_PCRE:
3887 default:
3888 g_error("hfinfo->type %d (%s) not handled\n",
3889 hfinfo->type,
3890 ftype_name(hfinfo->type));
3891 DISSECTOR_ASSERT_NOT_REACHED();
3892 break;
3894 i++;
3897 switch (hfinfo->type) {
3899 case FT_BOOLEAN:
3900 case FT_UINT8:
3901 case FT_UINT16:
3902 case FT_UINT24:
3903 case FT_UINT32:
3904 case FT_FRAMENUM:
3905 case FT_INT8:
3906 case FT_INT16:
3907 case FT_INT24:
3908 case FT_INT32:
3909 case FT_OID:
3910 case FT_REL_OID:
3911 /* for these types, "expr" is filled in the loop above */
3912 break;
3914 default:
3915 /* for all others, just copy "result" to "expr" */
3916 g_strlcpy(expr, result, size);
3917 break;
3920 if (!abbrev) {
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);
3928 } else {
3929 hfinfo = NULL;
3933 return abbrev ? abbrev : "";
3937 /* Set text of proto_item after having already been created. */
3938 void
3939 proto_item_set_text(proto_item *pi, const char *format, ...)
3941 field_info *fi = NULL;
3942 va_list ap;
3944 if (pi == NULL) {
3945 return;
3948 fi = PITEM_FINFO(pi);
3949 if (fi == NULL)
3950 return;
3952 if (fi->rep) {
3953 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
3954 fi->rep = NULL;
3957 va_start(ap, format);
3958 proto_tree_set_representation(pi, format, ap);
3959 va_end(ap);
3962 /* Append to text of proto_item after having already been created. */
3963 void
3964 proto_item_append_text(proto_item *pi, const char *format, ...)
3966 field_info *fi = NULL;
3967 size_t curlen;
3968 va_list ap;
3970 if (pi == NULL) {
3971 return;
3974 fi = PITEM_FINFO(pi);
3975 if (fi == NULL) {
3976 return;
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);
3994 va_end(ap);
3999 /* Prepend to text of proto_item after having already been created. */
4000 void
4001 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4003 field_info *fi = NULL;
4004 char representation[ITEM_LABEL_LENGTH];
4005 va_list ap;
4007 if (pi == NULL) {
4008 return;
4011 fi = PITEM_FINFO(pi);
4012 if (fi == NULL) {
4013 return;
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);
4024 } else
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);
4030 va_end(ap);
4031 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4035 void
4036 proto_item_set_len(proto_item *pi, const gint length)
4038 field_info *fi;
4040 if (pi == NULL)
4041 return;
4043 fi = PITEM_FINFO(pi);
4044 if (fi == NULL)
4045 return;
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
4064 * of that tvbuff.
4066 void
4067 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4069 field_info *fi;
4071 if (pi == NULL)
4072 return;
4074 fi = PITEM_FINFO(pi);
4075 if (fi == NULL)
4076 return;
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;
4090 proto_tree *
4091 proto_tree_create_root(packet_info *pinfo)
4093 proto_node *pnode;
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. */
4126 void
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;
4152 proto_tree *
4153 proto_item_add_subtree(proto_item *pi, const gint idx) {
4154 field_info *fi;
4156 if (!pi)
4157 return NULL;
4159 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4161 fi = PITEM_FINFO(pi);
4162 if (!fi)
4163 return (proto_tree *)pi;
4165 fi->tree_type = idx;
4167 return (proto_tree *)pi;
4170 proto_tree *
4171 proto_item_get_subtree(const proto_item *pi) {
4172 field_info *fi;
4174 if (!pi)
4175 return NULL;
4176 fi = PITEM_FINFO(pi);
4177 if ( (!fi) || (fi->tree_type == -1) )
4178 return NULL;
4179 return (proto_tree *)pi;
4182 proto_item *
4183 proto_item_get_parent(const proto_item *ti) {
4184 if (!ti)
4185 return NULL;
4186 return ti->parent;
4189 proto_item *
4190 proto_item_get_parent_nth(proto_item *ti, int gen) {
4191 if (!ti)
4192 return NULL;
4193 while (gen--) {
4194 ti = ti->parent;
4195 if (!ti)
4196 return NULL;
4198 return ti;
4202 proto_item *
4203 proto_tree_get_parent(const proto_tree *tree) {
4204 if (!tree)
4205 return NULL;
4206 return (proto_item *)tree;
4209 proto_tree *
4210 proto_tree_get_root(proto_tree *tree) {
4211 if (!tree)
4212 return NULL;
4213 while (tree->parent) {
4214 tree = tree->parent;
4216 return tree;
4219 void
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)
4230 return;
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);
4243 } else {
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) {
4248 break;
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;
4270 void
4271 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4272 const gint length)
4274 field_info *fi;
4276 if (tree == NULL)
4277 return;
4279 fi = PTREE_FINFO(tree);
4280 if (fi == NULL)
4281 return;
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;
4297 int proto_id;
4298 char *existing_name;
4299 gint *key;
4300 guint i;
4301 guchar c;
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++) {
4340 c = filter_name[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;
4384 return proto_id;
4387 void
4388 proto_mark_private(const int proto_id)
4390 protocol_t *protocol = find_protocol_by_id(proto_id);
4391 if (protocol)
4392 protocol->is_private = TRUE;
4395 gboolean
4396 proto_is_private(const int proto_id)
4398 protocol_t *protocol = find_protocol_by_id(proto_id);
4399 if (protocol)
4400 return protocol->is_private;
4401 else
4402 return FALSE;
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
4409 * the list.
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)
4418 return -1;
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)
4441 return -1;
4442 *cookie = list_item;
4443 protocol = (protocol_t *)list_item->data;
4444 return protocol->proto_id;
4447 header_field_info *
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))
4453 return NULL;
4455 *cookie = protocol->fields;
4456 return (header_field_info *)protocol->fields->data;
4459 header_field_info *
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)
4466 return NULL;
4468 *cookie = list_item;
4469 return (header_field_info *)list_item->data;
4472 protocol_t *
4473 find_protocol_by_id(const int proto_id)
4475 header_field_info *hfinfo;
4477 if (proto_id < 0)
4478 return NULL;
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;
4495 if(!filter_name){
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)
4503 return -1;
4504 return protocol->proto_id;
4507 const char *
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)
4515 return NULL;
4516 return protocol->name;
4519 const char *
4520 proto_get_protocol_short_name(const protocol_t *protocol)
4522 if (protocol == NULL)
4523 return "(none)";
4524 return protocol->short_name;
4527 const char *
4528 proto_get_protocol_long_name(const protocol_t *protocol)
4530 if (protocol == NULL)
4531 return "(none)";
4532 return protocol->name;
4535 const char *
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)
4542 return "(none)";
4543 return protocol->filter_name;
4546 gboolean
4547 proto_is_protocol_enabled(const protocol_t *protocol)
4549 return protocol->is_enabled;
4552 gboolean
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;
4561 void
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;
4571 void
4572 proto_enable_all(void)
4574 protocol_t *protocol;
4575 GList *list_item = protocols;
4577 if (protocols == NULL)
4578 return;
4580 while (list_item) {
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);
4588 void
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;
4597 static int
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;
4604 } else {
4605 proto->last_field =
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 */
4615 void
4616 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4618 hf_register_info *ptr = hf;
4619 protocol_t *proto;
4620 int i;
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) {
4633 fprintf(stderr,
4634 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4635 ptr->hfinfo.abbrev);
4636 return;
4639 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
4643 void
4644 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
4646 int i;
4647 protocol_t *proto;
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) {
4655 fprintf(stderr,
4656 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4657 hfi[i].abbrev);
4658 return;
4661 proto_register_field_common(proto, &hfi[i], parent);
4665 void
4666 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
4668 int i;
4669 protocol_t *proto;
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) {
4677 fprintf(stderr,
4678 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4679 hfi[i]->abbrev);
4680 return;
4683 proto_register_field_common(proto, hfi[i], parent);
4687 /* unregister already registered fields */
4688 void
4689 proto_unregister_field (const int parent, gint hf_id)
4691 hf_register_info *hf;
4692 protocol_t *proto;
4693 GSList *field;
4695 if (hf_id == -1 || hf_id == 0)
4696 return;
4698 proto = find_protocol_by_id (parent);
4699 if (!proto || !proto->fields) {
4700 return;
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);
4711 break;
4716 /* chars allowed in field abbrev */
4717 static
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" },
4770 { 0, NULL } };
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" },
4797 { 0, NULL } };
4799 /* temporary function containing assert part for easier profiling */
4800 static void
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]) {
4806 if (hfinfo->abbrev)
4807 /* Try to identify the field */
4808 g_error("Field (abbrev='%s') does not have a name\n",
4809 hfinfo->abbrev);
4810 else
4811 /* Hum, no luck */
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. */
4843 #if 0
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) )) {
4861 int n, m;
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));
4867 else
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)) {
4874 break;
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);
4891 #endif
4894 switch (hfinfo->type) {
4896 case FT_INT8:
4897 case FT_INT16:
4898 case FT_INT24:
4899 case FT_INT32:
4900 case FT_INT64:
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) {
4907 case BASE_HEX:
4908 case BASE_OCT:
4909 case BASE_DEC_HEX:
4910 case BASE_HEX_DEC:
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)"));
4916 /* FALL THROUGH */
4917 case FT_UINT8:
4918 case FT_UINT16:
4919 case FT_UINT24:
4920 case FT_UINT32:
4921 case FT_UINT64:
4922 /* Require integral types (other than frame number,
4923 * which is always displayed in decimal) to have a
4924 * number base.
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) {
4930 case BASE_DEC:
4931 case BASE_HEX:
4932 case BASE_OCT:
4933 case BASE_DEC_HEX:
4934 case BASE_HEX_DEC:
4935 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
4936 break;
4937 default:
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)"));
4944 break;
4946 case FT_PROTOCOL:
4947 case FT_FRAMENUM:
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)"));
4957 break;
4959 case FT_BOOLEAN:
4960 break;
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)"));
4974 break;
4976 default:
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)"));
4990 break;
4994 static void
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)
5015 static int
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);
5030 } else {
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;
5038 gpa_hfinfo.len++;
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;
5045 guchar c;
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);
5050 if (c) {
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;
5089 return hfinfo->id;
5092 void
5093 proto_register_subtree_array(gint *const *indices, const int num_indices)
5095 int i;
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++) {
5125 if (**ptr != -1) {
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;
5136 static inline gsize
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);
5142 return pos;
5145 static void
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
5153 * ^^^^^ name_pos
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);
5166 static gsize
5167 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5169 gsize name_pos;
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);
5181 return pos;
5184 static gsize
5185 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5187 gsize name_pos;
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);
5202 return pos;
5205 void
5206 proto_item_fill_label(field_info *fi, gchar *label_str)
5208 header_field_info *hfinfo;
5209 guint8 *bytes;
5210 guint32 integer;
5211 guint64 integer64;
5212 ipv4_addr *ipv4;
5213 e_guid_t *guid;
5214 guint32 n_addr; /* network-order IPv4 address */
5215 const gchar *name;
5216 address addr;
5218 if (!fi) {
5219 if (label_str)
5220 label_str[0]= '\0';
5221 /* XXX: Check validity of hfinfo->type */
5222 return;
5225 hfinfo = fi->hfinfo;
5227 switch (hfinfo->type) {
5228 case FT_NONE:
5229 case FT_PROTOCOL:
5230 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5231 break;
5233 case FT_BOOLEAN:
5234 fill_label_boolean(fi, label_str);
5235 break;
5237 case FT_BYTES:
5238 case FT_UINT_BYTES:
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>");
5242 break;
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
5250 case FT_UINT8:
5251 case FT_UINT16:
5252 case FT_UINT24:
5253 case FT_UINT32:
5254 if (hfinfo->bitmask) {
5255 fill_label_bitfield(fi, label_str, FALSE);
5256 } else {
5257 fill_label_number(fi, label_str, FALSE);
5259 break;
5261 case FT_FRAMENUM:
5262 fill_label_number(fi, label_str, FALSE);
5263 break;
5265 case FT_UINT64:
5266 fill_label_number64(fi, label_str, FALSE);
5267 break;
5269 case FT_INT8:
5270 case FT_INT16:
5271 case FT_INT24:
5272 case FT_INT32:
5273 if (hfinfo->bitmask) {
5274 fill_label_bitfield(fi, label_str, TRUE);
5275 } else {
5276 fill_label_number(fi, label_str, TRUE);
5278 break;
5280 case FT_INT64:
5281 fill_label_number64(fi, label_str, TRUE);
5282 break;
5284 case FT_FLOAT:
5285 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5286 "%s: %." G_STRINGIFY(FLT_DIG) "g",
5287 hfinfo->name, fvalue_get_floating(&fi->value));
5288 break;
5290 case FT_DOUBLE:
5291 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5292 "%s: %." G_STRINGIFY(DBL_DIG) "g",
5293 hfinfo->name, fvalue_get_floating(&fi->value));
5294 break;
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));
5300 break;
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)));
5306 break;
5308 case FT_IPXNET:
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);
5313 break;
5315 case FT_AX25:
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));
5320 break;
5322 case FT_VINES:
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 ));
5330 break;
5332 case FT_ETHER:
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));
5337 break;
5339 case FT_IPv4:
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));
5345 break;
5347 case FT_IPv6:
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));
5352 break;
5354 case FT_GUID:
5355 guid = (e_guid_t *)fvalue_get(&fi->value);
5356 label_fill(label_str, 0, hfinfo, guid_to_str(guid));
5357 break;
5359 case FT_OID:
5360 bytes = (guint8 *)fvalue_get(&fi->value);
5361 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5362 if (name) {
5363 label_fill_descr(label_str, 0, hfinfo,
5364 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5365 } else {
5366 label_fill(label_str, 0, hfinfo,
5367 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5369 break;
5371 case FT_REL_OID:
5372 bytes = (guint8 *)fvalue_get(&fi->value);
5373 name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5374 if (name) {
5375 label_fill_descr(label_str, 0, hfinfo,
5376 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5377 } else {
5378 label_fill(label_str, 0, hfinfo,
5379 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)));
5381 break;
5383 case FT_EUI64:
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));
5388 break;
5389 case FT_STRING:
5390 case FT_STRINGZ:
5391 case FT_UINT_STRING:
5392 bytes = (guint8 *)fvalue_get(&fi->value);
5393 label_fill(label_str, 0, hfinfo, format_text(bytes, strlen(bytes)));
5394 break;
5396 default:
5397 g_error("hfinfo->type %d (%s) not handled\n",
5398 hfinfo->type, ftype_name(hfinfo->type));
5399 DISSECTOR_ASSERT_NOT_REACHED();
5400 break;
5404 static void
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;
5410 guint32 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);
5424 /* Un-shift bits */
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);
5437 static const char *
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);
5452 static const char *
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()
5464 never returns? */
5465 return NULL;
5468 static const char *
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;
5476 static const char *
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 */
5485 static void
5486 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
5488 char *p;
5489 int bitfield_byte_length, bitwidth;
5490 guint32 unshifted_value;
5491 guint32 value;
5493 char buf[32];
5494 const char *out;
5496 header_field_info *hfinfo = fi->hfinfo;
5498 /* Figure out the bit width */
5499 bitwidth = hfinfo_bitwidth(hfinfo);
5501 /* Un-shift bits */
5502 if (is_signed)
5503 unshifted_value = fvalue_get_sinteger(&fi->value);
5504 else
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);
5531 else
5532 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
5534 else {
5535 out = hfinfo_number_value_format(hfinfo, buf, value);
5537 label_fill(label_str, bitfield_byte_length, hfinfo, out);
5541 static void
5542 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
5544 header_field_info *hfinfo = fi->hfinfo;
5545 guint32 value;
5547 char buf[32];
5548 const char *out;
5550 if (is_signed)
5551 value = fvalue_get_sinteger(&fi->value);
5552 else
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);
5570 else
5571 label_fill_descr(label_str, 0, hfinfo, val_str, out);
5573 else {
5574 out = hfinfo_number_value_format(hfinfo, buf, value);
5576 label_fill(label_str, 0, hfinfo, out);
5580 static void
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;
5585 guint64 value;
5586 char tmp[ITEM_LABEL_LENGTH+1];
5588 /* Pick the proper format string */
5589 if (is_signed)
5590 format = hfinfo_int64_format(hfinfo);
5591 else
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);
5599 else
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);
5608 else {
5609 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
5612 else {
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)
5626 int bitwidth = 0;
5628 if (!hfinfo->bitmask) {
5629 return 0;
5632 switch (hfinfo->type) {
5633 case FT_UINT8:
5634 case FT_INT8:
5635 bitwidth = 8;
5636 break;
5637 case FT_UINT16:
5638 case FT_INT16:
5639 bitwidth = 16;
5640 break;
5641 case FT_UINT24:
5642 case FT_INT24:
5643 bitwidth = 24;
5644 break;
5645 case FT_UINT32:
5646 case FT_INT32:
5647 bitwidth = 32;
5648 break;
5649 case FT_BOOLEAN:
5650 bitwidth = hfinfo->display; /* hacky? :) */
5651 break;
5652 default:
5653 DISSECTOR_ASSERT_NOT_REACHED();
5656 return bitwidth;
5659 static int
5660 _hfinfo_type_hex_octet(int type)
5662 switch (type) {
5663 case FT_INT8:
5664 case FT_UINT8:
5665 return 2;
5667 case FT_UINT16:
5668 case FT_INT16:
5669 return 4;
5671 case FT_UINT24:
5672 case FT_INT24:
5673 return 6;
5675 case FT_UINT32:
5676 case FT_INT32:
5677 return 8;
5679 default:
5680 DISSECTOR_ASSERT_NOT_REACHED();
5683 return -1;
5686 static const char *
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);
5692 *ptr = '\0';
5693 /* Properly format value */
5694 switch (display) {
5695 case BASE_DEC:
5696 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5698 case BASE_DEC_HEX:
5699 *(--ptr) = ')';
5700 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5701 *(--ptr) = '(';
5702 *(--ptr) = ' ';
5703 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5704 return ptr;
5706 case BASE_OCT:
5707 return oct_to_str_back(ptr, value);
5709 case BASE_HEX:
5710 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5712 case BASE_HEX_DEC:
5713 *(--ptr) = ')';
5714 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5715 *(--ptr) = '(';
5716 *(--ptr) = ' ';
5717 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5718 return ptr;
5720 default:
5721 DISSECTOR_ASSERT_NOT_REACHED();
5724 return ptr;
5727 static const char *
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.
5736 display = BASE_DEC;
5739 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5742 static const char *
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.
5752 display = BASE_DEC;
5755 switch (display) {
5756 case BASE_NONE:
5757 /* case BASE_DEC: */
5758 case BASE_DEC_HEX:
5759 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5760 case BASE_CUSTOM:
5761 display = BASE_DEC;
5762 break;
5764 /* case BASE_HEX: */
5765 case BASE_HEX_DEC:
5766 display = BASE_HEX;
5767 break;
5770 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5773 static const char *
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)
5780 return NULL;
5782 if (display == BASE_DEC_HEX)
5783 display = BASE_DEC;
5784 if (display == BASE_HEX_DEC)
5785 display = BASE_HEX;
5787 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5790 static const char *
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) {
5797 case BASE_DEC:
5798 format = "%" G_GINT64_MODIFIER "u";
5799 break;
5800 case BASE_DEC_HEX:
5801 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5802 break;
5803 case BASE_OCT: /* I'm lazy */
5804 format = "%#" G_GINT64_MODIFIER "o";
5805 break;
5806 case BASE_HEX:
5807 format = "0x%016" G_GINT64_MODIFIER "x";
5808 break;
5809 case BASE_HEX_DEC:
5810 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5811 break;
5812 default:
5813 DISSECTOR_ASSERT_NOT_REACHED();
5816 return format;
5819 static const char *
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) {
5826 case BASE_DEC:
5827 format = "%" G_GINT64_MODIFIER "d";
5828 break;
5829 case BASE_DEC_HEX:
5830 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
5831 break;
5832 case BASE_OCT: /* I'm lazy */
5833 format = "%#" G_GINT64_MODIFIER "o";
5834 break;
5835 case BASE_HEX:
5836 format = "0x%016" G_GINT64_MODIFIER "x";
5837 break;
5838 case BASE_HEX_DEC:
5839 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5840 break;
5841 default:
5842 DISSECTOR_ASSERT_NOT_REACHED();
5845 return format;
5849 proto_registrar_n(void)
5851 return gpa_hfinfo.len;
5854 const char *
5855 proto_registrar_get_name(const int n)
5857 header_field_info *hfinfo;
5859 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5860 return hfinfo->name;
5863 const char *
5864 proto_registrar_get_abbrev(const int n)
5866 header_field_info *hfinfo;
5868 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
5869 return hfinfo->abbrev;
5872 enum ftenum
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;
5890 gboolean
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. */
5903 gint
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. */
5914 gboolean
5915 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
5917 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
5919 if (!ptrs) {
5920 return FALSE;
5922 else if (g_ptr_array_len(ptrs) > 0) {
5923 return TRUE;
5925 else {
5926 return FALSE;
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()
5934 * handles that. */
5935 GPtrArray *
5936 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
5938 if (!tree)
5939 return NULL;
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));
5944 else
5945 return NULL;
5948 gboolean
5949 proto_tracking_interesting_fields(const proto_tree *tree)
5951 if (!tree)
5952 return FALSE;
5954 return (PTREE_DATA(tree)->interesting_hfids != NULL);
5957 /* Helper struct for proto_find_info() and proto_all_finfos() */
5958 typedef struct {
5959 GPtrArray *array;
5960 int id;
5961 } ffdata_t;
5963 /* Helper function for proto_find_info() */
5964 static gboolean
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. */
5975 return FALSE;
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).
5984 GPtrArray *
5985 proto_find_finfo(proto_tree *tree, const int id)
5987 ffdata_t ffdata;
5989 ffdata.array = g_ptr_array_new();
5990 ffdata.id = id;
5992 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
5994 return ffdata.array;
5997 /* Helper function for proto_all_finfos() */
5998 static gboolean
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. */
6007 return FALSE;
6010 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6011 GPtrArray *
6012 proto_all_finfos(proto_tree *tree)
6014 ffdata_t ffdata;
6016 ffdata.array = g_ptr_array_new();
6017 ffdata.id = 0;
6019 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6021 return ffdata.array;
6025 typedef struct {
6026 guint offset;
6027 field_info *finfo;
6028 tvbuff_t *tvb;
6029 } offset_search_t;
6031 static gboolean
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.
6056 * (yeah right) */
6057 field_info *
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
6073 * whatever.
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
6081 void
6082 proto_registrar_dump_protocols(void)
6084 protocol_t *protocol;
6085 int i;
6086 void *cookie = NULL;
6089 i = proto_get_first_protocol(&cookie);
6090 while (i != -1) {
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.
6109 * Value Strings
6110 * -------------
6111 * Field 1 = 'V'
6112 * Field 2 = Field abbreviation to which this value string corresponds
6113 * Field 3 = Integer value
6114 * Field 4 = String
6116 * Extended Value String Headers
6117 * -----------------------------
6118 * Field 1 = 'E'
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"
6124 * Range Strings
6125 * -------------
6126 * Field 1 = 'R'
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
6130 * Field 5 = String
6132 * True/False Strings
6133 * ------------------
6134 * Field 1 = 'T'
6135 * Field 2 = Field abbreviation to which this true/false string corresponds
6136 * Field 3 = True String
6137 * Field 4 = False String
6139 void
6140 proto_registrar_dump_values(void)
6142 header_field_info *hfinfo;
6143 int i, len, vi;
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) {
6154 continue;
6157 /* ignore protocols */
6158 if (proto_registrar_is_protocol(i)) {
6159 continue;
6161 /* process header fields */
6162 else {
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
6173 * for all lengths.)
6175 if (hfinfo->same_name_prev_id != -1)
6176 continue;
6178 vals = NULL;
6179 vals64 = NULL;
6180 range = NULL;
6181 tfs = NULL;
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;
6202 } else {
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? */
6212 if (vals) {
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);
6217 continue;
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",
6221 hfinfo->abbrev,
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));
6226 vi = 0;
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",
6231 hfinfo->abbrev,
6232 vals[vi].value,
6233 vals[vi].strptr);
6235 else {
6236 printf("V\t%s\t%u\t%s\n",
6237 hfinfo->abbrev,
6238 vals[vi].value,
6239 vals[vi].strptr);
6241 vi++;
6244 else if (vals64) {
6245 vi = 0;
6246 while (vals64[vi].strptr) {
6247 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6248 hfinfo->abbrev,
6249 vals64[vi].value,
6250 vals64[vi].strptr);
6251 vi++;
6255 /* print range strings? */
6256 else if (range) {
6257 vi = 0;
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",
6262 hfinfo->abbrev,
6263 range[vi].value_min,
6264 range[vi].value_max,
6265 range[vi].strptr);
6267 else {
6268 printf("R\t%s\t%u\t%u\t%s\n",
6269 hfinfo->abbrev,
6270 range[vi].value_min,
6271 range[vi].value_max,
6272 range[vi].strptr);
6274 vi++;
6278 /* Print true/false strings? */
6279 else if (tfs) {
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
6289 * whatever.
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.
6294 * Protocols
6295 * ---------
6296 * Field 1 = 'P'
6297 * Field 2 = descriptive protocol name
6298 * Field 3 = protocol abbreviation
6300 * Header Fields
6301 * -------------
6302 * Field 1 = 'F'
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
6311 void
6312 proto_registrar_dump_fields(void)
6314 header_field_info *hfinfo, *parent_hfinfo;
6315 int i, len;
6316 const char *enum_name;
6317 const char *base_name;
6318 const char *blurb;
6319 char width[5];
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)
6330 continue;
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 */
6337 else {
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
6348 * for all lengths.)
6350 if (hfinfo->same_name_prev_id != -1)
6351 continue;
6353 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6355 enum_name = ftype_name(hfinfo->type);
6356 base_name = "";
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) {
6370 case BASE_NONE:
6371 base_name = "BASE_NONE";
6372 break;
6373 case BASE_DEC:
6374 base_name = "BASE_DEC";
6375 break;
6376 case BASE_HEX:
6377 base_name = "BASE_HEX";
6378 break;
6379 case BASE_OCT:
6380 base_name = "BASE_OCT";
6381 break;
6382 case BASE_DEC_HEX:
6383 base_name = "BASE_DEC_HEX";
6384 break;
6385 case BASE_HEX_DEC:
6386 base_name = "BASE_HEX_DEC";
6387 break;
6388 case BASE_CUSTOM:
6389 base_name = "BASE_CUSTOM";
6390 break;
6391 default:
6392 base_name = "????";
6393 break;
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);
6398 base_name = width;
6401 blurb = hfinfo->blurb;
6402 if (blurb == NULL)
6403 blurb = "";
6404 else if (strlen(blurb) == 0)
6405 blurb = "\"\"";
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
6416 * whatever.
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"
6423 void
6424 proto_registrar_dump_ftypes(void)
6426 int fte;
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));
6433 static const char *
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) {
6440 case BASE_DEC:
6441 case BASE_DEC_HEX:
6442 case BASE_OCT: /* I'm lazy */
6443 case BASE_CUSTOM:
6444 switch (hfinfo->type) {
6445 case FT_UINT64:
6446 format = "%s == %" G_GINT64_MODIFIER "u";
6447 break;
6448 case FT_INT64:
6449 format = "%s == %" G_GINT64_MODIFIER "d";
6450 break;
6451 default:
6452 DISSECTOR_ASSERT_NOT_REACHED();
6455 break;
6456 case BASE_HEX:
6457 case BASE_HEX_DEC:
6458 switch (hfinfo->type) {
6459 case FT_UINT64:
6460 case FT_INT64:
6461 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6462 break;
6463 default:
6464 DISSECTOR_ASSERT_NOT_REACHED();
6467 break;
6468 default:
6469 DISSECTOR_ASSERT_NOT_REACHED();
6472 return format;
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.
6483 static gboolean
6484 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6485 char **filter)
6487 header_field_info *hfinfo;
6488 int abbrev_len;
6489 char *ptr;
6490 int buf_len;
6491 int dfilter_len, i;
6492 gint start, length, length_remaining;
6493 guint8 c;
6494 gchar is_signed_num = FALSE;
6496 if (!finfo)
6497 return 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) {
6508 case FT_INT8:
6509 case FT_INT16:
6510 case FT_INT24:
6511 case FT_INT32:
6512 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
6513 break;
6515 case FT_UINT8:
6516 case FT_UINT16:
6517 case FT_UINT24:
6518 case FT_UINT32:
6519 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
6520 break;
6522 default:
6523 break;
6526 if (str != NULL && filter != NULL) {
6527 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6528 return TRUE;
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) {
6554 case FT_INT8:
6555 case FT_INT16:
6556 case FT_INT24:
6557 case FT_INT32:
6558 is_signed_num = TRUE;
6559 /* FALLTHRU */
6560 case FT_UINT8:
6561 case FT_UINT16:
6562 case FT_UINT24:
6563 case FT_UINT32:
6564 case FT_FRAMENUM:
6565 if (filter != NULL) {
6566 guint32 number;
6568 char buf[32];
6569 const char *out;
6571 if (is_signed_num)
6572 number = fvalue_get_sinteger(&finfo->value);
6573 else
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);
6580 break;
6582 case FT_INT64:
6583 case FT_UINT64:
6584 if (filter != NULL) {
6585 const char *format = hfinfo_numeric_format(hfinfo);
6587 *filter = ep_strdup_printf(format,
6588 hfinfo->abbrev,
6589 fvalue_get_integer64(&finfo->value));
6591 break;
6593 case FT_PROTOCOL:
6594 if (filter != NULL)
6595 *filter = ep_strdup(finfo->hfinfo->abbrev);
6596 break;
6598 case FT_NONE:
6600 * If the length is 0, just match the name of the
6601 * field.
6603 * (Also check for negative values, just in case,
6604 * as we'll cast it to an unsigned value later.)
6606 length = finfo->length;
6607 if (length == 0) {
6608 if (filter != NULL)
6609 *filter = ep_strdup(finfo->hfinfo->abbrev);
6610 break;
6612 if (length < 0)
6613 return FALSE;
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".
6622 if (edt == NULL)
6623 return FALSE;
6626 * Is this field part of the raw frame tvbuff?
6627 * If not, we can't use "frame[N:M]" to match
6628 * it.
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;
6645 if (length <= 0)
6646 return FALSE;
6648 if (filter != NULL) {
6649 start = finfo->start;
6650 buf_len = 32 + length * 3;
6651 *filter = (char *)ep_alloc0(buf_len);
6652 ptr = *filter;
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);
6658 start++;
6659 if (i == 0 ) {
6660 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6662 else {
6663 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6667 break;
6669 case FT_PCRE:
6670 /* FT_PCRE never appears as a type for a registered field. It is
6671 * only used internally. */
6672 DISSECTOR_ASSERT_NOT_REACHED();
6673 break;
6675 /* By default, use the fvalue's "to_string_repr" method. */
6676 default:
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,
6684 FTREPR_DFILTER);
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 == ",
6690 hfinfo->abbrev);
6691 fvalue_to_string_repr(&finfo->value,
6692 FTREPR_DFILTER,
6693 &(*filter)[abbrev_len + 4]);
6695 break;
6698 return TRUE;
6702 * Returns TRUE if we can do a "match selected" on the field, FALSE
6703 * otherwise.
6705 gboolean
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.
6719 char *
6720 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6722 char *filter;
6724 if (!construct_match_selected_string(finfo, edt, &filter))
6725 return NULL;
6726 return 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".
6739 static gboolean
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,
6743 gboolean first)
6745 guint32 value = 0;
6746 guint32 available_bits = 0;
6747 guint32 tmpval;
6748 proto_tree *tree = NULL;
6749 header_field_info *hf;
6751 switch (len) {
6752 case 1:
6753 value = tvb_get_guint8(tvb, offset);
6754 available_bits = 0xFF;
6755 break;
6756 case 2:
6757 value = encoding ? tvb_get_letohs(tvb, offset) :
6758 tvb_get_ntohs(tvb, offset);
6759 available_bits = 0xFFFF;
6760 break;
6761 case 3:
6762 value = encoding ? tvb_get_letoh24(tvb, offset) :
6763 tvb_get_ntoh24(tvb, offset);
6764 available_bits = 0xFFFFFF;
6765 break;
6766 case 4:
6767 value = encoding ? tvb_get_letohl(tvb, offset) :
6768 tvb_get_ntohl(tvb, offset);
6769 available_bits = 0xFFFFFFFF;
6770 break;
6771 default:
6772 g_assert_not_reached();
6775 tree = proto_item_add_subtree(item, ett);
6776 while (*fields) {
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) {
6784 fields++;
6785 continue;
6788 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
6789 if (flags & BMT_NO_APPEND) {
6790 fields++;
6791 continue;
6793 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
6795 switch (hf->type) {
6796 case FT_INT8:
6797 case FT_UINT8:
6798 case FT_INT16:
6799 case FT_UINT16:
6800 case FT_INT24:
6801 case FT_UINT24:
6802 case FT_INT32:
6803 case FT_UINT32:
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 ? "" : ", ",
6811 hf->name, lbl);
6812 first = FALSE;
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"));
6817 first = FALSE;
6819 else if (!(flags & BMT_NO_INT)) {
6820 char buf[32];
6821 const char *out;
6823 if (!first) {
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);
6829 first = FALSE;
6832 break;
6833 case FT_BOOLEAN:
6834 if (hf->strings && !(flags & BMT_NO_TFS)) {
6835 /* If we have true/false strings, emit full - otherwise messages
6836 might look weird */
6837 const struct true_false_string *tfs =
6838 (const struct true_false_string *)hf->strings;
6840 if (tmpval) {
6841 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6842 hf->name, tfs->true_string);
6843 first = FALSE;
6844 } else if (!(flags & BMT_NO_FALSE)) {
6845 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6846 hf->name, tfs->false_string);
6847 first = FALSE;
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);
6852 first = FALSE;
6854 break;
6855 default:
6856 g_assert_not_reached();
6859 fields++;
6862 return first;
6865 /* This function will dissect a sequence of bytes that describe a
6866 * bitmask.
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.
6881 proto_item *
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;
6889 int len;
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);
6895 if (parent_tree) {
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);
6901 return item;
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.
6915 proto_item *
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);
6940 if (parent_tree) {
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,
6946 decodable_value);
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);
6956 if (item) {
6957 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
6958 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
6961 return item;
6964 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
6965 proto_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;
6974 if (parent_tree) {
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);
6983 return item;
6986 proto_item *
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;
6992 gint octet_length;
6993 gint octet_offset;
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.
7016 static proto_item *
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)
7021 gint offset;
7022 guint length;
7023 guint8 tot_no_bits;
7024 char *bf_str;
7025 char lbl_str[ITEM_LABEL_LENGTH];
7026 guint64 value = 0;
7028 proto_item *pi;
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);
7055 } else {
7056 DISSECTOR_ASSERT_NOT_REACHED();
7057 return NULL;
7060 /* Sign extend for signed types */
7061 switch (hf_field->type) {
7062 case FT_INT8:
7063 case FT_INT16:
7064 case FT_INT24:
7065 case FT_INT32:
7066 case FT_INT64:
7067 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7068 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7069 break;
7071 default:
7072 break;
7075 if (return_value) {
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) {
7085 case FT_BOOLEAN:
7086 /* Boolean field */
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,
7091 "%s = %s: %s",
7092 bf_str, hf_field->name,
7093 (guint32)value ? tfstring->true_string : tfstring->false_string);
7094 break;
7096 case FT_UINT8:
7097 case FT_UINT16:
7098 case FT_UINT24:
7099 case FT_UINT32:
7100 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7101 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7102 break;
7104 case FT_INT8:
7105 case FT_INT16:
7106 case FT_INT24:
7107 case FT_INT32:
7108 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7109 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7110 break;
7112 case FT_UINT64:
7113 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7114 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7115 break;
7117 case FT_INT64:
7118 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7119 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7120 break;
7122 default:
7123 DISSECTOR_ASSERT_NOT_REACHED();
7124 return NULL;
7125 break;
7128 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7129 return pi;
7132 proto_item *
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)
7137 proto_item *pi;
7138 gint no_of_bits;
7139 gint octet_offset;
7140 guint mask_initial_bit_offset;
7141 guint mask_greatest_bit_offset;
7142 guint octet_length;
7143 guint8 i;
7144 char *bf_str;
7145 char lbl_str[ITEM_LABEL_LENGTH];
7146 guint64 value;
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;
7165 no_of_bits = 0;
7166 value = 0;
7167 i = 0;
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,
7180 ENC_BIG_ENDIAN);
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) {
7207 case FT_INT8:
7208 case FT_INT16:
7209 case FT_INT24:
7210 case FT_INT32:
7211 case FT_INT64:
7212 if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
7213 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7214 break;
7215 default:
7216 break;
7219 if (return_value) {
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);
7228 bf_str[0] = '\0';
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? */
7247 /* Boolean field */
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,
7253 "%s = %s: %s",
7254 bf_str, hf_field->name,
7255 (guint32)value ? tfstring->true_string : tfstring->false_string);
7256 break;
7258 case FT_UINT8:
7259 case FT_UINT16:
7260 case FT_UINT24:
7261 case FT_UINT32:
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);
7264 break;
7266 case FT_INT8:
7267 case FT_INT16:
7268 case FT_INT24:
7269 case FT_INT32:
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);
7272 break;
7274 case FT_UINT64:
7275 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7276 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7277 break;
7279 case FT_INT64:
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);
7282 break;
7284 default:
7285 DISSECTOR_ASSERT_NOT_REACHED();
7286 return NULL;
7287 break;
7289 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7290 return pi;
7293 void
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,
7301 bit_offset >> 3,
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,
7305 tvb_get_bits(tvb,
7306 bit_offset,
7307 crumb_spec[crumb_index].crumb_bit_length,
7308 ENC_BIG_ENDIAN)),
7309 crumb_index,
7310 hfinfo->name);
7313 proto_item *
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)
7318 proto_item *item;
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));
7326 return item;
7329 static proto_item *
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,
7333 gchar *value_str)
7335 gint offset;
7336 guint length;
7337 guint8 tot_no_bits;
7338 char *str;
7339 guint64 value = 0;
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)
7364 length++;
7366 if (no_of_bits < 65) {
7367 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7368 } else {
7369 DISSECTOR_ASSERT_NOT_REACHED();
7370 return NULL;
7373 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7375 strcat(str, " = ");
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) {
7386 case FT_BOOLEAN:
7387 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7388 "%s: %s", str, value_str);
7389 break;
7391 case FT_UINT8:
7392 case FT_UINT16:
7393 case FT_UINT24:
7394 case FT_UINT32:
7395 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7396 "%s: %s", str, value_str);
7397 break;
7399 case FT_UINT64:
7400 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
7401 "%s: %s", str, value_str);
7402 break;
7404 case FT_INT8:
7405 case FT_INT16:
7406 case FT_INT24:
7407 case FT_INT32:
7408 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
7409 "%s: %s", str, value_str);
7410 break;
7412 case FT_INT64:
7413 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
7414 "%s: %s", str, value_str);
7415 break;
7417 case FT_FLOAT:
7418 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
7419 "%s: %s", str, value_str);
7420 break;
7422 default:
7423 DISSECTOR_ASSERT_NOT_REACHED();
7424 return NULL;
7425 break;
7429 static proto_item *
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,
7433 gchar *value_str)
7435 proto_item *item;
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));
7443 return item;
7446 #define CREATE_VALUE_STRING(dst,format,ap) \
7447 va_start(ap, format); \
7448 dst = ep_strdup_vprintf(format, ap); \
7449 va_end(ap);
7451 proto_item *
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, ...)
7457 va_list ap;
7458 gchar *dst;
7459 header_field_info *hf_field;
7461 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7463 switch (hf_field->type) {
7464 case FT_UINT8:
7465 case FT_UINT16:
7466 case FT_UINT24:
7467 case FT_UINT32:
7468 break;
7470 default:
7471 DISSECTOR_ASSERT_NOT_REACHED();
7472 return NULL;
7473 break;
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);
7481 proto_item *
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, ...)
7487 va_list ap;
7488 gchar *dst;
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);
7500 proto_item *
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, ...)
7506 va_list ap;
7507 gchar *dst;
7508 header_field_info *hf_field;
7510 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7512 switch (hf_field->type) {
7513 case FT_INT8:
7514 case FT_INT16:
7515 case FT_INT24:
7516 case FT_INT32:
7517 break;
7519 default:
7520 DISSECTOR_ASSERT_NOT_REACHED();
7521 return NULL;
7522 break;
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);
7530 proto_item *
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, ...)
7536 va_list ap;
7537 gchar *dst;
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);
7549 guchar
7550 proto_check_field_name(const gchar *field_name)
7552 return wrs_check_charset(fld_abbrev_chars, field_name);
7555 gboolean
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));
7562 void
7563 tree_expanded_set(int tree_type, gboolean value)
7565 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7567 if (value)
7568 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
7569 else
7570 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
7574 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7576 * Local variables:
7577 * c-basic-offset: 8
7578 * tab-width: 8
7579 * indent-tabs-mode: t
7580 * End:
7582 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7583 * :indentSize=8:tabSize=8:noTabs=false: