Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Wireshark-dev: [Wireshark-dev] Problemems with proto_tree_new_item after update

From: "Sebastian Breilmann" <mail@xxxxxxxxxxxxx>
Date: Wed, 19 Dec 2007 13:14:28 +0100
Hallo!

After an update from 0.99.6 to 0.99.7 I have problems with a custom dissector
I wrote. On 0.99.6 everything was fine, but now I get the mssage "[Dissector
bug, protocol RTSU: proto.c:1064: failed assertion "length == 6"]". I have no
idea to solve this :( Below is my disscetor-Source. Thank you for your help!

/***Source*******************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/dissectors/packet-tcp.h>
#include <string.h>
#include "units.h"

#define PROTO_TAG_RTSU	"RTSU"
#define FRAME_HEADER_LEN 4  // Minumum amount of bytes in PDU to determine
RTSU Packet length

static void dissect_rtsu_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree
*tree);
static void dissect_rtsu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static guint get_rtsu_message_len(packet_info *pinfo, tvbuff_t *tvb, int
offset);
static guint get_rtsu_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset);


static int proto_rtsu = -1;

static dissector_handle_t data_handle=NULL;

static dissector_handle_t rtsu_handle;

void dissect_rtsu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);

static int global_rtsu_port = 5555;

static gint hf_rtsu = -1;
static gint hf_rtsu_units = -1;
static gint hf_rtsu_length = -1;
static gint hf_rtsu_ulength = -1;
static gint hf_rtsu_group = -1;
static gint hf_rtsu_unit = -1;
static gint hf_rtsu_data = -1;

static gint ett_rtsu = -1;
static gint ett_rtsu_units = -1;
static gint ett_rtsu_length = -1;
static gint ett_rtsu_ulength = -1;
static gint ett_rtsu_group = -1;
static gint ett_rtsu_unit = -1;
static gint ett_rtsu_data = -1;

void proto_reg_handoff_rtsu(void)
{
	static gboolean initialized=FALSE;

	if (!initialized) {
		data_handle = find_dissector("data");
		rtsu_handle = create_dissector_handle(dissect_rtsu, proto_rtsu);
		dissector_add("tcp.port", global_rtsu_port, rtsu_handle); 
	}

}

void proto_register_rtsu (void)
{
	
	/*Register Items: (according to Packet Def. and Unit Def.)
		&hf_rtsu: Whole PDU
		&hf_rtsu_units: Tree Item 'Units'
		&hf_rtsu_length: Packet LEN
		&hf_rtsu_ulength: Unit LEN
		&hf_rtsu_group: First byte of ID
		&hf_rtsu_unit: Second byte if ID
		&hf_rtsu_data: Data in Unit
	*/

	static hf_register_info hf[] = {
		{ &hf_rtsu,
		{ "Data", "rtsu.data", FT_NONE, BASE_NONE, NULL, 0x0,
		"RTSU PDU", HFILL }},
		{ &hf_rtsu_units,
		{ "Units", "rtsu.units", FT_NONE, BASE_NONE, NULL, 0x0,
		 "RTSU Units", HFILL }},
		{ &hf_rtsu_length,
		{ "Packet Length", "rtsu.len", FT_UINT32, BASE_DEC, NULL, 0x0,
		"Packet Length", HFILL }},
		{ &hf_rtsu_ulength,
		{ "Unit Length", "rtsu.ulen", FT_UINT32, BASE_DEC, NULL, 0x0,
		"Unit Length", HFILL }},
		{ &hf_rtsu_group,
		{ "Group", "rtsu.group", FT_UINT8, BASE_DEC, VALS(packetgroupnames), 0x0,
		 "Group", HFILL }},
		{ &hf_rtsu_unit,
		{ "Unit", "rtsu.unit", FT_UINT8, BASE_DEC, VALS(group20unitnames), 0x0,
		 "Unit", HFILL }},
		{ &hf_rtsu_data,
		{ "Data", "rtsu.data", FT_BYTES, BASE_NONE, NULL, 0x0,
		 "Data", HFILL }}
		
	};
	static gint *ett[] = {
		&ett_rtsu,
		&ett_rtsu_units,
		&ett_rtsu_length,
		&ett_rtsu_ulength,
		&ett_rtsu_group,
		&ett_rtsu_unit,
		&ett_rtsu_data
		
	};
	proto_rtsu = proto_register_protocol ("RTSU Protocol", "RTSU", "rtsu");
	proto_register_field_array (proto_rtsu, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
	register_dissector("rtsu", dissect_rtsu, proto_rtsu);
	//}
}


//Determine the Unit Length
static guint 
get_rtsu_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
{
	guint8 l1,l2=0;
	guint length=0;
	tvb_memcpy(tvb, &l1 , offset+1, 1);
	tvb_memcpy(tvb, &l2 , offset, 1);
	length=256*l2+l1;

    return length;
}


//Determine the Packet Length
static guint 
get_rtsu_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
{
	guint8 l1,l2=0;
	guint length=0;
	tvb_memcpy(tvb, &l1 , offset+3, 1);
	tvb_memcpy(tvb, &l2 , offset+2, 1);
	length=256*l2+l1+6;

    return length;
}



//Dissector Call 
static void 
dissect_rtsu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    //Reassembling 
	tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
	get_rtsu_pdu_len, dissect_rtsu_message);
}


