Commit message: epan: Fix a memory leak.

Make sure _proto_tree_add_bits_ret_val allocates a bits array using the
packet scope, otherwise we leak memory. Fixes #17032.
CVE: CVE-2020-26419
CWE: CWE-401
Vulnerability description: Memory leak in the dissection engine in Wireshark 3.4.0 allows denial of service via packet injection or crafted capture file.

Project: wireshark

register_number_string_decoding_error(void)
{
	static ei_register_info ei[] = {
		{ &ei_number_string_decoding_failed_error,
			{ "_ws.number_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
			  "Failed to decode number from string", EXPFILL
			}
		},
		{ &ei_number_string_decoding_erange_error,
			{ "_ws.number_string.decoding_error.erange", PI_MALFORMED, PI_ERROR,
			  "Decoded number from string is out of valid range", EXPFILL
			}
		},
	};

	expert_module_t* expert_number_string_decoding_error;

	proto_number_string_decoding_error =
		proto_register_protocol("Number-String Decoding Error",
					"Number-string decoding error",
					"_ws.number_string.decoding_error");

	expert_number_string_decoding_error =
		expert_register_protocol(proto_number_string_decoding_error);
	expert_register_field_array(expert_number_string_decoding_error, ei, array_length(ei));

	/* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
	   disabling them makes no sense. */
	proto_set_cant_toggle(proto_number_string_decoding_error);
}

Project: wireshark

proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			     gint start, gint length, const char* value,
			     const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

test_length(header_field_info *hfinfo, tvbuff_t *tvb,
	    gint start, gint length, const guint encoding)
{
	gint size = length;

	if (!tvb)
		return;

	if ((hfinfo->type == FT_STRINGZ) ||
	    ((encoding & (ENC_VARIANT_MASK)) &&
	     (IS_FT_UINT(hfinfo->type) || IS_FT_INT(hfinfo->type)))) {
		/* If we're fetching until the end of the TVB, only validate
		 * that the offset is within range.
		 */
		if (length == -1)
			size = 0;
	}

	tvb_ensure_bytes_exist(tvb, start, size);
}

Project: wireshark

hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
{
	/* Get the underlying BASE_ value */
	int display = FIELD_DISPLAY(hfinfo->display);

	if (display == BASE_NONE)
		return NULL;

	if (display == BASE_DEC_HEX)
		display = BASE_DEC;
	if (display == BASE_HEX_DEC)
		display = BASE_HEX;

	return hfinfo_number_value_format_display(hfinfo, display, buf, value);
}

Project: wireshark

proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
{
	proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
}

Project: wireshark

ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
{
	ptvcursor_push_subtree(ptvc, it, ett_subtree);
	if (length == SUBTREE_UNDEFINED_LENGTH)
		ptvcursor_subtree_set_item(ptvc, it);
	return ptvcursor_tree(ptvc);
}

Project: wireshark

proto_item_set_len(proto_item *pi, const gint length)
{
	field_info *fi;

	TRY_TO_FAKE_THIS_REPR_VOID(pi);

	fi = PITEM_FINFO(pi);
	if (fi == NULL)
		return;

	finfo_set_len(fi, length);
}

Project: wireshark

proto_name_already_registered(const gchar *name)
{
	DISSECTOR_ASSERT_HINT(name, "No name present");

	if (g_hash_table_lookup(proto_names, name) != NULL)
		return TRUE;
	return FALSE;
}

Project: wireshark

proto_tree_set_int64(field_info *fi, gint64 value)
{
	header_field_info *hfinfo;
	guint64		   integer;
	gint		   no_of_bits;

	hfinfo = fi->hfinfo;
	integer = value;

	if (hfinfo->bitmask) {
		/* Mask out irrelevant portions */
		integer &= hfinfo->bitmask;

		/* Shift bits */
		integer >>= hfinfo_bitshift(hfinfo);

		no_of_bits = ws_count_ones(hfinfo->bitmask);
		integer = ws_sign_ext64(integer, no_of_bits);

		FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
		FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
	}

	fvalue_set_sinteger64(&fi->value, integer);
}

Project: wireshark

proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
		  gint *length)
{
	proto_item *pi;
	field_info *fi;
	gint		item_length;

	get_hfi_length(hfinfo, tvb, start, length, &item_length, ENC_NA);
	fi = new_field_info(tree, hfinfo, tvb, start, item_length);
	pi = proto_tree_add_node(tree, fi);

	return pi;
}

Project: wireshark

proto_register_plugin(const proto_plugin *plug)
{
	if (!plug) {
		/* XXX print useful warning */
		return;
	}
	dissector_plugins = g_slist_prepend(dissector_plugins, (proto_plugin *)plug);
}

Project: wireshark

get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
    gint start, gint length, gint *ret_length, const guint encoding)
{
	const guint8 *value;

	if (length < -1) {
		report_type_length_mismatch(tree, "a string", length, TRUE);
	}
	if (length == -1) {
		/* This can throw an exception */
		value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
	} else {
		/* In this case, length signifies the length of the string.
		 *
		 * This could either be a null-padded string, which doesn't
		 * necessarily have a '\0' at the end, or a null-terminated
		 * string, with a trailing '\0'.  (Yes, there are cases
		 * where you have a string that's both counted and null-
		 * terminated.)
		 *
		 * In the first case, we must allocate a buffer of length
		 * "length+1", to make room for a trailing '\0'.
		 *
		 * In the second case, we don't assume that there is a
		 * trailing '\0' there, as the packet might be malformed.
		 * (XXX - should we throw an exception if there's no
		 * trailing '\0'?)  Therefore, we allocate a buffer of
		 * length "length+1", and put in a trailing '\0', just to
		 * be safe.
		 *
		 * (XXX - this would change if we made string values counted
		 * rather than null-terminated.)
		 */
		value = tvb_get_string_enc(scope, tvb, start, length, encoding);
	}
	*ret_length = length;
	return value;
}

Project: wireshark

hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
{
	/* Get the underlying BASE_ value */
	int display = FIELD_DISPLAY(hfinfo->display);

	if (display == BASE_NONE)
		return NULL;

	if (display == BASE_DEC_HEX)
		display = BASE_DEC;
	if (display == BASE_HEX_DEC)
		display = BASE_HEX;

	return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
}

Project: wireshark

proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
{
	proto_item	  *pi;
	header_field_info *hfinfo;
	gchar		  *str;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);

	pi = proto_tree_add_text_node(tree, tvb, start, length);

	TRY_TO_FAKE_THIS_REPR(pi);

	str = tvb_format_text_wsp(NULL, tvb, start, length);
	proto_item_set_text(pi, "%s", str);
	wmem_free(NULL, str);

	return pi;
}

Project: wireshark

proto_registrar_dump_fieldcount(void)
{
	guint32			i;
	header_field_info	*hfinfo;
	guint32			deregistered_count = 0;
	guint32			same_name_count = 0;
	guint32			protocol_count = 0;

	for (i = 0; i < gpa_hfinfo.len; i++) {
		if (gpa_hfinfo.hfi[i] == NULL) {
			deregistered_count++;
			continue; /* This is a deregistered protocol or header field */
		}

		PROTO_REGISTRAR_GET_NTH(i, hfinfo);

		if (proto_registrar_is_protocol(i))
			protocol_count++;

		if (hfinfo->same_name_prev_id != -1)
			same_name_count++;
	}

	ws_debug_printf("There are %u header fields registered, of which:\n"
		"\t%u are deregistered\n"
		"\t%u are protocols\n"
		"\t%u have the same name as another field\n\n",
		gpa_hfinfo.len, deregistered_count, protocol_count,
		same_name_count);

	ws_debug_printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
		(gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
		    "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
		    "\n");

	ws_debug_printf("The header field table consumes %u KiB of memory.\n",
		(unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
	ws_debug_printf("The fields themselves consume %u KiB of memory.\n",
		(unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));

	return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
}

Project: wireshark

proto_tree_create_root(packet_info *pinfo)
{
	proto_node *pnode;

	/* Initialize the proto_node */
	pnode = g_slice_new(proto_tree);
	PROTO_NODE_INIT(pnode);
	pnode->parent = NULL;
	PNODE_FINFO(pnode) = NULL;
	pnode->tree_data = g_slice_new(tree_data_t);

	/* Make sure we can access pinfo everywhere */
	pnode->tree_data->pinfo = pinfo;

	/* Don't initialize the tree_data_t. Wait until we know we need it */
	pnode->tree_data->interesting_hfids = NULL;

	/* Set the default to FALSE so it's easier to
	 * find errors; if we expect to see the protocol tree
	 * but for some reason the default 'visible' is not
	 * changed, then we'll find out very quickly. */
	pnode->tree_data->visible = FALSE;

	/* Make sure that we fake protocols (if possible) */
	pnode->tree_data->fake_protocols = TRUE;

	/* Keep track of the number of children */
	pnode->tree_data->count = 0;

	return (proto_tree *)pnode;
}

Project: wireshark

tree_expanded_set(int tree_type, gboolean value)
{
	g_assert(tree_type >= 0 && tree_type < num_tree_types);

	if (value)
		tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
	else
		tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
}

Project: wireshark

ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
	      const guint encoding)
{
	field_info	  *new_fi;
	header_field_info *hfinfo;
	gint		   item_length;
	int		   offset;

	offset = ptvc->offset;
	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
	get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
	test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);

	ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
	    item_length, encoding);

	CHECK_FOR_NULL_TREE(ptvc->tree);

	/* Coast clear. Try and fake it */
	TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);

	new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);

	return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
		offset, length, encoding);
}

Project: wireshark

proto_disable_by_default(const int proto_id)
{
	protocol_t *protocol;

	protocol = find_protocol_by_id(proto_id);
	DISSECTOR_ASSERT(protocol->can_toggle);
	DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
	protocol->is_enabled = FALSE;
	protocol->enabled_by_default = FALSE;
}

Project: wireshark

proto_all_finfos(proto_tree *tree)
{
	ffdata_t ffdata;

	/* Pre allocate enough space to hold all fields in most cases */
	ffdata.array = g_ptr_array_sized_new(512);
	ffdata.id = 0;

	proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);

	return ffdata.array;
}

Project: wireshark

proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			   gint start, gint length, gint64 value,
			   const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
		     proto_item *item_to_move)
{
	/* This function doesn't generate any values. It only reorganizes the prococol tree
	 * so we can bail out immediately if it isn't visible. */
	if (!tree || !PTREE_DATA(tree)->visible)
		return;

	DISSECTOR_ASSERT(item_to_move->parent == tree);
	DISSECTOR_ASSERT(fixed_item->parent == tree);

	/*** cut item_to_move out ***/

	/* is item_to_move the first? */
	if (tree->first_child == item_to_move) {
		/* simply change first child to next */
		tree->first_child = item_to_move->next;

		DISSECTOR_ASSERT(tree->last_child != item_to_move);
	} else {
		proto_item *curr_item;
		/* find previous and change it's next */
		for (curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
			if (curr_item->next == item_to_move) {
				break;
			}
		}

		DISSECTOR_ASSERT(curr_item);

		curr_item->next = item_to_move->next;

		/* fix last_child if required */
		if (tree->last_child == item_to_move) {
			tree->last_child = curr_item;
		}
	}

	/*** insert to_move after fixed ***/
	item_to_move->next = fixed_item->next;
	fixed_item->next = item_to_move;
	if (tree->last_child == fixed_item) {
		tree->last_child = item_to_move;
	}
}

Project: wireshark

proto_tree_set_float(field_info *fi, float value)
{
	fvalue_set_floating(&fi->value, value);
}

Project: wireshark

ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, wmem_allocator_t *scope, const guint8 **retval)
{
	header_field_info *hfinfo;
	field_info		*new_fi;
	const guint8	*value;
	gint			item_length;
	int				offset;

	offset = ptvc->offset;

	PROTO_REGISTRAR_GET_NTH(hf, hfinfo);

	switch (hfinfo->type) {
	case FT_STRING:
		value = get_string_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
		break;
	case FT_STRINGZ:
		value = get_stringz_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
		break;
	case FT_UINT_STRING:
		value = get_uint_string_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
		break;
	case FT_STRINGZPAD:
		value = get_stringzpad_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
		break;
	case FT_STRINGZTRUNC:
		value = get_stringztrunc_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
		break;
	default:
		REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
		    hfinfo->abbrev);
	}

	if (retval)
		*retval = value;

	ptvc->offset += item_length;

	CHECK_FOR_NULL_TREE(ptvc->tree);

	TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);

	return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
		offset, length, encoding);
}

Project: wireshark

proto_get_first_protocol(void **cookie)
{
	protocol_t *protocol;

	if (protocols == NULL)
		return -1;
	*cookie = protocols;
	protocol = (protocol_t *)protocols->data;
	return protocol->proto_id;
}

Project: wireshark

proto_find_first_finfo(proto_tree *tree, const int id)
{
	ffdata_t ffdata;

	ffdata.array = g_ptr_array_new();
	ffdata.id = id;

	proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);

	return ffdata.array;
}

Project: wireshark

hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
{
	if (hfinfo->display & BASE_VAL64_STRING) {
		if (hfinfo->display & BASE_EXT_STRING)
			return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
		else
			return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
	}

	if (hfinfo->display & BASE_RANGE_STRING)
		return try_rval64_to_str(value, (const range_string *) hfinfo->strings);

	if (hfinfo->display & BASE_UNIT_STRING)
		return unit_name_string_get_value64(value, (const struct unit_name_string*) hfinfo->strings);

	/* If this is reached somebody registered a 64-bit field with a 32-bit
	 * value-string, which isn't right. */
	REPORT_DISSECTOR_BUG("field %s is a 64-bit field with a 32-bit value_string",
	    hfinfo->abbrev);

	/* This is necessary to squelch MSVC errors; is there
	   any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
	   never returns? */
	return NULL;
}

Project: wireshark

proto_is_protocol_enabled(const protocol_t *protocol)
{
	if (protocol == NULL)
		return FALSE;

	//parent protocol determines enable/disable for helper dissectors
	if (proto_is_pino(protocol))
		return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));

	return protocol->is_enabled;
}

Project: wireshark

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)
{
	return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
}

Project: wireshark

