Wireshark mailing list archives

Re: Sub_dissectors assertion failed


From: Guy Harris <guy () alum mit edu>
Date: Fri, 21 May 2010 14:18:44 -0700


On May 21, 2010, at 12:49 PM, Scott wrote:

I killed the original error of
ERROR:packet.c:709:dissector_add: assertion failed: (sub_dissectors)
by calling register_dissector_table() in proto_register_..().  Apparently I didn't know I needed to do that, but it 
makes sense.

Yes.  As indicated:

        1) you can't register in a dissector table until the dissector table is registered;

        2) the *only* ordering guarantee we offer is that all register routines are run before any register-handoff 
routines are run;

so, to make sure that all the dissector tables are registered before any registrations are attempted in dissector 
tables, you must register dissector tables in your register routine and register dissectors *in* dissector tables in 
the register-handoff routines (dissector tables are used by dissectors to hand off the remaining packet data to the 
next protocol, hence the "handoff" in "register-handoff").

I mean *any protocol that runs atop IP* can follow it.

Then you want to do what I suggested to find the right dissector for the following protocol - just get the "ip.proto" 
dissector table and use that.

I am going to work on all protocols registered with IP to follow it as soon as I get *another* custom 
dissector/protocol that I am working on, which can follow it, to work.  Let's call the custom protocol *custom* and 
the IP rider *it* to simplify things.

I have the custom protocol doing dissector_add("[field switch on *it*]", [macro expansion that matches a field 
value], *custom*_handle) in its handoff routine.  However, for some reason it is apparently not being called upon to 
dissect because it is not showing up as a header in the packet window.

So what protocols does your custom protocol run on top of?  It needs to register with the appropriate dissector table 
or tables for those protocols, using the appropriate value (Ethernet type, IP protocol type, etc.).

As a "by the way," you mentioned in your reply:
If you mean, for example, "any protocol that runs atop IP", then you should grab hold of the "ip.proto" dissector 
table:

       dissector_table_t ip_proto_dissector_table;
               ...
       ip_proto_dissector_table = find_dissector_table("ip.proto");

and then use that to hand off the payload to the next dissector with that dissector table, the protocol number, and 
dissector_try_port().
How do I "hand off the payload to the next dissector with that dissector table, the protocol number, and 
dissector_try_port()?"  Is that through a function call?

Yes.

The name of the function you call is "dissector_try_port".

And what does dissector_try_port() do?  All I could tell is that it returns a gboolean.

It takes, as arguments:

        1) a handle for a dissector table that uses integral values as keys (it should really be dissector_try_uint(); 
the "port" is historical);

        2) an integral value to use to select a dissector from that dissector table;

        3) a tvbuff_t * that refers to a tvbuff with the data to be dissected by the selected dissector;

        4) a packet_info *, which should be the one the dissector calling dissector_try_port() was handed;

        5) a proto_tree *, which should be the one the dissector calling dissector_try_port() was handed.

If it finds a dissector in the dissector table that was registered with the integral value in question, it calls it, 
handing it the tvbuff_t *, the packet_info *, and the proto_tree *, and returns TRUE.  If not, it returns FALSE; you 
then need to decide how to dissect the data (for example, just show it as raw data).

For example, the Ethernet dissector calls dissector_try_port(), handing it the Ethernet-type dissector table, and the 
Ethernet type value from the packet.

More questions I haven't been able to find answers to:
*The proto_handoff_..(void) routine's main job is to register the dissector with other dissectors so it gets called 
at the right moment, correct?

Yes.

*What is the difference between create_dissector_handle() and new_create_dissector_handle()?

There are two types of dissectors:

        1) dissectors for protocol fields such as Ethernet types where the value used when you select a dissector 
(integral value for dissector_try_port()) is uniquely assigned to a protocol, so that you can pretty much guarantee 
that the selected dissector is the right one;

        2) dissectors for protocol fields such as UDP or TCP ports where the value is assigned to the protocol but 
could be used by other protocols, so you *can't* guarantee that the selected dissector is the right one.

In addition, in some cases the calling dissector needs to know how much data from the tvbuff was considered part of the 
data for the called dissector's protocol, i.e. where it doesn't always get the rest of the packet.

"New-style" dissectors are for case 2) and for the other case mentioned.  For case 2), they do some heuristic checks to 
see if the packet looks appropriate for their protocol and, if not, they return 0 without having done any dissection, 
otherwise they return the amount of data dissected.  For the other case, they return the amount of data dissected.

(This has a problem if there's no packet data left to dissect, i.e. the tvbuff handed to them is zero-length; you can't 
distinguish between "this isn't one of my packets" and "this is one of my packets, and I dissected all 0 bytes of it".  
Yes, there are cases where this is a problem.)
___________________________________________________________________________
Sent via:    Wireshark-dev mailing list <wireshark-dev () wireshark org>
Archives:    http://www.wireshark.org/lists/wireshark-dev
Unsubscribe: https://wireshark.org/mailman/options/wireshark-dev
             mailto:wireshark-dev-request () wireshark org?subject=unsubscribe


Current thread: