/* proto.c
* Routines for protocol tree
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <
[email protected]>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <float.h>
#include <inttypes.h>
#include <errno.h>
#include "register-int.h"
#include "wmem_strbuf.h"
#include "ftypes.h"
#include "sign_ext.h"
#include "tvbuff.h"
#include "packet.h"
#include "strutil.h"
#include "unit_strings.h"
#include "bits_ctz.h"
#include "bits_count_ones.h"
#include "proto.h"
#include "utf8_entities.h"
/* Ptvcursor limits */
#define SUBTREE_ONCE_ALLOCATION_NUMBER 8
#define SUBTREE_MAX_LEVELS 256
#define max_tree_items 32
typedef struct __subtree_lvl {
int cursor_offset;
proto_item *it;
proto_tree *tree;
} subtree_lvl;
struct ptvcursor {
// wmem_allocator_t *scope;
subtree_lvl *pushed_tree;
uint8_t pushed_tree_index;
uint8_t pushed_tree_max;
proto_tree *tree;
tvbuff_t *tvb;
int offset;
};
#define cVALS(x) (const value_string*)(x)
/** See inlined comments.
@param tree the tree to append this item to
@param free_block a code block to call to free resources if this returns
@return NULL if 'tree' is null */
#define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block) \
if (!tree) { \
free_block; \
return NULL; \
}
/** See inlined comments.
@param tree the tree to append this item to
@param free_block a code block to call to free resources if this returns
@return NULL if 'tree' is null */
#define CHECK_FOR_NULL_TREE(tree) \
CHECK_FOR_NULL_TREE_AND_FREE(tree, ((void)0))
/** See inlined comments.
@param length the length of this item
@param cleanup_block a code block to call to free resources if this returns
@return NULL if 'length' is lower -1 or equal 0 */
#define CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length, cleanup_block) \
if (length < -1 || length == 0 ) { \
cleanup_block; \
return NULL; \
}
/** See inlined comments.
@param length the length of this item
@return NULL if 'length' is lower -1 or equal 0 */
#define CHECK_FOR_ZERO_OR_MINUS_LENGTH(length) \
CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length, ((void)0))
/** See inlined comments.
@param tree the tree to append this item to
@param hfindex field index
@param hfinfo header_field
@param free_block a code block to call to free resources if this returns
@return the header field matching 'hfinfo' */
#define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
/* If the tree is not visible and this item is not referenced \
we don't have to do much work at all but we should still \
return a node so that referenced field items below this node \
(think proto_item_add_subtree()) will still have somewhere \
to attach to or else filtering will not work (they would be \
ignored since tree would be NULL). \
DON'T try to fake a node where PTREE_FINFO(tree) is NULL \
since dissectors that want to do proto_item_set_len() or \
other operations that dereference this would crash. \
DON'T try to fake a node where PTREE_FINFO(tree) is visible \
because that means we can change its length or repr, and we \
don't want to do so with calls intended for this faked new \
item, so this item needs a new (hidden) child node. \
(PROTO_ITEM_IS_HIDDEN(tree) checks both conditions.) \
We fake FT_PROTOCOL unless some clients have requested us \
not to do so. \
*/ \
PTREE_DATA(tree)->count++; \
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
if (PTREE_DATA(tree)->count > max_tree_items) { \
free_block; \
/* Let the exception handler add items to the tree */ \
PTREE_DATA(tree)->count = 0; \
} \
if (!(PTREE_DATA(tree)->visible)) { \
if (PROTO_ITEM_IS_HIDDEN(tree)) { \
if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
&& (hfinfo->ref_type != HF_REF_TYPE_PRINT) \
&& (hfinfo->type != FT_PROTOCOL || \
PTREE_DATA(tree)->fake_protocols)) { \
free_block; \
/* just return tree back to the caller */\
return tree; \
} \
} \
}
/** See inlined comments.
@param tree the tree to append this item to
@param hfindex field index
@param hfinfo header_field
@return the header field matching 'hfinfo' */
#define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
/** See inlined comments.
@param pi the created protocol item we're about to return */
#define TRY_TO_FAKE_THIS_REPR(pi) \
if (!(PTREE_DATA(pi)->visible) && \
PROTO_ITEM_IS_HIDDEN(pi)) { \
/* If the tree (GUI) or item isn't visible it's pointless for \
* us to generate the protocol item's string representation */ \
return pi; \
}
/* Same as above but returning void */
#define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
if (!pi) \
return; \
if (!(PTREE_DATA(pi)->visible) && \
PROTO_ITEM_IS_HIDDEN(pi)) { \
/* If the tree (GUI) or item isn't visible it's pointless for \
* us to generate the protocol item's string representation */ \
return; \
}
/* Similar to above, but allows a NULL tree */
#define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
if ((pi == NULL) || (!(PTREE_DATA(pi)->visible) && \
PROTO_ITEM_IS_HIDDEN(pi))) { \
/* If the tree (GUI) or item isn't visible it's pointless for \
* us to generate the protocol item's string representation */ \
return pi; \
}
#ifdef ENABLE_CHECK_FILTER
#define CHECK_HF_VALUE(type, spec, start_values) \
{ \
const type *current; \
int n, m; \
current = start_values; \
for (n=0; current; n++, current++) { \
/* Drop out if we reached the end. */ \
if ((current->value == 0) && (current->strptr == NULL)) { \
break; \
} \
/* Check value against all previous */ \
for (m=0; m < n; m++) { \
/* There are lots of duplicates with the same string, \
so only report if different... */ \
if ((start_values[m].value == current->value) && \
(strcmp(start_values[m].strptr, current->strptr) != 0)) { \
printf("Field '%s' (%s) has a conflicting entry in its" \
" value_string: %" spec " is at indices %u (%s) and %u (%s)", \
hfinfo->name, hfinfo->abbrev, \
current->value, m, start_values[m].strptr, n, current->strptr); \
} \
} \
} \
}
#endif
/* The longest NUMBER-like field label we have is for BASE_OUI, which
* can have up to 64 bytes for the manufacturer name if resolved plus
* 11 bytes for the "XX:XX:XX ()" part = 75 octets.
*/
#define NUMBER_LABEL_LENGTH 80
static const char *hf_try_val_to_str(uint32_t value, const header_field_info *hfinfo);
static const char *hf_try_val64_to_str(uint64_t value, const header_field_info *hfinfo);
static const char *hf_try_val_to_str_const(uint32_t value, const header_field_info *hfinfo, const char *unknown_str);
static const char *hf_try_val64_to_str_const(uint64_t value, const header_field_info *hfinfo, const char *unknow