hfinfo_bitshift(const header_field_info *hfinfo)
{
	return ws_ctz(hfinfo->bitmask);
}

Project: wireshark

proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
{
	GByteArray *bytes;

	DISSECTOR_ASSERT(start_ptr != NULL || length == 0);

	bytes = g_byte_array_new();
	if (length > 0) {
		g_byte_array_append(bytes, start_ptr, length);
	}
	fvalue_set_byte_array(&fi->value, bytes);
}

Project: wireshark

proto_registrar_get_parent(const int n)
{
	header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(n, hfinfo);
	return hfinfo->parent;
}

Project: wireshark

fill_label_bitfield_varint(field_info *fi, gchar *label_str, gboolean is_signed)
{
	char       *p;
	int         bitfield_byte_length;
	guint32     value, unshifted_value;
	char        buf[48];
	const char *out;

	header_field_info *hfinfo = fi->hfinfo;

	/* Un-shift bits */
	if (is_signed) {
		value = fvalue_get_sinteger(&fi->value);
	} else {
		value = fvalue_get_uinteger(&fi->value);
	}
	unshifted_value = value;
	if (hfinfo->bitmask) {
		unshifted_value <<= hfinfo_bitshift(hfinfo);
	}

	/* Create the bitfield first */
	p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, fi->length*8);
	bitfield_byte_length = (int) (p - label_str);

	/* Fill in the textual info using stored (shifted) value */
	if (hfinfo->display == BASE_CUSTOM) {
		gchar tmp[ITEM_LABEL_LENGTH];
		const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;

		DISSECTOR_ASSERT(fmtfunc);
		fmtfunc(tmp, value);
		label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
	}
	else if (hfinfo->strings) {
		const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");

		out = hfinfo_number_vals_format(hfinfo, buf, value);
		if (out == NULL) /* BASE_NONE so don't put integer in descr */
			label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
		else
			label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
	}
	else {
		out = hfinfo_number_value_format(hfinfo, buf, value);

		label_fill(label_str, bitfield_byte_length, hfinfo, out);
	}
}

Project: wireshark

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 char *format, ...)
{
	va_list ap;
	gchar  *dst;
	header_field_info *hf_field;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);

	DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);

	CREATE_VALUE_STRING(dst, format, ap);

	return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
}

Project: wireshark

get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
{
	guint32 value;
	gboolean length_error;

	switch (length) {

	case 1:
		value = tvb_get_guint8(tvb, offset);
		if (encoding & ENC_ZIGBEE) {
			if (value == 0xFF) { /* Invalid Zigbee length, set to 0 */
				value = 0;
			}
		}
		break;

	case 2:
		value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
						       : tvb_get_ntohs(tvb, offset);
		if (encoding & ENC_ZIGBEE) {
			if (value == 0xFFFF) { /* Invalid Zigbee length, set to 0 */
				value = 0;
			}
		}
		break;

	case 3:
		value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
						       : tvb_get_ntoh24(tvb, offset);
		break;

	case 4:
		value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
						       : tvb_get_ntohl(tvb, offset);
		break;

	default:
		if (length < 1) {
			length_error = TRUE;
			value = 0;
		} else {
			length_error = FALSE;
			value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
							       : tvb_get_ntohl(tvb, offset);
		}
		report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
		break;
	}
	return value;
}

Project: wireshark

proto_tree_set_string(field_info *fi, const char* value)
{
	if (value) {
		fvalue_set_string(&fi->value, value);
	} else {
		/*
		 * XXX - why is a null value for a string field
		 * considered valid?
		 */
		fvalue_set_string(&fi->value, "[ Null ]");
	}
}

Project: wireshark

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, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

void proto_free_field_strings (ftenum_t field_type, unsigned int field_display, const void *field_strings)
{
	if (field_strings == NULL) {
		return;
	}

	switch (field_type) {
		case FT_FRAMENUM:
			/* This is just an integer represented as a pointer */
			break;
		case FT_PROTOCOL: {
			protocol_t *protocol = (protocol_t *)field_strings;
			g_free((gchar *)protocol->short_name);
			break;
		}
		case FT_BOOLEAN: {
			true_false_string *tf = (true_false_string *)field_strings;
			g_free((gchar *)tf->true_string);
			g_free((gchar *)tf->false_string);
			break;
		}
		case FT_UINT40:
		case FT_INT40:
		case FT_UINT48:
		case FT_INT48:
		case FT_UINT56:
		case FT_INT56:
		case FT_UINT64:
		case FT_INT64: {
			/*
			 * XXX - if it's BASE_RANGE_STRING, or
			 * BASE_EXT_STRING, should we free it?
			 */
			if (field_display & BASE_UNIT_STRING) {
				unit_name_string *unit = (unit_name_string *)field_strings;
				g_free((gchar *)unit->singular);
				g_free((gchar *)unit->plural);
			} else {
				val64_string *vs64 = (val64_string *)field_strings;
				while (vs64->strptr) {
					g_free((gchar *)vs64->strptr);
					vs64++;
				}
			}
			break;
		}
		case FT_CHAR:
		case FT_UINT8:
		case FT_INT8:
		case FT_UINT16:
		case FT_INT16:
		case FT_UINT24:
		case FT_INT24:
		case FT_UINT32:
		case FT_INT32:
		case FT_FLOAT:
		case FT_DOUBLE: {
			/*
			 * XXX - if it's BASE_RANGE_STRING, or
			 * BASE_EXT_STRING, should we free it?
			 */
			if (field_display & BASE_UNIT_STRING) {
				unit_name_string *unit = (unit_name_string *)field_strings;
				g_free((gchar *)unit->singular);
				g_free((gchar *)unit->plural);
			} else if (field_display & BASE_RANGE_STRING) {
				range_string *rs = (range_string *)field_strings;
				while (rs->strptr) {
					g_free((gchar *)rs->strptr);
					rs++;
				}
			} else {
				value_string *vs = (value_string *)field_strings;
				while (vs->strptr) {
					g_free((gchar *)vs->strptr);
					vs++;
				}
			}
			break;
		default:
			break;
		}
	}

	if (field_type != FT_FRAMENUM) {
		g_free((void *)field_strings);
	}
}

Project: wireshark

get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
		gint length, guint item_length, const gint encoding)
{
	guint32 n;

	/*
	 * We need to get the correct item length here.
	 * That's normally done by proto_tree_new_item(),
	 * but we won't be calling it.
	 */
	switch (hfinfo->type) {

	case FT_NONE:
	case FT_PROTOCOL:
	case FT_BYTES:
		/*
		 * The length is the specified length.
		 */
		break;

	case FT_UINT_BYTES:
		n = get_uint_value(NULL, tvb, start, length, encoding);
		item_length += n;
		break;

	/* XXX - make these just FT_UINT? */
	case FT_UINT8:
	case FT_UINT16:
	case FT_UINT24:
	case FT_UINT32:
	case FT_UINT40:
	case FT_UINT48:
	case FT_UINT56:
	case FT_UINT64:
	/* XXX - make these just FT_INT? */
	case FT_INT8:
	case FT_INT16:
	case FT_INT24:
	case FT_INT32:
	case FT_INT40:
	case FT_INT48:
	case FT_INT56:
	case FT_INT64:
		if (encoding & (ENC_VARIANT_MASK)) {
			if (length < -1) {
				report_type_length_mismatch(NULL, "a FT_[U]INT", length, TRUE);
			}
			if (length == -1) {
				guint64 dummy;
				/* This can throw an exception */
				/* XXX - do this without fetching the varint? */
				length = tvb_get_varint(tvb, start, FT_VARINT_MAX_LEN, &dummy, encoding);
				if (length == 0) {
					THROW(ReportedBoundsError);
				}
			}
			item_length = length;
			break;
		}

		/*
		 * The length is the specified length.
		 */
		break;

	case FT_BOOLEAN:
	case FT_CHAR:
	case FT_IPv4:
	case FT_IPXNET:
	case FT_IPv6:
	case FT_FCWWN:
	case FT_AX25:
	case FT_VINES:
	case FT_ETHER:
	case FT_EUI64:
	case FT_GUID:
	case FT_OID:
	case FT_REL_OID:
	case FT_SYSTEM_ID:
	case FT_FLOAT:
	case FT_DOUBLE:
	case FT_STRING:
		/*
		 * The length is the specified length.
		 */
		break;

	case FT_STRINGZ:
		if (length < -1) {
			report_type_length_mismatch(NULL, "a string", length, TRUE);
		}
		if (length == -1) {
			/* This can throw an exception */
			/* XXX - do this without fetching the string? */
			tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
		}
		item_length = length;
		break;

	case FT_UINT_STRING:
		n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
		item_length += n;
		break;

	case FT_STRINGZPAD:
	case FT_STRINGZTRUNC:
	case FT_ABSOLUTE_TIME:
	case FT_RELATIVE_TIME:
	case FT_IEEE_11073_SFLOAT:
	case FT_IEEE_11073_FLOAT:
		/*
		 * The length is the specified length.
		 */
		break;

	default:
		REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in gset_full_length()",
				     hfinfo->abbrev,
				     hfinfo->type,
				     ftype_name(hfinfo->type));
		break;
	}
	return item_length;
}

Project: wireshark

prefix_equal (gconstpointer ap, gconstpointer bp) {
	const gchar* a = (const gchar *)ap;
	const gchar* b = (const gchar *)bp;

	do {
		gchar ac = *a++;
		gchar bc = *b++;

		if ( (ac == '.' || ac == '\0') &&   (bc == '.' || bc == '\0') ) return TRUE;

		if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
		if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;

		if (ac != bc) return FALSE;
	} while (1);

	return FALSE;
}

Project: wireshark

hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
{
	int display = hfinfo->display;

	if (hfinfo->type == FT_FRAMENUM) {
		/*
		 * Frame numbers are always displayed in decimal.
		 */
		display = BASE_DEC;
	}

	return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
}

Project: wireshark

proto_get_protocol_filter_name(const int proto_id)
{
	protocol_t *protocol;

	protocol = find_protocol_by_id(proto_id);
	if (protocol == NULL)
		return "(none)";
	return protocol->filter_name;
}

Project: wireshark

ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
{
	subtree_lvl *subtree;
	if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
		ptvcursor_new_subtree_levels(ptvc);

	subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
	subtree->tree = ptvc->tree;
	subtree->it= NULL;
	ptvc->pushed_tree_index++;
	return ptvcursor_set_subtree(ptvc, it, ett_subtree);
}

Project: wireshark

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,
				 gchar *value_str)
{
	proto_item *item;

	if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
						      tvb, bit_offset, no_of_bits,
						      value_ptr, value_str))) {
		FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
		FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
	}
	return item;
}

Project: wireshark

other_decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
{
	int i;
	guint64 bit;
	char *p;

	i = 0;
	p = buf;

	/* This is a devel error. It is safer to stop here. */
	DISSECTOR_ASSERT(width >= 1);

	bit = G_GUINT64_CONSTANT(1) << (width - 1);
	for (;;) {
		if (mask & bit) {
			/* This bit is part of the field.  Show its value. */
			if (val & bit)
				*p++ = '1';
			else
				*p++ = '0';
		} else {
			/* This bit is not part of the field. */
			*p++ = '.';
		}
		bit >>= 1;
		i++;
		if (i >= width)
			break;
		if (i % 4 == 0)
			*p++ = ' ';
	}
	*p = '\0';
	return p;
}

Project: wireshark

proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const guint offset,
								const int len, int * const *fields, const guint encoding)
{
	guint64 value;

	if (tree) {
		value = get_uint64_value(tree, tvb, offset, len, encoding);
		proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
		    BMT_NO_APPEND, FALSE, TRUE, tree, value);
	}
}

Project: wireshark

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)
{
	header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
	field_info	*new_fi;
	guint64		value;

	DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");

	if ((!IS_FT_INT(hfinfo->type)) && (!IS_FT_UINT(hfinfo->type))) {
		REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT or FT_INT",
		    hfinfo->abbrev);
	}

	/* length validation for native number encoding caught by get_uint64_value() */
	/* length has to be -1 or > 0 regardless of encoding */
	if (length == 0)
		REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_varint",
			length);

	if (encoding & ENC_STRING) {
		REPORT_DISSECTOR_BUG("wrong encoding");
	}

	length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value, encoding);

	if (retval) {
		*retval = value;
		if (hfinfo->bitmask) {
			/* Mask out irrelevant portions */
			*retval &= hfinfo->bitmask;
			/* Shift bits */
			*retval >>= hfinfo_bitshift(hfinfo);
		}
	}

	if (lenretval) {
		*lenretval = length;
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(tree, hfinfo, tvb, start, length);

	proto_tree_set_uint64(new_fi, value);

	new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
	if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG)) {
		new_fi->flags |= FI_VARINT;
	}

	return proto_tree_add_node(tree, new_fi);

}

Project: wireshark

proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
				  gint start, gint length, const guint8* value,
				  const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
{
	GByteArray *bytes;

	DISSECTOR_ASSERT(value_ptr != NULL || length == 0);

	bytes = g_byte_array_new();
	if (length > 0) {
		g_byte_array_append(bytes, value_ptr, length);
	}
	fvalue_set_byte_array(&fi->value, bytes);
}

Project: wireshark

proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *text)
{
	return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
}

Project: wireshark

proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		     gint length, const guint64 value)
{
	proto_item	  *pi;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);

	pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
	proto_tree_set_eui64(PNODE_FINFO(pi), value);

	return pi;
}

Project: wireshark

proto_item_get_subtree(proto_item *pi) {
	field_info *fi;

	if (!pi)
		return NULL;
	fi = PITEM_FINFO(pi);
	if ( (!fi) || (fi->tree_type == -1) )
		return NULL;
	return (proto_tree *)pi;
}

Project: wireshark

