Sub-dissector not getting invoked


#1

The protocol I’m trying to dissect has an arbitrary and extensible number of payload types; I’m trying to build a dissector which will be extensible by further plugins or by recompiling the same plugin, as new payload types are added.

The packet has a header which is currently 20 bytes long, but which in future may be up to 256 bytes long; the header length is encoded in one of the bytes of the header. In practice the content of the payload is currently always little endian, but there is a byte in the header which indicates whether it is little endian of big endian (the header, thank $DEITY, is always big-endian and always will be).

The payload type is determined by the first eight bytes of the payload, which is to say the first eight bytes after the end of the header. The payload type is intended to be a human-readable string, but will not normally be null terminated.

So far I have a dissector which dissects the header just fine, and is looking very pretty. I’m trying to make it hand off to sub-dissectors, and I’m trying to learn how to do this by studying packet_tcp.c. My first sub-dissector registers, so I’ve got that far.

In my packet_ccsdu3.c file I’ve declared:

/* add the ability to hand off to sub-dissectors */
static dissector_table_t subdissector_table;
static heur_dissector_list_t heur_subdissector_list;
static dissector_handle_t data_handle;

and then at the end of the function proto_register_ccsdu3(void) I’m calling

/* Register subdissector table to allow subdissectors to attach - the use of 
 * FT_STRING for type is experimental and may be wrong! */
	subdissector_table = register_dissector_table("ccsdu-v3.PayloadSignature",
	    "Payload Signature", FT_STRING, BASE_DEC);
	register_heur_dissector_list("ccsdu3", &heur_subdissector_list);

At the end of the function dissect_ccsdu3() I’m calling

	if ( payload_length > 0) {
		result += dissect_payload( tvb, payload_offset, payload_length, pinfo, tree);
	}

which invokes

/**
 * Despatch to subdissectors (hopefully)
 *
 * @param tvb the buffer in which the packet was passed
 * @param offset the offset of the payload within that packet
 * @param length the advertised length of the payload
 * @param pinfo information about the packet
 * @param tree the user interface tree which we may populate
 *
 * @return the number of bytes dissected
 */
static int dissect_payload( tv_buff_t * tvb, int offset, int length, packet_info *pinfo, proto_tree *tree) {
	int result = 0;

	debug_print( "Attempting to despatch to sub-dissectors");
	if ( dissector_try_heuristic( heur_subdissector_list, 
		tvb_new_subset(tvb, offset, -1, -1), pinfo, tree)){
			result = length;
	}

	return result;
}

The subdissector attempts to register itself with :

/* Register the protocol name and description */
	proto_ccsdu3_dssstrng = proto_register_protocol("DSS string data",
	    "CCSDU-v3-DSSSTRNG", "ccsdu-v3-dssstrng");

and to register its handoff with:

void proto_reg_handoff_ccsdu3_dssstrng(void)
{
	static dissector_handle_t ccsdu3_dssstrng_handle;

		/*  Use new_create_dissector_handle() to indicate that dissect_ccsdu3_dssstrng()
		 *  returns the number of bytes it dissected (or 0 if it thinks the packet
		 *  is not a DSSSTRNG).
		 */
	ccsdu3_dssstrng_handle = new_create_dissector_handle(dissect_ccsdu3_dssstrng,
		proto_ccsdu3_dssstrng);

	dissector_add_string( "ccsdu-v3.PayloadSignature", DSSSTRNG_SIGNATURE, ccsdu3_dssstrng_handle);
}

What I’m getting in my debug log is:

In other words, the sub-dissector is there but is not getting invoked. What do I need to do to say
[list]

  • this dissector is a sub-dissector of that dissector
  • you discriminate these subsdissectors on the first eight bytes of the payload?
    [/list:u]

#2

And the solution…

I needed to look up my sub-dissector by string, not heuristics. The working version of dissect_payload is as follows:

/**
 * Despatch to subdissectors (hopefully)
 *
 * @param tvb the buffer in which the packet was passed
 * @param offset the offset of the payload within that packet
 * @param length the advertised length of the payload
 * @param pinfo information about the packet
 * @param tree the user interface tree which we may populate
 *
 * @return the number of bytes dissected
 */
static int dissect_payload( tvbuff_t *tvb, int offset, int length, packet_info *pinfo, proto_tree *tree) {
	int result = 0;

	char * payload_signature = 
		tvb_format_text(tvb, offset + CCSDU3_PLD_OFFSET_SIGNATURE, CCSDU3_PLD_SIG_SIZE);

#if DEBUG
	sprintf( debug_message_buffer, "Attempting to despatch to sub-dissector '%s'", payload_signature);
	debug_print( debug_message_buffer);
#endif

	if ( dissector_try_string( subdissector_table, payload_signature, 
		tvb_new_subset(tvb, offset, -1, -1), pinfo, tree)) {
		debug_print( "Lookup handoff successful");
		result = length;
	} else if ( dissector_try_heuristic( heur_subdissector_list, 
		tvb_new_subset(tvb, offset, -1, -1), pinfo, tree)){
		debug_print( "Heuristic handoff successful");
		result = length;
	} 

	return result;
}

Whether I can also make it work by heuristics is another problem for, as they say, another day.