2 * Routines for protocol tree
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include "ptvcursor.h"
38 #include "addr_resolv.h"
39 #include "oid_resolv.h"
42 #include "epan_dissect.h"
53 #define cVALS(x) (const value_string*)(x)
56 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) \
57 /* If this item is not referenced we dont have to do much work \
58 at all but we should still return a node so that \
59 field items below this node ( think proto_item_add_subtree() )\
60 will still have somewhere to attach to \
61 or else filtering will not work (they would be ignored since tree\
63 DONT try to fake a node where PITEM_FINFO(pi) is NULL \
64 since dissectors that want to do proto_item_set_len() ot \
65 other operations that dereference this would crash. \
66 We dont fake FT_PROTOCOL either since these are cheap and \
67 some stuff (proto hier stat) assumes they always exist. \
69 if(!(PTREE_DATA(tree)->visible)){ \
70 if(PITEM_FINFO(tree)){ \
71 register header_field_info *hfinfo; \
72 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
73 if((hfinfo->ref_count == 0) \
74 && (hfinfo->type!=FT_PROTOCOL)){ \
75 /* just return tree back to the caller */\
81 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex) ;
85 proto_tree_free_node(proto_node *node, gpointer data);
87 static void fill_label_boolean(field_info *fi, gchar *label_str);
88 static void fill_label_uint(field_info *fi, gchar *label_str);
89 static void fill_label_uint64(field_info *fi, gchar *label_str);
90 static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
91 static void fill_label_enumerated_bitfield(field_info *fi, gchar *label_str);
92 static void fill_label_numeric_bitfield(field_info *fi, gchar *label_str);
93 static void fill_label_int(field_info *fi, gchar *label_str);
94 static void fill_label_int64(field_info *fi, gchar *label_str);
95 static void fill_label_enumerated_int(field_info *fi, gchar *label_str);
97 int hfinfo_bitwidth(header_field_info *hfinfo);
98 static const char* hfinfo_uint_vals_format(header_field_info *hfinfo);
99 static const char* hfinfo_uint_format(header_field_info *hfinfo);
100 static const char* hfinfo_uint64_format(header_field_info *hfinfo);
101 static const char* hfinfo_int_vals_format(header_field_info *hfinfo);
102 static const char* hfinfo_int_format(header_field_info *hfinfo);
103 static const char* hfinfo_int64_format(header_field_info *hfinfo);
106 proto_tree_add_node(proto_tree *tree, field_info *fi);
108 static header_field_info *
109 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
113 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
114 gint start, gint item_length);
117 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb,
118 gint start, gint *length);
121 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb,
122 gint start, gint *length, field_info **pfi);
125 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
128 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
130 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
132 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
134 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
136 proto_tree_set_string(field_info *fi, const char* value, gboolean);
138 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
140 proto_tree_set_ether(field_info *fi, const guint8* value);
142 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
144 proto_tree_set_ipxnet(field_info *fi, guint32 value);
146 proto_tree_set_ipv4(field_info *fi, guint32 value);
148 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
150 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start);
152 proto_tree_set_guid(field_info *fi, const guint8* value_ptr);
154 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
156 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
158 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
160 proto_tree_set_boolean(field_info *fi, guint32 value);
162 proto_tree_set_float(field_info *fi, float value);
164 proto_tree_set_double(field_info *fi, double value);
166 proto_tree_set_uint(field_info *fi, guint32 value);
168 proto_tree_set_int(field_info *fi, gint32 value);
170 proto_tree_set_uint64(field_info *fi, guint64 value);
172 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
174 static int proto_register_field_init(header_field_info *hfinfo, int parent);
176 /* Comparision function for tree insertion. A wrapper around strcmp() */
177 static int g_strcmp(gconstpointer a, gconstpointer b);
179 /* special-case header field used within proto.c */
180 int hf_text_only = -1;
182 /* Structure for information about a protocol */
184 const char *name; /* long description */
185 const char *short_name; /* short description */
186 const char *filter_name; /* name of this protocol in filters */
187 int proto_id; /* field ID for this protocol */
188 GList *fields; /* fields for this protocol */
189 GList *last_field; /* pointer to end of list of fields */
190 gboolean is_enabled; /* TRUE if protocol is enabled */
191 gboolean can_toggle; /* TRUE if is_enabled can be changed */
194 /* List of all protocols */
195 static GList *protocols = NULL;
197 #define INITIAL_NUM_PROTOCOL_HFINFO 200
200 /* Contains information about protocols and header fields. Used when
201 * dissectors register their data */
202 static GMemChunk *gmc_hfinfo = NULL;
204 /* Contains information about a field when a dissector calls
205 * proto_tree_add_item. */
206 SLAB_ITEM_TYPE_DEFINE(field_info)
207 static SLAB_FREE_LIST_DEFINE(field_info)
208 static field_info *field_info_tmp=NULL;
209 #define FIELD_INFO_NEW(fi) \
210 SLAB_ALLOC(fi, field_info)
211 #define FIELD_INFO_FREE(fi) \
212 SLAB_FREE(fi, field_info)
216 /* Contains the space for proto_nodes. */
217 SLAB_ITEM_TYPE_DEFINE(proto_node)
218 static SLAB_FREE_LIST_DEFINE(proto_node)
219 #define PROTO_NODE_NEW(node) \
220 SLAB_ALLOC(node, proto_node) \
221 node->first_child = NULL; \
222 node->last_child = NULL; \
225 #define PROTO_NODE_FREE(node) \
226 SLAB_FREE(node, proto_node)
230 /* String space for protocol and field items for the GUI */
231 SLAB_ITEM_TYPE_DEFINE(item_label_t)
232 static SLAB_FREE_LIST_DEFINE(item_label_t)
233 #define ITEM_LABEL_NEW(il) \
234 SLAB_ALLOC(il, item_label_t)
235 #define ITEM_LABEL_FREE(il) \
236 SLAB_FREE(il, item_label_t)
239 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
240 DISSECTOR_ASSERT((guint)hfindex < gpa_hfinfo.len); \
241 hfinfo=gpa_hfinfo.hfi[hfindex];
244 /* List which stores protocols and fields that have been registered */
245 typedef struct _gpa_hfinfo_t {
247 guint32 allocated_len;
248 header_field_info **hfi;
250 gpa_hfinfo_t gpa_hfinfo;
252 /* Balanced tree of abbreviations and IDs */
253 static GTree *gpa_name_tree = NULL;
255 /* Points to the first element of an array of Booleans, indexed by
256 a subtree item type; that array element is TRUE if subtrees of
257 an item of that type are to be expanded. */
258 gboolean *tree_is_expanded;
260 /* Number of elements in that array. */
263 /* Name hashtables for fast detection of duplicate names */
264 static GHashTable* proto_names = NULL;
265 static GHashTable* proto_short_names = NULL;
266 static GHashTable* proto_filter_names = NULL;
269 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
271 const protocol_t *p1 = p1_arg;
272 const protocol_t *p2 = p2_arg;
274 return g_strcasecmp(p1->short_name, p2->short_name);
278 /* initialize data structures and register protocols and fields */
280 proto_init(const char *plugin_dir
285 void (register_all_protocols)(void),
286 void (register_all_protocol_handoffs)(void))
288 static hf_register_info hf[] = {
290 { "", "", FT_NONE, BASE_NONE, NULL, 0x0,
295 proto_names = g_hash_table_new(g_int_hash, g_int_equal);
296 proto_short_names = g_hash_table_new(g_int_hash, g_int_equal);
297 proto_filter_names = g_hash_table_new(g_int_hash, g_int_equal);
301 gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
302 sizeof(header_field_info),
303 INITIAL_NUM_PROTOCOL_HFINFO * sizeof(header_field_info),
307 gpa_hfinfo.allocated_len=0;
309 gpa_name_tree = g_tree_new(g_strcmp);
311 /* Initialize the ftype subsystem */
314 /* Register one special-case FT_TEXT_ONLY field for use when
315 converting ethereal to new-style proto_tree. These fields
316 are merely strings on the GUI tree; they are not filterable */
317 proto_register_field_array(-1, hf, array_length(hf));
319 /* Have each built-in dissector register its protocols, fields,
320 dissector tables, and dissectors to be called through a
321 handle, and do whatever one-time initialization it needs to
323 register_all_protocols();
326 /* Now scan for plugins and load all the ones we find, calling
327 their register routines to do the stuff described above. */
328 init_plugins(plugin_dir);
331 /* Now call the "handoff registration" routines of all built-in
332 dissectors; those routines register the dissector in other
333 dissectors' handoff tables, and fetch any dissector handles
335 register_all_protocol_handoffs();
338 /* Now do the same with plugins. */
339 register_all_plugin_handoffs();
342 /* sort the protocols by protocol name */
343 protocols = g_list_sort(protocols, proto_compare_name);
345 /* We've assigned all the subtree type values; allocate the array
346 for them, and zero it out. */
347 tree_is_expanded = g_malloc(num_tree_types*sizeof (gboolean));
348 memset(tree_is_expanded, 0, num_tree_types*sizeof (gboolean));
351 /* String comparison func for dfilter_token GTree */
353 g_strcmp(gconstpointer a, gconstpointer b)
355 return strcmp((const char*)a, (const char*)b);
361 /* Free the abbrev/ID GTree */
363 g_tree_destroy(gpa_name_tree);
364 gpa_name_tree = NULL;
368 g_mem_chunk_destroy(gmc_hfinfo);
370 if(gpa_hfinfo.allocated_len){
372 gpa_hfinfo.allocated_len=0;
373 g_free(gpa_hfinfo.hfi);
376 if (tree_is_expanded != NULL)
377 g_free(tree_is_expanded);
381 typedef gboolean (*proto_tree_traverse_func)(proto_node *, gpointer);
384 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
387 proto_node *pnode = tree;
391 if (func(pnode, data))
394 child = pnode->first_child;
395 while (child != NULL) {
397 * The routine we call might modify the child, e.g. by
398 * freeing it, so we get the child's successor before
399 * calling that routine.
402 child = current->next;
403 if (proto_tree_traverse_pre_order((proto_tree *)current, func,
412 proto_tree_traverse_in_order(proto_tree *tree, proto_tree_traverse_func func,
415 proto_node *pnode = tree;
419 child = pnode->first_child;
422 * The routine we call might modify the child, e.g. by
423 * freeing it, so we get the child's successor before
424 * calling that routine.
427 child = current->next;
429 if (proto_tree_traverse_in_order((proto_tree *)current, func,
433 if (func(pnode, data))
436 while (child != NULL) {
438 * The routine we call might modify the child, e.g. by
439 * freeing it, so we get the child's successor before
440 * calling that routine.
443 child = current->next;
444 if (proto_tree_traverse_in_order((proto_tree *)current,
449 if (func(pnode, data))
457 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
460 proto_node *node = tree;
463 node = node->first_child;
464 while (node != NULL) {
466 node = current->next;
467 func((proto_tree *)current, data);
471 /* frees the resources that the dissection a proto_tree uses */
473 proto_tree_free(proto_tree *tree)
475 proto_tree_traverse_in_order(tree, proto_tree_free_node, NULL);
479 free_GPtrArray_value(gpointer key _U_, gpointer value, gpointer user_data _U_)
481 GPtrArray *ptrs = value;
482 gint hfid = (gint)key;
483 header_field_info *hfinfo;
486 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
487 if(hfinfo->ref_count){
488 /* when a field is referenced by a filter this also
489 affects the refcount for the parent protocol so we need
490 to adjust the refcount for the parent as well
492 if( (hfinfo->parent != -1) && (hfinfo->ref_count) ){
493 header_field_info *parent_hfinfo;
494 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
495 parent_hfinfo->ref_count -= hfinfo->ref_count;
497 hfinfo->ref_count = 0;
500 g_ptr_array_free(ptrs, TRUE);
504 free_node_tree_data(tree_data_t *tree_data)
506 /* Free all the GPtrArray's in the interesting_hfids hash. */
507 g_hash_table_foreach(tree_data->interesting_hfids,
508 free_GPtrArray_value, NULL);
510 /* And then destroy the hash. */
511 g_hash_table_destroy(tree_data->interesting_hfids);
513 /* And finally the tree_data_t itself. */
517 #define FREE_NODE_FIELD_INFO(finfo) \
519 ITEM_LABEL_FREE(finfo->rep); \
521 FVALUE_CLEANUP(&finfo->value); \
522 FIELD_INFO_FREE(finfo);
525 proto_tree_free_node(proto_node *node, gpointer data _U_)
527 field_info *finfo = PITEM_FINFO(node);
530 /* This is the root node. Destroy the per-tree data.
531 * There is no field_info to destroy. */
532 free_node_tree_data(PTREE_DATA(node));
535 /* This is a child node. Don't free the per-tree data, but
536 * do free the field_info data. */
537 FREE_NODE_FIELD_INFO(finfo);
540 /* Free the proto_node. */
541 PROTO_NODE_FREE(node);
543 return FALSE; /* FALSE = do not end traversal of protocol tree */
546 /* Is the parsing being done for a visible proto_tree or an invisible one?
547 * By setting this correctly, the proto_tree creation is sped up by not
548 * having to call g_vsnprintf and copy strings around.
551 proto_tree_set_visible(proto_tree *tree, gboolean visible)
553 PTREE_DATA(tree)->visible = visible;
556 /* Assume dissector set only its protocol fields.
557 This function is called by dissectors and allowes to speed up filtering
558 in ethereal, if this function returns FALSE it is safe to reset tree to NULL
559 and thus skip calling most of the expensive proto_tree_add_...()
561 If the tree is visible we implicitely assume the field is referenced.
564 proto_field_is_referenced(proto_tree *tree, int proto_id)
566 register header_field_info *hfinfo;
572 if (PTREE_DATA(tree)->visible)
575 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
576 if (hfinfo->ref_count != 0)
583 /* Finds a record in the hf_info_records array by id. */
585 proto_registrar_get_nth(guint hfindex)
587 register header_field_info *hfinfo;
589 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
593 /* Finds a record in the hf_info_records array by name.
596 proto_registrar_get_byname(const char *field_name)
598 DISSECTOR_ASSERT(field_name != NULL);
599 return g_tree_lookup(gpa_name_tree, field_name);
602 /* Allocates an initializes a ptvcursor_t with 3 variables:
603 * proto_tree, tvbuff, and offset. */
605 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
609 ptvc = g_new(ptvcursor_t, 1);
612 ptvc->offset = offset;
616 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
618 ptvcursor_free(ptvcursor_t *ptvc)
623 /* Returns tvbuff. */
625 ptvcursor_tvbuff(ptvcursor_t* ptvc)
630 /* Returns current offset. */
632 ptvcursor_current_offset(ptvcursor_t* ptvc)
638 ptvcursor_tree(ptvcursor_t* ptvc)
644 ptvcursor_set_tree(ptvcursor_t* ptvc, proto_tree *tree)
649 /* Add a text-only node, leaving it to our caller to fill the text in */
651 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
655 pi = proto_tree_add_pi(tree, hf_text_only, tvb, start, &length, NULL);
662 /* Add a text-only node to the proto_tree */
664 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
665 const char *format, ...)
670 pi = proto_tree_add_text_node(tree, tvb, start, length);
674 va_start(ap, format);
675 proto_tree_set_representation(pi, format, ap);
681 /* Add a text-only node to the proto_tree (va_list version) */
683 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
684 gint length, const char *format, va_list ap)
688 pi = proto_tree_add_text_node(tree, tvb, start, length);
692 proto_tree_set_representation(pi, format, ap);
697 /* Add a text-only node for debugging purposes. The caller doesn't need
698 * to worry about tvbuff, start, or length. Debug message gets sent to
701 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
706 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
710 va_start(ap, format);
711 proto_tree_set_representation(pi, format, ap);
721 get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
728 value = tvb_get_guint8(tvb, offset);
732 value = little_endian ? tvb_get_letohs(tvb, offset)
733 : tvb_get_ntohs(tvb, offset);
737 value = little_endian ? tvb_get_letoh24(tvb, offset)
738 : tvb_get_ntoh24(tvb, offset);
742 value = little_endian ? tvb_get_letohl(tvb, offset)
743 : tvb_get_ntohl(tvb, offset);
747 THROW(ReportedBoundsError);
755 get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
762 value = (gint8)tvb_get_guint8(tvb, offset);
766 value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
767 : tvb_get_ntohs(tvb, offset));
771 value = little_endian ? tvb_get_letoh24(tvb, offset)
772 : tvb_get_ntoh24(tvb, offset);
773 if (value & 0x00800000) {
774 /* Sign bit is set; sign-extend it. */
780 value = little_endian ? tvb_get_letohl(tvb, offset)
781 : tvb_get_ntohl(tvb, offset);
785 THROW(ReportedBoundsError);
792 /* Add an item to a proto_tree, using the text label registered to that item;
793 the item is extracted from the tvbuff handed to it. */
795 proto_tree_new_item(field_info *new_fi, proto_tree *tree, int hfindex,
796 tvbuff_t *tvb, gint start, gint length, gboolean little_endian)
806 /* there is a possibility here that we might raise an exception
807 * and thus would lose track of the field_info.
808 * store it in a temp so that if we come here again we can reclaim
809 * the field_info without leaking memory.
811 /* XXX this only keeps track of one field_info struct,
812 if we ever go multithreaded for calls to this function
813 we have to change this code to use per thread variable.
816 /* oops, last one we got must have been lost due
818 * good thing we saved it, now we can reverse the
819 * memory leak and reclaim it.
821 SLAB_FREE(field_info_tmp, field_info);
823 /* we might throw an exception, keep track of this one
824 * across the "dangerous" section below.
826 field_info_tmp=new_fi;
828 switch(new_fi->hfinfo->type) {
830 /* no value to set for FT_NONE */
834 proto_tree_set_protocol_tvb(new_fi, tvb);
838 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
842 n = get_uint_value(tvb, start, length, little_endian);
843 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
845 /* Instead of calling proto_item_set_len(), since we don't yet
846 * have a proto_item, we set the field_info's length ourselves. */
847 new_fi->length = n + length;
851 proto_tree_set_boolean(new_fi,
852 get_uint_value(tvb, start, length, little_endian));
855 /* XXX - make these just FT_UINT? */
860 proto_tree_set_uint(new_fi,
861 get_uint_value(tvb, start, length, little_endian));
866 DISSECTOR_ASSERT(length == 8);
867 proto_tree_set_uint64_tvb(new_fi, tvb, start, little_endian);
870 /* XXX - make these just FT_INT? */
875 proto_tree_set_int(new_fi,
876 get_int_value(tvb, start, length, little_endian));
880 DISSECTOR_ASSERT(length == 4);
881 value = tvb_get_ipv4(tvb, start);
882 proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
886 DISSECTOR_ASSERT(length == 4);
887 proto_tree_set_ipxnet(new_fi,
888 get_uint_value(tvb, start, 4, FALSE));
892 DISSECTOR_ASSERT(length == 16);
893 proto_tree_set_ipv6_tvb(new_fi, tvb, start);
897 DISSECTOR_ASSERT(length == 6);
898 proto_tree_set_ether_tvb(new_fi, tvb, start);
902 DISSECTOR_ASSERT(length == 16);
903 proto_tree_set_guid_tvb(new_fi, tvb, start);
907 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
911 DISSECTOR_ASSERT(length == 4);
913 floatval = tvb_get_letohieee_float(tvb, start);
915 floatval = tvb_get_ntohieee_float(tvb, start);
916 proto_tree_set_float(new_fi, floatval);
920 DISSECTOR_ASSERT(length == 8);
922 doubleval = tvb_get_letohieee_double(tvb, start);
924 doubleval = tvb_get_ntohieee_double(tvb, start);
925 proto_tree_set_double(new_fi, doubleval);
929 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
930 proto_tree_set_string_tvb(new_fi, tvb, start, length);
934 DISSECTOR_ASSERT(length >= -1);
935 /* Instead of calling proto_item_set_len(),
936 * since we don't yet have a proto_item, we
937 * set the field_info's length ourselves.
939 * XXX - our caller can't use that length to
940 * advance an offset unless they arrange that
941 * there always be a protocol tree into which
942 * we're putting this item.
945 /* This can throw an exception */
946 length = tvb_strsize(tvb, start);
948 /* This g_malloc'ed memory is freed
949 in proto_tree_free_node() */
950 string = g_malloc(length);
952 tvb_memcpy(tvb, string, start, length);
953 } else if (length == 0) {
954 string = g_strdup("[Empty]");
956 /* In this case, length signifies
957 * the length of the string.
959 * This could either be a null-padded
960 * string, which doesn't necessarily
961 * have a '\0' at the end, or a
962 * null-terminated string, with a
963 * trailing '\0'. (Yes, there are
964 * cases where you have a string
965 * that's both counted and null-
968 * In the first case, we must
969 * allocate a buffer of length
970 * "length+1", to make room for
973 * In the second case, we don't
974 * assume that there is a trailing
975 * '\0' there, as the packet might
976 * be malformed. (XXX - should we
977 * throw an exception if there's no
978 * trailing '\0'?) Therefore, we
979 * allocate a buffer of length
980 * "length+1", and put in a trailing
981 * '\0', just to be safe.
983 * (XXX - this would change if
984 * we made string values counted
985 * rather than null-terminated.)
988 /* This g_malloc'ed memory is freed
989 * in proto_tree_free_node() */
990 string = tvb_get_string(tvb, start,
993 new_fi->length = length;
994 proto_tree_set_string(new_fi, string, TRUE);
998 /* This g_strdup'ed memory is freed in proto_tree_free_node() */
999 n = get_uint_value(tvb, start, length, little_endian);
1000 proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
1002 /* Instead of calling proto_item_set_len(), since we
1003 * don't yet have a proto_item, we set the
1004 * field_info's length ourselves.
1006 * XXX - our caller can't use that length to
1007 * advance an offset unless they arrange that
1008 * there always be a protocol tree into which
1009 * we're putting this item.
1011 new_fi->length = n + length;
1015 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1016 new_fi->hfinfo->type,
1017 ftype_name(new_fi->hfinfo->type));
1018 DISSECTOR_ASSERT_NOT_REACHED();
1022 /* Don't add new node to proto_tree until now so that any exceptions
1023 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1024 pi = proto_tree_add_node(tree, new_fi);
1026 /* we did not raise an exception so we dont have to remember this
1027 * field_info struct any more.
1029 field_info_tmp=NULL;
1031 /* If the proto_tree wants to keep a record of this finfo
1032 * for quick lookup, then record it. */
1033 if (new_fi->hfinfo->ref_count) {
1034 hash = PTREE_DATA(tree)->interesting_hfids;
1035 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
1037 g_ptr_array_add(ptrs, new_fi);
1044 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1045 and returns proto_item* */
1047 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1048 gboolean little_endian)
1051 header_field_info *hfinfo;
1056 offset = ptvc->offset;
1057 hfinfo = get_hfi_and_length(hfindex, ptvc->tvb, offset, &length,
1059 ptvc->offset += length;
1060 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1062 * The length of the rest of the item is in the first N
1063 * bytes of the item.
1065 n = get_uint_value(ptvc->tvb, offset, length, little_endian);
1068 if (ptvc->tree == NULL)
1071 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex);
1073 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset,
1078 return proto_tree_new_item(new_fi, ptvc->tree, hfindex, ptvc->tvb,
1079 offset, length, little_endian);
1082 /* Add an item to a proto_tree, using the text label registered to that item;
1083 the item is extracted from the tvbuff handed to it. */
1085 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1086 gint start, gint length, gboolean little_endian)
1093 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1095 new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
1100 return proto_tree_new_item(new_fi, tree, hfindex, tvb, start,
1101 length, little_endian);
1105 proto_tree_add_item_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1106 gint start, gint length, gboolean little_endian)
1110 pi = proto_tree_add_item(tree, hfindex, tvb, start, length, little_endian);
1114 PROTO_ITEM_SET_HIDDEN(pi);
1120 /* Add a FT_NONE to a proto_tree */
1122 proto_tree_add_none_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1123 gint length, const char *format, ...)
1127 header_field_info *hfinfo;
1132 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1133 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1135 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, NULL);
1137 va_start(ap, format);
1138 proto_tree_set_representation(pi, format, ap);
1141 /* no value to set for FT_NONE */
1145 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1146 * offset, and returns proto_item* */
1148 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1149 gboolean endianness)
1153 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1154 length, endianness);
1159 /* Advance the ptvcursor's offset within its tvbuff without
1160 * adding anything to the proto_tree. */
1162 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1164 ptvc->offset += length;
1169 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1171 fvalue_set(&fi->value, tvb, TRUE);
1174 /* Add a FT_PROTOCOL to a proto_tree */
1176 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1177 gint length, const char *format, ...)
1181 header_field_info *hfinfo;
1187 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1188 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1190 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1192 va_start(ap, format);
1193 proto_tree_set_representation(pi, format, ap);
1197 proto_tree_set_protocol_tvb(new_fi, tvb);
1200 proto_tree_set_protocol_tvb(new_fi, NULL);
1206 /* Add a FT_BYTES to a proto_tree */
1208 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1209 gint length, const guint8 *start_ptr)
1213 header_field_info *hfinfo;
1218 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1220 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1221 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
1223 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1224 proto_tree_set_bytes(new_fi, start_ptr, length);
1230 proto_tree_add_bytes_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1231 gint length, const guint8 *start_ptr)
1235 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1239 PROTO_ITEM_SET_HIDDEN(pi);
1245 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1246 gint length, const guint8 *start_ptr, const char *format, ...)
1251 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
1255 va_start(ap, format);
1256 proto_tree_set_representation(pi, format, ap);
1263 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
1267 bytes = g_byte_array_new();
1269 g_byte_array_append(bytes, start_ptr, length);
1271 fvalue_set(&fi->value, bytes, TRUE);
1276 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
1278 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
1281 /* Add a FT_*TIME to a proto_tree */
1283 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1284 nstime_t *value_ptr)
1288 header_field_info *hfinfo;
1293 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1295 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1296 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
1297 hfinfo->type == FT_RELATIVE_TIME);
1299 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1300 proto_tree_set_time(new_fi, value_ptr);
1306 proto_tree_add_time_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1307 nstime_t *value_ptr)
1311 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1315 PROTO_ITEM_SET_HIDDEN(pi);
1321 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1322 nstime_t *value_ptr, const char *format, ...)
1327 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
1331 va_start(ap, format);
1332 proto_tree_set_representation(pi, format, ap);
1338 /* Set the FT_*TIME value */
1340 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
1342 DISSECTOR_ASSERT(value_ptr != NULL);
1343 fvalue_set(&fi->value, value_ptr, FALSE);
1346 /* Add a FT_IPXNET to a proto_tree */
1348 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1353 header_field_info *hfinfo;
1358 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1360 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1361 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
1363 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1364 proto_tree_set_ipxnet(new_fi, value);
1370 proto_tree_add_ipxnet_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1375 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1379 PROTO_ITEM_SET_HIDDEN(pi);
1385 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1386 guint32 value, const char *format, ...)
1391 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
1395 va_start(ap, format);
1396 proto_tree_set_representation(pi, format, ap);
1402 /* Set the FT_IPXNET value */
1404 proto_tree_set_ipxnet(field_info *fi, guint32 value)
1406 fvalue_set_integer(&fi->value, value);
1409 /* Add a FT_IPv4 to a proto_tree */
1411 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1416 header_field_info *hfinfo;
1421 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1423 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1424 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
1426 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1427 proto_tree_set_ipv4(new_fi, value);
1433 proto_tree_add_ipv4_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1438 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1442 PROTO_ITEM_SET_HIDDEN(pi);
1448 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1449 guint32 value, const char *format, ...)
1454 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
1458 va_start(ap, format);
1459 proto_tree_set_representation(pi, format, ap);
1465 /* Set the FT_IPv4 value */
1467 proto_tree_set_ipv4(field_info *fi, guint32 value)
1469 fvalue_set_integer(&fi->value, value);
1472 /* Add a FT_IPv6 to a proto_tree */
1474 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1475 const guint8* value_ptr)
1479 header_field_info *hfinfo;
1484 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1486 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1487 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
1489 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1490 proto_tree_set_ipv6(new_fi, value_ptr);
1496 proto_tree_add_ipv6_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1497 const guint8* value_ptr)
1501 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1505 PROTO_ITEM_SET_HIDDEN(pi);
1511 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1512 const guint8* value_ptr, const char *format, ...)
1517 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
1521 va_start(ap, format);
1522 proto_tree_set_representation(pi, format, ap);
1528 /* Set the FT_IPv6 value */
1530 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
1532 DISSECTOR_ASSERT(value_ptr != NULL);
1533 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1537 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1539 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, 16));
1542 /* Add a FT_GUID to a proto_tree */
1544 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1545 const guint8* value_ptr)
1549 header_field_info *hfinfo;
1554 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1556 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1557 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
1559 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1560 proto_tree_set_guid(new_fi, value_ptr);
1566 proto_tree_add_guid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1567 const guint8* value_ptr)
1571 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1575 PROTO_ITEM_SET_HIDDEN(pi);
1581 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1582 const guint8* value_ptr, const char *format, ...)
1587 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
1591 va_start(ap, format);
1592 proto_tree_set_representation(pi, format, ap);
1598 /* Set the FT_GUID value */
1600 proto_tree_set_guid(field_info *fi, const guint8* value_ptr)
1602 DISSECTOR_ASSERT(value_ptr != NULL);
1603 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
1607 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1609 proto_tree_set_guid(fi, tvb_get_ptr(tvb, start, 16));
1612 /* Add a FT_OID to a proto_tree */
1614 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1615 const guint8* value_ptr)
1619 header_field_info *hfinfo;
1624 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1626 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1627 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
1629 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1630 proto_tree_set_oid(new_fi, value_ptr, length);
1636 proto_tree_add_oid_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1637 const guint8* value_ptr)
1641 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1645 PROTO_ITEM_SET_HIDDEN(pi);
1651 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1652 const guint8* value_ptr, const char *format, ...)
1657 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
1661 va_start(ap, format);
1662 proto_tree_set_representation(pi, format, ap);
1668 /* Set the FT_OID value */
1670 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
1674 DISSECTOR_ASSERT(value_ptr != NULL);
1676 bytes = g_byte_array_new();
1678 g_byte_array_append(bytes, value_ptr, length);
1680 fvalue_set(&fi->value, bytes, TRUE);
1684 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1686 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
1690 proto_tree_set_uint64(field_info *fi, guint64 value)
1692 fvalue_set_integer64(&fi->value, value);
1696 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian)
1700 value = little_endian ? tvb_get_letoh64(tvb, start)
1701 : tvb_get_ntoh64(tvb, start);
1703 proto_tree_set_uint64(fi, value);
1706 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
1707 * and frees it when the proto_tree is destroyed. */
1709 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1710 gint length, const char* value)
1714 header_field_info *hfinfo;
1719 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1721 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1722 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1724 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1725 DISSECTOR_ASSERT(length >= 0);
1726 proto_tree_set_string(new_fi, value, FALSE);
1732 proto_tree_add_string_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1733 gint length, const char* value)
1737 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1741 PROTO_ITEM_SET_HIDDEN(pi);
1747 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
1748 gint length, const char* value, const char *format, ...)
1753 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
1757 va_start(ap, format);
1758 proto_tree_set_representation(pi, format, ap);
1764 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
1765 * field info update instead of only updating the representation as does
1766 * proto_item_append_text()
1768 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
1769 * speed optimization.
1770 * Currently only WSP use this function so it is not that bad but try to
1771 * avoid using this one if possible.
1772 * IF you must use this function you MUST also disable the
1773 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
1774 * using proto_item_append_string().
1775 * Do that by faking that the tree is visible by setting :
1776 * PTREE_DATA(tree)->visible=1; (see packet-wsp.c)
1777 * BEFORE you create the item you are later going to use
1778 * proto_item_append_string() on.
1781 proto_item_append_string(proto_item *pi, const char *str)
1784 header_field_info *hfinfo;
1785 gchar *old_str, *new_str;
1792 fi = PITEM_FINFO(pi);
1793 hfinfo = fi->hfinfo;
1794 if (hfinfo->type == FT_PROTOCOL) {
1795 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
1798 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
1799 old_str = fvalue_get(&fi->value);
1800 new_str = g_strdup_printf("%s%s", old_str, str);
1801 fvalue_set(&fi->value, new_str, TRUE);
1804 /* Set the FT_STRING value */
1806 proto_tree_set_string(field_info *fi, const char* value,
1807 gboolean already_allocated)
1810 fvalue_set(&fi->value, (gpointer) value, already_allocated);
1812 fvalue_set(&fi->value, (gpointer) "[ Null ]", already_allocated);
1816 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
1821 length = tvb_ensure_length_remaining(tvb, start);
1824 /* This memory is freed in proto_tree_free_node() */
1825 string = tvb_get_string(tvb, start, length);
1826 proto_tree_set_string(fi, string, TRUE);
1829 /* Add a FT_ETHER to a proto_tree */
1831 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1832 const guint8* value)
1836 header_field_info *hfinfo;
1841 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1843 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1844 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
1846 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1847 proto_tree_set_ether(new_fi, value);
1853 proto_tree_add_ether_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1854 const guint8* value)
1858 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1862 PROTO_ITEM_SET_HIDDEN(pi);
1868 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1869 const guint8* value, const char *format, ...)
1874 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
1878 va_start(ap, format);
1879 proto_tree_set_representation(pi, format, ap);
1885 /* Set the FT_ETHER value */
1887 proto_tree_set_ether(field_info *fi, const guint8* value)
1889 fvalue_set(&fi->value, (gpointer) value, FALSE);
1893 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
1895 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
1898 /* Add a FT_BOOLEAN to a proto_tree */
1900 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1905 header_field_info *hfinfo;
1910 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1912 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1913 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
1915 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1916 proto_tree_set_boolean(new_fi, value);
1922 proto_tree_add_boolean_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1927 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1931 PROTO_ITEM_SET_HIDDEN(pi);
1937 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1938 guint32 value, const char *format, ...)
1943 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
1947 va_start(ap, format);
1948 proto_tree_set_representation(pi, format, ap);
1954 /* Set the FT_BOOLEAN value */
1956 proto_tree_set_boolean(field_info *fi, guint32 value)
1958 proto_tree_set_uint(fi, value);
1961 /* Add a FT_FLOAT to a proto_tree */
1963 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1968 header_field_info *hfinfo;
1973 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
1975 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1976 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
1978 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
1979 proto_tree_set_float(new_fi, value);
1985 proto_tree_add_float_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
1990 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
1994 PROTO_ITEM_SET_HIDDEN(pi);
2000 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2001 float value, const char *format, ...)
2006 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2010 va_start(ap, format);
2011 proto_tree_set_representation(pi, format, ap);
2017 /* Set the FT_FLOAT value */
2019 proto_tree_set_float(field_info *fi, float value)
2021 fvalue_set_floating(&fi->value, value);
2024 /* Add a FT_DOUBLE to a proto_tree */
2026 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2031 header_field_info *hfinfo;
2036 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2038 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2039 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2041 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2042 proto_tree_set_double(new_fi, value);
2048 proto_tree_add_double_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2053 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2057 PROTO_ITEM_SET_HIDDEN(pi);
2063 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2064 double value, const char *format, ...)
2069 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2073 va_start(ap, format);
2074 proto_tree_set_representation(pi, format, ap);
2080 /* Set the FT_DOUBLE value */
2082 proto_tree_set_double(field_info *fi, double value)
2084 fvalue_set_floating(&fi->value, value);
2087 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2089 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2092 proto_item *pi = NULL;
2094 header_field_info *hfinfo;
2099 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2101 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2102 switch(hfinfo->type) {
2108 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2110 proto_tree_set_uint(new_fi, value);
2114 DISSECTOR_ASSERT_NOT_REACHED();
2121 proto_tree_add_uint_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2126 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2130 PROTO_ITEM_SET_HIDDEN(pi);
2136 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2137 guint32 value, const char *format, ...)
2142 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
2146 va_start(ap, format);
2147 proto_tree_set_representation(pi, format, ap);
2153 /* Set the FT_UINT{8,16,24,32} value */
2155 proto_tree_set_uint(field_info *fi, guint32 value)
2157 header_field_info *hfinfo;
2160 hfinfo = fi->hfinfo;
2163 if (hfinfo->bitmask) {
2164 /* Mask out irrelevant portions */
2165 integer &= hfinfo->bitmask;
2168 if (hfinfo->bitshift > 0) {
2169 integer >>= hfinfo->bitshift;
2172 fvalue_set_integer(&fi->value, integer);
2175 /* Add FT_UINT64 to a proto_tree */
2177 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2180 proto_item *pi = NULL;
2182 header_field_info *hfinfo;
2187 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2189 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2190 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
2192 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2193 proto_tree_set_uint64(new_fi, value);
2199 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2200 guint64 value, const char *format, ...)
2205 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
2209 va_start(ap, format);
2210 proto_tree_set_representation(pi, format, ap);
2216 /* Add FT_INT{8,16,24,32} to a proto_tree */
2218 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2221 proto_item *pi = NULL;
2223 header_field_info *hfinfo;
2228 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2230 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2231 switch(hfinfo->type) {
2236 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length,
2238 proto_tree_set_int(new_fi, value);
2242 DISSECTOR_ASSERT_NOT_REACHED();
2249 proto_tree_add_int_hidden(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2254 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2258 PROTO_ITEM_SET_HIDDEN(pi);
2264 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2265 gint32 value, const char *format, ...)
2267 proto_item *pi = NULL;
2270 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
2274 va_start(ap, format);
2275 proto_tree_set_representation(pi, format, ap);
2281 /* Set the FT_INT{8,16,24,32} value */
2283 proto_tree_set_int(field_info *fi, gint32 value)
2285 header_field_info *hfinfo;
2288 hfinfo = fi->hfinfo;
2289 integer = (guint32) value;
2291 if (hfinfo->bitmask) {
2292 /* Mask out irrelevant portions */
2293 integer &= hfinfo->bitmask;
2296 if (hfinfo->bitshift > 0) {
2297 integer >>= hfinfo->bitshift;
2300 fvalue_set_integer(&fi->value, integer);
2303 /* Add FT_INT64 to a proto_tree */
2305 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2308 proto_item *pi = NULL;
2310 header_field_info *hfinfo;
2315 TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
2317 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2318 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
2320 pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
2321 proto_tree_set_uint64(new_fi, (guint64)value);
2327 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2328 gint64 value, const char *format, ...)
2333 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
2337 va_start(ap, format);
2338 proto_tree_set_representation(pi, format, ap);
2345 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
2347 proto_tree_add_node(proto_tree *tree, field_info *fi)
2349 proto_node *pnode, *tnode, *sibling;
2353 * Make sure "tree" is ready to have subtrees under it, by
2354 * checking whether it's been given an ett_ value.
2356 * "tnode->finfo" may be null; that's the case for the root
2357 * node of the protocol tree. That node is not displayed,
2358 * so it doesn't need an ett_ value to remember whether it
2363 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
2364 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
2365 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
2366 /* XXX - is it safe to continue here? */
2369 DISSECTOR_ASSERT(tfi == NULL ||
2370 (tfi->tree_type >= 0 && tfi->tree_type < num_tree_types));
2372 PROTO_NODE_NEW(pnode);
2373 pnode->parent = tnode;
2375 pnode->tree_data = PTREE_DATA(tree);
2377 if (tnode->last_child != NULL) {
2378 sibling = tnode->last_child;
2379 DISSECTOR_ASSERT(sibling->next == NULL);
2380 sibling->next = pnode;
2382 tnode->first_child = pnode;
2383 tnode->last_child = pnode;
2385 return (proto_item*)pnode;
2389 /* Generic way to allocate field_info and add to proto_tree.
2390 * Sets *pfi to address of newly-allocated field_info struct, if pfi is
2393 proto_tree_add_pi(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2394 gint *length, field_info **pfi)
2404 fi = alloc_field_info(tree, hfindex, tvb, start, length);
2405 pi = proto_tree_add_node(tree, fi);
2407 /* If the proto_tree wants to keep a record of this finfo
2408 * for quick lookup, then record it. */
2409 if (fi->hfinfo->ref_count) {
2410 hash = PTREE_DATA(tree)->interesting_hfids;
2411 ptrs = g_hash_table_lookup(hash, GINT_TO_POINTER(hfindex));
2413 g_ptr_array_add(ptrs, fi);
2417 /* Does the caller want to know the fi pointer? */
2426 static header_field_info *
2427 get_hfi_and_length(int hfindex, tvbuff_t *tvb, gint start, gint *length,
2430 header_field_info *hfinfo;
2431 gint length_remaining;
2434 * We only allow a null tvbuff if the item has a zero length,
2435 * i.e. if there's no data backing it.
2437 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
2439 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2442 * XXX - in some protocols, there are 32-bit unsigned length
2443 * fields, so lengths in protocol tree and tvbuff routines
2444 * should really be unsigned. We should have, for those
2445 * field types for which "to the end of the tvbuff" makes sense,
2446 * additional routines that take no length argument and
2447 * add fields that run to the end of the tvbuff.
2449 if (*length == -1) {
2451 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
2452 * a length of -1 means "set the length to what remains in
2455 * The assumption is either that
2457 * 1) the length of the item can only be determined
2458 * by dissection (typically true of items with
2459 * subitems, which are probably FT_NONE or
2464 * 2) if the tvbuff is "short" (either due to a short
2465 * snapshot length or due to lack of reassembly of
2466 * fragments/segments/whatever), we want to display
2467 * what's available in the field (probably FT_BYTES
2468 * or FT_STRING) and then throw an exception later
2472 * 3) the field is defined to be "what's left in the
2475 * so we set the length to what remains in the tvbuff so
2476 * that, if we throw an exception while dissecting, it
2477 * has what is probably the right value.
2479 * For FT_STRINGZ, it means "the string is null-terminated,
2480 * not null-padded; set the length to the actual length
2481 * of the string", and if the tvbuff if short, we just
2482 * throw an exception.
2484 * It's not valid for any other type of field.
2486 switch (hfinfo->type) {
2490 * We allow this to be zero-length - for
2491 * example, an ONC RPC NULL procedure has
2492 * neither arguments nor reply, so the
2493 * payload for that protocol is empty.
2495 * However, if the length is negative, the
2496 * start offset is *past* the byte past the
2497 * end of the tvbuff, so we throw an
2500 *length = tvb_length_remaining(tvb, start);
2503 * Use "tvb_ensure_bytes_exist()"
2504 * to force the appropriate exception
2507 tvb_ensure_bytes_exist(tvb, start, 0);
2509 DISSECTOR_ASSERT(*length >= 0);
2515 *length = tvb_ensure_length_remaining(tvb, start);
2516 DISSECTOR_ASSERT(*length >= 0);
2521 * Leave the length as -1, so our caller knows
2527 DISSECTOR_ASSERT_NOT_REACHED();
2529 *item_length = *length;
2531 *item_length = *length;
2532 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
2534 * These types are for interior nodes of the
2535 * tree, and don't have data associated with
2536 * them; if the length is negative (XXX - see
2537 * above) or goes past the end of the tvbuff,
2538 * cut it short at the end of the tvbuff.
2539 * That way, if this field is selected in
2540 * Ethereal, we don't highlight stuff past
2541 * the end of the data.
2543 /* XXX - what to do, if we don't have a tvb? */
2545 length_remaining = tvb_length_remaining(tvb, start);
2546 if (*item_length < 0 ||
2547 (*item_length > 0 &&
2548 (length_remaining < *item_length)))
2549 *item_length = length_remaining;
2552 if (*item_length < 0) {
2553 THROW(ReportedBoundsError);
2561 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2562 gint start, gint item_length)
2568 fi->hfinfo = hfinfo;
2570 fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
2571 fi->length = item_length;
2574 if (!PTREE_DATA(tree)->visible)
2575 FI_SET_FLAG(fi, FI_HIDDEN);
2576 fvalue_init(&fi->value, fi->hfinfo->type);
2579 /* add the data source tvbuff */
2580 fi->ds_tvb=tvb?TVB_GET_DS_TVB(tvb):NULL;
2586 alloc_field_info(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2589 header_field_info *hfinfo;
2592 hfinfo = get_hfi_and_length(hfindex, tvb, start, length, &item_length);
2593 return new_field_info(tree, hfinfo, tvb, start, item_length);
2596 /* Set representation of a proto_tree entry, if the protocol tree is to
2599 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
2601 int ret; /*tmp return value */
2602 field_info *fi = PITEM_FINFO(pi);
2604 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2605 ITEM_LABEL_NEW(fi->rep);
2606 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH, format, ap);
2607 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
2608 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2612 /* Set text of proto_item after having already been created. */
2614 proto_item_set_text(proto_item *pi, const char *format, ...)
2616 field_info *fi = NULL;
2623 fi = PITEM_FINFO(pi);
2626 ITEM_LABEL_FREE(fi->rep);
2629 va_start(ap, format);
2630 proto_tree_set_representation(pi, format, ap);
2634 /* Append to text of proto_item after having already been created. */
2636 proto_item_append_text(proto_item *pi, const char *format, ...)
2638 field_info *fi = NULL;
2641 int ret; /*tmp return value */
2647 fi = PITEM_FINFO(pi);
2649 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
2650 va_start(ap, format);
2653 * If we don't already have a representation,
2654 * generate the default representation.
2656 if (fi->rep == NULL) {
2657 ITEM_LABEL_NEW(fi->rep);
2658 proto_item_fill_label(fi, fi->rep->representation);
2661 curlen = strlen(fi->rep->representation);
2662 if (ITEM_LABEL_LENGTH > curlen) {
2663 ret = g_vsnprintf(fi->rep->representation + curlen,
2664 ITEM_LABEL_LENGTH - curlen, format, ap);
2665 if ((ret == -1) || (ret >= (int)(ITEM_LABEL_LENGTH - curlen)))
2666 fi->rep->representation[ITEM_LABEL_LENGTH - 1] = '\0';
2673 proto_item_set_len(proto_item *pi, gint length)
2679 fi = PITEM_FINFO(pi);
2680 DISSECTOR_ASSERT(length >= 0);
2681 fi->length = length;
2685 * Sets the length of the item based on its start and on the specified
2686 * offset, which is the offset past the end of the item; as the start
2687 * in the item is relative to the beginning of the data source tvbuff,
2688 * we need to pass in a tvbuff - the end offset is relative to the beginning
2692 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
2698 fi = PITEM_FINFO(pi);
2699 end += TVB_RAW_OFFSET(tvb);
2700 DISSECTOR_ASSERT(end >= fi->start);
2701 fi->length = end - fi->start;
2705 proto_item_get_len(proto_item *pi)
2707 field_info *fi = PITEM_FINFO(pi);
2712 /** clear flags according to the mask and set new flag values */
2713 #define FI_REPLACE_FLAGS(fi, mask, flags_in) { \
2714 (fi->flags = (fi)->flags & ~(mask)); \
2715 (fi->flags = (fi)->flags | (flags_in)); \
2719 proto_item_set_expert_flags(proto_item *pi, int group, int severity)
2721 if(pi == NULL || pi->finfo == NULL)
2724 /* only change things if severity is worse or at least equal than before */
2725 if(severity >= FI_GET_FLAG(pi->finfo, PI_SEVERITY_MASK)) {
2726 FI_REPLACE_FLAGS(pi->finfo, PI_GROUP_MASK, group);
2727 FI_REPLACE_FLAGS(pi->finfo, PI_SEVERITY_MASK, severity);
2738 proto_tree_create_root(void)
2742 /* Initialize the proto_node */
2743 PROTO_NODE_NEW(pnode);
2744 pnode->parent = NULL;
2745 pnode->finfo = NULL;
2746 pnode->tree_data = g_new(tree_data_t, 1);
2748 /* Initialize the tree_data_t */
2749 pnode->tree_data->interesting_hfids =
2750 g_hash_table_new(g_direct_hash, g_direct_equal);
2752 /* Set the default to FALSE so it's easier to
2753 * find errors; if we expect to see the protocol tree
2754 * but for some reason the default 'visible' is not
2755 * changed, then we'll find out very quickly. */
2756 pnode->tree_data->visible = FALSE;
2758 return (proto_tree*) pnode;
2762 /* "prime" a proto_tree with a single hfid that a dfilter
2763 * is interested in. */
2765 proto_tree_prime_hfid(proto_tree *tree, gint hfid)
2767 header_field_info *hfinfo;
2769 g_hash_table_insert(PTREE_DATA(tree)->interesting_hfids,
2770 GINT_TO_POINTER(hfid), g_ptr_array_new());
2772 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
2773 /* this field is referenced by a filter so increase the refcount.
2774 also increase the refcount for the parent, i.e the protocol.
2776 hfinfo->ref_count++;
2777 /* only increase the refcount if there is a parent.
2778 if this is a protocol and not a field then parent will be -1
2779 and there is no parent to add any refcounting for.
2781 if (hfinfo->parent != -1) {
2782 header_field_info *parent_hfinfo;
2783 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
2784 parent_hfinfo->ref_count++;
2789 proto_item_add_subtree(proto_item *pi, gint idx) {
2795 fi = PITEM_FINFO(pi);
2796 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
2797 fi->tree_type = idx;
2799 return (proto_tree*) pi;
2803 proto_item_get_subtree(proto_item *pi) {
2808 fi = PITEM_FINFO(pi);
2809 if ( (!fi) || (fi->tree_type == -1) )
2811 return (proto_tree*) pi;
2815 proto_item_get_parent(proto_item *ti) {
2816 /* dont bother if tree is not visible */
2817 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2823 proto_item_get_parent_nth(proto_item *ti, int gen) {
2824 /* dont bother if tree is not visible */
2825 if( (!ti) || (!(PTREE_DATA(ti)->visible)) )
2837 proto_tree_get_parent(proto_tree *tree) {
2838 /* dont bother if tree is not visible */
2839 if( (!tree) || (!(PTREE_DATA(tree)->visible)) )
2841 return (proto_item*) tree;
2846 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item, proto_item *item_to_move)
2848 proto_item *curr_item;
2851 /*** cut item_to_move out ***/
2853 /* is item_to_move the first? */
2854 if(tree->first_child == item_to_move) {
2855 /* simply change first child to next */
2856 tree->first_child = item_to_move->next;
2858 /* find previous and change it's next */
2859 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
2860 if(curr_item->next == item_to_move) {
2865 DISSECTOR_ASSERT(curr_item);
2867 curr_item->next = item_to_move->next;
2869 /* fix last_child if required */
2870 if(tree->last_child == item_to_move) {
2871 tree->last_child = curr_item;
2875 /*** insert to_move after fixed ***/
2876 item_to_move->next = fixed_item->next;
2877 fixed_item->next = item_to_move;
2878 if(tree->last_child == fixed_item) {
2879 tree->last_child = item_to_move;
2885 proto_register_protocol(const char *name, const char *short_name, const char *filter_name)
2887 protocol_t *protocol;
2888 header_field_info *hfinfo;
2890 char *existing_name;
2894 gboolean found_invalid;
2897 * Make sure there's not already a protocol with any of those
2898 * names. Crash if there is, as that's an error in the code
2899 * or an inappropriate plugin.
2900 * This situation has to be fixed to not register more than one
2901 * protocol with the same name.
2903 * This is done by reducing the number of strcmp (and alike) calls as much as possible,
2904 * as this significally slows down startup time.
2906 * Drawback: As a hash value is used to reduce insert time,
2907 * this might lead to a hash collision.
2908 * However, as we have around 500+ protocols and we're using a 32 bit int this is very,
2912 key = g_malloc (sizeof(gint));
2913 *key = g_str_hash(name);
2914 existing_name = g_hash_table_lookup(proto_names, key);
2915 if (existing_name != NULL) {
2916 /* g_error will terminate the program */
2917 g_error("Duplicate protocol name \"%s\"!"
2918 " This might be caused by an inappropriate plugin or a development error.", name);
2920 g_hash_table_insert(proto_names, key, (gpointer)name);
2922 key = g_malloc (sizeof(gint));
2923 *key = g_str_hash(short_name);
2924 existing_name = g_hash_table_lookup(proto_short_names, key);
2925 if (existing_name != NULL) {
2926 g_error("Duplicate protocol short_name \"%s\"!"
2927 " This might be caused by an inappropriate plugin or a development error.", short_name);
2929 g_hash_table_insert(proto_short_names, key, (gpointer)short_name);
2931 found_invalid = FALSE;
2932 for (i = 0; i < strlen(filter_name); i++) {
2934 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
2935 found_invalid = TRUE;
2938 if (found_invalid) {
2939 g_warning("Protocol filter name \"%s\" has one or more invalid characters.", filter_name);
2941 key = g_malloc (sizeof(gint));
2942 *key = g_str_hash(filter_name);
2943 existing_name = g_hash_table_lookup(proto_filter_names, key);
2944 if (existing_name != NULL) {
2945 g_error("Duplicate protocol filter_name \"%s\"!"
2946 " This might be caused by an inappropriate plugin or a development error.", filter_name);
2948 g_hash_table_insert(proto_filter_names, key, (gpointer)filter_name);
2950 /* Add this protocol to the list of known protocols; the list
2951 is sorted by protocol short name. */
2952 protocol = g_malloc(sizeof (protocol_t));
2953 protocol->name = name;
2954 protocol->short_name = short_name;
2955 protocol->filter_name = filter_name;
2956 protocol->fields = NULL;
2957 protocol->is_enabled = TRUE; /* protocol is enabled by default */
2958 protocol->can_toggle = TRUE;
2959 /* list will be sorted later by name, when all protocols completed registering */
2960 protocols = g_list_append(protocols, protocol);
2962 /* Here we do allocate a new header_field_info struct */
2963 hfinfo = g_mem_chunk_alloc(gmc_hfinfo);
2964 hfinfo->name = name;
2965 hfinfo->abbrev = filter_name;
2966 hfinfo->type = FT_PROTOCOL;
2967 hfinfo->strings = protocol;
2968 hfinfo->bitmask = 0;
2969 hfinfo->bitshift = 0;
2970 hfinfo->ref_count = 0;
2971 hfinfo->blurb = NULL;
2972 hfinfo->parent = -1; /* this field differentiates protos and fields */
2974 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
2975 protocol->proto_id = proto_id;
2980 * Routines to use to iterate over the protocols.
2981 * The argument passed to the iterator routines is an opaque cookie to
2982 * their callers; it's the GList pointer for the current element in
2984 * The ID of the protocol is returned, or -1 if there is no protocol.
2987 proto_get_first_protocol(void **cookie)
2989 protocol_t *protocol;
2991 if (protocols == NULL)
2993 *cookie = protocols;
2994 protocol = protocols->data;
2995 return protocol->proto_id;
2999 proto_get_next_protocol(void **cookie)
3001 GList *list_item = *cookie;
3002 protocol_t *protocol;
3004 list_item = g_list_next(list_item);
3005 if (list_item == NULL)
3007 *cookie = list_item;
3008 protocol = list_item->data;
3009 return protocol->proto_id;
3013 proto_get_first_protocol_field(int proto_id, void **cookie)
3015 protocol_t *protocol = find_protocol_by_id(proto_id);
3016 hf_register_info *ptr;
3018 if ((protocol == NULL) || (protocol->fields == NULL))
3021 *cookie = protocol->fields;
3022 ptr = protocol->fields->data;
3023 return &ptr->hfinfo;
3027 proto_get_next_protocol_field(void **cookie)
3029 GList *list_item = *cookie;
3030 hf_register_info *ptr;
3032 list_item = g_list_next(list_item);
3033 if (list_item == NULL)
3036 *cookie = list_item;
3037 ptr = list_item->data;
3038 return &ptr->hfinfo;
3042 find_protocol_by_id(int proto_id)
3044 header_field_info *hfinfo;
3049 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
3050 DISSECTOR_ASSERT(hfinfo->type==FT_PROTOCOL);
3051 return (protocol_t *)hfinfo->strings;
3054 static gint compare_filter_name(gconstpointer proto_arg,
3055 gconstpointer filter_name)
3057 const protocol_t *protocol = proto_arg;
3058 const gchar* f_name = filter_name;
3060 return (strcmp(protocol->filter_name, f_name));
3064 proto_get_id(protocol_t *protocol)
3066 return protocol->proto_id;
3069 int proto_get_id_by_filter_name(const gchar* filter_name)
3072 protocol_t *protocol;
3074 list_entry = g_list_find_custom(protocols, filter_name,
3075 compare_filter_name);
3076 if (list_entry == NULL)
3078 protocol = list_entry->data;
3079 return protocol->proto_id;
3083 proto_get_protocol_name(int proto_id)
3085 protocol_t *protocol;
3087 protocol = find_protocol_by_id(proto_id);
3088 return protocol->name;
3092 proto_get_protocol_short_name(protocol_t *protocol)
3094 if (protocol == NULL)
3096 return protocol->short_name;
3100 proto_get_protocol_filter_name(int proto_id)
3102 protocol_t *protocol;
3104 protocol = find_protocol_by_id(proto_id);
3105 return protocol->filter_name;
3109 proto_is_protocol_enabled(protocol_t *protocol)
3111 return protocol->is_enabled;
3115 proto_can_toggle_protocol(int proto_id)
3117 protocol_t *protocol;
3119 protocol = find_protocol_by_id(proto_id);
3120 return protocol->can_toggle;
3124 proto_set_decoding(int proto_id, gboolean enabled)
3126 protocol_t *protocol;
3128 protocol = find_protocol_by_id(proto_id);
3129 DISSECTOR_ASSERT(protocol->can_toggle);
3130 protocol->is_enabled = enabled;
3134 proto_set_cant_toggle(int proto_id)
3136 protocol_t *protocol;
3138 protocol = find_protocol_by_id(proto_id);
3139 protocol->can_toggle = FALSE;
3142 /* for use with static arrays only, since we don't allocate our own copies
3143 of the header_field_info struct contained within the hf_register_info struct */
3145 proto_register_field_array(int parent, hf_register_info *hf, int num_records)
3148 hf_register_info *ptr = hf;
3151 proto = find_protocol_by_id(parent);
3152 for (i = 0; i < num_records; i++, ptr++) {
3154 * Make sure we haven't registered this yet.
3155 * Most fields have variables associated with them
3156 * that are initialized to -1; some have array elements,
3157 * or possibly uninitialized variables, so we also allow
3158 * 0 (which is unlikely to be the field ID we get back
3159 * from "proto_register_field_init()").
3161 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
3163 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
3168 if (proto != NULL) {
3169 if (proto->fields == NULL) {
3170 proto->fields = g_list_append(NULL, ptr);
3171 proto->last_field = proto->fields;
3174 g_list_append(proto->last_field, ptr)->next;
3177 field_id = proto_register_field_init(&ptr->hfinfo, parent);
3178 *ptr->p_id = field_id;
3183 proto_register_field_init(header_field_info *hfinfo, int parent)
3185 /* The field must have names */
3186 DISSECTOR_ASSERT(hfinfo->name);
3187 DISSECTOR_ASSERT(hfinfo->abbrev);
3189 /* These types of fields are allowed to have value_strings, true_false_strings or a protocol_t struct*/
3190 DISSECTOR_ASSERT((hfinfo->strings == NULL) || (
3191 (hfinfo->type == FT_UINT8) ||
3192 (hfinfo->type == FT_UINT16) ||
3193 (hfinfo->type == FT_UINT24) ||
3194 (hfinfo->type == FT_UINT32) ||
3195 (hfinfo->type == FT_INT8) ||
3196 (hfinfo->type == FT_INT16) ||
3197 (hfinfo->type == FT_INT24) ||
3198 (hfinfo->type == FT_INT32) ||
3199 (hfinfo->type == FT_BOOLEAN) ||
3200 (hfinfo->type == FT_PROTOCOL) ||
3201 (hfinfo->type == FT_FRAMENUM) ));
3203 switch (hfinfo->type) {
3213 /* Require integral types (other than frame number, which is
3214 always displayed in decimal) to have a number base */
3215 DISSECTOR_ASSERT(hfinfo->display != BASE_NONE);
3219 /* Don't allow bitfields or value strings for frame numbers */
3220 DISSECTOR_ASSERT(hfinfo->bitmask == 0);
3221 DISSECTOR_ASSERT(hfinfo->strings == NULL);
3227 /* if this is a bitfield, compute bitshift */
3228 if (hfinfo->bitmask) {
3229 while ((hfinfo->bitmask & (1 << hfinfo->bitshift)) == 0)
3233 hfinfo->parent = parent;
3234 hfinfo->same_name_next = NULL;
3235 hfinfo->same_name_prev = NULL;
3237 /* if we always add and never delete, then id == len - 1 is correct */
3238 if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
3239 if(!gpa_hfinfo.hfi){
3240 gpa_hfinfo.allocated_len=1000;
3241 gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
3243 gpa_hfinfo.allocated_len+=1000;
3244 gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
3247 gpa_hfinfo.hfi[gpa_hfinfo.len]=hfinfo;
3249 hfinfo->id = gpa_hfinfo.len - 1;
3251 /* if we have real names, enter this field in the name tree */
3252 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
3254 header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
3258 /* Check that the filter name (abbreviation) is legal;
3259 * it must contain only alphanumerics, '-', "_", and ".". */
3260 for (p = hfinfo->abbrev; (c = *p) != '\0'; p++)
3261 DISSECTOR_ASSERT(isalnum(c) || c == '-' || c == '_' ||
3264 /* We allow multiple hfinfo's to be registered under the same
3265 * abbreviation. This was done for X.25, as, depending
3266 * on whether it's modulo-8 or modulo-128 operation,
3267 * some bitfield fields may be in different bits of
3268 * a byte, and we want to be able to refer to that field
3269 * with one name regardless of whether the packets
3270 * are modulo-8 or modulo-128 packets. */
3271 same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
3272 if (same_name_hfinfo) {
3273 /* There's already a field with this name.
3274 * Put it after that field in the list of
3275 * fields with this name, then allow the code
3276 * after this if{} block to replace the old
3277 * hfinfo with the new hfinfo in the GTree. Thus,
3278 * we end up with a linked-list of same-named hfinfo's,
3279 * with the root of the list being the hfinfo in the GTree */
3280 same_name_next_hfinfo =
3281 same_name_hfinfo->same_name_next;
3283 hfinfo->same_name_next = same_name_next_hfinfo;
3284 if (same_name_next_hfinfo)
3285 same_name_next_hfinfo->same_name_prev = hfinfo;
3287 same_name_hfinfo->same_name_next = hfinfo;
3288 hfinfo->same_name_prev = same_name_hfinfo;
3290 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
3297 proto_register_subtree_array(gint *const *indices, int num_indices)
3300 gint *const *ptr = indices;
3303 * If we've already allocated the array of tree types, expand
3304 * it; this lets plugins such as mate add tree types after
3305 * the initial startup. (If we haven't already allocated it,
3306 * we don't allocate it; on the first pass, we just assign
3307 * ett values and keep track of how many we've assigned, and
3308 * when we're finished registering all dissectors we allocate
3309 * the array, so that we do only one allocation rather than
3310 * wasting CPU time and memory by growing the array for each
3311 * dissector that registers ett values.)
3313 if (tree_is_expanded != NULL) {
3315 g_realloc(tree_is_expanded,
3316 (num_tree_types+num_indices)*sizeof (gboolean));
3317 memset(tree_is_expanded + num_tree_types, 0,
3318 num_indices*sizeof (gboolean));
3322 * Assign "num_indices" subtree numbers starting at "num_tree_types",
3323 * returning the indices through the pointers in the array whose
3324 * first element is pointed to by "indices", and update
3325 * "num_tree_types" appropriately.
3327 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++)
3328 **ptr = num_tree_types;
3332 proto_item_fill_label(field_info *fi, gchar *label_str)
3334 header_field_info *hfinfo = fi->hfinfo;
3339 guint32 n_addr; /* network-order IPv4 address */
3341 int ret; /*tmp return value */
3343 switch(hfinfo->type) {
3346 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3347 "%s", hfinfo->name);
3348 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3349 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3353 fill_label_boolean(fi, label_str);
3358 bytes = fvalue_get(&fi->value);
3360 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3361 "%s: %s", hfinfo->name,
3362 bytes_to_str(bytes, fvalue_length(&fi->value)));
3363 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3364 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3367 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3368 "%s: <MISSING>", hfinfo->name);
3369 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3370 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3374 /* Four types of integers to take care of:
3375 * Bitfield, with val_string
3376 * Bitfield, w/o val_string
3377 * Non-bitfield, with val_string
3378 * Non-bitfield, w/o val_string
3385 if (hfinfo->bitmask) {
3386 if (hfinfo->strings) {
3387 fill_label_enumerated_bitfield(fi, label_str);
3390 fill_label_numeric_bitfield(fi, label_str);
3394 if (hfinfo->strings) {
3395 fill_label_enumerated_uint(fi, label_str);
3398 fill_label_uint(fi, label_str);
3404 fill_label_uint64(fi, label_str);
3411 DISSECTOR_ASSERT(!hfinfo->bitmask);
3412 if (hfinfo->strings) {
3413 fill_label_enumerated_int(fi, label_str);
3416 fill_label_int(fi, label_str);
3421 fill_label_int64(fi, label_str);
3425 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3426 "%s: %." STRINGIFY(FLT_DIG) "f",
3427 hfinfo->name, fvalue_get_floating(&fi->value));
3428 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3429 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3433 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3434 "%s: %." STRINGIFY(DBL_DIG) "g",
3435 hfinfo->name, fvalue_get_floating(&fi->value));
3436 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3437 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3440 case FT_ABSOLUTE_TIME:
3441 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3442 "%s: %s", hfinfo->name,
3443 abs_time_to_str(fvalue_get(&fi->value)));
3444 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3445 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3448 case FT_RELATIVE_TIME:
3449 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3450 "%s: %s seconds", hfinfo->name,
3451 rel_time_to_secs_str(fvalue_get(&fi->value)));
3452 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3453 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3457 integer = fvalue_get_integer(&fi->value);
3458 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3459 "%s: %s (0x%08X)", hfinfo->name,
3460 get_ipxnet_name(integer), integer);
3461 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3462 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3466 bytes = fvalue_get(&fi->value);
3467 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3468 "%s: %s (%s)", hfinfo->name,
3469 get_ether_name(bytes),
3470 ether_to_str(bytes));
3471 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3472 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3476 ipv4 = fvalue_get(&fi->value);
3477 n_addr = ipv4_get_net_order_addr(ipv4);
3478 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3479 "%s: %s (%s)", hfinfo->name,
3480 get_hostname(n_addr),
3481 ip_to_str((guint8*)&n_addr));
3482 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3483 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3487 bytes = fvalue_get(&fi->value);
3488 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3489 "%s: %s (%s)", hfinfo->name,
3490 get_hostname6((struct e_in6_addr *)bytes),
3491 ip6_to_str((struct e_in6_addr*)bytes));
3492 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3493 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3497 bytes = fvalue_get(&fi->value);
3498 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3499 "%s: %s", hfinfo->name,
3500 guid_to_str(bytes));
3501 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3502 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3506 bytes = fvalue_get(&fi->value);
3507 name = (oid_resolv_enabled()) ? get_oid_name(bytes, fvalue_length(&fi->value)) : NULL;
3509 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3510 "%s: %s (%s)", hfinfo->name,
3511 oid_to_str(bytes, fvalue_length(&fi->value)), name);
3513 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3514 "%s: %s", hfinfo->name,
3515 oid_to_str(bytes, fvalue_length(&fi->value)));
3517 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3518 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3523 case FT_UINT_STRING:
3524 bytes = fvalue_get(&fi->value);
3525 if(strlen(bytes) > ITEM_LABEL_LENGTH) {
3526 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3527 "%s [truncated]: %s", hfinfo->name,
3528 format_text(bytes, strlen(bytes)));
3530 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3531 "%s: %s", hfinfo->name,
3532 format_text(bytes, strlen(bytes)));
3534 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3535 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3539 g_error("hfinfo->type %d (%s) not handled\n",
3541 ftype_name(hfinfo->type));
3542 DISSECTOR_ASSERT_NOT_REACHED();
3548 fill_label_boolean(field_info *fi, gchar *label_str)
3550 char *p = label_str;
3551 int bitfield_byte_length = 0, bitwidth;
3552 guint32 unshifted_value;
3554 int ret; /*tmp return value */
3556 header_field_info *hfinfo = fi->hfinfo;
3557 static const true_false_string default_tf = { "True", "False" };
3558 const true_false_string *tfstring = &default_tf;
3560 if (hfinfo->strings) {
3561 tfstring = (const struct true_false_string*) hfinfo->strings;
3564 value = fvalue_get_integer(&fi->value);
3565 if (hfinfo->bitmask) {
3566 /* Figure out the bit width */
3567 bitwidth = hfinfo_bitwidth(hfinfo);
3570 unshifted_value = value;
3571 if (hfinfo->bitshift > 0) {
3572 unshifted_value <<= hfinfo->bitshift;
3575 /* Create the bitfield first */
3576 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3577 bitfield_byte_length = p - label_str;
3580 /* Fill in the textual info */
3581 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3582 "%s: %s", hfinfo->name,
3583 value ? tfstring->true_string : tfstring->false_string);
3584 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3585 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3589 /* Fills data for bitfield ints with val_strings */
3591 fill_label_enumerated_bitfield(field_info *fi, gchar *label_str)
3593 const char *format = NULL;
3595 int bitfield_byte_length, bitwidth;
3596 guint32 unshifted_value;
3598 int ret; /*tmp return value */
3600 header_field_info *hfinfo = fi->hfinfo;
3602 /* Figure out the bit width */
3603 bitwidth = hfinfo_bitwidth(hfinfo);
3605 /* Pick the proper format string */
3606 format = hfinfo_uint_vals_format(hfinfo);
3609 unshifted_value = fvalue_get_integer(&fi->value);
3610 value = unshifted_value;
3611 if (hfinfo->bitshift > 0) {
3612 unshifted_value <<= hfinfo->bitshift;
3615 /* Create the bitfield first */
3616 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3617 bitfield_byte_length = p - label_str;
3619 /* Fill in the textual info using stored (shifted) value */
3620 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3621 format, hfinfo->name,
3622 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3623 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3624 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3628 fill_label_numeric_bitfield(field_info *fi, gchar *label_str)
3630 const char *format = NULL;
3632 int bitfield_byte_length, bitwidth;
3633 guint32 unshifted_value;
3635 int ret; /*tmp return value */
3637 header_field_info *hfinfo = fi->hfinfo;
3639 /* Figure out the bit width */
3640 bitwidth = hfinfo_bitwidth(hfinfo);
3642 /* Pick the proper format string */
3643 format = hfinfo_uint_format(hfinfo);
3646 unshifted_value = fvalue_get_integer(&fi->value);
3647 value = unshifted_value;
3648 if (hfinfo->bitshift > 0) {
3649 unshifted_value <<= hfinfo->bitshift;
3652 /* Create the bitfield using */
3653 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
3654 bitfield_byte_length = p - label_str;
3656 /* Fill in the textual info using stored (shifted) value */
3657 if (IS_BASE_DUAL(hfinfo->display)) {
3658 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3659 format, hfinfo->name, value, value);
3661 ret = g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
3662 format, hfinfo->name, value);
3664 if ((ret == -1) || (ret >= (ITEM_LABEL_LENGTH - bitfield_byte_length)))
3665 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3670 fill_label_enumerated_uint(field_info *fi, gchar *label_str)
3672 const char *format = NULL;
3673 header_field_info *hfinfo = fi->hfinfo;
3675 int ret; /*tmp return value */
3677 /* Pick the proper format string */
3678 format = hfinfo_uint_vals_format(hfinfo);
3680 value = fvalue_get_integer(&fi->value);
3682 /* Fill in the textual info */
3683 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3684 format, hfinfo->name,
3685 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3686 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3687 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3691 fill_label_uint(field_info *fi, gchar *label_str)
3693 const char *format = NULL;
3694 header_field_info *hfinfo = fi->hfinfo;
3696 int ret; /*tmp return value */
3698 /* Pick the proper format string */
3699 format = hfinfo_uint_format(hfinfo);
3700 value = fvalue_get_integer(&fi->value);
3702 /* Fill in the textual info */
3703 if (IS_BASE_DUAL(hfinfo->display)) {
3704 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3705 format, hfinfo->name, value, value);
3707 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3708 format, hfinfo->name, value);
3710 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3711 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3715 fill_label_uint64(field_info *fi, gchar *label_str)
3717 const char *format = NULL;
3718 header_field_info *hfinfo = fi->hfinfo;
3720 int ret; /*tmp return value */
3722 /* Pick the proper format string */
3723 format = hfinfo_uint64_format(hfinfo);
3724 value = fvalue_get_integer64(&fi->value);
3726 /* Fill in the textual info */
3727 if (IS_BASE_DUAL(hfinfo->display)) {
3728 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3729 format, hfinfo->name, value, value);
3731 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3732 format, hfinfo->name, value);
3734 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3735 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3739 fill_label_enumerated_int(field_info *fi, gchar *label_str)
3741 const char *format = NULL;
3742 header_field_info *hfinfo = fi->hfinfo;
3744 int ret; /*tmp return value */
3746 /* Pick the proper format string */
3747 format = hfinfo_int_vals_format(hfinfo);
3748 value = fvalue_get_integer(&fi->value);
3750 /* Fill in the textual info */
3751 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3752 format, hfinfo->name,
3753 val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
3754 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3755 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3759 fill_label_int(field_info *fi, gchar *label_str)
3761 const char *format = NULL;
3762 header_field_info *hfinfo = fi->hfinfo;
3764 int ret; /*tmp return value */
3766 /* Pick the proper format string */
3767 format = hfinfo_int_format(hfinfo);
3768 value = fvalue_get_integer(&fi->value);
3770 /* Fill in the textual info */
3771 if (IS_BASE_DUAL(hfinfo->display)) {
3772 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3773 format, hfinfo->name, value, value);
3775 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3776 format, hfinfo->name, value);
3778 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3779 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3783 fill_label_int64(field_info *fi, gchar *label_str)
3785 const char *format = NULL;
3786 header_field_info *hfinfo = fi->hfinfo;
3788 int ret; /*tmp return value */
3790 /* Pick the proper format string */
3791 format = hfinfo_int64_format(hfinfo);
3792 value = fvalue_get_integer64(&fi->value);
3794 /* Fill in the textual info */
3795 if (IS_BASE_DUAL(hfinfo->display)) {
3796 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3797 format, hfinfo->name, value, value);
3799 ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
3800 format, hfinfo->name, value);
3802 if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
3803 label_str[ITEM_LABEL_LENGTH - 1] = '\0';
3807 hfinfo_bitwidth(header_field_info *hfinfo)
3811 if (!hfinfo->bitmask) {
3815 switch(hfinfo->type) {
3833 bitwidth = hfinfo->display; /* hacky? :) */
3836 DISSECTOR_ASSERT_NOT_REACHED();
3843 hfinfo_uint_vals_format(header_field_info *hfinfo)
3845 const char *format = NULL;
3847 switch(hfinfo->display) {
3850 format = "%s: %s (%u)";
3852 case BASE_OCT: /* I'm lazy */
3853 format = "%s: %s (%o)";
3857 switch(hfinfo->type) {
3859 format = "%s: %s (0x%02x)";
3862 format = "%s: %s (0x%04x)";
3865 format = "%s: %s (0x%06x)";
3868 format = "%s: %s (0x%08x)";
3871 DISSECTOR_ASSERT_NOT_REACHED();
3876 DISSECTOR_ASSERT_NOT_REACHED();
3883 hfinfo_uint_format(header_field_info *hfinfo)
3885 const char *format = NULL;
3887 /* Pick the proper format string */
3888 if (hfinfo->type == FT_FRAMENUM) {
3890 * Frame numbers are always displayed in decimal.
3894 switch(hfinfo->display) {
3899 switch(hfinfo->type) {
3901 format = "%s: %u (0x%02x)";
3904 format = "%s: %u (0x%04x)";
3907 format = "%s: %u (0x%06x)";
3910 format = "%s: %u (0x%08x)";
3913 DISSECTOR_ASSERT_NOT_REACHED();
3917 case BASE_OCT: /* I'm lazy */
3921 switch(hfinfo->type) {
3923 format = "%s: 0x%02x";
3926 format = "%s: 0x%04x";
3929 format = "%s: 0x%06x";
3932 format = "%s: 0x%08x";
3935 DISSECTOR_ASSERT_NOT_REACHED();
3940 switch(hfinfo->type) {
3942 format = "%s: 0x%02x (%u)";
3945 format = "%s: 0x%04x (%u)";
3948 format = "%s: 0x%06x (%u)";
3951 format = "%s: 0x%08x (%u)";
3954 DISSECTOR_ASSERT_NOT_REACHED();
3959 DISSECTOR_ASSERT_NOT_REACHED();
3967 hfinfo_int_vals_format(header_field_info *hfinfo)
3969 const char *format = NULL;
3971 switch(hfinfo->display) {
3974 format = "%s: %s (%d)";
3976 case BASE_OCT: /* I'm lazy */
3977 format = "%s: %s (%o)";
3981 switch(hfinfo->type) {
3983 format = "%s: %s (0x%02x)";
3986 format = "%s: %s (0x%04x)";
3989 format = "%s: %s (0x%06x)";
3992 format = "%s: %s (0x%08x)";
3995 DISSECTOR_ASSERT_NOT_REACHED();
4000 DISSECTOR_ASSERT_NOT_REACHED();
4007 hfinfo_uint64_format(header_field_info *hfinfo)
4009 const char *format = NULL;
4011 /* Pick the proper format string */
4012 switch(hfinfo->display) {
4014 format = "%s: %" PRIu64;
4017 format = "%s: %" PRIu64 " (%" PRIx64 ")";
4019 case BASE_OCT: /* I'm lazy */
4020 format = "%s: %" PRIo64;
4023 format = "%s: 0x%016" PRIx64;
4026 format = "%s: 0x%016" PRIx64 " (%" PRIu64 ")";
4029 DISSECTOR_ASSERT_NOT_REACHED();
4036 hfinfo_int_format(header_field_info *hfinfo)
4038 const char *format = NULL;
4040 /* Pick the proper format string */
4041 switch(hfinfo->display) {
4046 switch(hfinfo->type) {
4048 format = "%s: %d (0x%02x)";
4051 format = "%s: %d (0x%04x)";
4054 format = "%s: %d (0x%06x)";
4057 format = "%s: %d (0x%08x)";
4060 DISSECTOR_ASSERT_NOT_REACHED();
4063 case BASE_OCT: /* I'm lazy */
4067 switch(hfinfo->type) {
4069 format = "%s: 0x%02x";
4072 format = "%s: 0x%04x";
4075 format = "%s: 0x%06x";
4078 format = "%s: 0x%08x";
4081 DISSECTOR_ASSERT_NOT_REACHED();
4085 switch(hfinfo->type) {
4087 format = "%s: 0x%02x (%d)";
4090 format = "%s: 0x%04x (%d)";
4093 format = "%s: 0x%06x (%d)";
4096 format = "%s: 0x%08x (%d)";
4099 DISSECTOR_ASSERT_NOT_REACHED();
4104 DISSECTOR_ASSERT_NOT_REACHED();
4111 hfinfo_int64_format(header_field_info *hfinfo)
4113 const char *format = NULL;
4115 /* Pick the proper format string */
4116 switch(hfinfo->display) {
4118 format = "%s: %" PRId64;
4121 format = "%s: %" PRId64 " (%" PRIx64 ")";
4123 case BASE_OCT: /* I'm lazy */
4124 format = "%s: %" PRIo64;
4127 format = "%s: 0x%016" PRIx64;
4130 format = "%s: 0x%016" PRIx64 " (%" PRId64 ")";
4133 DISSECTOR_ASSERT_NOT_REACHED();
4142 proto_registrar_n(void)
4144 return gpa_hfinfo.len;
4148 proto_registrar_get_name(int n)
4150 header_field_info *hfinfo;
4152 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4153 return hfinfo->name;
4157 proto_registrar_get_abbrev(int n)
4159 header_field_info *hfinfo;
4161 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4162 return hfinfo->abbrev;
4166 proto_registrar_get_ftype(int n)
4168 header_field_info *hfinfo;
4170 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4171 return hfinfo->type;
4175 proto_registrar_get_parent(int n)
4177 header_field_info *hfinfo;
4179 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4180 return hfinfo->parent;
4184 proto_registrar_is_protocol(int n)
4186 header_field_info *hfinfo;
4188 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4189 return (hfinfo->parent == -1 ? TRUE : FALSE);
4192 /* Returns length of field in packet (not necessarily the length
4193 * in our internal representation, as in the case of IPv4).
4194 * 0 means undeterminable at time of registration
4195 * -1 means the field is not registered. */
4197 proto_registrar_get_length(int n)
4199 header_field_info *hfinfo;
4201 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
4202 return ftype_length(hfinfo->type);
4207 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
4208 * it exists anywhere, or FALSE if it exists nowhere. */
4210 proto_check_for_protocol_or_field(proto_tree* tree, int id)
4212 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
4217 else if (g_ptr_array_len(ptrs) > 0) {
4225 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
4226 * This only works if the hfindex was "primed" before the dissection
4227 * took place, as we just pass back the already-created GPtrArray*.
4228 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
4231 proto_get_finfo_ptr_array(proto_tree *tree, int id)
4233 return g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
4234 GINT_TO_POINTER(id));
4238 /* Helper struct and function for proto_find_info() */
4245 find_finfo(proto_node *node, gpointer data)
4247 field_info *fi = PITEM_FINFO(node);
4248 if (fi && fi->hfinfo) {
4249 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
4250 g_ptr_array_add(((ffdata_t*)data)->array, fi);
4254 /* Don't stop traversing. */
4258 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
4259 * This works on any proto_tree, primed or unprimed, but actually searches
4260 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
4261 * The caller does need to free the returned GPtrArray with
4262 * g_ptr_array_free(<array>, FALSE).
4265 proto_find_finfo(proto_tree *tree, int id)
4269 ffdata.array = g_ptr_array_new();
4272 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
4274 return ffdata.array;
4285 check_for_offset(proto_node *node, gpointer data)
4287 field_info *fi = PITEM_FINFO(node);
4288 offset_search_t *offsearch = data;
4290 /* !fi == the top most container node which holds nothing */
4291 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
4292 if (offsearch->offset >= (guint) fi->start &&
4293 offsearch->offset < (guint) (fi->start + fi->length)) {
4295 offsearch->finfo = fi;
4296 return FALSE; /* keep traversing */
4299 return FALSE; /* keep traversing */
4302 /* Search a proto_tree backwards (from leaves to root) looking for the field
4303 * whose start/length occupies 'offset' */
4304 /* XXX - I couldn't find an easy way to search backwards, so I search
4305 * forwards, w/o stopping. Therefore, the last finfo I find will the be
4306 * the one I want to return to the user. This algorithm is inefficient
4307 * and could be re-done, but I'd have to handle all the children and
4308 * siblings of each node myself. When I have more time I'll do that.
4311 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
4313 offset_search_t offsearch;
4315 offsearch.offset = offset;
4316 offsearch.finfo = NULL;
4317 offsearch.tvb = tvb;
4319 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
4321 return offsearch.finfo;
4324 /* Dumps the protocols in the registration database to stdout. An independent
4325 * program can take this output and format it into nice tables or HTML or
4328 * There is one record per line. The fields are tab-delimited.
4330 * Field 1 = protocol name
4331 * Field 2 = protocol short name
4332 * Field 3 = protocol filter name
4335 proto_registrar_dump_protocols(void)
4337 protocol_t *protocol;
4341 for (i = proto_get_first_protocol(&cookie); i != -1;
4342 i = proto_get_next_protocol(&cookie)) {
4343 protocol = find_protocol_by_id(i);
4344 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
4345 protocol->filter_name);
4349 /* Dumps the value_string and true/false strings for fields that have
4350 * them. There is one record per line. Fields are tab-delimited.
4351 * There are two types of records, Value String records and True/False
4352 * String records. The first field, 'V' or 'T', indicates the type
4358 * Field 2 = field abbreviation to which this value string corresponds
4359 * Field 3 = Integer value
4362 * True/False Strings
4363 * ------------------
4365 * Field 2 = field abbreviation to which this true/false string corresponds
4366 * Field 3 = True String
4367 * Field 4 = False String
4370 proto_registrar_dump_values(void)
4372 header_field_info *hfinfo, *parent_hfinfo;
4374 const value_string *vals;
4375 const true_false_string *tfs;
4377 len = gpa_hfinfo.len;
4378 for (i = 0; i < len ; i++) {
4379 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4381 if (hfinfo->id == hf_text_only) {
4385 /* ignore protocols */
4386 if (proto_registrar_is_protocol(i)) {
4389 /* process header fields */
4392 * If this field isn't at the head of the list of
4393 * fields with this name, skip this field - all
4394 * fields with the same name are really just versions
4395 * of the same field stored in different bits, and
4396 * should have the same type/radix/value list, and
4397 * just differ in their bit masks. (If a field isn't
4398 * a bitfield, but can be, say, 1 or 2 bytes long,
4399 * it can just be made FT_UINT16, meaning the
4400 * *maximum* length is 2 bytes, and be used
4403 if (hfinfo->same_name_prev != NULL)
4406 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4411 if (hfinfo->type == FT_UINT8 ||
4412 hfinfo->type == FT_UINT16 ||
4413 hfinfo->type == FT_UINT24 ||
4414 hfinfo->type == FT_UINT32 ||
4415 hfinfo->type == FT_UINT64 ||
4416 hfinfo->type == FT_INT8 ||
4417 hfinfo->type == FT_INT16 ||
4418 hfinfo->type == FT_INT24 ||
4419 hfinfo->type == FT_INT32 ||
4420 hfinfo->type == FT_INT64) {
4422 vals = hfinfo->strings;
4424 else if (hfinfo->type == FT_BOOLEAN) {
4425 tfs = hfinfo->strings;
4428 /* Print value strings? */
4431 while (vals[vi].strptr) {
4432 /* Print in the proper base */
4433 if (hfinfo->display == BASE_HEX) {
4434 printf("V\t%s\t0x%x\t%s\n",
4440 printf("V\t%s\t%u\t%s\n",
4449 /* Print true/false strings? */
4451 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
4452 tfs->true_string, tfs->false_string);
4458 /* Dumps the contents of the registration database to stdout. An indepedent
4459 * program can take this output and format it into nice tables or HTML or
4462 * There is one record per line. Each record is either a protocol or a header
4463 * field, differentiated by the first field. The fields are tab-delimited.
4468 * Field 2 = descriptive protocol name
4469 * Field 3 = protocol abbreviation
4475 * Field 2 = descriptive field name
4476 * Field 3 = field abbreviation
4477 * Field 4 = type ( textual representation of the the ftenum type )
4478 * Field 5 = parent protocol abbreviation
4479 * Field 6 = blurb describing field
4483 * Field 2 = descriptive field name
4484 * Field 3 = field abbreviation
4485 * Field 4 = type ( textual representation of the the ftenum type )
4486 * Field 5 = parent protocol abbreviation
4487 * Field 6 = blurb describing field
4488 * Field 7 = base for display (for integer types)
4489 * Field 8 = blurb describing field (yes, apparently we repeated this accidentally)
4493 * Field 2 = descriptive field name
4494 * Field 3 = field abbreviation
4495 * Field 4 = type ( textual representation of the the ftenum type )
4496 * Field 5 = parent protocol abbreviation
4497 * Field 6 = blurb describing field
4498 * Field 7 = base for display (for integer types)
4502 proto_registrar_dump_fields(int format)
4504 header_field_info *hfinfo, *parent_hfinfo;
4506 const char *enum_name;
4507 const char *base_name;
4510 len = gpa_hfinfo.len;
4511 for (i = 0; i < len ; i++) {
4512 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
4515 * Skip fields with zero-length names or abbreviations;
4516 * the pseudo-field for "proto_tree_add_text()" is such
4517 * a field, and we don't want it in the list of filterable
4520 * XXX - perhaps the name and abbrev field should be null
4521 * pointers rather than null strings for that pseudo-field,
4522 * but we'd have to add checks for null pointers in some
4523 * places if we did that.
4525 * Or perhaps protocol tree items added with
4526 * "proto_tree_add_text()" should have -1 as the field index,
4527 * with no pseudo-field being used, but that might also
4528 * require special checks for -1 to be added.
4530 /* XXX - we could just skip the special text
4531 * pseudo-field by testing: if (hfinfo->id == hf_text_only)
4533 if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
4536 /* format for protocols */
4537 if (proto_registrar_is_protocol(i)) {
4538 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
4540 /* format for header fields */
4543 * If this field isn't at the head of the list of
4544 * fields with this name, skip this field - all
4545 * fields with the same name are really just versions
4546 * of the same field stored in different bits, and
4547 * should have the same type/radix/value list, and
4548 * just differ in their bit masks. (If a field isn't
4549 * a bitfield, but can be, say, 1 or 2 bytes long,
4550 * it can just be made FT_UINT16, meaning the
4551 * *maximum* length is 2 bytes, and be used
4554 if (hfinfo->same_name_prev != NULL)
4557 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4559 enum_name = ftype_name(hfinfo->type);
4563 if (hfinfo->type == FT_UINT8 ||
4564 hfinfo->type == FT_UINT16 ||
4565 hfinfo->type == FT_UINT24 ||
4566 hfinfo->type == FT_UINT32 ||
4567 hfinfo->type == FT_UINT64 ||
4568 hfinfo->type == FT_INT8 ||
4569 hfinfo->type == FT_INT16 ||
4570 hfinfo->type == FT_INT24 ||
4571 hfinfo->type == FT_INT32 ||
4572 hfinfo->type == FT_INT64) {
4575 switch(hfinfo->display) {
4577 base_name = "BASE_NONE";
4580 base_name = "BASE_DEC";
4583 base_name = "BASE_HEX";
4586 base_name = "BASE_OCT";
4589 base_name = "BASE_DEC_HEX";
4592 base_name = "BASE_HEX_DEC";
4598 blurb = hfinfo->blurb;
4602 printf("F\t%s\t%s\t%s\t%s\t%s\n",
4603 hfinfo->name, hfinfo->abbrev, enum_name,
4604 parent_hfinfo->abbrev, blurb);
4606 else if (format == 2) {
4607 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
4608 hfinfo->name, hfinfo->abbrev, enum_name,
4609 parent_hfinfo->abbrev, blurb,
4612 else if (format == 3) {
4613 printf("F\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
4614 hfinfo->name, hfinfo->abbrev, enum_name,
4615 parent_hfinfo->abbrev, blurb,
4616 base_name, hfinfo->bitmask);
4619 g_assert_not_reached();
4626 hfinfo_numeric_format(header_field_info *hfinfo)
4628 const char *format = NULL;
4630 /* Pick the proper format string */
4631 if (hfinfo->type == FT_FRAMENUM) {
4633 * Frame numbers are always displayed in decimal.
4635 format = "%s == %u";
4637 /* Pick the proper format string */
4638 switch(hfinfo->display) {
4641 case BASE_OCT: /* I'm lazy */
4642 switch(hfinfo->type) {
4647 format = "%s == %u";
4650 format = "%s == %" PRIu64;
4656 format = "%s == %d";
4659 format = "%s == %" PRId64;
4662 DISSECTOR_ASSERT_NOT_REACHED();
4668 switch(hfinfo->type) {
4670 format = "%s == 0x%02x";
4673 format = "%s == 0x%04x";
4676 format = "%s == 0x%06x";
4679 format = "%s == 0x%08x";
4682 format = "%s == 0x%016" PRIx64;
4685 DISSECTOR_ASSERT_NOT_REACHED();
4690 DISSECTOR_ASSERT_NOT_REACHED();
4698 * Returns TRUE if we can do a "match selected" on the field, FALSE
4702 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
4704 header_field_info *hfinfo;
4707 hfinfo = finfo->hfinfo;
4708 DISSECTOR_ASSERT(hfinfo);
4710 switch(hfinfo->type) {
4729 case FT_ABSOLUTE_TIME:
4730 case FT_RELATIVE_TIME:
4733 case FT_UINT_STRING:
4741 * These all have values, so we can match.
4747 * This doesn't have a value, so we'd match
4748 * on the raw bytes at this address.
4750 * Should we be allowed to access to the raw bytes?
4751 * If "edt" is NULL, the answer is "no".
4757 * Is this field part of the raw frame tvbuff?
4758 * If not, we can't use "frame[N:M]" to match
4761 * XXX - should this be frame-relative, or
4762 * protocol-relative?
4764 * XXX - does this fallback for non-registered
4765 * fields even make sense?
4767 if (finfo->ds_tvb != edt->tvb)
4771 * If the length is 0, there's nothing to match, so
4772 * we can't match. (Also check for negative values,
4773 * just in case, as we'll cast it to an unsigned
4776 length = finfo->length;
4781 * Don't go past the end of that tvbuff.
4783 if ((guint)length > tvb_length(finfo->ds_tvb))
4784 length = tvb_length(finfo->ds_tvb);
4791 /* This function returns a string allocated with packet lifetime scope.
4792 * You do not need to [g_]free() this string since it will be automatically
4793 * freed once the next packet is dissected.
4796 proto_construct_dfilter_string(field_info *finfo, epan_dissect_t *edt)
4798 header_field_info *hfinfo;
4804 gint start, length, length_remaining;
4807 hfinfo = finfo->hfinfo;
4808 DISSECTOR_ASSERT(hfinfo);
4809 abbrev_len = strlen(hfinfo->abbrev);
4812 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
4813 * functions for FT_UINT and FT_INT types, as we choose the base in
4814 * the string expression based on the display base of the field.
4816 * Note that the base does matter, as this is also used for
4817 * the protocolinfo tap.
4819 * It might be nice to use them in "proto_item_fill_label()"
4820 * as well, although, there, you'd have to deal with the base
4821 * *and* with resolved values for addresses.
4823 * Perhaps we need two different val_to_string routines, one
4824 * to generate items for display filters and one to generate
4825 * strings for display, and pass to both of them the
4826 * "display" and "strings" values in the header_field_info
4827 * structure for the field, so they can get the base and,
4828 * if the field is Boolean or an enumerated integer type,
4829 * the tables used to generate human-readable values.
4831 switch(hfinfo->type) {
4843 * 4 bytes for " == ".
4846 * a sign + up to 10 digits of 32-bit integer,
4849 * "0x" + 8 digits of 32-bit integer, in hex;
4851 * 11 digits of 32-bit integer, in octal.
4852 * (No, we don't do octal, but this way,
4853 * we know that if we do, this will still
4856 * 1 byte for the trailing '\0'.
4858 dfilter_len = abbrev_len + 4 + 11 + 1;
4859 buf = ep_alloc0(dfilter_len);
4860 format = hfinfo_numeric_format(hfinfo);
4861 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer(&finfo->value));
4867 * 4 bytes for " == ".
4870 * a sign + up to 20 digits of 32-bit integer,
4873 * "0x" + 16 digits of 32-bit integer, in hex;
4875 * 22 digits of 32-bit integer, in octal.
4876 * (No, we don't do octal, but this way,
4877 * we know that if we do, this will still
4880 * 1 byte for the trailing '\0'.
4882 dfilter_len = abbrev_len + 4 + 22 + 1;
4883 buf = ep_alloc0(dfilter_len);
4884 format = hfinfo_numeric_format(hfinfo);
4885 g_snprintf(buf, dfilter_len, format, hfinfo->abbrev, fvalue_get_integer64(&finfo->value));
4888 /* These use the fvalue's "to_string_repr" method. */
4897 case FT_ABSOLUTE_TIME:
4898 case FT_RELATIVE_TIME:
4903 /* Figure out the string length needed.
4904 * The ft_repr length.
4905 * 4 bytes for " == ".
4906 * 1 byte for trailing NUL.
4908 dfilter_len = fvalue_string_repr_len(&finfo->value,
4910 dfilter_len += abbrev_len + 4 + 1;
4911 buf = ep_alloc0(dfilter_len);
4913 /* Create the string */
4914 g_snprintf(buf, dfilter_len, "%s == ", hfinfo->abbrev);
4915 fvalue_to_string_repr(&finfo->value,
4917 &buf[abbrev_len + 4]);
4921 buf = ep_strdup(finfo->hfinfo->abbrev);
4926 * This doesn't have a value, so we'd match
4927 * on the raw bytes at this address.
4929 * Should we be allowed to access to the raw bytes?
4930 * If "edt" is NULL, the answer is "no".
4936 * Is this field part of the raw frame tvbuff?
4937 * If not, we can't use "frame[N:M]" to match
4940 * XXX - should this be frame-relative, or
4941 * protocol-relative?
4943 * XXX - does this fallback for non-registered
4944 * fields even make sense?
4946 if (finfo->ds_tvb != edt->tvb)
4947 return NULL; /* you lose */
4950 * If the length is 0, there's nothing to match, so
4951 * we can't match. (Also check for negative values,
4952 * just in case, as we'll cast it to an unsigned
4955 length = finfo->length;
4960 * Don't go past the end of that tvbuff.
4962 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
4963 if (length > length_remaining)
4964 length = length_remaining;
4968 start = finfo->start;
4969 buf_len = 32 + length * 3;
4970 buf = ep_alloc0(buf_len);
4973 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "frame[%d:%d] == ", finfo->start, length);
4974 for (i=0;i<length; i++) {
4975 c = tvb_get_guint8(finfo->ds_tvb, start);
4978 ptr += g_snprintf(ptr, buf_len-(ptr-buf), "%02x", c);
4981 ptr += snprintf(ptr, buf_len-(ptr-buf), ":%02x", c);