label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
{
	gsize name_pos;

	/* "%s: %s", hfinfo->name, text */
	name_pos = pos = label_concat(label_str, pos, hfinfo->name);
	if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
		pos = label_concat(label_str, pos, ": ");
		pos = label_concat(label_str, pos, text ? text : "(null)");
	}

	if (pos >= ITEM_LABEL_LENGTH) {
		/* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
		label_mark_truncated(label_str, name_pos);
	}

	return pos;
}

Project: wireshark

proto_register_field_init(header_field_info *hfinfo, const int parent)
{

	tmp_fld_check_assert(hfinfo);

	hfinfo->parent         = parent;
	hfinfo->same_name_next = NULL;
	hfinfo->same_name_prev_id = -1;

	/* if we always add and never delete, then id == len - 1 is correct */
	if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
		if (!gpa_hfinfo.hfi) {
			gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
			gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
		} else {
			gpa_hfinfo.allocated_len += 1000;
			gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
						   sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
			/*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
		}
	}
	gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
	gpa_hfinfo.len++;
	hfinfo->id = gpa_hfinfo.len - 1;

	/* if we have real names, enter this field in the name tree */
	if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {

		header_field_info *same_name_next_hfinfo;
		guchar c;

		/* Check that the filter name (abbreviation) is legal;
		 * it must contain only alphanumerics, '-', "_", and ".". */
		c = proto_check_field_name(hfinfo->abbrev);
		if (c) {
			if (c == '.') {
				fprintf(stderr, "Invalid leading, duplicated or trailing '.' found in filter name '%s'\n", hfinfo->abbrev);
			} else if (g_ascii_isprint(c)) {
				fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
			} else {
				fprintf(stderr, "Invalid byte \\%03o in filter name '%s'\n", c, hfinfo->abbrev);
			}
			DISSECTOR_ASSERT_NOT_REACHED();
		}

		/* We allow multiple hfinfo's to be registered under the same
		 * abbreviation. This was done for X.25, as, depending
		 * on whether it's modulo-8 or modulo-128 operation,
		 * some bitfield fields may be in different bits of
		 * a byte, and we want to be able to refer to that field
		 * with one name regardless of whether the packets
		 * are modulo-8 or modulo-128 packets. */

		same_name_hfinfo = NULL;

		g_hash_table_insert(gpa_name_map, (gpointer) (hfinfo->abbrev), hfinfo);
		/* GLIB 2.x - if it is already present
		 * the previous hfinfo with the same name is saved
		 * to same_name_hfinfo by value destroy callback */
		if (same_name_hfinfo) {
			/* There's already a field with this name.
			 * Put the current field *before* that field
			 * in the list of fields with this name, Thus,
			 * we end up with an effectively
			 * doubly-linked-list of same-named hfinfo's,
			 * with the head of the list (stored in the
			 * hash) being the last seen hfinfo.
			 */
			same_name_next_hfinfo =
				same_name_hfinfo->same_name_next;

			hfinfo->same_name_next = same_name_next_hfinfo;
			if (same_name_next_hfinfo)
				same_name_next_hfinfo->same_name_prev_id = hfinfo->id;

			same_name_hfinfo->same_name_next = hfinfo;
			hfinfo->same_name_prev_id = same_name_hfinfo->id;
#ifdef ENABLE_CHECK_FILTER
			while (same_name_hfinfo) {
				if (_ftype_common(hfinfo->type) != _ftype_common(same_name_hfinfo->type))
					g_warning("'%s' exists multiple times with incompatible types: %s and %s", hfinfo->abbrev, ftype_name(hfinfo->type), ftype_name(same_name_hfinfo->type));
				same_name_hfinfo = same_name_hfinfo->same_name_next;
			}
#endif
		}
	}

	return hfinfo->id;
}

Project: wireshark

proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
			const guint encoding)
{
	e_guid_t guid;

	tvb_get_guid(tvb, start, &guid, encoding);
	proto_tree_set_guid(fi, &guid);
}

Project: wireshark

proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
{
	if (!tree)
		return NULL;

	if (PTREE_DATA(tree)->interesting_hfids != NULL)
		return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
					   GINT_TO_POINTER(id));
	else
		return NULL;
}

Project: wireshark

proto_get_next_protocol_field(const int proto_id, void **cookie)
{
	protocol_t *protocol = find_protocol_by_id(proto_id);
	guint       i        = GPOINTER_TO_UINT(*cookie) - 1;

	i++;

	if ((protocol->fields == NULL) || (i >= protocol->fields->len))
		return NULL;

	*cookie = GUINT_TO_POINTER(i + 1);
	return (header_field_info *)g_ptr_array_index(protocol->fields, i);
}

Project: wireshark

proto_registrar_get_byname(const char *field_name)
{
	header_field_info    *hfinfo;
	prefix_initializer_t  pi;

	if (!field_name)
		return NULL;

	if (g_strcmp0(field_name, last_field_name) == 0) {
		return last_hfinfo;
	}

	hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);

	if (hfinfo) {
		g_free(last_field_name);
		last_field_name = g_strdup(field_name);
		last_hfinfo = hfinfo;
		return hfinfo;
	}

	if (!prefixes)
		return NULL;

	if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
		pi(field_name);
		g_hash_table_remove(prefixes, field_name);
	} else {
		return NULL;
	}

	hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);

	if (hfinfo) {
		g_free(last_field_name);
		last_field_name = g_strdup(field_name);
		last_hfinfo = hfinfo;
	}
	return hfinfo;
}

Project: wireshark

proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
			   const gint start, gint length, const char *format,
			   ...)
{
	proto_item	  *pi;
	va_list		   ap;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);

	pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);

	TRY_TO_FAKE_THIS_REPR(pi);

	va_start(ap, format);
	proto_tree_set_representation(pi, format, ap);
	va_end(ap);

	/* no value to set for FT_NONE */
	return pi;
}

Project: wireshark

tree_expanded(int tree_type)
{
	if (tree_type == -1) {
		return FALSE;
	}
	g_assert(tree_type >= 0 && tree_type < num_tree_types);
	return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
}

Project: wireshark

proto_registrar_dump_ftypes(void)
{
	int fte;

	for (fte = 0; fte < FT_NUM_TYPES; fte++) {
		ws_debug_printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
	}
}

Project: wireshark

fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
{
	header_field_info *hfinfo = fi->hfinfo;
	guint64            value;

	char               buf[48];
	const char        *out;

	if (is_signed)
		value = fvalue_get_sinteger64(&fi->value);
	else
		value = fvalue_get_uinteger64(&fi->value);

	/* Fill in the textual info */
	if (hfinfo->display == BASE_CUSTOM) {
		gchar tmp[ITEM_LABEL_LENGTH];
		const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;

		DISSECTOR_ASSERT(fmtfunc64);
		fmtfunc64(tmp, value);
		label_fill(label_str, 0, hfinfo, tmp);
	}
	else if (hfinfo->strings) {
		const char *val_str = hf_try_val64_to_str(value, hfinfo);

		out = hfinfo_number_vals_format64(hfinfo, buf, value);
		if (hfinfo->display & BASE_SPECIAL_VALS) {
			/*
			 * Unique values only display value_string string
			 * if there is a match. Otherwise it's just a number
			 */
			if (val_str) {
				label_fill_descr(label_str, 0, hfinfo, val_str, out);
			} else {
				label_fill(label_str, 0, hfinfo, out);
			}
		} else {
			if (val_str == NULL)
				val_str = "Unknown";

			if (out == NULL) /* BASE_NONE so don't put integer in descr */
				label_fill(label_str, 0, hfinfo, val_str);
			else
				label_fill_descr(label_str, 0, hfinfo, val_str, out);
		}
	}
	else {
		out = hfinfo_number_value_format64(hfinfo, buf, value);

		label_fill(label_str, 0, hfinfo, out);
	}
}

Project: wireshark

proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
			const gint length)
{
	field_info *fi;

	if (tree == NULL)
		return;

	fi = PTREE_FINFO(tree);
	if (fi == NULL)
		return;

	start += tvb_raw_offset(tvb);
	DISSECTOR_ASSERT(start >= 0);
	DISSECTOR_ASSERT(length >= 0);

	fi->appendix_start = start;
	fi->appendix_length = length;
}

Project: wireshark

proto_tree_get_parent_tree(proto_tree *tree) {
	if (!tree)
		return NULL;

	/* we're the root tree, there's no parent
	   return ourselves so the caller has at least a tree to attach to */
	if (!tree->parent)
		return tree;

	return (proto_tree *)tree->parent;
}

Project: wireshark

proto_tree_set_ether(field_info *fi, const guint8* value)
{
	fvalue_set_bytes(&fi->value, value);
}

Project: wireshark

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)
{
	return proto_tree_add_item_ret_string_and_length(tree, hfindex,
	    tvb, start, length, encoding, scope, retval, &length);
}

Project: wireshark

hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
{
	const char *str = hf_try_val64_to_str(value, hfinfo);

	return (str) ? str : unknown_str;
}

Project: wireshark

fill_label_boolean(field_info *fi, gchar *label_str)
{
	char	*p                    = label_str;
	int      bitfield_byte_length = 0, bitwidth;
	guint64  unshifted_value;
	guint64  value;

	header_field_info	*hfinfo   = fi->hfinfo;
	const true_false_string	*tfstring = &tfs_true_false;

	if (hfinfo->strings) {
		tfstring = (const struct true_false_string*) hfinfo->strings;
	}

	value = fvalue_get_uinteger64(&fi->value);
	if (hfinfo->bitmask) {
		/* Figure out the bit width */
		bitwidth = hfinfo_container_bitwidth(hfinfo);

		/* Un-shift bits */
		unshifted_value = value;
		unshifted_value <<= hfinfo_bitshift(hfinfo);

		/* Create the bitfield first */
		p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
		bitfield_byte_length = (int) (p - label_str);
	}

	/* Fill in the textual info */
	label_fill(label_str, bitfield_byte_length, hfinfo, tfs_get_string(!!value, tfstring));
}

Project: wireshark

proto_get_id(const protocol_t *protocol)
{
	return protocol->proto_id;
}

Project: wireshark

proto_get_first_protocol_field(const int proto_id, void **cookie)
{
	protocol_t *protocol = find_protocol_by_id(proto_id);

	if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
		return NULL;

	*cookie = GUINT_TO_POINTER(0 + 1);
	return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
}

Project: wireshark

proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
	const guint bit_offset, const gint no_of_chars)
{
	proto_item	  *pi;
	header_field_info *hfinfo;
	gint		   byte_length;
	gint		   byte_offset;
	gchar		  *string;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);

	byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
	byte_offset = bit_offset >> 3;

	string = tvb_get_ascii_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);

	if (hfinfo->display == STR_UNICODE) {
		DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
	}

	pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
	DISSECTOR_ASSERT(byte_length >= 0);
	proto_tree_set_string(PNODE_FINFO(pi), string);

	return pi;
}

Project: wireshark

proto_registrar_get_ftype(const int n)
{
	header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(n, hfinfo);
	return hfinfo->type;
}

Project: wireshark

proto_tree_set_double(field_info *fi, double value)
{
	fvalue_set_floating(&fi->value, value);
}

Project: wireshark

proto_cleanup_base(void)
{
	protocol_t *protocol;
	header_field_info *hfinfo;

	/* Free the abbrev/ID hash table */
	if (gpa_name_map) {
		g_hash_table_destroy(gpa_name_map);
		gpa_name_map = NULL;
	}
	if (gpa_protocol_aliases) {
		g_hash_table_destroy(gpa_protocol_aliases);
		gpa_protocol_aliases = NULL;
	}
	g_free(last_field_name);
	last_field_name = NULL;

	while (protocols) {
		protocol = (protocol_t *)protocols->data;
		PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
		DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);

		g_slice_free(header_field_info, hfinfo);
		if (protocol->parent_proto_id != -1) {
			// pino protocol
			DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields
			DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list
		} else {
			if (protocol->fields) {
				g_ptr_array_free(protocol->fields, TRUE);
			}
			g_list_free(protocol->heur_list);
		}
		protocols = g_list_remove(protocols, protocol);
		g_free(protocol);
	}

	if (proto_names) {
		g_hash_table_destroy(proto_names);
		proto_names = NULL;
	}

	if (proto_short_names) {
		g_hash_table_destroy(proto_short_names);
		proto_short_names = NULL;
	}

	if (proto_filter_names) {
		g_hash_table_destroy(proto_filter_names);
		proto_filter_names = NULL;
	}

	if (gpa_hfinfo.allocated_len) {
		gpa_hfinfo.len           = 0;
		gpa_hfinfo.allocated_len = 0;
		g_free(gpa_hfinfo.hfi);
		gpa_hfinfo.hfi           = NULL;
	}

	if (deregistered_fields) {
		g_ptr_array_free(deregistered_fields, TRUE);
		deregistered_fields = NULL;
	}

	if (deregistered_data) {
		g_ptr_array_free(deregistered_data, TRUE);
		deregistered_data = NULL;
	}

	g_free(tree_is_expanded);
	tree_is_expanded = NULL;

	if (prefixes)
		g_hash_table_destroy(prefixes);
}

Project: wireshark

get_int64_value(proto_tree *tree, tvbuff_t *tvb, gint start, guint length, const guint encoding)
{
	guint64 value = get_uint64_value(tree, tvb, start, length, encoding);

	switch (length) {
		case 7:
			value = ws_sign_ext64(value, 56);
			break;
		case 6:
			value = ws_sign_ext64(value, 48);
			break;
		case 5:
			value = ws_sign_ext64(value, 40);
			break;
		case 4:
			value = ws_sign_ext64(value, 32);
			break;
		case 3:
			value = ws_sign_ext64(value, 24);
			break;
		case 2:
			value = ws_sign_ext64(value, 16);
			break;
		case 1:
			value = ws_sign_ext64(value, 8);
			break;
	}

	return value;
}

Project: wireshark

proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			     gint start, gint length, double value,
			     const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
			 const guint encoding)
{
	proto_item *item;

	item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
				   length, encoding);

	return item;
}

Project: wireshark

hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
{
	/* Get the underlying BASE_ value */
	int display = FIELD_DISPLAY(hfinfo->display);

	return hfinfo_char_value_format_display(display, buf, value);
}

Project: wireshark

call_plugin_register_handoff(gpointer data, gpointer user_data _U_)
{
	proto_plugin *plug = (proto_plugin *)data;

	if (plug->register_handoff) {
		plug->register_handoff();
	}
}

Project: wireshark

proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			    gint start, gint length, float value,
			    const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
				   gint start, gint length, double value,
				   const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

