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

Wireshark-dev: Re: [Wireshark-dev] Sub_dissectors assertion failed

From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Mon, 24 May 2010 14:54:09 -0700
On May 24, 2010, at 12:18 PM, Scott wrote:

> On Mon, May 24, 2010 at 11:57 AM, Guy Harris <guy@xxxxxxxxxxxx> wrote:
>> So that means that either the IP protocol rider protocol, or the custom protocol, needs to have a field giving the protocol number of the protocol that runs top the custom protocol.  Which of of them has that field?
>> 
> 
> The IP Rider contains that field.

OK, so that's a little more complicated.  There are (at least) three ways of handling that:

	1) dissect the IP rider and the custom protocol as separate protocols, and use the standard mechanisms for handing off from the IP rider dissector to the custom protocol dissector;

	2) dissect the IP rider and the custom protocol as separate protocols, and use a specialized mechanism for handing off from the IP rider dissector to the custom protocol dissector;

	3) dissect them as a single protocol.

For 1), you would have to pass the IP protocol number from the IP rider protocol to the custom protocol.  What you would do there is:

In the IP rider dissector:

	in its register-handoff routine, register it in the "ip.proto" dissector table with its IP protocol number, and fetch a handle for the custom protocol dissector with find_dissector(), using the name the custom dissector uses to register itself;

	in its dissection routine, fetch the IP protocol number field's value into a local variable, and, when you want to call the custom protocol's dissector, set "pinfo->private_data" to point to the local variable and call the custom protocol dissector, using its handle, with call_dissector().

In the custom protocol dissector:

	in its register routine, register the dissector handle with register_dissector(), using the same name that the IP rider dissector uses to find it;

	in its register-handoff routine, fetch the "ip.proto" dissector table with find_dissector_table();

	in its dissection routine, when it is to call the dissector for its payload, use dissector_try_port(), using the IP protocol number pointed to by pinfo->private_data.

2) could be done similar to 1), except that you could just directly call the custom protocol dissector and have it take an additional argument, the IP protocol number, as an argument, or you could just dissect both protocol layers in the same routine.  That would, however, mean that some of the work done for you by call_dissector(), such as saving and restoring some state (which might not matter if your dissector doesn't change it), setting the current protocol name that shows up in some messages, and updating the list-of-protocols field, won't be done.  I wouldn't recommend doing it that way.

How 3) would be done should be obvious, but there might be reasons not to do that.

>>> I overcame the problem of the protocols not matching by seeing that the protocol number copied over from IP to my IP rider and *supposedly* stored in hf_[IPR protocol] field was incorrect.  It was 65,000 something when printf'd.  What does hf_register_info do with that variable (hf_[IPR protocol])?
>> 
>> What do you mean by "hf_[IPR protocol]"?
> 
> Sorry, I wasn't especially clear.  I meant one of the variables declared as:
> static int hf_IPR_protocol = -1;
> that is used in the hf_register_info struct.  I didn't know what those were for (I thought they stored the actual value extracted from the packet), but you answered my question with:
>  
>> the hf_ values set by proto_register_field_array(), are used as indices into a big table of structures giving information about protocols and fields.  Those indices are passed to various routines that add items to protocol trees, as well as some other routines.

Yes - not all fields *have* integral values, so the hf_ variable couldn't be used for that purpose.

> If this is still the wrong format (calling dissector_try_port twice or otherwise), please let me know!

Yes, it is - see above for the right way to handle those two protocols.

> Otherwise, here comes another question.  I solved the problem exhibited in:
> http://img80.imageshack.us/img80/5582/malformed.gif

You mean the problem that Wireshark thinks that 0x1bc4 is not equal to 0x1bc4? :-)

> by hardcoding a value into the reported_length parameter of tvb_new_subset() instead of using -1.  This is obviously not a long term solution, so what I need to get at is the IP header's value for "Total Length" (ip.len).

That's odd - the reported_length value for the tvbuff handed to the IPR dissector should be the total length value from the IP header unless this is an IP fragment, so changing the value of the length shouldn't matter.

Is the packet in question the first fragment of an IP datagram?