//Main Dissector Function
static void 
dissect_rtsu_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

	proto_item *rtsu_item = NULL;
	proto_item *rtsu_sub_item = NULL;
	proto_tree *rtsu_tree = NULL;
	proto_tree *rtsu_units_tree = NULL;
	guint16 firstbyte,secondbyte = 0;
	guint16 group = 0;
	guint16 unit = 0;

	if (check_col(pinfo->cinfo, COL_PROTOCOL))
		col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_RTSU);
	
	if(check_col(pinfo->cinfo,COL_INFO)){
		col_clear(pinfo->cinfo,COL_INFO);
	}


	firstbyte = tvb_get_guint8( tvb, 0 );
	secondbyte = tvb_get_guint8( tvb, 1 );
	group = tvb_get_guint8( tvb, 6 ); // Get the (first) group byte to present it
in the Info Col
	if (check_col(pinfo->cinfo, COL_INFO)) {
		
		//First and Second Byte should be 0xFA, otherwise it seems not to be a RTSU
Unit
		if ((firstbyte==secondbyte) && (firstbyte == 250)) {
			col_add_fstr(pinfo->cinfo, COL_INFO, "%s", 
			val_to_str(group, packetgroupnames, "Unknown Group:0x%02x"));
		}
		else col_add_fstr(pinfo->cinfo, COL_INFO,"no RTSU Unit");
	}
	
	//More Information

	if (tree) { 
		guint32 offset = 0; //current postition in PDU
		guint32 length=0,ulength = 0;
	
		
		//The First tree entry is the wohle packet length
		rtsu_item = proto_tree_add_item(tree, proto_rtsu, tvb, 0, -1, FALSE);
		rtsu_tree = proto_item_add_subtree(rtsu_item, ett_rtsu);

		
		offset+=2;
		length = get_rtsu_len(pinfo,  tvb,  offset);
		proto_tree_add_uint(rtsu_tree, hf_rtsu_length, tvb, offset, 2, length);
		offset+=2;
		
		//The next entry is the sub item 'Units'
		rtsu_units_tree = proto_item_add_subtree(rtsu_item, ett_rtsu);
		rtsu_sub_item = proto_tree_add_item( rtsu_tree, hf_rtsu_units, tvb, offset,
length, FALSE );
		rtsu_units_tree = proto_item_add_subtree(rtsu_sub_item, ett_rtsu);
		
		
		//While there are units left in packet 
		while (offset<length+4)		{
			group = tvb_get_guint8( tvb, 6 + offset -4); // Get the group byte
			unit = tvb_get_guint8( tvb, 7 + offset -4); // Get the unit byte
			unit=group*100+unit;// Encode to Unit ID
			ulength = get_rtsu_len(pinfo,  tvb,  offset); //Get the length of the unit
			proto_tree_add_uint(rtsu_units_tree, hf_rtsu_ulength, tvb, offset, 2,
ulength); //present unit length

			offset+=2;
			proto_tree_add_item(rtsu_units_tree, hf_rtsu_group, tvb, offset, 1, FALSE);
//present unit group
			offset++;
			proto_tree_add_uint(rtsu_units_tree, hf_rtsu_unit, tvb, offset, 1, unit);
//present unit name
			offset++;
			proto_tree_add_item( rtsu_units_tree, hf_rtsu_data, tvb, offset, ulength,
FALSE );//present unit data
			offset+=ulength;
		}
		
	}

}	//End of RTSU dissector function