ptvcursor_add_ret_uint(ptvcursor_t *ptvc, int hfindex, gint length,
	      const guint encoding, guint32 *retval)
{
	field_info	  *new_fi;
	header_field_info *hfinfo;
	gint		   item_length;
	int		   offset;
	guint32		   value;

	offset = ptvc->offset;
	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);

	switch (hfinfo->type) {
	case FT_CHAR:
	case FT_UINT8:
	case FT_UINT16:
	case FT_UINT24:
	case FT_UINT32:
		break;
	default:
		REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
		    hfinfo->abbrev);
	}

	get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
	test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);

	/* I believe it's ok if this is called with a NULL tree */
	/* XXX - modify if we ever support EBCDIC FT_CHAR */
	value = get_uint_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);

	if (retval) {
		*retval = value;
		if (hfinfo->bitmask) {
			/* Mask out irrelevant portions */
			*retval &= (guint32)(hfinfo->bitmask);
			/* Shift bits */
			*retval >>= hfinfo_bitshift(hfinfo);
		}
	}

	ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
	    item_length, encoding);

	CHECK_FOR_NULL_TREE(ptvc->tree);

	/* Coast clear. Try and fake it */
	TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);

	new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);

	return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
		offset, length, encoding);
}

Project: wireshark

proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			   gint start, gint length, nstime_t *value_ptr,
			   const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hfindex, gint length, const guint encoding, gboolean *retval)
{
	header_field_info *hfinfo;
	field_info		*new_fi;
	gint			item_length;
	int				offset;
	guint64			value, bitval;

	offset = ptvc->offset;
	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);

	if (hfinfo->type != FT_BOOLEAN) {
		REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
		    hfinfo->abbrev);
	}

	/* length validation for native number encoding caught by get_uint64_value() */
	/* length has to be -1 or > 0 regardless of encoding */
	if (length < -1 || length == 0)
		REPORT_DISSECTOR_BUG("Invalid length %d passed to ptvcursor_add_ret_boolean",
			length);

	if (encoding & ENC_STRING) {
		REPORT_DISSECTOR_BUG("wrong encoding");
	}

	get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
	test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);

	/* I believe it's ok if this is called with a NULL tree */
	value = get_uint64_value(ptvc->tree, ptvc->tvb, offset, length, encoding);

	if (retval) {
		bitval = value;
		if (hfinfo->bitmask) {
			/* Mask out irrelevant portions */
			bitval &= hfinfo->bitmask;
		}
		*retval = (bitval != 0);
	}

	ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
	    item_length, encoding);

	CHECK_FOR_NULL_TREE(ptvc->tree);

	TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);

	return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
		offset, length, encoding);
}

Project: wireshark

proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, gint start,
			   gint length, const char *format, va_list ap)
{
	proto_item        *pi;
	header_field_info *hfinfo;

	if (length == -1) {
		length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
	} else {
		tvb_ensure_bytes_exist(tvb, start, length);
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);

	pi = proto_tree_add_text_node(tree, tvb, start, length);

	TRY_TO_FAKE_THIS_REPR(pi);

	proto_tree_set_representation(pi, format, ap);

	return pi;
}

Project: wireshark

proto_tree_set_eui64(field_info *fi, const guint64 value)
{
	fvalue_set_uinteger64(&fi->value, value);
}

Project: wireshark

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 char *format, ...)
{
	va_list ap;
	gchar  *dst;
	header_field_info *hf_field;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);

	switch (hf_field->type) {
		case FT_UINT8:
		case FT_UINT16:
		case FT_UINT24:
		case FT_UINT32:
			break;

		default:
			REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
			    hf_field->abbrev);
			return NULL;
			break;
	}

	CREATE_VALUE_STRING(dst, format, ap);

	return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
}

Project: wireshark

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, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
{
	g_free(last_field_name);
	last_field_name = NULL;

	if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
		/* No hfinfo with the same name */
		g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
		return;
	}

	if (hfinfo->same_name_next) {
		hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
	}

	if (hfinfo->same_name_prev_id != -1) {
		header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
		same_name_prev->same_name_next = hfinfo->same_name_next;
		if (!hfinfo->same_name_next) {
			/* It's always the latest added hfinfo which is stored in gpa_name_map */
			g_hash_table_insert(gpa_name_map, (gpointer) (same_name_prev->abbrev), same_name_prev);
		}
	}
}

Project: wireshark

fill_label_bitfield_varint64(field_info *fi, gchar *label_str, gboolean is_signed)
{
	char       *p;
	int         bitfield_byte_length;
	guint64     unshifted_value;
	guint64     value;

	char        buf[48];
	const char *out;

	header_field_info *hfinfo = fi->hfinfo;

	/* Un-shift bits */
	if (is_signed) {
		value = fvalue_get_sinteger64(&fi->value);
	} else {
		value = fvalue_get_uinteger64(&fi->value);
	}
	unshifted_value = value;
	if (hfinfo->bitmask) {
		unshifted_value <<= hfinfo_bitshift(hfinfo);
	}

	/* Create the bitfield first */
	p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, fi->length*8);
	bitfield_byte_length = (int) (p - label_str);

	/* Fill in the textual info using stored (shifted) value */
	if (hfinfo->display == BASE_CUSTOM) {
		gchar tmp[ITEM_LABEL_LENGTH];
		const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;

		DISSECTOR_ASSERT(fmtfunc64);
		fmtfunc64(tmp, value);
		label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
	}
	else if (hfinfo->strings) {
		const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");

		out = hfinfo_number_vals_format64(hfinfo, buf, value);
		if (out == NULL) /* BASE_NONE so don't put integer in descr */
			label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
		else
			label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
	}
	else {
		out = hfinfo_number_value_format64(hfinfo, buf, value);

		label_fill(label_str, bitfield_byte_length, hfinfo, out);
	}
}

Project: wireshark

proto_registrar_get_nth(guint hfindex)
{
	register header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
	return hfinfo;
}

Project: wireshark

proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			  gint start, gint length, const guint8* value_ptr,
			  const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		    gint length, guint32 value)
{
	proto_item	  *pi = NULL;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	switch (hfinfo->type) {
		case FT_CHAR:
		case FT_UINT8:
		case FT_UINT16:
		case FT_UINT24:
		case FT_UINT32:
		case FT_FRAMENUM:
			pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
			proto_tree_set_uint(PNODE_FINFO(pi), value);
			break;

		default:
			REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
			    hfinfo->abbrev);
	}

	return pi;
}

Project: wireshark

proto_tree_prime_with_hfid(proto_tree *tree _U_, const gint hfid)
{
	header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
	/* this field is referenced by a filter so increase the refcount.
	   also increase the refcount for the parent, i.e the protocol.
	*/
	hfinfo->ref_type = HF_REF_TYPE_DIRECT;
	/* only increase the refcount if there is a parent.
	   if this is a protocol and not a field then parent will be -1
	   and there is no parent to add any refcounting for.
	*/
	if (hfinfo->parent != -1) {
		header_field_info *parent_hfinfo;
		PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);

		/* Mark parent as indirectly referenced unless it is already directly
		 * referenced, i.e. the user has specified the parent in a filter.
		 */
		if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
			parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
	}
}

Project: wireshark

proto_get_id_by_filter_name(const gchar *filter_name)
{
	const protocol_t *protocol = NULL;

	DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");

	protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);

	if (protocol == NULL)
		return -1;
	return protocol->proto_id;
}

Project: wireshark

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)
{
	proto_item *pi;
	gint        no_of_bits;
	gint        octet_offset;
	guint       mask_initial_bit_offset;
	guint       mask_greatest_bit_offset;
	guint       octet_length;
	guint8      i;
	char        bf_str[256];
	char        lbl_str[ITEM_LABEL_LENGTH];
	guint64     value;
	guint64     composite_bitmask;
	guint64     composite_bitmap;

	header_field_info       *hf_field;
	const true_false_string *tfstring;

	/* We can't fake it just yet. We have to fill in the 'return_value' parameter */
	PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);

	if (hf_field->bitmask != 0) {
		REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_split_bits_item_ret_val"
				     " with field '%s' (%s) with bitmask != 0",
				     hf_field->abbrev, hf_field->name);
	}

	mask_initial_bit_offset = bit_offset % 8;

	no_of_bits = 0;
	value      = 0;
	i          = 0;
	mask_greatest_bit_offset = 0;
	composite_bitmask        = 0;
	composite_bitmap         = 0;

	while (crumb_spec[i].crumb_bit_length != 0) {
		guint64 crumb_mask, crumb_value;
		guint8	crumb_end_bit_offset;

		crumb_value = tvb_get_bits64(tvb,
					     bit_offset + crumb_spec[i].crumb_bit_offset,
					     crumb_spec[i].crumb_bit_length,
					     ENC_BIG_ENDIAN);
		value      += crumb_value;
		no_of_bits += crumb_spec[i].crumb_bit_length;
		DISSECTOR_ASSERT_HINT(no_of_bits <= 64, "a value larger than 64 bits cannot be represented");

		/* The bitmask is 64 bit, left-aligned, starting at the first bit of the
		   octet containing the initial offset.
		   If the mask is beyond 32 bits, then give up on bit map display.
		   This could be improved in future, probably showing a table
		   of 32 or 64 bits per row */
		if (mask_greatest_bit_offset < 32) {
			crumb_end_bit_offset = mask_initial_bit_offset
				+ crumb_spec[i].crumb_bit_offset
				+ crumb_spec[i].crumb_bit_length;
			crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;

			if (crumb_end_bit_offset > mask_greatest_bit_offset) {
				mask_greatest_bit_offset = crumb_end_bit_offset;
			}
			/* Currently the bitmap of the crumbs are only shown if
			 * smaller than 32 bits. Do not bother calculating the
			 * mask if it is larger than that. */
			if (crumb_end_bit_offset <= 32) {
				composite_bitmask |= (crumb_mask  << (64 - crumb_end_bit_offset));
				composite_bitmap  |= (crumb_value << (64 - crumb_end_bit_offset));
			}
		}
		/* Shift left for the next segment */
		value <<= crumb_spec[++i].crumb_bit_length;
	}

	/* Sign extend for signed types */
	switch (hf_field->type) {
		case FT_INT8:
		case FT_INT16:
		case FT_INT24:
		case FT_INT32:
		case FT_INT40:
		case FT_INT48:
		case FT_INT56:
		case FT_INT64:
			value = ws_sign_ext64(value, no_of_bits);
			break;
		default:
			break;
	}

	if (return_value) {
		*return_value = value;
	}

	/* Coast clear. Try and fake it */
	CHECK_FOR_NULL_TREE(tree);
	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);

	/* initialise the format string */
	bf_str[0] = '\0';

	octet_offset = bit_offset >> 3;

	/* Round up mask length to nearest octet */
	octet_length = ((mask_greatest_bit_offset + 7) >> 3);
	mask_greatest_bit_offset = octet_length << 3;

	/* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
	   It would be a useful enhancement to eliminate this restriction. */
	if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
		other_decode_bitfield_value(bf_str,
					    (guint32)(composite_bitmap  >> (64 - mask_greatest_bit_offset)),
					    (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
					    mask_greatest_bit_offset);
	} else {
		/* If the bitmask is too large, try to describe its contents. */
		g_snprintf(bf_str, sizeof(bf_str), "%d bits", no_of_bits);
	}

	switch (hf_field->type) {
	case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
		/* Boolean field */
		tfstring = &tfs_true_false;
		if (hf_field->strings)
			tfstring = (const true_false_string *) hf_field->strings;
		return proto_tree_add_boolean_format(tree, hfindex,
						     tvb, octet_offset, octet_length, (guint32)value,
						     "%s = %s: %s",
						     bf_str, hf_field->name, tfs_get_string(!!value, tfstring));
		break;

	case FT_CHAR:
		pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
		fill_label_char(PITEM_FINFO(pi), lbl_str);
		break;

	case FT_UINT8:
	case FT_UINT16:
	case FT_UINT24:
	case FT_UINT32:
		pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
		fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
		break;

	case FT_INT8:
	case FT_INT16:
	case FT_INT24:
	case FT_INT32:
		pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
		fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
		break;

	case FT_UINT40:
	case FT_UINT48:
	case FT_UINT56:
	case FT_UINT64:
		pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
		fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
		break;

	case FT_INT40:
	case FT_INT48:
	case FT_INT56:
	case FT_INT64:
		pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
		fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
		break;

	default:
		REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_split_bits_item_ret_val()",
				     hf_field->abbrev,
				     hf_field->type,
				     ftype_name(hf_field->type));
		return NULL;
		break;
	}
	proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
	return pi;
}

Project: wireshark

hfinfo_format_text(wmem_allocator_t *scope, const header_field_info *hfinfo,
    const guchar *string)
{
	switch (hfinfo->display) {
		case STR_ASCII:
			return format_text(scope, string, strlen(string));
/*
		case STR_ASCII_WSP
			return format_text_wsp(string, strlen(string));
 */
		case STR_UNICODE:
			return format_text(scope, string, strlen(string));
	}

	return format_text(scope, string, strlen(string));
}

Project: wireshark

proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			  gint start, gint length, gint32 value,
			  const char *format, ...)
{
	proto_item *pi;
	va_list     ap;

	pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

proto_item_prepend_text(proto_item *pi, const char *format, ...)
{
	field_info *fi = NULL;
	char        representation[ITEM_LABEL_LENGTH];
	va_list     ap;

	TRY_TO_FAKE_THIS_REPR_VOID(pi);

	fi = PITEM_FINFO(pi);
	if (fi == NULL) {
		return;
	}

	if (!proto_item_is_hidden(pi)) {
		/*
		 * If we don't already have a representation,
		 * generate the default representation.
		 */
		if (fi->rep == NULL) {
			ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
			proto_item_fill_label(fi, representation);
		} else
			g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);

		va_start(ap, format);
		g_vsnprintf(fi->rep->representation,
			ITEM_LABEL_LENGTH, format, ap);
		va_end(ap);
		g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
	}
}

Project: wireshark

