1 /* proto.c
2 * Routines for protocol tree
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "config.h"
12 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <glib.h>
17 #include <float.h>
18 #include <errno.h>
19
20 #include <wsutil/bits_ctz.h>
21 #include <wsutil/bits_count_ones.h>
22 #include <wsutil/sign_ext.h>
23 #include <wsutil/utf8_entities.h>
24 #include <wsutil/json_dumper.h>
25 #include <wsutil/wslog.h>
26 #include <wsutil/ws_assert.h>
27
28 #include <ftypes/ftypes-int.h>
29
30 #include "packet.h"
31 #include "exceptions.h"
32 #include "ptvcursor.h"
33 #include "strutil.h"
34 #include "addr_resolv.h"
35 #include "address_types.h"
36 #include "oids.h"
37 #include "proto.h"
38 #include "epan_dissect.h"
39 #include "tvbuff.h"
40 #include <epan/wmem_scopes.h>
41 #include "charsets.h"
42 #include "column-utils.h"
43 #include "to_str.h"
44 #include "osi-utils.h"
45 #include "expert.h"
46 #include "show_exception.h"
47 #include "in_cksum.h"
48 #include "register-int.h"
49
50 #include <wsutil/crash_info.h>
51 #include <wsutil/epochs.h>
52
53 /* Ptvcursor limits */
54 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
55 #define SUBTREE_MAX_LEVELS 256
56
57 typedef struct __subtree_lvl {
58 gint cursor_offset;
59 proto_item *it;
60 proto_tree *tree;
61 } subtree_lvl;
62
63 struct ptvcursor {
64 wmem_allocator_t *scope;
65 subtree_lvl *pushed_tree;
66 guint8 pushed_tree_index;
67 guint8 pushed_tree_max;
68 proto_tree *tree;
69 tvbuff_t *tvb;
70 gint offset;
71 };
72
73 #define cVALS(x) (const value_string*)(x)
74
75 /** See inlined comments.
76 @param tree the tree to append this item to
77 @param free_block a code block to call to free resources if this returns
78 @return NULL if 'tree' is null */
79 #define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block) \
80 if (!tree) { \
81 free_block; \
82 return NULL; \
83 }
84
85 /** See inlined comments.
86 @param tree the tree to append this item to
87 @param free_block a code block to call to free resources if this returns
88 @return NULL if 'tree' is null */
89 #define CHECK_FOR_NULL_TREE(tree) \
90 CHECK_FOR_NULL_TREE_AND_FREE(tree, ((void)0))
91
92 /** See inlined comments.
93 @param tree the tree to append this item to
94 @param hfindex field index
95 @param hfinfo header_field
96 @param free_block a code block to call to free resources if this returns
97 @return the header field matching 'hfinfo' */
98 #define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
99 /* If this item is not referenced we don't have to do much work \
100 at all but we should still return a node so that field items \
101 below this node (think proto_item_add_subtree()) will still \
102 have somewhere to attach to or else filtering will not work \
103 (they would be ignored since tree would be NULL). \
104 DON'T try to fake a node where PTREE_FINFO(tree) is NULL \
105 since dissectors that want to do proto_item_set_len() or \
106 other operations that dereference this would crash. \
107 We fake FT_PROTOCOL unless some clients have requested us \
108 not to do so. \
109 */ \
110 PTREE_DATA(tree)->count++; \
111 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
112 if (PTREE_DATA(tree)->count > prefs.gui_max_tree_items) { \
113 free_block; \
114 if (wireshark_abort_on_too_many_items) \
115 ws_error("Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
116 hfinfo->abbrev, prefs.gui_max_tree_items); \
117 /* Let the exception handler add items to the tree */ \
118 PTREE_DATA(tree)->count = 0; \
119 THROW_MESSAGE(DissectorError, \
120 wmem_strdup_printf(PNODE_POOL(tree), \
121 "Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
122 hfinfo->abbrev, prefs.gui_max_tree_items)); \
123 } \
124 if (!(PTREE_DATA(tree)->visible)) { \
125 if (PTREE_FINFO(tree)) { \
126 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
127 && (hfinfo->type != FT_PROTOCOL || \
128 PTREE_DATA(tree)->fake_protocols)) { \
129 free_block; \
130 /* just return tree back to the caller */\
131 return tree; \
132 } \
133 } \
134 }
135
136 /** See inlined comments.
137 @param tree the tree to append this item to
138 @param hfindex field index
139 @param hfinfo header_field
140 @return the header field matching 'hfinfo' */
141 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
142 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
143
144
145 /** See inlined comments.
146 @param pi the created protocol item we're about to return */
147 #define TRY_TO_FAKE_THIS_REPR(pi) \
148 ws_assert(pi); \
149 if (!(PTREE_DATA(pi)->visible)) { \
150 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
151 * items string representation */ \
152 return pi; \
153 }
154 /* Same as above but returning void */
155 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
156 if (!pi) \
157 return; \
158 if (!(PTREE_DATA(pi)->visible)) { \
159 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
160 * items string representation */ \
161 return; \
162 }
163 /* Similar to above, but allows a NULL tree */
164 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
165 if ((pi == NULL) || (!(PTREE_DATA(pi)->visible))) { \
166 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
167 * items string representation */ \
168 return pi; \
169 }
170
171 #ifdef ENABLE_CHECK_FILTER
172 #define CHECK_HF_VALUE(type, modifier, start_values) \
173 { \
174 const type *current; \
175 int n, m; \
176 current = start_values; \
177 for (n=0; current; n++, current++) { \
178 /* Drop out if we reached the end. */ \
179 if ((current->value == 0) && (current->strptr == NULL)) { \
180 break; \
181 } \
182 /* Check value against all previous */ \
183 for (m=0; m < n; m++) { \
184 /* There are lots of duplicates with the same string, \
185 so only report if different... */ \
186 if ((start_values[m].value == current->value) && \
187 (strcmp(start_values[m].strptr, current->strptr) != 0)) { \
188 ws_warning("Field '%s' (%s) has a conflicting entry in its" \
189 " value_string: %" modifier "u is at indices %u (%s) and %u (%s)", \
190 hfinfo->name, hfinfo->abbrev, \
191 current->value, m, start_values[m].strptr, n, current->strptr); \
192 } \
193 } \
194 } \
195 }
196 #endif
197
198
199 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
200 static const char *hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo);
201 static int hfinfo_bitoffset(const header_field_info *hfinfo);
202 static int hfinfo_mask_bitwidth(const header_field_info *hfinfo);
203 static int hfinfo_container_bitwidth(const header_field_info *hfinfo);
204
205 static void label_mark_truncated(char *label_str, gsize name_pos);
206 #define LABEL_MARK_TRUNCATED_START(label_str) label_mark_truncated(label_str, 0)
207
208 static void fill_label_boolean(field_info *fi, gchar *label_str);
209 static void fill_label_bitfield_char(field_info *fi, gchar *label_str);
210 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
211 static void fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed);
212 static void fill_label_bitfield_varint(field_info *fi, gchar *label_str, gboolean is_signed);
213 static void fill_label_bitfield_varint64(field_info *fi, gchar *label_str, gboolean is_signed);
214 static void fill_label_char(field_info *fi, gchar *label_str);
215 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
216 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
217
218 static const char *hfinfo_char_value_format_display(int display, char buf[7], guint32 value);
219 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
220 static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value);
221 static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
222 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
223 static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
224 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
225 static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
226 static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
227 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
228 static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
229
230 static void proto_cleanup_base(void);
231
232 static proto_item *
233 proto_tree_add_node(proto_tree *tree, field_info *fi);
234
235 static void
236 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
237 gint *item_length, const guint encoding);
238
239 static gint
240 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
241 gint length, guint item_length, const gint encoding);
242
243 static field_info *
244 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
245 const gint start, const gint item_length);
246
247 static proto_item *
248 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
249 gint start, gint *length);
250
251 static void
252 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
253 static void
254 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
255
256 static void
257 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data);
258 static void
259 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
260 static void
261 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
262 static void
263 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
264 static void
265 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
266 static void
267 proto_tree_set_string(field_info *fi, const char* value);
268 static void
269 proto_tree_set_ax25(field_info *fi, const guint8* value);
270 static void
271 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
272 static void
273 proto_tree_set_vines(field_info *fi, const guint8* value);
274 static void
275 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
276 static void
277 proto_tree_set_ether(field_info *fi, const guint8* value);
278 static void
279 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
280 static void
281 proto_tree_set_ipxnet(field_info *fi, guint32 value);
282 static void
283 proto_tree_set_ipv4(field_info *fi, ws_in4_addr value);
284 static void
285 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
286 static void
287 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
288 static void
289 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
290 static void
291 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
292 static void
293 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
294 static void
295 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
296 static void
297 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
298 static void
299 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length);
300 static void
301 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
302 static void
303 proto_tree_set_boolean(field_info *fi, guint64 value);
304 static void
305 proto_tree_set_float(field_info *fi, float value);
306 static void
307 proto_tree_set_double(field_info *fi, double value);
308 static void
309 proto_tree_set_uint(field_info *fi, guint32 value);
310 static void
311 proto_tree_set_int(field_info *fi, gint32 value);
312 static void
313 proto_tree_set_uint64(field_info *fi, guint64 value);
314 static void
315 proto_tree_set_int64(field_info *fi, gint64 value);
316 static void
317 proto_tree_set_eui64(field_info *fi, const guint64 value);
318 static void
319 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
320
321 /* Handle type length mismatch (now filterable) expert info */
322 static int proto_type_length_mismatch = -1;
323 static expert_field ei_type_length_mismatch_error = EI_INIT;
324 static expert_field ei_type_length_mismatch_warn = EI_INIT;
325 static void register_type_length_mismatch(void);
326
327 /* Handle number string decoding errors with expert info */
328 static int proto_number_string_decoding_error = -1;
329 static expert_field ei_number_string_decoding_failed_error = EI_INIT;
330 static expert_field ei_number_string_decoding_erange_error = EI_INIT;
331 static void register_number_string_decodinws_error(void);
332
333 /* Handle string errors expert info */
334 static int proto_string_errors = -1;
335 static expert_field ei_string_trailing_characters = EI_INIT;
336 static void register_string_errors(void);
337
338 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
339
340 /* special-case header field used within proto.c */
341 static header_field_info hfi_text_only =
342 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
343 int hf_text_only = -1;
344
345 /* Structure for information about a protocol */
346 struct _protocol {
347 const char *name; /* long description */
348 const char *short_name; /* short description */
349 const char *filter_name; /* name of this protocol in filters */
350 GPtrArray *fields; /* fields for this protocol */
351 int proto_id; /* field ID for this protocol */
352 gboolean is_enabled; /* TRUE if protocol is enabled */
353 gboolean enabled_by_default; /* TRUE if protocol is enabled by default */
354 gboolean can_toggle; /* TRUE if is_enabled can be changed */
355 int parent_proto_id; /* Used to identify "pino"s (Protocol In Name Only).
356 For dissectors that need a protocol name so they
357 can be added to a dissector table, but use the
358 parent_proto_id for things like enable/disable */
359 GList *heur_list; /* Heuristic dissectors associated with this protocol */
360 };
361
362 /* List of all protocols */
363 static GList *protocols = NULL;
364
365 /* Structure stored for deregistered g_slice */
366 struct g_slice_data {
367 gsize block_size;
368 gpointer mem_block;
369 };
370
371 /* Deregistered fields */
372 static GPtrArray *deregistered_fields = NULL;
373 static GPtrArray *deregistered_data = NULL;
374 static GPtrArray *deregistered_slice = NULL;
375
376 /* indexed by prefix, contains initializers */
377 static GHashTable* prefixes = NULL;
378
379 /* Contains information about a field when a dissector calls
380 * proto_tree_add_item. */
381 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
382 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
383
384 /* Contains the space for proto_nodes. */
385 #define PROTO_NODE_INIT(node) \
386 node->first_child = NULL; \
387 node->last_child = NULL; \
388 node->next = NULL;
389
390 #define PROTO_NODE_FREE(pool, node) \
391 wmem_free(pool, node)
392
393 /* String space for protocol and field items for the GUI */
394 #define ITEM_LABEL_NEW(pool, il) \
395 il = wmem_new(pool, item_label_t);
396 #define ITEM_LABEL_FREE(pool, il) \
397 wmem_free(pool, il);
398
399 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
400 if((guint)hfindex >= gpa_hfinfo.len && wireshark_abort_on_dissector_bug) \
401 ws_error("Unregistered hf! index=%d", hfindex); \
402 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
403 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
404 hfinfo = gpa_hfinfo.hfi[hfindex];
405
406 /* List which stores protocols and fields that have been registered */
407 typedef struct _gpa_hfinfo_t {
408 guint32 len;
409 guint32 allocated_len;
410 header_field_info **hfi;
411 } gpa_hfinfo_t;
412
413 static gpa_hfinfo_t gpa_hfinfo;
414
415 /* Hash table of abbreviations and IDs */
416 static GHashTable *gpa_name_map = NULL;
417 static header_field_info *same_name_hfinfo;
418
419 /* Hash table protocol aliases. const char * -> const char * */
420 static GHashTable *gpa_protocol_aliases = NULL;
421
422 /*
423 * We're called repeatedly with the same field name when sorting a column.
424 * Cache our last gpa_name_map hit for faster lookups.
425 */
426 static char *last_field_name = NULL;
427 static header_field_info *last_hfinfo;
428
save_same_name_hfinfo(gpointer data)429 static void save_same_name_hfinfo(gpointer data)
430 {
431 same_name_hfinfo = (header_field_info*)data;
432 }
433
434 /* Points to the first element of an array of bits, indexed by
435 a subtree item type; that array element is TRUE if subtrees of
436 an item of that type are to be expanded. */
437 static guint32 *tree_is_expanded;
438
439 /* Number of elements in that array. */
440 int num_tree_types;
441
442 /* Name hashtables for fast detection of duplicate names */
443 static GHashTable* proto_names = NULL;
444 static GHashTable* proto_short_names = NULL;
445 static GHashTable* proto_filter_names = NULL;
446
447 static gint
proto_compare_name(gconstpointer p1_arg,gconstpointer p2_arg)448 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
449 {
450 const protocol_t *p1 = (const protocol_t *)p1_arg;
451 const protocol_t *p2 = (const protocol_t *)p2_arg;
452
453 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
454 }
455
456 static GSList *dissector_plugins = NULL;
457
458 #ifdef HAVE_PLUGINS
459 void
proto_register_plugin(const proto_plugin * plug)460 proto_register_plugin(const proto_plugin *plug)
461 {
462 dissector_plugins = g_slist_prepend(dissector_plugins, (proto_plugin *)plug);
463 }
464 #else /* HAVE_PLUGINS */
465 void
proto_register_plugin(const proto_plugin * plug _U_)466 proto_register_plugin(const proto_plugin *plug _U_)
467 {
468 ws_warning("proto_register_plugin: built without support for binary plugins");
469 }
470 #endif /* HAVE_PLUGINS */
471
472 static void
call_plugin_register_protoinfo(gpointer data,gpointer user_data _U_)473 call_plugin_register_protoinfo(gpointer data, gpointer user_data _U_)
474 {
475 proto_plugin *plug = (proto_plugin *)data;
476
477 if (plug->register_protoinfo) {
478 plug->register_protoinfo();
479 }
480 }
481
482 static void
call_plugin_register_handoff(gpointer data,gpointer user_data _U_)483 call_plugin_register_handoff(gpointer data, gpointer user_data _U_)
484 {
485 proto_plugin *plug = (proto_plugin *)data;
486
487 if (plug->register_handoff) {
488 plug->register_handoff();
489 }
490 }
491
492 /* initialize data structures and register protocols and fields */
493 void
proto_init(GSList * register_all_plugin_protocols_list,GSList * register_all_plugin_handoffs_list,register_cb cb,gpointer client_data)494 proto_init(GSList *register_all_plugin_protocols_list,
495 GSList *register_all_plugin_handoffs_list,
496 register_cb cb,
497 gpointer client_data)
498 {
499 proto_cleanup_base();
500
501 proto_names = g_hash_table_new(g_str_hash, g_str_equal);
502 proto_short_names = g_hash_table_new(g_str_hash, g_str_equal);
503 proto_filter_names = g_hash_table_new(g_str_hash, g_str_equal);
504
505 gpa_hfinfo.len = 0;
506 gpa_hfinfo.allocated_len = 0;
507 gpa_hfinfo.hfi = NULL;
508 gpa_name_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
509 gpa_protocol_aliases = g_hash_table_new(g_str_hash, g_str_equal);
510 deregistered_fields = g_ptr_array_new();
511 deregistered_data = g_ptr_array_new();
512 deregistered_slice = g_ptr_array_new();
513
514 /* Initialize the ftype subsystem */
515 ftypes_initialize();
516
517 /* Initialize the addres type subsystem */
518 address_types_initialize();
519
520 /* Register one special-case FT_TEXT_ONLY field for use when
521 converting wireshark to new-style proto_tree. These fields
522 are merely strings on the GUI tree; they are not filterable */
523 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
524
525 /* Register the pseudo-protocols used for exceptions. */
526 register_show_exception();
527 register_type_length_mismatch();
528 register_number_string_decodinws_error();
529 register_string_errors();
530
531 /* Have each built-in dissector register its protocols, fields,
532 dissector tables, and dissectors to be called through a
533 handle, and do whatever one-time initialization it needs to
534 do. */
535 register_all_protocols(cb, client_data);
536
537 /* Now call the registration routines for all epan plugins. */
538 for (GSList *l = register_all_plugin_protocols_list; l != NULL; l = l->next) {
539 ((void (*)(register_cb, gpointer))l->data)(cb, client_data);
540 }
541
542 /* Now call the registration routines for all dissector plugins. */
543 if (cb)
544 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
545 g_slist_foreach(dissector_plugins, call_plugin_register_protoinfo, NULL);
546
547 /* Now call the "handoff registration" routines of all built-in
548 dissectors; those routines register the dissector in other
549 dissectors' handoff tables, and fetch any dissector handles
550 they need. */
551 register_all_protocol_handoffs(cb, client_data);
552
553 /* Now do the same with epan plugins. */
554 for (GSList *l = register_all_plugin_handoffs_list; l != NULL; l = l->next) {
555 ((void (*)(register_cb, gpointer))l->data)(cb, client_data);
556 }
557
558 /* Now do the same with dissector plugins. */
559 if (cb)
560 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
561 g_slist_foreach(dissector_plugins, call_plugin_register_handoff, NULL);
562
563 /* sort the protocols by protocol name */
564 protocols = g_list_sort(protocols, proto_compare_name);
565
566 /* We've assigned all the subtree type values; allocate the array
567 for them, and zero it out. */
568 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
569 }
570
571 static void
proto_cleanup_base(void)572 proto_cleanup_base(void)
573 {
574 protocol_t *protocol;
575 header_field_info *hfinfo;
576
577 /* Free the abbrev/ID hash table */
578 if (gpa_name_map) {
579 g_hash_table_destroy(gpa_name_map);
580 gpa_name_map = NULL;
581 }
582 if (gpa_protocol_aliases) {
583 g_hash_table_destroy(gpa_protocol_aliases);
584 gpa_protocol_aliases = NULL;
585 }
586 g_free(last_field_name);
587 last_field_name = NULL;
588
589 while (protocols) {
590 protocol = (protocol_t *)protocols->data;
591 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
592 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
593
594 g_slice_free(header_field_info, hfinfo);
595 if (protocol->parent_proto_id != -1) {
596 // pino protocol
597 DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields
598 DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list
599 } else {
600 if (protocol->fields) {
601 g_ptr_array_free(protocol->fields, TRUE);
602 }
603 g_list_free(protocol->heur_list);
604 }
605 protocols = g_list_remove(protocols, protocol);
606 g_free(protocol);
607 }
608
609 if (proto_names) {
610 g_hash_table_destroy(proto_names);
611 proto_names = NULL;
612 }
613
614 if (proto_short_names) {
615 g_hash_table_destroy(proto_short_names);
616 proto_short_names = NULL;
617 }
618
619 if (proto_filter_names) {
620 g_hash_table_destroy(proto_filter_names);
621 proto_filter_names = NULL;
622 }
623
624 if (gpa_hfinfo.allocated_len) {
625 gpa_hfinfo.len = 0;
626 gpa_hfinfo.allocated_len = 0;
627 g_free(gpa_hfinfo.hfi);
628 gpa_hfinfo.hfi = NULL;
629 }
630
631 if (deregistered_fields) {
632 g_ptr_array_free(deregistered_fields, TRUE);
633 deregistered_fields = NULL;
634 }
635
636 if (deregistered_data) {
637 g_ptr_array_free(deregistered_data, TRUE);
638 deregistered_data = NULL;
639 }
640
641 if (deregistered_slice) {
642 g_ptr_array_free(deregistered_slice, TRUE);
643 deregistered_slice = NULL;
644 }
645
646 g_free(tree_is_expanded);
647 tree_is_expanded = NULL;
648
649 if (prefixes)
650 g_hash_table_destroy(prefixes);
651 }
652
653 void
proto_cleanup(void)654 proto_cleanup(void)
655 {
656 proto_free_deregistered_fields();
657 proto_cleanup_base();
658
659 g_slist_free(dissector_plugins);
660 dissector_plugins = NULL;
661 }
662
663 static gboolean
proto_tree_traverse_pre_order(proto_tree * tree,proto_tree_traverse_func func,gpointer data)664 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
665 gpointer data)
666 {
667 proto_node *pnode = tree;
668 proto_node *child;
669 proto_node *current;
670
671 if (func(pnode, data))
672 return TRUE;
673
674 child = pnode->first_child;
675 while (child != NULL) {
676 /*
677 * The routine we call might modify the child, e.g. by
678 * freeing it, so we get the child's successor before
679 * calling that routine.
680 */
681 current = child;
682 child = current->next;
683 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
684 return TRUE;
685 }
686
687 return FALSE;
688 }
689
690 gboolean
proto_tree_traverse_post_order(proto_tree * tree,proto_tree_traverse_func func,gpointer data)691 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
692 gpointer data)
693 {
694 proto_node *pnode = tree;
695 proto_node *child;
696 proto_node *current;
697
698 child = pnode->first_child;
699 while (child != NULL) {
700 /*
701 * The routine we call might modify the child, e.g. by
702 * freeing it, so we get the child's successor before
703 * calling that routine.
704 */
705 current = child;
706 child = current->next;
707 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
708 return TRUE;
709 }
710 if (func(pnode, data))
711 return TRUE;
712
713 return FALSE;
714 }
715
716 void
proto_tree_children_foreach(proto_tree * tree,proto_tree_foreach_func func,gpointer data)717 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
718 gpointer data)
719 {
720 proto_node *node = tree;
721 proto_node *current;
722
723 if (!node)
724 return;
725
726 node = node->first_child;
727 while (node != NULL) {
728 current = node;
729 node = current->next;
730 func((proto_tree *)current, data);
731 }
732 }
733
734 static void
free_GPtrArray_value(gpointer key,gpointer value,gpointer user_data _U_)735 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
736 {
737 GPtrArray *ptrs = (GPtrArray *)value;
738 gint hfid = GPOINTER_TO_UINT(key);
739 header_field_info *hfinfo;
740
741 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
742 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
743 /* when a field is referenced by a filter this also
744 affects the refcount for the parent protocol so we need
745 to adjust the refcount for the parent as well
746 */
747 if (hfinfo->parent != -1) {
748 header_field_info *parent_hfinfo;
749 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
750 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
751 }
752 hfinfo->ref_type = HF_REF_TYPE_NONE;
753 }
754
755 g_ptr_array_free(ptrs, TRUE);
756 }
757
758 static void
proto_tree_free_node(proto_node * node,gpointer data _U_)759 proto_tree_free_node(proto_node *node, gpointer data _U_)
760 {
761 field_info *finfo = PNODE_FINFO(node);
762
763 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
764
765 FVALUE_CLEANUP(&finfo->value);
766 }
767
768 void
proto_tree_reset(proto_tree * tree)769 proto_tree_reset(proto_tree *tree)
770 {
771 tree_data_t *tree_data = PTREE_DATA(tree);
772
773 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
774
775 /* free tree data */
776 if (tree_data->interesting_hfids) {
777 /* Free all the GPtrArray's in the interesting_hfids hash. */
778 g_hash_table_foreach(tree_data->interesting_hfids,
779 free_GPtrArray_value, NULL);
780
781 /* And then remove all values. */
782 g_hash_table_remove_all(tree_data->interesting_hfids);
783 }
784
785 /* Reset track of the number of children */
786 tree_data->count = 0;
787
788 PROTO_NODE_INIT(tree);
789 }
790
791 /* frees the resources that the dissection a proto_tree uses */
792 void
proto_tree_free(proto_tree * tree)793 proto_tree_free(proto_tree *tree)
794 {
795 tree_data_t *tree_data = PTREE_DATA(tree);
796
797 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
798
799 /* free tree data */
800 if (tree_data->interesting_hfids) {
801 /* Free all the GPtrArray's in the interesting_hfids hash. */
802 g_hash_table_foreach(tree_data->interesting_hfids,
803 free_GPtrArray_value, NULL);
804
805 /* And then destroy the hash. */
806 g_hash_table_destroy(tree_data->interesting_hfids);
807 }
808
809 g_slice_free(tree_data_t, tree_data);
810
811 g_slice_free(proto_tree, tree);
812 }
813
814 /* Is the parsing being done for a visible proto_tree or an invisible one?
815 * By setting this correctly, the proto_tree creation is sped up by not
816 * having to call g_vsnprintf and copy strings around.
817 */
818 gboolean
proto_tree_set_visible(proto_tree * tree,gboolean visible)819 proto_tree_set_visible(proto_tree *tree, gboolean visible)
820 {
821 gboolean old_visible = PTREE_DATA(tree)->visible;
822
823 PTREE_DATA(tree)->visible = visible;
824
825 return old_visible;
826 }
827
828 void
proto_tree_set_fake_protocols(proto_tree * tree,gboolean fake_protocols)829 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
830 {
831 PTREE_DATA(tree)->fake_protocols = fake_protocols;
832 }
833
834 /* Assume dissector set only its protocol fields.
835 This function is called by dissectors and allows the speeding up of filtering
836 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
837 and thus skip calling most of the expensive proto_tree_add_...()
838 functions.
839 If the tree is visible we implicitly assume the field is referenced.
840 */
841 gboolean
proto_field_is_referenced(proto_tree * tree,int proto_id)842 proto_field_is_referenced(proto_tree *tree, int proto_id)
843 {
844 register header_field_info *hfinfo;
845
846
847 if (!tree)
848 return FALSE;
849
850 if (PTREE_DATA(tree)->visible)
851 return TRUE;
852
853 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
854 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
855 return TRUE;
856
857 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
858 return TRUE;
859
860 return FALSE;
861 }
862
863
864 /* Finds a record in the hfinfo array by id. */
865 header_field_info *
proto_registrar_get_nth(guint hfindex)866 proto_registrar_get_nth(guint hfindex)
867 {
868 register header_field_info *hfinfo;
869
870 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
871 return hfinfo;
872 }
873
874
875 /* Prefix initialization
876 * this allows for a dissector to register a display filter name prefix
877 * so that it can delay the initialization of the hf array as long as
878 * possible.
879 */
880
881 /* compute a hash for the part before the dot of a display filter */
882 static guint
prefix_hash(gconstpointer key)883 prefix_hash (gconstpointer key) {
884 /* end the string at the dot and compute its hash */
885 gchar* copy = g_strdup((const gchar *)key);
886 gchar* c = copy;
887 guint tmp;
888
889 for (; *c; c++) {
890 if (*c == '.') {
891 *c = 0;
892 break;
893 }
894 }
895
896 tmp = g_str_hash(copy);
897 g_free(copy);
898 return tmp;
899 }
900
901 /* are both strings equal up to the end or the dot? */
902 static gboolean
prefix_equal(gconstpointer ap,gconstpointer bp)903 prefix_equal (gconstpointer ap, gconstpointer bp) {
904 const gchar* a = (const gchar *)ap;
905 const gchar* b = (const gchar *)bp;
906
907 do {
908 gchar ac = *a++;
909 gchar bc = *b++;
910
911 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
912
913 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
914 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
915
916 if (ac != bc) return FALSE;
917 } while (1);
918
919 return FALSE;
920 }
921
922 /* Register a new prefix for "delayed" initialization of field arrays */
923 void
proto_register_prefix(const char * prefix,prefix_initializer_t pi)924 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
925 if (! prefixes ) {
926 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
927 }
928
929 g_hash_table_insert(prefixes, (gpointer)prefix, (gpointer)pi);
930 }
931
932 /* helper to call all prefix initializers */
933 static gboolean
initialize_prefix(gpointer k,gpointer v,gpointer u _U_)934 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
935 ((prefix_initializer_t)v)((const char *)k);
936 return TRUE;
937 }
938
939 /** Initialize every remaining uninitialized prefix. */
940 void
proto_initialize_all_prefixes(void)941 proto_initialize_all_prefixes(void) {
942 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
943 }
944
945 /* Finds a record in the hfinfo array by name.
946 * If it fails to find it in the already registered fields,
947 * it tries to find and call an initializer in the prefixes
948 * table and if so it looks again.
949 */
950
951 header_field_info *
proto_registrar_get_byname(const char * field_name)952 proto_registrar_get_byname(const char *field_name)
953 {
954 header_field_info *hfinfo;
955 prefix_initializer_t pi;
956
957 if (!field_name)
958 return NULL;
959
960 if (g_strcmp0(field_name, last_field_name) == 0) {
961 return last_hfinfo;
962 }
963
964 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
965
966 if (hfinfo) {
967 g_free(last_field_name);
968 last_field_name = g_strdup(field_name);
969 last_hfinfo = hfinfo;
970 return hfinfo;
971 }
972
973 if (!prefixes)
974 return NULL;
975
976 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
977 pi(field_name);
978 g_hash_table_remove(prefixes, field_name);
979 } else {
980 return NULL;
981 }
982
983 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
984
985 if (hfinfo) {
986 g_free(last_field_name);
987 last_field_name = g_strdup(field_name);
988 last_hfinfo = hfinfo;
989 }
990 return hfinfo;
991 }
992
993 header_field_info*
proto_registrar_get_byalias(const char * alias_name)994 proto_registrar_get_byalias(const char *alias_name)
995 {
996 if (!alias_name) {
997 return NULL;
998 }
999
1000 /* Find our aliased protocol. */
1001 char *an_copy = g_strdup(alias_name);
1002 char *dot = strchr(an_copy, '.');
1003 if (dot) {
1004 *dot = '\0';
1005 }
1006 const char *proto_pfx = (const char *) g_hash_table_lookup(gpa_protocol_aliases, an_copy);
1007 if (!proto_pfx) {
1008 g_free(an_copy);
1009 return NULL;
1010 }
1011
1012 /* Construct our aliased field and look it up. */
1013 GString *filter_name = g_string_new(proto_pfx);
1014 if (dot) {
1015 g_string_append_printf(filter_name, ".%s", dot+1);
1016 }
1017 header_field_info *hfinfo = proto_registrar_get_byname(filter_name->str);
1018 g_free(an_copy);
1019 g_string_free(filter_name, TRUE);
1020
1021 return hfinfo;
1022 }
1023
1024 int
proto_registrar_get_id_byname(const char * field_name)1025 proto_registrar_get_id_byname(const char *field_name)
1026 {
1027 header_field_info *hfinfo;
1028
1029 hfinfo = proto_registrar_get_byname(field_name);
1030
1031 if (!hfinfo)
1032 return -1;
1033
1034 return hfinfo->id;
1035 }
1036
1037
1038 static char *
hfinfo_format_text(wmem_allocator_t * scope,const header_field_info * hfinfo,const guchar * string)1039 hfinfo_format_text(wmem_allocator_t *scope, const header_field_info *hfinfo,
1040 const guchar *string)
1041 {
1042 switch (hfinfo->display) {
1043 case STR_ASCII:
1044 return format_text(scope, string, strlen(string));
1045 /*
1046 case STR_ASCII_WSP
1047 return format_text_wsp(string, strlen(string));
1048 */
1049 case STR_UNICODE:
1050 return format_text(scope, string, strlen(string));
1051 }
1052
1053 return format_text(scope, string, strlen(string));
1054 }
1055
1056 static char *
hfinfo_format_bytes(wmem_allocator_t * scope,const header_field_info * hfinfo,const guint8 * bytes,guint length)1057 hfinfo_format_bytes(wmem_allocator_t *scope, const header_field_info *hfinfo,
1058 const guint8 *bytes, guint length)
1059 {
1060 char *str = NULL;
1061 const guint8 *p;
1062 gboolean is_printable;
1063
1064 if (bytes) {
1065 if (hfinfo->display & BASE_SHOW_ASCII_PRINTABLE) {
1066 /*
1067 * Check whether all bytes are printable.
1068 */
1069 is_printable = TRUE;
1070 for (p = bytes; p < bytes+length; p++) {
1071 if (!g_ascii_isprint(*p)) {
1072 /* Not printable. */
1073 is_printable = FALSE;
1074 break;
1075 }
1076 }
1077
1078 /*
1079 * If all bytes are printable ASCII, show the bytes
1080 * as a string - in quotes to indicate that it's
1081 * a string.
1082 */
1083 if (is_printable) {
1084 str = wmem_strdup_printf(scope, "\"%.*s\"",
1085 (int)length, bytes);
1086 return str;
1087 }
1088 }
1089
1090 /*
1091 * Either it's not printable ASCII, or we don't care whether
1092 * it's printable ASCII; show it as hex bytes.
1093 */
1094 switch (FIELD_DISPLAY(hfinfo->display)) {
1095 case SEP_DOT:
1096 str = bytes_to_str_punct(scope, bytes, length, '.');
1097 break;
1098 case SEP_DASH:
1099 str = bytes_to_str_punct(scope, bytes, length, '-');
1100 break;
1101 case SEP_COLON:
1102 str = bytes_to_str_punct(scope, bytes, length, ':');
1103 break;
1104 case SEP_SPACE:
1105 str = bytes_to_str_punct(scope, bytes, length, ' ');
1106 break;
1107 case BASE_NONE:
1108 default:
1109 if (prefs.display_byte_fields_with_spaces) {
1110 str = bytes_to_str_punct(scope, bytes, length, ' ');
1111 } else {
1112 str = bytes_to_str(scope, bytes, length);
1113 }
1114 break;
1115 }
1116 }
1117 else {
1118 if (hfinfo->display & BASE_ALLOW_ZERO) {
1119 str = wmem_strdup(scope, "<none>");
1120 } else {
1121 str = wmem_strdup(scope, "<MISSING>");
1122 }
1123 }
1124 return str;
1125 }
1126
1127 static void
ptvcursor_new_subtree_levels(ptvcursor_t * ptvc)1128 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
1129 {
1130 subtree_lvl *pushed_tree;
1131
1132 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
1133 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
1134
1135 pushed_tree = (subtree_lvl *)wmem_realloc(ptvc->scope, (void *)ptvc->pushed_tree, sizeof(subtree_lvl) * ptvc->pushed_tree_max);
1136 DISSECTOR_ASSERT(pushed_tree != NULL);
1137 ptvc->pushed_tree = pushed_tree;
1138 }
1139
1140 static void
ptvcursor_free_subtree_levels(ptvcursor_t * ptvc)1141 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
1142 {
1143 ptvc->pushed_tree = NULL;
1144 ptvc->pushed_tree_max = 0;
1145 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
1146 ptvc->pushed_tree_index = 0;
1147 }
1148
1149 /* Allocates an initializes a ptvcursor_t with 3 variables:
1150 * proto_tree, tvbuff, and offset. */
1151 ptvcursor_t *
ptvcursor_new(wmem_allocator_t * scope,proto_tree * tree,tvbuff_t * tvb,gint offset)1152 ptvcursor_new(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb, gint offset)
1153 {
1154 ptvcursor_t *ptvc;
1155
1156 ptvc = wmem_new(scope, ptvcursor_t);
1157 ptvc->scope = scope;
1158 ptvc->tree = tree;
1159 ptvc->tvb = tvb;
1160 ptvc->offset = offset;
1161 ptvc->pushed_tree = NULL;
1162 ptvc->pushed_tree_max = 0;
1163 ptvc->pushed_tree_index = 0;
1164 return ptvc;
1165 }
1166
1167
1168 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1169 void
ptvcursor_free(ptvcursor_t * ptvc)1170 ptvcursor_free(ptvcursor_t *ptvc)
1171 {
1172 ptvcursor_free_subtree_levels(ptvc);
1173 /*g_free(ptvc);*/
1174 }
1175
1176 /* Returns tvbuff. */
1177 tvbuff_t *
ptvcursor_tvbuff(ptvcursor_t * ptvc)1178 ptvcursor_tvbuff(ptvcursor_t *ptvc)
1179 {
1180 return ptvc->tvb;
1181 }
1182
1183 /* Returns current offset. */
1184 gint
ptvcursor_current_offset(ptvcursor_t * ptvc)1185 ptvcursor_current_offset(ptvcursor_t *ptvc)
1186 {
1187 return ptvc->offset;
1188 }
1189
1190 proto_tree *
ptvcursor_tree(ptvcursor_t * ptvc)1191 ptvcursor_tree(ptvcursor_t *ptvc)
1192 {
1193 if (!ptvc)
1194 return NULL;
1195
1196 return ptvc->tree;
1197 }
1198
1199 void
ptvcursor_set_tree(ptvcursor_t * ptvc,proto_tree * tree)1200 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
1201 {
1202 ptvc->tree = tree;
1203 }
1204
1205 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1206 proto_tree *
ptvcursor_push_subtree(ptvcursor_t * ptvc,proto_item * it,gint ett_subtree)1207 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1208 {
1209 subtree_lvl *subtree;
1210 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
1211 ptvcursor_new_subtree_levels(ptvc);
1212
1213 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1214 subtree->tree = ptvc->tree;
1215 subtree->it= NULL;
1216 ptvc->pushed_tree_index++;
1217 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
1218 }
1219
1220 /* pops a subtree */
1221 void
ptvcursor_pop_subtree(ptvcursor_t * ptvc)1222 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
1223 {
1224 subtree_lvl *subtree;
1225
1226 if (ptvc->pushed_tree_index <= 0)
1227 return;
1228
1229 ptvc->pushed_tree_index--;
1230 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1231 if (subtree->it != NULL)
1232 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
1233
1234 ptvc->tree = subtree->tree;
1235 }
1236
1237 /* saves the current tvb offset and the item in the current subtree level */
1238 static void
ptvcursor_subtree_set_item(ptvcursor_t * ptvc,proto_item * it)1239 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
1240 {
1241 subtree_lvl *subtree;
1242
1243 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
1244
1245 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
1246 subtree->it = it;
1247 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
1248 }
1249
1250 /* Creates a subtree and adds it to the cursor as the working tree but does not
1251 * save the old working tree */
1252 proto_tree *
ptvcursor_set_subtree(ptvcursor_t * ptvc,proto_item * it,gint ett_subtree)1253 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1254 {
1255 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1256 return ptvc->tree;
1257 }
1258
1259 static proto_tree *
ptvcursor_add_subtree_item(ptvcursor_t * ptvc,proto_item * it,gint ett_subtree,gint length)1260 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
1261 {
1262 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1263 if (length == SUBTREE_UNDEFINED_LENGTH)
1264 ptvcursor_subtree_set_item(ptvc, it);
1265 return ptvcursor_tree(ptvc);
1266 }
1267
1268 /* Add an item to the tree and create a subtree
1269 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1270 * In this case, when the subtree will be closed, the parent item length will
1271 * be equal to the advancement of the cursor since the creation of the subtree.
1272 */
1273 proto_tree *
ptvcursor_add_with_subtree(ptvcursor_t * ptvc,int hfindex,gint length,const guint encoding,gint ett_subtree)1274 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
1275 const guint encoding, gint ett_subtree)
1276 {
1277 proto_item *it;
1278
1279 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1280 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1281 }
1282
1283 static proto_item *
1284 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
1285
1286 /* Add a text node to the tree and create a subtree
1287 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1288 * In this case, when the subtree will be closed, the item length will be equal
1289 * to the advancement of the cursor since the creation of the subtree.
1290 */
1291 proto_tree *
ptvcursor_add_text_with_subtree(ptvcursor_t * ptvc,gint length,gint ett_subtree,const char * format,...)1292 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
1293 gint ett_subtree, const char *format, ...)
1294 {
1295 proto_item *pi;
1296 va_list ap;
1297 header_field_info *hfinfo;
1298 proto_tree *tree;
1299
1300 tree = ptvcursor_tree(ptvc);
1301
1302 CHECK_FOR_NULL_TREE(tree);
1303
1304 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1305
1306 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1307 ptvcursor_current_offset(ptvc), length);
1308
1309 TRY_TO_FAKE_THIS_REPR(pi);
1310
1311 va_start(ap, format);
1312 proto_tree_set_representation(pi, format, ap);
1313 va_end(ap);
1314
1315 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1316 }
1317
1318 /* Add a text-only node, leaving it to our caller to fill the text in */
1319 static proto_item *
proto_tree_add_text_node(proto_tree * tree,tvbuff_t * tvb,gint start,gint length)1320 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1321 {
1322 proto_item *pi;
1323
1324 if (tree == NULL)
1325 return NULL;
1326
1327 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1328
1329 return pi;
1330 }
1331
1332 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1333 proto_item *
proto_tree_add_text_internal(proto_tree * tree,tvbuff_t * tvb,gint start,gint length,const char * format,...)1334 proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1335 const char *format, ...)
1336 {
1337 proto_item *pi;
1338 va_list ap;
1339 header_field_info *hfinfo;
1340
1341 if (length == -1) {
1342 length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
1343 } else {
1344 tvb_ensure_bytes_exist(tvb, start, length);
1345 }
1346
1347 CHECK_FOR_NULL_TREE(tree);
1348
1349 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1350
1351 pi = proto_tree_add_text_node(tree, tvb, start, length);
1352
1353 TRY_TO_FAKE_THIS_REPR(pi);
1354
1355 va_start(ap, format);
1356 proto_tree_set_representation(pi, format, ap);
1357 va_end(ap);
1358
1359 return pi;
1360 }
1361
1362 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1363 proto_item *
proto_tree_add_text_valist_internal(proto_tree * tree,tvbuff_t * tvb,gint start,gint length,const char * format,va_list ap)1364 proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, gint start,
1365 gint length, const char *format, va_list ap)
1366 {
1367 proto_item *pi;
1368 header_field_info *hfinfo;
1369
1370 if (length == -1) {
1371 length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
1372 } else {
1373 tvb_ensure_bytes_exist(tvb, start, length);
1374 }
1375
1376 CHECK_FOR_NULL_TREE(tree);
1377
1378 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1379
1380 pi = proto_tree_add_text_node(tree, tvb, start, length);
1381
1382 TRY_TO_FAKE_THIS_REPR(pi);
1383
1384 proto_tree_set_representation(pi, format, ap);
1385
1386 return pi;
1387 }
1388
1389 /* Add a text-only node that creates a subtree underneath.
1390 */
1391 proto_tree *
proto_tree_add_subtree(proto_tree * tree,tvbuff_t * tvb,gint start,gint length,gint idx,proto_item ** tree_item,const char * text)1392 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *text)
1393 {
1394 return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1395 }
1396
1397 /* Add a text-only node that creates a subtree underneath.
1398 */
1399 proto_tree *
proto_tree_add_subtree_format(proto_tree * tree,tvbuff_t * tvb,gint start,gint length,gint idx,proto_item ** tree_item,const char * format,...)1400 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *format, ...)
1401 {
1402 proto_tree *pt;
1403 proto_item *pi;
1404 va_list ap;
1405
1406 va_start(ap, format);
1407 pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
1408 va_end(ap);
1409
1410 if (tree_item != NULL)
1411 *tree_item = pi;
1412
1413 pt = proto_item_add_subtree(pi, idx);
1414
1415 return pt;
1416 }
1417
1418 /* Add a text-only node for debugging purposes. The caller doesn't need
1419 * to worry about tvbuff, start, or length. Debug message gets sent to
1420 * STDOUT, too */
1421 proto_item *
proto_tree_add_debug_text(proto_tree * tree,const char * format,...)1422 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1423 {
1424 proto_item *pi;
1425 va_list ap;
1426
1427 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1428
1429 if (pi) {
1430 va_start(ap, format);
1431 proto_tree_set_representation(pi, format, ap);
1432 va_end(ap);
1433 }
1434 va_start(ap, format);
1435 vprintf(format, ap);
1436 va_end(ap);
1437 printf("\n");
1438
1439 return pi;
1440 }
1441
1442 proto_item *
proto_tree_add_format_text(proto_tree * tree,tvbuff_t * tvb,gint start,gint length)1443 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1444 {
1445 proto_item *pi;
1446 header_field_info *hfinfo;
1447
1448 CHECK_FOR_NULL_TREE(tree);
1449
1450 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1451
1452 pi = proto_tree_add_text_node(tree, tvb, start, length);
1453
1454 TRY_TO_FAKE_THIS_REPR(pi);
1455
1456 proto_item_set_text(pi, "%s", tvb_format_text(tree->tree_data->pinfo->pool, tvb, start, length));
1457
1458 return pi;
1459 }
1460
1461 proto_item *
proto_tree_add_format_wsp_text(proto_tree * tree,tvbuff_t * tvb,gint start,gint length)1462 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1463 {
1464 proto_item *pi;
1465 header_field_info *hfinfo;
1466 gchar *str;
1467
1468 CHECK_FOR_NULL_TREE(tree);
1469
1470 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1471
1472 pi = proto_tree_add_text_node(tree, tvb, start, length);
1473
1474 TRY_TO_FAKE_THIS_REPR(pi);
1475
1476 str = tvb_format_text_wsp(NULL, tvb, start, length);
1477 proto_item_set_text(pi, "%s", str);
1478 wmem_free(NULL, str);
1479
1480 return pi;
1481 }
1482
proto_report_dissector_bug(const char * format,...)1483 void proto_report_dissector_bug(const char *format, ...)
1484 {
1485 va_list args;
1486
1487 if (wireshark_abort_on_dissector_bug) {
1488 /*
1489 * Try to have the error message show up in the crash
1490 * information.
1491 */
1492 va_start(args, format);
1493 ws_vadd_crash_info(format, args);
1494 va_end(args);
1495
1496 /*
1497 * Print the error message.
1498 */
1499 va_start(args, format);
1500 vfprintf(stderr, format, args);
1501 va_end(args);
1502 putc('\n', stderr);
1503
1504 /*
1505 * And crash.
1506 */
1507 abort();
1508 } else {
1509 va_start(args, format);
1510 VTHROW_FORMATTED(DissectorError, format, args);
1511 va_end(args);
1512 }
1513 }
1514
1515 /* We could probably get away with changing is_error to a minimum length value. */
1516 static void
report_type_length_mismatch(proto_tree * tree,const gchar * descr,int length,gboolean is_error)1517 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error)
1518 {
1519 if (is_error) {
1520 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1521 } else {
1522 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1523 }
1524
1525 if (is_error) {
1526 THROW(ReportedBoundsError);
1527 }
1528 }
1529
1530 static guint32
get_uint_value(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,const guint encoding)1531 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1532 {
1533 guint32 value;
1534 gboolean length_error;
1535
1536 switch (length) {
1537
1538 case 1:
1539 value = tvb_get_guint8(tvb, offset);
1540 if (encoding & ENC_ZIGBEE) {
1541 if (value == 0xFF) { /* Invalid Zigbee length, set to 0 */
1542 value = 0;
1543 }
1544 }
1545 break;
1546
1547 case 2:
1548 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1549 : tvb_get_ntohs(tvb, offset);
1550 if (encoding & ENC_ZIGBEE) {
1551 if (value == 0xFFFF) { /* Invalid Zigbee length, set to 0 */
1552 value = 0;
1553 }
1554 }
1555 break;
1556
1557 case 3:
1558 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1559 : tvb_get_ntoh24(tvb, offset);
1560 break;
1561
1562 case 4:
1563 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1564 : tvb_get_ntohl(tvb, offset);
1565 break;
1566
1567 default:
1568 if (length < 1) {
1569 length_error = TRUE;
1570 value = 0;
1571 } else {
1572 length_error = FALSE;
1573 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1574 : tvb_get_ntohl(tvb, offset);
1575 }
1576 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1577 break;
1578 }
1579 return value;
1580 }
1581
1582 static inline guint64
get_uint64_value(proto_tree * tree,tvbuff_t * tvb,gint offset,guint length,const guint encoding)1583 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, const guint encoding)
1584 {
1585 guint64 value;
1586 gboolean length_error;
1587
1588 switch (length) {
1589
1590 case 1:
1591 value = tvb_get_guint8(tvb, offset);
1592 break;
1593
1594 case 2:
1595 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1596 : tvb_get_ntohs(tvb, offset);
1597 break;
1598
1599 case 3:
1600 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1601 : tvb_get_ntoh24(tvb, offset);
1602 break;
1603
1604 case 4:
1605 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1606 : tvb_get_ntohl(tvb, offset);
1607 break;
1608
1609 case 5:
1610 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh40(tvb, offset)
1611 : tvb_get_ntoh40(tvb, offset);
1612 break;
1613
1614 case 6:
1615 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh48(tvb, offset)
1616 : tvb_get_ntoh48(tvb, offset);
1617 break;
1618
1619 case 7:
1620 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh56(tvb, offset)
1621 : tvb_get_ntoh56(tvb, offset);
1622 break;
1623
1624 case 8:
1625 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1626 : tvb_get_ntoh64(tvb, offset);
1627 break;
1628
1629 default:
1630 if (length < 1) {
1631 length_error = TRUE;
1632 value = 0;
1633 } else {
1634 length_error = FALSE;
1635 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1636 : tvb_get_ntoh64(tvb, offset);
1637 }
1638 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1639 break;
1640 }
1641 return value;
1642 }
1643
1644 static gint32
get_int_value(proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,const guint encoding)1645 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1646 {
1647 gint32 value;
1648 gboolean length_error;
1649
1650 switch (length) {
1651
1652 case 1:
1653 value = tvb_get_gint8(tvb, offset);
1654 break;
1655
1656 case 2:
1657 value = encoding ? tvb_get_letohis(tvb, offset)
1658 : tvb_get_ntohis(tvb, offset);
1659 break;
1660
1661 case 3:
1662 value = encoding ? tvb_get_letohi24(tvb, offset)
1663 : tvb_get_ntohi24(tvb, offset);
1664 break;
1665
1666 case 4:
1667 value = encoding ? tvb_get_letohil(tvb, offset)
1668 : tvb_get_ntohil(tvb, offset);
1669 break;
1670
1671 default:
1672 if (length < 1) {
1673 length_error = TRUE;
1674 value = 0;
1675 } else {
1676 length_error = FALSE;
1677 value = encoding ? tvb_get_letohil(tvb, offset)
1678 : tvb_get_ntohil(tvb, offset);
1679 }
1680 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1681 break;
1682 }
1683 return value;
1684 }
1685
1686 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1687 * be cast-able as a gint64. This is weird, but what the code has always done.
1688 */
1689 static inline guint64
get_int64_value(proto_tree * tree,tvbuff_t * tvb,gint start,guint length,const guint encoding)1690 get_int64_value(proto_tree *tree, tvbuff_t *tvb, gint start, guint length, const guint encoding)
1691 {
1692 guint64 value = get_uint64_value(tree, tvb, start, length, encoding);
1693
1694 switch (length) {
1695 case 7:
1696 value = ws_sign_ext64(value, 56);
1697 break;
1698 case 6:
1699 value = ws_sign_ext64(value, 48);
1700 break;
1701 case 5:
1702 value = ws_sign_ext64(value, 40);
1703 break;
1704 case 4:
1705 value = ws_sign_ext64(value, 32);
1706 break;
1707 case 3:
1708 value = ws_sign_ext64(value, 24);
1709 break;
1710 case 2:
1711 value = ws_sign_ext64(value, 16);
1712 break;
1713 case 1:
1714 value = ws_sign_ext64(value, 8);
1715 break;
1716 }
1717
1718 return value;
1719 }
1720
1721 /* For FT_STRING */
1722 static inline const guint8 *
get_string_value(wmem_allocator_t * scope,tvbuff_t * tvb,gint start,gint length,gint * ret_length,const guint encoding)1723 get_string_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1724 gint length, gint *ret_length, const guint encoding)
1725 {
1726 if (length == -1) {
1727 length = tvb_ensure_captured_length_remaining(tvb, start);
1728 }
1729 *ret_length = length;
1730 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1731 }
1732
1733 /* For FT_STRINGZ */
1734 static inline const guint8 *
get_stringz_value(wmem_allocator_t * scope,proto_tree * tree,tvbuff_t * tvb,gint start,gint length,gint * ret_length,const guint encoding)1735 get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
1736 gint start, gint length, gint *ret_length, const guint encoding)
1737 {
1738 const guint8 *value;
1739
1740 if (length < -1) {
1741 report_type_length_mismatch(tree, "a string", length, TRUE);
1742 }
1743 if (length == -1) {
1744 /* This can throw an exception */
1745 value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
1746 } else {
1747 /* In this case, length signifies the length of the string.
1748 *
1749 * This could either be a null-padded string, which doesn't
1750 * necessarily have a '\0' at the end, or a null-terminated
1751 * string, with a trailing '\0'. (Yes, there are cases
1752 * where you have a string that's both counted and null-
1753 * terminated.)
1754 *
1755 * In the first case, we must allocate a buffer of length
1756 * "length+1", to make room for a trailing '\0'.
1757 *
1758 * In the second case, we don't assume that there is a
1759 * trailing '\0' there, as the packet might be malformed.
1760 * (XXX - should we throw an exception if there's no
1761 * trailing '\0'?) Therefore, we allocate a buffer of
1762 * length "length+1", and put in a trailing '\0', just to
1763 * be safe.
1764 *
1765 * (XXX - this would change if we made string values counted
1766 * rather than null-terminated.)
1767 */
1768 value = tvb_get_string_enc(scope, tvb, start, length, encoding);
1769 }
1770 *ret_length = length;
1771 return value;
1772 }
1773
1774 /* For FT_UINT_STRING */
1775 static inline const guint8 *
get_uint_string_value(wmem_allocator_t * scope,proto_tree * tree,tvbuff_t * tvb,gint start,gint length,gint * ret_length,const guint encoding)1776 get_uint_string_value(wmem_allocator_t *scope, proto_tree *tree,
1777 tvbuff_t *tvb, gint start, gint length, gint *ret_length,
1778 const guint encoding)
1779 {
1780 guint32 n;
1781 const guint8 *value;
1782
1783 /* I believe it's ok if this is called with a NULL tree */
1784 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1785 value = tvb_get_string_enc(scope, tvb, start + length, n, encoding);
1786 length += n;
1787 *ret_length = length;
1788 return value;
1789 }
1790
1791 /* For FT_STRINGZPAD */
1792 static inline const guint8 *
get_stringzpad_value(wmem_allocator_t * scope,tvbuff_t * tvb,gint start,gint length,gint * ret_length,const guint encoding)1793 get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1794 gint length, gint *ret_length, const guint encoding)
1795 {
1796 /*
1797 * XXX - currently, string values are null-
1798 * terminated, so a "zero-padded" string
1799 * isn't special. If we represent string
1800 * values as something that includes a counted
1801 * array of bytes, we'll need to strip the
1802 * trailing NULs.
1803 */
1804 if (length == -1) {
1805 length = tvb_ensure_captured_length_remaining(tvb, start);
1806 }
1807 *ret_length = length;
1808 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1809 }
1810
1811 /* For FT_STRINGZTRUNC */
1812 static inline const guint8 *
get_stringztrunc_value(wmem_allocator_t * scope,tvbuff_t * tvb,gint start,gint length,gint * ret_length,const guint encoding)1813 get_stringztrunc_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1814 gint length, gint *ret_length, const guint encoding)
1815 {
1816 /*
1817 * XXX - currently, string values are null-
1818 * terminated, so a "zero-truncated" string
1819 * isn't special. If we represent string
1820 * values as something that includes a counted
1821 * array of bytes, we'll need to strip everything
1822 * starting with the terminating NUL.
1823 */
1824 if (length == -1) {
1825 length = tvb_ensure_captured_length_remaining(tvb, start);
1826 }
1827 *ret_length = length;
1828 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1829 }
1830
1831 /*
1832 * Deltas between the epochs for various non-UN*X time stamp formats and
1833 * the January 1, 1970, 00:00:00 (proleptic?) UTC epoch for the UN*X time
1834 * stamp format.
1835 */
1836
1837 /*
1838 * NTP Era 0: the epoch is January 1, 1900, 00:00:00 (proleptic?) UTC.
1839 * XXX - if it's OK if this is unsigned, can we just use
1840 * EPOCH_DELTA_1900_01_01_00_00_00_UTC?
1841 */
1842 #define NTP_TIMEDIFF1900TO1970SEC G_GINT64_CONSTANT(2208988800)
1843
1844 /*
1845 * NTP Era 1: the epoch is January 1, 2036, 00:00:00 UTC.
1846 */
1847 #define NTP_TIMEDIFF1970TO2036SEC G_GINT64_CONSTANT(2085978496)
1848
1849 /* this can be called when there is no tree, so tree may be null */
1850 static void
get_time_value(proto_tree * tree,tvbuff_t * tvb,const gint start,const gint length,const guint encoding,nstime_t * time_stamp,const gboolean is_relative)1851 get_time_value(proto_tree *tree, tvbuff_t *tvb, const gint start,
1852 const gint length, const guint encoding, nstime_t *time_stamp,
1853 const gboolean is_relative)
1854 {
1855 guint32 tmpsecs;
1856 guint64 tmp64secs;
1857 guint64 todusecs;
1858
1859 switch (encoding) {
1860
1861 case ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN:
1862 /*
1863 * If the length is 16, 8-byte seconds, followed
1864 * by 8-byte fractional time in nanoseconds,
1865 * both big-endian.
1866 *
1867 * If the length is 12, 8-byte seconds, followed
1868 * by 4-byte fractional time in nanoseconds,
1869 * both big-endian.
1870 *
1871 * If the length is 8, 4-byte seconds, followed
1872 * by 4-byte fractional time in nanoseconds,
1873 * both big-endian.
1874 *
1875 * For absolute times, the seconds are seconds
1876 * since the UN*X epoch.
1877 */
1878 if (length == 16) {
1879 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
1880 time_stamp->nsecs = (guint32)tvb_get_ntoh64(tvb, start+8);
1881 } else if (length == 12) {
1882 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
1883 time_stamp->nsecs = tvb_get_ntohl(tvb, start+8);
1884 } else if (length == 8) {
1885 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1886 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1887 } else if (length == 4) {
1888 /*
1889 * Backwards compatibility.
1890 * ENC_TIME_SECS_NSECS is 0; using
1891 * ENC_BIG_ENDIAN by itself with a 4-byte
1892 * time-in-seconds value was done in the
1893 * past.
1894 */
1895 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1896 time_stamp->nsecs = 0;
1897 } else {
1898 time_stamp->secs = 0;
1899 time_stamp->nsecs = 0;
1900 report_type_length_mismatch(tree, "a timespec", length, (length < 4));
1901 }
1902 break;
1903
1904 case ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN:
1905 /*
1906 * If the length is 16, 8-byte seconds, followed
1907 * by 8-byte fractional time in nanoseconds,
1908 * both little-endian.
1909 *
1910 * If the length is 12, 8-byte seconds, followed
1911 * by 4-byte fractional time in nanoseconds,
1912 * both little-endian.
1913 *
1914 * If the length is 8, 4-byte seconds, followed
1915 * by 4-byte fractional time in nanoseconds,
1916 * both little-endian.
1917 *
1918 * For absolute times, the seconds are seconds
1919 * since the UN*X epoch.
1920 */
1921 if (length == 16) {
1922 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
1923 time_stamp->nsecs = (guint32)tvb_get_letoh64(tvb, start+8);
1924 } else if (length == 12) {
1925 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
1926 time_stamp->nsecs = tvb_get_letohl(tvb, start+8);
1927 } else if (length == 8) {
1928 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1929 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
1930 } else if (length == 4) {
1931 /*
1932 * Backwards compatibility.
1933 * ENC_TIME_SECS_NSECS is 0; using
1934 * ENC_LITTLE_ENDIAN by itself with a 4-byte
1935 * time-in-seconds value was done in the
1936 * past.
1937 */
1938 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1939 time_stamp->nsecs = 0;
1940 } else {
1941 time_stamp->secs = 0;
1942 time_stamp->nsecs = 0;
1943 report_type_length_mismatch(tree, "a timespec", length, (length < 4));
1944 }
1945 break;
1946
1947 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1948 /*
1949 * NTP time stamp, big-endian.
1950 * Only supported for absolute times.
1951 */
1952 DISSECTOR_ASSERT(!is_relative);
1953
1954 /* We need a temporary variable here so the unsigned math
1955 * works correctly (for years > 2036 according to RFC 2030
1956 * chapter 3).
1957 *
1958 * If bit 0 is set, the UTC time is in the range 1968-2036 and
1959 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
1960 * If bit 0 is not set, the time is in the range 2036-2104 and
1961 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
1962 */
1963 tmpsecs = tvb_get_ntohl(tvb, start);
1964 if ((tmpsecs & 0x80000000) != 0)
1965 time_stamp->secs = (time_t)((gint64)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
1966 else
1967 time_stamp->secs = (time_t)((gint64)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
1968
1969 if (length == 8) {
1970 /*
1971 * Convert 1/2^32s of a second to nanoseconds.
1972 */
1973 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1974 if ((time_stamp->nsecs == 0) && (tmpsecs == 0)) {
1975 //This is "NULL" time
1976 time_stamp->secs = 0;
1977 }
1978 } else if (length == 4) {
1979 /*
1980 * Backwards compatibility.
1981 */
1982 if (tmpsecs == 0) {
1983 //This is "NULL" time
1984 time_stamp->secs = 0;
1985 }
1986 time_stamp->nsecs = 0;
1987 } else {
1988 time_stamp->secs = 0;
1989 time_stamp->nsecs = 0;
1990 report_type_length_mismatch(tree, "an NTP time stamp", length, (length < 4));
1991 }
1992 break;
1993
1994 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1995 /*
1996 * NTP time stamp, little-endian.
1997 * Only supported for absolute times.
1998 */
1999 DISSECTOR_ASSERT(!is_relative);
2000
2001 /* We need a temporary variable here so the unsigned math
2002 * works correctly (for years > 2036 according to RFC 2030
2003 * chapter 3).
2004 *
2005 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2006 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2007 * If bit 0 is not set, the time is in the range 2036-2104 and
2008 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2009 */
2010 tmpsecs = tvb_get_letohl(tvb, start);
2011 if ((tmpsecs & 0x80000000) != 0)
2012 time_stamp->secs = (time_t)((gint64)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2013 else
2014 time_stamp->secs = (time_t)((gint64)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2015
2016 if (length == 8) {
2017 /*
2018 * Convert 1/2^32s of a second to nanoseconds.
2019 */
2020 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
2021 if ((time_stamp->nsecs == 0) && (tmpsecs == 0)) {
2022 //This is "NULL" time
2023 time_stamp->secs = 0;
2024 }
2025 } else if (length == 4) {
2026 /*
2027 * Backwards compatibility.
2028 */
2029 if (tmpsecs == 0) {
2030 //This is "NULL" time
2031 time_stamp->secs = 0;
2032 }
2033 time_stamp->nsecs = 0;
2034 } else {
2035 time_stamp->secs = 0;
2036 time_stamp->nsecs = 0;
2037 report_type_length_mismatch(tree, "an NTP time stamp", length, (length < 4));
2038 }
2039 break;
2040
2041 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
2042 /*
2043 * S/3x0 and z/Architecture TOD clock time stamp,
2044 * big-endian. The epoch is January 1, 1900,
2045 * 00:00:00 (proleptic?) UTC.
2046 *
2047 * Only supported for absolute times.
2048 */
2049 DISSECTOR_ASSERT(!is_relative);
2050 DISSECTOR_ASSERT(length == 8);
2051
2052 if (length == 8) {
2053 todusecs = tvb_get_ntoh64(tvb, start) >> 12;
2054 time_stamp->secs = (time_t)((todusecs / 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC);
2055 time_stamp->nsecs = (int)((todusecs % 1000000) * 1000);
2056 } else {
2057 time_stamp->secs = 0;
2058 time_stamp->nsecs = 0;
2059 report_type_length_mismatch(tree, "a TOD clock time stamp", length, (length < 4));
2060 }
2061 break;
2062
2063 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
2064 /*
2065 * S/3x0 and z/Architecture TOD clock time stamp,
2066 * little-endian. The epoch is January 1, 1900,
2067 * 00:00:00 (proleptic?) UTC.
2068 *
2069 * Only supported for absolute times.
2070 */
2071 DISSECTOR_ASSERT(!is_relative);
2072
2073 if (length == 8) {
2074 todusecs = tvb_get_letoh64(tvb, start) >> 12 ;
2075 time_stamp->secs = (time_t)((todusecs / 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC);
2076 time_stamp->nsecs = (int)((todusecs % 1000000) * 1000);
2077 } else {
2078 time_stamp->secs = 0;
2079 time_stamp->nsecs = 0;
2080 report_type_length_mismatch(tree, "a TOD clock time stamp", length, (length < 4));
2081 }
2082 break;
2083
2084 case ENC_TIME_RTPS|ENC_BIG_ENDIAN:
2085 /*
2086 * Time stamp using the same seconds/fraction format
2087 * as NTP, but with the origin of the time stamp being
2088 * the UNIX epoch rather than the NTP epoch; big-
2089 * endian.
2090 *
2091 * Only supported for absolute times.
2092 */
2093 DISSECTOR_ASSERT(!is_relative);
2094
2095 if (length == 8) {
2096 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
2097 /*
2098 * Convert 1/2^32s of a second to nanoseconds.
2099 */
2100 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
2101 } else {
2102 time_stamp->secs = 0;
2103 time_stamp->nsecs = 0;
2104 report_type_length_mismatch(tree, "an RTPS time stamp", length, (length < 4));
2105 }
2106 break;
2107
2108 case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN:
2109 /*
2110 * Time stamp using the same seconds/fraction format
2111 * as NTP, but with the origin of the time stamp being
2112 * the UNIX epoch rather than the NTP epoch; little-
2113 * endian.
2114 *
2115 * Only supported for absolute times.
2116 */
2117 DISSECTOR_ASSERT(!is_relative);
2118
2119 if (length == 8) {
2120 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2121 /*
2122 * Convert 1/2^32s of a second to nanoseconds.
2123 */
2124 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
2125 } else {
2126 time_stamp->secs = 0;
2127 time_stamp->nsecs = 0;
2128 report_type_length_mismatch(tree, "an RTPS time stamp", length, (length < 4));
2129 }
2130 break;
2131
2132 case ENC_TIME_MIP6 | ENC_BIG_ENDIAN:
2133 /*
2134 * MIP6 time stamp, big-endian.
2135 * A 64-bit unsigned integer field containing a timestamp. The
2136 * value indicates the number of seconds since January 1, 1970,
2137 * 00:00 UTC, by using a fixed point format. In this format, the
2138 * integer number of seconds is contained in the first 48 bits of
2139 * the field, and the remaining 16 bits indicate the number of
2140 * 1/65536 fractions of a second.
2141
2142 * Only supported for absolute times.
2143 */
2144 DISSECTOR_ASSERT(!is_relative);
2145
2146 if (length == 8) {
2147 /* We need a temporary variable here so the casting and fractions
2148 * of a second work correctly.
2149 */
2150 tmp64secs = tvb_get_ntoh48(tvb, start);
2151 tmpsecs = tvb_get_ntohs(tvb, start + 6);
2152 tmpsecs <<= 16;
2153
2154 if ((tmp64secs == 0) && (tmpsecs == 0)) {
2155 //This is "NULL" time
2156 time_stamp->secs = 0;
2157 time_stamp->nsecs = 0;
2158 } else {
2159 time_stamp->secs = (time_t)tmp64secs;
2160 time_stamp->nsecs = (int)((tmpsecs / 4294967296.0) * 1000000000);
2161 }
2162 } else {
2163 time_stamp->secs = 0;
2164 time_stamp->nsecs = 0;
2165 report_type_length_mismatch(tree, "an NTP time stamp", length, (length != 8));
2166 }
2167 break;
2168
2169 case ENC_TIME_SECS_USECS|ENC_BIG_ENDIAN:
2170 /*
2171 * 4-byte seconds, followed by 4-byte fractional
2172 * time in microseconds, both big-endian.
2173 * For absolute times, the seconds are seconds
2174 * since the UN*X epoch.
2175 */
2176 if (length == 8) {
2177 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
2178 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000;
2179 } else {
2180 time_stamp->secs = 0;
2181 time_stamp->nsecs = 0;
2182 report_type_length_mismatch(tree, "a timeval", length, (length < 4));
2183 }
2184 break;
2185
2186 case ENC_TIME_SECS_USECS|ENC_LITTLE_ENDIAN:
2187 /*
2188 * 4-byte seconds, followed by 4-byte fractional
2189 * time in microseconds, both little-endian.
2190 * For absolute times, the seconds are seconds
2191 * since the UN*X epoch.
2192 */
2193 if (length == 8) {
2194 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2195 time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000;
2196 } else {
2197 time_stamp->secs = 0;
2198 time_stamp->nsecs = 0;
2199 report_type_length_mismatch(tree, "a timeval", length, (length < 4));
2200 }
2201 break;
2202
2203 case ENC_TIME_SECS|ENC_BIG_ENDIAN:
2204 case ENC_TIME_SECS|ENC_LITTLE_ENDIAN:
2205 /*
2206 * Seconds, 1 to 8 bytes.
2207 * For absolute times, it's seconds since the
2208 * UN*X epoch.
2209 */
2210 if (length >= 1 && length <= 8) {
2211 time_stamp->secs = (time_t)get_uint64_value(tree, tvb, start, length, encoding);
2212 time_stamp->nsecs = 0;
2213 } else {
2214 time_stamp->secs = 0;
2215 time_stamp->nsecs = 0;
2216 report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, (length < 4));
2217 }
2218 break;
2219
2220 case ENC_TIME_MSECS|ENC_BIG_ENDIAN:
2221 case ENC_TIME_MSECS|ENC_LITTLE_ENDIAN:
2222 /*
2223 * Milliseconds, 1 to 8 bytes.
2224 * For absolute times, it's milliseconds since the
2225 * UN*X epoch.
2226 */
2227 if (length >= 1 && length <= 8) {
2228 guint64 msecs;
2229
2230 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2231 time_stamp->secs = (time_t)(msecs / 1000);
2232 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2233 } else {
2234 time_stamp->secs = 0;
2235 time_stamp->nsecs = 0;
2236 report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, (length < 4));
2237 }
2238 break;
2239
2240 case ENC_TIME_NSECS|ENC_BIG_ENDIAN:
2241 case ENC_TIME_NSECS|ENC_LITTLE_ENDIAN:
2242 /*
2243 * nanoseconds, 1 to 8 bytes.
2244 * For absolute times, it's nanoseconds since the
2245 * UN*X epoch.
2246 */
2247
2248 if (length >= 1 && length <= 8) {
2249 guint64 nsecs;
2250
2251 nsecs = get_uint64_value(tree, tvb, start, length, encoding);
2252 time_stamp->secs = (time_t)(nsecs / 1000000000);
2253 time_stamp->nsecs = (int)(nsecs % 1000000000);
2254 } else {
2255 time_stamp->secs = 0;
2256 time_stamp->nsecs = 0;
2257 report_type_length_mismatch(tree, "a time-in-nanoseconds time stamp", length, (length < 4));
2258 }
2259 break;
2260
2261 case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN:
2262 /*
2263 * 1/64ths of a second since the UN*X epoch,
2264 * big-endian.
2265 *
2266 * Only supported for absolute times.
2267 */
2268 DISSECTOR_ASSERT(!is_relative);
2269
2270 if (length == 8) {
2271 /*
2272 * The upper 48 bits are seconds since the
2273 * UN*X epoch.
2274 */
2275 time_stamp->secs = (time_t)tvb_get_ntoh48(tvb, start);
2276 /*
2277 * The lower 16 bits are 1/2^16s of a second;
2278 * convert them to nanoseconds.
2279 *
2280 * XXX - this may give the impression of higher
2281 * precision than you actually get.
2282 */
2283 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0));
2284 } else {
2285 time_stamp->secs = 0;
2286 time_stamp->nsecs = 0;
2287 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, (length < 4));
2288 }
2289 break;
2290
2291 case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN:
2292 /*
2293 * 1/64ths of a second since the UN*X epoch,
2294 * little-endian.
2295 *
2296 * Only supported for absolute times.
2297 */
2298 DISSECTOR_ASSERT(!is_relative);
2299
2300 if (length == 8) {
2301 /*
2302 * XXX - this is assuming that, if anybody
2303 * were ever to use this format - RFC 3971
2304 * doesn't, because that's an Internet
2305 * protocol, and those use network byte
2306 * order, i.e. big-endian - they'd treat it
2307 * as a 64-bit count of 1/2^16s of a second,
2308 * putting the upper 48 bits at the end.
2309 *
2310 * The lower 48 bits are seconds since the
2311 * UN*X epoch.
2312 */
2313 time_stamp->secs = (time_t)tvb_get_letoh48(tvb, start+2);
2314 /*
2315 * The upper 16 bits are 1/2^16s of a second;
2316 * convert them to nanoseconds.
2317 *
2318 * XXX - this may give the impression of higher
2319 * precision than you actually get.
2320 */
2321 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0));
2322 } else {
2323 time_stamp->secs = 0;
2324 time_stamp->nsecs = 0;
2325 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, (length < 4));
2326 }
2327 break;
2328
2329 case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN:
2330 /*
2331 * NTP time stamp, with 1-second resolution (i.e.,
2332 * seconds since the NTP epoch), big-endian.
2333 * Only supported for absolute times.
2334 */
2335 DISSECTOR_ASSERT(!is_relative);
2336
2337 if (length == 4) {
2338 /*
2339 * We need a temporary variable here so the unsigned math
2340 * works correctly (for years > 2036 according to RFC 2030
2341 * chapter 3).
2342 *
2343 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2344 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2345 * If bit 0 is not set, the time is in the range 2036-2104 and
2346 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2347 */
2348 tmpsecs = tvb_get_ntohl(tvb, start);
2349 if ((tmpsecs & 0x80000000) != 0)
2350 time_stamp->secs = (time_t)((gint64)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2351 else
2352 time_stamp->secs = (time_t)((gint64)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2353 time_stamp->nsecs = 0;
2354 } else {
2355 time_stamp->secs = 0;
2356 time_stamp->nsecs = 0;
2357 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, (length < 4));
2358 }
2359 break;
2360
2361 case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN:
2362 /*
2363 * NTP time stamp, with 1-second resolution (i.e.,
2364 * seconds since the NTP epoch), little-endian.
2365 * Only supported for absolute times.
2366 */
2367 DISSECTOR_ASSERT(!is_relative);
2368
2369 /*
2370 * We need a temporary variable here so the unsigned math
2371 * works correctly (for years > 2036 according to RFC 2030
2372 * chapter 3).
2373 *
2374 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2375 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2376 * If bit 0 is not set, the time is in the range 2036-2104 and
2377 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2378 */
2379 if (length == 4) {
2380 tmpsecs = tvb_get_letohl(tvb, start);
2381 if ((tmpsecs & 0x80000000) != 0)
2382 time_stamp->secs = (time_t)((gint64)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2383 else
2384 time_stamp->secs = (time_t)((gint64)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2385 time_stamp->nsecs = 0;
2386 } else {
2387 time_stamp->secs = 0;
2388 time_stamp->nsecs = 0;
2389 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, (length < 4));
2390 }
2391 break;
2392 case ENC_TIME_MSEC_NTP | ENC_BIG_ENDIAN:
2393 /*
2394 * Milliseconds, 1 to 8 bytes.
2395 * For absolute times, it's milliseconds since the
2396 * NTP epoch.
2397 */
2398 if (length >= 1 && length <= 8) {
2399 guint64 msecs;
2400
2401 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2402 tmpsecs = (guint32)(msecs / 1000);
2403 /*
2404 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2405 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2406 * If bit 0 is not set, the time is in the range 2036-2104 and
2407 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2408 */
2409 if ((tmpsecs & 0x80000000) != 0)
2410 time_stamp->secs = (time_t)((gint64)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2411 else
2412 time_stamp->secs = (time_t)((gint64)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2413 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2414 }
2415 else {
2416 time_stamp->secs = 0;
2417 time_stamp->nsecs = 0;
2418 report_type_length_mismatch(tree, "a time-in-milliseconds NTP time stamp", length, (length < 4));
2419 }
2420 break;
2421
2422 case ENC_TIME_CLASSIC_MAC_OS_SECS|ENC_BIG_ENDIAN:
2423 /*
2424 * Classic Mac OS time stamps, big-endian.
2425 * Only supported for absolute times.
2426 */
2427 DISSECTOR_ASSERT(!is_relative);
2428
2429 if (length == 8) {
2430 tmp64secs = tvb_get_ntoh64(tvb, start);
2431 time_stamp->secs = (time_t)(gint64)(tmp64secs - EPOCH_DELTA_1904_01_01_00_00_00_UTC);
2432 time_stamp->nsecs = 0;
2433 } else if (length == 4) {
2434 tmpsecs = tvb_get_ntohl(tvb, start);
2435 time_stamp->secs = (time_t)(gint32)(tmpsecs - EPOCH_DELTA_1904_01_01_00_00_00_UTC);
2436 time_stamp->nsecs = 0;
2437 } else {
2438 time_stamp->secs = 0;
2439 time_stamp->nsecs = 0;
2440 report_type_length_mismatch(tree, "an MP4 time stamp", length, (length < 4));
2441 }
2442 break;
2443
2444 default:
2445 DISSECTOR_ASSERT_NOT_REACHED();
2446 break;
2447 }
2448 }
2449
2450 static void
tree_data_add_maybe_interesting_field(tree_data_t * tree_data,field_info * fi)2451 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
2452 {
2453 const header_field_info *hfinfo = fi->hfinfo;
2454
2455 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
2456 GPtrArray *ptrs = NULL;
2457
2458 if (tree_data->interesting_hfids == NULL) {
2459 /* Initialize the hash because we now know that it is needed */
2460 tree_data->interesting_hfids =
2461 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
2462 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
2463 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
2464 GINT_TO_POINTER(hfinfo->id));
2465 }
2466
2467 if (!ptrs) {
2468 /* First element triggers the creation of pointer array */
2469 ptrs = g_ptr_array_new();
2470 g_hash_table_insert(tree_data->interesting_hfids,
2471 GINT_TO_POINTER(hfinfo->id), ptrs);
2472 }
2473
2474 g_ptr_array_add(ptrs, fi);
2475 }
2476 }
2477
2478
2479 /*
2480 * Validates that field length bytes are available starting from
2481 * start (pos/neg). Throws an exception if they aren't.
2482 */
2483 static void
test_length(header_field_info * hfinfo,tvbuff_t * tvb,gint start,gint length,const guint encoding)2484 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2485 gint start, gint length, const guint encoding)
2486 {
2487 gint size = length;
2488
2489 if (!tvb)
2490 return;
2491
2492 if ((hfinfo->type == FT_STRINGZ) ||
2493 ((encoding & (ENC_VARIANT_MASK)) &&
2494 (IS_FT_UINT(hfinfo->type) || IS_FT_INT(hfinfo->type)))) {
2495 /* If we're fetching until the end of the TVB, only validate
2496 * that the offset is within range.
2497 */
2498 if (length == -1)
2499 size = 0;
2500 }
2501
2502 tvb_ensure_bytes_exist(tvb, start, size);
2503 }
2504
2505 static void
detect_trailing_stray_characters(guint encoding,const char * string,gint length,proto_item * pi)2506 detect_trailing_stray_characters(guint encoding, const char *string, gint length, proto_item *pi)
2507 {
2508 gboolean found_stray_character = FALSE;
2509
2510 if (!string)
2511 return;
2512
2513 switch (encoding & ENC_CHARENCODING_MASK) {
2514 case ENC_ASCII:
2515 case ENC_UTF_8:
2516 for (gint i = (gint)strlen(string); i < length; i++) {
2517 if (string[i] != '\0') {
2518 found_stray_character = TRUE;
2519 break;
2520 }
2521 }
2522 break;
2523
2524 default:
2525 break;
2526 }
2527
2528 if (found_stray_character) {
2529 expert_add_info(NULL, pi, &ei_string_trailing_characters);
2530 }
2531 }
2532
2533 /* Add an item to a proto_tree, using the text label registered to that item;
2534 the item is extracted from the tvbuff handed to it. */
2535 static proto_item *
proto_tree_new_item(field_info * new_fi,proto_tree * tree,tvbuff_t * tvb,gint start,gint length,guint encoding)2536 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
2537 tvbuff_t *tvb, gint start, gint length,
2538 guint encoding)
2539 {
2540 proto_item *pi;
2541 guint32 value, n;
2542 guint64 value64;
2543 ws_in4_addr ipv4_value;
2544 float floatval;
2545 double doubleval;
2546 const char *stringval = NULL;
2547 nstime_t time_stamp;
2548 gboolean length_error;
2549
2550 switch (new_fi->hfinfo->type) {
2551 case FT_NONE:
2552 /* no value to set for FT_NONE */
2553 break;
2554
2555 case FT_PROTOCOL:
2556 proto_tree_set_protocol_tvb(new_fi, tvb, new_fi->hfinfo->name);
2557 break;
2558
2559 case FT_BYTES:
2560 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
2561 break;
2562
2563 case FT_UINT_BYTES:
2564 n = get_uint_value(tree, tvb, start, length, encoding);
2565 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
2566
2567 /* Instead of calling proto_item_set_len(), since we don't yet
2568 * have a proto_item, we set the field_info's length ourselves. */
2569 new_fi->length = n + length;
2570 break;
2571
2572 case FT_BOOLEAN:
2573 /*
2574 * Map all non-zero values to little-endian for
2575 * backwards compatibility.
2576 */
2577 if (encoding)
2578 encoding = ENC_LITTLE_ENDIAN;
2579 proto_tree_set_boolean(new_fi,
2580 get_uint64_value(tree, tvb, start, length, encoding));
2581 break;
2582
2583 case FT_CHAR:
2584 /* XXX - make these just FT_UINT? */
2585 case FT_UINT8:
2586 case FT_UINT16:
2587 case FT_UINT24:
2588 case FT_UINT32:
2589 if (encoding & ENC_VARINT_PROTOBUF) {
2590 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2591 new_fi->flags |= FI_VARINT;
2592 value = (guint32)value64;
2593 } else if (encoding & ENC_VARINT_QUIC) {
2594 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2595 value = (guint32)value64;
2596 } else if (encoding & ENC_VARINT_ZIGZAG) {
2597 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2598 new_fi->flags |= FI_VARINT;
2599 value = (guint32)value64;
2600 }
2601 else {
2602 /*
2603 * Map all non-zero values to little-endian for
2604 * backwards compatibility.
2605 */
2606 if (encoding)
2607 encoding = ENC_LITTLE_ENDIAN;
2608
2609 value = get_uint_value(tree, tvb, start, length, encoding);
2610 }
2611 proto_tree_set_uint(new_fi, value);
2612 break;
2613
2614 case FT_UINT40:
2615 case FT_UINT48:
2616 case FT_UINT56:
2617 case FT_UINT64:
2618
2619 if (encoding & ENC_VARINT_PROTOBUF) {
2620 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2621 new_fi->flags |= FI_VARINT;
2622 } else if (encoding & ENC_VARINT_QUIC) {
2623 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2624 } else if (encoding & ENC_VARINT_ZIGZAG) {
2625 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2626 new_fi->flags |= FI_VARINT;
2627 }
2628 else {
2629 /*
2630 * Map all other non-zero values to little-endian for
2631 * backwards compatibility.
2632 */
2633 if (encoding)
2634 encoding = ENC_LITTLE_ENDIAN;
2635
2636 value64 = get_uint64_value(tree, tvb, start, length, encoding);
2637 }
2638 proto_tree_set_uint64(new_fi, value64);
2639 break;
2640
2641 /* XXX - make these just FT_INT? */
2642 case FT_INT8:
2643 case FT_INT16:
2644 case FT_INT24:
2645 case FT_INT32:
2646 /*
2647 * Map all non-zero values to little-endian for
2648 * backwards compatibility.
2649 */
2650 if (encoding)
2651 encoding = ENC_LITTLE_ENDIAN;
2652 proto_tree_set_int(new_fi,
2653 get_int_value(tree, tvb, start, length, encoding));
2654 break;
2655
2656 case FT_INT40:
2657 case FT_INT48:
2658 case FT_INT56:
2659 case FT_INT64:
2660 /*
2661 * Map all non-zero values to little-endian for
2662 * backwards compatibility.
2663 */
2664 if (encoding)
2665 encoding = ENC_LITTLE_ENDIAN;
2666 proto_tree_set_int64(new_fi,
2667 get_int64_value(tree, tvb, start, length, encoding));
2668 break;
2669
2670 case FT_IPv4:
2671 /*
2672 * Map all non-zero values to little-endian for
2673 * backwards compatibility.
2674 */
2675 if (encoding)
2676 encoding = ENC_LITTLE_ENDIAN;
2677 if (length != FT_IPv4_LEN) {
2678 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
2679 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
2680 }
2681 ipv4_value = tvb_get_ipv4(tvb, start);
2682 /*
2683 * NOTE: to support code written when
2684 * proto_tree_add_item() took a gboolean as its
2685 * last argument, with FALSE meaning "big-endian"
2686 * and TRUE meaning "little-endian", we treat any
2687 * non-zero value of "encoding" as meaning
2688 * "little-endian".
2689 */
2690 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(ipv4_value) : ipv4_value);
2691 break;
2692
2693 case FT_IPXNET:
2694 if (length != FT_IPXNET_LEN) {
2695 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
2696 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
2697 }
2698 proto_tree_set_ipxnet(new_fi,
2699 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
2700 break;
2701
2702 case FT_IPv6:
2703 if (length != FT_IPv6_LEN) {
2704 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
2705 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
2706 }
2707 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
2708 break;
2709
2710 case FT_FCWWN:
2711 if (length != FT_FCWWN_LEN) {
2712 length_error = length < FT_FCWWN_LEN ? TRUE : FALSE;
2713 report_type_length_mismatch(tree, "an FCWWN address", length, length_error);
2714 }
2715 proto_tree_set_fcwwn_tvb(new_fi, tvb, start, length);
2716 break;
2717
2718 case FT_AX25:
2719 if (length != 7) {
2720 length_error = length < 7 ? TRUE : FALSE;
2721 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
2722 }
2723 proto_tree_set_ax25_tvb(new_fi, tvb, start);
2724 break;
2725
2726 case FT_VINES:
2727 if (length != VINES_ADDR_LEN) {
2728 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
2729 report_type_length_mismatch(tree, "a Vines address", length, length_error);
2730 }
2731 proto_tree_set_vines_tvb(new_fi, tvb, start);
2732 break;
2733
2734 case FT_ETHER:
2735 if (length != FT_ETHER_LEN) {
2736 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
2737 report_type_length_mismatch(tree, "a MAC address", length, length_error);
2738 }
2739 proto_tree_set_ether_tvb(new_fi, tvb, start);
2740 break;
2741
2742 case FT_EUI64:
2743 /*
2744 * Map all non-zero values to little-endian for
2745 * backwards compatibility.
2746 */
2747 if (encoding)
2748 encoding = ENC_LITTLE_ENDIAN;
2749 if (length != FT_EUI64_LEN) {
2750 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
2751 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
2752 }
2753 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
2754 break;
2755 case FT_GUID:
2756 /*
2757 * Map all non-zero values to little-endian for
2758 * backwards compatibility.
2759 */
2760 if (encoding)
2761 encoding = ENC_LITTLE_ENDIAN;
2762 if (length != FT_GUID_LEN) {
2763 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
2764 report_type_length_mismatch(tree, "a GUID", length, length_error);
2765 }
2766 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
2767 break;
2768
2769 case FT_OID:
2770 case FT_REL_OID:
2771 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
2772 break;
2773
2774 case FT_SYSTEM_ID:
2775 proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
2776 break;
2777
2778 case FT_FLOAT:
2779 /*
2780 * NOTE: to support code written when
2781 * proto_tree_add_item() took a gboolean as its
2782 * last argument, with FALSE meaning "big-endian"
2783 * and TRUE meaning "little-endian", we treat any
2784 * non-zero value of "encoding" as meaning
2785 * "little-endian".
2786 *
2787 * At some point in the future, we might
2788 * support non-IEEE-binary floating-point
2789 * formats in the encoding as well
2790 * (IEEE decimal, System/3x0, VAX).
2791 */
2792 if (encoding)
2793 encoding = ENC_LITTLE_ENDIAN;
2794 if (length != 4) {
2795 length_error = length < 4 ? TRUE : FALSE;
2796 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
2797 }
2798 if (encoding)
2799 floatval = tvb_get_letohieee_float(tvb, start);
2800 else
2801 floatval = tvb_get_ntohieee_float(tvb, start);
2802 proto_tree_set_float(new_fi, floatval);
2803 break;
2804
2805 case FT_DOUBLE:
2806 /*
2807 * NOTE: to support code written when
2808 * proto_tree_add_item() took a gboolean as its
2809 * last argument, with FALSE meaning "big-endian"
2810 * and TRUE meaning "little-endian", we treat any
2811 * non-zero value of "encoding" as meaning
2812 * "little-endian".
2813 *
2814 * At some point in the future, we might
2815 * support non-IEEE-binary floating-point
2816 * formats in the encoding as well
2817 * (IEEE decimal, System/3x0, VAX).
2818 */
2819 if (encoding == TRUE)
2820 encoding = ENC_LITTLE_ENDIAN;
2821 if (length != 8) {
2822 length_error = length < 8 ? TRUE : FALSE;
2823 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
2824 }
2825 if (encoding)
2826 doubleval = tvb_get_letohieee_double(tvb, start);
2827 else
2828 doubleval = tvb_get_ntohieee_double(tvb, start);
2829 proto_tree_set_double(new_fi, doubleval);
2830 break;
2831
2832 case FT_STRING:
2833 stringval = get_string_value(PNODE_POOL(tree),
2834 tvb, start, length, &length, encoding);
2835 proto_tree_set_string(new_fi, stringval);
2836
2837 /* Instead of calling proto_item_set_len(), since we
2838 * don't yet have a proto_item, we set the
2839 * field_info's length ourselves.
2840 *
2841 * XXX - our caller can't use that length to
2842 * advance an offset unless they arrange that
2843 * there always be a protocol tree into which
2844 * we're putting this item.
2845 */
2846 new_fi->length = length;
2847 break;
2848
2849 case FT_STRINGZ:
2850 stringval = get_stringz_value(PNODE_POOL(tree),
2851 tree, tvb, start, length, &length, encoding);
2852 proto_tree_set_string(new_fi, stringval);
2853
2854 /* Instead of calling proto_item_set_len(),
2855 * since we don't yet have a proto_item, we
2856 * set the field_info's length ourselves.
2857 *
2858 * XXX - our caller can't use that length to
2859 * advance an offset unless they arrange that
2860 * there always be a protocol tree into which
2861 * we're putting this item.
2862 */
2863 new_fi->length = length;
2864 break;
2865
2866 case FT_UINT_STRING:
2867 /*
2868 * NOTE: to support code written when
2869 * proto_tree_add_item() took a gboolean as its
2870 * last argument, with FALSE meaning "big-endian"
2871 * and TRUE meaning "little-endian", if the
2872 * encoding value is TRUE, treat that as
2873 * ASCII with a little-endian length.
2874 *
2875 * This won't work for code that passes
2876 * arbitrary non-zero values; that code
2877 * will need to be fixed.
2878 */
2879 if (encoding == TRUE)
2880 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
2881 stringval = get_uint_string_value(PNODE_POOL(tree),
2882 tree, tvb, start, length, &length, encoding);
2883 proto_tree_set_string(new_fi, stringval);
2884
2885 /* Instead of calling proto_item_set_len(), since we
2886 * don't yet have a proto_item, we set the
2887 * field_info's length ourselves.
2888 *
2889 * XXX - our caller can't use that length to
2890 * advance an offset unless they arrange that
2891 * there always be a protocol tree into which
2892 * we're putting this item.
2893 */
2894 new_fi->length = length;
2895 break;
2896
2897 case FT_STRINGZPAD:
2898 stringval = get_stringzpad_value(PNODE_POOL(tree),
2899 tvb, start, length, &length, encoding);
2900 proto_tree_set_string(new_fi, stringval);
2901
2902 /* Instead of calling proto_item_set_len(), since we
2903 * don't yet have a proto_item, we set the
2904 * field_info's length ourselves.
2905 *
2906 * XXX - our caller can't use that length to
2907 * advance an offset unless they arrange that
2908 * there always be a protocol tree into which
2909 * we're putting this item.
2910 */
2911 new_fi->length = length;
2912 break;
2913
2914 case FT_STRINGZTRUNC:
2915 stringval = get_stringztrunc_value(PNODE_POOL(tree),
2916 tvb, start, length, &length, encoding);
2917 proto_tree_set_string(new_fi, stringval);
2918
2919 /* Instead of calling proto_item_set_len(), since we
2920 * don't yet have a proto_item, we set the
2921 * field_info's length ourselves.
2922 *
2923 * XXX - our caller can't use that length to
2924 * advance an offset unless they arrange that
2925 * there always be a protocol tree into which
2926 * we're putting this item.
2927 */
2928 new_fi->length = length;
2929 break;
2930
2931 case FT_ABSOLUTE_TIME:
2932 /*
2933 * Absolute times can be in any of a number of
2934 * formats, and they can be big-endian or
2935 * little-endian.
2936 *
2937 * Historically FT_TIMEs were only timespecs;
2938 * the only question was whether they were stored
2939 * in big- or little-endian format.
2940 *
2941 * For backwards compatibility, we interpret an
2942 * encoding of 1 as meaning "little-endian timespec",
2943 * so that passing TRUE is interpreted as that.
2944 */
2945 if (encoding == TRUE)
2946 encoding = ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN;
2947
2948 get_time_value(tree, tvb, start, length, encoding, &time_stamp, FALSE);
2949
2950 proto_tree_set_time(new_fi, &time_stamp);
2951 break;
2952
2953 case FT_RELATIVE_TIME:
2954 /*
2955 * Relative times can be in any of a number of
2956 * formats, and they can be big-endian or
2957 * little-endian.
2958 *
2959 * Historically FT_TIMEs were only timespecs;
2960 * the only question was whether they were stored
2961 * in big- or little-endian format.
2962 *
2963 * For backwards compatibility, we interpret an
2964 * encoding of 1 as meaning "little-endian timespec",
2965 * so that passing TRUE is interpreted as that.
2966 */
2967 if (encoding == TRUE)
2968 encoding = ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN;
2969
2970 get_time_value(tree, tvb, start, length, encoding, &time_stamp, TRUE);
2971
2972 proto_tree_set_time(new_fi, &time_stamp);
2973 break;
2974 case FT_IEEE_11073_SFLOAT:
2975 if (encoding)
2976 encoding = ENC_LITTLE_ENDIAN;
2977 if (length != 2) {
2978 length_error = length < 2 ? TRUE : FALSE;
2979 report_type_length_mismatch(tree, "a IEEE 11073 SFLOAT", length, length_error);
2980 }
2981
2982 fvalue_set_uinteger(&new_fi->value, tvb_get_guint16(tvb, start, encoding));
2983
2984 break;
2985 case FT_IEEE_11073_FLOAT:
2986 if (encoding)
2987 encoding = ENC_LITTLE_ENDIAN;
2988 if (length != 4) {
2989 length_error = length < 4 ? TRUE : FALSE;
2990 report_type_length_mismatch(tree, "a IEEE 11073 FLOAT", length, length_error);
2991 }
2992
2993 break;
2994 default:
2995 REPORT_DISSECTOR_BUG("field %s is of unknown type %d (%s)",
2996 new_fi->hfinfo->abbrev,
2997 new_fi->hfinfo->type,
2998 ftype_name(new_fi->hfinfo->type));
2999 break;
3000 }
3001 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3002
3003 /* Don't add new node to proto_tree until now so that any exceptions
3004 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
3005 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
3006 * to know which item caused exception? */
3007 pi = proto_tree_add_node(tree, new_fi);
3008
3009 switch (new_fi->hfinfo->type) {
3010
3011 case FT_STRING:
3012 detect_trailing_stray_characters(encoding, stringval, length, pi);
3013 break;
3014
3015 default:
3016 break;
3017 }
3018
3019 return pi;
3020 }
3021
3022 proto_item *
proto_tree_add_item_ret_int(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,gint32 * retval)3023 proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3024 const gint start, gint length,
3025 const guint encoding, gint32 *retval)
3026 {
3027 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3028 field_info *new_fi;
3029 gint32 value;
3030
3031 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3032
3033 switch (hfinfo->type) {
3034 case FT_INT8:
3035 case FT_INT16:
3036 case FT_INT24:
3037 case FT_INT32:
3038 break;
3039 case FT_INT64:
3040 REPORT_DISSECTOR_BUG("64-bit signed integer field %s used with proto_tree_add_item_ret_int()",
3041 hfinfo->abbrev);
3042 default:
3043 REPORT_DISSECTOR_BUG("Non-signed-integer field %s used with proto_tree_add_item_ret_int()",
3044 hfinfo->abbrev);
3045 }
3046
3047 /* length validation for native number encoding caught by get_uint_value() */
3048 /* length has to be -1 or > 0 regardless of encoding */
3049 if (length < -1 || length == 0)
3050 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_int",
3051 length);
3052
3053 if (encoding & ENC_STRING) {
3054 REPORT_DISSECTOR_BUG("wrong encoding");
3055 }
3056 /* I believe it's ok if this is called with a NULL tree */
3057 value = get_int_value(tree, tvb, start, length, encoding);
3058
3059 if (retval) {
3060 gint no_of_bits;
3061 *retval = value;
3062 if (hfinfo->bitmask) {
3063 /* Mask out irrelevant portions */
3064 *retval &= (guint32)(hfinfo->bitmask);
3065 /* Shift bits */
3066 *retval >>= hfinfo_bitshift(hfinfo);
3067 }
3068 no_of_bits = ws_count_ones(hfinfo->bitmask);
3069 *retval = ws_sign_ext32(*retval, no_of_bits);
3070 }
3071
3072 CHECK_FOR_NULL_TREE(tree);
3073
3074 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3075
3076 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3077
3078 proto_tree_set_int(new_fi, value);
3079
3080 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3081
3082 return proto_tree_add_node(tree, new_fi);
3083 }
3084
3085 proto_item *
proto_tree_add_item_ret_uint(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,guint32 * retval)3086 proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3087 const gint start, gint length,
3088 const guint encoding, guint32 *retval)
3089 {
3090 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3091 field_info *new_fi;
3092 guint32 value;
3093
3094 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3095
3096 switch (hfinfo->type) {
3097 case FT_CHAR:
3098 case FT_UINT8:
3099 case FT_UINT16:
3100 case FT_UINT24:
3101 case FT_UINT32:
3102 break;
3103 default:
3104 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3105 hfinfo->abbrev);
3106 }
3107
3108 /* length validation for native number encoding caught by get_uint_value() */
3109 /* length has to be -1 or > 0 regardless of encoding */
3110 if (length < -1 || length == 0)
3111 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_uint",
3112 length);
3113
3114 if (encoding & ENC_STRING) {
3115 REPORT_DISSECTOR_BUG("wrong encoding");
3116 }
3117 /* I believe it's ok if this is called with a NULL tree */
3118 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3119 if (encoding & (ENC_VARIANT_MASK)) {
3120 guint64 temp64;
3121 tvb_get_varint(tvb, start, length, &temp64, encoding);
3122 value = (guint32)temp64;
3123 } else {
3124 value = get_uint_value(tree, tvb, start, length, encoding);
3125 }
3126
3127 if (retval) {
3128 *retval = value;
3129 if (hfinfo->bitmask) {
3130 /* Mask out irrelevant portions */
3131 *retval &= (guint32)(hfinfo->bitmask);
3132 /* Shift bits */
3133 *retval >>= hfinfo_bitshift(hfinfo);
3134 }
3135 }
3136
3137 CHECK_FOR_NULL_TREE(tree);
3138
3139 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3140
3141 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3142
3143 proto_tree_set_uint(new_fi, value);
3144
3145 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3146 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
3147 new_fi->flags |= FI_VARINT;
3148 }
3149 return proto_tree_add_node(tree, new_fi);
3150 }
3151
3152 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3153 * and returns proto_item* and uint value retreived*/
3154 proto_item *
ptvcursor_add_ret_uint(ptvcursor_t * ptvc,int hfindex,gint length,const guint encoding,guint32 * retval)3155 ptvcursor_add_ret_uint(ptvcursor_t *ptvc, int hfindex, gint length,
3156 const guint encoding, guint32 *retval)
3157 {
3158 field_info *new_fi;
3159 header_field_info *hfinfo;
3160 gint item_length;
3161 int offset;
3162 guint32 value;
3163
3164 offset = ptvc->offset;
3165 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3166
3167 switch (hfinfo->type) {
3168 case FT_CHAR:
3169 case FT_UINT8:
3170 case FT_UINT16:
3171 case FT_UINT24:
3172 case FT_UINT32:
3173 break;
3174 default:
3175 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3176 hfinfo->abbrev);
3177 }
3178
3179 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3180 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3181
3182 /* I believe it's ok if this is called with a NULL tree */
3183 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3184 value = get_uint_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
3185
3186 if (retval) {
3187 *retval = value;
3188 if (hfinfo->bitmask) {
3189 /* Mask out irrelevant portions */
3190 *retval &= (guint32)(hfinfo->bitmask);
3191 /* Shift bits */
3192 *retval >>= hfinfo_bitshift(hfinfo);
3193 }
3194 }
3195
3196 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3197 item_length, encoding);
3198
3199 CHECK_FOR_NULL_TREE(ptvc->tree);
3200
3201 /* Coast clear. Try and fake it */
3202 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3203
3204 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3205
3206 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3207 offset, length, encoding);
3208 }
3209
3210 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3211 * and returns proto_item* and int value retreived*/
3212 proto_item *
ptvcursor_add_ret_int(ptvcursor_t * ptvc,int hfindex,gint length,const guint encoding,gint32 * retval)3213 ptvcursor_add_ret_int(ptvcursor_t *ptvc, int hfindex, gint length,
3214 const guint encoding, gint32 *retval)
3215 {
3216 field_info *new_fi;
3217 header_field_info *hfinfo;
3218 gint item_length;
3219 int offset;
3220 guint32 value;
3221
3222 offset = ptvc->offset;
3223 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3224
3225 switch (hfinfo->type) {
3226 case FT_INT8:
3227 case FT_INT16:
3228 case FT_INT24:
3229 case FT_INT32:
3230 break;
3231 default:
3232 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
3233 hfinfo->abbrev);
3234 }
3235
3236 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3237 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3238
3239 /* I believe it's ok if this is called with a NULL tree */
3240 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3241 value = get_int_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
3242
3243 if (retval) {
3244 gint no_of_bits;
3245 *retval = value;
3246 if (hfinfo->bitmask) {
3247 /* Mask out irrelevant portions */
3248 *retval &= (guint32)(hfinfo->bitmask);
3249 /* Shift bits */
3250 *retval >>= hfinfo_bitshift(hfinfo);
3251 }
3252 no_of_bits = ws_count_ones(hfinfo->bitmask);
3253 *retval = ws_sign_ext32(*retval, no_of_bits);
3254 }
3255
3256 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3257 item_length, encoding);
3258
3259 CHECK_FOR_NULL_TREE(ptvc->tree);
3260
3261 /* Coast clear. Try and fake it */
3262 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3263
3264 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3265
3266 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3267 offset, length, encoding);
3268 }
3269
3270 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3271 * and returns proto_item* and string value retreived */
3272 proto_item*
ptvcursor_add_ret_string(ptvcursor_t * ptvc,int hf,gint length,const guint encoding,wmem_allocator_t * scope,const guint8 ** retval)3273 ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, wmem_allocator_t *scope, const guint8 **retval)
3274 {
3275 header_field_info *hfinfo;
3276 field_info *new_fi;
3277 const guint8 *value;
3278 gint item_length;
3279 int offset;
3280
3281 offset = ptvc->offset;
3282
3283 PROTO_REGISTRAR_GET_NTH(hf, hfinfo);
3284
3285 switch (hfinfo->type) {
3286 case FT_STRING:
3287 value = get_string_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3288 break;
3289 case FT_STRINGZ:
3290 value = get_stringz_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
3291 break;
3292 case FT_UINT_STRING:
3293 value = get_uint_string_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
3294 break;
3295 case FT_STRINGZPAD:
3296 value = get_stringzpad_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3297 break;
3298 case FT_STRINGZTRUNC:
3299 value = get_stringztrunc_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3300 break;
3301 default:
3302 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
3303 hfinfo->abbrev);
3304 }
3305
3306 if (retval)
3307 *retval = value;
3308
3309 ptvc->offset += item_length;
3310
3311 CHECK_FOR_NULL_TREE(ptvc->tree);
3312
3313 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
3314
3315 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3316
3317 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3318 offset, length, encoding);
3319 }
3320
3321 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3322 * and returns proto_item* and boolean value retreived */
3323 proto_item*
ptvcursor_add_ret_boolean(ptvcursor_t * ptvc,int hfindex,gint length,const guint encoding,gboolean * retval)3324 ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hfindex, gint length, const guint encoding, gboolean *retval)
3325 {
3326 header_field_info *hfinfo;
3327 field_info *new_fi;
3328 gint item_length;
3329 int offset;
3330 guint64 value, bitval;
3331
3332 offset = ptvc->offset;
3333 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3334
3335 if (hfinfo->type != FT_BOOLEAN) {
3336 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3337 hfinfo->abbrev);
3338 }
3339
3340 /* length validation for native number encoding caught by get_uint64_value() */
3341 /* length has to be -1 or > 0 regardless of encoding */
3342 if (length < -1 || length == 0)
3343 REPORT_DISSECTOR_BUG("Invalid length %d passed to ptvcursor_add_ret_boolean",
3344 length);
3345
3346 if (encoding & ENC_STRING) {
3347 REPORT_DISSECTOR_BUG("wrong encoding");
3348 }
3349
3350 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3351 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3352
3353 /* I believe it's ok if this is called with a NULL tree */
3354 value = get_uint64_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
3355
3356 if (retval) {
3357 bitval = value;
3358 if (hfinfo->bitmask) {
3359 /* Mask out irrelevant portions */
3360 bitval &= hfinfo->bitmask;
3361 }
3362 *retval = (bitval != 0);
3363 }
3364
3365 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3366 item_length, encoding);
3367
3368 CHECK_FOR_NULL_TREE(ptvc->tree);
3369
3370 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
3371
3372 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3373
3374 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3375 offset, length, encoding);
3376 }
3377
3378 proto_item *
proto_tree_add_item_ret_uint64(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,guint64 * retval)3379 proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3380 const gint start, gint length, const guint encoding, guint64 *retval)
3381 {
3382 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3383 field_info *new_fi;
3384 guint64 value;
3385
3386 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3387
3388 switch (hfinfo->type) {
3389 case FT_UINT40:
3390 case FT_UINT48:
3391 case FT_UINT56:
3392 case FT_UINT64:
3393 break;
3394 default:
3395 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
3396 hfinfo->abbrev);
3397 }
3398
3399 /* length validation for native number encoding caught by get_uint64_value() */
3400 /* length has to be -1 or > 0 regardless of encoding */
3401 if (length < -1 || length == 0)
3402 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_uint64",
3403 length);
3404
3405 if (encoding & ENC_STRING) {
3406 REPORT_DISSECTOR_BUG("wrong encoding");
3407 }
3408 /* I believe it's ok if this is called with a NULL tree */
3409 if (encoding & (ENC_VARIANT_MASK)) {
3410 tvb_get_varint(tvb, start, length, &value, encoding);
3411 } else {
3412 value = get_uint64_value(tree, tvb, start, length, encoding);
3413 }
3414
3415 if (retval) {
3416 *retval = value;
3417 if (hfinfo->bitmask) {
3418 /* Mask out irrelevant portions */
3419 *retval &= hfinfo->bitmask;
3420 /* Shift bits */
3421 *retval >>= hfinfo_bitshift(hfinfo);
3422 }
3423 }
3424
3425 CHECK_FOR_NULL_TREE(tree);
3426
3427 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3428
3429 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3430
3431 proto_tree_set_uint64(new_fi, value);
3432
3433 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3434 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
3435 new_fi->flags |= FI_VARINT;
3436 }
3437
3438 return proto_tree_add_node(tree, new_fi);
3439 }
3440
3441 proto_item *
proto_tree_add_item_ret_int64(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,gint64 * retval)3442 proto_tree_add_item_ret_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3443 const gint start, gint length, const guint encoding, gint64 *retval)
3444 {
3445 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3446 field_info *new_fi;
3447 gint64 value;
3448
3449 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3450
3451 switch (hfinfo->type) {
3452 case FT_INT40:
3453 case FT_INT48:
3454 case FT_INT56:
3455 case FT_INT64:
3456 break;
3457 default:
3458 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
3459 hfinfo->abbrev);
3460 }
3461
3462 /* length validation for native number encoding caught by get_uint64_value() */
3463 /* length has to be -1 or > 0 regardless of encoding */
3464 if (length < -1 || length == 0)
3465 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_int64",
3466 length);
3467
3468 if (encoding & ENC_STRING) {
3469 REPORT_DISSECTOR_BUG("wrong encoding");
3470 }
3471 /* I believe it's ok if this is called with a NULL tree */
3472 if (encoding & (ENC_VARIANT_MASK)) {
3473 tvb_get_varint(tvb, start, length, &value, encoding);
3474 }
3475 else {
3476 value = get_int64_value(tree, tvb, start, length, encoding);
3477 }
3478
3479 if (retval) {
3480 *retval = value;
3481 }
3482
3483 CHECK_FOR_NULL_TREE(tree);
3484
3485 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3486
3487 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3488
3489 proto_tree_set_int64(new_fi, value);
3490
3491 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3492 if (encoding & (ENC_VARINT_PROTOBUF | ENC_VARINT_ZIGZAG)) {
3493 new_fi->flags |= FI_VARINT;
3494 }
3495
3496 return proto_tree_add_node(tree, new_fi);
3497 }
3498
3499 proto_item *
proto_tree_add_item_ret_varint(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,guint64 * retval,gint * lenretval)3500 proto_tree_add_item_ret_varint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3501 const gint start, gint length, const guint encoding, guint64 *retval, gint *lenretval)
3502 {
3503 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3504 field_info *new_fi;
3505 guint64 value;
3506
3507 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3508
3509 if ((!IS_FT_INT(hfinfo->type)) && (!IS_FT_UINT(hfinfo->type))) {
3510 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT or FT_INT",
3511 hfinfo->abbrev);
3512 }
3513
3514 /* length validation for native number encoding caught by get_uint64_value() */
3515 /* length has to be -1 or > 0 regardless of encoding */
3516 if (length == 0)
3517 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_varint",
3518 length);
3519
3520 if (encoding & ENC_STRING) {
3521 REPORT_DISSECTOR_BUG("wrong encoding");
3522 }
3523
3524 length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value, encoding);
3525
3526 if (retval) {
3527 *retval = value;
3528 if (hfinfo->bitmask) {
3529 /* Mask out irrelevant portions */
3530 *retval &= hfinfo->bitmask;
3531 /* Shift bits */
3532 *retval >>= hfinfo_bitshift(hfinfo);
3533 }
3534 }
3535
3536 if (lenretval) {
3537 *lenretval = length;
3538 }
3539
3540 CHECK_FOR_NULL_TREE(tree);
3541
3542 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3543
3544 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3545
3546 proto_tree_set_uint64(new_fi, value);
3547
3548 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3549 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
3550 new_fi->flags |= FI_VARINT;
3551 }
3552
3553 return proto_tree_add_node(tree, new_fi);
3554
3555 }
3556
3557 proto_item *
proto_tree_add_item_ret_boolean(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,gboolean * retval)3558 proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3559 const gint start, gint length,
3560 const guint encoding, gboolean *retval)
3561 {
3562 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3563 field_info *new_fi;
3564 guint64 value, bitval;
3565
3566 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3567
3568 if (hfinfo->type != FT_BOOLEAN) {
3569 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3570 hfinfo->abbrev);
3571 }
3572
3573 /* length validation for native number encoding caught by get_uint64_value() */
3574 /* length has to be -1 or > 0 regardless of encoding */
3575 if (length < -1 || length == 0)
3576 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_boolean",
3577 length);
3578
3579 if (encoding & ENC_STRING) {
3580 REPORT_DISSECTOR_BUG("wrong encoding");
3581 }
3582 /* I believe it's ok if this is called with a NULL tree */
3583 value = get_uint64_value(tree, tvb, start, length, encoding);
3584
3585 if (retval) {
3586 bitval = value;
3587 if (hfinfo->bitmask) {
3588 /* Mask out irrelevant portions */
3589 bitval &= hfinfo->bitmask;
3590 }
3591 *retval = (bitval != 0);
3592 }
3593
3594 CHECK_FOR_NULL_TREE(tree);
3595
3596 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3597
3598 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3599
3600 proto_tree_set_boolean(new_fi, value);
3601
3602 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3603
3604 return proto_tree_add_node(tree, new_fi);
3605 }
3606
3607 proto_item *
proto_tree_add_item_ret_ipv4(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,ws_in4_addr * retval)3608 proto_tree_add_item_ret_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3609 const gint start, gint length,
3610 const guint encoding, ws_in4_addr *retval)
3611 {
3612 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3613 field_info *new_fi;
3614 ws_in4_addr value;
3615
3616 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3617
3618 switch (hfinfo->type) {
3619 case FT_IPv4:
3620 break;
3621 default:
3622 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv4",
3623 hfinfo->abbrev);
3624 }
3625
3626 if (length != FT_IPv4_LEN)
3627 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv4",
3628 length);
3629
3630 if (encoding & (ENC_STRING | ENC_VARIANT_MASK | ENC_VARINT_PROTOBUF | ENC_VARINT_ZIGZAG)) {
3631 REPORT_DISSECTOR_BUG("wrong encoding");
3632 }
3633
3634 /*
3635 * NOTE: to support code written when proto_tree_add_item() took
3636 * a gboolean as its last argument, with FALSE meaning "big-endian"
3637 * and TRUE meaning "little-endian", we treat any non-zero value
3638 * of "encoding" as meaning "little-endian".
3639 */
3640 value = tvb_get_ipv4(tvb, start);
3641 if (encoding)
3642 value = GUINT32_SWAP_LE_BE(value);
3643
3644 if (retval) {
3645 *retval = value;
3646 }
3647
3648 CHECK_FOR_NULL_TREE(tree);
3649
3650 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3651
3652 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3653
3654 proto_tree_set_ipv4(new_fi, value);
3655
3656 new_fi->flags |= encoding ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3657 return proto_tree_add_node(tree, new_fi);
3658 }
3659
3660 proto_item *
proto_tree_add_item_ret_string_and_length(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,wmem_allocator_t * scope,const guint8 ** retval,gint * lenretval)3661 proto_tree_add_item_ret_string_and_length(proto_tree *tree, int hfindex,
3662 tvbuff_t *tvb,
3663 const gint start, gint length,
3664 const guint encoding,
3665 wmem_allocator_t *scope,
3666 const guint8 **retval,
3667 gint *lenretval)
3668 {
3669 proto_item *pi;
3670 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3671 field_info *new_fi;
3672 const guint8 *value;
3673
3674 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3675
3676 switch (hfinfo->type) {
3677 case FT_STRING:
3678 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
3679 break;
3680 case FT_STRINGZ:
3681 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
3682 break;
3683 case FT_UINT_STRING:
3684 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
3685 break;
3686 case FT_STRINGZPAD:
3687 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
3688 break;
3689 case FT_STRINGZTRUNC:
3690 value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
3691 break;
3692 default:
3693 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
3694 hfinfo->abbrev);
3695 }
3696
3697 if (retval)
3698 *retval = value;
3699
3700 CHECK_FOR_NULL_TREE(tree);
3701
3702 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3703
3704 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
3705
3706 proto_tree_set_string(new_fi, value);
3707
3708 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3709
3710 pi = proto_tree_add_node(tree, new_fi);
3711
3712 switch (hfinfo->type) {
3713
3714 case FT_STRINGZ:
3715 case FT_STRINGZPAD:
3716 case FT_STRINGZTRUNC:
3717 case FT_UINT_STRING:
3718 break;
3719
3720 case FT_STRING:
3721 detect_trailing_stray_characters(encoding, value, length, pi);
3722 break;
3723
3724 default:
3725 ws_assert_not_reached();
3726 }
3727
3728 return pi;
3729 }
3730
3731 proto_item *
proto_tree_add_item_ret_string(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,wmem_allocator_t * scope,const guint8 ** retval)3732 proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3733 const gint start, gint length,
3734 const guint encoding, wmem_allocator_t *scope,
3735 const guint8 **retval)
3736 {
3737 return proto_tree_add_item_ret_string_and_length(tree, hfindex,
3738 tvb, start, length, encoding, scope, retval, &length);
3739 }
3740
3741 proto_item *
proto_tree_add_item_ret_display_string_and_length(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,wmem_allocator_t * scope,char ** retval,gint * lenretval)3742 proto_tree_add_item_ret_display_string_and_length(proto_tree *tree, int hfindex,
3743 tvbuff_t *tvb,
3744 const gint start, gint length,
3745 const guint encoding,
3746 wmem_allocator_t *scope,
3747 char **retval,
3748 gint *lenretval)
3749 {
3750 proto_item *pi;
3751 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3752 field_info *new_fi;
3753 const guint8 *value;
3754 guint32 n = 0;
3755
3756 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3757
3758 switch (hfinfo->type) {
3759 case FT_STRING:
3760 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
3761 *retval = hfinfo_format_text(scope, hfinfo, value);
3762 break;
3763 case FT_STRINGZ:
3764 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
3765 *retval = hfinfo_format_text(scope, hfinfo, value);
3766 break;
3767 case FT_UINT_STRING:
3768 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
3769 *retval = hfinfo_format_text(scope, hfinfo, value);
3770 break;
3771 case FT_STRINGZPAD:
3772 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
3773 *retval = hfinfo_format_text(scope, hfinfo, value);
3774 break;
3775 case FT_STRINGZTRUNC:
3776 value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
3777 *retval = hfinfo_format_text(scope, hfinfo, value);
3778 break;
3779 case FT_BYTES:
3780 value = tvb_get_ptr(tvb, start, length);
3781 *retval = hfinfo_format_bytes(scope, hfinfo, value, length);
3782 *lenretval = length;
3783 break;
3784 case FT_UINT_BYTES:
3785 n = get_uint_value(tree, tvb, start, length, encoding);
3786 value = tvb_get_ptr(tvb, start + length, n);
3787 *retval = hfinfo_format_bytes(scope, hfinfo, value, n);
3788 *lenretval = length + n;
3789 break;
3790 default:
3791 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, FT_STRINGZTRUNC, FT_BYTES, or FT_UINT_BYTES",
3792 hfinfo->abbrev);
3793 }
3794
3795 CHECK_FOR_NULL_TREE(tree);
3796
3797 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3798
3799 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
3800
3801 switch (hfinfo->type) {
3802
3803 case FT_STRING:
3804 case FT_STRINGZ:
3805 case FT_UINT_STRING:
3806 case FT_STRINGZPAD:
3807 case FT_STRINGZTRUNC:
3808 proto_tree_set_string(new_fi, value);
3809 break;
3810
3811 case FT_BYTES:
3812 proto_tree_set_bytes(new_fi, value, length);
3813 break;
3814
3815 case FT_UINT_BYTES:
3816 proto_tree_set_bytes(new_fi, value, n);
3817 break;
3818
3819 default:
3820 ws_assert_not_reached();
3821 }
3822
3823 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3824
3825 pi = proto_tree_add_node(tree, new_fi);
3826
3827 switch (hfinfo->type) {
3828
3829 case FT_STRINGZ:
3830 case FT_STRINGZPAD:
3831 case FT_STRINGZTRUNC:
3832 case FT_UINT_STRING:
3833 break;
3834
3835 case FT_STRING:
3836 detect_trailing_stray_characters(encoding, value, length, pi);
3837 break;
3838
3839 case FT_BYTES:
3840 case FT_UINT_BYTES:
3841 break;
3842
3843 default:
3844 ws_assert_not_reached();
3845 }
3846
3847 return pi;
3848 }
3849
3850 proto_item *
proto_tree_add_item_ret_display_string(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,wmem_allocator_t * scope,char ** retval)3851 proto_tree_add_item_ret_display_string(proto_tree *tree, int hfindex,
3852 tvbuff_t *tvb,
3853 const gint start, gint length,
3854 const guint encoding,
3855 wmem_allocator_t *scope,
3856 char **retval)
3857 {
3858 return proto_tree_add_item_ret_display_string_and_length(tree, hfindex,
3859 tvb, start, length, encoding, scope, retval, &length);
3860 }
3861
3862 proto_item *
proto_tree_add_item_ret_time_string(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,wmem_allocator_t * scope,char ** retval)3863 proto_tree_add_item_ret_time_string(proto_tree *tree, int hfindex,
3864 tvbuff_t *tvb,
3865 const gint start, gint length, const guint encoding,
3866 wmem_allocator_t *scope, char **retval)
3867 {
3868 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3869 field_info *new_fi;
3870 nstime_t time_stamp;
3871
3872 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3873
3874 switch (hfinfo->type) {
3875 case FT_ABSOLUTE_TIME:
3876 get_time_value(tree, tvb, start, length, encoding, &time_stamp, FALSE);
3877 *retval = abs_time_to_str(scope, &time_stamp, (absolute_time_display_e)hfinfo->display, TRUE);
3878 break;
3879 case FT_RELATIVE_TIME:
3880 get_time_value(tree, tvb, start, length, encoding, &time_stamp, TRUE);
3881 *retval = rel_time_to_secs_str(scope, &time_stamp);
3882 break;
3883 default:
3884 REPORT_DISSECTOR_BUG("field %s is not of type FT_ABSOLUTE_TIME or FT_RELATIVE_TIME",
3885 hfinfo->abbrev);
3886 }
3887
3888 CHECK_FOR_NULL_TREE(tree);
3889
3890 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3891
3892 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3893
3894 switch (hfinfo->type) {
3895
3896 case FT_ABSOLUTE_TIME:
3897 case FT_RELATIVE_TIME:
3898 proto_tree_set_time(new_fi, &time_stamp);
3899 break;
3900 default:
3901 ws_assert_not_reached();
3902 }
3903
3904 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3905
3906 return proto_tree_add_node(tree, new_fi);
3907 }
3908
3909 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3910 and returns proto_item* */
3911 proto_item *
ptvcursor_add(ptvcursor_t * ptvc,int hfindex,gint length,const guint encoding)3912 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
3913 const guint encoding)
3914 {
3915 field_info *new_fi;
3916 header_field_info *hfinfo;
3917 gint item_length;
3918 int offset;
3919
3920 offset = ptvc->offset;
3921 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3922 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3923 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3924
3925 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3926 item_length, encoding);
3927
3928 CHECK_FOR_NULL_TREE(ptvc->tree);
3929
3930 /* Coast clear. Try and fake it */
3931 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3932
3933 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3934
3935 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3936 offset, length, encoding);
3937 }
3938
3939 /* Add an item to a proto_tree, using the text label registered to that item;
3940 the item is extracted from the tvbuff handed to it. */
3941 proto_item *
proto_tree_add_item_new(proto_tree * tree,header_field_info * hfinfo,tvbuff_t * tvb,const gint start,gint length,const guint encoding)3942 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3943 const gint start, gint length, const guint encoding)
3944 {
3945 field_info *new_fi;
3946 gint item_length;
3947
3948 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3949
3950 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
3951 test_length(hfinfo, tvb, start, item_length, encoding);
3952
3953 CHECK_FOR_NULL_TREE(tree);
3954
3955 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3956
3957 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
3958
3959 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
3960 }
3961
3962 proto_item *
proto_tree_add_item(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding)3963 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3964 const gint start, gint length, const guint encoding)
3965 {
3966 register header_field_info *hfinfo;
3967
3968 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3969 return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
3970 }
3971
3972 /* Add an item to a proto_tree, using the text label registered to that item;
3973 the item is extracted from the tvbuff handed to it.
3974
3975 Return the length of the item through the pointer. */
3976 proto_item *
proto_tree_add_item_new_ret_length(proto_tree * tree,header_field_info * hfinfo,tvbuff_t * tvb,const gint start,gint length,const guint encoding,gint * lenretval)3977 proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
3978 tvbuff_t *tvb, const gint start,
3979 gint length, const guint encoding,
3980 gint *lenretval)
3981 {
3982 field_info *new_fi;
3983 gint item_length;
3984 proto_item *item;
3985
3986 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3987
3988 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
3989 test_length(hfinfo, tvb, start, item_length, encoding);
3990
3991 if (!tree) {
3992 /*
3993 * We need to get the correct item length here.
3994 * That's normally done by proto_tree_new_item(),
3995 * but we won't be calling it.
3996 */
3997 *lenretval = get_full_length(hfinfo, tvb, start, length,
3998 item_length, encoding);
3999 return NULL;
4000 }
4001
4002 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo, {
4003 /*
4004 * Even if the tree item is not referenced (and thus faked),
4005 * the caller must still be informed of the actual length.
4006 */
4007 *lenretval = get_full_length(hfinfo, tvb, start, length,
4008 item_length, encoding);
4009 });
4010
4011 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4012
4013 item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
4014 *lenretval = new_fi->length;
4015 return item;
4016 }
4017
4018 proto_item *
proto_tree_add_item_ret_length(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,gint * lenretval)4019 proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4020 const gint start, gint length,
4021 const guint encoding, gint *lenretval)
4022 {
4023 register header_field_info *hfinfo;
4024
4025 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4026 return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, lenretval);
4027 }
4028
4029 /* which FT_ types can use proto_tree_add_bytes_item() */
4030 static inline gboolean
validate_proto_tree_add_bytes_ftype(const enum ftenum type)4031 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
4032 {
4033 return (type == FT_BYTES ||
4034 type == FT_UINT_BYTES ||
4035 type == FT_OID ||
4036 type == FT_REL_OID ||
4037 type == FT_SYSTEM_ID );
4038 }
4039
4040 /* Note: this does no validation that the byte array of an FT_OID or
4041 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
4042 so I think it's ok to continue not validating it?
4043 */
4044 proto_item *
proto_tree_add_bytes_item(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,GByteArray * retval,gint * endoff,gint * err)4045 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4046 const gint start, gint length, const guint encoding,
4047 GByteArray *retval, gint *endoff, gint *err)
4048 {
4049 field_info *new_fi;
4050 GByteArray *bytes = retval;
4051 GByteArray *created_bytes = NULL;
4052 gint saved_err = 0;
4053 guint32 n = 0;
4054 header_field_info *hfinfo;
4055 gboolean generate = (bytes || tree) ? TRUE : FALSE;
4056
4057 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4058
4059 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4060
4061 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
4062 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
4063
4064 /* length has to be -1 or > 0 regardless of encoding */
4065 /* invalid FT_UINT_BYTES length is caught in get_uint_value() */
4066 if (length < -1 || length == 0) {
4067 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_bytes_item for %s",
4068 length, ftype_name(hfinfo->type));
4069 }
4070
4071 if (encoding & ENC_STR_NUM) {
4072 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
4073 }
4074
4075 if (generate && (encoding & ENC_STR_HEX)) {
4076 if (hfinfo->type == FT_UINT_BYTES) {
4077 /* can't decode FT_UINT_BYTES from strings */
4078 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
4079 "FT_UINT_BYTES type, but as ENC_STR_HEX");
4080 }
4081
4082 if (!bytes) {
4083 /* caller doesn't care about return value, but we need it to
4084 call tvb_get_string_bytes() and set the tree later */
4085 bytes = created_bytes = g_byte_array_new();
4086 }
4087
4088 /* bytes might be NULL after this, but can't add expert error until later */
4089 bytes = tvb_get_string_bytes(tvb, start, length, encoding, bytes, endoff);
4090
4091 /* grab the errno now before it gets overwritten */
4092 saved_err = errno;
4093 }
4094 else if (generate) {
4095 tvb_ensure_bytes_exist(tvb, start, length);
4096
4097 if (!bytes) {
4098 /* caller doesn't care about return value, but we need it to
4099 call tvb_get_string_bytes() and set the tree later */
4100 bytes = created_bytes = g_byte_array_new();
4101 }
4102
4103 if (hfinfo->type == FT_UINT_BYTES) {
4104 n = length; /* n is now the "header" length */
4105 length = get_uint_value(tree, tvb, start, n, encoding);
4106 /* length is now the value's length; only store the value in the array */
4107 g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
4108 }
4109 else if (length > 0) {
4110 g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
4111 }
4112
4113 if (endoff)
4114 *endoff = start + n + length;
4115 }
4116
4117 if (err) *err = saved_err;
4118
4119 CHECK_FOR_NULL_TREE_AND_FREE(tree,
4120 {
4121 if (created_bytes)
4122 g_byte_array_free(created_bytes, TRUE);
4123 created_bytes = NULL;
4124 bytes = NULL;
4125 } );
4126
4127 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
4128 {
4129 if (created_bytes)
4130 g_byte_array_free(created_bytes, TRUE);
4131 created_bytes = NULL;
4132 bytes = NULL;
4133 } );
4134
4135 /* n will be zero except when it's a FT_UINT_BYTES */
4136 new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
4137
4138 if (encoding & ENC_STRING) {
4139 if (saved_err == ERANGE)
4140 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
4141 else if (!bytes || saved_err != 0)
4142 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
4143
4144 if (bytes)
4145 proto_tree_set_bytes_gbytearray(new_fi, bytes);
4146 else
4147 proto_tree_set_bytes(new_fi, NULL, 0);
4148
4149 if (created_bytes)
4150 g_byte_array_free(created_bytes, TRUE);
4151 }
4152 else {
4153 /* n will be zero except when it's a FT_UINT_BYTES */
4154 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
4155
4156 FI_SET_FLAG(new_fi,
4157 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
4158 }
4159
4160 return proto_tree_add_node(tree, new_fi);
4161 }
4162
4163
4164 proto_item *
proto_tree_add_time_item(proto_tree * tree,int hfindex,tvbuff_t * tvb,const gint start,gint length,const guint encoding,nstime_t * retval,gint * endoff,gint * err)4165 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4166 const gint start, gint length, const guint encoding,
4167 nstime_t *retval, gint *endoff, gint *err)
4168 {
4169 field_info *new_fi;
4170 nstime_t time_stamp;
4171 gint saved_err = 0;
4172 header_field_info *hfinfo;
4173
4174 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4175
4176 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4177
4178 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
4179
4180 /* length has to be -1 or > 0 regardless of encoding */
4181 if (length < -1 || length == 0) {
4182 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_time_item",
4183 length);
4184 }
4185
4186 time_stamp.secs = 0;
4187 time_stamp.nsecs = 0;
4188
4189 if (encoding & ENC_STR_TIME_MASK) {
4190 tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff);
4191 /* grab the errno now before it gets overwritten */
4192 saved_err = errno;
4193 }
4194 else {
4195 const gboolean is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? TRUE : FALSE;
4196
4197 tvb_ensure_bytes_exist(tvb, start, length);
4198 get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
4199 if (endoff) *endoff = length;
4200 }
4201
4202 if (err) *err = saved_err;
4203
4204 if (retval) {
4205 retval->secs = time_stamp.secs;
4206 retval->nsecs = time_stamp.nsecs;
4207 }
4208
4209 CHECK_FOR_NULL_TREE(tree);
4210
4211 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4212
4213 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4214
4215 proto_tree_set_time(new_fi, &time_stamp);
4216
4217 if (encoding & ENC_STRING) {
4218 if (saved_err == ERANGE)
4219 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
4220 else if (saved_err == EDOM)
4221 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
4222 }
4223 else {
4224 FI_SET_FLAG(new_fi,
4225 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
4226 }
4227
4228 return proto_tree_add_node(tree, new_fi);
4229 }
4230
4231 /* Add a FT_NONE to a proto_tree */
4232 proto_item *
proto_tree_add_none_format(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const gint start,gint length,const char * format,...)4233 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
4234 const gint start, gint length, const char *format,
4235 ...)
4236 {
4237 proto_item *pi;
4238 va_list ap;
4239 header_field_info *hfinfo;
4240
4241 CHECK_FOR_NULL_TREE(tree);
4242
4243 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4244
4245 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
4246
4247 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4248
4249 TRY_TO_FAKE_THIS_REPR(pi);
4250
4251 va_start(ap, format);
4252 proto_tree_set_representation(pi, format, ap);
4253 va_end(ap);
4254
4255 /* no value to set for FT_NONE */
4256 return pi;
4257 }
4258
4259 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
4260 * offset, and returns proto_item* */
4261 proto_item *
ptvcursor_add_no_advance(ptvcursor_t * ptvc,int hf,gint length,const guint encoding)4262 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
4263 const guint encoding)
4264 {
4265 proto_item *item;
4266
4267 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
4268 length, encoding);
4269
4270 return item;
4271 }
4272
4273 /* Advance the ptvcursor's offset within its tvbuff without
4274 * adding anything to the proto_tree. */
4275 void
ptvcursor_advance(ptvcursor_t * ptvc,gint length)4276 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
4277 {
4278 ptvc->offset += length;
4279 }
4280
4281
4282 static void
proto_tree_set_protocol_tvb(field_info * fi,tvbuff_t * tvb,const char * field_data)4283 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data)
4284 {
4285 fvalue_set_protocol(&fi->value, tvb, field_data);
4286 }
4287
4288 /* Add a FT_PROTOCOL to a proto_tree */
4289 proto_item *
proto_tree_add_protocol_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const char * format,...)4290 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4291 gint start, gint length, const char *format, ...)
4292 {
4293 proto_item *pi;
4294 tvbuff_t *protocol_tvb;
4295 va_list ap;
4296 header_field_info *hfinfo;
4297 gchar* protocol_rep;
4298
4299 CHECK_FOR_NULL_TREE(tree);
4300
4301 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4302
4303 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
4304
4305 /*
4306 * This can throw an exception, so do it before we allocate anything.
4307 */
4308 protocol_tvb = (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length));
4309
4310 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4311
4312 va_start(ap, format);
4313 protocol_rep = g_strdup_vprintf(format, ap);
4314 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), protocol_tvb, protocol_rep);
4315 g_free(protocol_rep);
4316 va_end(ap);
4317
4318 TRY_TO_FAKE_THIS_REPR(pi);
4319
4320 va_start(ap, format);
4321 proto_tree_set_representation(pi, format, ap);
4322 va_end(ap);
4323
4324 return pi;
4325 }
4326
4327 /* Add a FT_BYTES to a proto_tree */
4328 proto_item *
proto_tree_add_bytes(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * start_ptr)4329 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4330 gint length, const guint8 *start_ptr)
4331 {
4332 proto_item *pi;
4333 header_field_info *hfinfo;
4334 gint item_length;
4335
4336 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4337 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
4338 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4339
4340 CHECK_FOR_NULL_TREE(tree);
4341
4342 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4343
4344 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
4345
4346 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4347 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
4348
4349 return pi;
4350 }
4351
4352 /* Add a FT_BYTES to a proto_tree */
4353 proto_item *
proto_tree_add_bytes_with_length(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint tvbuff_length,const guint8 * start_ptr,gint ptr_length)4354 proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4355 gint tvbuff_length, const guint8 *start_ptr, gint ptr_length)
4356 {
4357 proto_item *pi;
4358 header_field_info *hfinfo;
4359 gint item_length;
4360
4361 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4362 get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length, ENC_NA);
4363 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4364
4365 CHECK_FOR_NULL_TREE(tree);
4366
4367 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4368
4369 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
4370
4371 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &tvbuff_length);
4372 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, ptr_length);
4373
4374 return pi;
4375 }
4376
4377 proto_item *
proto_tree_add_bytes_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * start_ptr,const char * format,...)4378 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4379 gint start, gint length,
4380 const guint8 *start_ptr,
4381 const char *format, ...)
4382 {
4383 proto_item *pi;
4384 va_list ap;
4385
4386 if (start_ptr == NULL)
4387 start_ptr = tvb_get_ptr(tvb, start, length);
4388
4389 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
4390
4391 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
4392
4393 va_start(ap, format);
4394 proto_tree_set_representation_value(pi, format, ap);
4395 va_end(ap);
4396
4397 return pi;
4398 }
4399
4400 proto_item *
proto_tree_add_bytes_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * start_ptr,const char * format,...)4401 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4402 gint start, gint length, const guint8 *start_ptr,
4403 const char *format, ...)
4404 {
4405 proto_item *pi;
4406 va_list ap;
4407
4408 if (start_ptr == NULL)
4409 start_ptr = tvb_get_ptr(tvb, start, length);
4410
4411 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
4412
4413 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
4414
4415 va_start(ap, format);
4416 proto_tree_set_representation(pi, format, ap);
4417 va_end(ap);
4418
4419 return pi;
4420 }
4421
4422 static void
proto_tree_set_bytes(field_info * fi,const guint8 * start_ptr,gint length)4423 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
4424 {
4425 GByteArray *bytes;
4426
4427 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
4428
4429 bytes = g_byte_array_new();
4430 if (length > 0) {
4431 g_byte_array_append(bytes, start_ptr, length);
4432 }
4433 fvalue_set_byte_array(&fi->value, bytes);
4434 }
4435
4436
4437 static void
proto_tree_set_bytes_tvb(field_info * fi,tvbuff_t * tvb,gint offset,gint length)4438 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
4439 {
4440 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
4441 }
4442
4443 static void
proto_tree_set_bytes_gbytearray(field_info * fi,const GByteArray * value)4444 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
4445 {
4446 GByteArray *bytes;
4447
4448 DISSECTOR_ASSERT(value != NULL);
4449
4450 bytes = byte_array_dup(value);
4451
4452 fvalue_set_byte_array(&fi->value, bytes);
4453 }
4454
4455 /* Add a FT_*TIME to a proto_tree */
4456 proto_item *
proto_tree_add_time(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const nstime_t * value_ptr)4457 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4458 gint length, const nstime_t *value_ptr)
4459 {
4460 proto_item *pi;
4461 header_field_info *hfinfo;
4462
4463 CHECK_FOR_NULL_TREE(tree);
4464
4465 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4466
4467 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
4468
4469 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4470 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
4471
4472 return pi;
4473 }
4474
4475 proto_item *
proto_tree_add_time_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,nstime_t * value_ptr,const char * format,...)4476 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4477 gint start, gint length, nstime_t *value_ptr,
4478 const char *format, ...)
4479 {
4480 proto_item *pi;
4481 va_list ap;
4482
4483 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
4484 if (pi != tree) {
4485 va_start(ap, format);
4486 proto_tree_set_representation_value(pi, format, ap);
4487 va_end(ap);
4488 }
4489
4490 return pi;
4491 }
4492
4493 proto_item *
proto_tree_add_time_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,nstime_t * value_ptr,const char * format,...)4494 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4495 gint start, gint length, nstime_t *value_ptr,
4496 const char *format, ...)
4497 {
4498 proto_item *pi;
4499 va_list ap;
4500
4501 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
4502 if (pi != tree) {
4503 TRY_TO_FAKE_THIS_REPR(pi);
4504
4505 va_start(ap, format);
4506 proto_tree_set_representation(pi, format, ap);
4507 va_end(ap);
4508 }
4509
4510 return pi;
4511 }
4512
4513 /* Set the FT_*TIME value */
4514 static void
proto_tree_set_time(field_info * fi,const nstime_t * value_ptr)4515 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
4516 {
4517 DISSECTOR_ASSERT(value_ptr != NULL);
4518
4519 fvalue_set_time(&fi->value, value_ptr);
4520 }
4521
4522 /* Add a FT_IPXNET to a proto_tree */
4523 proto_item *
proto_tree_add_ipxnet(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value)4524 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4525 gint length, guint32 value)
4526 {
4527 proto_item *pi;
4528 header_field_info *hfinfo;
4529
4530 CHECK_FOR_NULL_TREE(tree);
4531
4532 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4533
4534 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
4535
4536 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4537 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
4538
4539 return pi;
4540 }
4541
4542 proto_item *
proto_tree_add_ipxnet_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value,const char * format,...)4543 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4544 gint start, gint length, guint32 value,
4545 const char *format, ...)
4546 {
4547 proto_item *pi;
4548 va_list ap;
4549
4550 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
4551 if (pi != tree) {
4552 va_start(ap, format);
4553 proto_tree_set_representation_value(pi, format, ap);
4554 va_end(ap);
4555 }
4556
4557 return pi;
4558 }
4559
4560 proto_item *
proto_tree_add_ipxnet_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value,const char * format,...)4561 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4562 gint start, gint length, guint32 value,
4563 const char *format, ...)
4564 {
4565 proto_item *pi;
4566 va_list ap;
4567
4568 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
4569 if (pi != tree) {
4570 TRY_TO_FAKE_THIS_REPR(pi);
4571
4572 va_start(ap, format);
4573 proto_tree_set_representation(pi, format, ap);
4574 va_end(ap);
4575 }
4576
4577 return pi;
4578 }
4579
4580 /* Set the FT_IPXNET value */
4581 static void
proto_tree_set_ipxnet(field_info * fi,guint32 value)4582 proto_tree_set_ipxnet(field_info *fi, guint32 value)
4583 {
4584 fvalue_set_uinteger(&fi->value, value);
4585 }
4586
4587 /* Add a FT_IPv4 to a proto_tree */
4588 proto_item *
proto_tree_add_ipv4(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,ws_in4_addr value)4589 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4590 gint length, ws_in4_addr value)
4591 {
4592 proto_item *pi;
4593 header_field_info *hfinfo;
4594
4595 CHECK_FOR_NULL_TREE(tree);
4596
4597 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4598
4599 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
4600
4601 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4602 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
4603
4604 return pi;
4605 }
4606
4607 proto_item *
proto_tree_add_ipv4_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,ws_in4_addr value,const char * format,...)4608 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4609 gint start, gint length, ws_in4_addr value,
4610 const char *format, ...)
4611 {
4612 proto_item *pi;
4613 va_list ap;
4614
4615 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
4616 if (pi != tree) {
4617 va_start(ap, format);
4618 proto_tree_set_representation_value(pi, format, ap);
4619 va_end(ap);
4620 }
4621
4622 return pi;
4623 }
4624
4625 proto_item *
proto_tree_add_ipv4_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,ws_in4_addr value,const char * format,...)4626 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4627 gint start, gint length, ws_in4_addr value,
4628 const char *format, ...)
4629 {
4630 proto_item *pi;
4631 va_list ap;
4632
4633 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
4634 if (pi != tree) {
4635 TRY_TO_FAKE_THIS_REPR(pi);
4636
4637 va_start(ap, format);
4638 proto_tree_set_representation(pi, format, ap);
4639 va_end(ap);
4640 }
4641
4642 return pi;
4643 }
4644
4645 /* Set the FT_IPv4 value */
4646 static void
proto_tree_set_ipv4(field_info * fi,ws_in4_addr value)4647 proto_tree_set_ipv4(field_info *fi, ws_in4_addr value)
4648 {
4649 fvalue_set_uinteger(&fi->value, value);
4650 }
4651
4652 /* Add a FT_IPv6 to a proto_tree */
4653 proto_item *
proto_tree_add_ipv6(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const ws_in6_addr * value_ptr)4654 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4655 gint length, const ws_in6_addr *value_ptr)
4656 {
4657 proto_item *pi;
4658 header_field_info *hfinfo;
4659
4660 CHECK_FOR_NULL_TREE(tree);
4661
4662 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4663
4664 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
4665
4666 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4667 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr->bytes);
4668
4669 return pi;
4670 }
4671
4672 proto_item *
proto_tree_add_ipv6_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const ws_in6_addr * value_ptr,const char * format,...)4673 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4674 gint start, gint length,
4675 const ws_in6_addr *value_ptr,
4676 const char *format, ...)
4677 {
4678 proto_item *pi;
4679 va_list ap;
4680
4681 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
4682 if (pi != tree) {
4683 va_start(ap, format);
4684 proto_tree_set_representation_value(pi, format, ap);
4685 va_end(ap);
4686 }
4687
4688 return pi;
4689 }
4690
4691 proto_item *
proto_tree_add_ipv6_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const ws_in6_addr * value_ptr,const char * format,...)4692 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4693 gint start, gint length,
4694 const ws_in6_addr *value_ptr,
4695 const char *format, ...)
4696 {
4697 proto_item *pi;
4698 va_list ap;
4699
4700 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
4701 if (pi != tree) {
4702 TRY_TO_FAKE_THIS_REPR(pi);
4703
4704 va_start(ap, format);
4705 proto_tree_set_representation(pi, format, ap);
4706 va_end(ap);
4707 }
4708
4709 return pi;
4710 }
4711
4712 /* Set the FT_IPv6 value */
4713 static void
proto_tree_set_ipv6(field_info * fi,const guint8 * value_ptr)4714 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
4715 {
4716 DISSECTOR_ASSERT(value_ptr != NULL);
4717 fvalue_set_bytes(&fi->value, value_ptr);
4718 }
4719
4720 static void
proto_tree_set_ipv6_tvb(field_info * fi,tvbuff_t * tvb,gint start,gint length)4721 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
4722 {
4723 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
4724 }
4725
4726 /* Set the FT_FCWWN value */
4727 static void
proto_tree_set_fcwwn(field_info * fi,const guint8 * value_ptr)4728 proto_tree_set_fcwwn(field_info *fi, const guint8* value_ptr)
4729 {
4730 DISSECTOR_ASSERT(value_ptr != NULL);
4731 fvalue_set_bytes(&fi->value, value_ptr);
4732 }
4733
4734 static void
proto_tree_set_fcwwn_tvb(field_info * fi,tvbuff_t * tvb,gint start,gint length)4735 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
4736 {
4737 proto_tree_set_fcwwn(fi, tvb_get_ptr(tvb, start, length));
4738 }
4739
4740 /* Add a FT_GUID to a proto_tree */
4741 proto_item *
proto_tree_add_guid(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const e_guid_t * value_ptr)4742 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4743 gint length, const e_guid_t *value_ptr)
4744 {
4745 proto_item *pi;
4746 header_field_info *hfinfo;
4747
4748 CHECK_FOR_NULL_TREE(tree);
4749
4750 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4751
4752 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
4753
4754 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4755 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
4756
4757 return pi;
4758 }
4759
4760 proto_item *
proto_tree_add_guid_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const e_guid_t * value_ptr,const char * format,...)4761 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4762 gint start, gint length,
4763 const e_guid_t *value_ptr,
4764 const char *format, ...)
4765 {
4766 proto_item *pi;
4767 va_list ap;
4768
4769 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
4770 if (pi != tree) {
4771 va_start(ap, format);
4772 proto_tree_set_representation_value(pi, format, ap);
4773 va_end(ap);
4774 }
4775
4776 return pi;
4777 }
4778
4779 proto_item *
proto_tree_add_guid_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const e_guid_t * value_ptr,const char * format,...)4780 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4781 gint start, gint length, const e_guid_t *value_ptr,
4782 const char *format, ...)
4783 {
4784 proto_item *pi;
4785 va_list ap;
4786
4787 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
4788 if (pi != tree) {
4789 TRY_TO_FAKE_THIS_REPR(pi);
4790
4791 va_start(ap, format);
4792 proto_tree_set_representation(pi, format, ap);
4793 va_end(ap);
4794 }
4795
4796 return pi;
4797 }
4798
4799 /* Set the FT_GUID value */
4800 static void
proto_tree_set_guid(field_info * fi,const e_guid_t * value_ptr)4801 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
4802 {
4803 DISSECTOR_ASSERT(value_ptr != NULL);
4804 fvalue_set_guid(&fi->value, value_ptr);
4805 }
4806
4807 static void
proto_tree_set_guid_tvb(field_info * fi,tvbuff_t * tvb,gint start,const guint encoding)4808 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
4809 const guint encoding)
4810 {
4811 e_guid_t guid;
4812
4813 tvb_get_guid(tvb, start, &guid, encoding);
4814 proto_tree_set_guid(fi, &guid);
4815 }
4816
4817 /* Add a FT_OID to a proto_tree */
4818 proto_item *
proto_tree_add_oid(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * value_ptr)4819 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4820 gint length, const guint8* value_ptr)
4821 {
4822 proto_item *pi;
4823 header_field_info *hfinfo;
4824
4825 CHECK_FOR_NULL_TREE(tree);
4826
4827 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4828
4829 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
4830
4831 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4832 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
4833
4834 return pi;
4835 }
4836
4837 proto_item *
proto_tree_add_oid_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * value_ptr,const char * format,...)4838 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4839 gint start, gint length,
4840 const guint8* value_ptr,
4841 const char *format, ...)
4842 {
4843 proto_item *pi;
4844 va_list ap;
4845
4846 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
4847 if (pi != tree) {
4848 va_start(ap, format);
4849 proto_tree_set_representation_value(pi, format, ap);
4850 va_end(ap);
4851 }
4852
4853 return pi;
4854 }
4855
4856 proto_item *
proto_tree_add_oid_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * value_ptr,const char * format,...)4857 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4858 gint start, gint length, const guint8* value_ptr,
4859 const char *format, ...)
4860 {
4861 proto_item *pi;
4862 va_list ap;
4863
4864 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
4865 if (pi != tree) {
4866 TRY_TO_FAKE_THIS_REPR(pi);
4867
4868 va_start(ap, format);
4869 proto_tree_set_representation(pi, format, ap);
4870 va_end(ap);
4871 }
4872
4873 return pi;
4874 }
4875
4876 /* Set the FT_OID value */
4877 static void
proto_tree_set_oid(field_info * fi,const guint8 * value_ptr,gint length)4878 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
4879 {
4880 GByteArray *bytes;
4881
4882 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
4883
4884 bytes = g_byte_array_new();
4885 if (length > 0) {
4886 g_byte_array_append(bytes, value_ptr, length);
4887 }
4888 fvalue_set_byte_array(&fi->value, bytes);
4889 }
4890
4891 static void
proto_tree_set_oid_tvb(field_info * fi,tvbuff_t * tvb,gint start,gint length)4892 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
4893 {
4894 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
4895 }
4896
4897 /* Set the FT_SYSTEM_ID value */
4898 static void
proto_tree_set_system_id(field_info * fi,const guint8 * value_ptr,gint length)4899 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length)
4900 {
4901 GByteArray *bytes;
4902
4903 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
4904
4905 bytes = g_byte_array_new();
4906 if (length > 0) {
4907 g_byte_array_append(bytes, value_ptr, length);
4908 }
4909 fvalue_set_byte_array(&fi->value, bytes);
4910 }
4911
4912 static void
proto_tree_set_system_id_tvb(field_info * fi,tvbuff_t * tvb,gint start,gint length)4913 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
4914 {
4915 proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
4916 }
4917
4918 /* Add a FT_STRING, FT_STRINGZ, FT_STRINGZPAD, or FT_STRINGZTRUNC to a
4919 * proto_tree. Creates own copy of string, and frees it when the proto_tree
4920 * is destroyed. */
4921 proto_item *
proto_tree_add_string(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const char * value)4922 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4923 gint length, const char* value)
4924 {
4925 proto_item *pi;
4926 header_field_info *hfinfo;
4927 gint item_length;
4928
4929 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4930 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
4931 /*
4932 * Special case - if the length is 0, skip the test, so that
4933 * we can have an empty string right after the end of the
4934 * packet. (This handles URL-encoded forms where the last field
4935 * has no value so the form ends right after the =.)
4936 */
4937 if (item_length != 0)
4938 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4939
4940 CHECK_FOR_NULL_TREE(tree);
4941
4942 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4943
4944 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
4945
4946 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4947 DISSECTOR_ASSERT(length >= 0);
4948 proto_tree_set_string(PNODE_FINFO(pi), value);
4949
4950 return pi;
4951 }
4952
4953 proto_item *
proto_tree_add_string_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const char * value,const char * format,...)4954 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4955 gint start, gint length, const char* value,
4956 const char *format,
4957 ...)
4958 {
4959 proto_item *pi;
4960 va_list ap;
4961
4962 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
4963 if (pi != tree) {
4964 va_start(ap, format);
4965 proto_tree_set_representation_value(pi, format, ap);
4966 va_end(ap);
4967 }
4968
4969 return pi;
4970 }
4971
4972 proto_item *
proto_tree_add_string_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const char * value,const char * format,...)4973 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4974 gint start, gint length, const char* value,
4975 const char *format, ...)
4976 {
4977 proto_item *pi;
4978 va_list ap;
4979
4980 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
4981 if (pi != tree) {
4982 TRY_TO_FAKE_THIS_REPR(pi);
4983
4984 va_start(ap, format);
4985 proto_tree_set_representation(pi, format, ap);
4986 va_end(ap);
4987 }
4988
4989 return pi;
4990 }
4991
4992 /* Set the FT_STRING value */
4993 static void
proto_tree_set_string(field_info * fi,const char * value)4994 proto_tree_set_string(field_info *fi, const char* value)
4995 {
4996 if (value) {
4997 fvalue_set_string(&fi->value, value);
4998 } else {
4999 /*
5000 * XXX - why is a null value for a string field
5001 * considered valid?
5002 */
5003 fvalue_set_string(&fi->value, "[ Null ]");
5004 }
5005 }
5006
5007 /* Set the FT_AX25 value */
5008 static void
proto_tree_set_ax25(field_info * fi,const guint8 * value)5009 proto_tree_set_ax25(field_info *fi, const guint8* value)
5010 {
5011 fvalue_set_bytes(&fi->value, value);
5012 }
5013
5014 static void
proto_tree_set_ax25_tvb(field_info * fi,tvbuff_t * tvb,gint start)5015 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
5016 {
5017 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
5018 }
5019
5020 /* Set the FT_VINES value */
5021 static void
proto_tree_set_vines(field_info * fi,const guint8 * value)5022 proto_tree_set_vines(field_info *fi, const guint8* value)
5023 {
5024 fvalue_set_bytes(&fi->value, value);
5025 }
5026
5027 static void
proto_tree_set_vines_tvb(field_info * fi,tvbuff_t * tvb,gint start)5028 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
5029 {
5030 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
5031 }
5032
5033 /* Add a FT_ETHER to a proto_tree */
5034 proto_item *
proto_tree_add_ether(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * value)5035 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5036 gint length, const guint8* value)
5037 {
5038 proto_item *pi;
5039 header_field_info *hfinfo;
5040
5041 CHECK_FOR_NULL_TREE(tree);
5042
5043 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5044
5045 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
5046
5047 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5048 proto_tree_set_ether(PNODE_FINFO(pi), value);
5049
5050 return pi;
5051 }
5052
5053 proto_item *
proto_tree_add_ether_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * value,const char * format,...)5054 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5055 gint start, gint length, const guint8* value,
5056 const char *format, ...)
5057 {
5058 proto_item *pi;
5059 va_list ap;
5060
5061 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
5062 if (pi != tree) {
5063 va_start(ap, format);
5064 proto_tree_set_representation_value(pi, format, ap);
5065 va_end(ap);
5066 }
5067
5068 return pi;
5069 }
5070
5071 proto_item *
proto_tree_add_ether_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint8 * value,const char * format,...)5072 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5073 gint start, gint length, const guint8* value,
5074 const char *format, ...)
5075 {
5076 proto_item *pi;
5077 va_list ap;
5078
5079 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
5080 if (pi != tree) {
5081 TRY_TO_FAKE_THIS_REPR(pi);
5082
5083 va_start(ap, format);
5084 proto_tree_set_representation(pi, format, ap);
5085 va_end(ap);
5086 }
5087
5088 return pi;
5089 }
5090
5091 /* Set the FT_ETHER value */
5092 static void
proto_tree_set_ether(field_info * fi,const guint8 * value)5093 proto_tree_set_ether(field_info *fi, const guint8* value)
5094 {
5095 fvalue_set_bytes(&fi->value, value);
5096 }
5097
5098 static void
proto_tree_set_ether_tvb(field_info * fi,tvbuff_t * tvb,gint start)5099 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
5100 {
5101 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
5102 }
5103
5104 /* Add a FT_BOOLEAN to a proto_tree */
5105 proto_item *
proto_tree_add_boolean(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value)5106 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5107 gint length, guint32 value)
5108 {
5109 proto_item *pi;
5110 header_field_info *hfinfo;
5111
5112 CHECK_FOR_NULL_TREE(tree);
5113
5114 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5115
5116 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
5117
5118 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5119 proto_tree_set_boolean(PNODE_FINFO(pi), value);
5120
5121 return pi;
5122 }
5123
5124 proto_item *
proto_tree_add_boolean_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value,const char * format,...)5125 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
5126 tvbuff_t *tvb, gint start, gint length,
5127 guint32 value, const char *format, ...)
5128 {
5129 proto_item *pi;
5130 va_list ap;
5131
5132 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
5133 if (pi != tree) {
5134 va_start(ap, format);
5135 proto_tree_set_representation_value(pi, format, ap);
5136 va_end(ap);
5137 }
5138
5139 return pi;
5140 }
5141
5142 proto_item *
proto_tree_add_boolean_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value,const char * format,...)5143 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5144 gint start, gint length, guint32 value,
5145 const char *format, ...)
5146 {
5147 proto_item *pi;
5148 va_list ap;
5149
5150 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
5151 if (pi != tree) {
5152 TRY_TO_FAKE_THIS_REPR(pi);
5153
5154 va_start(ap, format);
5155 proto_tree_set_representation(pi, format, ap);
5156 va_end(ap);
5157 }
5158
5159 return pi;
5160 }
5161
5162 static proto_item *
proto_tree_add_boolean64(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint64 value)5163 proto_tree_add_boolean64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5164 gint length, guint64 value)
5165 {
5166 proto_item *pi;
5167 header_field_info *hfinfo;
5168
5169 CHECK_FOR_NULL_TREE(tree);
5170
5171 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5172
5173 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
5174
5175 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5176 proto_tree_set_boolean(PNODE_FINFO(pi), value);
5177
5178 return pi;
5179 }
5180
5181 /* Set the FT_BOOLEAN value */
5182 static void
proto_tree_set_boolean(field_info * fi,guint64 value)5183 proto_tree_set_boolean(field_info *fi, guint64 value)
5184 {
5185 proto_tree_set_uint64(fi, value);
5186 }
5187
5188 /* Generate, into "buf", a string showing the bits of a bitfield.
5189 Return a pointer to the character after that string. */
5190 static char *
other_decode_bitfield_value(char * buf,const guint64 val,const guint64 mask,const int width)5191 other_decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
5192 {
5193 int i;
5194 guint64 bit;
5195 char *p;
5196
5197 i = 0;
5198 p = buf;
5199
5200 /* This is a devel error. It is safer to stop here. */
5201 DISSECTOR_ASSERT(width >= 1);
5202
5203 bit = G_GUINT64_CONSTANT(1) << (width - 1);
5204 for (;;) {
5205 if (mask & bit) {
5206 /* This bit is part of the field. Show its value. */
5207 if (val & bit)
5208 *p++ = '1';
5209 else
5210 *p++ = '0';
5211 } else {
5212 /* This bit is not part of the field. */
5213 *p++ = '.';
5214 }
5215 bit >>= 1;
5216 i++;
5217 if (i >= width)
5218 break;
5219 if (i % 4 == 0)
5220 *p++ = ' ';
5221 }
5222 *p = '\0';
5223 return p;
5224 }
5225
5226 static char *
decode_bitfield_value(char * buf,const guint64 val,const guint64 mask,const int width)5227 decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
5228 {
5229 char *p;
5230
5231 p = other_decode_bitfield_value(buf, val, mask, width);
5232 p = g_stpcpy(p, " = ");
5233
5234 return p;
5235 }
5236
5237 static char *
other_decode_bitfield_varint_value(char * buf,guint64 val,guint64 mask,const int width)5238 other_decode_bitfield_varint_value(char *buf, guint64 val, guint64 mask, const int width)
5239 {
5240 int i = 0;
5241 guint64 bit;
5242 char *p;
5243
5244 p = buf;
5245 bit = G_GUINT64_CONSTANT(1) << (width - 1);
5246 for (;;) {
5247 if (((8-(i % 8)) != 8) && /* MSB is never used for value. */
5248 (mask & bit)) {
5249 /* This bit is part of the field. Show its value. */
5250 if (val & bit)
5251 *p++ = '1';
5252 else
5253 *p++ = '0';
5254 } else {
5255 /* This bit is not part of the field. */
5256 *p++ = '.';
5257 }
5258 bit >>= 1;
5259 i++;
5260 if (i >= width)
5261 break;
5262 if (i % 4 == 0)
5263 *p++ = ' ';
5264 }
5265
5266 *p = '\0';
5267 return p;
5268 }
5269
5270 static char *
decode_bitfield_varint_value(char * buf,const guint64 val,const guint64 mask,const int width)5271 decode_bitfield_varint_value(char *buf, const guint64 val, const guint64 mask, const int width)
5272 {
5273 char *p;
5274
5275 p = other_decode_bitfield_varint_value(buf, val, mask, width);
5276 p = g_stpcpy(p, " = ");
5277
5278 return p;
5279 }
5280
5281 /* Add a FT_FLOAT to a proto_tree */
5282 proto_item *
proto_tree_add_float(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,float value)5283 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5284 gint length, float value)
5285 {
5286 proto_item *pi;
5287 header_field_info *hfinfo;
5288
5289 CHECK_FOR_NULL_TREE(tree);
5290
5291 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5292
5293 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
5294
5295 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5296 proto_tree_set_float(PNODE_FINFO(pi), value);
5297
5298 return pi;
5299 }
5300
5301 proto_item *
proto_tree_add_float_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,float value,const char * format,...)5302 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5303 gint start, gint length, float value,
5304 const char *format, ...)
5305 {
5306 proto_item *pi;
5307 va_list ap;
5308
5309 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
5310 if (pi != tree) {
5311 va_start(ap, format);
5312 proto_tree_set_representation_value(pi, format, ap);
5313 va_end(ap);
5314 }
5315
5316 return pi;
5317 }
5318
5319 proto_item *
proto_tree_add_float_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,float value,const char * format,...)5320 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5321 gint start, gint length, float value,
5322 const char *format, ...)
5323 {
5324 proto_item *pi;
5325 va_list ap;
5326
5327 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
5328 if (pi != tree) {
5329 TRY_TO_FAKE_THIS_REPR(pi);
5330
5331 va_start(ap, format);
5332 proto_tree_set_representation(pi, format, ap);
5333 va_end(ap);
5334 }
5335
5336 return pi;
5337 }
5338
5339 /* Set the FT_FLOAT value */
5340 static void
proto_tree_set_float(field_info * fi,float value)5341 proto_tree_set_float(field_info *fi, float value)
5342 {
5343 fvalue_set_floating(&fi->value, value);
5344 }
5345
5346 /* Add a FT_DOUBLE to a proto_tree */
5347 proto_item *
proto_tree_add_double(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,double value)5348 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5349 gint length, double value)
5350 {
5351 proto_item *pi;
5352 header_field_info *hfinfo;
5353
5354 CHECK_FOR_NULL_TREE(tree);
5355
5356 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5357
5358 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
5359
5360 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5361 proto_tree_set_double(PNODE_FINFO(pi), value);
5362
5363 return pi;
5364 }
5365
5366 proto_item *
proto_tree_add_double_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,double value,const char * format,...)5367 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5368 gint start, gint length, double value,
5369 const char *format, ...)
5370 {
5371 proto_item *pi;
5372 va_list ap;
5373
5374 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
5375 if (pi != tree) {
5376 va_start(ap, format);
5377 proto_tree_set_representation_value(pi, format, ap);
5378 va_end(ap);
5379 }
5380
5381 return pi;
5382 }
5383
5384 proto_item *
proto_tree_add_double_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,double value,const char * format,...)5385 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5386 gint start, gint length, double value,
5387 const char *format, ...)
5388 {
5389 proto_item *pi;
5390 va_list ap;
5391
5392 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
5393 if (pi != tree) {
5394 TRY_TO_FAKE_THIS_REPR(pi);
5395
5396 va_start(ap, format);
5397 proto_tree_set_representation(pi, format, ap);
5398 va_end(ap);
5399 }
5400
5401 return pi;
5402 }
5403
5404 /* Set the FT_DOUBLE value */
5405 static void
proto_tree_set_double(field_info * fi,double value)5406 proto_tree_set_double(field_info *fi, double value)
5407 {
5408 fvalue_set_floating(&fi->value, value);
5409 }
5410
5411 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
5412 proto_item *
proto_tree_add_uint(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value)5413 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5414 gint length, guint32 value)
5415 {
5416 proto_item *pi = NULL;
5417 header_field_info *hfinfo;
5418
5419 CHECK_FOR_NULL_TREE(tree);
5420
5421 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5422
5423 switch (hfinfo->type) {
5424 case FT_CHAR:
5425 case FT_UINT8:
5426 case FT_UINT16:
5427 case FT_UINT24:
5428 case FT_UINT32:
5429 case FT_FRAMENUM:
5430 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5431 proto_tree_set_uint(PNODE_FINFO(pi), value);
5432 break;
5433
5434 default:
5435 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
5436 hfinfo->abbrev);
5437 }
5438
5439 return pi;
5440 }
5441
5442 proto_item *
proto_tree_add_uint_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value,const char * format,...)5443 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5444 gint start, gint length, guint32 value,
5445 const char *format, ...)
5446 {
5447 proto_item *pi;
5448 va_list ap;
5449
5450 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
5451 if (pi != tree) {
5452 va_start(ap, format);
5453 proto_tree_set_representation_value(pi, format, ap);
5454 va_end(ap);
5455 }
5456
5457 return pi;
5458 }
5459
5460 proto_item *
proto_tree_add_uint_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint32 value,const char * format,...)5461 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5462 gint start, gint length, guint32 value,
5463 const char *format, ...)
5464 {
5465 proto_item *pi;
5466 va_list ap;
5467
5468 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
5469 if (pi != tree) {
5470 TRY_TO_FAKE_THIS_REPR(pi);
5471
5472 va_start(ap, format);
5473 proto_tree_set_representation(pi, format, ap);
5474 va_end(ap);
5475 }
5476
5477 return pi;
5478 }
5479
5480 /* Set the FT_UINT{8,16,24,32} value */
5481 static void
proto_tree_set_uint(field_info * fi,guint32 value)5482 proto_tree_set_uint(field_info *fi, guint32 value)
5483 {
5484 header_field_info *hfinfo;
5485 guint32 integer;
5486
5487 hfinfo = fi->hfinfo;
5488 integer = value;
5489
5490 if (hfinfo->bitmask) {
5491 /* Mask out irrelevant portions */
5492 integer &= (guint32)(hfinfo->bitmask);
5493
5494 /* Shift bits */
5495 integer >>= hfinfo_bitshift(hfinfo);
5496
5497 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5498 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
5499 }
5500
5501 fvalue_set_uinteger(&fi->value, integer);
5502 }
5503
5504 /* Add FT_UINT{40,48,56,64} to a proto_tree */
5505 proto_item *
proto_tree_add_uint64(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint64 value)5506 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5507 gint length, guint64 value)
5508 {
5509 proto_item *pi = NULL;
5510 header_field_info *hfinfo;
5511
5512 CHECK_FOR_NULL_TREE(tree);
5513
5514 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5515
5516 switch (hfinfo->type) {
5517 case FT_UINT40:
5518 case FT_UINT48:
5519 case FT_UINT56:
5520 case FT_UINT64:
5521 case FT_FRAMENUM:
5522 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5523 proto_tree_set_uint64(PNODE_FINFO(pi), value);
5524 break;
5525
5526 default:
5527 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
5528 hfinfo->abbrev);
5529 }
5530
5531 return pi;
5532 }
5533
5534 proto_item *
proto_tree_add_uint64_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint64 value,const char * format,...)5535 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5536 gint start, gint length, guint64 value,
5537 const char *format, ...)
5538 {
5539 proto_item *pi;
5540 va_list ap;
5541
5542 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
5543 if (pi != tree) {
5544 va_start(ap, format);
5545 proto_tree_set_representation_value(pi, format, ap);
5546 va_end(ap);
5547 }
5548
5549 return pi;
5550 }
5551
5552 proto_item *
proto_tree_add_uint64_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,guint64 value,const char * format,...)5553 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5554 gint start, gint length, guint64 value,
5555 const char *format, ...)
5556 {
5557 proto_item *pi;
5558 va_list ap;
5559
5560 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
5561 if (pi != tree) {
5562 TRY_TO_FAKE_THIS_REPR(pi);
5563
5564 va_start(ap, format);
5565 proto_tree_set_representation(pi, format, ap);
5566 va_end(ap);
5567 }
5568
5569 return pi;
5570 }
5571
5572 /* Set the FT_UINT{40,48,56,64} value */
5573 static void
proto_tree_set_uint64(field_info * fi,guint64 value)5574 proto_tree_set_uint64(field_info *fi, guint64 value)
5575 {
5576 header_field_info *hfinfo;
5577 guint64 integer;
5578
5579 hfinfo = fi->hfinfo;
5580 integer = value;
5581
5582 if (hfinfo->bitmask) {
5583 /* Mask out irrelevant portions */
5584 integer &= hfinfo->bitmask;
5585
5586 /* Shift bits */
5587 integer >>= hfinfo_bitshift(hfinfo);
5588
5589 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5590 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
5591 }
5592
5593 fvalue_set_uinteger64(&fi->value, integer);
5594 }
5595
5596 /* Add FT_INT{8,16,24,32} to a proto_tree */
5597 proto_item *
proto_tree_add_int(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,gint32 value)5598 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5599 gint length, gint32 value)
5600 {
5601 proto_item *pi = NULL;
5602 header_field_info *hfinfo;
5603
5604 CHECK_FOR_NULL_TREE(tree);
5605
5606 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5607
5608 switch (hfinfo->type) {
5609 case FT_INT8:
5610 case FT_INT16:
5611 case FT_INT24:
5612 case FT_INT32:
5613 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5614 proto_tree_set_int(PNODE_FINFO(pi), value);
5615 break;
5616
5617 default:
5618 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
5619 hfinfo->abbrev);
5620 }
5621
5622 return pi;
5623 }
5624
5625 proto_item *
proto_tree_add_int_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,gint32 value,const char * format,...)5626 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5627 gint start, gint length, gint32 value,
5628 const char *format, ...)
5629 {
5630 proto_item *pi;
5631 va_list ap;
5632
5633 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
5634 if (pi != tree) {
5635 va_start(ap, format);
5636 proto_tree_set_representation_value(pi, format, ap);
5637 va_end(ap);
5638 }
5639
5640 return pi;
5641 }
5642
5643 proto_item *
proto_tree_add_int_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,gint32 value,const char * format,...)5644 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5645 gint start, gint length, gint32 value,
5646 const char *format, ...)
5647 {
5648 proto_item *pi;
5649 va_list ap;
5650
5651 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
5652 if (pi != tree) {
5653 TRY_TO_FAKE_THIS_REPR(pi);
5654
5655 va_start(ap, format);
5656 proto_tree_set_representation(pi, format, ap);
5657 va_end(ap);
5658 }
5659
5660 return pi;
5661 }
5662
5663 /* Set the FT_INT{8,16,24,32} value */
5664 static void
proto_tree_set_int(field_info * fi,gint32 value)5665 proto_tree_set_int(field_info *fi, gint32 value)
5666 {
5667 header_field_info *hfinfo;
5668 guint32 integer;
5669 gint no_of_bits;
5670
5671 hfinfo = fi->hfinfo;
5672 integer = (guint32) value;
5673
5674 if (hfinfo->bitmask) {
5675 /* Mask out irrelevant portions */
5676 integer &= (guint32)(hfinfo->bitmask);
5677
5678 /* Shift bits */
5679 integer >>= hfinfo_bitshift(hfinfo);
5680
5681 no_of_bits = ws_count_ones(hfinfo->bitmask);
5682 integer = ws_sign_ext32(integer, no_of_bits);
5683
5684 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5685 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
5686 }
5687
5688 fvalue_set_sinteger(&fi->value, integer);
5689 }
5690
5691 /* Add FT_INT{40,48,56,64} to a proto_tree */
5692 proto_item *
proto_tree_add_int64(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,gint64 value)5693 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5694 gint length, gint64 value)
5695 {
5696 proto_item *pi = NULL;
5697 header_field_info *hfinfo;
5698
5699 CHECK_FOR_NULL_TREE(tree);
5700
5701 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5702
5703 switch (hfinfo->type) {
5704 case FT_INT40:
5705 case FT_INT48:
5706 case FT_INT56:
5707 case FT_INT64:
5708 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5709 proto_tree_set_int64(PNODE_FINFO(pi), value);
5710 break;
5711
5712 default:
5713 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
5714 hfinfo->abbrev);
5715 }
5716
5717 return pi;
5718 }
5719
5720 proto_item *
proto_tree_add_int64_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,gint64 value,const char * format,...)5721 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5722 gint start, gint length, gint64 value,
5723 const char *format, ...)
5724 {
5725 proto_item *pi;
5726 va_list ap;
5727
5728 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
5729 if (pi != tree) {
5730 va_start(ap, format);
5731 proto_tree_set_representation_value(pi, format, ap);
5732 va_end(ap);
5733 }
5734
5735 return pi;
5736 }
5737
5738 /* Set the FT_INT{40,48,56,64} value */
5739 static void
proto_tree_set_int64(field_info * fi,gint64 value)5740 proto_tree_set_int64(field_info *fi, gint64 value)
5741 {
5742 header_field_info *hfinfo;
5743 guint64 integer;
5744 gint no_of_bits;
5745
5746 hfinfo = fi->hfinfo;
5747 integer = value;
5748
5749 if (hfinfo->bitmask) {
5750 /* Mask out irrelevant portions */
5751 integer &= hfinfo->bitmask;
5752
5753 /* Shift bits */
5754 integer >>= hfinfo_bitshift(hfinfo);
5755
5756 no_of_bits = ws_count_ones(hfinfo->bitmask);
5757 integer = ws_sign_ext64(integer, no_of_bits);
5758
5759 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5760 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
5761 }
5762
5763 fvalue_set_sinteger64(&fi->value, integer);
5764 }
5765
5766 proto_item *
proto_tree_add_int64_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,gint64 value,const char * format,...)5767 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5768 gint start, gint length, gint64 value,
5769 const char *format, ...)
5770 {
5771 proto_item *pi;
5772 va_list ap;
5773
5774 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
5775 if (pi != tree) {
5776 TRY_TO_FAKE_THIS_REPR(pi);
5777
5778 va_start(ap, format);
5779 proto_tree_set_representation(pi, format, ap);
5780 va_end(ap);
5781 }
5782
5783 return pi;
5784 }
5785
5786 /* Add a FT_EUI64 to a proto_tree */
5787 proto_item *
proto_tree_add_eui64(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint64 value)5788 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5789 gint length, const guint64 value)
5790 {
5791 proto_item *pi;
5792 header_field_info *hfinfo;
5793
5794 CHECK_FOR_NULL_TREE(tree);
5795
5796 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5797
5798 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
5799
5800 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5801 proto_tree_set_eui64(PNODE_FINFO(pi), value);
5802
5803 return pi;
5804 }
5805
5806 proto_item *
proto_tree_add_eui64_format_value(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint64 value,const char * format,...)5807 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5808 gint start, gint length, const guint64 value,
5809 const char *format, ...)
5810 {
5811 proto_item *pi;
5812 va_list ap;
5813
5814 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
5815 if (pi != tree) {
5816 va_start(ap, format);
5817 proto_tree_set_representation_value(pi, format, ap);
5818 va_end(ap);
5819 }
5820
5821 return pi;
5822 }
5823
5824 proto_item *
proto_tree_add_eui64_format(proto_tree * tree,int hfindex,tvbuff_t * tvb,gint start,gint length,const guint64 value,const char * format,...)5825 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5826 gint start, gint length, const guint64 value,
5827 const char *format, ...)
5828 {
5829 proto_item *pi;
5830 va_list ap;
5831
5832 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
5833 if (pi != tree) {
5834 TRY_TO_FAKE_THIS_REPR(pi);
5835
5836 va_start(ap, format);
5837 proto_tree_set_representation(pi, format, ap);
5838 va_end(ap);
5839 }
5840
5841 return pi;
5842 }
5843
5844 /* Set the FT_EUI64 value */
5845 static void
proto_tree_set_eui64(field_info * fi,const guint64 value)5846 proto_tree_set_eui64(field_info *fi, const guint64 value)
5847 {
5848 fvalue_set_uinteger64(&fi->value, value);
5849 }
5850 static void
proto_tree_set_eui64_tvb(field_info * fi,tvbuff_t * tvb,gint start,const guint encoding)5851 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
5852 {
5853 if (encoding)
5854 {
5855 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
5856 } else {
5857 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
5858 }
5859 }
5860
5861 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
5862 static proto_item *
proto_tree_add_node(proto_tree * tree,field_info * fi)5863 proto_tree_add_node(proto_tree *tree, field_info *fi)
5864 {
5865 proto_node *pnode, *tnode, *sibling;
5866 field_info *tfi;
5867 guint depth = 1;
5868
5869 /*
5870 * Restrict our depth. proto_tree_traverse_pre_order and
5871 * proto_tree_traverse_post_order (and possibly others) are recursive
5872 * so we need to be mindful of our stack size.
5873 */
5874 if (tree->first_child == NULL) {
5875 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
5876 depth++;
5877 if (G_UNLIKELY(depth > prefs.gui_max_tree_depth)) {
5878 THROW_MESSAGE(DissectorError, wmem_strdup_printf(PNODE_POOL(tree),
5879 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
5880 prefs.gui_max_tree_depth,
5881 fi->hfinfo->name, fi->hfinfo->abbrev, G_STRFUNC, __LINE__));
5882 }
5883 }
5884 }
5885
5886 /*
5887 * Make sure "tree" is ready to have subtrees under it, by
5888 * checking whether it's been given an ett_ value.
5889 *
5890 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
5891 * node of the protocol tree. That node is not displayed,
5892 * so it doesn't need an ett_ value to remember whether it
5893 * was expanded.
5894 */
5895 tnode = tree;
5896 tfi = PNODE_FINFO(tnode);
5897 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
5898 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
5899 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__);
5900 /* XXX - is it safe to continue here? */
5901 }
5902
5903 pnode = wmem_new(PNODE_POOL(tree), proto_node);
5904 PROTO_NODE_INIT(pnode);
5905 pnode->parent = tnode;
5906 PNODE_FINFO(pnode) = fi;
5907 pnode->tree_data = PTREE_DATA(tree);
5908
5909 if (tnode->last_child != NULL) {
5910 sibling = tnode->last_child;
5911 DISSECTOR_ASSERT(sibling->next == NULL);
5912 sibling->next = pnode;
5913 } else
5914 tnode->first_child = pnode;
5915 tnode->last_child = pnode;
5916
5917 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
5918
5919 return (proto_item *)pnode;
5920 }
5921
5922
5923 /* Generic way to allocate field_info and add to proto_tree.
5924 * Sets *pfi to address of newly-allocated field_info struct */
5925 static proto_item *
proto_tree_add_pi(proto_tree * tree,header_field_info * hfinfo,tvbuff_t * tvb,gint start,gint * length)5926 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
5927 gint *length)
5928 {
5929 proto_item *pi;
5930 field_info *fi;
5931 gint item_length;
5932
5933 get_hfi_length(hfinfo, tvb, start, length, &item_length, ENC_NA);
5934 fi = new_field_info(tree, hfinfo, tvb, start, item_length);
5935 pi = proto_tree_add_node(tree, fi);
5936
5937 return pi;
5938 }
5939
5940
5941 static void
get_hfi_length(header_field_info * hfinfo,tvbuff_t * tvb,const gint start,gint * length,gint * item_length,const guint encoding)5942 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
5943 gint *item_length, const guint encoding)
5944 {
5945 gint length_remaining;
5946
5947 /*
5948 * We only allow a null tvbuff if the item has a zero length,
5949 * i.e. if there's no data backing it.
5950 */
5951 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
5952
5953 /*
5954 * XXX - in some protocols, there are 32-bit unsigned length
5955 * fields, so lengths in protocol tree and tvbuff routines
5956 * should really be unsigned. We should have, for those
5957 * field types for which "to the end of the tvbuff" makes sense,
5958 * additional routines that take no length argument and
5959 * add fields that run to the end of the tvbuff.
5960 */
5961 if (*length == -1) {
5962 /*
5963 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING,
5964 * FT_STRINGZPAD, and FT_STRINGZTRUNC fields, a length
5965 * of -1 means "set the length to what remains in the
5966 * tvbuff".
5967 *
5968 * The assumption is either that
5969 *
5970 * 1) the length of the item can only be determined
5971 * by dissection (typically true of items with
5972 * subitems, which are probably FT_NONE or
5973 * FT_PROTOCOL)
5974 *
5975 * or
5976 *
5977 * 2) if the tvbuff is "short" (either due to a short
5978 * snapshot length or due to lack of reassembly of
5979 * fragments/segments/whatever), we want to display
5980 * what's available in the field (probably FT_BYTES
5981 * or FT_STRING) and then throw an exception later
5982 *
5983 * or
5984 *
5985 * 3) the field is defined to be "what's left in the
5986 * packet"
5987 *
5988 * so we set the length to what remains in the tvbuff so
5989 * that, if we throw an exception while dissecting, it
5990 * has what is probably the right value.
5991 *
5992 * For FT_STRINGZ, it means "the string is null-terminated,
5993 * not null-padded; set the length to the actual length
5994 * of the string", and if the tvbuff if short, we just
5995 * throw an exception.
5996 *
5997 * For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG, it means "find the end of the string",
5998 * and if the tvbuff if short, we just throw an exception.
5999 *
6000 * It's not valid for any other type of field. For those
6001 * fields, we treat -1 the same way we treat other
6002 * negative values - we assume the length is a Really
6003 * Big Positive Number, and throw a ReportedBoundsError
6004 * exception, under the assumption that the Really Big
6005 * Length would run past the end of the packet.
6006 */
6007 if ((IS_FT_INT(hfinfo->type)) || (IS_FT_UINT(hfinfo->type))) {
6008 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
6009 /*
6010 * Leave the length as -1, so our caller knows
6011 * it was -1.
6012 */
6013 *item_length = *length;
6014 return;
6015 } else if (encoding & ENC_VARINT_QUIC) {
6016 switch (tvb_get_guint8(tvb, start) >> 6)
6017 {
6018 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
6019 *item_length = 1;
6020 break;
6021 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
6022 *item_length = 2;
6023 break;
6024 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
6025 *item_length = 4;
6026 break;
6027 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
6028 *item_length = 8;
6029 break;
6030 }
6031 }
6032 }
6033
6034 switch (hfinfo->type) {
6035
6036 case FT_PROTOCOL:
6037 case FT_NONE:
6038 case FT_BYTES:
6039 case FT_STRING:
6040 case FT_STRINGZPAD:
6041 case FT_STRINGZTRUNC:
6042 /*
6043 * We allow FT_PROTOCOLs to be zero-length -
6044 * for example, an ONC RPC NULL procedure has
6045 * neither arguments nor reply, so the
6046 * payload for that protocol is empty.
6047 *
6048 * We also allow the others to be zero-length -
6049 * because that's the way the code has been for a
6050 * long, long time.
6051 *
6052 * However, we want to ensure that the start
6053 * offset is not *past* the byte past the end
6054 * of the tvbuff: we throw an exception in that
6055 * case.
6056 */
6057 *length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
6058 DISSECTOR_ASSERT(*length >= 0);
6059 break;
6060
6061 case FT_STRINGZ:
6062 /*
6063 * Leave the length as -1, so our caller knows
6064 * it was -1.
6065 */
6066 break;
6067
6068 default:
6069 THROW(ReportedBoundsError);
6070 DISSECTOR_ASSERT_NOT_REACHED();
6071 }
6072 *item_length = *length;
6073 } else {
6074 *item_length = *length;
6075 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
6076 /*
6077 * These types are for interior nodes of the
6078 * tree, and don't have data associated with
6079 * them; if the length is negative (XXX - see
6080 * above) or goes past the end of the tvbuff,
6081 * cut it short at the end of the tvbuff.
6082 * That way, if this field is selected in
6083 * Wireshark, we don't highlight stuff past
6084 * the end of the data.
6085 */
6086 /* XXX - what to do, if we don't have a tvb? */
6087 if (tvb) {
6088 length_remaining = tvb_captured_length_remaining(tvb, start);
6089 if (*item_length < 0 ||
6090 (*item_length > 0 &&
6091 (length_remaining < *item_length)))
6092 *item_length = length_remaining;
6093 }
6094 }
6095 if (*item_length < 0) {
6096 THROW(ReportedBoundsError);
6097 }
6098 }
6099 }
6100
6101 static gint
get_full_length(header_field_info * hfinfo,tvbuff_t * tvb,const gint start,gint length,guint item_length,const gint encoding)6102 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
6103 gint length, guint item_length, const gint encoding)
6104 {
6105 guint32 n;
6106
6107 /*
6108 * We need to get the correct item length here.
6109 * That's normally done by proto_tree_new_item(),
6110 * but we won't be calling it.
6111 */
6112 switch (hfinfo->type) {
6113
6114 case FT_NONE:
6115 case FT_PROTOCOL:
6116 case FT_BYTES:
6117 /*
6118 * The length is the specified length.
6119 */
6120 break;
6121
6122 case FT_UINT_BYTES:
6123 n = get_uint_value(NULL, tvb, start, length, encoding);
6124 item_length += n;
6125 break;
6126
6127 /* XXX - make these just FT_UINT? */
6128 case FT_UINT8:
6129 case FT_UINT16:
6130 case FT_UINT24:
6131 case FT_UINT32:
6132 case FT_UINT40:
6133 case FT_UINT48:
6134 case FT_UINT56:
6135 case FT_UINT64:
6136 /* XXX - make these just FT_INT? */
6137 case FT_INT8:
6138 case FT_INT16:
6139 case FT_INT24:
6140 case FT_INT32:
6141 case FT_INT40:
6142 case FT_INT48:
6143 case FT_INT56:
6144 case FT_INT64:
6145 if (encoding & (ENC_VARIANT_MASK)) {
6146 if (length < -1) {
6147 report_type_length_mismatch(NULL, "a FT_[U]INT", length, TRUE);
6148 }
6149 if (length == -1) {
6150 guint64 dummy;
6151 /* This can throw an exception */
6152 /* XXX - do this without fetching the varint? */
6153 length = tvb_get_varint(tvb, start, FT_VARINT_MAX_LEN, &dummy, encoding);
6154 if (length == 0) {
6155 THROW(ReportedBoundsError);
6156 }
6157 }
6158 item_length = length;
6159 break;
6160 }
6161
6162 /*
6163 * The length is the specified length.
6164 */
6165 break;
6166
6167 case FT_BOOLEAN:
6168 case FT_CHAR:
6169 case FT_IPv4:
6170 case FT_IPXNET:
6171 case FT_IPv6:
6172 case FT_FCWWN:
6173 case FT_AX25:
6174 case FT_VINES:
6175 case FT_ETHER:
6176 case FT_EUI64:
6177 case FT_GUID:
6178 case FT_OID:
6179 case FT_REL_OID:
6180 case FT_SYSTEM_ID:
6181 case FT_FLOAT:
6182 case FT_DOUBLE:
6183 case FT_STRING:
6184 /*
6185 * The length is the specified length.
6186 */
6187 break;
6188
6189 case FT_STRINGZ:
6190 if (length < -1) {
6191 report_type_length_mismatch(NULL, "a string", length, TRUE);
6192 }
6193 if (length == -1) {
6194 /* This can throw an exception */
6195 /* XXX - do this without fetching the string? */
6196 wmem_free(NULL, tvb_get_stringz_enc(NULL, tvb, start, &length, encoding));
6197 }
6198 item_length = length;
6199 break;
6200
6201 case FT_UINT_STRING:
6202 n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
6203 item_length += n;
6204 break;
6205
6206 case FT_STRINGZPAD:
6207 case FT_STRINGZTRUNC:
6208 case FT_ABSOLUTE_TIME:
6209 case FT_RELATIVE_TIME:
6210 case FT_IEEE_11073_SFLOAT:
6211 case FT_IEEE_11073_FLOAT:
6212 /*
6213 * The length is the specified length.
6214 */
6215 break;
6216
6217 default:
6218 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in gset_full_length()",
6219 hfinfo->abbrev,
6220 hfinfo->type,
6221 ftype_name(hfinfo->type));
6222 break;
6223 }
6224 return item_length;
6225 }
6226
6227 static field_info *
new_field_info(proto_tree * tree,header_field_info * hfinfo,tvbuff_t * tvb,const gint start,const gint item_length)6228 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
6229 const gint start, const gint item_length)
6230 {
6231 field_info *fi;
6232
6233 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
6234
6235 fi->hfinfo = hfinfo;
6236 fi->start = start;
6237 fi->start += (tvb)?tvb_raw_offset(tvb):0;
6238 fi->length = item_length;
6239 fi->tree_type = -1;
6240 fi->flags = 0;
6241 if (!PTREE_DATA(tree)->visible)
6242 FI_SET_FLAG(fi, FI_HIDDEN);
6243 fvalue_init(&fi->value, fi->hfinfo->type);
6244 fi->rep = NULL;
6245
6246 /* add the data source tvbuff */
6247 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
6248
6249 fi->appendix_start = 0;
6250 fi->appendix_length = 0;
6251
6252 return fi;
6253 }
6254
6255 /* If the protocol tree is to be visible, set the representation of a
6256 proto_tree entry with the name of the field for the item and with
6257 the value formatted with the supplied printf-style format and
6258 argument list. */
6259 static void
proto_tree_set_representation_value(proto_item * pi,const char * format,va_list ap)6260 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
6261 {
6262 ws_assert(pi);
6263
6264 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
6265 * items string representation */
6266 if (PTREE_DATA(pi)->visible && !proto_item_is_hidden(pi)) {
6267 int ret = 0;
6268 field_info *fi = PITEM_FINFO(pi);
6269 header_field_info *hf;
6270
6271 DISSECTOR_ASSERT(fi);
6272
6273 hf = fi->hfinfo;
6274
6275 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6276 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
6277 guint64 val;
6278 char *p;
6279
6280 if (IS_FT_UINT32(hf->type))
6281 val = fvalue_get_uinteger(&fi->value);
6282 else
6283 val = fvalue_get_uinteger64(&fi->value);
6284
6285 val <<= hfinfo_bitshift(hf);
6286
6287 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
6288 ret = (int) (p - fi->rep->representation);
6289 }
6290
6291 /* put in the hf name */
6292 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
6293
6294 /* If possible, Put in the value of the string */
6295 if (ret < ITEM_LABEL_LENGTH) {
6296 ret += g_vsnprintf(fi->rep->representation + ret,
6297 ITEM_LABEL_LENGTH - ret, format, ap);
6298 }
6299 if (ret >= ITEM_LABEL_LENGTH) {
6300 /* Uh oh, we don't have enough room. Tell the user
6301 * that the field is truncated.
6302 */
6303 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
6304 }
6305 }
6306 }
6307
6308 /* If the protocol tree is to be visible, set the representation of a
6309 proto_tree entry with the representation formatted with the supplied
6310 printf-style format and argument list. */
6311 static void
proto_tree_set_representation(proto_item * pi,const char * format,va_list ap)6312 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
6313 {
6314 int ret; /*tmp return value */
6315 field_info *fi = PITEM_FINFO(pi);
6316
6317 DISSECTOR_ASSERT(fi);
6318
6319 if (!proto_item_is_hidden(pi)) {
6320 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6321 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
6322 format, ap);
6323 if (ret >= ITEM_LABEL_LENGTH) {
6324 /* Uh oh, we don't have enough room. Tell the user
6325 * that the field is truncated.
6326 */
6327 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
6328 }
6329 }
6330 }
6331
6332 static int
protoo_strlcpy(gchar * dest,const gchar * src,gsize dest_size)6333 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
6334 {
6335 gsize res = g_strlcpy(dest, src, dest_size);
6336
6337 if (res > dest_size)
6338 res = dest_size;
6339 return (int) res;
6340 }
6341
6342 static header_field_info *
hfinfo_same_name_get_prev(const header_field_info * hfinfo)6343 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
6344 {
6345 header_field_info *dup_hfinfo;
6346
6347 if (hfinfo->same_name_prev_id == -1)
6348 return NULL;
6349 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
6350 return dup_hfinfo;
6351 }
6352
6353 static void
hfinfo_remove_from_gpa_name_map(const header_field_info * hfinfo)6354 hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
6355 {
6356 g_free(last_field_name);
6357 last_field_name = NULL;
6358
6359 if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
6360 /* No hfinfo with the same name */
6361 g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
6362 return;
6363 }
6364
6365 if (hfinfo->same_name_next) {
6366 hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
6367 }
6368
6369 if (hfinfo->same_name_prev_id != -1) {
6370 header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
6371 same_name_prev->same_name_next = hfinfo->same_name_next;
6372 if (!hfinfo->same_name_next) {
6373 /* It's always the latest added hfinfo which is stored in gpa_name_map */
6374 g_hash_table_insert(gpa_name_map, (gpointer) (same_name_prev->abbrev), same_name_prev);
6375 }
6376 }
6377 }
6378
6379 int
proto_item_fill_display_label(field_info * finfo,gchar * display_label_str,const int label_str_size)6380 proto_item_fill_display_label(field_info *finfo, gchar *display_label_str, const int label_str_size)
6381 {
6382 header_field_info *hfinfo = finfo->hfinfo;
6383 int label_len = 0;
6384 char *tmp_str;
6385 guint8 *bytes;
6386 guint32 number;
6387 guint64 number64;
6388 const true_false_string *tfstring;
6389 const char *hf_str_val;
6390 char number_buf[48];
6391 const char *number_out;
6392 address addr;
6393 ws_in4_addr ipv4;
6394 ws_in6_addr *ipv6;
6395
6396 switch (hfinfo->type) {
6397
6398 case FT_NONE:
6399 case FT_PROTOCOL:
6400 return protoo_strlcpy(display_label_str, UTF8_CHECK_MARK, label_str_size);
6401
6402 case FT_UINT_BYTES:
6403 case FT_BYTES:
6404 tmp_str = hfinfo_format_bytes(NULL,
6405 hfinfo,
6406 (guint8 *)fvalue_get(&finfo->value),
6407 fvalue_length(&finfo->value));
6408 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6409 wmem_free(NULL, tmp_str);
6410 break;
6411
6412 case FT_ABSOLUTE_TIME:
6413 tmp_str = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&finfo->value), (absolute_time_display_e)hfinfo->display, TRUE);
6414 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6415 wmem_free(NULL, tmp_str);
6416 break;
6417
6418 case FT_RELATIVE_TIME:
6419 tmp_str = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&finfo->value));
6420 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6421 wmem_free(NULL, tmp_str);
6422 break;
6423
6424 case FT_BOOLEAN:
6425 number64 = fvalue_get_uinteger64(&finfo->value);
6426 tfstring = &tfs_true_false;
6427 if (hfinfo->strings) {
6428 tfstring = (const struct true_false_string*) hfinfo->strings;
6429 }
6430 label_len = protoo_strlcpy(display_label_str,
6431 tfs_get_string(!!number64, tfstring), label_str_size);
6432 break;
6433
6434 case FT_CHAR:
6435 number = fvalue_get_uinteger(&finfo->value);
6436
6437 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
6438 gchar tmp[ITEM_LABEL_LENGTH];
6439 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
6440
6441 DISSECTOR_ASSERT(fmtfunc);
6442 fmtfunc(tmp, number);
6443
6444 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
6445
6446 } else if (hfinfo->strings) {
6447 number_out = hf_try_val_to_str(number, hfinfo);
6448
6449 if (!number_out) {
6450 number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
6451 }
6452
6453 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6454
6455 } else {
6456 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
6457
6458 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6459 }
6460
6461 break;
6462
6463 /* XXX - make these just FT_NUMBER? */
6464 case FT_INT8:
6465 case FT_INT16:
6466 case FT_INT24:
6467 case FT_INT32:
6468 case FT_UINT8:
6469 case FT_UINT16:
6470 case FT_UINT24:
6471 case FT_UINT32:
6472 case FT_FRAMENUM:
6473 hf_str_val = NULL;
6474 number = IS_FT_INT(hfinfo->type) ?
6475 (guint32) fvalue_get_sinteger(&finfo->value) :
6476 fvalue_get_uinteger(&finfo->value);
6477
6478 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
6479 gchar tmp[ITEM_LABEL_LENGTH];
6480 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
6481
6482 DISSECTOR_ASSERT(fmtfunc);
6483 fmtfunc(tmp, number);
6484
6485 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
6486
6487 } else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
6488 if (hfinfo->display & BASE_UNIT_STRING) {
6489 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
6490 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6491 hf_str_val = hf_try_val_to_str(number, hfinfo);
6492 label_len += protoo_strlcpy(display_label_str+label_len, hf_str_val, label_str_size-label_len);
6493 } else {
6494 number_out = hf_try_val_to_str(number, hfinfo);
6495
6496 if (!number_out) {
6497 number_out = hfinfo_number_value_format_display(hfinfo, hfinfo->display, number_buf, number);
6498 }
6499
6500 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6501 }
6502 } else {
6503 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
6504
6505 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6506 }
6507
6508 break;
6509
6510 case FT_INT40:
6511 case FT_INT48:
6512 case FT_INT56:
6513 case FT_INT64:
6514 case FT_UINT40:
6515 case FT_UINT48:
6516 case FT_UINT56:
6517 case FT_UINT64:
6518 hf_str_val = NULL;
6519 number64 = IS_FT_INT(hfinfo->type) ?
6520 (guint64) fvalue_get_sinteger64(&finfo->value) :
6521 fvalue_get_uinteger64(&finfo->value);
6522
6523 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
6524 gchar tmp[ITEM_LABEL_LENGTH];
6525 custom_fmt_func_64_t fmtfunc64 = (custom_fmt_func_64_t)hfinfo->strings;
6526
6527 DISSECTOR_ASSERT(fmtfunc64);
6528 fmtfunc64(tmp, number64);
6529
6530 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
6531 } else if (hfinfo->strings) {
6532 if (hfinfo->display & BASE_UNIT_STRING) {
6533 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
6534 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6535 hf_str_val = hf_try_val64_to_str(number64, hfinfo);
6536 label_len += protoo_strlcpy(display_label_str+label_len, hf_str_val, label_str_size-label_len);
6537 } else {
6538 number_out = hf_try_val64_to_str(number64, hfinfo);
6539
6540 if (!number_out)
6541 number_out = hfinfo_number_value_format_display64(hfinfo, hfinfo->display, number_buf, number64);
6542
6543 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6544 }
6545 } else {
6546 number_out = hfinfo_number_value_format64(hfinfo, number_buf, number64);
6547
6548 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
6549 }
6550
6551 break;
6552
6553 case FT_EUI64:
6554 tmp_str = eui64_to_str(NULL, fvalue_get_uinteger64(&finfo->value));
6555 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6556 wmem_free(NULL, tmp_str);
6557 break;
6558
6559 case FT_IPv4:
6560 ipv4 = fvalue_get_uinteger(&finfo->value);
6561 set_address (&addr, AT_IPv4, 4, &ipv4);
6562 address_to_str_buf(&addr, display_label_str, label_str_size);
6563 label_len = (int)strlen(display_label_str);
6564 break;
6565
6566 case FT_IPv6:
6567 ipv6 = (ws_in6_addr *)fvalue_get(&finfo->value);
6568 set_address (&addr, AT_IPv6, sizeof(ws_in6_addr), ipv6);
6569 address_to_str_buf(&addr, display_label_str, label_str_size);
6570 label_len = (int)strlen(display_label_str);
6571 break;
6572
6573 case FT_FCWWN:
6574 set_address (&addr, AT_FCWWN, FCWWN_ADDR_LEN, fvalue_get(&finfo->value));
6575 address_to_str_buf(&addr, display_label_str, label_str_size);
6576 label_len = (int)strlen(display_label_str);
6577 break;
6578
6579 case FT_ETHER:
6580 set_address (&addr, AT_ETHER, FT_ETHER_LEN, fvalue_get(&finfo->value));
6581 address_to_str_buf(&addr, display_label_str, label_str_size);
6582 label_len = (int)strlen(display_label_str);
6583 break;
6584
6585 case FT_GUID:
6586 tmp_str = guid_to_str(NULL, (e_guid_t *)fvalue_get(&finfo->value));
6587 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6588 wmem_free(NULL, tmp_str);
6589 break;
6590
6591 case FT_REL_OID:
6592 bytes = (guint8 *)fvalue_get(&finfo->value);
6593 tmp_str = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
6594 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6595 wmem_free(NULL, tmp_str);
6596 break;
6597
6598 case FT_OID:
6599 bytes = (guint8 *)fvalue_get(&finfo->value);
6600 tmp_str = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
6601 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6602 wmem_free(NULL, tmp_str);
6603 break;
6604
6605 case FT_SYSTEM_ID:
6606 bytes = (guint8 *)fvalue_get(&finfo->value);
6607 tmp_str = print_system_id(NULL, bytes, fvalue_length(&finfo->value));
6608 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6609 wmem_free(NULL, tmp_str);
6610 break;
6611
6612 case FT_FLOAT:
6613 if (hfinfo->display & BASE_UNIT_STRING) {
6614 double d_value = fvalue_get_floating(&finfo->value);
6615 g_snprintf(display_label_str, label_str_size,
6616 "%." G_STRINGIFY(FLT_DIG) "g%s", d_value,
6617 unit_name_string_get_double(d_value, (const unit_name_string*)hfinfo->strings));
6618 } else {
6619 g_snprintf(display_label_str, label_str_size,
6620 "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
6621 }
6622 label_len = (int)strlen(display_label_str);
6623 break;
6624
6625 case FT_DOUBLE:
6626 if (hfinfo->display & BASE_UNIT_STRING) {
6627 double d_value = fvalue_get_floating(&finfo->value);
6628 g_snprintf(display_label_str, label_str_size,
6629 "%." G_STRINGIFY(DBL_DIG) "g%s", d_value,
6630 unit_name_string_get_double(d_value, (const unit_name_string*)hfinfo->strings));
6631 } else {
6632 g_snprintf(display_label_str, label_str_size,
6633 "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
6634 }
6635 label_len = (int)strlen(display_label_str);
6636 break;
6637
6638 case FT_STRING:
6639 case FT_STRINGZ:
6640 case FT_UINT_STRING:
6641 case FT_STRINGZPAD:
6642 case FT_STRINGZTRUNC:
6643 bytes = (guint8 *)fvalue_get(&finfo->value);
6644 tmp_str = hfinfo_format_text(NULL, hfinfo, bytes);
6645 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6646 wmem_free(NULL, tmp_str);
6647 break;
6648
6649 default:
6650 /* First try ftype string representation */
6651 tmp_str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
6652 if (!tmp_str) {
6653 /* Default to show as bytes */
6654 bytes = (guint8 *)fvalue_get(&finfo->value);
6655 tmp_str = bytes_to_str(NULL, bytes, fvalue_length(&finfo->value));
6656 }
6657 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
6658 wmem_free(NULL, tmp_str);
6659 break;
6660 }
6661 return label_len;
6662 }
6663
6664 /* -------------------------- */
6665 const gchar *
proto_custom_set(proto_tree * tree,GSList * field_ids,gint occurrence,gchar * result,gchar * expr,const int size)6666 proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
6667 gchar *result, gchar *expr, const int size)
6668 {
6669 guint32 number;
6670 guint64 number64;
6671 guint8 *bytes;
6672
6673 int len, prev_len, last, i, offset_r = 0, offset_e = 0, label_len;
6674 GPtrArray *finfos;
6675 field_info *finfo = NULL;
6676 header_field_info* hfinfo;
6677 const gchar *abbrev = NULL;
6678
6679 const char *hf_str_val;
6680 char number_buf[48];
6681 const char *number_out;
6682 char *str;
6683 int *field_idx;
6684 int field_id;
6685 int ii = 0;
6686
6687 ws_assert(field_ids != NULL);
6688 while ((field_idx = (int *) g_slist_nth_data(field_ids, ii++))) {
6689 field_id = *field_idx;
6690 PROTO_REGISTRAR_GET_NTH((guint)field_id, hfinfo);
6691
6692 /* do we need to rewind ? */
6693 if (!hfinfo)
6694 return "";
6695
6696 if (occurrence < 0) {
6697 /* Search other direction */
6698 while (hfinfo->same_name_prev_id != -1) {
6699 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
6700 }
6701 }
6702
6703 prev_len = 0; /* Reset handled occurrences */
6704
6705 while (hfinfo) {
6706 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
6707
6708 if (!finfos || !(len = g_ptr_array_len(finfos))) {
6709 if (occurrence < 0) {
6710 hfinfo = hfinfo->same_name_next;
6711 } else {
6712 hfinfo = hfinfo_same_name_get_prev(hfinfo);
6713 }
6714 continue;
6715 }
6716
6717 /* Are there enough occurrences of the field? */
6718 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
6719 if (occurrence < 0) {
6720 hfinfo = hfinfo->same_name_next;
6721 } else {
6722 hfinfo = hfinfo_same_name_get_prev(hfinfo);
6723 }
6724 prev_len += len;
6725 continue;
6726 }
6727
6728 /* Calculate single index or set outer bounderies */
6729 if (occurrence < 0) {
6730 i = occurrence + len + prev_len;
6731 last = i;
6732 } else if (occurrence > 0) {
6733 i = occurrence - 1 - prev_len;
6734 last = i;
6735 } else {
6736 i = 0;
6737 last = len - 1;
6738 }
6739
6740 prev_len += len; /* Count handled occurrences */
6741
6742 while (i <= last) {
6743 finfo = (field_info *)g_ptr_array_index(finfos, i);
6744
6745 if (offset_r && (offset_r < (size - 2)))
6746 result[offset_r++] = ',';
6747
6748 if (offset_e && (offset_e < (size - 2)))
6749 expr[offset_e++] = ',';
6750
6751 switch (hfinfo->type) {
6752
6753 case FT_NONE:
6754 case FT_PROTOCOL:
6755 /* Prevent multiple check marks */
6756 if (strstr(result, UTF8_CHECK_MARK ",") == NULL) {
6757 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6758 } else {
6759 result[--offset_r] = '\0'; /* Remove the added trailing ',' again */
6760 }
6761 break;
6762
6763 case FT_BOOLEAN:
6764 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6765
6766 number64 = fvalue_get_uinteger64(&finfo->value);
6767 offset_e += protoo_strlcpy(expr+offset_e,
6768 number64 ? "1" : "0", size-offset_e);
6769 break;
6770
6771 case FT_CHAR:
6772 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6773
6774 number = fvalue_get_uinteger(&finfo->value);
6775
6776 if (hfinfo->strings && FIELD_DISPLAY(hfinfo->display) == BASE_NONE) {
6777 hf_str_val = hf_try_val_to_str(number, hfinfo);
6778 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
6779 } else {
6780 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
6781
6782 (void) g_strlcpy(expr+offset_e, number_out, size-offset_e);
6783 }
6784
6785 offset_e = (int)strlen(expr);
6786 break;
6787
6788 /* XXX - make these just FT_NUMBER? */
6789 case FT_INT8:
6790 case FT_INT16:
6791 case FT_INT24:
6792 case FT_INT32:
6793 case FT_UINT8:
6794 case FT_UINT16:
6795 case FT_UINT24:
6796 case FT_UINT32:
6797 case FT_FRAMENUM:
6798 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6799
6800 hf_str_val = NULL;
6801 number = IS_FT_INT(hfinfo->type) ?
6802 (guint32) fvalue_get_sinteger(&finfo->value) :
6803 fvalue_get_uinteger(&finfo->value);
6804
6805 if (hfinfo->strings && hfinfo->type != FT_FRAMENUM && FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM) {
6806 hf_str_val = hf_try_val_to_str(number, hfinfo);
6807 }
6808
6809 if (hf_str_val && FIELD_DISPLAY(hfinfo->display) == BASE_NONE) {
6810
6811 hf_str_val = hf_try_val_to_str(number, hfinfo);
6812 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
6813 } else {
6814 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
6815
6816 (void) g_strlcpy(expr+offset_e, number_out, size-offset_e);
6817 }
6818
6819 offset_e = (int)strlen(expr);
6820 break;
6821
6822 case FT_INT40:
6823 case FT_INT48:
6824 case FT_INT56:
6825 case FT_INT64:
6826 case FT_UINT40:
6827 case FT_UINT48:
6828 case FT_UINT56:
6829 case FT_UINT64:
6830 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6831
6832 hf_str_val = NULL;
6833 number64 = IS_FT_INT(hfinfo->type) ?
6834 (guint64) fvalue_get_sinteger64(&finfo->value) :
6835 fvalue_get_uinteger64(&finfo->value);
6836
6837 if (hfinfo->strings && hfinfo->type != FT_FRAMENUM && FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM) {
6838 hf_str_val = hf_try_val64_to_str(number64, hfinfo);
6839 }
6840
6841 if (hf_str_val && FIELD_DISPLAY(hfinfo->display) == BASE_NONE) {
6842 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
6843 } else {
6844 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
6845
6846 (void) g_strlcpy(expr+offset_e, number_out, size-offset_e);
6847 }
6848
6849 offset_e = (int)strlen(expr);
6850 break;
6851
6852 case FT_REL_OID:
6853 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6854
6855 bytes = (guint8 *)fvalue_get(&finfo->value);
6856 str = rel_oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
6857 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
6858 wmem_free(NULL, str);
6859 break;
6860
6861 case FT_OID:
6862 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6863
6864 bytes = (guint8 *)fvalue_get(&finfo->value);
6865 str = oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
6866 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
6867 wmem_free(NULL, str);
6868 break;
6869
6870 case FT_SYSTEM_ID:
6871 label_len = proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6872
6873 offset_e += protoo_strlcpy(expr+offset_e, result+offset_r, size-offset_e);
6874
6875 offset_r += label_len;
6876 break;
6877
6878 default:
6879 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
6880 break;
6881 }
6882 i++;
6883 }
6884
6885 switch (hfinfo->type) {
6886
6887 case FT_BOOLEAN:
6888 case FT_CHAR:
6889 case FT_UINT8:
6890 case FT_UINT16:
6891 case FT_UINT24:
6892 case FT_UINT32:
6893 case FT_UINT40:
6894 case FT_UINT48:
6895 case FT_UINT56:
6896 case FT_UINT64:
6897 case FT_FRAMENUM:
6898 case FT_INT8:
6899 case FT_INT16:
6900 case FT_INT24:
6901 case FT_INT32:
6902 case FT_INT40:
6903 case FT_INT48:
6904 case FT_INT56:
6905 case FT_INT64:
6906 case FT_OID:
6907 case FT_REL_OID:
6908 case FT_SYSTEM_ID:
6909 /* for these types, "expr" is filled in the loop above */
6910 break;
6911
6912 default:
6913 /* for all others, just copy "result" to "expr" */
6914 (void) g_strlcpy(expr, result, size);
6915 break;
6916 }
6917
6918 if (!abbrev) {
6919 /* Store abbrev for return value */
6920 abbrev = hfinfo->abbrev;
6921 }
6922
6923 if (occurrence == 0) {
6924 /* Fetch next hfinfo with same name (abbrev) */
6925 hfinfo = hfinfo_same_name_get_prev(hfinfo);
6926 } else {
6927 hfinfo = NULL;
6928 }
6929 }
6930 }
6931
6932 return abbrev ? abbrev : "";
6933 }
6934
6935
6936 /* Set text of proto_item after having already been created. */
6937 void
proto_item_set_text(proto_item * pi,const char * format,...)6938 proto_item_set_text(proto_item *pi, const char *format, ...)
6939 {
6940 field_info *fi = NULL;
6941 va_list ap;
6942
6943 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6944
6945 fi = PITEM_FINFO(pi);
6946 if (fi == NULL)
6947 return;
6948
6949 if (fi->rep) {
6950 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
6951 fi->rep = NULL;
6952 }
6953
6954 va_start(ap, format);
6955 proto_tree_set_representation(pi, format, ap);
6956 va_end(ap);
6957 }
6958
6959 /* Append to text of proto_item after having already been created. */
6960 void
proto_item_append_text(proto_item * pi,const char * format,...)6961 proto_item_append_text(proto_item *pi, const char *format, ...)
6962 {
6963 field_info *fi = NULL;
6964 size_t curlen;
6965 va_list ap;
6966
6967 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6968
6969 fi = PITEM_FINFO(pi);
6970 if (fi == NULL) {
6971 return;
6972 }
6973
6974 if (!proto_item_is_hidden(pi)) {
6975 /*
6976 * If we don't already have a representation,
6977 * generate the default representation.
6978 */
6979 if (fi->rep == NULL) {
6980 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6981 proto_item_fill_label(fi, fi->rep->representation);
6982 }
6983
6984 curlen = strlen(fi->rep->representation);
6985 if (ITEM_LABEL_LENGTH > curlen) {
6986 va_start(ap, format);
6987 g_vsnprintf(fi->rep->representation + curlen,
6988 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
6989 va_end(ap);
6990 }
6991 }
6992 }
6993
6994 /* Prepend to text of proto_item after having already been created. */
6995 void
proto_item_prepend_text(proto_item * pi,const char * format,...)6996 proto_item_prepend_text(proto_item *pi, const char *format, ...)
6997 {
6998 field_info *fi = NULL;
6999 char representation[ITEM_LABEL_LENGTH];
7000 va_list ap;
7001
7002 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7003
7004 fi = PITEM_FINFO(pi);
7005 if (fi == NULL) {
7006 return;
7007 }
7008
7009 if (!proto_item_is_hidden(pi)) {
7010 /*
7011 * If we don't already have a representation,
7012 * generate the default representation.
7013 */
7014 if (fi->rep == NULL) {
7015 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
7016 proto_item_fill_label(fi, representation);
7017 } else
7018 (void) g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
7019
7020 va_start(ap, format);
7021 g_vsnprintf(fi->rep->representation,
7022 ITEM_LABEL_LENGTH, format, ap);
7023 va_end(ap);
7024 (void) g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
7025 }
7026 }
7027
7028 static void
finfo_set_len(field_info * fi,const gint length)7029 finfo_set_len(field_info *fi, const gint length)
7030 {
7031 gint length_remaining;
7032
7033 DISSECTOR_ASSERT_HINT(length >= 0, fi->hfinfo->abbrev);
7034 length_remaining = tvb_captured_length_remaining(fi->ds_tvb, fi->start);
7035 if (length > length_remaining)
7036 fi->length = length_remaining;
7037 else
7038 fi->length = length;
7039
7040 /*
7041 * You cannot just make the "len" field of a GByteArray
7042 * larger, if there's no data to back that length;
7043 * you can only make it smaller.
7044 */
7045 if (fi->value.ftype->ftype == FT_BYTES && fi->length <= (gint)fi->value.value.bytes->len)
7046 fi->value.value.bytes->len = fi->length;
7047 }
7048
7049 void
proto_item_set_len(proto_item * pi,const gint length)7050 proto_item_set_len(proto_item *pi, const gint length)
7051 {
7052 field_info *fi;
7053
7054 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7055
7056 fi = PITEM_FINFO(pi);
7057 if (fi == NULL)
7058 return;
7059
7060 finfo_set_len(fi, length);
7061 }
7062
7063 /*
7064 * Sets the length of the item based on its start and on the specified
7065 * offset, which is the offset past the end of the item; as the start
7066 * in the item is relative to the beginning of the data source tvbuff,
7067 * we need to pass in a tvbuff - the end offset is relative to the beginning
7068 * of that tvbuff.
7069 */
7070 void
proto_item_set_end(proto_item * pi,tvbuff_t * tvb,gint end)7071 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
7072 {
7073 field_info *fi;
7074 gint length;
7075
7076 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7077
7078 fi = PITEM_FINFO(pi);
7079 if (fi == NULL)
7080 return;
7081
7082 end += tvb_raw_offset(tvb);
7083 DISSECTOR_ASSERT(end >= fi->start);
7084 length = end - fi->start;
7085
7086 finfo_set_len(fi, length);
7087 }
7088
7089 int
proto_item_get_len(const proto_item * pi)7090 proto_item_get_len(const proto_item *pi)
7091 {
7092 field_info *fi;
7093
7094 if (!pi)
7095 return -1;
7096 fi = PITEM_FINFO(pi);
7097 return fi ? fi->length : -1;
7098 }
7099
7100 void
proto_item_set_bits_offset_len(proto_item * ti,int bits_offset,int bits_len)7101 proto_item_set_bits_offset_len(proto_item *ti, int bits_offset, int bits_len) {
7102 if (!ti) {
7103 return;
7104 }
7105 FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_OFFSET(bits_offset));
7106 FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_SIZE(bits_len));
7107 }
7108
7109 char *
proto_item_get_display_repr(wmem_allocator_t * scope,proto_item * pi)7110 proto_item_get_display_repr(wmem_allocator_t *scope, proto_item *pi)
7111 {
7112 field_info *fi;
7113
7114 if (!pi)
7115 return "";
7116 fi = PITEM_FINFO(pi);
7117 DISSECTOR_ASSERT(fi->hfinfo != NULL);
7118 return fvalue_to_string_repr(scope, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
7119 }
7120
7121 proto_tree *
proto_tree_create_root(packet_info * pinfo)7122 proto_tree_create_root(packet_info *pinfo)
7123 {
7124 proto_node *pnode;
7125
7126 /* Initialize the proto_node */
7127 pnode = g_slice_new(proto_tree);
7128 PROTO_NODE_INIT(pnode);
7129 pnode->parent = NULL;
7130 PNODE_FINFO(pnode) = NULL;
7131 pnode->tree_data = g_slice_new(tree_data_t);
7132
7133 /* Make sure we can access pinfo everywhere */
7134 pnode->tree_data->pinfo = pinfo;
7135
7136 /* Don't initialize the tree_data_t. Wait until we know we need it */
7137 pnode->tree_data->interesting_hfids = NULL;
7138
7139 /* Set the default to FALSE so it's easier to
7140 * find errors; if we expect to see the protocol tree
7141 * but for some reason the default 'visible' is not
7142 * changed, then we'll find out very quickly. */
7143 pnode->tree_data->visible = FALSE;
7144
7145 /* Make sure that we fake protocols (if possible) */
7146 pnode->tree_data->fake_protocols = TRUE;
7147
7148 /* Keep track of the number of children */
7149 pnode->tree_data->count = 0;
7150
7151 return (proto_tree *)pnode;
7152 }
7153
7154
7155 /* "prime" a proto_tree with a single hfid that a dfilter
7156 * is interested in. */
7157 void
proto_tree_prime_with_hfid(proto_tree * tree _U_,const gint hfid)7158 proto_tree_prime_with_hfid(proto_tree *tree _U_, const gint hfid)
7159 {
7160 header_field_info *hfinfo;
7161
7162 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
7163 /* this field is referenced by a filter so increase the refcount.
7164 also increase the refcount for the parent, i.e the protocol.
7165 */
7166 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
7167 /* only increase the refcount if there is a parent.
7168 if this is a protocol and not a field then parent will be -1
7169 and there is no parent to add any refcounting for.
7170 */
7171 if (hfinfo->parent != -1) {
7172 header_field_info *parent_hfinfo;
7173 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
7174
7175 /* Mark parent as indirectly referenced unless it is already directly
7176 * referenced, i.e. the user has specified the parent in a filter.
7177 */
7178 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
7179 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
7180 }
7181 }
7182
7183 proto_tree *
proto_item_add_subtree(proto_item * pi,const gint idx)7184 proto_item_add_subtree(proto_item *pi, const gint idx) {
7185 field_info *fi;
7186
7187 if (!pi)
7188 return NULL;
7189
7190 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
7191
7192 fi = PITEM_FINFO(pi);
7193 if (!fi)
7194 return (proto_tree *)pi;
7195
7196 fi->tree_type = idx;
7197
7198 return (proto_tree *)pi;
7199 }
7200
7201 proto_tree *
proto_item_get_subtree(proto_item * pi)7202 proto_item_get_subtree(proto_item *pi) {
7203 field_info *fi;
7204
7205 if (!pi)
7206 return NULL;
7207 fi = PITEM_FINFO(pi);
7208 if ( (!fi) || (fi->tree_type == -1) )
7209 return NULL;
7210 return (proto_tree *)pi;
7211 }
7212
7213 proto_item *
proto_item_get_parent(const proto_item * ti)7214 proto_item_get_parent(const proto_item *ti) {
7215 if (!ti)
7216 return NULL;
7217 return ti->parent;
7218 }
7219
7220 proto_item *
proto_item_get_parent_nth(proto_item * ti,int gen)7221 proto_item_get_parent_nth(proto_item *ti, int gen) {
7222 if (!ti)
7223 return NULL;
7224 while (gen--) {
7225 ti = ti->parent;
7226 if (!ti)
7227 return NULL;
7228 }
7229 return ti;
7230 }
7231
7232
7233 proto_item *
proto_tree_get_parent(proto_tree * tree)7234 proto_tree_get_parent(proto_tree *tree) {
7235 if (!tree)
7236 return NULL;
7237 return (proto_item *)tree;
7238 }
7239
7240 proto_tree *
proto_tree_get_parent_tree(proto_tree * tree)7241 proto_tree_get_parent_tree(proto_tree *tree) {
7242 if (!tree)
7243 return NULL;
7244
7245 /* we're the root tree, there's no parent
7246 return ourselves so the caller has at least a tree to attach to */
7247 if (!tree->parent)
7248 return tree;
7249
7250 return (proto_tree *)tree->parent;
7251 }
7252
7253 proto_tree *
proto_tree_get_root(proto_tree * tree)7254 proto_tree_get_root(proto_tree *tree) {
7255 if (!tree)
7256 return NULL;
7257 while (tree->parent) {
7258 tree = tree->parent;
7259 }
7260 return tree;
7261 }
7262
7263 void
proto_tree_move_item(proto_tree * tree,proto_item * fixed_item,proto_item * item_to_move)7264 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
7265 proto_item *item_to_move)
7266 {
7267 /* This function doesn't generate any values. It only reorganizes the prococol tree
7268 * so we can bail out immediately if it isn't visible. */
7269 if (!tree || !PTREE_DATA(tree)->visible)
7270 return;
7271
7272 DISSECTOR_ASSERT(item_to_move->parent == tree);
7273 DISSECTOR_ASSERT(fixed_item->parent == tree);
7274
7275 /*** cut item_to_move out ***/
7276
7277 /* is item_to_move the first? */
7278 if (tree->first_child == item_to_move) {
7279 /* simply change first child to next */
7280 tree->first_child = item_to_move->next;
7281
7282 DISSECTOR_ASSERT(tree->last_child != item_to_move);
7283 } else {
7284 proto_item *curr_item;
7285 /* find previous and change it's next */
7286 for (curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
7287 if (curr_item->next == item_to_move) {
7288 break;
7289 }
7290 }
7291
7292 DISSECTOR_ASSERT(curr_item);
7293
7294 curr_item->next = item_to_move->next;
7295
7296 /* fix last_child if required */
7297 if (tree->last_child == item_to_move) {
7298 tree->last_child = curr_item;
7299 }
7300 }
7301
7302 /*** insert to_move after fixed ***/
7303 item_to_move->next = fixed_item->next;
7304 fixed_item->next = item_to_move;
7305 if (tree->last_child == fixed_item) {
7306 tree->last_child = item_to_move;
7307 }
7308 }
7309
7310 void
proto_tree_set_appendix(proto_tree * tree,tvbuff_t * tvb,gint start,const gint length)7311 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
7312 const gint length)
7313 {
7314 field_info *fi;
7315
7316 if (tree == NULL)
7317 return;
7318
7319 fi = PTREE_FINFO(tree);
7320 if (fi == NULL)
7321 return;
7322
7323 start += tvb_raw_offset(tvb);
7324 DISSECTOR_ASSERT(start >= 0);
7325 DISSECTOR_ASSERT(length >= 0);
7326
7327 fi->appendix_start = start;
7328 fi->appendix_length = length;
7329 }
7330
7331 static void
check_valid_filter_name_or_fail(const char * filter_name)7332 check_valid_filter_name_or_fail(const char *filter_name)
7333 {
7334 gboolean found_invalid = proto_check_field_name(filter_name);
7335
7336 /* Additionally forbid upper case characters. */
7337 if (!found_invalid) {
7338 for (guint i = 0; filter_name[i]; i++) {
7339 if (g_ascii_isupper(filter_name[i])) {
7340 found_invalid = TRUE;
7341 break;
7342 }
7343 }
7344 }
7345
7346 if (found_invalid) {
7347 ws_error("Protocol filter name \"%s\" has one or more invalid characters."
7348 " Allowed are lower characters, digits, '-', '_' and non-repeating '.'."
7349 " This might be caused by an inappropriate plugin or a development error.", filter_name);
7350 }
7351
7352 const char *reserved_filter_names[] = {
7353 /* Display filter keywords. */
7354 "eq",
7355 "ne",
7356 "gt",
7357 "ge",
7358 "lt",
7359 "le",
7360 "bitwise_and",
7361 "contains",
7362 "matches",
7363 "not",
7364 "and",
7365 "or",
7366 "in",
7367 NULL
7368 };
7369
7370 /* Check for reserved keywords. */
7371 for (const char **ptr = reserved_filter_names; *ptr != NULL; ptr++) {
7372 if (strcmp(*ptr, filter_name) == 0) {
7373 ws_error("Protocol filter name \"%s\" is a reserved keyword.", filter_name);
7374 }
7375 }
7376 }
7377
7378 int
proto_register_protocol(const char * name,const char * short_name,const char * filter_name)7379 proto_register_protocol(const char *name, const char *short_name,
7380 const char *filter_name)
7381 {
7382 protocol_t *protocol;
7383 header_field_info *hfinfo;
7384
7385 /*
7386 * Make sure there's not already a protocol with any of those
7387 * names. Crash if there is, as that's an error in the code
7388 * or an inappropriate plugin.
7389 * This situation has to be fixed to not register more than one
7390 * protocol with the same name.
7391 */
7392
7393 if (g_hash_table_lookup(proto_names, name)) {
7394 /* ws_error will terminate the program */
7395 ws_error("Duplicate protocol name \"%s\"!"
7396 " This might be caused by an inappropriate plugin or a development error.", name);
7397 }
7398
7399 if (g_hash_table_lookup(proto_short_names, short_name)) {
7400 ws_error("Duplicate protocol short_name \"%s\"!"
7401 " This might be caused by an inappropriate plugin or a development error.", short_name);
7402 }
7403
7404 check_valid_filter_name_or_fail(filter_name);
7405
7406 if (g_hash_table_lookup(proto_filter_names, filter_name)) {
7407 ws_error("Duplicate protocol filter_name \"%s\"!"
7408 " This might be caused by an inappropriate plugin or a development error.", filter_name);
7409 }
7410
7411 /*
7412 * Add this protocol to the list of known protocols;
7413 * the list is sorted by protocol short name.
7414 */
7415 protocol = g_new(protocol_t, 1);
7416 protocol->name = name;
7417 protocol->short_name = short_name;
7418 protocol->filter_name = filter_name;
7419 protocol->fields = NULL; /* Delegate until actually needed */
7420 protocol->is_enabled = TRUE; /* protocol is enabled by default */
7421 protocol->enabled_by_default = TRUE; /* see previous comment */
7422 protocol->can_toggle = TRUE;
7423 protocol->parent_proto_id = -1;
7424 protocol->heur_list = NULL;
7425
7426 /* List will be sorted later by name, when all protocols completed registering */
7427 protocols = g_list_prepend(protocols, protocol);
7428 g_hash_table_insert(proto_names, (gpointer)name, protocol);
7429 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
7430 g_hash_table_insert(proto_short_names, (gpointer)short_name, protocol);
7431
7432 /* Here we allocate a new header_field_info struct */
7433 hfinfo = g_slice_new(header_field_info);
7434 hfinfo->name = name;
7435 hfinfo->abbrev = filter_name;
7436 hfinfo->type = FT_PROTOCOL;
7437 hfinfo->display = BASE_NONE;
7438 hfinfo->strings = protocol;
7439 hfinfo->bitmask = 0;
7440 hfinfo->ref_type = HF_REF_TYPE_NONE;
7441 hfinfo->blurb = NULL;
7442 hfinfo->parent = -1; /* This field differentiates protos and fields */
7443
7444 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
7445 return protocol->proto_id;
7446 }
7447
7448 int
proto_register_protocol_in_name_only(const char * name,const char * short_name,const char * filter_name,int parent_proto,enum ftenum field_type)7449 proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type)
7450 {
7451 protocol_t *protocol;
7452 header_field_info *hfinfo;
7453
7454 /*
7455 * Helper protocols don't need the strict rules as a "regular" protocol
7456 * Just register it in a list and make a hf_ field from it
7457 */
7458 if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) {
7459 ws_error("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name);
7460 }
7461
7462 if (parent_proto < 0) {
7463 ws_error("Must have a valid parent protocol for helper protocol \"%s\"!"
7464 " This might be caused by an inappropriate plugin or a development error.", name);
7465 }
7466
7467 check_valid_filter_name_or_fail(filter_name);
7468
7469 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
7470 protocol = g_new(protocol_t, 1);
7471 protocol->name = name;
7472 protocol->short_name = short_name;
7473 protocol->filter_name = filter_name;
7474 protocol->fields = NULL; /* Delegate until actually needed */
7475
7476 /* Enabling and toggling is really determined by parent protocol,
7477 but provide default values here */
7478 protocol->is_enabled = TRUE;
7479 protocol->enabled_by_default = TRUE;
7480 protocol->can_toggle = TRUE;
7481
7482 protocol->parent_proto_id = parent_proto;
7483 protocol->heur_list = NULL;
7484
7485 /* List will be sorted later by name, when all protocols completed registering */
7486 protocols = g_list_prepend(protocols, protocol);
7487
7488 /* Here we allocate a new header_field_info struct */
7489 hfinfo = g_slice_new(header_field_info);
7490 hfinfo->name = name;
7491 hfinfo->abbrev = filter_name;
7492 hfinfo->type = field_type;
7493 hfinfo->display = BASE_NONE;
7494 if (field_type == FT_BYTES) {
7495 hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO);
7496 }
7497 hfinfo->strings = protocol;
7498 hfinfo->bitmask = 0;
7499 hfinfo->ref_type = HF_REF_TYPE_NONE;
7500 hfinfo->blurb = NULL;
7501 hfinfo->parent = -1; /* This field differentiates protos and fields */
7502
7503 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
7504 return protocol->proto_id;
7505 }
7506
7507 gboolean
proto_deregister_protocol(const char * short_name)7508 proto_deregister_protocol(const char *short_name)
7509 {
7510 protocol_t *protocol;
7511 header_field_info *hfinfo;
7512 int proto_id;
7513 guint i;
7514
7515 proto_id = proto_get_id_by_short_name(short_name);
7516 protocol = find_protocol_by_id(proto_id);
7517 if (protocol == NULL)
7518 return FALSE;
7519
7520 g_hash_table_remove(proto_names, protocol->name);
7521 g_hash_table_remove(proto_short_names, (gpointer)short_name);
7522 g_hash_table_remove(proto_filter_names, (gpointer)protocol->filter_name);
7523
7524 if (protocol->fields) {
7525 for (i = 0; i < protocol->fields->len; i++) {
7526 hfinfo = (header_field_info *)g_ptr_array_index(protocol->fields, i);
7527 hfinfo_remove_from_gpa_name_map(hfinfo);
7528 expert_deregister_expertinfo(hfinfo->abbrev);
7529 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hfinfo->id]);
7530 }
7531 g_ptr_array_free(protocol->fields, TRUE);
7532 protocol->fields = NULL;
7533 }
7534
7535 g_list_free(protocol->heur_list);
7536
7537 /* Remove this protocol from the list of known protocols */
7538 protocols = g_list_remove(protocols, protocol);
7539
7540 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[proto_id]);
7541 g_hash_table_steal(gpa_name_map, protocol->filter_name);
7542
7543 g_free(last_field_name);
7544 last_field_name = NULL;
7545
7546 return TRUE;
7547 }
7548
7549 void
proto_register_alias(const int proto_id,const char * alias_name)7550 proto_register_alias(const int proto_id, const char *alias_name)
7551 {
7552 protocol_t *protocol;
7553
7554 protocol = find_protocol_by_id(proto_id);
7555 if (alias_name && protocol) {
7556 g_hash_table_insert(gpa_protocol_aliases, (gpointer) alias_name, (gpointer)protocol->filter_name);
7557 }
7558 }
7559
7560 /*
7561 * Routines to use to iterate over the protocols.
7562 * The argument passed to the iterator routines is an opaque cookie to
7563 * their callers; it's the GList pointer for the current element in
7564 * the list.
7565 * The ID of the protocol is returned, or -1 if there is no protocol.
7566 */
7567 int
proto_get_first_protocol(void ** cookie)7568 proto_get_first_protocol(void **cookie)
7569 {
7570 protocol_t *protocol;
7571
7572 if (protocols == NULL)
7573 return -1;
7574 *cookie = protocols;
7575 protocol = (protocol_t *)protocols->data;
7576 return protocol->proto_id;
7577 }
7578
7579 int
proto_get_data_protocol(void * cookie)7580 proto_get_data_protocol(void *cookie)
7581 {
7582 GList *list_item = (GList *)cookie;
7583
7584 protocol_t *protocol = (protocol_t *)list_item->data;
7585 return protocol->proto_id;
7586 }
7587
7588 int
proto_get_next_protocol(void ** cookie)7589 proto_get_next_protocol(void **cookie)
7590 {
7591 GList *list_item = (GList *)*cookie;
7592 protocol_t *protocol;
7593
7594 list_item = g_list_next(list_item);
7595 if (list_item == NULL)
7596 return -1;
7597 *cookie = list_item;
7598 protocol = (protocol_t *)list_item->data;
7599 return protocol->proto_id;
7600 }
7601
7602 /* XXX: Unfortunately certain functions in proto_hier_tree_model.c
7603 assume that the cookie stored by
7604 proto_get_(first|next)_protocol_field() will never have a
7605 value of NULL. So, to preserve this semantic, the cookie value
7606 below is adjusted so that the cookie value stored is 1 + the
7607 current (zero-based) array index.
7608 */
7609 header_field_info *
proto_get_first_protocol_field(const int proto_id,void ** cookie)7610 proto_get_first_protocol_field(const int proto_id, void **cookie)
7611 {
7612 protocol_t *protocol = find_protocol_by_id(proto_id);
7613
7614 if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
7615 return NULL;
7616
7617 *cookie = GUINT_TO_POINTER(0 + 1);
7618 return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
7619 }
7620
7621 header_field_info *
proto_get_next_protocol_field(const int proto_id,void ** cookie)7622 proto_get_next_protocol_field(const int proto_id, void **cookie)
7623 {
7624 protocol_t *protocol = find_protocol_by_id(proto_id);
7625 guint i = GPOINTER_TO_UINT(*cookie) - 1;
7626
7627 i++;
7628
7629 if ((protocol->fields == NULL) || (i >= protocol->fields->len))
7630 return NULL;
7631
7632 *cookie = GUINT_TO_POINTER(i + 1);
7633 return (header_field_info *)g_ptr_array_index(protocol->fields, i);
7634 }
7635
7636 protocol_t *
find_protocol_by_id(const int proto_id)7637 find_protocol_by_id(const int proto_id)
7638 {
7639 header_field_info *hfinfo;
7640
7641 if (proto_id < 0)
7642 return NULL;
7643
7644 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
7645 if (hfinfo->type != FT_PROTOCOL) {
7646 DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
7647 }
7648 return (protocol_t *)hfinfo->strings;
7649 }
7650
7651 int
proto_get_id(const protocol_t * protocol)7652 proto_get_id(const protocol_t *protocol)
7653 {
7654 return protocol->proto_id;
7655 }
7656
7657 gboolean
proto_name_already_registered(const gchar * name)7658 proto_name_already_registered(const gchar *name)
7659 {
7660 DISSECTOR_ASSERT_HINT(name, "No name present");
7661
7662 if (g_hash_table_lookup(proto_names, name) != NULL)
7663 return TRUE;
7664 return FALSE;
7665 }
7666
7667 int
proto_get_id_by_filter_name(const gchar * filter_name)7668 proto_get_id_by_filter_name(const gchar *filter_name)
7669 {
7670 const protocol_t *protocol = NULL;
7671
7672 DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
7673
7674 protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
7675
7676 if (protocol == NULL)
7677 return -1;
7678 return protocol->proto_id;
7679 }
7680
7681 int
proto_get_id_by_short_name(const gchar * short_name)7682 proto_get_id_by_short_name(const gchar *short_name)
7683 {
7684 const protocol_t *protocol = NULL;
7685
7686 DISSECTOR_ASSERT_HINT(short_name, "No short name present");
7687
7688 protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
7689
7690 if (protocol == NULL)
7691 return -1;
7692 return protocol->proto_id;
7693 }
7694
7695 const char *
proto_get_protocol_name(const int proto_id)7696 proto_get_protocol_name(const int proto_id)
7697 {
7698 protocol_t *protocol;
7699
7700 protocol = find_protocol_by_id(proto_id);
7701
7702 if (protocol == NULL)
7703 return NULL;
7704 return protocol->name;
7705 }
7706
7707 const char *
proto_get_protocol_short_name(const protocol_t * protocol)7708 proto_get_protocol_short_name(const protocol_t *protocol)
7709 {
7710 if (protocol == NULL)
7711 return "(none)";
7712 return protocol->short_name;
7713 }
7714
7715 const char *
proto_get_protocol_long_name(const protocol_t * protocol)7716 proto_get_protocol_long_name(const protocol_t *protocol)
7717 {
7718 if (protocol == NULL)
7719 return "(none)";
7720 return protocol->name;
7721 }
7722
7723 const char *
proto_get_protocol_filter_name(const int proto_id)7724 proto_get_protocol_filter_name(const int proto_id)
7725 {
7726 protocol_t *protocol;
7727
7728 protocol = find_protocol_by_id(proto_id);
7729 if (protocol == NULL)
7730 return "(none)";
7731 return protocol->filter_name;
7732 }
7733
proto_add_heuristic_dissector(protocol_t * protocol,const char * short_name)7734 void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
7735 {
7736 heur_dtbl_entry_t* heuristic_dissector;
7737
7738 if (protocol == NULL)
7739 return;
7740
7741 heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
7742 if (heuristic_dissector != NULL)
7743 {
7744 protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
7745 }
7746 }
7747
proto_heuristic_dissector_foreach(const protocol_t * protocol,GFunc func,gpointer user_data)7748 void proto_heuristic_dissector_foreach(const protocol_t *protocol, GFunc func, gpointer user_data)
7749 {
7750 if (protocol == NULL)
7751 return;
7752
7753 g_list_foreach(protocol->heur_list, func, user_data);
7754 }
7755
7756 void
proto_get_frame_protocols(const wmem_list_t * layers,gboolean * is_ip,gboolean * is_tcp,gboolean * is_udp,gboolean * is_sctp,gboolean * is_tls,gboolean * is_rtp,gboolean * is_lte_rlc)7757 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip,
7758 gboolean *is_tcp, gboolean *is_udp,
7759 gboolean *is_sctp, gboolean *is_tls,
7760 gboolean *is_rtp,
7761 gboolean *is_lte_rlc)
7762 {
7763 wmem_list_frame_t *protos = wmem_list_head(layers);
7764 int proto_id;
7765 const char *proto_name;
7766
7767 /* Walk the list of a available protocols in the packet and
7768 attempt to find "major" ones. */
7769 /* It might make more sense to assemble and return a bitfield. */
7770 while (protos != NULL)
7771 {
7772 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
7773 proto_name = proto_get_protocol_filter_name(proto_id);
7774
7775 if (is_ip && ((!strcmp(proto_name, "ip")) ||
7776 (!strcmp(proto_name, "ipv6")))) {
7777 *is_ip = TRUE;
7778 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
7779 *is_tcp = TRUE;
7780 } else if (is_udp && !strcmp(proto_name, "udp")) {
7781 *is_udp = TRUE;
7782 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
7783 *is_sctp = TRUE;
7784 } else if (is_tls && !strcmp(proto_name, "tls")) {
7785 *is_tls = TRUE;
7786 } else if (is_rtp && !strcmp(proto_name, "rtp")) {
7787 *is_rtp = TRUE;
7788 } else if (is_lte_rlc && !strcmp(proto_name, "rlc-lte")) {
7789 *is_lte_rlc = TRUE;
7790 }
7791
7792 protos = wmem_list_frame_next(protos);
7793 }
7794 }
7795
7796 gboolean
proto_is_frame_protocol(const wmem_list_t * layers,const char * proto_name)7797 proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name)
7798 {
7799 wmem_list_frame_t *protos = wmem_list_head(layers);
7800 int proto_id;
7801 const char *name;
7802
7803 /* Walk the list of a available protocols in the packet and
7804 attempt to find the specified protocol. */
7805 while (protos != NULL)
7806 {
7807 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
7808 name = proto_get_protocol_filter_name(proto_id);
7809
7810 if (!strcmp(name, proto_name))
7811 {
7812 return TRUE;
7813 }
7814
7815 protos = wmem_list_frame_next(protos);
7816 }
7817
7818 return FALSE;
7819 }
7820
7821 gboolean
proto_is_pino(const protocol_t * protocol)7822 proto_is_pino(const protocol_t *protocol)
7823 {
7824 return (protocol->parent_proto_id != -1);
7825 }
7826
7827 gboolean
proto_is_protocol_enabled(const protocol_t * protocol)7828 proto_is_protocol_enabled(const protocol_t *protocol)
7829 {
7830 if (protocol == NULL)
7831 return FALSE;
7832
7833 //parent protocol determines enable/disable for helper dissectors
7834 if (proto_is_pino(protocol))
7835 return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));
7836
7837 return protocol->is_enabled;
7838 }
7839
7840 gboolean
proto_is_protocol_enabled_by_default(const protocol_t * protocol)7841 proto_is_protocol_enabled_by_default(const protocol_t *protocol)
7842 {
7843 //parent protocol determines enable/disable for helper dissectors
7844 if (proto_is_pino(protocol))
7845 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id));
7846
7847 return protocol->enabled_by_default;
7848 }
7849
7850 gboolean
proto_can_toggle_protocol(const int proto_id)7851 proto_can_toggle_protocol(const int proto_id)
7852 {
7853 protocol_t *protocol;
7854
7855 protocol = find_protocol_by_id(proto_id);
7856 //parent protocol determines toggling for helper dissectors
7857 if (proto_is_pino(protocol))
7858 return proto_can_toggle_protocol(protocol->parent_proto_id);
7859
7860 return protocol->can_toggle;
7861 }
7862
7863 void
proto_disable_by_default(const int proto_id)7864 proto_disable_by_default(const int proto_id)
7865 {
7866 protocol_t *protocol;
7867
7868 protocol = find_protocol_by_id(proto_id);
7869 DISSECTOR_ASSERT(protocol->can_toggle);
7870 DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
7871 protocol->is_enabled = FALSE;
7872 protocol->enabled_by_default = FALSE;
7873 }
7874
7875 void
proto_set_decoding(const int proto_id,const gboolean enabled)7876 proto_set_decoding(const int proto_id, const gboolean enabled)
7877 {
7878 protocol_t *protocol;
7879
7880 protocol = find_protocol_by_id(proto_id);
7881 DISSECTOR_ASSERT(protocol->can_toggle);
7882 DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
7883 protocol->is_enabled = enabled;
7884 }
7885
7886 void
proto_reenable_all(void)7887 proto_reenable_all(void)
7888 {
7889 protocol_t *protocol;
7890 GList *list_item = protocols;
7891
7892 if (protocols == NULL)
7893 return;
7894
7895 while (list_item) {
7896 protocol = (protocol_t *)list_item->data;
7897 if (protocol->can_toggle && protocol->enabled_by_default)
7898 protocol->is_enabled = TRUE;
7899 list_item = g_list_next(list_item);
7900 }
7901 }
7902
7903 void
proto_set_cant_toggle(const int proto_id)7904 proto_set_cant_toggle(const int proto_id)
7905 {
7906 protocol_t *protocol;
7907
7908 protocol = find_protocol_by_id(proto_id);
7909 protocol->can_toggle = FALSE;
7910 }
7911
7912 static int
proto_register_field_common(protocol_t * proto,header_field_info * hfi,const int parent)7913 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
7914 {
7915 if (proto != NULL) {
7916 g_ptr_array_add(proto->fields, hfi);
7917 }
7918
7919 return proto_register_field_init(hfi, parent);
7920 }
7921
7922 /* for use with static arrays only, since we don't allocate our own copies
7923 of the header_field_info struct contained within the hf_register_info struct */
7924 void
proto_register_field_array(const int parent,hf_register_info * hf,const int num_records)7925 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
7926 {
7927 hf_register_info *ptr = hf;
7928 protocol_t *proto;
7929 int i;
7930
7931 proto = find_protocol_by_id(parent);
7932
7933 if (proto->fields == NULL) {
7934 proto->fields = g_ptr_array_sized_new(num_records);
7935 }
7936
7937 for (i = 0; i < num_records; i++, ptr++) {
7938 /*
7939 * Make sure we haven't registered this yet.
7940 * Most fields have variables associated with them
7941 * that are initialized to -1; some have array elements,
7942 * or possibly uninitialized variables, so we also allow
7943 * 0 (which is unlikely to be the field ID we get back
7944 * from "proto_register_field_init()").
7945 */
7946 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
7947 fprintf(stderr,
7948 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
7949 ptr->hfinfo.abbrev);
7950 return;
7951 }
7952
7953 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
7954 }
7955 }
7956
7957 void
proto_register_fields_section(const int parent,header_field_info * hfi,const int num_records)7958 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
7959 {
7960 int i;
7961 protocol_t *proto;
7962
7963 proto = find_protocol_by_id(parent);
7964
7965 if (proto->fields == NULL) {
7966 proto->fields = g_ptr_array_sized_new(num_records);
7967 }
7968
7969 for (i = 0; i < num_records; i++) {
7970 /*
7971 * Make sure we haven't registered this yet.
7972 */
7973 if (hfi[i].id != -1) {
7974 fprintf(stderr,
7975 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
7976 hfi[i].abbrev);
7977 return;
7978 }
7979
7980 proto_register_field_common(proto, &hfi[i], parent);
7981 }
7982 }
7983
7984 void
proto_register_fields_manual(const int parent,header_field_info ** hfi,const int num_records)7985 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
7986 {
7987 int i;
7988 protocol_t *proto;
7989
7990 proto = find_protocol_by_id(parent);
7991
7992 if (proto->fields == NULL) {
7993 proto->fields = g_ptr_array_sized_new(num_records);
7994 }
7995
7996
7997 for (i = 0; i < num_records; i++) {
7998 /*
7999 * Make sure we haven't registered this yet.
8000 */
8001 if (hfi[i]->id != -1) {
8002 fprintf(stderr,
8003 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
8004 hfi[i]->abbrev);
8005 return;
8006 }
8007
8008 proto_register_field_common(proto, hfi[i], parent);
8009 }
8010 }
8011
8012 /* deregister already registered fields */
8013 void
proto_deregister_field(const int parent,gint hf_id)8014 proto_deregister_field (const int parent, gint hf_id)
8015 {
8016 header_field_info *hfi;
8017 protocol_t *proto;
8018 guint i;
8019
8020 g_free(last_field_name);
8021 last_field_name = NULL;
8022
8023 if (hf_id == -1 || hf_id == 0)
8024 return;
8025
8026 proto = find_protocol_by_id (parent);
8027 if (!proto || proto->fields == NULL) {
8028 return;
8029 }
8030
8031 for (i = 0; i < proto->fields->len; i++) {
8032 hfi = (header_field_info *)g_ptr_array_index(proto->fields, i);
8033 if (hfi->id == hf_id) {
8034 /* Found the hf_id in this protocol */
8035 g_hash_table_steal(gpa_name_map, hfi->abbrev);
8036 g_ptr_array_remove_index_fast(proto->fields, i);
8037 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hf_id]);
8038 return;
8039 }
8040 }
8041 }
8042
8043 void
proto_add_deregistered_data(void * data)8044 proto_add_deregistered_data (void *data)
8045 {
8046 g_ptr_array_add(deregistered_data, data);
8047 }
8048
8049 void
proto_add_deregistered_slice(gsize block_size,gpointer mem_block)8050 proto_add_deregistered_slice (gsize block_size, gpointer mem_block)
8051 {
8052 struct g_slice_data *slice_data = g_slice_new(struct g_slice_data);
8053
8054 slice_data->block_size = block_size;
8055 slice_data->mem_block = mem_block;
8056
8057 g_ptr_array_add(deregistered_slice, slice_data);
8058 }
8059
proto_free_field_strings(ftenum_t field_type,unsigned int field_display,const void * field_strings)8060 void proto_free_field_strings (ftenum_t field_type, unsigned int field_display, const void *field_strings)
8061 {
8062 if (field_strings == NULL) {
8063 return;
8064 }
8065
8066 switch (field_type) {
8067 case FT_FRAMENUM:
8068 /* This is just an integer represented as a pointer */
8069 break;
8070 case FT_PROTOCOL: {
8071 protocol_t *protocol = (protocol_t *)field_strings;
8072 g_free((gchar *)protocol->short_name);
8073 break;
8074 }
8075 case FT_BOOLEAN: {
8076 true_false_string *tf = (true_false_string *)field_strings;
8077 g_free((gchar *)tf->true_string);
8078 g_free((gchar *)tf->false_string);
8079 break;
8080 }
8081 case FT_UINT40:
8082 case FT_INT40:
8083 case FT_UINT48:
8084 case FT_INT48:
8085 case FT_UINT56:
8086 case FT_INT56:
8087 case FT_UINT64:
8088 case FT_INT64: {
8089 /*
8090 * XXX - if it's BASE_RANGE_STRING, or
8091 * BASE_EXT_STRING, should we free it?
8092 */
8093 if (field_display & BASE_UNIT_STRING) {
8094 unit_name_string *unit = (unit_name_string *)field_strings;
8095 g_free((gchar *)unit->singular);
8096 g_free((gchar *)unit->plural);
8097 } else {
8098 val64_string *vs64 = (val64_string *)field_strings;
8099 while (vs64->strptr) {
8100 g_free((gchar *)vs64->strptr);
8101 vs64++;
8102 }
8103 }
8104 break;
8105 }
8106 case FT_CHAR:
8107 case FT_UINT8:
8108 case FT_INT8:
8109 case FT_UINT16:
8110 case FT_INT16:
8111 case FT_UINT24:
8112 case FT_INT24:
8113 case FT_UINT32:
8114 case FT_INT32:
8115 case FT_FLOAT:
8116 case FT_DOUBLE: {
8117 /*
8118 * XXX - if it's BASE_RANGE_STRING, or
8119 * BASE_EXT_STRING, should we free it?
8120 */
8121 if (field_display & BASE_UNIT_STRING) {
8122 unit_name_string *unit = (unit_name_string *)field_strings;
8123 g_free((gchar *)unit->singular);
8124 g_free((gchar *)unit->plural);
8125 } else if (field_display & BASE_RANGE_STRING) {
8126 range_string *rs = (range_string *)field_strings;
8127 while (rs->strptr) {
8128 g_free((gchar *)rs->strptr);
8129 rs++;
8130 }
8131 } else {
8132 value_string *vs = (value_string *)field_strings;
8133 while (vs->strptr) {
8134 g_free((gchar *)vs->strptr);
8135 vs++;
8136 }
8137 }
8138 break;
8139 default:
8140 break;
8141 }
8142 }
8143
8144 if (field_type != FT_FRAMENUM) {
8145 g_free((void *)field_strings);
8146 }
8147 }
8148
8149 static void
free_deregistered_field(gpointer data,gpointer user_data _U_)8150 free_deregistered_field (gpointer data, gpointer user_data _U_)
8151 {
8152 header_field_info *hfi = (header_field_info *) data;
8153 gint hf_id = hfi->id;
8154
8155 g_free((char *)hfi->name);
8156 g_free((char *)hfi->abbrev);
8157 g_free((char *)hfi->blurb);
8158
8159 proto_free_field_strings(hfi->type, hfi->display, hfi->strings);
8160
8161 if (hfi->parent == -1)
8162 g_slice_free(header_field_info, hfi);
8163
8164 gpa_hfinfo.hfi[hf_id] = NULL; /* Invalidate this hf_id / proto_id */
8165 }
8166
8167 static void
free_deregistered_data(gpointer data,gpointer user_data _U_)8168 free_deregistered_data (gpointer data, gpointer user_data _U_)
8169 {
8170 g_free (data);
8171 }
8172
8173 static void
free_deregistered_slice(gpointer data,gpointer user_data _U_)8174 free_deregistered_slice (gpointer data, gpointer user_data _U_)
8175 {
8176 struct g_slice_data *slice_data = (struct g_slice_data *)data;
8177
8178 g_slice_free1(slice_data->block_size, slice_data->mem_block);
8179 g_slice_free(struct g_slice_data, slice_data);
8180 }
8181
8182 /* free deregistered fields and data */
8183 void
proto_free_deregistered_fields(void)8184 proto_free_deregistered_fields (void)
8185 {
8186 expert_free_deregistered_expertinfos();
8187
8188 g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
8189 g_ptr_array_free(deregistered_fields, TRUE);
8190 deregistered_fields = g_ptr_array_new();
8191
8192 g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
8193 g_ptr_array_free(deregistered_data, TRUE);
8194 deregistered_data = g_ptr_array_new();
8195
8196 g_ptr_array_foreach(deregistered_slice, free_deregistered_slice, NULL);
8197 g_ptr_array_free(deregistered_slice, TRUE);
8198 deregistered_slice = g_ptr_array_new();
8199 }
8200
8201 /* chars allowed in field abbrev: alphanumerics, '-', "_", and ".". */
8202 static
8203 const guint8 fld_abbrev_chars[256] = {
8204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
8205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
8206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
8207 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
8208 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
8209 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
8210 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
8211 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
8212 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
8213 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
8214 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
8215 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
8216 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
8217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
8218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
8219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
8220 };
8221
8222 static const value_string hf_display[] = {
8223 { BASE_NONE, "BASE_NONE" },
8224 { BASE_DEC, "BASE_DEC" },
8225 { BASE_HEX, "BASE_HEX" },
8226 { BASE_OCT, "BASE_OCT" },
8227 { BASE_DEC_HEX, "BASE_DEC_HEX" },
8228 { BASE_HEX_DEC, "BASE_HEX_DEC" },
8229 { BASE_CUSTOM, "BASE_CUSTOM" },
8230 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
8231 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
8232 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
8233 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
8234 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
8235 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
8236 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
8237 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
8238 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
8239 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
8240 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
8241 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
8242 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
8243 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
8244 /* Alias: BASE_NONE { BASE_FLOAT, "BASE_FLOAT" }, */
8245 /* Alias: BASE_NONE { STR_ASCII, "STR_ASCII" }, */
8246 { STR_UNICODE, "STR_UNICODE" },
8247 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
8248 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
8249 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
8250 { BASE_PT_UDP, "BASE_PT_UDP" },
8251 { BASE_PT_TCP, "BASE_PT_TCP" },
8252 { BASE_PT_DCCP, "BASE_PT_DCCP" },
8253 { BASE_PT_SCTP, "BASE_PT_SCTP" },
8254 { BASE_OUI, "BASE_OUI" },
8255 { 0, NULL } };
8256
proto_field_display_to_string(int field_display)8257 const char* proto_field_display_to_string(int field_display)
8258 {
8259 return val_to_str_const(field_display, hf_display, "Unknown");
8260 }
8261
8262 static inline port_type
display_to_port_type(field_display_e e)8263 display_to_port_type(field_display_e e)
8264 {
8265 switch (e) {
8266 case BASE_PT_UDP:
8267 return PT_UDP;
8268 case BASE_PT_TCP:
8269 return PT_TCP;
8270 case BASE_PT_DCCP:
8271 return PT_DCCP;
8272 case BASE_PT_SCTP:
8273 return PT_SCTP;
8274 default:
8275 break;
8276 }
8277 return PT_NONE;
8278 }
8279
8280 /* temporary function containing assert part for easier profiling */
8281 static void
tmp_fld_check_assert(header_field_info * hfinfo)8282 tmp_fld_check_assert(header_field_info *hfinfo)
8283 {
8284 gchar* tmp_str;
8285
8286 /* The field must have a name (with length > 0) */
8287 if (!hfinfo->name || !hfinfo->name[0]) {
8288 if (hfinfo->abbrev)
8289 /* Try to identify the field */
8290 ws_error("Field (abbrev='%s') does not have a name\n",
8291 hfinfo->abbrev);
8292 else
8293 /* Hum, no luck */
8294 ws_error("Field does not have a name (nor an abbreviation)\n");
8295 }
8296
8297 /* fields with an empty string for an abbreviation aren't filterable */
8298 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
8299 ws_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
8300
8301 /* These types of fields are allowed to have value_strings,
8302 * true_false_strings or a protocol_t struct
8303 */
8304 if (hfinfo->strings != NULL) {
8305 switch (hfinfo->type) {
8306 case FT_CHAR:
8307 case FT_UINT8:
8308 case FT_UINT16:
8309 case FT_UINT24:
8310 case FT_UINT32:
8311 case FT_UINT40:
8312 case FT_UINT48:
8313 case FT_UINT56:
8314 case FT_UINT64:
8315 case FT_INT8:
8316 case FT_INT16:
8317 case FT_INT24:
8318 case FT_INT32:
8319 case FT_INT40:
8320 case FT_INT48:
8321 case FT_INT56:
8322 case FT_INT64:
8323 case FT_BOOLEAN:
8324 case FT_PROTOCOL:
8325 case FT_FRAMENUM:
8326 break;
8327 case FT_FLOAT:
8328 case FT_DOUBLE:
8329 //allowed to support string if its a unit decsription
8330 if (hfinfo->display & BASE_UNIT_STRING)
8331 break;
8332
8333 //fallthrough
8334 case FT_BYTES:
8335 //allowed to support string if its a protocol (for pinos)
8336 if (hfinfo->display & BASE_PROTOCOL_INFO)
8337 break;
8338
8339 //fallthrough
8340 default:
8341 ws_error("Field '%s' (%s) has a 'strings' value but is of type %s"
8342 " (which is not allowed to have strings)\n",
8343 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
8344 }
8345 }
8346
8347 /* TODO: This check may slow down startup, and output quite a few warnings.
8348 It would be good to be able to enable this (and possibly other checks?)
8349 in non-release builds. */
8350 #ifdef ENABLE_CHECK_FILTER
8351 /* Check for duplicate value_string values.
8352 There are lots that have the same value *and* string, so for now only
8353 report those that have same value but different string. */
8354 if ((hfinfo->strings != NULL) &&
8355 !(hfinfo->display & BASE_RANGE_STRING) &&
8356 !(hfinfo->display & BASE_UNIT_STRING) &&
8357 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
8358 (
8359 (hfinfo->type == FT_CHAR) ||
8360 (hfinfo->type == FT_UINT8) ||
8361 (hfinfo->type == FT_UINT16) ||
8362 (hfinfo->type == FT_UINT24) ||
8363 (hfinfo->type == FT_UINT32) ||
8364 (hfinfo->type == FT_INT8) ||
8365 (hfinfo->type == FT_INT16) ||
8366 (hfinfo->type == FT_INT24) ||
8367 (hfinfo->type == FT_INT32) )) {
8368
8369 if (hfinfo->display & BASE_EXT_STRING) {
8370 if (hfinfo->display & BASE_VAL64_STRING) {
8371 const val64_string *start_values = VAL64_STRING_EXT_VS_P((const val64_string_ext*)hfinfo->strings);
8372 CHECK_HF_VALUE(val64_string, G_GINT64_MODIFIER, start_values);
8373 } else {
8374 const value_string *start_values = VALUE_STRING_EXT_VS_P((const value_string_ext*)hfinfo->strings);
8375 CHECK_HF_VALUE(value_string, "", start_values);
8376 }
8377 } else {
8378 const value_string *start_values = (const value_string*)hfinfo->strings;
8379 CHECK_HF_VALUE(value_string, "", start_values);
8380 }
8381 }
8382
8383 if (hfinfo->type == FT_BOOLEAN) {
8384 const true_false_string *tfs = (const true_false_string*)hfinfo->strings;
8385 if (tfs) {
8386 if (strcmp(tfs->false_string, tfs->true_string) == 0) {
8387 ws_warning("Field '%s' (%s) has identical true and false strings (\"%s\", \"%s\")",
8388 hfinfo->name, hfinfo->abbrev,
8389 tfs->false_string, tfs->true_string);
8390 }
8391 }
8392 }
8393
8394 if (hfinfo->display & BASE_RANGE_STRING) {
8395 const range_string *rs = (const range_string*)(hfinfo->strings);
8396 if (rs) {
8397 const range_string *this_it = rs;
8398
8399 do {
8400 if (this_it->value_max < this_it->value_min) {
8401 ws_warning("value_range_string error: %s (%s) entry for \"%s\" - max(%u 0x%x) is less than min(%u 0x%x)",
8402 hfinfo->name, hfinfo->abbrev,
8403 this_it->strptr,
8404 this_it->value_max, this_it->value_max,
8405 this_it->value_min, this_it->value_min);
8406 ++this_it;
8407 continue;
8408 }
8409
8410 for (const range_string *prev_it=rs; prev_it < this_it; ++prev_it) {
8411 /* Not OK if this one is completely hidden by an earlier one! */
8412 if ((prev_it->value_min <= this_it->value_min) && (prev_it->value_max >= this_it->value_max)) {
8413 ws_warning("value_range_string error: %s (%s) hidden by earlier entry "
8414 "(prev=\"%s\": %u 0x%x -> %u 0x%x) (this=\"%s\": %u 0x%x -> %u 0x%x)",
8415 hfinfo->name, hfinfo->abbrev,
8416 prev_it->strptr, prev_it->value_min, prev_it->value_min,
8417 prev_it->value_max, prev_it->value_max,
8418 this_it->strptr, this_it->value_min, this_it->value_min,
8419 this_it->value_max, this_it->value_max);
8420 }
8421 }
8422 ++this_it;
8423 } while (this_it->strptr);
8424 }
8425 }
8426 #endif
8427
8428 switch (hfinfo->type) {
8429
8430 case FT_CHAR:
8431 /* Require the char type to have BASE_HEX, BASE_OCT,
8432 * BASE_CUSTOM, or BASE_NONE as its base.
8433 *
8434 * If the display value is BASE_NONE and there is a
8435 * strings conversion then the dissector writer is
8436 * telling us that the field's numerical value is
8437 * meaningless; we'll avoid showing the value to the
8438 * user.
8439 */
8440 switch (FIELD_DISPLAY(hfinfo->display)) {
8441 case BASE_HEX:
8442 case BASE_OCT:
8443 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
8444 break;
8445 case BASE_NONE:
8446 if (hfinfo->strings == NULL)
8447 ws_error("Field '%s' (%s) is an integral value (%s)"
8448 " but is being displayed as BASE_NONE but"
8449 " without a strings conversion",
8450 hfinfo->name, hfinfo->abbrev,
8451 ftype_name(hfinfo->type));
8452 break;
8453 default:
8454 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
8455 ws_error("Field '%s' (%s) is a character value (%s)"
8456 " but is being displayed as %s\n",
8457 hfinfo->name, hfinfo->abbrev,
8458 ftype_name(hfinfo->type), tmp_str);
8459 wmem_free(NULL, tmp_str);
8460 }
8461 if (hfinfo->display & BASE_UNIT_STRING) {
8462 ws_error("Field '%s' (%s) is a character value (%s) but has a unit string\n",
8463 hfinfo->name, hfinfo->abbrev,
8464 ftype_name(hfinfo->type));
8465 }
8466 break;
8467 case FT_INT8:
8468 case FT_INT16:
8469 case FT_INT24:
8470 case FT_INT32:
8471 case FT_INT40:
8472 case FT_INT48:
8473 case FT_INT56:
8474 case FT_INT64:
8475 /* Hexadecimal and octal are, in printf() and everywhere
8476 * else, unsigned so don't allow dissectors to register a
8477 * signed field to be displayed unsigned. (Else how would
8478 * we display negative values?)
8479 */
8480 switch (FIELD_DISPLAY(hfinfo->display)) {
8481 case BASE_HEX:
8482 case BASE_OCT:
8483 case BASE_DEC_HEX:
8484 case BASE_HEX_DEC:
8485 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
8486 ws_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
8487 hfinfo->name, hfinfo->abbrev,
8488 ftype_name(hfinfo->type), tmp_str);
8489 wmem_free(NULL, tmp_str);
8490 }
8491 /* FALL THROUGH */
8492 case FT_UINT8:
8493 case FT_UINT16:
8494 case FT_UINT24:
8495 case FT_UINT32:
8496 case FT_UINT40:
8497 case FT_UINT48:
8498 case FT_UINT56:
8499 case FT_UINT64:
8500 if (IS_BASE_PORT(hfinfo->display)) {
8501 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
8502 if (hfinfo->type != FT_UINT16) {
8503 ws_error("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s\n",
8504 hfinfo->name, hfinfo->abbrev,
8505 tmp_str, ftype_name(hfinfo->type));
8506 }
8507 if (hfinfo->strings != NULL) {
8508 ws_error("Field '%s' (%s) is an %s (%s) but has a strings value\n",
8509 hfinfo->name, hfinfo->abbrev,
8510 ftype_name(hfinfo->type), tmp_str);
8511 }
8512 if (hfinfo->bitmask != 0) {
8513 ws_error("Field '%s' (%s) is an %s (%s) but has a bitmask\n",
8514 hfinfo->name, hfinfo->abbrev,
8515 ftype_name(hfinfo->type), tmp_str);
8516 }
8517 wmem_free(NULL, tmp_str);
8518 break;
8519 }
8520
8521 if (hfinfo->display == BASE_OUI) {
8522 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
8523 if (hfinfo->type != FT_UINT24) {
8524 ws_error("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT24, not %s\n",
8525 hfinfo->name, hfinfo->abbrev,
8526 tmp_str, ftype_name(hfinfo->type));
8527 }
8528 if (hfinfo->strings != NULL) {
8529 ws_error("Field '%s' (%s) is an %s (%s) but has a strings value\n",
8530 hfinfo->name, hfinfo->abbrev,
8531 ftype_name(hfinfo->type), tmp_str);
8532 }
8533 if (hfinfo->bitmask != 0) {
8534 ws_error("Field '%s' (%s) is an %s (%s) but has a bitmask\n",
8535 hfinfo->name, hfinfo->abbrev,
8536 ftype_name(hfinfo->type), tmp_str);
8537 }
8538 wmem_free(NULL, tmp_str);
8539 break;
8540 }
8541
8542 /* Require integral types (other than frame number,
8543 * which is always displayed in decimal) to have a
8544 * number base.
8545 *
8546 * If the display value is BASE_NONE and there is a
8547 * strings conversion then the dissector writer is
8548 * telling us that the field's numerical value is
8549 * meaningless; we'll avoid showing the value to the
8550 * user.
8551 */
8552 switch (FIELD_DISPLAY(hfinfo->display)) {
8553 case BASE_DEC:
8554 case BASE_HEX:
8555 case BASE_OCT:
8556 case BASE_DEC_HEX:
8557 case BASE_HEX_DEC:
8558 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
8559 break;
8560 case BASE_NONE:
8561 if (hfinfo->strings == NULL) {
8562 ws_error("Field '%s' (%s) is an integral value (%s)"
8563 " but is being displayed as BASE_NONE but"
8564 " without a strings conversion",
8565 hfinfo->name, hfinfo->abbrev,
8566 ftype_name(hfinfo->type));
8567 }
8568 if (hfinfo->display & BASE_SPECIAL_VALS) {
8569 ws_error("Field '%s' (%s) is an integral value (%s)"
8570 " that is being displayed as BASE_NONE but"
8571 " with BASE_SPECIAL_VALS",
8572 hfinfo->name, hfinfo->abbrev,
8573 ftype_name(hfinfo->type));
8574 }
8575 break;
8576
8577 default:
8578 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
8579 ws_error("Field '%s' (%s) is an integral value (%s)"
8580 " but is being displayed as %s\n",
8581 hfinfo->name, hfinfo->abbrev,
8582 ftype_name(hfinfo->type), tmp_str);
8583 wmem_free(NULL, tmp_str);
8584 }
8585 break;
8586 case FT_BYTES:
8587 case FT_UINT_BYTES:
8588 /* Require bytes to have a "display type" that could
8589 * add a character between displayed bytes.
8590 */
8591 switch (FIELD_DISPLAY(hfinfo->display)) {
8592 case BASE_NONE:
8593 case SEP_DOT:
8594 case SEP_DASH:
8595 case SEP_COLON:
8596 case SEP_SPACE:
8597 break;
8598 default:
8599 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
8600 ws_error("Field '%s' (%s) is an byte array but is being displayed as %s instead of BASE_NONE, SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE\n",
8601 hfinfo->name, hfinfo->abbrev, tmp_str);
8602 wmem_free(NULL, tmp_str);
8603 }
8604 if (hfinfo->bitmask != 0)
8605 ws_error("Field '%s' (%s) is an %s but has a bitmask\n",
8606 hfinfo->name, hfinfo->abbrev,
8607 ftype_name(hfinfo->type));
8608 //allowed to support string if its a protocol (for pinos)
8609 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO)))
8610 ws_error("Field '%s' (%s) is an %s but has a strings value\n",
8611 hfinfo->name, hfinfo->abbrev,
8612 ftype_name(hfinfo->type));
8613 break;
8614
8615 case FT_PROTOCOL:
8616 case FT_FRAMENUM:
8617 if (hfinfo->display != BASE_NONE) {
8618 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
8619 ws_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
8620 hfinfo->name, hfinfo->abbrev,
8621 ftype_name(hfinfo->type), tmp_str);
8622 wmem_free(NULL, tmp_str);
8623 }
8624 if (hfinfo->bitmask != 0)
8625 ws_error("Field '%s' (%s) is an %s but has a bitmask\n",
8626 hfinfo->name, hfinfo->abbrev,
8627 ftype_name(hfinfo->type));
8628 break;
8629
8630 case FT_BOOLEAN:
8631 break;
8632
8633 case FT_ABSOLUTE_TIME:
8634 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
8635 hfinfo->display == ABSOLUTE_TIME_UTC ||
8636 hfinfo->display == ABSOLUTE_TIME_NTP_UTC ||
8637 hfinfo->display == ABSOLUTE_TIME_DOY_UTC)) {
8638 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
8639 ws_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
8640 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type), tmp_str);
8641 wmem_free(NULL, tmp_str);
8642 }
8643 if (hfinfo->bitmask != 0)
8644 ws_error("Field '%s' (%s) is an %s but has a bitmask\n",
8645 hfinfo->name, hfinfo->abbrev,
8646 ftype_name(hfinfo->type));
8647 break;
8648
8649 case FT_STRING:
8650 case FT_STRINGZ:
8651 case FT_UINT_STRING:
8652 case FT_STRINGZPAD:
8653 case FT_STRINGZTRUNC:
8654 switch (hfinfo->display) {
8655 case STR_ASCII:
8656 case STR_UNICODE:
8657 break;
8658
8659 default:
8660 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
8661 ws_error("Field '%s' (%s) is an string value (%s)"
8662 " but is being displayed as %s\n",
8663 hfinfo->name, hfinfo->abbrev,
8664 ftype_name(hfinfo->type), tmp_str);
8665 wmem_free(NULL, tmp_str);
8666 }
8667
8668 if (hfinfo->bitmask != 0)
8669 ws_error("Field '%s' (%s) is an %s but has a bitmask\n",
8670 hfinfo->name, hfinfo->abbrev,
8671 ftype_name(hfinfo->type));
8672 if (hfinfo->strings != NULL)
8673 ws_error("Field '%s' (%s) is an %s but has a strings value\n",
8674 hfinfo->name, hfinfo->abbrev,
8675 ftype_name(hfinfo->type));
8676 break;
8677
8678 case FT_IPv4:
8679 switch (hfinfo->display) {
8680 case BASE_NONE:
8681 case BASE_NETMASK:
8682 break;
8683
8684 default:
8685 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
8686 ws_error("Field '%s' (%s) is an IPv4 value (%s)"
8687 " but is being displayed as %s\n",
8688 hfinfo->name, hfinfo->abbrev,
8689 ftype_name(hfinfo->type), tmp_str);
8690 wmem_free(NULL, tmp_str);
8691 break;
8692 }
8693 break;
8694 case FT_FLOAT:
8695 case FT_DOUBLE:
8696 if (FIELD_DISPLAY(hfinfo->display) != BASE_NONE) {
8697 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
8698 ws_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
8699 hfinfo->name, hfinfo->abbrev,
8700 ftype_name(hfinfo->type),
8701 tmp_str);
8702 wmem_free(NULL, tmp_str);
8703 }
8704 if (hfinfo->bitmask != 0)
8705 ws_error("Field '%s' (%s) is an %s but has a bitmask\n",
8706 hfinfo->name, hfinfo->abbrev,
8707 ftype_name(hfinfo->type));
8708 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_UNIT_STRING)))
8709 ws_error("Field '%s' (%s) is an %s but has a strings value\n",
8710 hfinfo->name, hfinfo->abbrev,
8711 ftype_name(hfinfo->type));
8712 break;
8713 default:
8714 if (hfinfo->display != BASE_NONE) {
8715 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
8716 ws_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
8717 hfinfo->name, hfinfo->abbrev,
8718 ftype_name(hfinfo->type),
8719 tmp_str);
8720 wmem_free(NULL, tmp_str);
8721 }
8722 if (hfinfo->bitmask != 0)
8723 ws_error("Field '%s' (%s) is an %s but has a bitmask\n",
8724 hfinfo->name, hfinfo->abbrev,
8725 ftype_name(hfinfo->type));
8726 if (hfinfo->strings != NULL)
8727 ws_error("Field '%s' (%s) is an %s but has a strings value\n",
8728 hfinfo->name, hfinfo->abbrev,
8729 ftype_name(hfinfo->type));
8730 break;
8731 }
8732 }
8733
8734 #ifdef ENABLE_CHECK_FILTER
8735 static enum ftenum
_ftype_common(enum ftenum type)8736 _ftype_common(enum ftenum type)
8737 {
8738 switch (type) {
8739 case FT_INT8:
8740 case FT_INT16:
8741 case FT_INT24:
8742 case FT_INT32:
8743 return FT_INT32;
8744
8745 case FT_CHAR:
8746 case FT_UINT8:
8747 case FT_UINT16:
8748 case FT_UINT24:
8749 case FT_UINT32:
8750 case FT_IPXNET:
8751 case FT_FRAMENUM:
8752 return FT_UINT32;
8753
8754 case FT_UINT64:
8755 case FT_EUI64:
8756 return FT_UINT64;
8757
8758 case FT_STRING:
8759 case FT_STRINGZ:
8760 case FT_UINT_STRING:
8761 return FT_STRING;
8762
8763 case FT_FLOAT:
8764 case FT_DOUBLE:
8765 return FT_DOUBLE;
8766
8767 case FT_BYTES:
8768 case FT_UINT_BYTES:
8769 case FT_ETHER:
8770 case FT_OID:
8771 return FT_BYTES;
8772
8773 case FT_ABSOLUTE_TIME:
8774 case FT_RELATIVE_TIME:
8775 return FT_ABSOLUTE_TIME;
8776
8777 default:
8778 return type;
8779 }
8780 }
8781 #endif
8782
8783 static void
register_type_length_mismatch(void)8784 register_type_length_mismatch(void)
8785 {
8786 static ei_register_info ei[] = {
8787 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
8788 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
8789 };
8790
8791 expert_module_t* expert_type_length_mismatch;
8792
8793 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
8794
8795 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
8796 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
8797
8798 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
8799 disabling them makes no sense. */
8800 proto_set_cant_toggle(proto_type_length_mismatch);
8801 }
8802
8803 static void
register_number_string_decodinws_error(void)8804 register_number_string_decodinws_error(void)
8805 {
8806 static ei_register_info ei[] = {
8807 { &ei_number_string_decoding_failed_error,
8808 { "_ws.number_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
8809 "Failed to decode number from string", EXPFILL
8810 }
8811 },
8812 { &ei_number_string_decoding_erange_error,
8813 { "_ws.number_string.decoding_error.erange", PI_MALFORMED, PI_ERROR,
8814 "Decoded number from string is out of valid range", EXPFILL
8815 }
8816 },
8817 };
8818
8819 expert_module_t* expert_number_string_decoding_error;
8820
8821 proto_number_string_decoding_error =
8822 proto_register_protocol("Number-String Decoding Error",
8823 "Number-string decoding error",
8824 "_ws.number_string.decoding_error");
8825
8826 expert_number_string_decoding_error =
8827 expert_register_protocol(proto_number_string_decoding_error);
8828 expert_register_field_array(expert_number_string_decoding_error, ei, array_length(ei));
8829
8830 /* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
8831 disabling them makes no sense. */
8832 proto_set_cant_toggle(proto_number_string_decoding_error);
8833 }
8834
8835 static void
register_string_errors(void)8836 register_string_errors(void)
8837 {
8838 static ei_register_info ei[] = {
8839 { &ei_string_trailing_characters,
8840 { "_ws.string.trailing_stray_characters", PI_UNDECODED, PI_WARN, "Trailing stray characters", EXPFILL }
8841 },
8842 };
8843
8844 expert_module_t* expert_string_errors;
8845
8846 proto_string_errors = proto_register_protocol("String Errors", "String errors", "_ws.string");
8847
8848 expert_string_errors = expert_register_protocol(proto_string_errors);
8849 expert_register_field_array(expert_string_errors, ei, array_length(ei));
8850
8851 /* "String Errors" isn't really a protocol, it's an error indication;
8852 disabling them makes no sense. */
8853 proto_set_cant_toggle(proto_string_errors);
8854 }
8855
8856 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (235000+PRE_ALLOC_EXPERT_FIELDS_MEM)
8857 static int
proto_register_field_init(header_field_info * hfinfo,const int parent)8858 proto_register_field_init(header_field_info *hfinfo, const int parent)
8859 {
8860
8861 tmp_fld_check_assert(hfinfo);
8862
8863 hfinfo->parent = parent;
8864 hfinfo->same_name_next = NULL;
8865 hfinfo->same_name_prev_id = -1;
8866
8867 /* if we always add and never delete, then id == len - 1 is correct */
8868 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
8869 if (!gpa_hfinfo.hfi) {
8870 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
8871 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
8872 } else {
8873 gpa_hfinfo.allocated_len += 1000;
8874 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
8875 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
8876 /*ws_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
8877 }
8878 }
8879 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
8880 gpa_hfinfo.len++;
8881 hfinfo->id = gpa_hfinfo.len - 1;
8882
8883 /* if we have real names, enter this field in the name tree */
8884 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
8885
8886 header_field_info *same_name_next_hfinfo;
8887 guchar c;
8888
8889 /* Check that the filter name (abbreviation) is legal;
8890 * it must contain only alphanumerics, '-', "_", and ".". */
8891 c = proto_check_field_name(hfinfo->abbrev);
8892 if (c) {
8893 if (c == '.') {
8894 fprintf(stderr, "Invalid leading, duplicated or trailing '.' found in filter name '%s'\n", hfinfo->abbrev);
8895 } else if (g_ascii_isprint(c)) {
8896 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
8897 } else {
8898 fprintf(stderr, "Invalid byte \\%03o in filter name '%s'\n", c, hfinfo->abbrev);
8899 }
8900 DISSECTOR_ASSERT_NOT_REACHED();
8901 }
8902
8903 /* We allow multiple hfinfo's to be registered under the same
8904 * abbreviation. This was done for X.25, as, depending
8905 * on whether it's modulo-8 or modulo-128 operation,
8906 * some bitfield fields may be in different bits of
8907 * a byte, and we want to be able to refer to that field
8908 * with one name regardless of whether the packets
8909 * are modulo-8 or modulo-128 packets. */
8910
8911 same_name_hfinfo = NULL;
8912
8913 g_hash_table_insert(gpa_name_map, (gpointer) (hfinfo->abbrev), hfinfo);
8914 /* GLIB 2.x - if it is already present
8915 * the previous hfinfo with the same name is saved
8916 * to same_name_hfinfo by value destroy callback */
8917 if (same_name_hfinfo) {
8918 /* There's already a field with this name.
8919 * Put the current field *before* that field
8920 * in the list of fields with this name, Thus,
8921 * we end up with an effectively
8922 * doubly-linked-list of same-named hfinfo's,
8923 * with the head of the list (stored in the
8924 * hash) being the last seen hfinfo.
8925 */
8926 same_name_next_hfinfo =
8927 same_name_hfinfo->same_name_next;
8928
8929 hfinfo->same_name_next = same_name_next_hfinfo;
8930 if (same_name_next_hfinfo)
8931 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
8932
8933 same_name_hfinfo->same_name_next = hfinfo;
8934 hfinfo->same_name_prev_id = same_name_hfinfo->id;
8935 #ifdef ENABLE_CHECK_FILTER
8936 while (same_name_hfinfo) {
8937 if (_ftype_common(hfinfo->type) != _ftype_common(same_name_hfinfo->type))
8938 ws_warning("'%s' exists multiple times with incompatible types: %s and %s", hfinfo->abbrev, ftype_name(hfinfo->type), ftype_name(same_name_hfinfo->type));
8939 same_name_hfinfo = same_name_hfinfo->same_name_next;
8940 }
8941 #endif
8942 }
8943 }
8944
8945 return hfinfo->id;
8946 }
8947
8948 void
proto_register_subtree_array(gint * const * indices,const int num_indices)8949 proto_register_subtree_array(gint * const *indices, const int num_indices)
8950 {
8951 int i;
8952 gint *const *ptr = indices;
8953
8954 /*
8955 * If we've already allocated the array of tree types, expand
8956 * it; this lets plugins such as mate add tree types after
8957 * the initial startup. (If we haven't already allocated it,
8958 * we don't allocate it; on the first pass, we just assign
8959 * ett values and keep track of how many we've assigned, and
8960 * when we're finished registering all dissectors we allocate
8961 * the array, so that we do only one allocation rather than
8962 * wasting CPU time and memory by growing the array for each
8963 * dissector that registers ett values.)
8964 */
8965 if (tree_is_expanded != NULL) {
8966 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
8967
8968 /* set new items to 0 */
8969 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
8970 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
8971 tree_is_expanded[i >> 5] &= ~(1U << (i & 31));
8972 }
8973
8974 /*
8975 * Assign "num_indices" subtree numbers starting at "num_tree_types",
8976 * returning the indices through the pointers in the array whose
8977 * first element is pointed to by "indices", and update
8978 * "num_tree_types" appropriately.
8979 */
8980 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
8981 if (**ptr != -1) {
8982 /* ws_error will terminate the program */
8983 ws_error("register_subtree_array: subtree item type (ett_...) not -1 !"
8984 " This is a development error:"
8985 " Either the subtree item type has already been assigned or"
8986 " was not initialized to -1.");
8987 }
8988 **ptr = num_tree_types;
8989 }
8990 }
8991
8992 static inline gsize
label_concat(char * label_str,gsize pos,const char * str)8993 label_concat(char *label_str, gsize pos, const char *str)
8994 {
8995 if (pos < ITEM_LABEL_LENGTH)
8996 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
8997
8998 return pos;
8999 }
9000
9001 static void
label_mark_truncated(char * label_str,gsize name_pos)9002 label_mark_truncated(char *label_str, gsize name_pos)
9003 {
9004 static const char trunc_str[] = " [truncated]";
9005 const size_t trunc_len = sizeof(trunc_str)-1;
9006 gchar *last_char;
9007
9008 /* ..... field_name: dataaaaaaaaaaaaa
9009 * |
9010 * ^^^^^ name_pos
9011 *
9012 * ..... field_name [truncated]: dataaaaaaaaaaaaa
9013 *
9014 * name_pos==0 means that we have only data or only a field_name
9015 */
9016
9017 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
9018 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
9019 memcpy(label_str + name_pos, trunc_str, trunc_len);
9020
9021 /* in general, label_str is UTF-8
9022 we can truncate it only at the beginning of a new character
9023 we go backwards from the byte right after our buffer and
9024 find the next starting byte of a UTF-8 character, this is
9025 where we cut
9026 there's no need to use g_utf8_find_prev_char(), the search
9027 will always succeed since we copied trunc_str into the
9028 buffer */
9029 last_char = g_utf8_prev_char(&label_str[ITEM_LABEL_LENGTH - 1]);
9030 *last_char = '\0';
9031
9032 } else if (name_pos < ITEM_LABEL_LENGTH)
9033 (void) g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
9034 }
9035
9036 static gsize
label_fill(char * label_str,gsize pos,const header_field_info * hfinfo,const char * text)9037 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
9038 {
9039 gsize name_pos;
9040
9041 /* "%s: %s", hfinfo->name, text */
9042 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
9043 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
9044 pos = label_concat(label_str, pos, ": ");
9045 pos = label_concat(label_str, pos, text ? text : "(null)");
9046 }
9047
9048 if (pos >= ITEM_LABEL_LENGTH) {
9049 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9050 label_mark_truncated(label_str, name_pos);
9051 }
9052
9053 return pos;
9054 }
9055
9056 static gsize
label_fill_descr(char * label_str,gsize pos,const header_field_info * hfinfo,const char * text,const char * descr)9057 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
9058 {
9059 gsize name_pos;
9060
9061 /* "%s: %s (%s)", hfinfo->name, text, descr */
9062 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
9063 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
9064 pos = label_concat(label_str, pos, ": ");
9065 if (hfinfo->display & BASE_UNIT_STRING) {
9066 pos = label_concat(label_str, pos, descr ? descr : "(null)");
9067 pos = label_concat(label_str, pos, text ? text : "(null)");
9068 } else {
9069 pos = label_concat(label_str, pos, text ? text : "(null)");
9070 pos = label_concat(label_str, pos, " (");
9071 pos = label_concat(label_str, pos, descr ? descr : "(null)");
9072 pos = label_concat(label_str, pos, ")");
9073 }
9074 }
9075
9076 if (pos >= ITEM_LABEL_LENGTH) {
9077 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9078 label_mark_truncated(label_str, name_pos);
9079 }
9080
9081 return pos;
9082 }
9083
9084 void
proto_item_fill_label(field_info * fi,gchar * label_str)9085 proto_item_fill_label(field_info *fi, gchar *label_str)
9086 {
9087 header_field_info *hfinfo;
9088 guint8 *bytes;
9089 guint32 integer;
9090 guint64 integer64;
9091 ws_in4_addr ipv4;
9092 e_guid_t *guid;
9093 gchar *name;
9094 address addr;
9095 char *addr_str;
9096 char *tmp;
9097
9098 if (!fi) {
9099 if (label_str)
9100 label_str[0]= '\0';
9101 /* XXX: Check validity of hfinfo->type */
9102 return;
9103 }
9104
9105 hfinfo = fi->hfinfo;
9106
9107 switch (hfinfo->type) {
9108 case FT_NONE:
9109 case FT_PROTOCOL:
9110 (void) g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
9111 break;
9112
9113 case FT_BOOLEAN:
9114 fill_label_boolean(fi, label_str);
9115 break;
9116
9117 case FT_BYTES:
9118 case FT_UINT_BYTES:
9119 tmp = hfinfo_format_bytes(NULL, hfinfo,
9120 (guint8 *)fvalue_get(&fi->value),
9121 fvalue_length(&fi->value));
9122 label_fill(label_str, 0, hfinfo, tmp);
9123 wmem_free(NULL, tmp);
9124 break;
9125
9126 case FT_CHAR:
9127 if (hfinfo->bitmask) {
9128 fill_label_bitfield_char(fi, label_str);
9129 } else {
9130 fill_label_char(fi, label_str);
9131 }
9132 break;
9133
9134 /* Four types of integers to take care of:
9135 * Bitfield, with val_string
9136 * Bitfield, w/o val_string
9137 * Non-bitfield, with val_string
9138 * Non-bitfield, w/o val_string
9139 */
9140 case FT_UINT8:
9141 case FT_UINT16:
9142 case FT_UINT24:
9143 case FT_UINT32:
9144 if (hfinfo->bitmask) {
9145 if (fi->flags & FI_VARINT) {
9146 fill_label_bitfield_varint(fi, label_str, FALSE);
9147 } else {
9148 fill_label_bitfield(fi, label_str, FALSE);
9149 }
9150 } else {
9151 fill_label_number(fi, label_str, FALSE);
9152 }
9153 break;
9154
9155 case FT_FRAMENUM:
9156 fill_label_number(fi, label_str, FALSE);
9157 break;
9158
9159 case FT_UINT40:
9160 case FT_UINT48:
9161 case FT_UINT56:
9162 case FT_UINT64:
9163 if (hfinfo->bitmask) {
9164 if (fi->flags & FI_VARINT) {
9165 fill_label_bitfield_varint64(fi, label_str, FALSE);
9166 } else {
9167 fill_label_bitfield64(fi, label_str, FALSE);
9168 }
9169 } else {
9170 fill_label_number64(fi, label_str, FALSE);
9171 }
9172 break;
9173
9174 case FT_INT8:
9175 case FT_INT16:
9176 case FT_INT24:
9177 case FT_INT32:
9178 if (hfinfo->bitmask) {
9179 if (fi->flags & FI_VARINT) {
9180 fill_label_bitfield_varint(fi, label_str, TRUE);
9181 } else {
9182 fill_label_bitfield(fi, label_str, TRUE);
9183 }
9184 } else {
9185 fill_label_number(fi, label_str, TRUE);
9186 }
9187 break;
9188
9189 case FT_INT40:
9190 case FT_INT48:
9191 case FT_INT56:
9192 case FT_INT64:
9193 if (hfinfo->bitmask) {
9194 if (fi->flags & FI_VARINT) {
9195 fill_label_bitfield_varint64(fi, label_str, TRUE);
9196 } else {
9197 fill_label_bitfield64(fi, label_str, TRUE);
9198 }
9199 } else {
9200 fill_label_number64(fi, label_str, TRUE);
9201 }
9202 break;
9203
9204 case FT_FLOAT:
9205 {
9206 double d_value = fvalue_get_floating(&fi->value);
9207 if (hfinfo->display & BASE_UNIT_STRING) {
9208 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9209 "%s: %." G_STRINGIFY(FLT_DIG) "g%s",
9210 hfinfo->name, d_value,
9211 unit_name_string_get_double(d_value, (const unit_name_string*)hfinfo->strings));
9212 } else {
9213 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9214 "%s: %." G_STRINGIFY(FLT_DIG) "g",
9215 hfinfo->name, d_value);
9216 }
9217 break;
9218 }
9219
9220 case FT_DOUBLE:
9221 {
9222 double d_value = fvalue_get_floating(&fi->value);
9223 if (hfinfo->display & BASE_UNIT_STRING) {
9224 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9225 "%s: %." G_STRINGIFY(DBL_DIG) "g%s",
9226 hfinfo->name, d_value,
9227 unit_name_string_get_double(d_value, (const unit_name_string*)hfinfo->strings));
9228 } else {
9229 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9230 "%s: %." G_STRINGIFY(DBL_DIG) "g",
9231 hfinfo->name, d_value);
9232 }
9233 break;
9234 }
9235
9236 case FT_ABSOLUTE_TIME:
9237 tmp = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&fi->value), (absolute_time_display_e)hfinfo->display, TRUE);
9238 label_fill(label_str, 0, hfinfo, tmp);
9239 wmem_free(NULL, tmp);
9240 break;
9241
9242 case FT_RELATIVE_TIME:
9243 tmp = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&fi->value));
9244 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9245 "%s: %s seconds", hfinfo->name, tmp);
9246 wmem_free(NULL, tmp);
9247 break;
9248
9249 case FT_IPXNET:
9250 integer = fvalue_get_uinteger(&fi->value);
9251 tmp = get_ipxnet_name(NULL, integer);
9252 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9253 "%s: %s (0x%08X)", hfinfo->name,
9254 tmp, integer);
9255 wmem_free(NULL, tmp);
9256 break;
9257
9258 case FT_AX25:
9259 addr.type = AT_AX25;
9260 addr.len = AX25_ADDR_LEN;
9261 addr.data = (guint8 *)fvalue_get(&fi->value);
9262
9263 addr_str = (char*)address_to_str(NULL, &addr);
9264 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9265 "%s: %s", hfinfo->name, addr_str);
9266 wmem_free(NULL, addr_str);
9267 break;
9268
9269 case FT_VINES:
9270 addr.type = AT_VINES;
9271 addr.len = VINES_ADDR_LEN;
9272 addr.data = (guint8 *)fvalue_get(&fi->value);
9273
9274 addr_str = (char*)address_to_str(NULL, &addr);
9275 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9276 "%s: %s", hfinfo->name, addr_str);
9277 wmem_free(NULL, addr_str);
9278 break;
9279
9280 case FT_ETHER:
9281 bytes = (guint8 *)fvalue_get(&fi->value);
9282
9283 addr.type = AT_ETHER;
9284 addr.len = 6;
9285 addr.data = bytes;
9286
9287 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
9288 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9289 "%s: %s", hfinfo->name, addr_str);
9290 wmem_free(NULL, addr_str);
9291 break;
9292
9293 case FT_IPv4:
9294 ipv4 = fvalue_get_uinteger(&fi->value);
9295
9296 addr.type = AT_IPv4;
9297 addr.len = 4;
9298 addr.data = &ipv4;
9299
9300 if (hfinfo->display == BASE_NETMASK) {
9301 addr_str = (char*)address_to_str(NULL, &addr);
9302 } else {
9303 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
9304 }
9305 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9306 "%s: %s", hfinfo->name, addr_str);
9307 wmem_free(NULL, addr_str);
9308 break;
9309
9310 case FT_IPv6:
9311 bytes = (guint8 *)fvalue_get(&fi->value);
9312
9313 addr.type = AT_IPv6;
9314 addr.len = 16;
9315 addr.data = bytes;
9316
9317 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
9318 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9319 "%s: %s", hfinfo->name, addr_str);
9320 wmem_free(NULL, addr_str);
9321 break;
9322
9323 case FT_FCWWN:
9324 addr.type = AT_FCWWN;
9325 addr.len = FCWWN_ADDR_LEN;
9326 addr.data = (guint8 *)fvalue_get(&fi->value);
9327
9328 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
9329 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9330 "%s: %s", hfinfo->name, addr_str);
9331 wmem_free(NULL, addr_str);
9332 break;
9333
9334 case FT_GUID:
9335 guid = (e_guid_t *)fvalue_get(&fi->value);
9336 tmp = guid_to_str(NULL, guid);
9337 label_fill(label_str, 0, hfinfo, tmp);
9338 wmem_free(NULL, tmp);
9339 break;
9340
9341 case FT_OID:
9342 bytes = (guint8 *)fvalue_get(&fi->value);
9343 name = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
9344 tmp = oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
9345 if (name) {
9346 label_fill_descr(label_str, 0, hfinfo, tmp, name);
9347 wmem_free(NULL, name);
9348 } else {
9349 label_fill(label_str, 0, hfinfo, tmp);
9350 }
9351 wmem_free(NULL, tmp);
9352 break;
9353
9354 case FT_REL_OID:
9355 bytes = (guint8 *)fvalue_get(&fi->value);
9356 name = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
9357 tmp = rel_oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
9358 if (name) {
9359 label_fill_descr(label_str, 0, hfinfo, tmp, name);
9360 wmem_free(NULL, name);
9361 } else {
9362 label_fill(label_str, 0, hfinfo, tmp);
9363 }
9364 wmem_free(NULL, tmp);
9365 break;
9366
9367 case FT_SYSTEM_ID:
9368 bytes = (guint8 *)fvalue_get(&fi->value);
9369 tmp = print_system_id(NULL, bytes, fvalue_length(&fi->value));
9370 label_fill(label_str, 0, hfinfo, tmp);
9371 wmem_free(NULL, tmp);
9372 break;
9373
9374 case FT_EUI64:
9375 integer64 = fvalue_get_uinteger64(&fi->value);
9376 addr_str = eui64_to_str(NULL, integer64);
9377 tmp = (char*)eui64_to_display(NULL, integer64);
9378 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str);
9379 wmem_free(NULL, tmp);
9380 wmem_free(NULL, addr_str);
9381 break;
9382 case FT_STRING:
9383 case FT_STRINGZ:
9384 case FT_UINT_STRING:
9385 case FT_STRINGZPAD:
9386 case FT_STRINGZTRUNC:
9387 bytes = (guint8 *)fvalue_get(&fi->value);
9388 tmp = hfinfo_format_text(NULL, hfinfo, bytes);
9389 label_fill(label_str, 0, hfinfo, tmp);
9390 wmem_free(NULL, tmp);
9391 break;
9392
9393 case FT_IEEE_11073_SFLOAT:
9394 case FT_IEEE_11073_FLOAT:
9395 tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
9396 g_snprintf(label_str, ITEM_LABEL_LENGTH,
9397 "%s: %s",
9398 hfinfo->name, tmp);
9399 wmem_free(NULL, tmp);
9400 break;
9401
9402 default:
9403 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_fill_label()",
9404 hfinfo->abbrev,
9405 hfinfo->type,
9406 ftype_name(hfinfo->type));
9407 break;
9408 }
9409 }
9410
9411 static void
fill_label_boolean(field_info * fi,gchar * label_str)9412 fill_label_boolean(field_info *fi, gchar *label_str)
9413 {
9414 char *p = label_str;
9415 int bitfield_byte_length = 0, bitwidth;
9416 guint64 unshifted_value;
9417 guint64 value;
9418
9419 header_field_info *hfinfo = fi->hfinfo;
9420 const true_false_string *tfstring = &tfs_true_false;
9421
9422 if (hfinfo->strings) {
9423 tfstring = (const struct true_false_string*) hfinfo->strings;
9424 }
9425
9426 value = fvalue_get_uinteger64(&fi->value);
9427 if (hfinfo->bitmask) {
9428 /* Figure out the bit width */
9429 bitwidth = hfinfo_container_bitwidth(hfinfo);
9430
9431 /* Un-shift bits */
9432 unshifted_value = value;
9433 unshifted_value <<= hfinfo_bitshift(hfinfo);
9434
9435 /* Create the bitfield first */
9436 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
9437 bitfield_byte_length = (int) (p - label_str);
9438 }
9439
9440 /* Fill in the textual info */
9441 label_fill(label_str, bitfield_byte_length, hfinfo, tfs_get_string(!!value, tfstring));
9442 }
9443
9444 static const char *
hf_try_val_to_str(guint32 value,const header_field_info * hfinfo)9445 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
9446 {
9447 if (hfinfo->display & BASE_RANGE_STRING)
9448 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
9449
9450 if (hfinfo->display & BASE_EXT_STRING) {
9451 if (hfinfo->display & BASE_VAL64_STRING)
9452 return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
9453 else
9454 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
9455 }
9456
9457 if (hfinfo->display & BASE_VAL64_STRING)
9458 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
9459
9460 if (hfinfo->display & BASE_UNIT_STRING)
9461 return unit_name_string_get_value(value, (const struct unit_name_string*) hfinfo->strings);
9462
9463 return try_val_to_str(value, (const value_string *) hfinfo->strings);
9464 }
9465
9466 static const char *
hf_try_val64_to_str(guint64 value,const header_field_info * hfinfo)9467 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
9468 {
9469 if (hfinfo->display & BASE_VAL64_STRING) {
9470 if (hfinfo->display & BASE_EXT_STRING)
9471 return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
9472 else
9473 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
9474 }
9475
9476 if (hfinfo->display & BASE_RANGE_STRING)
9477 return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
9478
9479 if (hfinfo->display & BASE_UNIT_STRING)
9480 return unit_name_string_get_value64(value, (const struct unit_name_string*) hfinfo->strings);
9481
9482 /* If this is reached somebody registered a 64-bit field with a 32-bit
9483 * value-string, which isn't right. */
9484 REPORT_DISSECTOR_BUG("field %s is a 64-bit field with a 32-bit value_string",
9485 hfinfo->abbrev);
9486
9487 /* This is necessary to squelch MSVC errors; is there
9488 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
9489 never returns? */
9490 return NULL;
9491 }
9492
9493 static const char *
hf_try_val_to_str_const(guint32 value,const header_field_info * hfinfo,const char * unknown_str)9494 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
9495 {
9496 const char *str = hf_try_val_to_str(value, hfinfo);
9497
9498 return (str) ? str : unknown_str;
9499 }
9500
9501 static const char *
hf_try_val64_to_str_const(guint64 value,const header_field_info * hfinfo,const char * unknown_str)9502 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
9503 {
9504 const char *str = hf_try_val64_to_str(value, hfinfo);
9505
9506 return (str) ? str : unknown_str;
9507 }
9508
9509 /* Fills data for bitfield chars with val_strings */
9510 static void
fill_label_bitfield_char(field_info * fi,gchar * label_str)9511 fill_label_bitfield_char(field_info *fi, gchar *label_str)
9512 {
9513 char *p;
9514 int bitfield_byte_length, bitwidth;
9515 guint32 unshifted_value;
9516 guint32 value;
9517
9518 char buf[32];
9519 const char *out;
9520
9521 header_field_info *hfinfo = fi->hfinfo;
9522
9523 /* Figure out the bit width */
9524 bitwidth = hfinfo_container_bitwidth(hfinfo);
9525
9526 /* Un-shift bits */
9527 value = fvalue_get_uinteger(&fi->value);
9528
9529 unshifted_value = value;
9530 if (hfinfo->bitmask) {
9531 unshifted_value <<= hfinfo_bitshift(hfinfo);
9532 }
9533
9534 /* Create the bitfield first */
9535 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
9536 bitfield_byte_length = (int) (p - label_str);
9537
9538 /* Fill in the textual info using stored (shifted) value */
9539 if (hfinfo->display == BASE_CUSTOM) {
9540 gchar tmp[ITEM_LABEL_LENGTH];
9541 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
9542
9543 DISSECTOR_ASSERT(fmtfunc);
9544 fmtfunc(tmp, value);
9545 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
9546 }
9547 else if (hfinfo->strings) {
9548 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
9549
9550 out = hfinfo_char_vals_format(hfinfo, buf, value);
9551 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9552 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
9553 else
9554 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
9555 }
9556 else {
9557 out = hfinfo_char_value_format(hfinfo, buf, value);
9558
9559 label_fill(label_str, bitfield_byte_length, hfinfo, out);
9560 }
9561 }
9562
9563 /* Fills data for bitfield ints with val_strings */
9564 static void
fill_label_bitfield(field_info * fi,gchar * label_str,gboolean is_signed)9565 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
9566 {
9567 char *p;
9568 int bitfield_byte_length, bitwidth;
9569 guint32 unshifted_value;
9570 guint32 value;
9571
9572 char buf[32];
9573 const char *out;
9574
9575 header_field_info *hfinfo = fi->hfinfo;
9576
9577 /* Figure out the bit width */
9578 bitwidth = hfinfo_container_bitwidth(hfinfo);
9579
9580 /* Un-shift bits */
9581 if (is_signed)
9582 value = fvalue_get_sinteger(&fi->value);
9583 else
9584 value = fvalue_get_uinteger(&fi->value);
9585
9586 unshifted_value = value;
9587 if (hfinfo->bitmask) {
9588 unshifted_value <<= hfinfo_bitshift(hfinfo);
9589 }
9590
9591 /* Create the bitfield first */
9592 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
9593 bitfield_byte_length = (int) (p - label_str);
9594
9595 /* Fill in the textual info using stored (shifted) value */
9596 if (hfinfo->display == BASE_CUSTOM) {
9597 gchar tmp[ITEM_LABEL_LENGTH];
9598 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
9599
9600 DISSECTOR_ASSERT(fmtfunc);
9601 fmtfunc(tmp, value);
9602 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
9603 }
9604 else if (hfinfo->strings) {
9605 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
9606
9607 out = hfinfo_number_vals_format(hfinfo, buf, value);
9608 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9609 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
9610 else
9611 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
9612 }
9613 else {
9614 out = hfinfo_number_value_format(hfinfo, buf, value);
9615
9616 label_fill(label_str, bitfield_byte_length, hfinfo, out);
9617 }
9618 }
9619
9620 static void
fill_label_bitfield64(field_info * fi,gchar * label_str,gboolean is_signed)9621 fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed)
9622 {
9623 char *p;
9624 int bitfield_byte_length, bitwidth;
9625 guint64 unshifted_value;
9626 guint64 value;
9627
9628 char buf[48];
9629 const char *out;
9630
9631 header_field_info *hfinfo = fi->hfinfo;
9632
9633 /* Figure out the bit width */
9634 bitwidth = hfinfo_container_bitwidth(hfinfo);
9635
9636 /* Un-shift bits */
9637 if (is_signed)
9638 value = fvalue_get_sinteger64(&fi->value);
9639 else
9640 value = fvalue_get_uinteger64(&fi->value);
9641
9642 unshifted_value = value;
9643 if (hfinfo->bitmask) {
9644 unshifted_value <<= hfinfo_bitshift(hfinfo);
9645 }
9646
9647 /* Create the bitfield first */
9648 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
9649 bitfield_byte_length = (int) (p - label_str);
9650
9651 /* Fill in the textual info using stored (shifted) value */
9652 if (hfinfo->display == BASE_CUSTOM) {
9653 gchar tmp[ITEM_LABEL_LENGTH];
9654 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
9655
9656 DISSECTOR_ASSERT(fmtfunc64);
9657 fmtfunc64(tmp, value);
9658 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
9659 }
9660 else if (hfinfo->strings) {
9661 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
9662
9663 out = hfinfo_number_vals_format64(hfinfo, buf, value);
9664 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9665 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
9666 else
9667 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
9668 }
9669 else {
9670 out = hfinfo_number_value_format64(hfinfo, buf, value);
9671
9672 label_fill(label_str, bitfield_byte_length, hfinfo, out);
9673 }
9674 }
9675
9676 static void
fill_label_bitfield_varint(field_info * fi,gchar * label_str,gboolean is_signed)9677 fill_label_bitfield_varint(field_info *fi, gchar *label_str, gboolean is_signed)
9678 {
9679 char *p;
9680 int bitfield_byte_length;
9681 guint32 value, unshifted_value;
9682 char buf[48];
9683 const char *out;
9684
9685 header_field_info *hfinfo = fi->hfinfo;
9686
9687 /* Un-shift bits */
9688 if (is_signed) {
9689 value = fvalue_get_sinteger(&fi->value);
9690 } else {
9691 value = fvalue_get_uinteger(&fi->value);
9692 }
9693 unshifted_value = value;
9694 if (hfinfo->bitmask) {
9695 unshifted_value <<= hfinfo_bitshift(hfinfo);
9696 }
9697
9698 /* Create the bitfield first */
9699 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, fi->length*8);
9700 bitfield_byte_length = (int) (p - label_str);
9701
9702 /* Fill in the textual info using stored (shifted) value */
9703 if (hfinfo->display == BASE_CUSTOM) {
9704 gchar tmp[ITEM_LABEL_LENGTH];
9705 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
9706
9707 DISSECTOR_ASSERT(fmtfunc);
9708 fmtfunc(tmp, value);
9709 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
9710 }
9711 else if (hfinfo->strings) {
9712 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
9713
9714 out = hfinfo_number_vals_format(hfinfo, buf, value);
9715 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9716 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
9717 else
9718 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
9719 }
9720 else {
9721 out = hfinfo_number_value_format(hfinfo, buf, value);
9722
9723 label_fill(label_str, bitfield_byte_length, hfinfo, out);
9724 }
9725 }
9726
9727 static void
fill_label_bitfield_varint64(field_info * fi,gchar * label_str,gboolean is_signed)9728 fill_label_bitfield_varint64(field_info *fi, gchar *label_str, gboolean is_signed)
9729 {
9730 char *p;
9731 int bitfield_byte_length;
9732 guint64 unshifted_value;
9733 guint64 value;
9734
9735 char buf[48];
9736 const char *out;
9737
9738 header_field_info *hfinfo = fi->hfinfo;
9739
9740 /* Un-shift bits */
9741 if (is_signed) {
9742 value = fvalue_get_sinteger64(&fi->value);
9743 } else {
9744 value = fvalue_get_uinteger64(&fi->value);
9745 }
9746 unshifted_value = value;
9747 if (hfinfo->bitmask) {
9748 unshifted_value <<= hfinfo_bitshift(hfinfo);
9749 }
9750
9751 /* Create the bitfield first */
9752 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, fi->length*8);
9753 bitfield_byte_length = (int) (p - label_str);
9754
9755 /* Fill in the textual info using stored (shifted) value */
9756 if (hfinfo->display == BASE_CUSTOM) {
9757 gchar tmp[ITEM_LABEL_LENGTH];
9758 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
9759
9760 DISSECTOR_ASSERT(fmtfunc64);
9761 fmtfunc64(tmp, value);
9762 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
9763 }
9764 else if (hfinfo->strings) {
9765 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
9766
9767 out = hfinfo_number_vals_format64(hfinfo, buf, value);
9768 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9769 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
9770 else
9771 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
9772 }
9773 else {
9774 out = hfinfo_number_value_format64(hfinfo, buf, value);
9775
9776 label_fill(label_str, bitfield_byte_length, hfinfo, out);
9777 }
9778 }
9779
9780 static void
fill_label_char(field_info * fi,gchar * label_str)9781 fill_label_char(field_info *fi, gchar *label_str)
9782 {
9783 header_field_info *hfinfo = fi->hfinfo;
9784 guint32 value;
9785
9786 char buf[32];
9787 const char *out;
9788
9789 value = fvalue_get_uinteger(&fi->value);
9790
9791 /* Fill in the textual info */
9792 if (hfinfo->display == BASE_CUSTOM) {
9793 gchar tmp[ITEM_LABEL_LENGTH];
9794 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
9795
9796 DISSECTOR_ASSERT(fmtfunc);
9797 fmtfunc(tmp, value);
9798 label_fill(label_str, 0, hfinfo, tmp);
9799 }
9800 else if (hfinfo->strings) {
9801 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
9802
9803 out = hfinfo_char_vals_format(hfinfo, buf, value);
9804 label_fill_descr(label_str, 0, hfinfo, val_str, out);
9805 }
9806 else {
9807 out = hfinfo_char_value_format(hfinfo, buf, value);
9808
9809 label_fill(label_str, 0, hfinfo, out);
9810 }
9811 }
9812
9813 static void
fill_label_number(field_info * fi,gchar * label_str,gboolean is_signed)9814 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
9815 {
9816 header_field_info *hfinfo = fi->hfinfo;
9817 guint32 value;
9818
9819 char buf[32];
9820 const char *out;
9821
9822 if (is_signed)
9823 value = fvalue_get_sinteger(&fi->value);
9824 else
9825 value = fvalue_get_uinteger(&fi->value);
9826
9827 /* Fill in the textual info */
9828 if (hfinfo->display == BASE_CUSTOM) {
9829 gchar tmp[ITEM_LABEL_LENGTH];
9830 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
9831
9832 DISSECTOR_ASSERT(fmtfunc);
9833 fmtfunc(tmp, value);
9834 label_fill(label_str, 0, hfinfo, tmp);
9835 }
9836 else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
9837 /*
9838 * It makes no sense to have a value-string table for a
9839 * frame-number field - they're just integers giving
9840 * the ordinal frame number.
9841 */
9842 const char *val_str = hf_try_val_to_str(value, hfinfo);
9843
9844 out = hfinfo_number_vals_format(hfinfo, buf, value);
9845 if (hfinfo->display & BASE_SPECIAL_VALS) {
9846 /*
9847 * Unique values only display value_string string
9848 * if there is a match. Otherwise it's just a number
9849 */
9850 if (val_str) {
9851 label_fill_descr(label_str, 0, hfinfo, val_str, out);
9852 } else {
9853 label_fill(label_str, 0, hfinfo, out);
9854 }
9855 } else {
9856 if (val_str == NULL)
9857 val_str = "Unknown";
9858
9859 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9860 label_fill(label_str, 0, hfinfo, val_str);
9861 else
9862 label_fill_descr(label_str, 0, hfinfo, val_str, out);
9863 }
9864 }
9865 else if (IS_BASE_PORT(hfinfo->display)) {
9866 gchar tmp[ITEM_LABEL_LENGTH];
9867
9868 port_with_resolution_to_str_buf(tmp, sizeof(tmp),
9869 display_to_port_type((field_display_e)hfinfo->display), value);
9870 label_fill(label_str, 0, hfinfo, tmp);
9871 }
9872 else {
9873 out = hfinfo_number_value_format(hfinfo, buf, value);
9874
9875 label_fill(label_str, 0, hfinfo, out);
9876 }
9877 }
9878
9879 static void
fill_label_number64(field_info * fi,gchar * label_str,gboolean is_signed)9880 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
9881 {
9882 header_field_info *hfinfo = fi->hfinfo;
9883 guint64 value;
9884
9885 char buf[48];
9886 const char *out;
9887
9888 if (is_signed)
9889 value = fvalue_get_sinteger64(&fi->value);
9890 else
9891 value = fvalue_get_uinteger64(&fi->value);
9892
9893 /* Fill in the textual info */
9894 if (hfinfo->display == BASE_CUSTOM) {
9895 gchar tmp[ITEM_LABEL_LENGTH];
9896 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
9897
9898 DISSECTOR_ASSERT(fmtfunc64);
9899 fmtfunc64(tmp, value);
9900 label_fill(label_str, 0, hfinfo, tmp);
9901 }
9902 else if (hfinfo->strings) {
9903 const char *val_str = hf_try_val64_to_str(value, hfinfo);
9904
9905 out = hfinfo_number_vals_format64(hfinfo, buf, value);
9906 if (hfinfo->display & BASE_SPECIAL_VALS) {
9907 /*
9908 * Unique values only display value_string string
9909 * if there is a match. Otherwise it's just a number
9910 */
9911 if (val_str) {
9912 label_fill_descr(label_str, 0, hfinfo, val_str, out);
9913 } else {
9914 label_fill(label_str, 0, hfinfo, out);
9915 }
9916 } else {
9917 if (val_str == NULL)
9918 val_str = "Unknown";
9919
9920 if (out == NULL) /* BASE_NONE so don't put integer in descr */
9921 label_fill(label_str, 0, hfinfo, val_str);
9922 else
9923 label_fill_descr(label_str, 0, hfinfo, val_str, out);
9924 }
9925 }
9926 else {
9927 out = hfinfo_number_value_format64(hfinfo, buf, value);
9928
9929 label_fill(label_str, 0, hfinfo, out);
9930 }
9931 }
9932
9933 int
hfinfo_bitshift(const header_field_info * hfinfo)9934 hfinfo_bitshift(const header_field_info *hfinfo)
9935 {
9936 return ws_ctz(hfinfo->bitmask);
9937 }
9938
9939
9940 static int
hfinfo_bitoffset(const header_field_info * hfinfo)9941 hfinfo_bitoffset(const header_field_info *hfinfo)
9942 {
9943 if (!hfinfo->bitmask) {
9944 return 0;
9945 }
9946
9947 /* ilog2 = first set bit, counting 0 as the last bit; we want 0
9948 * as the first bit */
9949 return hfinfo_container_bitwidth(hfinfo) - 1 - ws_ilog2(hfinfo->bitmask);
9950 }
9951
9952 static int
hfinfo_mask_bitwidth(const header_field_info * hfinfo)9953 hfinfo_mask_bitwidth(const header_field_info *hfinfo)
9954 {
9955 if (!hfinfo->bitmask) {
9956 return 0;
9957 }
9958
9959 /* ilog2 = first set bit, ctz = last set bit */
9960 return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
9961 }
9962
9963 static int
hfinfo_type_bitwidth(enum ftenum type)9964 hfinfo_type_bitwidth(enum ftenum type)
9965 {
9966 int bitwidth = 0;
9967
9968 switch (type) {
9969 case FT_CHAR:
9970 case FT_UINT8:
9971 case FT_INT8:
9972 bitwidth = 8;
9973 break;
9974 case FT_UINT16:
9975 case FT_INT16:
9976 bitwidth = 16;
9977 break;
9978 case FT_UINT24:
9979 case FT_INT24:
9980 bitwidth = 24;
9981 break;
9982 case FT_UINT32:
9983 case FT_INT32:
9984 bitwidth = 32;
9985 break;
9986 case FT_UINT40:
9987 case FT_INT40:
9988 bitwidth = 40;
9989 break;
9990 case FT_UINT48:
9991 case FT_INT48:
9992 bitwidth = 48;
9993 break;
9994 case FT_UINT56:
9995 case FT_INT56:
9996 bitwidth = 56;
9997 break;
9998 case FT_UINT64:
9999 case FT_INT64:
10000 bitwidth = 64;
10001 break;
10002 default:
10003 DISSECTOR_ASSERT_NOT_REACHED();
10004 ;
10005 }
10006 return bitwidth;
10007 }
10008
10009
10010 static int
hfinfo_container_bitwidth(const header_field_info * hfinfo)10011 hfinfo_container_bitwidth(const header_field_info *hfinfo)
10012 {
10013 if (!hfinfo->bitmask) {
10014 return 0;
10015 }
10016
10017 if (hfinfo->type == FT_BOOLEAN) {
10018 return hfinfo->display; /* hacky? :) */
10019 }
10020
10021 return hfinfo_type_bitwidth(hfinfo->type);
10022 }
10023
10024 static int
hfinfo_hex_digits(const header_field_info * hfinfo)10025 hfinfo_hex_digits(const header_field_info *hfinfo)
10026 {
10027 int bitwidth;
10028
10029 /* If we have a bitmask, hfinfo->type is the width of the container, so not
10030 * appropriate to determine the number of hex digits for the field.
10031 * So instead, we compute it from the bitmask.
10032 */
10033 if (hfinfo->bitmask != 0) {
10034 bitwidth = hfinfo_mask_bitwidth(hfinfo);
10035 } else {
10036 bitwidth = hfinfo_type_bitwidth(hfinfo->type);
10037 }
10038
10039 /* Divide by 4, rounding up, to get number of hex digits. */
10040 return (bitwidth + 3) / 4;
10041 }
10042
10043 static const char *
hfinfo_char_value_format_display(int display,char buf[7],guint32 value)10044 hfinfo_char_value_format_display(int display, char buf[7], guint32 value)
10045 {
10046 char *ptr = &buf[6];
10047 static const gchar hex_digits[16] =
10048 { '0', '1', '2', '3', '4', '5', '6', '7',
10049 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
10050
10051 *ptr = '\0';
10052 *(--ptr) = '\'';
10053 /* Properly format value */
10054 if (g_ascii_isprint(value)) {
10055 /*
10056 * Printable, so just show the character, and, if it needs
10057 * to be escaped, escape it.
10058 */
10059 *(--ptr) = value;
10060 if (value == '\\' || value == '\'')
10061 *(--ptr) = '\\';
10062 } else {
10063 /*
10064 * Non-printable; show it as an escape sequence.
10065 */
10066 switch (value) {
10067
10068 case '\0':
10069 /*
10070 * Show a NUL with only one digit.
10071 */
10072 *(--ptr) = '0';
10073 break;
10074
10075 case '\a':
10076 *(--ptr) = 'a';
10077 break;
10078
10079 case '\b':
10080 *(--ptr) = 'b';
10081 break;
10082
10083 case '\f':
10084 *(--ptr) = 'f';
10085 break;
10086
10087 case '\n':
10088 *(--ptr) = 'n';
10089 break;
10090
10091 case '\r':
10092 *(--ptr) = 'r';
10093 break;
10094
10095 case '\t':
10096 *(--ptr) = 't';
10097 break;
10098
10099 case '\v':
10100 *(--ptr) = 'v';
10101 break;
10102
10103 default:
10104 switch (FIELD_DISPLAY(display)) {
10105
10106 case BASE_OCT:
10107 *(--ptr) = (value & 0x7) + '0';
10108 value >>= 3;
10109 *(--ptr) = (value & 0x7) + '0';
10110 value >>= 3;
10111 *(--ptr) = (value & 0x7) + '0';
10112 break;
10113
10114 case BASE_HEX:
10115 *(--ptr) = hex_digits[value & 0x0F];
10116 value >>= 4;
10117 *(--ptr) = hex_digits[value & 0x0F];
10118 *(--ptr) = 'x';
10119 break;
10120
10121 default:
10122 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
10123 }
10124 }
10125 *(--ptr) = '\\';
10126 }
10127 *(--ptr) = '\'';
10128 return ptr;
10129 }
10130
10131 static const char *
hfinfo_number_value_format_display(const header_field_info * hfinfo,int display,char buf[32],guint32 value)10132 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
10133 {
10134 char *ptr = &buf[31];
10135 gboolean isint = IS_FT_INT(hfinfo->type);
10136
10137 *ptr = '\0';
10138 /* Properly format value */
10139 switch (FIELD_DISPLAY(display)) {
10140 case BASE_DEC:
10141 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
10142
10143 case BASE_DEC_HEX:
10144 *(--ptr) = ')';
10145 ptr = hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10146 *(--ptr) = '(';
10147 *(--ptr) = ' ';
10148 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
10149 return ptr;
10150
10151 case BASE_OCT:
10152 return oct_to_str_back(ptr, value);
10153
10154 case BASE_HEX:
10155 return hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10156
10157 case BASE_HEX_DEC:
10158 *(--ptr) = ')';
10159 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
10160 *(--ptr) = '(';
10161 *(--ptr) = ' ';
10162 ptr = hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10163 return ptr;
10164
10165 case BASE_PT_UDP:
10166 case BASE_PT_TCP:
10167 case BASE_PT_DCCP:
10168 case BASE_PT_SCTP:
10169 port_with_resolution_to_str_buf(buf, 32,
10170 display_to_port_type((field_display_e)display), value);
10171 return buf;
10172 case BASE_OUI:
10173 {
10174 guint8 p_oui[3];
10175 const gchar *manuf_name;
10176
10177 p_oui[0] = value >> 16 & 0xFF;
10178 p_oui[1] = value >> 8 & 0xFF;
10179 p_oui[2] = value & 0xFF;
10180
10181 /* Attempt an OUI lookup. */
10182 manuf_name = uint_get_manuf_name_if_known(value);
10183 if (manuf_name == NULL) {
10184 /* Could not find an OUI. */
10185 g_snprintf(buf, 32, "%02x:%02x:%02x", p_oui[0], p_oui[1], p_oui[2]);
10186 }
10187 else {
10188 /* Found an address string. */
10189 g_snprintf(buf, 32, "%02x:%02x:%02x (%s)", p_oui[0], p_oui[1], p_oui[2], manuf_name);
10190 }
10191 return buf;
10192 }
10193
10194 default:
10195 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
10196 }
10197 return ptr;
10198 }
10199
10200 static const char *
hfinfo_number_value_format_display64(const header_field_info * hfinfo,int display,char buf[48],guint64 value)10201 hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value)
10202 {
10203 char *ptr = &buf[47];
10204 gboolean isint = IS_FT_INT(hfinfo->type);
10205
10206 *ptr = '\0';
10207 /* Properly format value */
10208 switch (FIELD_DISPLAY(display)) {
10209 case BASE_DEC:
10210 return isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
10211
10212 case BASE_DEC_HEX:
10213 *(--ptr) = ')';
10214 ptr = hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10215 *(--ptr) = '(';
10216 *(--ptr) = ' ';
10217 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
10218 return ptr;
10219
10220 case BASE_OCT:
10221 return oct64_to_str_back(ptr, value);
10222
10223 case BASE_HEX:
10224 return hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10225
10226 case BASE_HEX_DEC:
10227 *(--ptr) = ')';
10228 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
10229 *(--ptr) = '(';
10230 *(--ptr) = ' ';
10231 ptr = hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10232 return ptr;
10233
10234 default:
10235 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
10236 }
10237
10238 return ptr;
10239 }
10240
10241 static const char *
hfinfo_number_value_format(const header_field_info * hfinfo,char buf[32],guint32 value)10242 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
10243 {
10244 int display = hfinfo->display;
10245
10246 if (hfinfo->type == FT_FRAMENUM) {
10247 /*
10248 * Frame numbers are always displayed in decimal.
10249 */
10250 display = BASE_DEC;
10251 }
10252
10253 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
10254 }
10255
10256 static const char *
hfinfo_number_value_format64(const header_field_info * hfinfo,char buf[48],guint64 value)10257 hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value)
10258 {
10259 int display = hfinfo->display;
10260
10261 if (hfinfo->type == FT_FRAMENUM) {
10262 /*
10263 * Frame numbers are always displayed in decimal.
10264 */
10265 display = BASE_DEC;
10266 }
10267
10268 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
10269 }
10270
10271 static const char *
hfinfo_char_value_format(const header_field_info * hfinfo,char buf[32],guint32 value)10272 hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
10273 {
10274 /* Get the underlying BASE_ value */
10275 int display = FIELD_DISPLAY(hfinfo->display);
10276
10277 return hfinfo_char_value_format_display(display, buf, value);
10278 }
10279
10280 static const char *
hfinfo_numeric_value_format(const header_field_info * hfinfo,char buf[32],guint32 value)10281 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
10282 {
10283 /* Get the underlying BASE_ value */
10284 int display = FIELD_DISPLAY(hfinfo->display);
10285
10286 if (hfinfo->type == FT_FRAMENUM) {
10287 /*
10288 * Frame numbers are always displayed in decimal.
10289 */
10290 display = BASE_DEC;
10291 }
10292
10293 if (IS_BASE_PORT(display)) {
10294 display = BASE_DEC;
10295 } else if (display == BASE_OUI) {
10296 display = BASE_HEX;
10297 }
10298
10299 switch (display) {
10300 case BASE_NONE:
10301 /* case BASE_DEC: */
10302 case BASE_DEC_HEX:
10303 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
10304 case BASE_CUSTOM:
10305 display = BASE_DEC;
10306 break;
10307
10308 /* case BASE_HEX: */
10309 case BASE_HEX_DEC:
10310 display = BASE_HEX;
10311 break;
10312 }
10313
10314 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
10315 }
10316
10317 static const char *
hfinfo_numeric_value_format64(const header_field_info * hfinfo,char buf[48],guint64 value)10318 hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value)
10319 {
10320 /* Get the underlying BASE_ value */
10321 int display = FIELD_DISPLAY(hfinfo->display);
10322
10323 if (hfinfo->type == FT_FRAMENUM) {
10324 /*
10325 * Frame numbers are always displayed in decimal.
10326 */
10327 display = BASE_DEC;
10328 }
10329
10330 switch (display) {
10331 case BASE_NONE:
10332 /* case BASE_DEC: */
10333 case BASE_DEC_HEX:
10334 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
10335 case BASE_CUSTOM:
10336 display = BASE_DEC;
10337 break;
10338
10339 /* case BASE_HEX: */
10340 case BASE_HEX_DEC:
10341 display = BASE_HEX;
10342 break;
10343 }
10344
10345 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
10346 }
10347
10348 static const char *
hfinfo_char_vals_format(const header_field_info * hfinfo,char buf[32],guint32 value)10349 hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
10350 {
10351 /* Get the underlying BASE_ value */
10352 int display = FIELD_DISPLAY(hfinfo->display);
10353
10354 return hfinfo_char_value_format_display(display, buf, value);
10355 }
10356
10357 static const char *
hfinfo_number_vals_format(const header_field_info * hfinfo,char buf[32],guint32 value)10358 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
10359 {
10360 /* Get the underlying BASE_ value */
10361 int display = FIELD_DISPLAY(hfinfo->display);
10362
10363 if (display == BASE_NONE)
10364 return NULL;
10365
10366 if (display == BASE_DEC_HEX)
10367 display = BASE_DEC;
10368 if (display == BASE_HEX_DEC)
10369 display = BASE_HEX;
10370
10371 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
10372 }
10373
10374 static const char *
hfinfo_number_vals_format64(const header_field_info * hfinfo,char buf[48],guint64 value)10375 hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[48], guint64 value)
10376 {
10377 /* Get the underlying BASE_ value */
10378 int display = FIELD_DISPLAY(hfinfo->display);
10379
10380 if (display == BASE_NONE)
10381 return NULL;
10382
10383 if (display == BASE_DEC_HEX)
10384 display = BASE_DEC;
10385 if (display == BASE_HEX_DEC)
10386 display = BASE_HEX;
10387
10388 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
10389 }
10390
10391 const char *
proto_registrar_get_name(const int n)10392 proto_registrar_get_name(const int n)
10393 {
10394 header_field_info *hfinfo;
10395
10396 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
10397 return hfinfo->name;
10398 }
10399
10400 const char *
proto_registrar_get_abbrev(const int n)10401 proto_registrar_get_abbrev(const int n)
10402 {
10403 header_field_info *hfinfo;
10404
10405 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
10406 return hfinfo->abbrev;
10407 }
10408
10409 enum ftenum
proto_registrar_get_ftype(const int n)10410 proto_registrar_get_ftype(const int n)
10411 {
10412 header_field_info *hfinfo;
10413
10414 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
10415 return hfinfo->type;
10416 }
10417
10418 int
proto_registrar_get_parent(const int n)10419 proto_registrar_get_parent(const int n)
10420 {
10421 header_field_info *hfinfo;
10422
10423 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
10424 return hfinfo->parent;
10425 }
10426
10427 gboolean
proto_registrar_is_protocol(const int n)10428 proto_registrar_is_protocol(const int n)
10429 {
10430 header_field_info *hfinfo;
10431
10432 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
10433 return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? TRUE : FALSE);
10434 }
10435
10436 /* Returns length of field in packet (not necessarily the length
10437 * in our internal representation, as in the case of IPv4).
10438 * 0 means undeterminable at time of registration
10439 * -1 means the field is not registered. */
10440 gint
proto_registrar_get_length(const int n)10441 proto_registrar_get_length(const int n)
10442 {
10443 header_field_info *hfinfo;
10444
10445 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
10446 return ftype_length(hfinfo->type);
10447 }
10448
10449 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
10450 * it exists anywhere, or FALSE if it exists nowhere. */
10451 gboolean
proto_check_for_protocol_or_field(const proto_tree * tree,const int id)10452 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
10453 {
10454 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
10455
10456 if (g_ptr_array_len(ptrs) > 0) {
10457 return TRUE;
10458 }
10459 else {
10460 return FALSE;
10461 }
10462 }
10463
10464 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
10465 * This only works if the hfindex was "primed" before the dissection
10466 * took place, as we just pass back the already-created GPtrArray*.
10467 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
10468 * handles that. */
10469 GPtrArray *
proto_get_finfo_ptr_array(const proto_tree * tree,const int id)10470 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
10471 {
10472 if (!tree)
10473 return NULL;
10474
10475 if (PTREE_DATA(tree)->interesting_hfids != NULL)
10476 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
10477 GINT_TO_POINTER(id));
10478 else
10479 return NULL;
10480 }
10481
10482 gboolean
proto_tracking_interesting_fields(const proto_tree * tree)10483 proto_tracking_interesting_fields(const proto_tree *tree)
10484 {
10485 GHashTable *interesting_hfids;
10486
10487 if (!tree)
10488 return FALSE;
10489
10490 interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
10491
10492 return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
10493 }
10494
10495 /* Helper struct for proto_find_info() and proto_all_finfos() */
10496 typedef struct {
10497 GPtrArray *array;
10498 int id;
10499 } ffdata_t;
10500
10501 /* Helper function for proto_find_info() */
10502 static gboolean
find_finfo(proto_node * node,gpointer data)10503 find_finfo(proto_node *node, gpointer data)
10504 {
10505 field_info *fi = PNODE_FINFO(node);
10506 if (fi && fi->hfinfo) {
10507 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
10508 g_ptr_array_add(((ffdata_t*)data)->array, fi);
10509 }
10510 }
10511
10512 /* Don't stop traversing. */
10513 return FALSE;
10514 }
10515
10516 /* Helper function for proto_find_first_info() */
10517 static gboolean
find_first_finfo(proto_node * node,gpointer data)10518 find_first_finfo(proto_node *node, gpointer data)
10519 {
10520 field_info *fi = PNODE_FINFO(node);
10521 if (fi && fi->hfinfo) {
10522 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
10523 g_ptr_array_add(((ffdata_t*)data)->array, fi);
10524
10525 /* Stop traversing. */
10526 return TRUE;
10527 }
10528 }
10529
10530 /* Continue traversing. */
10531 return FALSE;
10532 }
10533
10534 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
10535 * This works on any proto_tree, primed or unprimed, but actually searches
10536 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
10537 * The caller does need to free the returned GPtrArray with
10538 * g_ptr_array_free(<array>, TRUE).
10539 */
10540 GPtrArray *
proto_find_finfo(proto_tree * tree,const int id)10541 proto_find_finfo(proto_tree *tree, const int id)
10542 {
10543 ffdata_t ffdata;
10544
10545 ffdata.array = g_ptr_array_new();
10546 ffdata.id = id;
10547
10548 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
10549
10550 return ffdata.array;
10551 }
10552
10553 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
10554 * This works on any proto_tree, primed or unprimed, but actually searches
10555 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
10556 * The caller does need to free the returned GPtrArray with
10557 * g_ptr_array_free(<array>, TRUE).
10558 */
10559 GPtrArray *
proto_find_first_finfo(proto_tree * tree,const int id)10560 proto_find_first_finfo(proto_tree *tree, const int id)
10561 {
10562 ffdata_t ffdata;
10563
10564 ffdata.array = g_ptr_array_new();
10565 ffdata.id = id;
10566
10567 proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);
10568
10569 return ffdata.array;
10570 }
10571
10572 /* Helper function for proto_all_finfos() */
10573 static gboolean
every_finfo(proto_node * node,gpointer data)10574 every_finfo(proto_node *node, gpointer data)
10575 {
10576 field_info *fi = PNODE_FINFO(node);
10577 if (fi && fi->hfinfo) {
10578 g_ptr_array_add(((ffdata_t*)data)->array, fi);
10579 }
10580
10581 /* Don't stop traversing. */
10582 return FALSE;
10583 }
10584
10585 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
10586 GPtrArray *
proto_all_finfos(proto_tree * tree)10587 proto_all_finfos(proto_tree *tree)
10588 {
10589 ffdata_t ffdata;
10590
10591 /* Pre allocate enough space to hold all fields in most cases */
10592 ffdata.array = g_ptr_array_sized_new(512);
10593 ffdata.id = 0;
10594
10595 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
10596
10597 return ffdata.array;
10598 }
10599
10600
10601 typedef struct {
10602 guint offset;
10603 field_info *finfo;
10604 tvbuff_t *tvb;
10605 } offset_search_t;
10606
10607 static gboolean
check_for_offset(proto_node * node,gpointer data)10608 check_for_offset(proto_node *node, gpointer data)
10609 {
10610 field_info *fi = PNODE_FINFO(node);
10611 offset_search_t *offsearch = (offset_search_t *)data;
10612
10613 /* !fi == the top most container node which holds nothing */
10614 if (fi && !proto_item_is_hidden(node) && !proto_item_is_generated(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
10615 if (offsearch->offset >= (guint) fi->start &&
10616 offsearch->offset < (guint) (fi->start + fi->length)) {
10617
10618 offsearch->finfo = fi;
10619 return FALSE; /* keep traversing */
10620 }
10621 }
10622 return FALSE; /* keep traversing */
10623 }
10624
10625 /* Search a proto_tree backwards (from leaves to root) looking for the field
10626 * whose start/length occupies 'offset' */
10627 /* XXX - I couldn't find an easy way to search backwards, so I search
10628 * forwards, w/o stopping. Therefore, the last finfo I find will the be
10629 * the one I want to return to the user. This algorithm is inefficient
10630 * and could be re-done, but I'd have to handle all the children and
10631 * siblings of each node myself. When I have more time I'll do that.
10632 * (yeah right) */
10633 field_info *
proto_find_field_from_offset(proto_tree * tree,guint offset,tvbuff_t * tvb)10634 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
10635 {
10636 offset_search_t offsearch;
10637
10638 offsearch.offset = offset;
10639 offsearch.finfo = NULL;
10640 offsearch.tvb = tvb;
10641
10642 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
10643
10644 return offsearch.finfo;
10645 }
10646
10647 typedef struct {
10648 gint length;
10649 gchar *buf;
10650 } decoded_data_t;
10651
10652 static gboolean
check_for_undecoded(proto_node * node,gpointer data)10653 check_for_undecoded(proto_node *node, gpointer data)
10654 {
10655 field_info *fi = PNODE_FINFO(node);
10656 decoded_data_t* decoded = (decoded_data_t*)data;
10657 gint i;
10658 guint byte;
10659 guint bit;
10660
10661 if (fi && fi->hfinfo->type != FT_PROTOCOL) {
10662 for (i = fi->start; i < fi->start + fi->length && i < decoded->length; i++) {
10663 byte = i / 8;
10664 bit = i % 8;
10665 decoded->buf[byte] |= (1 << bit);
10666 }
10667 }
10668
10669 return FALSE;
10670 }
10671
10672 gchar*
proto_find_undecoded_data(proto_tree * tree,guint length)10673 proto_find_undecoded_data(proto_tree *tree, guint length)
10674 {
10675 decoded_data_t decoded;
10676 decoded.length = length;
10677 decoded.buf = (gchar*)wmem_alloc0(PNODE_POOL(tree), length / 8 + 1);
10678
10679 proto_tree_traverse_pre_order(tree, check_for_undecoded, &decoded);
10680 return decoded.buf;
10681 }
10682
10683 /* Dumps the protocols in the registration database to stdout. An independent
10684 * program can take this output and format it into nice tables or HTML or
10685 * whatever.
10686 *
10687 * There is one record per line. The fields are tab-delimited.
10688 *
10689 * Field 1 = protocol name
10690 * Field 2 = protocol short name
10691 * Field 3 = protocol filter name
10692 */
10693 void
proto_registrar_dump_protocols(void)10694 proto_registrar_dump_protocols(void)
10695 {
10696 protocol_t *protocol;
10697 int i;
10698 void *cookie = NULL;
10699
10700
10701 i = proto_get_first_protocol(&cookie);
10702 while (i != -1) {
10703 protocol = find_protocol_by_id(i);
10704 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
10705 protocol->filter_name);
10706 i = proto_get_next_protocol(&cookie);
10707 }
10708 }
10709
10710 /* Dumps the value_strings, extended value string headers, range_strings
10711 * or true/false strings for fields that have them.
10712 * There is one record per line. Fields are tab-delimited.
10713 * There are four types of records: Value String, Extended Value String Header,
10714 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
10715 * the type of record.
10716 *
10717 * Note that a record will be generated only if the value_string,... is referenced
10718 * in a registered hfinfo entry.
10719 *
10720 *
10721 * Value Strings
10722 * -------------
10723 * Field 1 = 'V'
10724 * Field 2 = Field abbreviation to which this value string corresponds
10725 * Field 3 = Integer value
10726 * Field 4 = String
10727 *
10728 * Extended Value String Headers
10729 * -----------------------------
10730 * Field 1 = 'E'
10731 * Field 2 = Field abbreviation to which this extended value string header corresponds
10732 * Field 3 = Extended Value String "Name"
10733 * Field 4 = Number of entries in the associated value_string array
10734 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
10735 *
10736 * Range Strings
10737 * -------------
10738 * Field 1 = 'R'
10739 * Field 2 = Field abbreviation to which this range string corresponds
10740 * Field 3 = Integer value: lower bound
10741 * Field 4 = Integer value: upper bound
10742 * Field 5 = String
10743 *
10744 * True/False Strings
10745 * ------------------
10746 * Field 1 = 'T'
10747 * Field 2 = Field abbreviation to which this true/false string corresponds
10748 * Field 3 = True String
10749 * Field 4 = False String
10750 */
10751 void
proto_registrar_dump_values(void)10752 proto_registrar_dump_values(void)
10753 {
10754 header_field_info *hfinfo;
10755 int i, len, vi;
10756 const value_string *vals;
10757 const val64_string *vals64;
10758 const range_string *range;
10759 const true_false_string *tfs;
10760 const unit_name_string *units;
10761
10762 len = gpa_hfinfo.len;
10763 for (i = 0; i < len ; i++) {
10764 if (gpa_hfinfo.hfi[i] == NULL)
10765 continue; /* This is a deregistered protocol or field */
10766
10767 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
10768
10769 if (hfinfo->id == hf_text_only) {
10770 continue;
10771 }
10772
10773 /* ignore protocols */
10774 if (proto_registrar_is_protocol(i)) {
10775 continue;
10776 }
10777 /* process header fields */
10778 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
10779 /*
10780 * If this field isn't at the head of the list of
10781 * fields with this name, skip this field - all
10782 * fields with the same name are really just versions
10783 * of the same field stored in different bits, and
10784 * should have the same type/radix/value list, and
10785 * just differ in their bit masks. (If a field isn't
10786 * a bitfield, but can be, say, 1 or 2 bytes long,
10787 * it can just be made FT_UINT16, meaning the
10788 * *maximum* length is 2 bytes, and be used
10789 * for all lengths.)
10790 */
10791 if (hfinfo->same_name_prev_id != -1)
10792 continue;
10793 #endif
10794 vals = NULL;
10795 vals64 = NULL;
10796 range = NULL;
10797 tfs = NULL;
10798 units = NULL;
10799
10800 if (hfinfo->strings != NULL) {
10801 if (FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM &&
10802 (hfinfo->type == FT_CHAR ||
10803 hfinfo->type == FT_UINT8 ||
10804 hfinfo->type == FT_UINT16 ||
10805 hfinfo->type == FT_UINT24 ||
10806 hfinfo->type == FT_UINT32 ||
10807 hfinfo->type == FT_UINT40 ||
10808 hfinfo->type == FT_UINT48 ||
10809 hfinfo->type == FT_UINT56 ||
10810 hfinfo->type == FT_UINT64 ||
10811 hfinfo->type == FT_INT8 ||
10812 hfinfo->type == FT_INT16 ||
10813 hfinfo->type == FT_INT24 ||
10814 hfinfo->type == FT_INT32 ||
10815 hfinfo->type == FT_INT40 ||
10816 hfinfo->type == FT_INT48 ||
10817 hfinfo->type == FT_INT56 ||
10818 hfinfo->type == FT_INT64 ||
10819 hfinfo->type == FT_FLOAT ||
10820 hfinfo->type == FT_DOUBLE)) {
10821
10822 if (hfinfo->display & BASE_RANGE_STRING) {
10823 range = (const range_string *)hfinfo->strings;
10824 } else if (hfinfo->display & BASE_EXT_STRING) {
10825 if (hfinfo->display & BASE_VAL64_STRING) {
10826 vals64 = VAL64_STRING_EXT_VS_P((const val64_string_ext *)hfinfo->strings);
10827 } else {
10828 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
10829 }
10830 } else if (hfinfo->display & BASE_VAL64_STRING) {
10831 vals64 = (const val64_string *)hfinfo->strings;
10832 } else if (hfinfo->display & BASE_UNIT_STRING) {
10833 units = (const unit_name_string *)hfinfo->strings;
10834 } else {
10835 vals = (const value_string *)hfinfo->strings;
10836 }
10837 }
10838 else if (hfinfo->type == FT_BOOLEAN) {
10839 tfs = (const struct true_false_string *)hfinfo->strings;
10840 }
10841 }
10842
10843 /* Print value strings? */
10844 if (vals) {
10845 if (hfinfo->display & BASE_EXT_STRING) {
10846 if (hfinfo->display & BASE_VAL64_STRING) {
10847 val64_string_ext *vse_p = (val64_string_ext *)hfinfo->strings;
10848 if (!val64_string_ext_validate(vse_p)) {
10849 ws_warning("Invalid val64_string_ext ptr for: %s", hfinfo->abbrev);
10850 continue;
10851 }
10852 try_val64_to_str_ext(0, vse_p); /* "prime" the extended val64_string */
10853 printf("E\t%s\t%u\t%s\t%s\n",
10854 hfinfo->abbrev,
10855 VAL64_STRING_EXT_VS_NUM_ENTRIES(vse_p),
10856 VAL64_STRING_EXT_VS_NAME(vse_p),
10857 val64_string_ext_match_type_str(vse_p));
10858 } else {
10859 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
10860 if (!value_string_ext_validate(vse_p)) {
10861 ws_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
10862 continue;
10863 }
10864 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
10865 printf("E\t%s\t%u\t%s\t%s\n",
10866 hfinfo->abbrev,
10867 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
10868 VALUE_STRING_EXT_VS_NAME(vse_p),
10869 value_string_ext_match_type_str(vse_p));
10870 }
10871 }
10872 vi = 0;
10873 while (vals[vi].strptr) {
10874 /* Print in the proper base */
10875 if (hfinfo->type == FT_CHAR) {
10876 if (g_ascii_isprint(vals[vi].value)) {
10877 printf("V\t%s\t'%c'\t%s\n",
10878 hfinfo->abbrev,
10879 vals[vi].value,
10880 vals[vi].strptr);
10881 } else {
10882 if (hfinfo->display == BASE_HEX) {
10883 printf("V\t%s\t'\\x%02x'\t%s\n",
10884 hfinfo->abbrev,
10885 vals[vi].value,
10886 vals[vi].strptr);
10887 }
10888 else {
10889 printf("V\t%s\t'\\%03o'\t%s\n",
10890 hfinfo->abbrev,
10891 vals[vi].value,
10892 vals[vi].strptr);
10893 }
10894 }
10895 } else {
10896 if (hfinfo->display == BASE_HEX) {
10897 printf("V\t%s\t0x%x\t%s\n",
10898 hfinfo->abbrev,
10899 vals[vi].value,
10900 vals[vi].strptr);
10901 }
10902 else {
10903 printf("V\t%s\t%u\t%s\n",
10904 hfinfo->abbrev,
10905 vals[vi].value,
10906 vals[vi].strptr);
10907 }
10908 }
10909 vi++;
10910 }
10911 }
10912 else if (vals64) {
10913 vi = 0;
10914 while (vals64[vi].strptr) {
10915 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
10916 hfinfo->abbrev,
10917 vals64[vi].value,
10918 vals64[vi].strptr);
10919 vi++;
10920 }
10921 }
10922
10923 /* print range strings? */
10924 else if (range) {
10925 vi = 0;
10926 while (range[vi].strptr) {
10927 /* Print in the proper base */
10928 if (FIELD_DISPLAY(hfinfo->display) == BASE_HEX) {
10929 printf("R\t%s\t0x%x\t0x%x\t%s\n",
10930 hfinfo->abbrev,
10931 range[vi].value_min,
10932 range[vi].value_max,
10933 range[vi].strptr);
10934 }
10935 else {
10936 printf("R\t%s\t%u\t%u\t%s\n",
10937 hfinfo->abbrev,
10938 range[vi].value_min,
10939 range[vi].value_max,
10940 range[vi].strptr);
10941 }
10942 vi++;
10943 }
10944 }
10945
10946 /* Print true/false strings? */
10947 else if (tfs) {
10948 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
10949 tfs->true_string, tfs->false_string);
10950 }
10951 /* Print unit strings? */
10952 else if (units) {
10953 printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
10954 units->singular, units->plural ? units->plural : "(no plural)");
10955 }
10956 }
10957 }
10958
10959 /* Prints the number of registered fields.
10960 * Useful for determining an appropriate value for
10961 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
10962 *
10963 * Returns FALSE if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
10964 * the number of fields, TRUE otherwise.
10965 */
10966 gboolean
proto_registrar_dump_fieldcount(void)10967 proto_registrar_dump_fieldcount(void)
10968 {
10969 guint32 i;
10970 header_field_info *hfinfo;
10971 guint32 deregistered_count = 0;
10972 guint32 same_name_count = 0;
10973 guint32 protocol_count = 0;
10974
10975 for (i = 0; i < gpa_hfinfo.len; i++) {
10976 if (gpa_hfinfo.hfi[i] == NULL) {
10977 deregistered_count++;
10978 continue; /* This is a deregistered protocol or header field */
10979 }
10980
10981 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
10982
10983 if (proto_registrar_is_protocol(i))
10984 protocol_count++;
10985
10986 if (hfinfo->same_name_prev_id != -1)
10987 same_name_count++;
10988 }
10989
10990 printf("There are %u header fields registered, of which:\n"
10991 "\t%u are deregistered\n"
10992 "\t%u are protocols\n"
10993 "\t%u have the same name as another field\n\n",
10994 gpa_hfinfo.len, deregistered_count, protocol_count,
10995 same_name_count);
10996
10997 printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
10998 (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
10999 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
11000 "\n");
11001
11002 printf("The header field table consumes %u KiB of memory.\n",
11003 (unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
11004 printf("The fields themselves consume %u KiB of memory.\n",
11005 (unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));
11006
11007 return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
11008 }
11009
11010 static void
elastic_add_base_mapping(json_dumper * dumper)11011 elastic_add_base_mapping(json_dumper *dumper)
11012 {
11013 json_dumper_set_member_name(dumper, "index_patterns");
11014 json_dumper_value_string(dumper, "packets-*");
11015
11016 json_dumper_set_member_name(dumper, "settings");
11017 json_dumper_begin_object(dumper);
11018 json_dumper_set_member_name(dumper, "index.mapping.total_fields.limit");
11019 json_dumper_value_anyf(dumper, "%d", 1000000);
11020 json_dumper_end_object(dumper);
11021 }
11022
11023 static gchar*
ws_type_to_elastic(guint type _U_)11024 ws_type_to_elastic(guint type _U_)
11025 {
11026 switch(type) {
11027 case FT_UINT16:
11028 case FT_INT16:
11029 case FT_INT32:
11030 case FT_UINT24:
11031 case FT_INT24:
11032 return "integer";
11033 case FT_INT8:
11034 case FT_UINT8:
11035 return "short";
11036 case FT_FRAMENUM:
11037 case FT_UINT32:
11038 case FT_UINT40:
11039 case FT_UINT48:
11040 case FT_UINT56:
11041 case FT_UINT64: // Actually it's not handled by 'long' elastic type.
11042 case FT_INT48:
11043 case FT_INT64:
11044 return "long";
11045 case FT_FLOAT:
11046 case FT_DOUBLE:
11047 return "float";
11048 case FT_IPv6:
11049 case FT_IPv4:
11050 return "ip";
11051 case FT_ABSOLUTE_TIME:
11052 case FT_RELATIVE_TIME:
11053 return "date";
11054 case FT_BYTES:
11055 case FT_UINT_BYTES:
11056 return "byte";
11057 case FT_BOOLEAN:
11058 return "boolean";
11059 default:
11060 return NULL;
11061 }
11062 }
11063
11064 static gchar*
dot_to_underscore(gchar * str)11065 dot_to_underscore(gchar* str)
11066 {
11067 unsigned i;
11068 for (i = 0; i < strlen(str); i++) {
11069 if (str[i] == '.')
11070 str[i] = '_';
11071 }
11072 return str;
11073 }
11074
11075 /* Dumps a mapping file for ElasticSearch
11076 */
11077 void
proto_registrar_dump_elastic(const gchar * filter)11078 proto_registrar_dump_elastic(const gchar* filter)
11079 {
11080 header_field_info *hfinfo;
11081 header_field_info *parent_hfinfo;
11082 guint i;
11083 gboolean open_object = TRUE;
11084 const char* prev_proto = NULL;
11085 gchar* str;
11086 gchar** protos = NULL;
11087 gchar* proto;
11088 gboolean found;
11089 guint j;
11090 gchar* type;
11091
11092 /* We have filtering protocols. Extract them. */
11093 if (filter) {
11094 protos = g_strsplit(filter, ",", -1);
11095 }
11096
11097 /*
11098 * To help tracking down the json tree, objects have been appended with a comment:
11099 * n.label -> where n is the indentation level and label the name of the object
11100 */
11101
11102 json_dumper dumper = {
11103 .output_file = stdout,
11104 .flags = JSON_DUMPER_FLAGS_PRETTY_PRINT,
11105 };
11106 json_dumper_begin_object(&dumper); // 1.root
11107 elastic_add_base_mapping(&dumper);
11108
11109 json_dumper_set_member_name(&dumper, "mappings");
11110 json_dumper_begin_object(&dumper); // 2.mappings
11111 json_dumper_set_member_name(&dumper, "doc");
11112
11113 json_dumper_begin_object(&dumper); // 3.doc
11114 json_dumper_set_member_name(&dumper, "dynamic");
11115 json_dumper_value_anyf(&dumper, "false");
11116
11117 json_dumper_set_member_name(&dumper, "properties");
11118 json_dumper_begin_object(&dumper); // 4.properties
11119 json_dumper_set_member_name(&dumper, "timestamp");
11120 json_dumper_begin_object(&dumper); // 5.timestamp
11121 json_dumper_set_member_name(&dumper, "type");
11122 json_dumper_value_string(&dumper, "date");
11123 json_dumper_end_object(&dumper); // 5.timestamp
11124
11125 json_dumper_set_member_name(&dumper, "layers");
11126 json_dumper_begin_object(&dumper); // 5.layers
11127 json_dumper_set_member_name(&dumper, "properties");
11128 json_dumper_begin_object(&dumper); // 6.properties
11129
11130 for (i = 0; i < gpa_hfinfo.len; i++) {
11131 if (gpa_hfinfo.hfi[i] == NULL)
11132 continue; /* This is a deregistered protocol or header field */
11133
11134 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11135
11136 /*
11137 * Skip the pseudo-field for "proto_tree_add_text()" since
11138 * we don't want it in the list of filterable protocols.
11139 */
11140 if (hfinfo->id == hf_text_only)
11141 continue;
11142
11143 if (!proto_registrar_is_protocol(i)) {
11144 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
11145
11146 /*
11147 * Skip the field if filter protocols have been set and this one's
11148 * parent is not listed.
11149 */
11150 if (protos) {
11151 found = FALSE;
11152 j = 0;
11153 proto = protos[0];
11154 while(proto) {
11155 if (!g_strcmp0(proto, parent_hfinfo->abbrev)) {
11156 found = TRUE;
11157 break;
11158 }
11159 j++;
11160 proto = protos[j];
11161 }
11162 if (!found)
11163 continue;
11164 }
11165
11166 if (prev_proto && g_strcmp0(parent_hfinfo->abbrev, prev_proto)) {
11167 json_dumper_end_object(&dumper); // 8.properties
11168 json_dumper_end_object(&dumper); // 7.parent_hfinfo->abbrev
11169 open_object = TRUE;
11170 }
11171
11172 prev_proto = parent_hfinfo->abbrev;
11173
11174 if (open_object) {
11175 json_dumper_set_member_name(&dumper, parent_hfinfo->abbrev);
11176 json_dumper_begin_object(&dumper); // 7.parent_hfinfo->abbrev
11177 json_dumper_set_member_name(&dumper, "properties");
11178 json_dumper_begin_object(&dumper); // 8.properties
11179 open_object = FALSE;
11180 }
11181 /* Skip the fields that would map into string. This is the default in elasticsearch. */
11182 type = ws_type_to_elastic(hfinfo->type);
11183 if (type) {
11184 str = g_strdup_printf("%s_%s", prev_proto, hfinfo->abbrev);
11185 json_dumper_set_member_name(&dumper, dot_to_underscore(str));
11186 g_free(str);
11187 json_dumper_begin_object(&dumper); // 9.hfinfo->abbrev
11188 json_dumper_set_member_name(&dumper, "type");
11189 json_dumper_value_string(&dumper, type);
11190 json_dumper_end_object(&dumper); // 9.hfinfo->abbrev
11191 }
11192 }
11193 }
11194
11195 if (prev_proto) {
11196 json_dumper_end_object(&dumper); // 8.properties
11197 json_dumper_end_object(&dumper); // 7.parent_hfinfo->abbrev
11198 }
11199
11200 json_dumper_end_object(&dumper); // 6.properties
11201 json_dumper_end_object(&dumper); // 5.layers
11202 json_dumper_end_object(&dumper); // 4.properties
11203 json_dumper_end_object(&dumper); // 3.doc
11204 json_dumper_end_object(&dumper); // 2.mappings
11205 json_dumper_end_object(&dumper); // 1.root
11206 gboolean ret = json_dumper_finish(&dumper);
11207 DISSECTOR_ASSERT(ret);
11208
11209 g_strfreev(protos);
11210 }
11211
11212 /* Dumps the contents of the registration database to stdout. An independent
11213 * program can take this output and format it into nice tables or HTML or
11214 * whatever.
11215 *
11216 * There is one record per line. Each record is either a protocol or a header
11217 * field, differentiated by the first field. The fields are tab-delimited.
11218 *
11219 * Protocols
11220 * ---------
11221 * Field 1 = 'P'
11222 * Field 2 = descriptive protocol name
11223 * Field 3 = protocol abbreviation
11224 *
11225 * Header Fields
11226 * -------------
11227 * Field 1 = 'F'
11228 * Field 2 = descriptive field name
11229 * Field 3 = field abbreviation
11230 * Field 4 = type ( textual representation of the the ftenum type )
11231 * Field 5 = parent protocol abbreviation
11232 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
11233 * Field 7 = bitmask: format: hex: 0x....
11234 * Field 8 = blurb describing field
11235 */
11236 void
proto_registrar_dump_fields(void)11237 proto_registrar_dump_fields(void)
11238 {
11239 header_field_info *hfinfo, *parent_hfinfo;
11240 int i, len;
11241 const char *enum_name;
11242 const char *base_name;
11243 const char *blurb;
11244 char width[5];
11245
11246 len = gpa_hfinfo.len;
11247 for (i = 0; i < len ; i++) {
11248 if (gpa_hfinfo.hfi[i] == NULL)
11249 continue; /* This is a deregistered protocol or header field */
11250
11251 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11252
11253 /*
11254 * Skip the pseudo-field for "proto_tree_add_text()" since
11255 * we don't want it in the list of filterable fields.
11256 */
11257 if (hfinfo->id == hf_text_only)
11258 continue;
11259
11260 /* format for protocols */
11261 if (proto_registrar_is_protocol(i)) {
11262 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
11263 }
11264 /* format for header fields */
11265 else {
11266 /*
11267 * If this field isn't at the head of the list of
11268 * fields with this name, skip this field - all
11269 * fields with the same name are really just versions
11270 * of the same field stored in different bits, and
11271 * should have the same type/radix/value list, and
11272 * just differ in their bit masks. (If a field isn't
11273 * a bitfield, but can be, say, 1 or 2 bytes long,
11274 * it can just be made FT_UINT16, meaning the
11275 * *maximum* length is 2 bytes, and be used
11276 * for all lengths.)
11277 */
11278 if (hfinfo->same_name_prev_id != -1)
11279 continue;
11280
11281 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
11282
11283 enum_name = ftype_name(hfinfo->type);
11284 base_name = "";
11285
11286 if (hfinfo->type == FT_CHAR ||
11287 hfinfo->type == FT_UINT8 ||
11288 hfinfo->type == FT_UINT16 ||
11289 hfinfo->type == FT_UINT24 ||
11290 hfinfo->type == FT_UINT32 ||
11291 hfinfo->type == FT_UINT40 ||
11292 hfinfo->type == FT_UINT48 ||
11293 hfinfo->type == FT_UINT56 ||
11294 hfinfo->type == FT_UINT64 ||
11295 hfinfo->type == FT_INT8 ||
11296 hfinfo->type == FT_INT16 ||
11297 hfinfo->type == FT_INT24 ||
11298 hfinfo->type == FT_INT32 ||
11299 hfinfo->type == FT_INT40 ||
11300 hfinfo->type == FT_INT48 ||
11301 hfinfo->type == FT_INT56 ||
11302 hfinfo->type == FT_INT64) {
11303
11304 switch (FIELD_DISPLAY(hfinfo->display)) {
11305 case BASE_NONE:
11306 case BASE_DEC:
11307 case BASE_HEX:
11308 case BASE_OCT:
11309 case BASE_DEC_HEX:
11310 case BASE_HEX_DEC:
11311 case BASE_CUSTOM:
11312 case BASE_PT_UDP:
11313 case BASE_PT_TCP:
11314 case BASE_PT_DCCP:
11315 case BASE_PT_SCTP:
11316 case BASE_OUI:
11317 base_name = val_to_str_const(FIELD_DISPLAY(hfinfo->display), hf_display, "????");
11318 break;
11319 default:
11320 base_name = "????";
11321 break;
11322 }
11323 } else if (hfinfo->type == FT_BOOLEAN) {
11324 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
11325 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
11326 base_name = width;
11327 }
11328
11329 blurb = hfinfo->blurb;
11330 if (blurb == NULL)
11331 blurb = "";
11332 else if (strlen(blurb) == 0)
11333 blurb = "\"\"";
11334
11335 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" G_GINT64_MODIFIER "x\t%s\n",
11336 hfinfo->name, hfinfo->abbrev, enum_name,
11337 parent_hfinfo->abbrev, base_name,
11338 hfinfo->bitmask, blurb);
11339 }
11340 }
11341 }
11342
11343 /* Dumps field types and descriptive names to stdout. An independent
11344 * program can take this output and format it into nice tables or HTML or
11345 * whatever.
11346 *
11347 * There is one record per line. The fields are tab-delimited.
11348 *
11349 * Field 1 = field type name, e.g. FT_UINT8
11350 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
11351 */
11352 void
proto_registrar_dump_ftypes(void)11353 proto_registrar_dump_ftypes(void)
11354 {
11355 int fte;
11356
11357 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
11358 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
11359 }
11360 }
11361
11362 /* This function indicates whether it's possible to construct a
11363 * "match selected" display filter string for the specified field,
11364 * returns an indication of whether it's possible, and, if it's
11365 * possible and "filter" is non-null, constructs the filter and
11366 * sets "*filter" to point to it.
11367 * You do not need to [g_]free() this string since it will be automatically
11368 * freed once the next packet is dissected.
11369 */
11370 static gboolean
construct_match_selected_string(field_info * finfo,epan_dissect_t * edt,char ** filter)11371 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
11372 char **filter)
11373 {
11374 header_field_info *hfinfo;
11375 int abbrev_len;
11376 char *ptr;
11377 int buf_len;
11378 int dfilter_len, i;
11379 gint start, length, length_remaining;
11380 guint8 c;
11381 gchar is_signed_num = FALSE;
11382
11383 if (!finfo)
11384 return FALSE;
11385
11386 hfinfo = finfo->hfinfo;
11387 DISSECTOR_ASSERT(hfinfo);
11388 abbrev_len = (int) strlen(hfinfo->abbrev);
11389
11390 if (hfinfo->strings && FIELD_DISPLAY(hfinfo->display) == BASE_NONE) {
11391 const gchar *str = NULL;
11392
11393 switch (hfinfo->type) {
11394
11395 case FT_INT8:
11396 case FT_INT16:
11397 case FT_INT24:
11398 case FT_INT32:
11399 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
11400 break;
11401
11402 case FT_CHAR:
11403 case FT_UINT8:
11404 case FT_UINT16:
11405 case FT_UINT24:
11406 case FT_UINT32:
11407 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
11408 break;
11409
11410 default:
11411 break;
11412 }
11413
11414 if (str != NULL && filter != NULL) {
11415 *filter = wmem_strdup_printf(NULL, "%s == \"%s\"", hfinfo->abbrev, str);
11416 return TRUE;
11417 }
11418 }
11419
11420 /*
11421 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
11422 * functions for FT_UINT and FT_INT types, as we choose the base in
11423 * the string expression based on the display base of the field.
11424 *
11425 * Note that the base does matter, as this is also used for
11426 * the protocolinfo tap.
11427 *
11428 * It might be nice to use them in "proto_item_fill_label()"
11429 * as well, although, there, you'd have to deal with the base
11430 * *and* with resolved values for addresses.
11431 *
11432 * Perhaps we need two different val_to_string routines, one
11433 * to generate items for display filters and one to generate
11434 * strings for display, and pass to both of them the
11435 * "display" and "strings" values in the header_field_info
11436 * structure for the field, so they can get the base and,
11437 * if the field is Boolean or an enumerated integer type,
11438 * the tables used to generate human-readable values.
11439 */
11440 switch (hfinfo->type) {
11441
11442 case FT_CHAR:
11443 if (filter != NULL) {
11444 guint32 number;
11445
11446 char buf [48];
11447 const char *out;
11448
11449 number = fvalue_get_uinteger(&finfo->value);
11450
11451 out = hfinfo_char_value_format(hfinfo, buf, number);
11452
11453 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
11454 }
11455 break;
11456
11457 case FT_INT8:
11458 case FT_INT16:
11459 case FT_INT24:
11460 case FT_INT32:
11461 is_signed_num = TRUE;
11462 /* FALLTHRU */
11463 case FT_UINT8:
11464 case FT_UINT16:
11465 case FT_UINT24:
11466 case FT_UINT32:
11467 case FT_FRAMENUM:
11468 if (filter != NULL) {
11469 guint32 number;
11470
11471 char buf[32];
11472 const char *out;
11473
11474 if (is_signed_num)
11475 number = fvalue_get_sinteger(&finfo->value);
11476 else
11477 number = fvalue_get_uinteger(&finfo->value);
11478
11479 out = hfinfo_numeric_value_format(hfinfo, buf, number);
11480
11481 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
11482 }
11483 break;
11484
11485 case FT_INT40:
11486 case FT_INT48:
11487 case FT_INT56:
11488 case FT_INT64:
11489 is_signed_num = TRUE;
11490 /* FALLTHRU */
11491 case FT_UINT40:
11492 case FT_UINT48:
11493 case FT_UINT56:
11494 case FT_UINT64:
11495 if (filter != NULL) {
11496 guint64 number;
11497
11498 char buf [48];
11499 const char *out;
11500
11501 if (is_signed_num)
11502 number = fvalue_get_sinteger64(&finfo->value);
11503 else
11504 number = fvalue_get_uinteger64(&finfo->value);
11505
11506 out = hfinfo_numeric_value_format64(hfinfo, buf, number);
11507
11508 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
11509 }
11510 break;
11511
11512 case FT_PROTOCOL:
11513 if (filter != NULL)
11514 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
11515 break;
11516
11517 case FT_NONE:
11518 /*
11519 * If the length is 0, just match the name of the
11520 * field.
11521 *
11522 * (Also check for negative values, just in case,
11523 * as we'll cast it to an unsigned value later.)
11524 */
11525 length = finfo->length;
11526 if (length == 0) {
11527 if (filter != NULL)
11528 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
11529 break;
11530 }
11531 if (length < 0)
11532 return FALSE;
11533
11534 /*
11535 * This doesn't have a value, so we'd match
11536 * on the raw bytes at this address.
11537 *
11538 * Should we be allowed to access to the raw bytes?
11539 * If "edt" is NULL, the answer is "no".
11540 */
11541 if (edt == NULL)
11542 return FALSE;
11543
11544 /*
11545 * Is this field part of the raw frame tvbuff?
11546 * If not, we can't use "frame[N:M]" to match
11547 * it.
11548 *
11549 * XXX - should this be frame-relative, or
11550 * protocol-relative?
11551 *
11552 * XXX - does this fallback for non-registered
11553 * fields even make sense?
11554 */
11555 if (finfo->ds_tvb != edt->tvb)
11556 return FALSE; /* you lose */
11557
11558 /*
11559 * Don't go past the end of that tvbuff.
11560 */
11561 length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
11562 if (length > length_remaining)
11563 length = length_remaining;
11564 if (length <= 0)
11565 return FALSE;
11566
11567 if (filter != NULL) {
11568 start = finfo->start;
11569 buf_len = 32 + length * 3;
11570 *filter = (char *)wmem_alloc0(NULL, buf_len);
11571 ptr = *filter;
11572
11573 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
11574 "frame[%d:%d] == ", finfo->start, length);
11575 for (i=0; i<length; i++) {
11576 c = tvb_get_guint8(finfo->ds_tvb, start);
11577 start++;
11578 if (i == 0 ) {
11579 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
11580 }
11581 else {
11582 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
11583 }
11584 }
11585 }
11586 break;
11587
11588 /* By default, use the fvalue's "to_string_repr" method. */
11589 default:
11590 /* Figure out the string length needed.
11591 * The ft_repr length.
11592 * 4 bytes for " == ".
11593 * 1 byte for trailing NUL.
11594 */
11595 if (filter != NULL) {
11596 char* str;
11597 dfilter_len = fvalue_string_repr_len(&finfo->value,
11598 FTREPR_DFILTER, finfo->hfinfo->display);
11599 dfilter_len += abbrev_len + 4 + 1;
11600 *filter = (char *)wmem_alloc0(NULL, dfilter_len);
11601
11602 /* Create the string */
11603 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
11604 g_snprintf(*filter, dfilter_len, "%s == %s", hfinfo->abbrev, str);
11605 wmem_free(NULL, str);
11606 }
11607 break;
11608 }
11609
11610 return TRUE;
11611 }
11612
11613 /*
11614 * Returns TRUE if we can do a "match selected" on the field, FALSE
11615 * otherwise.
11616 */
11617 gboolean
proto_can_match_selected(field_info * finfo,epan_dissect_t * edt)11618 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
11619 {
11620 return construct_match_selected_string(finfo, edt, NULL);
11621 }
11622
11623 /* This function attempts to construct a "match selected" display filter
11624 * string for the specified field; if it can do so, it returns a pointer
11625 * to the string, otherwise it returns NULL.
11626 *
11627 * The string is wmem allocated and must be freed with "wmem_free(NULL, ...)".
11628 */
11629 char *
proto_construct_match_selected_string(field_info * finfo,epan_dissect_t * edt)11630 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
11631 {
11632 char *filter = NULL;
11633
11634 if (!construct_match_selected_string(finfo, edt, &filter))
11635 {
11636 wmem_free(NULL, filter);
11637 return NULL;
11638 }
11639 return filter;
11640 }
11641
11642 /* This function is common code for all proto_tree_add_bitmask... functions.
11643 */
11644
11645 static gboolean
proto_item_add_bitmask_tree(proto_item * item,tvbuff_t * tvb,const int offset,const int len,const gint ett,int * const * fields,const int flags,gboolean first,gboolean use_parent_tree,proto_tree * tree,guint64 value)11646 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
11647 const int len, const gint ett, int * const *fields,
11648 const int flags, gboolean first,
11649 gboolean use_parent_tree,
11650 proto_tree* tree, guint64 value)
11651 {
11652 guint64 available_bits = G_MAXUINT64;
11653 guint64 bitmask = 0;
11654 guint64 tmpval;
11655 header_field_info *hf;
11656 guint32 integer32;
11657 gint bit_offset;
11658 gint no_of_bits;
11659
11660 if (!*fields)
11661 REPORT_DISSECTOR_BUG("Illegal call of proto_item_add_bitmask_tree without fields");
11662
11663 if (len < 0 || len > 8)
11664 REPORT_DISSECTOR_BUG("Invalid len: %d", len);
11665 /**
11666 * packet-frame.c uses len=0 since the value is taken from the packet
11667 * metadata, not the packet bytes. In that case, assume that all bits
11668 * in the provided value are valid.
11669 */
11670 if (len > 0) {
11671 available_bits >>= (8 - (guint)len)*8;
11672 }
11673
11674 if (use_parent_tree == FALSE)
11675 tree = proto_item_add_subtree(item, ett);
11676
11677 while (*fields) {
11678 guint64 present_bits;
11679 PROTO_REGISTRAR_GET_NTH(**fields,hf);
11680 DISSECTOR_ASSERT_HINT(hf->bitmask != 0, hf->abbrev);
11681
11682 bitmask |= hf->bitmask;
11683
11684 /* Skip fields that aren't fully present */
11685 present_bits = available_bits & hf->bitmask;
11686 if (present_bits != hf->bitmask) {
11687 fields++;
11688 continue;
11689 }
11690
11691 switch (hf->type) {
11692 case FT_CHAR:
11693 case FT_UINT8:
11694 case FT_UINT16:
11695 case FT_UINT24:
11696 case FT_UINT32:
11697 proto_tree_add_uint(tree, **fields, tvb, offset, len, (guint32)value);
11698 break;
11699
11700 case FT_INT8:
11701 case FT_INT16:
11702 case FT_INT24:
11703 case FT_INT32:
11704 proto_tree_add_int(tree, **fields, tvb, offset, len, (gint32)value);
11705 break;
11706
11707 case FT_UINT40:
11708 case FT_UINT48:
11709 case FT_UINT56:
11710 case FT_UINT64:
11711 proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
11712 break;
11713
11714 case FT_INT40:
11715 case FT_INT48:
11716 case FT_INT56:
11717 case FT_INT64:
11718 proto_tree_add_int64(tree, **fields, tvb, offset, len, (gint64)value);
11719 break;
11720
11721 case FT_BOOLEAN:
11722 proto_tree_add_boolean64(tree, **fields, tvb, offset, len, value);
11723 break;
11724
11725 default:
11726 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
11727 hf->abbrev,
11728 hf->type,
11729 ftype_name(hf->type));
11730 break;
11731 }
11732 if (flags & BMT_NO_APPEND) {
11733 fields++;
11734 continue;
11735 }
11736 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
11737
11738 switch (hf->type) {
11739 case FT_CHAR:
11740 if (hf->display == BASE_CUSTOM) {
11741 gchar lbl[ITEM_LABEL_LENGTH];
11742 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
11743
11744 DISSECTOR_ASSERT(fmtfunc);
11745 fmtfunc(lbl, (guint32) tmpval);
11746 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11747 hf->name, lbl);
11748 first = FALSE;
11749 }
11750 else if (hf->strings) {
11751 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11752 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
11753 first = FALSE;
11754 }
11755 else if (!(flags & BMT_NO_INT)) {
11756 char buf[32];
11757 const char *out;
11758
11759 if (!first) {
11760 proto_item_append_text(item, ", ");
11761 }
11762
11763 out = hfinfo_char_value_format(hf, buf, (guint32) tmpval);
11764 proto_item_append_text(item, "%s: %s", hf->name, out);
11765 first = FALSE;
11766 }
11767
11768 break;
11769
11770 case FT_UINT8:
11771 case FT_UINT16:
11772 case FT_UINT24:
11773 case FT_UINT32:
11774 if (hf->display == BASE_CUSTOM) {
11775 gchar lbl[ITEM_LABEL_LENGTH];
11776 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
11777
11778 DISSECTOR_ASSERT(fmtfunc);
11779 fmtfunc(lbl, (guint32) tmpval);
11780 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11781 hf->name, lbl);
11782 first = FALSE;
11783 }
11784 else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
11785 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11786 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
11787 first = FALSE;
11788 }
11789 else if (!(flags & BMT_NO_INT)) {
11790 char buf[32];
11791 const char *out;
11792
11793 if (!first) {
11794 proto_item_append_text(item, ", ");
11795 }
11796
11797 out = hfinfo_number_value_format(hf, buf, (guint32) tmpval);
11798 if (hf->display & BASE_UNIT_STRING) {
11799 proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (const unit_name_string*)hf->strings));
11800 } else {
11801 proto_item_append_text(item, "%s: %s", hf->name, out);
11802 }
11803 first = FALSE;
11804 }
11805
11806 break;
11807
11808 case FT_INT8:
11809 case FT_INT16:
11810 case FT_INT24:
11811 case FT_INT32:
11812 integer32 = (guint32) tmpval;
11813 if (hf->bitmask) {
11814 no_of_bits = ws_count_ones(hf->bitmask);
11815 integer32 = ws_sign_ext32(integer32, no_of_bits);
11816 }
11817 if (hf->display == BASE_CUSTOM) {
11818 gchar lbl[ITEM_LABEL_LENGTH];
11819 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
11820
11821 DISSECTOR_ASSERT(fmtfunc);
11822 fmtfunc(lbl, (gint32) integer32);
11823 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11824 hf->name, lbl);
11825 first = FALSE;
11826 }
11827 else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
11828 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11829 hf->name, hf_try_val_to_str_const((gint32) integer32, hf, "Unknown"));
11830 first = FALSE;
11831 }
11832 else if (!(flags & BMT_NO_INT)) {
11833 char buf[32];
11834 const char *out;
11835
11836 if (!first) {
11837 proto_item_append_text(item, ", ");
11838 }
11839
11840 out = hfinfo_number_value_format(hf, buf, (gint32) integer32);
11841 if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
11842 proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (const unit_name_string*)hf->strings));
11843 } else {
11844 proto_item_append_text(item, "%s: %s", hf->name, out);
11845 }
11846 first = FALSE;
11847 }
11848
11849 break;
11850
11851 case FT_UINT40:
11852 case FT_UINT48:
11853 case FT_UINT56:
11854 case FT_UINT64:
11855 if (hf->display == BASE_CUSTOM) {
11856 gchar lbl[ITEM_LABEL_LENGTH];
11857 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
11858
11859 DISSECTOR_ASSERT(fmtfunc);
11860 fmtfunc(lbl, tmpval);
11861 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11862 hf->name, lbl);
11863 first = FALSE;
11864 }
11865 else if (hf->strings) {
11866 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11867 hf->name, hf_try_val64_to_str_const(tmpval, hf, "Unknown"));
11868 first = FALSE;
11869 }
11870 else if (!(flags & BMT_NO_INT)) {
11871 char buf[48];
11872 const char *out;
11873
11874 if (!first) {
11875 proto_item_append_text(item, ", ");
11876 }
11877
11878 out = hfinfo_number_value_format64(hf, buf, tmpval);
11879 proto_item_append_text(item, "%s: %s", hf->name, out);
11880 first = FALSE;
11881 }
11882
11883 break;
11884
11885 case FT_INT40:
11886 case FT_INT48:
11887 case FT_INT56:
11888 case FT_INT64:
11889 if (hf->bitmask) {
11890 no_of_bits = ws_count_ones(hf->bitmask);
11891 tmpval = ws_sign_ext64(tmpval, no_of_bits);
11892 }
11893 if (hf->display == BASE_CUSTOM) {
11894 gchar lbl[ITEM_LABEL_LENGTH];
11895 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
11896
11897 DISSECTOR_ASSERT(fmtfunc);
11898 fmtfunc(lbl, (gint64) tmpval);
11899 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11900 hf->name, lbl);
11901 first = FALSE;
11902 }
11903 else if (hf->strings) {
11904 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11905 hf->name, hf_try_val64_to_str_const((gint64) tmpval, hf, "Unknown"));
11906 first = FALSE;
11907 }
11908 else if (!(flags & BMT_NO_INT)) {
11909 char buf[48];
11910 const char *out;
11911
11912 if (!first) {
11913 proto_item_append_text(item, ", ");
11914 }
11915
11916 out = hfinfo_number_value_format64(hf, buf, (gint64) tmpval);
11917 proto_item_append_text(item, "%s: %s", hf->name, out);
11918 first = FALSE;
11919 }
11920
11921 break;
11922
11923 case FT_BOOLEAN:
11924 if (hf->strings && !(flags & BMT_NO_TFS)) {
11925 /* If we have true/false strings, emit full - otherwise messages
11926 might look weird */
11927 const struct true_false_string *tfs =
11928 (const struct true_false_string *)hf->strings;
11929
11930 if (tmpval) {
11931 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11932 hf->name, tfs->true_string);
11933 first = FALSE;
11934 } else if (!(flags & BMT_NO_FALSE)) {
11935 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
11936 hf->name, tfs->false_string);
11937 first = FALSE;
11938 }
11939 } else if (hf->bitmask & value) {
11940 /* If the flag is set, show the name */
11941 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
11942 first = FALSE;
11943 }
11944 break;
11945 default:
11946 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
11947 hf->abbrev,
11948 hf->type,
11949 ftype_name(hf->type));
11950 break;
11951 }
11952
11953 fields++;
11954 }
11955
11956 /* XXX: We don't pass the hfi into this function. Perhaps we should,
11957 * but then again most dissectors don't set the bitmask field for
11958 * the higher level bitmask hfi, so calculate the bitmask from the
11959 * fields present. */
11960 if (item) {
11961 bit_offset = len*8 - 1 - ws_ilog2(bitmask);
11962 no_of_bits = ws_ilog2(bitmask) - ws_ctz(bitmask) + 1;
11963 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
11964 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
11965 }
11966 return first;
11967 }
11968
11969 /* This function will dissect a sequence of bytes that describe a
11970 * bitmask and supply the value of that sequence through a pointer.
11971 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
11972 * to be dissected.
11973 * This field will form an expansion under which the individual fields of the
11974 * bitmask is dissected and displayed.
11975 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
11976 *
11977 * fields is an array of pointers to int that lists all the fields of the
11978 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
11979 * or another integer of the same type/size as hf_hdr with a mask specified.
11980 * This array is terminated by a NULL entry.
11981 *
11982 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
11983 * FT_integer fields that have a value_string attached will have the
11984 * matched string displayed on the expansion line.
11985 */
11986 proto_item *
proto_tree_add_bitmask_ret_uint64(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const int hf_hdr,const gint ett,int * const * fields,const guint encoding,guint64 * retval)11987 proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
11988 const guint offset, const int hf_hdr,
11989 const gint ett, int * const *fields,
11990 const guint encoding, guint64 *retval)
11991 {
11992 return proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, retval);
11993 }
11994
11995 /* This function will dissect a sequence of bytes that describe a
11996 * bitmask.
11997 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
11998 * to be dissected.
11999 * This field will form an expansion under which the individual fields of the
12000 * bitmask is dissected and displayed.
12001 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12002 *
12003 * fields is an array of pointers to int that lists all the fields of the
12004 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12005 * or another integer of the same type/size as hf_hdr with a mask specified.
12006 * This array is terminated by a NULL entry.
12007 *
12008 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12009 * FT_integer fields that have a value_string attached will have the
12010 * matched string displayed on the expansion line.
12011 */
12012 proto_item *
proto_tree_add_bitmask(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const int hf_hdr,const gint ett,int * const * fields,const guint encoding)12013 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
12014 const guint offset, const int hf_hdr,
12015 const gint ett, int * const *fields,
12016 const guint encoding)
12017 {
12018 return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
12019 }
12020
12021 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12022 * what data is appended to the header.
12023 */
12024 proto_item *
proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const int hf_hdr,const gint ett,int * const * fields,const guint encoding,const int flags,guint64 * retval)12025 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
12026 const int hf_hdr, const gint ett, int * const *fields, const guint encoding, const int flags,
12027 guint64 *retval)
12028 {
12029 proto_item *item = NULL;
12030 header_field_info *hf;
12031 int len;
12032 guint64 value;
12033
12034 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12035 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12036 len = ftype_length(hf->type);
12037 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12038
12039 if (parent_tree) {
12040 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
12041 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12042 flags, FALSE, FALSE, NULL, value);
12043 }
12044
12045 *retval = value;
12046 if (hf->bitmask) {
12047 /* Mask out irrelevant portions */
12048 *retval &= hf->bitmask;
12049 /* Shift bits */
12050 *retval >>= hfinfo_bitshift(hf);
12051 }
12052
12053 return item;
12054 }
12055
12056 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12057 * what data is appended to the header.
12058 */
12059 proto_item *
proto_tree_add_bitmask_with_flags(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const int hf_hdr,const gint ett,int * const * fields,const guint encoding,const int flags)12060 proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
12061 const int hf_hdr, const gint ett, int * const *fields, const guint encoding, const int flags)
12062 {
12063 proto_item *item = NULL;
12064 header_field_info *hf;
12065 int len;
12066 guint64 value;
12067
12068 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12069 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12070
12071 if (parent_tree) {
12072 len = ftype_length(hf->type);
12073 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
12074 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12075 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12076 flags, FALSE, FALSE, NULL, value);
12077 }
12078
12079 return item;
12080 }
12081
12082 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
12083 can't be retrieved directly from tvb) */
12084 proto_item *
proto_tree_add_bitmask_value(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const int hf_hdr,const gint ett,int * const * fields,const guint64 value)12085 proto_tree_add_bitmask_value(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
12086 const int hf_hdr, const gint ett, int * const *fields, const guint64 value)
12087 {
12088 return proto_tree_add_bitmask_value_with_flags(parent_tree, tvb, offset,
12089 hf_hdr, ett, fields, value, BMT_NO_INT|BMT_NO_TFS);
12090 }
12091
12092 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
12093 WS_DLL_PUBLIC proto_item *
proto_tree_add_bitmask_value_with_flags(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const int hf_hdr,const gint ett,int * const * fields,const guint64 value,const int flags)12094 proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
12095 const int hf_hdr, const gint ett, int * const *fields, const guint64 value, const int flags)
12096 {
12097 proto_item *item = NULL;
12098 header_field_info *hf;
12099 int len;
12100
12101 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12102 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12103 /* the proto_tree_add_uint/_uint64() calls below
12104 will fail if tvb==NULL and len!=0 */
12105 len = tvb ? ftype_length(hf->type) : 0;
12106
12107 if (parent_tree) {
12108 if (len <= 4)
12109 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, (guint32)value);
12110 else
12111 item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
12112
12113 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12114 flags, FALSE, FALSE, NULL, value);
12115 }
12116
12117 return item;
12118 }
12119
12120 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
12121 void
proto_tree_add_bitmask_list(proto_tree * tree,tvbuff_t * tvb,const guint offset,const int len,int * const * fields,const guint encoding)12122 proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const guint offset,
12123 const int len, int * const *fields, const guint encoding)
12124 {
12125 guint64 value;
12126
12127 if (tree) {
12128 value = get_uint64_value(tree, tvb, offset, len, encoding);
12129 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12130 BMT_NO_APPEND, FALSE, TRUE, tree, value);
12131 }
12132 }
12133
12134 WS_DLL_PUBLIC void
proto_tree_add_bitmask_list_value(proto_tree * tree,tvbuff_t * tvb,const guint offset,const int len,int * const * fields,const guint64 value)12135 proto_tree_add_bitmask_list_value(proto_tree *tree, tvbuff_t *tvb, const guint offset,
12136 const int len, int * const *fields, const guint64 value)
12137 {
12138 if (tree) {
12139 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12140 BMT_NO_APPEND, FALSE, TRUE, tree, value);
12141 }
12142 }
12143
12144
12145 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
12146 * This is intended to support bitmask fields whose lengths can vary, perhaps
12147 * as the underlying standard evolves over time.
12148 * With this API there is the possibility of being called to display more or
12149 * less data than the dissector was coded to support.
12150 * In such cases, it is assumed that bitmasks are extended on the MSb end.
12151 * Thus when presented with "too much" or "too little" data, MSbits will be
12152 * ignored or MSfields sacrificed.
12153 *
12154 * Only fields for which all defined bits are available are displayed.
12155 */
12156 proto_item *
proto_tree_add_bitmask_len(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const guint len,const int hf_hdr,const gint ett,int * const * fields,struct expert_field * exp,const guint encoding)12157 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
12158 const guint offset, const guint len, const int hf_hdr,
12159 const gint ett, int * const *fields, struct expert_field* exp,
12160 const guint encoding)
12161 {
12162 proto_item *item = NULL;
12163 header_field_info *hf;
12164 guint decodable_len;
12165 guint decodable_offset;
12166 guint32 decodable_value;
12167 guint64 value;
12168
12169 PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
12170 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12171
12172 decodable_offset = offset;
12173 decodable_len = MIN(len, (guint) ftype_length(hf->type));
12174
12175 /* If we are ftype_length-limited,
12176 * make sure we decode as many LSBs as possible.
12177 */
12178 if (encoding == ENC_BIG_ENDIAN) {
12179 decodable_offset += (len - decodable_len);
12180 }
12181
12182 if (parent_tree) {
12183 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
12184 decodable_len, encoding);
12185
12186 /* The root item covers all the bytes even if we can't decode them all */
12187 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
12188 decodable_value);
12189 }
12190
12191 if (decodable_len < len) {
12192 /* Dissector likely requires updating for new protocol revision */
12193 expert_add_info_format(NULL, item, exp,
12194 "Only least-significant %d of %d bytes decoded",
12195 decodable_len, len);
12196 }
12197
12198 if (item) {
12199 value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
12200 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
12201 ett, fields, BMT_NO_INT|BMT_NO_TFS, FALSE, FALSE, NULL, value);
12202 }
12203
12204 return item;
12205 }
12206
12207 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
12208 proto_item *
proto_tree_add_bitmask_text(proto_tree * parent_tree,tvbuff_t * tvb,const guint offset,const guint len,const char * name,const char * fallback,const gint ett,int * const * fields,const guint encoding,const int flags)12209 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
12210 const guint offset, const guint len,
12211 const char *name, const char *fallback,
12212 const gint ett, int * const *fields,
12213 const guint encoding, const int flags)
12214 {
12215 proto_item *item = NULL;
12216 guint64 value;
12217
12218 if (parent_tree) {
12219 item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
12220 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12221 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12222 flags, TRUE, FALSE, NULL, value) && fallback) {
12223 /* Still at first item - append 'fallback' text if any */
12224 proto_item_append_text(item, "%s", fallback);
12225 }
12226 }
12227
12228 return item;
12229 }
12230
12231 proto_item *
proto_tree_add_bits_item(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,const guint encoding)12232 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
12233 const guint bit_offset, const gint no_of_bits,
12234 const guint encoding)
12235 {
12236 header_field_info *hfinfo;
12237 gint octet_length;
12238 gint octet_offset;
12239
12240 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
12241
12242 octet_length = (no_of_bits + 7) >> 3;
12243 octet_offset = bit_offset >> 3;
12244 test_length(hfinfo, tvb, octet_offset, octet_length, encoding);
12245
12246 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
12247 * but only after doing a bunch more work (which we can, in the common
12248 * case, shortcut here).
12249 */
12250 CHECK_FOR_NULL_TREE(tree);
12251 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
12252
12253 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
12254 }
12255
12256 /*
12257 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
12258 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
12259 * Offset should be given in bits from the start of the tvb.
12260 */
12261
12262 static proto_item *
_proto_tree_add_bits_ret_val(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,guint64 * return_value,const guint encoding)12263 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
12264 const guint bit_offset, const gint no_of_bits,
12265 guint64 *return_value, const guint encoding)
12266 {
12267 gint offset;
12268 guint length;
12269 guint8 tot_no_bits;
12270 char *bf_str;
12271 char lbl_str[ITEM_LABEL_LENGTH];
12272 guint64 value = 0;
12273 guint8 *bytes = NULL;
12274 size_t bytes_length = 0;
12275
12276 proto_item *pi;
12277 header_field_info *hf_field;
12278
12279 const true_false_string *tfstring;
12280
12281 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
12282 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
12283
12284 if (hf_field->bitmask != 0) {
12285 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_ret_val"
12286 " with field '%s' (%s) with bitmask != 0",
12287 hf_field->abbrev, hf_field->name);
12288 }
12289
12290 if (no_of_bits == 0) {
12291 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of 0",
12292 hf_field->abbrev);
12293 }
12294
12295 /* Byte align offset */
12296 offset = bit_offset>>3;
12297
12298 /*
12299 * Calculate the number of octets used to hold the bits
12300 */
12301 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
12302 length = (tot_no_bits + 7) >> 3;
12303
12304 if (no_of_bits < 65) {
12305 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
12306 } else if (hf_field->type != FT_BYTES) {
12307 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of %u > 65",
12308 hf_field->abbrev, no_of_bits);
12309 return NULL;
12310 }
12311
12312 /* Sign extend for signed types */
12313 switch (hf_field->type) {
12314 case FT_INT8:
12315 case FT_INT16:
12316 case FT_INT24:
12317 case FT_INT32:
12318 case FT_INT40:
12319 case FT_INT48:
12320 case FT_INT56:
12321 case FT_INT64:
12322 value = ws_sign_ext64(value, no_of_bits);
12323 break;
12324
12325 default:
12326 break;
12327 }
12328
12329 if (return_value) {
12330 *return_value = value;
12331 }
12332
12333 /* Coast clear. Try and fake it */
12334 CHECK_FOR_NULL_TREE(tree);
12335 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12336
12337 bf_str = decode_bits_in_field(PNODE_POOL(tree), bit_offset, no_of_bits, value, encoding);
12338
12339 switch (hf_field->type) {
12340 case FT_BOOLEAN:
12341 /* Boolean field */
12342 tfstring = &tfs_true_false;
12343 if (hf_field->strings)
12344 tfstring = (const true_false_string *)hf_field->strings;
12345 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
12346 "%s = %s: %s",
12347 bf_str, hf_field->name, tfs_get_string(!!value, tfstring));
12348 break;
12349
12350 case FT_CHAR:
12351 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
12352 fill_label_char(PITEM_FINFO(pi), lbl_str);
12353 break;
12354
12355 case FT_UINT8:
12356 case FT_UINT16:
12357 case FT_UINT24:
12358 case FT_UINT32:
12359 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
12360 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
12361 break;
12362
12363 case FT_INT8:
12364 case FT_INT16:
12365 case FT_INT24:
12366 case FT_INT32:
12367 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
12368 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
12369 break;
12370
12371 case FT_UINT40:
12372 case FT_UINT48:
12373 case FT_UINT56:
12374 case FT_UINT64:
12375 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
12376 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
12377 break;
12378
12379 case FT_INT40:
12380 case FT_INT48:
12381 case FT_INT56:
12382 case FT_INT64:
12383 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
12384 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
12385 break;
12386
12387 case FT_BYTES:
12388 bytes = tvb_get_bits_array(PNODE_POOL(tree), tvb, bit_offset, no_of_bits, &bytes_length, encoding);
12389 pi = proto_tree_add_bytes_with_length(tree, hfindex, tvb, offset, length, bytes, (gint) bytes_length);
12390 proto_item_fill_label(PITEM_FINFO(pi), lbl_str);
12391 proto_item_set_text(pi, "%s", lbl_str);
12392 return pi;
12393 break;
12394
12395 default:
12396 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_ret_val()",
12397 hf_field->abbrev,
12398 hf_field->type,
12399 ftype_name(hf_field->type));
12400 return NULL;
12401 break;
12402 }
12403
12404 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
12405 return pi;
12406 }
12407
12408 proto_item *
proto_tree_add_split_bits_item_ret_val(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const crumb_spec_t * crumb_spec,guint64 * return_value)12409 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
12410 const guint bit_offset, const crumb_spec_t *crumb_spec,
12411 guint64 *return_value)
12412 {
12413 proto_item *pi;
12414 gint no_of_bits;
12415 gint octet_offset;
12416 guint mask_initial_bit_offset;
12417 guint mask_greatest_bit_offset;
12418 guint octet_length;
12419 guint8 i;
12420 char bf_str[256];
12421 char lbl_str[ITEM_LABEL_LENGTH];
12422 guint64 value;
12423 guint64 composite_bitmask;
12424 guint64 composite_bitmap;
12425
12426 header_field_info *hf_field;
12427 const true_false_string *tfstring;
12428
12429 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
12430 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
12431
12432 if (hf_field->bitmask != 0) {
12433 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_split_bits_item_ret_val"
12434 " with field '%s' (%s) with bitmask != 0",
12435 hf_field->abbrev, hf_field->name);
12436 }
12437
12438 mask_initial_bit_offset = bit_offset % 8;
12439
12440 no_of_bits = 0;
12441 value = 0;
12442 i = 0;
12443 mask_greatest_bit_offset = 0;
12444 composite_bitmask = 0;
12445 composite_bitmap = 0;
12446
12447 while (crumb_spec[i].crumb_bit_length != 0) {
12448 guint64 crumb_mask, crumb_value;
12449 guint8 crumb_end_bit_offset;
12450
12451 crumb_value = tvb_get_bits64(tvb,
12452 bit_offset + crumb_spec[i].crumb_bit_offset,
12453 crumb_spec[i].crumb_bit_length,
12454 ENC_BIG_ENDIAN);
12455 value += crumb_value;
12456 no_of_bits += crumb_spec[i].crumb_bit_length;
12457 DISSECTOR_ASSERT_HINT(no_of_bits <= 64, "a value larger than 64 bits cannot be represented");
12458
12459 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
12460 octet containing the initial offset.
12461 If the mask is beyond 32 bits, then give up on bit map display.
12462 This could be improved in future, probably showing a table
12463 of 32 or 64 bits per row */
12464 if (mask_greatest_bit_offset < 32) {
12465 crumb_end_bit_offset = mask_initial_bit_offset
12466 + crumb_spec[i].crumb_bit_offset
12467 + crumb_spec[i].crumb_bit_length;
12468 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
12469
12470 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
12471 mask_greatest_bit_offset = crumb_end_bit_offset;
12472 }
12473 /* Currently the bitmap of the crumbs are only shown if
12474 * smaller than 32 bits. Do not bother calculating the
12475 * mask if it is larger than that. */
12476 if (crumb_end_bit_offset <= 32) {
12477 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
12478 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
12479 }
12480 }
12481 /* Shift left for the next segment */
12482 value <<= crumb_spec[++i].crumb_bit_length;
12483 }
12484
12485 /* Sign extend for signed types */
12486 switch (hf_field->type) {
12487 case FT_INT8:
12488 case FT_INT16:
12489 case FT_INT24:
12490 case FT_INT32:
12491 case FT_INT40:
12492 case FT_INT48:
12493 case FT_INT56:
12494 case FT_INT64:
12495 value = ws_sign_ext64(value, no_of_bits);
12496 break;
12497 default:
12498 break;
12499 }
12500
12501 if (return_value) {
12502 *return_value = value;
12503 }
12504
12505 /* Coast clear. Try and fake it */
12506 CHECK_FOR_NULL_TREE(tree);
12507 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12508
12509 /* initialise the format string */
12510 bf_str[0] = '\0';
12511
12512 octet_offset = bit_offset >> 3;
12513
12514 /* Round up mask length to nearest octet */
12515 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
12516 mask_greatest_bit_offset = octet_length << 3;
12517
12518 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
12519 It would be a useful enhancement to eliminate this restriction. */
12520 if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
12521 other_decode_bitfield_value(bf_str,
12522 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
12523 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
12524 mask_greatest_bit_offset);
12525 } else {
12526 /* If the bitmask is too large, try to describe its contents. */
12527 g_snprintf(bf_str, sizeof(bf_str), "%d bits", no_of_bits);
12528 }
12529
12530 switch (hf_field->type) {
12531 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
12532 /* Boolean field */
12533 tfstring = &tfs_true_false;
12534 if (hf_field->strings)
12535 tfstring = (const true_false_string *) hf_field->strings;
12536 return proto_tree_add_boolean_format(tree, hfindex,
12537 tvb, octet_offset, octet_length, (guint32)value,
12538 "%s = %s: %s",
12539 bf_str, hf_field->name, tfs_get_string(!!value, tfstring));
12540 break;
12541
12542 case FT_CHAR:
12543 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
12544 fill_label_char(PITEM_FINFO(pi), lbl_str);
12545 break;
12546
12547 case FT_UINT8:
12548 case FT_UINT16:
12549 case FT_UINT24:
12550 case FT_UINT32:
12551 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
12552 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
12553 break;
12554
12555 case FT_INT8:
12556 case FT_INT16:
12557 case FT_INT24:
12558 case FT_INT32:
12559 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
12560 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
12561 break;
12562
12563 case FT_UINT40:
12564 case FT_UINT48:
12565 case FT_UINT56:
12566 case FT_UINT64:
12567 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
12568 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
12569 break;
12570
12571 case FT_INT40:
12572 case FT_INT48:
12573 case FT_INT56:
12574 case FT_INT64:
12575 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
12576 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
12577 break;
12578
12579 default:
12580 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_split_bits_item_ret_val()",
12581 hf_field->abbrev,
12582 hf_field->type,
12583 ftype_name(hf_field->type));
12584 return NULL;
12585 break;
12586 }
12587 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
12588 return pi;
12589 }
12590
12591 void
proto_tree_add_split_bits_crumb(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const crumb_spec_t * crumb_spec,guint16 crumb_index)12592 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
12593 const crumb_spec_t *crumb_spec, guint16 crumb_index)
12594 {
12595 header_field_info *hfinfo;
12596 gint start = bit_offset >> 3;
12597 gint length = ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1;
12598
12599 /* We have to duplicate this length check from proto_tree_add_text_internal in order to check for a null tree
12600 * so that we can use the tree's memory scope in calculating the string */
12601 if (length == -1) {
12602 tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
12603 } else {
12604 tvb_ensure_bytes_exist(tvb, start, length);
12605 }
12606 if (!tree) return;
12607
12608 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
12609 proto_tree_add_text_internal(tree, tvb, start, length,
12610 "%s crumb %d of %s (decoded above)",
12611 decode_bits_in_field(PNODE_POOL(tree), bit_offset, crumb_spec[crumb_index].crumb_bit_length,
12612 tvb_get_bits(tvb,
12613 bit_offset,
12614 crumb_spec[crumb_index].crumb_bit_length,
12615 ENC_BIG_ENDIAN),
12616 ENC_BIG_ENDIAN),
12617 crumb_index,
12618 hfinfo->name);
12619 }
12620
12621 proto_item *
proto_tree_add_bits_ret_val(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,guint64 * return_value,const guint encoding)12622 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
12623 const guint bit_offset, const gint no_of_bits,
12624 guint64 *return_value, const guint encoding)
12625 {
12626 proto_item *item;
12627
12628 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
12629 bit_offset, no_of_bits,
12630 return_value, encoding))) {
12631 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
12632 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
12633 }
12634 return item;
12635 }
12636
12637 static proto_item *
_proto_tree_add_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,void * value_ptr,const guint encoding,gchar * value_str)12638 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
12639 tvbuff_t *tvb, const guint bit_offset,
12640 const gint no_of_bits, void *value_ptr,
12641 const guint encoding, gchar *value_str)
12642 {
12643 gint offset;
12644 guint length;
12645 guint8 tot_no_bits;
12646 char *str;
12647 guint64 value = 0;
12648 header_field_info *hf_field;
12649
12650 /* We do not have to return a value, try to fake it as soon as possible */
12651 CHECK_FOR_NULL_TREE(tree);
12652 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12653
12654 if (hf_field->bitmask != 0) {
12655 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_format_value"
12656 " with field '%s' (%s) with bitmask != 0",
12657 hf_field->abbrev, hf_field->name);
12658 }
12659
12660 if (no_of_bits == 0) {
12661 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of 0",
12662 hf_field->abbrev);
12663 }
12664
12665 /* Byte align offset */
12666 offset = bit_offset>>3;
12667
12668 /*
12669 * Calculate the number of octets used to hold the bits
12670 */
12671 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
12672 length = tot_no_bits>>3;
12673 /* If we are using part of the next octet, increase length by 1 */
12674 if (tot_no_bits & 0x07)
12675 length++;
12676
12677 if (no_of_bits < 65) {
12678 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
12679 } else {
12680 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of %u > 65",
12681 hf_field->abbrev, no_of_bits);
12682 return NULL;
12683 }
12684
12685 str = decode_bits_in_field(PNODE_POOL(tree), bit_offset, no_of_bits, value, encoding);
12686
12687 (void) g_strlcat(str, " = ", 256+64);
12688 (void) g_strlcat(str, hf_field->name, 256+64);
12689
12690 /*
12691 * This function does not receive an actual value but a dimensionless pointer to that value.
12692 * For this reason, the type of the header field is examined in order to determine
12693 * what kind of value we should read from this address.
12694 * The caller of this function must make sure that for the specific header field type the address of
12695 * a compatible value is provided.
12696 */
12697 switch (hf_field->type) {
12698 case FT_BOOLEAN:
12699 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
12700 "%s: %s", str, value_str);
12701 break;
12702
12703 case FT_CHAR:
12704 case FT_UINT8:
12705 case FT_UINT16:
12706 case FT_UINT24:
12707 case FT_UINT32:
12708 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
12709 "%s: %s", str, value_str);
12710 break;
12711
12712 case FT_UINT40:
12713 case FT_UINT48:
12714 case FT_UINT56:
12715 case FT_UINT64:
12716 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
12717 "%s: %s", str, value_str);
12718 break;
12719
12720 case FT_INT8:
12721 case FT_INT16:
12722 case FT_INT24:
12723 case FT_INT32:
12724 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
12725 "%s: %s", str, value_str);
12726 break;
12727
12728 case FT_INT40:
12729 case FT_INT48:
12730 case FT_INT56:
12731 case FT_INT64:
12732 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
12733 "%s: %s", str, value_str);
12734 break;
12735
12736 case FT_FLOAT:
12737 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
12738 "%s: %s", str, value_str);
12739 break;
12740
12741 default:
12742 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_format_value()",
12743 hf_field->abbrev,
12744 hf_field->type,
12745 ftype_name(hf_field->type));
12746 return NULL;
12747 break;
12748 }
12749 }
12750
12751 static proto_item *
proto_tree_add_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,void * value_ptr,const guint encoding,gchar * value_str)12752 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
12753 tvbuff_t *tvb, const guint bit_offset,
12754 const gint no_of_bits, void *value_ptr,
12755 const guint encoding, gchar *value_str)
12756 {
12757 proto_item *item;
12758
12759 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
12760 tvb, bit_offset, no_of_bits,
12761 value_ptr, encoding, value_str))) {
12762 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
12763 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
12764 }
12765 return item;
12766 }
12767
12768 #define CREATE_VALUE_STRING(tree,dst,format,ap) \
12769 va_start(ap, format); \
12770 dst = wmem_strdup_vprintf(PNODE_POOL(tree), format, ap); \
12771 va_end(ap);
12772
12773 proto_item *
proto_tree_add_uint_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,guint32 value,const guint encoding,const char * format,...)12774 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
12775 tvbuff_t *tvb, const guint bit_offset,
12776 const gint no_of_bits, guint32 value,
12777 const guint encoding,
12778 const char *format, ...)
12779 {
12780 va_list ap;
12781 gchar *dst;
12782 header_field_info *hf_field;
12783
12784 CHECK_FOR_NULL_TREE(tree);
12785
12786 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12787
12788 switch (hf_field->type) {
12789 case FT_UINT8:
12790 case FT_UINT16:
12791 case FT_UINT24:
12792 case FT_UINT32:
12793 break;
12794
12795 default:
12796 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
12797 hf_field->abbrev);
12798 return NULL;
12799 break;
12800 }
12801
12802 CREATE_VALUE_STRING(tree, dst, format, ap);
12803
12804 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12805 }
12806
12807 proto_item *
proto_tree_add_uint64_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,guint64 value,const guint encoding,const char * format,...)12808 proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
12809 tvbuff_t *tvb, const guint bit_offset,
12810 const gint no_of_bits, guint64 value,
12811 const guint encoding,
12812 const char *format, ...)
12813 {
12814 va_list ap;
12815 gchar *dst;
12816 header_field_info *hf_field;
12817
12818 CHECK_FOR_NULL_TREE(tree);
12819
12820 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12821
12822 switch (hf_field->type) {
12823 case FT_UINT40:
12824 case FT_UINT48:
12825 case FT_UINT56:
12826 case FT_UINT64:
12827 break;
12828
12829 default:
12830 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
12831 hf_field->abbrev);
12832 return NULL;
12833 break;
12834 }
12835
12836 CREATE_VALUE_STRING(tree, dst, format, ap);
12837
12838 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12839 }
12840
12841 proto_item *
proto_tree_add_float_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,float value,const guint encoding,const char * format,...)12842 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
12843 tvbuff_t *tvb, const guint bit_offset,
12844 const gint no_of_bits, float value,
12845 const guint encoding,
12846 const char *format, ...)
12847 {
12848 va_list ap;
12849 gchar *dst;
12850 header_field_info *hf_field;
12851
12852 CHECK_FOR_NULL_TREE(tree);
12853
12854 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12855
12856 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
12857
12858 CREATE_VALUE_STRING(tree, dst, format, ap);
12859
12860 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12861 }
12862
12863 proto_item *
proto_tree_add_int_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,gint32 value,const guint encoding,const char * format,...)12864 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
12865 tvbuff_t *tvb, const guint bit_offset,
12866 const gint no_of_bits, gint32 value,
12867 const guint encoding,
12868 const char *format, ...)
12869 {
12870 va_list ap;
12871 gchar *dst;
12872 header_field_info *hf_field;
12873
12874 CHECK_FOR_NULL_TREE(tree);
12875
12876 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12877
12878 switch (hf_field->type) {
12879 case FT_INT8:
12880 case FT_INT16:
12881 case FT_INT24:
12882 case FT_INT32:
12883 break;
12884
12885 default:
12886 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
12887 hf_field->abbrev);
12888 return NULL;
12889 break;
12890 }
12891
12892 CREATE_VALUE_STRING(tree, dst, format, ap);
12893
12894 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12895 }
12896
12897 proto_item *
proto_tree_add_int64_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,gint64 value,const guint encoding,const char * format,...)12898 proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
12899 tvbuff_t *tvb, const guint bit_offset,
12900 const gint no_of_bits, gint64 value,
12901 const guint encoding,
12902 const char *format, ...)
12903 {
12904 va_list ap;
12905 gchar *dst;
12906 header_field_info *hf_field;
12907
12908 CHECK_FOR_NULL_TREE(tree);
12909
12910 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12911
12912 switch (hf_field->type) {
12913 case FT_INT40:
12914 case FT_INT48:
12915 case FT_INT56:
12916 case FT_INT64:
12917 break;
12918
12919 default:
12920 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
12921 hf_field->abbrev);
12922 return NULL;
12923 break;
12924 }
12925
12926 CREATE_VALUE_STRING(tree, dst, format, ap);
12927
12928 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12929 }
12930
12931 proto_item *
proto_tree_add_boolean_bits_format_value(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,guint32 value,const guint encoding,const char * format,...)12932 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
12933 tvbuff_t *tvb, const guint bit_offset,
12934 const gint no_of_bits, guint32 value,
12935 const guint encoding,
12936 const char *format, ...)
12937 {
12938 va_list ap;
12939 gchar *dst;
12940 header_field_info *hf_field;
12941
12942 CHECK_FOR_NULL_TREE(tree);
12943
12944 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12945
12946 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
12947
12948 CREATE_VALUE_STRING(tree, dst, format, ap);
12949
12950 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12951 }
12952
12953 proto_item *
proto_tree_add_boolean_bits_format_value64(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_bits,guint64 value,const guint encoding,const char * format,...)12954 proto_tree_add_boolean_bits_format_value64(proto_tree *tree, const int hfindex,
12955 tvbuff_t *tvb, const guint bit_offset,
12956 const gint no_of_bits, guint64 value,
12957 const guint encoding,
12958 const char *format, ...)
12959 {
12960 va_list ap;
12961 gchar *dst;
12962 header_field_info *hf_field;
12963
12964 CHECK_FOR_NULL_TREE(tree);
12965
12966 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
12967
12968 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
12969
12970 CREATE_VALUE_STRING(tree, dst, format, ap);
12971
12972 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
12973 }
12974
12975 proto_item *
proto_tree_add_ts_23_038_7bits_packed_item(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_chars)12976 proto_tree_add_ts_23_038_7bits_packed_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
12977 const guint bit_offset, const gint no_of_chars)
12978 {
12979 proto_item *pi;
12980 header_field_info *hfinfo;
12981 gint byte_length;
12982 gint byte_offset;
12983 gchar *string;
12984
12985 CHECK_FOR_NULL_TREE(tree);
12986
12987 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
12988
12989 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
12990
12991 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
12992 byte_offset = bit_offset >> 3;
12993
12994 string = tvb_get_ts_23_038_7bits_string_packed(PNODE_POOL(tree), tvb, bit_offset, no_of_chars);
12995
12996 if (hfinfo->display == STR_UNICODE) {
12997 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
12998 }
12999
13000 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
13001 DISSECTOR_ASSERT(byte_length >= 0);
13002 proto_tree_set_string(PNODE_FINFO(pi), string);
13003
13004 return pi;
13005 }
13006
13007 proto_item *
proto_tree_add_ascii_7bits_item(proto_tree * tree,const int hfindex,tvbuff_t * tvb,const guint bit_offset,const gint no_of_chars)13008 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13009 const guint bit_offset, const gint no_of_chars)
13010 {
13011 proto_item *pi;
13012 header_field_info *hfinfo;
13013 gint byte_length;
13014 gint byte_offset;
13015 gchar *string;
13016
13017 CHECK_FOR_NULL_TREE(tree);
13018
13019 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13020
13021 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
13022
13023 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
13024 byte_offset = bit_offset >> 3;
13025
13026 string = tvb_get_ascii_7bits_string(PNODE_POOL(tree), tvb, bit_offset, no_of_chars);
13027
13028 if (hfinfo->display == STR_UNICODE) {
13029 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
13030 }
13031
13032 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
13033 DISSECTOR_ASSERT(byte_length >= 0);
13034 proto_tree_set_string(PNODE_FINFO(pi), string);
13035
13036 return pi;
13037 }
13038
13039 const value_string proto_checksum_vals[] = {
13040 { PROTO_CHECKSUM_E_BAD, "Bad" },
13041 { PROTO_CHECKSUM_E_GOOD, "Good" },
13042 { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" },
13043 { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" },
13044 { PROTO_CHECKSUM_E_ILLEGAL, "Illegal" },
13045
13046 { 0, NULL }
13047 };
13048
13049 proto_item *
proto_tree_add_checksum(proto_tree * tree,tvbuff_t * tvb,const guint offset,const int hf_checksum,const int hf_checksum_status,struct expert_field * bad_checksum_expert,packet_info * pinfo,guint32 computed_checksum,const guint encoding,const guint flags)13050 proto_tree_add_checksum(proto_tree *tree, tvbuff_t *tvb, const guint offset,
13051 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
13052 packet_info *pinfo, guint32 computed_checksum, const guint encoding, const guint flags)
13053 {
13054 header_field_info *hfinfo = proto_registrar_get_nth(hf_checksum);
13055 guint32 checksum;
13056 guint32 len;
13057 proto_item* ti = NULL;
13058 proto_item* ti2;
13059 gboolean incorrect_checksum = TRUE;
13060
13061 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
13062
13063 switch (hfinfo->type) {
13064 case FT_UINT8:
13065 len = 1;
13066 break;
13067 case FT_UINT16:
13068 len = 2;
13069 break;
13070 case FT_UINT24:
13071 len = 3;
13072 break;
13073 case FT_UINT32:
13074 len = 4;
13075 break;
13076 default:
13077 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13078 hfinfo->abbrev);
13079 }
13080
13081 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
13082 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, len, 0, "[missing]");
13083 proto_item_set_generated(ti);
13084 if (hf_checksum_status != -1) {
13085 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, len, PROTO_CHECKSUM_E_NOT_PRESENT);
13086 proto_item_set_generated(ti2);
13087 }
13088 return ti;
13089 }
13090
13091 if (flags & PROTO_CHECKSUM_GENERATED) {
13092 ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, len, computed_checksum);
13093 proto_item_set_generated(ti);
13094 } else {
13095 ti = proto_tree_add_item_ret_uint(tree, hf_checksum, tvb, offset, len, encoding, &checksum);
13096 if (flags & PROTO_CHECKSUM_VERIFY) {
13097 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
13098 if (computed_checksum == 0) {
13099 proto_item_append_text(ti, " [correct]");
13100 if (hf_checksum_status != -1) {
13101 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
13102 proto_item_set_generated(ti2);
13103 }
13104 incorrect_checksum = FALSE;
13105 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
13106 computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
13107 }
13108 } else {
13109 if (checksum == computed_checksum) {
13110 proto_item_append_text(ti, " [correct]");
13111 if (hf_checksum_status != -1) {
13112 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
13113 proto_item_set_generated(ti2);
13114 }
13115 incorrect_checksum = FALSE;
13116 }
13117 }
13118
13119 if (incorrect_checksum) {
13120 if (hf_checksum_status != -1) {
13121 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
13122 proto_item_set_generated(ti2);
13123 }
13124 if (flags & PROTO_CHECKSUM_ZERO) {
13125 proto_item_append_text(ti, " [incorrect]");
13126 if (bad_checksum_expert != NULL)
13127 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
13128 } else {
13129 proto_item_append_text(ti, " incorrect, should be 0x%0*x", len*2, computed_checksum);
13130 if (bad_checksum_expert != NULL)
13131 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s [should be 0x%0*x]", expert_get_summary(bad_checksum_expert), len * 2, computed_checksum);
13132 }
13133 }
13134 } else {
13135 if (hf_checksum_status != -1) {
13136 proto_item_append_text(ti, " [unverified]");
13137 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
13138 proto_item_set_generated(ti2);
13139 }
13140 }
13141 }
13142
13143 return ti;
13144 }
13145
13146 guchar
proto_check_field_name(const gchar * field_name)13147 proto_check_field_name(const gchar *field_name)
13148 {
13149 const char *p = field_name;
13150 guchar c = '.', lastc;
13151
13152 do {
13153 lastc = c;
13154 c = *(p++);
13155 /* Leading '.' or substring ".." are disallowed. */
13156 if (c == '.' && lastc == '.') {
13157 break;
13158 }
13159 } while (fld_abbrev_chars[c]);
13160
13161 /* Trailing '.' is disallowed. */
13162 if (lastc == '.') {
13163 return '.';
13164 }
13165 return c;
13166 }
13167
13168 gboolean
tree_expanded(int tree_type)13169 tree_expanded(int tree_type)
13170 {
13171 if (tree_type == -1) {
13172 return FALSE;
13173 }
13174 ws_assert(tree_type >= 0 && tree_type < num_tree_types);
13175 return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
13176 }
13177
13178 void
tree_expanded_set(int tree_type,gboolean value)13179 tree_expanded_set(int tree_type, gboolean value)
13180 {
13181 ws_assert(tree_type >= 0 && tree_type < num_tree_types);
13182
13183 if (value)
13184 tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
13185 else
13186 tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
13187 }
13188
13189 /*
13190 * Editor modelines - https://www.wireshark.org/tools/modelines.html
13191 *
13192 * Local variables:
13193 * c-basic-offset: 8
13194 * tab-width: 8
13195 * indent-tabs-mode: t
13196 * End:
13197 *
13198 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
13199 * :indentSize=8:tabSize=8:noTabs=false:
13200 */
13201