proto_registrar_dump_values(void)
{
	header_field_info	*hfinfo;
	int			i, len, vi;
	const value_string	*vals;
	const val64_string	*vals64;
	const range_string	*range;
	const true_false_string	*tfs;
	const unit_name_string	*units;

	len = gpa_hfinfo.len;
	for (i = 0; i < len ; i++) {
		if (gpa_hfinfo.hfi[i] == NULL)
			continue; /* This is a deregistered protocol or field */

		PROTO_REGISTRAR_GET_NTH(i, hfinfo);

		if (hfinfo->id == hf_text_only) {
			continue;
		}

		/* ignore protocols */
		if (proto_registrar_is_protocol(i)) {
			continue;
		}
		/* process header fields */
#if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
		/*
		 * If this field isn't at the head of the list of
		 * fields with this name, skip this field - all
		 * fields with the same name are really just versions
		 * of the same field stored in different bits, and
		 * should have the same type/radix/value list, and
		 * just differ in their bit masks.	(If a field isn't
		 * a bitfield, but can be, say, 1 or 2 bytes long,
		 * it can just be made FT_UINT16, meaning the
		 * *maximum* length is 2 bytes, and be used
		 * for all lengths.)
		 */
		if (hfinfo->same_name_prev_id != -1)
			continue;
#endif
		vals   = NULL;
		vals64 = NULL;
		range  = NULL;
		tfs    = NULL;
		units  = NULL;

		if (hfinfo->strings != NULL) {
			if (FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM &&
			    (hfinfo->type == FT_CHAR  ||
			     hfinfo->type == FT_UINT8  ||
			     hfinfo->type == FT_UINT16 ||
			     hfinfo->type == FT_UINT24 ||
			     hfinfo->type == FT_UINT32 ||
			     hfinfo->type == FT_UINT40 ||
			     hfinfo->type == FT_UINT48 ||
			     hfinfo->type == FT_UINT56 ||
			     hfinfo->type == FT_UINT64 ||
			     hfinfo->type == FT_INT8   ||
			     hfinfo->type == FT_INT16  ||
			     hfinfo->type == FT_INT24  ||
			     hfinfo->type == FT_INT32  ||
			     hfinfo->type == FT_INT40  ||
			     hfinfo->type == FT_INT48  ||
			     hfinfo->type == FT_INT56  ||
			     hfinfo->type == FT_INT64  ||
			     hfinfo->type == FT_FLOAT  ||
			     hfinfo->type == FT_DOUBLE)) {

				if (hfinfo->display & BASE_RANGE_STRING) {
					range = (const range_string *)hfinfo->strings;
				} else if (hfinfo->display & BASE_EXT_STRING) {
					if (hfinfo->display & BASE_VAL64_STRING) {
						vals64 = VAL64_STRING_EXT_VS_P((const val64_string_ext *)hfinfo->strings);
					} else {
						vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
					}
				} else if (hfinfo->display & BASE_VAL64_STRING) {
					vals64 = (const val64_string *)hfinfo->strings;
				} else if (hfinfo->display & BASE_UNIT_STRING) {
					units = (const unit_name_string *)hfinfo->strings;
				} else {
					vals = (const value_string *)hfinfo->strings;
				}
			}
			else if (hfinfo->type == FT_BOOLEAN) {
				tfs = (const struct true_false_string *)hfinfo->strings;
			}
		}

		/* Print value strings? */
		if (vals) {
			if (hfinfo->display & BASE_EXT_STRING) {
				if (hfinfo->display & BASE_VAL64_STRING) {
					val64_string_ext *vse_p = (val64_string_ext *)hfinfo->strings;
					if (!val64_string_ext_validate(vse_p)) {
						g_warning("Invalid val64_string_ext ptr for: %s", hfinfo->abbrev);
						continue;
					}
					try_val64_to_str_ext(0, vse_p); /* "prime" the extended val64_string */
					ws_debug_printf("E\t%s\t%u\t%s\t%s\n",
					       hfinfo->abbrev,
					       VAL64_STRING_EXT_VS_NUM_ENTRIES(vse_p),
					       VAL64_STRING_EXT_VS_NAME(vse_p),
					       val64_string_ext_match_type_str(vse_p));
				} else {
					value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
					if (!value_string_ext_validate(vse_p)) {
						g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
						continue;
					}
					try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
					ws_debug_printf("E\t%s\t%u\t%s\t%s\n",
					       hfinfo->abbrev,
					       VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
					       VALUE_STRING_EXT_VS_NAME(vse_p),
					       value_string_ext_match_type_str(vse_p));
				}
			}
			vi = 0;
			while (vals[vi].strptr) {
				/* Print in the proper base */
				if (hfinfo->type == FT_CHAR) {
					if (g_ascii_isprint(vals[vi].value)) {
						ws_debug_printf("V\t%s\t'%c'\t%s\n",
						       hfinfo->abbrev,
						       vals[vi].value,
						       vals[vi].strptr);
					} else {
						if (hfinfo->display == BASE_HEX) {
							ws_debug_printf("V\t%s\t'\\x%02x'\t%s\n",
							       hfinfo->abbrev,
							       vals[vi].value,
							       vals[vi].strptr);
						}
						else {
							ws_debug_printf("V\t%s\t'\\%03o'\t%s\n",
							       hfinfo->abbrev,
							       vals[vi].value,
							       vals[vi].strptr);
						}
					}
				} else {
					if (hfinfo->display == BASE_HEX) {
						ws_debug_printf("V\t%s\t0x%x\t%s\n",
						       hfinfo->abbrev,
						       vals[vi].value,
						       vals[vi].strptr);
					}
					else {
						ws_debug_printf("V\t%s\t%u\t%s\n",
						       hfinfo->abbrev,
						       vals[vi].value,
						       vals[vi].strptr);
					}
				}
				vi++;
			}
		}
		else if (vals64) {
			vi = 0;
			while (vals64[vi].strptr) {
				ws_debug_printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
				       hfinfo->abbrev,
				       vals64[vi].value,
				       vals64[vi].strptr);
				vi++;
			}
		}

		/* print range strings? */
		else if (range) {
			vi = 0;
			while (range[vi].strptr) {
				/* Print in the proper base */
				if (FIELD_DISPLAY(hfinfo->display) == BASE_HEX) {
					ws_debug_printf("R\t%s\t0x%x\t0x%x\t%s\n",
					       hfinfo->abbrev,
					       range[vi].value_min,
					       range[vi].value_max,
					       range[vi].strptr);
				}
				else {
					ws_debug_printf("R\t%s\t%u\t%u\t%s\n",
					       hfinfo->abbrev,
					       range[vi].value_min,
					       range[vi].value_max,
					       range[vi].strptr);
				}
				vi++;
			}
		}

		/* Print true/false strings? */
		else if (tfs) {
			ws_debug_printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
			       tfs->true_string, tfs->false_string);
		}
		/* Print unit strings? */
		else if (units) {
			ws_debug_printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
			       units->singular, units->plural ? units->plural : "(no plural)");
		}
	}
}

Project: wireshark

protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
{
	gsize res = g_strlcpy(dest, src, dest_size);

	if (res > dest_size)
		res = dest_size;
	return (int) res;
}

Project: wireshark

fill_label_bitfield_char(field_info *fi, gchar *label_str)
{
	char       *p;
	int         bitfield_byte_length, bitwidth;
	guint32     unshifted_value;
	guint32     value;

	char        buf[32];
	const char *out;

	header_field_info *hfinfo = fi->hfinfo;

	/* Figure out the bit width */
	bitwidth = hfinfo_container_bitwidth(hfinfo);

	/* Un-shift bits */
	value = fvalue_get_uinteger(&fi->value);

	unshifted_value = value;
	if (hfinfo->bitmask) {
		unshifted_value <<= hfinfo_bitshift(hfinfo);
	}

	/* Create the bitfield first */
	p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
	bitfield_byte_length = (int) (p - label_str);

	/* Fill in the textual info using stored (shifted) value */
	if (hfinfo->display == BASE_CUSTOM) {
		gchar tmp[ITEM_LABEL_LENGTH];
		const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;

		DISSECTOR_ASSERT(fmtfunc);
		fmtfunc(tmp, value);
		label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
	}
	else if (hfinfo->strings) {
		const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");

		out = hfinfo_char_vals_format(hfinfo, buf, value);
		if (out == NULL) /* BASE_NONE so don't put integer in descr */
			label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
		else
			label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
	}
	else {
		out = hfinfo_char_value_format(hfinfo, buf, value);

		label_fill(label_str, bitfield_byte_length, hfinfo, out);
	}
}

Project: wireshark

proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		   gint length, const guint8* value_ptr)
{
	proto_item	  *pi;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);

	pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
	proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);

	return pi;
}

Project: wireshark

proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		   gint length, gint32 value)
{
	proto_item	  *pi = NULL;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	switch (hfinfo->type) {
		case FT_INT8:
		case FT_INT16:
		case FT_INT24:
		case FT_INT32:
			pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
			proto_tree_set_int(PNODE_FINFO(pi), value);
			break;

		default:
			REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
			    hfinfo->abbrev);
	}

	return pi;
}

Project: wireshark

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, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

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)
{
	field_info	  *new_fi;
	nstime_t	   time_stamp;
	gint		   saved_err = 0;
	header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);

	DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");

	DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);

	/* length has to be -1 or > 0 regardless of encoding */
	if (length < -1 || length == 0) {
		REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_time_item",
		    length);
	}

	time_stamp.secs  = 0;
	time_stamp.nsecs = 0;

	if (encoding & ENC_STR_TIME_MASK) {
		tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff);
		/* grab the errno now before it gets overwritten */
		saved_err = errno;
	}
	else {
		const gboolean is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? TRUE : FALSE;

		tvb_ensure_bytes_exist(tvb, start, length);
		get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
		if (endoff) *endoff = length;
	}

	if (err) *err = saved_err;

	if (retval) {
		retval->secs  = time_stamp.secs;
		retval->nsecs = time_stamp.nsecs;
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(tree, hfinfo, tvb, start, length);

	proto_tree_set_time(new_fi, &time_stamp);

	if (encoding & ENC_STRING) {
		if (saved_err == ERANGE)
		    expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
		else if (saved_err == EDOM)
		    expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
	}
	else {
		FI_SET_FLAG(new_fi,
			(encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
	}

	return proto_tree_add_node(tree, new_fi);
}

Project: wireshark

proto_register_protocol(const char *name, const char *short_name,
			const char *filter_name)
{
	protocol_t *protocol;
	header_field_info *hfinfo;

	/*
	 * Make sure there's not already a protocol with any of those
	 * names.  Crash if there is, as that's an error in the code
	 * or an inappropriate plugin.
	 * This situation has to be fixed to not register more than one
	 * protocol with the same name.
	 */

	if (g_hash_table_lookup(proto_names, name)) {
		/* g_error will terminate the program */
		g_error("Duplicate protocol name \"%s\"!"
			" This might be caused by an inappropriate plugin or a development error.", name);
	}

	if (g_hash_table_lookup(proto_short_names, short_name)) {
		g_error("Duplicate protocol short_name \"%s\"!"
			" This might be caused by an inappropriate plugin or a development error.", short_name);
	}

	check_valid_filter_name_or_fail(filter_name);

	if (g_hash_table_lookup(proto_filter_names, filter_name)) {
		g_error("Duplicate protocol filter_name \"%s\"!"
			" This might be caused by an inappropriate plugin or a development error.", filter_name);
	}

	/*
	 * Add this protocol to the list of known protocols;
	 * the list is sorted by protocol short name.
	 */
	protocol = g_new(protocol_t, 1);
	protocol->name = name;
	protocol->short_name = short_name;
	protocol->filter_name = filter_name;
	protocol->fields = NULL; /* Delegate until actually needed */
	protocol->is_enabled = TRUE; /* protocol is enabled by default */
	protocol->enabled_by_default = TRUE; /* see previous comment */
	protocol->can_toggle = TRUE;
	protocol->parent_proto_id = -1;
	protocol->heur_list = NULL;

	/* List will be sorted later by name, when all protocols completed registering */
	protocols = g_list_prepend(protocols, protocol);
	g_hash_table_insert(proto_names, (gpointer)name, protocol);
	g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
	g_hash_table_insert(proto_short_names, (gpointer)short_name, protocol);

	/* Here we allocate a new header_field_info struct */
	hfinfo = g_slice_new(header_field_info);
	hfinfo->name = name;
	hfinfo->abbrev = filter_name;
	hfinfo->type = FT_PROTOCOL;
	hfinfo->display = BASE_NONE;
	hfinfo->strings = protocol;
	hfinfo->bitmask = 0;
	hfinfo->ref_type = HF_REF_TYPE_NONE;
	hfinfo->blurb = NULL;
	hfinfo->parent = -1; /* This field differentiates protos and fields */

	protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
	return protocol->proto_id;
}

Project: wireshark

proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                            const gint start, gint length,
                            const guint encoding, gint32 *retval)
{
	header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
	field_info	  *new_fi;
	gint32		   value;

	DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");

	switch (hfinfo->type) {
	case FT_INT8:
	case FT_INT16:
	case FT_INT24:
	case FT_INT32:
		break;
	case FT_INT64:
		REPORT_DISSECTOR_BUG("64-bit signed integer field %s used with proto_tree_add_item_ret_int()",
		    hfinfo->abbrev);
	default:
		REPORT_DISSECTOR_BUG("Non-signed-integer field %s used with proto_tree_add_item_ret_int()",
		    hfinfo->abbrev);
	}

	/* length validation for native number encoding caught by get_uint_value() */
	/* length has to be -1 or > 0 regardless of encoding */
	if (length < -1 || length == 0)
		REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_int",
			length);

	if (encoding & ENC_STRING) {
		REPORT_DISSECTOR_BUG("wrong encoding");
	}
	/* I believe it's ok if this is called with a NULL tree */
	value = get_int_value(tree, tvb, start, length, encoding);

	if (retval) {
		gint no_of_bits;
		*retval = value;
		if (hfinfo->bitmask) {
			/* Mask out irrelevant portions */
			*retval &= (guint32)(hfinfo->bitmask);
			/* Shift bits */
			*retval >>= hfinfo_bitshift(hfinfo);
		}
		no_of_bits = ws_count_ones(hfinfo->bitmask);
		*retval = ws_sign_ext32(*retval, no_of_bits);
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(tree, hfinfo, tvb, start, length);

	proto_tree_set_int(new_fi, value);

	new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;

	return proto_tree_add_node(tree, new_fi);
}

Project: wireshark

proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
	if (! prefixes ) {
		prefixes = g_hash_table_new(prefix_hash, prefix_equal);
	}

	g_hash_table_insert(prefixes, (gpointer)prefix, (gpointer)pi);
}

Project: wireshark

find_protocol_by_id(const int proto_id)
{
	header_field_info *hfinfo;

	if (proto_id < 0)
		return NULL;

	PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
	if (hfinfo->type != FT_PROTOCOL) {
		DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
	}
	return (protocol_t *)hfinfo->strings;
}

Project: wireshark

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, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
{
	proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
}

Project: wireshark

proto_registrar_is_protocol(const int n)
{
	header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(n, hfinfo);
	return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? TRUE : FALSE);
}

Project: wireshark

proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
{
	PTREE_DATA(tree)->fake_protocols = fake_protocols;
}

Project: wireshark

proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
{
	if (proto != NULL) {
		g_ptr_array_add(proto->fields, hfi);
	}

	return proto_register_field_init(hfi, parent);
}

Project: wireshark

proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
				 gint start, gint length, guint32 value,
				 const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

dot_to_underscore(gchar* str)
{
	unsigned i;
	for (i = 0; i < strlen(str); i++) {
		if (str[i] == '.')
			str[i] = '_';
	}
	return str;
}

Project: wireshark

find_first_finfo(proto_node *node, gpointer data)
{
	field_info *fi = PNODE_FINFO(node);
	if (fi && fi->hfinfo) {
		if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
			g_ptr_array_add(((ffdata_t*)data)->array, fi);

			/* Stop traversing. */
			return TRUE;
		}
	}

	/* Continue traversing. */
	return FALSE;
}

Project: wireshark

proto_item_append_text(proto_item *pi, const char *format, ...)
{
	field_info *fi = NULL;
	size_t      curlen;
	va_list     ap;

	TRY_TO_FAKE_THIS_REPR_VOID(pi);

	fi = PITEM_FINFO(pi);
	if (fi == NULL) {
		return;
	}

	if (!proto_item_is_hidden(pi)) {
		/*
		 * If we don't already have a representation,
		 * generate the default representation.
		 */
		if (fi->rep == NULL) {
			ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
			proto_item_fill_label(fi, fi->rep->representation);
		}

		curlen = strlen(fi->rep->representation);
		if (ITEM_LABEL_LENGTH > curlen) {
			va_start(ap, format);
			g_vsnprintf(fi->rep->representation + curlen,
				ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
			va_end(ap);
		}
	}
}

Project: wireshark

proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
{
	proto_item *pi;
	va_list	    ap;

	pi = proto_tree_add_text_node(tree, NULL, 0, 0);

	if (pi) {
		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}
	va_start(ap, format);
	vprintf(format, ap);
	va_end(ap);
	ws_debug_printf("\n");

	return pi;
}

Project: wireshark

proto_tree_get_root(proto_tree *tree) {
	if (!tree)
		return NULL;
	while (tree->parent) {
		tree = tree->parent;
	}
	return tree;
}

Project: wireshark

proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *format, ...)
{
	proto_tree *pt;
	proto_item *pi;
	va_list	    ap;

	va_start(ap, format);
	pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
	va_end(ap);

	if (tree_item != NULL)
		*tree_item = pi;

	pt = proto_item_add_subtree(pi, idx);

	return pt;
}

Project: wireshark

proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
				    tvbuff_t *tvb, gint start, gint length,
				    guint32 value, const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

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 char *format, ...)
{
	va_list ap;
	gchar  *dst;
	header_field_info *hf_field;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);

	DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);

	CREATE_VALUE_STRING(dst, format, ap);

	return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
}

Project: wireshark

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 char *format, ...)
{
	va_list ap;
	gchar  *dst;
	header_field_info *hf_field;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);

	switch (hf_field->type) {
		case FT_INT40:
		case FT_INT48:
		case FT_INT56:
		case FT_INT64:
			break;

		default:
			REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
			    hf_field->abbrev);
			return NULL;
			break;
	}

	CREATE_VALUE_STRING(dst, format, ap);

	return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
}

Project: wireshark

proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		     gint length, const guint8 *start_ptr)
{
	proto_item	  *pi;
	header_field_info *hfinfo;
	gint		  item_length;

	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
	get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
	test_length(hfinfo, tvb, start, item_length, ENC_NA);

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);

	pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
	proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);

	return pi;
}

Project: wireshark

proto_registrar_get_id_byname(const char *field_name)
{
	header_field_info *hfinfo;

	hfinfo = proto_registrar_get_byname(field_name);

	if (!hfinfo)
		return -1;

	return hfinfo->id;
}

Project: wireshark

get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
{
	gint32 value;
	gboolean length_error;

	switch (length) {

	case 1:
		value = tvb_get_gint8(tvb, offset);
		break;

	case 2:
		value = encoding ? tvb_get_letohis(tvb, offset)
				 : tvb_get_ntohis(tvb, offset);
		break;

	case 3:
		value = encoding ? tvb_get_letohi24(tvb, offset)
				 : tvb_get_ntohi24(tvb, offset);
		break;

	case 4:
		value = encoding ? tvb_get_letohil(tvb, offset)
				 : tvb_get_ntohil(tvb, offset);
		break;

	default:
		if (length < 1) {
			length_error = TRUE;
			value = 0;
		} else {
			length_error = FALSE;
			value = encoding ? tvb_get_letohil(tvb, offset)
					 : tvb_get_ntohil(tvb, offset);
		}
		report_type_length_mismatch(tree, "a signed integer", length, length_error);
		break;
	}
	return value;
}

Project: wireshark

proto_field_is_referenced(proto_tree *tree, int proto_id)
{
	register header_field_info *hfinfo;


	if (!tree)
		return FALSE;

	if (PTREE_DATA(tree)->visible)
		return TRUE;

	PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
	if (hfinfo->ref_type != HF_REF_TYPE_NONE)
		return TRUE;

	if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
		return TRUE;

	return FALSE;
}

Project: wireshark

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)
{
	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);
}

Project: wireshark

void proto_report_dissector_bug(const char *format, ...)
{
	va_list args;

	if (wireshark_abort_on_dissector_bug) {
		/*
		 * Try to have the error message show up in the crash
		 * information.
		 */
		va_start(args, format);
		ws_vadd_crash_info(format, args);
		va_end(args);

		/*
		 * Print the error message.
		 */
		va_start(args, format);
		vfprintf(stderr, format, args);
		va_end(args);
		putc('\n', stderr);

		/*
		 * And crash.
		 */
		abort();
	} else {
		va_start(args, format);
		VTHROW_FORMATTED(DissectorError, format, args);
		va_end(args);
	}
}

Project: wireshark

void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
{
	heur_dtbl_entry_t* heuristic_dissector;

	if (protocol == NULL)
		return;

	heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
	if (heuristic_dissector != NULL)
	{
		protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
	}
}

Project: wireshark

proto_item_set_bits_offset_len(proto_item *ti, int bits_offset, int bits_len) {
	if (!ti) {
		return;
	}
	FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_OFFSET(bits_offset));
	FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_SIZE(bits_len));
}

Project: wireshark

proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			    gint start, gint length, const guint8 *start_ptr,
			    const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	if (start_ptr == NULL)
		start_ptr = tvb_get_ptr(tvb, start, length);

	pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);

	TRY_TO_FAKE_THIS_REPR_NESTED(pi);

	va_start(ap, format);
	proto_tree_set_representation(pi, format, ap);
	va_end(ap);

	return pi;
}

Project: wireshark

proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
                                const gint start, gint length,
                                const guint encoding, gboolean *retval)
{
	header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
	field_info	  *new_fi;
	guint64		   value, bitval;

	DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");

	if (hfinfo->type != FT_BOOLEAN) {
		REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
		    hfinfo->abbrev);
	}

	/* length validation for native number encoding caught by get_uint64_value() */
	/* length has to be -1 or > 0 regardless of encoding */
	if (length < -1 || length == 0)
		REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_boolean",
			length);

	if (encoding & ENC_STRING) {
		REPORT_DISSECTOR_BUG("wrong encoding");
	}
	/* I believe it's ok if this is called with a NULL tree */
	value = get_uint64_value(tree, tvb, start, length, encoding);

	if (retval) {
		bitval = value;
		if (hfinfo->bitmask) {
			/* Mask out irrelevant portions */
			bitval &= hfinfo->bitmask;
		}
		*retval = (bitval != 0);
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(tree, hfinfo, tvb, start, length);

	proto_tree_set_boolean(new_fi, value);

	new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;

	return proto_tree_add_node(tree, new_fi);
}

Project: wireshark

label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
{
	gsize name_pos;

	/* "%s: %s (%s)", hfinfo->name, text, descr */
	name_pos = pos = label_concat(label_str, pos, hfinfo->name);
	if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
		pos = label_concat(label_str, pos, ": ");
		if (hfinfo->display & BASE_UNIT_STRING) {
			pos = label_concat(label_str, pos, descr ? descr : "(null)");
			pos = label_concat(label_str, pos, text ? text : "(null)");
		} else {
			pos = label_concat(label_str, pos, text ? text : "(null)");
			pos = label_concat(label_str, pos, " (");
			pos = label_concat(label_str, pos, descr ? descr : "(null)");
			pos = label_concat(label_str, pos, ")");
		}
	}

	if (pos >= ITEM_LABEL_LENGTH) {
		/* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
		label_mark_truncated(label_str, name_pos);
	}

	return pos;
}

Project: wireshark

fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
{
	header_field_info *hfinfo = fi->hfinfo;
	guint32            value;

	char               buf[32];
	const char        *out;

	if (is_signed)
		value = fvalue_get_sinteger(&fi->value);
	else
		value = fvalue_get_uinteger(&fi->value);

	/* Fill in the textual info */
	if (hfinfo->display == BASE_CUSTOM) {
		gchar tmp[ITEM_LABEL_LENGTH];
		const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;

		DISSECTOR_ASSERT(fmtfunc);
		fmtfunc(tmp, value);
		label_fill(label_str, 0, hfinfo, tmp);
	}
	else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
		/*
		 * It makes no sense to have a value-string table for a
		 * frame-number field - they're just integers giving
		 * the ordinal frame number.
		 */
		const char *val_str = hf_try_val_to_str(value, hfinfo);

		out = hfinfo_number_vals_format(hfinfo, buf, value);
		if (hfinfo->display & BASE_SPECIAL_VALS) {
			/*
			 * Unique values only display value_string string
			 * if there is a match. Otherwise it's just a number
			 */
			if (val_str) {
				label_fill_descr(label_str, 0, hfinfo, val_str, out);
			} else {
				label_fill(label_str, 0, hfinfo, out);
			}
		} else {
			if (val_str == NULL)
				val_str = "Unknown";

			if (out == NULL) /* BASE_NONE so don't put integer in descr */
				label_fill(label_str, 0, hfinfo, val_str);
			else
				label_fill_descr(label_str, 0, hfinfo, val_str, out);
		}
	}
	else if (IS_BASE_PORT(hfinfo->display)) {
		gchar tmp[ITEM_LABEL_LENGTH];

		port_with_resolution_to_str_buf(tmp, sizeof(tmp),
			display_to_port_type((field_display_e)hfinfo->display), value);
		label_fill(label_str, 0, hfinfo, tmp);
	}
	else {
		out = hfinfo_number_value_format(hfinfo, buf, value);

		label_fill(label_str, 0, hfinfo, out);
	}
}

Project: wireshark

hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value)
{
	char *ptr = &buf[47];
	gboolean isint = IS_FT_INT(hfinfo->type);

	*ptr = '\0';
	/* Properly format value */
	switch (FIELD_DISPLAY(display)) {
		case BASE_DEC:
			return isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);

		case BASE_DEC_HEX:
			*(--ptr) = ')';
			ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
			*(--ptr) = '(';
			*(--ptr) = ' ';
			ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
			return ptr;

		case BASE_OCT:
			return oct64_to_str_back(ptr, value);

		case BASE_HEX:
			return hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);

		case BASE_HEX_DEC:
			*(--ptr) = ')';
			ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
			*(--ptr) = '(';
			*(--ptr) = ' ';
			ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
			return ptr;

		default:
			g_assert_not_reached();
	}

	return ptr;
}

Project: wireshark

proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
			     gint start, gint length, guint32 value,
			     const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		TRY_TO_FAKE_THIS_REPR(pi);

		va_start(ap, format);
		proto_tree_set_representation(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

ptvcursor_current_offset(ptvcursor_t *ptvc)
{
	return ptvc->offset;
}

Project: wireshark

proto_tree_free_node(proto_node *node, gpointer data _U_)
{
	field_info *finfo  = PNODE_FINFO(node);

	proto_tree_children_foreach(node, proto_tree_free_node, NULL);

	FVALUE_CLEANUP(&finfo->value);
}

Project: wireshark

proto_free_deregistered_fields (void)
{
	expert_free_deregistered_expertinfos();

	g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
	g_ptr_array_free(deregistered_fields, TRUE);
	deregistered_fields = g_ptr_array_new();

	g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
	g_ptr_array_free(deregistered_data, TRUE);
	deregistered_data = g_ptr_array_new();
}

Project: wireshark

label_mark_truncated(char *label_str, gsize name_pos)
{
	static const char  trunc_str[] = " [truncated]";
	const size_t       trunc_len = sizeof(trunc_str)-1;
	gchar             *last_char;

	/* ..... field_name: dataaaaaaaaaaaaa
	 *                 |
	 *                 ^^^^^ name_pos
	 *
	 * ..... field_name [truncated]: dataaaaaaaaaaaaa
	 *
	 * name_pos==0 means that we have only data or only a field_name
	 */

	if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
		memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
		memcpy(label_str + name_pos, trunc_str, trunc_len);

		/* in general, label_str is UTF-8
		   we can truncate it only at the beginning of a new character
		   we go backwards from the byte right after our buffer and
		    find the next starting byte of a UTF-8 character, this is
		    where we cut
		   there's no need to use g_utf8_find_prev_char(), the search
		    will always succeed since we copied trunc_str into the
		    buffer */
		last_char = g_utf8_prev_char(&label_str[ITEM_LABEL_LENGTH - 1]);
		*last_char = '\0';

	} else if (name_pos < ITEM_LABEL_LENGTH)
		g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
}

Project: wireshark

fill_label_char(field_info *fi, gchar *label_str)
{
	header_field_info *hfinfo = fi->hfinfo;
	guint32            value;

	char               buf[32];
	const char        *out;

	value = fvalue_get_uinteger(&fi->value);

	/* Fill in the textual info */
	if (hfinfo->display == BASE_CUSTOM) {
		gchar tmp[ITEM_LABEL_LENGTH];
		const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;

		DISSECTOR_ASSERT(fmtfunc);
		fmtfunc(tmp, value);
		label_fill(label_str, 0, hfinfo, tmp);
	}
	else if (hfinfo->strings) {
		const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");

		out = hfinfo_char_vals_format(hfinfo, buf, value);
		label_fill_descr(label_str, 0, hfinfo, val_str, out);
	}
	else {
		out = hfinfo_char_value_format(hfinfo, buf, value);

		label_fill(label_str, 0, hfinfo, out);
	}
}

Project: wireshark

proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		      gint length, guint32 value)
{
	proto_item	  *pi;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);

	pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
	proto_tree_set_ipxnet(PNODE_FINFO(pi), value);

	return pi;
}

Project: wireshark

proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
{
	g_assert(pi);

	/* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
	 * items string representation */
	if (PTREE_DATA(pi)->visible && !proto_item_is_hidden(pi)) {
		int               ret = 0;
		field_info        *fi = PITEM_FINFO(pi);
		header_field_info *hf;

		DISSECTOR_ASSERT(fi);

		hf = fi->hfinfo;

		ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
		if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
			guint64 val;
			char *p;

			if (IS_FT_UINT32(hf->type))
				val = fvalue_get_uinteger(&fi->value);
			else
				val = fvalue_get_uinteger64(&fi->value);

			val <<= hfinfo_bitshift(hf);

			p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
			ret = (int) (p - fi->rep->representation);
		}

		/* put in the hf name */
		ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);

		/* If possible, Put in the value of the string */
		if (ret < ITEM_LABEL_LENGTH) {
			ret += g_vsnprintf(fi->rep->representation + ret,
					  ITEM_LABEL_LENGTH - ret, format, ap);
		}
		if (ret >= ITEM_LABEL_LENGTH) {
			/* Uh oh, we don't have enough room.  Tell the user
			 * that the field is truncated.
			 */
			LABEL_MARK_TRUNCATED_START(fi->rep->representation);
		}
	}
}

Project: wireshark

proto_item_fill_label(field_info *fi, gchar *label_str)
{
	header_field_info  *hfinfo;
	guint8		   *bytes;
	guint32		    integer;
	guint64		    integer64;
	ws_in4_addr         ipv4;
	e_guid_t	   *guid;
	gchar		   *name;
	address		    addr;
	char		   *addr_str;
	char		   *tmp;

	if (!fi) {
		if (label_str)
			label_str[0]= '\0';
		/* XXX: Check validity of hfinfo->type */
		return;
	}

	hfinfo = fi->hfinfo;

	switch (hfinfo->type) {
		case FT_NONE:
		case FT_PROTOCOL:
			g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
			break;

		case FT_BOOLEAN:
			fill_label_boolean(fi, label_str);
			break;

		case FT_BYTES:
		case FT_UINT_BYTES:
			tmp = hfinfo_format_bytes(NULL, hfinfo,
			    (guint8 *)fvalue_get(&fi->value),
			    fvalue_length(&fi->value));
			label_fill(label_str, 0, hfinfo, tmp);
			wmem_free(NULL, tmp);
			break;

		case FT_CHAR:
			if (hfinfo->bitmask) {
				fill_label_bitfield_char(fi, label_str);
			} else {
				fill_label_char(fi, label_str);
			}
			break;

		/* Four types of integers to take care of:
		 *	Bitfield, with val_string
		 *	Bitfield, w/o val_string
		 *	Non-bitfield, with val_string
		 *	Non-bitfield, w/o val_string
		 */
		case FT_UINT8:
		case FT_UINT16:
		case FT_UINT24:
		case FT_UINT32:
			if (hfinfo->bitmask) {
				if (fi->flags & FI_VARINT) {
					fill_label_bitfield_varint(fi, label_str, FALSE);
				} else {
					fill_label_bitfield(fi, label_str, FALSE);
				}
			} else {
				fill_label_number(fi, label_str, FALSE);
			}
			break;

		case FT_FRAMENUM:
			fill_label_number(fi, label_str, FALSE);
			break;

		case FT_UINT40:
		case FT_UINT48:
		case FT_UINT56:
		case FT_UINT64:
			if (hfinfo->bitmask) {
				if (fi->flags & FI_VARINT) {
					fill_label_bitfield_varint64(fi, label_str, FALSE);
				} else {
					fill_label_bitfield64(fi, label_str, FALSE);
				}
			} else {
				fill_label_number64(fi, label_str, FALSE);
			}
			break;

		case FT_INT8:
		case FT_INT16:
		case FT_INT24:
		case FT_INT32:
			if (hfinfo->bitmask) {
				if (fi->flags & FI_VARINT) {
					fill_label_bitfield_varint(fi, label_str, TRUE);
				} else {
					fill_label_bitfield(fi, label_str, TRUE);
				}
			} else {
				fill_label_number(fi, label_str, TRUE);
			}
			break;

		case FT_INT40:
		case FT_INT48:
		case FT_INT56:
		case FT_INT64:
			if (hfinfo->bitmask) {
				if (fi->flags & FI_VARINT) {
					fill_label_bitfield_varint64(fi, label_str, TRUE);
				} else {
					fill_label_bitfield64(fi, label_str, TRUE);
				}
			} else {
				fill_label_number64(fi, label_str, TRUE);
			}
			break;

		case FT_FLOAT:
		{
			double d_value = fvalue_get_floating(&fi->value);
			if (hfinfo->display & BASE_UNIT_STRING) {
				g_snprintf(label_str, ITEM_LABEL_LENGTH,
					   "%s: %." G_STRINGIFY(FLT_DIG) "g%s",
					   hfinfo->name, d_value,
					   unit_name_string_get_double(d_value, (const unit_name_string*)hfinfo->strings));
			} else {
				g_snprintf(label_str, ITEM_LABEL_LENGTH,
					   "%s: %." G_STRINGIFY(FLT_DIG) "g",
					   hfinfo->name, d_value);
			}
			break;
		}

		case FT_DOUBLE:
		{
			double d_value = fvalue_get_floating(&fi->value);
			if (hfinfo->display & BASE_UNIT_STRING) {
				g_snprintf(label_str, ITEM_LABEL_LENGTH,
					   "%s: %." G_STRINGIFY(DBL_DIG) "g%s",
					   hfinfo->name, d_value,
					   unit_name_string_get_double(d_value, (const unit_name_string*)hfinfo->strings));
			} else {
				g_snprintf(label_str, ITEM_LABEL_LENGTH,
					   "%s: %." G_STRINGIFY(DBL_DIG) "g",
					   hfinfo->name, d_value);
			}
			break;
		}

		case FT_ABSOLUTE_TIME:
			tmp = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&fi->value), (absolute_time_display_e)hfinfo->display, TRUE);
			label_fill(label_str, 0, hfinfo, tmp);
			wmem_free(NULL, tmp);
			break;

		case FT_RELATIVE_TIME:
			tmp = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&fi->value));
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s seconds", hfinfo->name, tmp);
			wmem_free(NULL, tmp);
			break;

		case FT_IPXNET:
			integer = fvalue_get_uinteger(&fi->value);
			tmp = get_ipxnet_name(NULL, integer);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s (0x%08X)", hfinfo->name,
				   tmp, integer);
			wmem_free(NULL, tmp);
			break;

		case FT_AX25:
			addr.type = AT_AX25;
			addr.len  = AX25_ADDR_LEN;
			addr.data = (guint8 *)fvalue_get(&fi->value);

			addr_str = (char*)address_to_str(NULL, &addr);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s", hfinfo->name, addr_str);
			wmem_free(NULL, addr_str);
			break;

		case FT_VINES:
			addr.type = AT_VINES;
			addr.len  = VINES_ADDR_LEN;
			addr.data = (guint8 *)fvalue_get(&fi->value);

			addr_str = (char*)address_to_str(NULL, &addr);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s", hfinfo->name, addr_str);
			wmem_free(NULL, addr_str);
			break;

		case FT_ETHER:
			bytes = (guint8 *)fvalue_get(&fi->value);

			addr.type = AT_ETHER;
			addr.len  = 6;
			addr.data = bytes;

			addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s", hfinfo->name, addr_str);
			wmem_free(NULL, addr_str);
			break;

		case FT_IPv4:
			ipv4 = fvalue_get_uinteger(&fi->value);

			addr.type = AT_IPv4;
			addr.len  = 4;
			addr.data = &ipv4;

			if (hfinfo->display == BASE_NETMASK) {
				addr_str = (char*)address_to_str(NULL, &addr);
			} else {
				addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
			}
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s", hfinfo->name, addr_str);
			wmem_free(NULL, addr_str);
			break;

		case FT_IPv6:
			bytes = (guint8 *)fvalue_get(&fi->value);

			addr.type = AT_IPv6;
			addr.len  = 16;
			addr.data = bytes;

			addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s", hfinfo->name, addr_str);
			wmem_free(NULL, addr_str);
			break;

		case FT_FCWWN:
			addr.type = AT_FCWWN;
			addr.len  = FCWWN_ADDR_LEN;
			addr.data = (guint8 *)fvalue_get(&fi->value);

			addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
				   "%s: %s", hfinfo->name, addr_str);
			wmem_free(NULL, addr_str);
			break;

		case FT_GUID:
			guid = (e_guid_t *)fvalue_get(&fi->value);
			tmp = guid_to_str(NULL, guid);
			label_fill(label_str, 0, hfinfo, tmp);
			wmem_free(NULL, tmp);
			break;

		case FT_OID:
			bytes = (guint8 *)fvalue_get(&fi->value);
			name = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
			tmp = oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
			if (name) {
				label_fill_descr(label_str, 0, hfinfo, tmp, name);
				wmem_free(NULL, name);
			} else {
				label_fill(label_str, 0, hfinfo, tmp);
			}
			wmem_free(NULL, tmp);
			break;

		case FT_REL_OID:
			bytes = (guint8 *)fvalue_get(&fi->value);
			name = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
			tmp = rel_oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
			if (name) {
				label_fill_descr(label_str, 0, hfinfo, tmp, name);
				wmem_free(NULL, name);
			} else {
				label_fill(label_str, 0, hfinfo, tmp);
			}
			wmem_free(NULL, tmp);
			break;

		case FT_SYSTEM_ID:
			bytes = (guint8 *)fvalue_get(&fi->value);
			tmp = print_system_id(NULL, bytes, fvalue_length(&fi->value));
			label_fill(label_str, 0, hfinfo, tmp);
			wmem_free(NULL, tmp);
			break;

		case FT_EUI64:
			integer64 = fvalue_get_uinteger64(&fi->value);
			addr_str = eui64_to_str(NULL, integer64);
			tmp = (char*)eui64_to_display(NULL, integer64);
			label_fill_descr(label_str, 0, hfinfo, tmp, addr_str);
			wmem_free(NULL, tmp);
			wmem_free(NULL, addr_str);
			break;
		case FT_STRING:
		case FT_STRINGZ:
		case FT_UINT_STRING:
		case FT_STRINGZPAD:
		case FT_STRINGZTRUNC:
			bytes = (guint8 *)fvalue_get(&fi->value);
			tmp = hfinfo_format_text(NULL, hfinfo, bytes);
			label_fill(label_str, 0, hfinfo, tmp);
			wmem_free(NULL, tmp);
			break;

		case FT_IEEE_11073_SFLOAT:
		case FT_IEEE_11073_FLOAT:
			tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
			g_snprintf(label_str, ITEM_LABEL_LENGTH,
						"%s: %s",
						hfinfo->name, tmp);
			wmem_free(NULL, tmp);
			break;

		default:
			REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_fill_label()",
					     hfinfo->abbrev,
					     hfinfo->type,
					     ftype_name(hfinfo->type));
			break;
	}
}

Project: wireshark

check_for_undecoded(proto_node *node, gpointer data)
{
	field_info *fi = PNODE_FINFO(node);
	decoded_data_t* decoded = (decoded_data_t*)data;
	gint i;
	guint byte;
	guint bit;

	if (fi && fi->hfinfo->type != FT_PROTOCOL) {
		for (i = fi->start; i < fi->start + fi->length && i < decoded->length; i++) {
			byte = i / 8;
			bit = i % 8;
			decoded->buf[byte] |= (1 << bit);
		}
	}

	return FALSE;
}

Project: wireshark

proto_init(GSList *register_all_plugin_protocols_list,
	   GSList *register_all_plugin_handoffs_list,
	   register_cb cb,
	   gpointer client_data)
{
	proto_cleanup_base();

	proto_names        = g_hash_table_new(g_str_hash, g_str_equal);
	proto_short_names  = g_hash_table_new(g_str_hash, g_str_equal);
	proto_filter_names = g_hash_table_new(g_str_hash, g_str_equal);

	gpa_hfinfo.len           = 0;
	gpa_hfinfo.allocated_len = 0;
	gpa_hfinfo.hfi           = NULL;
	gpa_name_map             = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
	gpa_protocol_aliases     = g_hash_table_new(g_str_hash, g_str_equal);
	deregistered_fields      = g_ptr_array_new();
	deregistered_data        = g_ptr_array_new();

	/* Initialize the ftype subsystem */
	ftypes_initialize();

	/* Initialize the addres type subsystem */
	address_types_initialize();

	/* Register one special-case FT_TEXT_ONLY field for use when
	   converting wireshark to new-style proto_tree. These fields
	   are merely strings on the GUI tree; they are not filterable */
	hf_text_only = proto_register_field_init(&hfi_text_only, -1);

	/* Register the pseudo-protocols used for exceptions. */
	register_show_exception();
	register_type_length_mismatch();
	register_number_string_decoding_error();
	register_string_errors();

	/* Have each built-in dissector register its protocols, fields,
	   dissector tables, and dissectors to be called through a
	   handle, and do whatever one-time initialization it needs to
	   do. */
	register_all_protocols(cb, client_data);

	/* Now call the registration routines for all epan plugins. */
	for (GSList *l = register_all_plugin_protocols_list; l != NULL; l = l->next) {
		((void (*)(register_cb, gpointer))l->data)(cb, client_data);
	}

#ifdef HAVE_PLUGINS
	/* Now call the registration routines for all dissector plugins. */
	if (cb)
		(*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
	g_slist_foreach(dissector_plugins, call_plugin_register_protoinfo, NULL);
#endif

	/* Now call the "handoff registration" routines of all built-in
	   dissectors; those routines register the dissector in other
	   dissectors' handoff tables, and fetch any dissector handles
	   they need. */
	register_all_protocol_handoffs(cb, client_data);

	/* Now do the same with epan plugins. */
	for (GSList *l = register_all_plugin_handoffs_list; l != NULL; l = l->next) {
		((void (*)(register_cb, gpointer))l->data)(cb, client_data);
	}

#ifdef HAVE_PLUGINS
	/* Now do the same with dissector plugins. */
	if (cb)
		(*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
	g_slist_foreach(dissector_plugins, call_plugin_register_handoff, NULL);
#endif

	/* sort the protocols by protocol name */
	protocols = g_list_sort(protocols, proto_compare_name);

	/* We've assigned all the subtree type values; allocate the array
	   for them, and zero it out. */
	tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
}

Project: wireshark

check_for_offset(proto_node *node, gpointer data)
{
	field_info	*fi        = PNODE_FINFO(node);
	offset_search_t	*offsearch = (offset_search_t *)data;

	/* !fi == the top most container node which holds nothing */
	if (fi && !proto_item_is_hidden(node) && !proto_item_is_generated(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
		if (offsearch->offset >= (guint) fi->start &&
				offsearch->offset < (guint) (fi->start + fi->length)) {

			offsearch->finfo = fi;
			return FALSE; /* keep traversing */
		}
	}
	return FALSE; /* keep traversing */
}

Project: wireshark

ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
{
	subtree_lvl *pushed_tree;

	DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
	ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;

	pushed_tree = (subtree_lvl *)wmem_alloc(wmem_packet_scope(), sizeof(subtree_lvl) * ptvc->pushed_tree_max);
	DISSECTOR_ASSERT(pushed_tree != NULL);
	if (ptvc->pushed_tree)
		memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
	ptvc->pushed_tree = pushed_tree;
}

Project: wireshark

proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
				  gint start, gint length, const guint64 value,
				  const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;

	pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
	if (pi != tree) {
		va_start(ap, format);
		proto_tree_set_representation_value(pi, format, ap);
		va_end(ap);
	}

	return pi;
}

Project: wireshark

ptvcursor_add_ret_int(ptvcursor_t *ptvc, int hfindex, gint length,
	      const guint encoding, gint32 *retval)
{
	field_info	  *new_fi;
	header_field_info *hfinfo;
	gint		   item_length;
	int		   offset;
	guint32		   value;

	offset = ptvc->offset;
	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);

	switch (hfinfo->type) {
	case FT_INT8:
	case FT_INT16:
	case FT_INT24:
	case FT_INT32:
		break;
	default:
		REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
		    hfinfo->abbrev);
	}

	get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
	test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);

	/* I believe it's ok if this is called with a NULL tree */
	/* XXX - modify if we ever support EBCDIC FT_CHAR */
	value = get_int_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);

	if (retval) {
		gint no_of_bits;
		*retval = value;
		if (hfinfo->bitmask) {
			/* Mask out irrelevant portions */
			*retval &= (guint32)(hfinfo->bitmask);
			/* Shift bits */
			*retval >>= hfinfo_bitshift(hfinfo);
		}
		no_of_bits = ws_count_ones(hfinfo->bitmask);
		*retval = ws_sign_ext32(*retval, no_of_bits);
	}

	ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
	    item_length, encoding);

	CHECK_FOR_NULL_TREE(ptvc->tree);

	/* Coast clear. Try and fake it */
	TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);

	new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);

	return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
		offset, length, encoding);
}

Project: wireshark

proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
		    gint length, const ws_in6_addr *value_ptr)
{
	proto_item	  *pi;
	header_field_info *hfinfo;

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);

	DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);

	pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
	proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr->bytes);

	return pi;
}

Project: wireshark

proto_registrar_get_length(const int n)
{
	header_field_info *hfinfo;

	PROTO_REGISTRAR_GET_NTH(n, hfinfo);
	return ftype_length(hfinfo->type);
}

Project: wireshark

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)
{
	proto_item        *item = NULL;
	header_field_info *hf;
	int                len;
	guint64            value;

	PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
	DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
	len = ftype_length(hf->type);
	value = get_uint64_value(parent_tree, tvb, offset, len, encoding);

	if (parent_tree) {
		item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
		proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
		    flags, FALSE, FALSE, NULL, value);
	}

	*retval = value;
	if (hf->bitmask) {
		/* Mask out irrelevant portions */
		*retval &= hf->bitmask;
		/* Shift bits */
		*retval >>= hfinfo_bitshift(hf);
	}

	return item;
}

Project: wireshark

hfinfo_container_bitwidth(const header_field_info *hfinfo)
{
	if (!hfinfo->bitmask) {
		return 0;
	}

	if (hfinfo->type == FT_BOOLEAN) {
		return hfinfo->display; /* hacky? :) */
	}

	return hfinfo_type_bitwidth(hfinfo->type);
}

Project: wireshark

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)
{
	proto_item *pi;
	header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
	field_info	  *new_fi;
	const guint8	  *value;
	guint32		   n = 0;

	DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");

	switch (hfinfo->type) {
	case FT_STRING:
		value = get_string_value(scope, tvb, start, length, lenretval, encoding);
		*retval = hfinfo_format_text(scope, hfinfo, value);
		break;
	case FT_STRINGZ:
		value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
		*retval = hfinfo_format_text(scope, hfinfo, value);
		break;
	case FT_UINT_STRING:
		value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
		*retval = hfinfo_format_text(scope, hfinfo, value);
		break;
	case FT_STRINGZPAD:
		value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
		*retval = hfinfo_format_text(scope, hfinfo, value);
		break;
	case FT_STRINGZTRUNC:
		value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
		*retval = hfinfo_format_text(scope, hfinfo, value);
		break;
	case FT_BYTES:
		value = tvb_get_ptr(tvb, start, length);
		*retval = hfinfo_format_bytes(scope, hfinfo, value, length);
		*lenretval = length;
		break;
	case FT_UINT_BYTES:
		n = get_uint_value(tree, tvb, start, length, encoding);
		value = tvb_get_ptr(tvb, start + length, n);
		*retval = hfinfo_format_bytes(scope, hfinfo, value, n);
		*lenretval = length + n;
		break;
	default:
		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",
		    hfinfo->abbrev);
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);

	new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);

	switch (hfinfo->type) {

	case FT_STRING:
	case FT_STRINGZ:
	case FT_UINT_STRING:
	case FT_STRINGZPAD:
	case FT_STRINGZTRUNC:
		proto_tree_set_string(new_fi, value);
		break;

	case FT_BYTES:
		proto_tree_set_bytes(new_fi, value, length);
		break;

	case FT_UINT_BYTES:
		proto_tree_set_bytes(new_fi, value, n);
		break;
	default:
		g_assert_not_reached();
	}

	new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;

	pi = proto_tree_add_node(tree, new_fi);

	switch (hfinfo->type) {

	case FT_STRINGZ:
	case FT_STRINGZPAD:
	case FT_STRINGZTRUNC:
	case FT_UINT_STRING:
		break;

	case FT_STRING:
		detect_trailing_stray_characters(encoding, value, length, pi);
		break;

	case FT_BYTES:
	case FT_UINT_BYTES:
		break;

	default:
		g_assert_not_reached();
	}

	return pi;
}

Project: wireshark

hfinfo_mask_bitwidth(const header_field_info *hfinfo)
{
	if (!hfinfo->bitmask) {
		return 0;
	}

	/* ilog2 = first set bit, ctz = last set bit */
	return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
}

Project: wireshark

get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
    gint length, gint *ret_length, const guint encoding)
{
	/*
	 * XXX - currently, string values are null-
	 * terminated, so a "zero-padded" string
	 * isn't special.  If we represent string
	 * values as something that includes a counted
	 * array of bytes, we'll need to strip the
	 * trailing NULs.
	 */
	if (length == -1) {
		length = tvb_ensure_captured_length_remaining(tvb, start);
	}
	*ret_length = length;
	return tvb_get_string_enc(scope, tvb, start, length, encoding);
}

Project: wireshark

proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
		    const char *format, ...)
{
	proto_item	  *pi;
	va_list		   ap;
	header_field_info *hfinfo;

	if (length == -1) {
		length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
	} else {
		tvb_ensure_bytes_exist(tvb, start, length);
	}

	CHECK_FOR_NULL_TREE(tree);

	TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);

	pi = proto_tree_add_text_node(tree, tvb, start, length);

	TRY_TO_FAKE_THIS_REPR(pi);

	va_start(ap, format);
	proto_tree_set_representation(pi, format, ap);
	va_end(ap);

	return pi;
}

Project: wireshark

proto_registrar_dump_elastic(const gchar* filter)
{
	header_field_info *hfinfo;
	header_field_info *parent_hfinfo;
	guint i;
	gboolean open_object = TRUE;
	const char* prev_proto = NULL;
	gchar* str;
	gchar** protos = NULL;
	gchar* proto;
	gboolean found;
	guint j;
	gchar* type;

	/* We have filtering protocols. Extract them. */
	if (filter) {
		protos = g_strsplit(filter, ",", -1);
	}

	/*
	 * To help tracking down the json tree, objects have been appended with a comment:
	 * n.label -> where n is the indentation level and label the name of the object
	 */

	json_dumper dumper = {
		.output_file = stdout,
		.flags = JSON_DUMPER_FLAGS_PRETTY_PRINT,
	};
	json_dumper_begin_object(&dumper); // 1.root
	elastic_add_base_mapping(&dumper);

	json_dumper_set_member_name(&dumper, "mappings");
	json_dumper_begin_object(&dumper); // 2.mappings
	json_dumper_set_member_name(&dumper, "doc");

	json_dumper_begin_object(&dumper); // 3.doc
	json_dumper_set_member_name(&dumper, "dynamic");
	json_dumper_value_anyf(&dumper, "false");

	json_dumper_set_member_name(&dumper, "properties");
	json_dumper_begin_object(&dumper); // 4.properties
	json_dumper_set_member_name(&dumper, "timestamp");
	json_dumper_begin_object(&dumper); // 5.timestamp
	json_dumper_set_member_name(&dumper, "type");
	json_dumper_value_string(&dumper, "date");
	json_dumper_end_object(&dumper); // 5.timestamp

	json_dumper_set_member_name(&dumper, "layers");
	json_dumper_begin_object(&dumper); // 5.layers
	json_dumper_set_member_name(&dumper, "properties");
	json_dumper_begin_object(&dumper); // 6.properties

	for (i = 0; i < gpa_hfinfo.len; i++) {
		if (gpa_hfinfo.hfi[i] == NULL)
			continue; /* This is a deregistered protocol or header field */

		PROTO_REGISTRAR_GET_NTH(i, hfinfo);

		/*
		 * Skip the pseudo-field for "proto_tree_add_text()" since
		 * we don't want it in the list of filterable protocols.
		 */
		if (hfinfo->id == hf_text_only)
			continue;

		if (!proto_registrar_is_protocol(i)) {
			PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);

			/*
			 * Skip the field if filter protocols have been set and this one's
			 * parent is not listed.
			 */
			if (protos) {
				found = FALSE;
				j = 0;
				proto = protos[0];
				while(proto) {
					if (!g_strcmp0(proto, parent_hfinfo->abbrev)) {
						found = TRUE;
						break;
					}
					j++;
					proto = protos[j];
				}
				if (!found)
					continue;
			}

			if (prev_proto && g_strcmp0(parent_hfinfo->abbrev, prev_proto)) {
				json_dumper_end_object(&dumper); // 8.properties
				json_dumper_end_object(&dumper); // 7.parent_hfinfo->abbrev
				open_object = TRUE;
			}

			prev_proto = parent_hfinfo->abbrev;

			if (open_object) {
				json_dumper_set_member_name(&dumper, parent_hfinfo->abbrev);
				json_dumper_begin_object(&dumper); // 7.parent_hfinfo->abbrev
				json_dumper_set_member_name(&dumper, "properties");
				json_dumper_begin_object(&dumper); // 8.properties
				open_object = FALSE;
			}
			/* Skip the fields that would map into string. This is the default in elasticsearch. */
			type = ws_type_to_elastic(hfinfo->type);
			if (type) {
				str = g_strdup_printf("%s_%s", prev_proto, hfinfo->abbrev);
				json_dumper_set_member_name(&dumper, dot_to_underscore(str));
				g_free(str);
				json_dumper_begin_object(&dumper); // 9.hfinfo->abbrev
				json_dumper_set_member_name(&dumper, "type");
				json_dumper_value_string(&dumper, type);
				json_dumper_end_object(&dumper); // 9.hfinfo->abbrev
			}
		}
	}

	if (prev_proto) {
		json_dumper_end_object(&dumper); // 8.properties
		json_dumper_end_object(&dumper); // 7.parent_hfinfo->abbrev
	}

	json_dumper_end_object(&dumper); // 6.properties
	json_dumper_end_object(&dumper); // 5.layers
	json_dumper_end_object(&dumper); // 4.properties
	json_dumper_end_object(&dumper); // 3.doc
	json_dumper_end_object(&dumper); // 2.mappings
	json_dumper_end_object(&dumper); // 1.root
	gboolean ret = json_dumper_finish(&dumper);
	DISSECTOR_ASSERT(ret);

	g_strfreev(protos);
}