Ethereal-dev: Re: [Ethereal-dev] Can I prevent a called dissector from changing the summary wi

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxx>
Date: Wed, 11 Jun 2003 11:18:55 -0700
On Wed, Jun 11, 2003 at 10:38:43AM -0700, Jeff Rizzo wrote:
> I'm writing a dissector for sFlow (RFC 3176), which can sometimes
> capture packet headers from other protocols.  Since I want these
> headers dissected as well, I pass them on to other dissectors
> (such as the Ethernet dissector), and that seems to work OK.
> 
> However, I just noticed that when I add a filter to search on sflow
> agent address, it re-draws the traffic summary screen with
> the dissected summary info for the last sample in the packet,

This suggests that you're only calling the other dissector if the "tree"
argument is non-null.  When the file is read in, each frame is
dissected, in order to

	1) build up any state needed by the dissectors later;

	2) set the column text.

Unless a color filter or read filter is in effect, the protocol tree
doesn't need to be constructed, in which case the "tree" argument is
null.  If you're not calling the other dissector in that case, that
dissector won't get to change the column text.

However, when you filter the display, the protocol tree has to be
constructed (a display filter checks values in the protocol tree), so
the "tree" argument is non-null; if, in that case, you call the other
dissectors, they *do* get a chance to change the column text.

Subdissectors must be called regardless of whether the "tree" argument
is null or not; otherwise, they might not get called in the first pass
through the file, and might not get a chance to correctly set the
columns or construct necessary state.  In this particular case, that
might not matter, but that principle should still be followed.

> which is *not* what I want.  Is there any way to prevent this?

Before you call the other dissector, mark the columns as "read-only"
by calling

	col_set_writable(pinfo->cinfo, FALSE);

and save the addresses in the "pinfo" structure as well.  When the
dissector returns, restore the addresses and set the writability of the
columns appropriately:

	gboolean save_writable;
	volatile address save_dl_src;
        volatile address save_dl_dst;
        volatile address save_net_src;
        volatile address save_net_dst;
        volatile address save_src;
        volatile address save_dst;

		...

	save_writable = col_get_writable(pinfo->cinfo);
	col_set_writable(pinfo->cinfo, FALSE);
 	save_dl_src = pinfo->dl_src;
	save_dl_dst = pinfo->dl_dst;
	save_net_src = pinfo->net_src;
	save_net_dst = pinfo->net_dst;
	save_src = pinfo->src;
	save_dst = pinfo->dst;

	/* Dissect the contained packet. */
	TRY {
		call_dissector(handle, next_tvb, pinfo, tree);
	}
	CATCH2(BoundsError, ReportedBoundsError) {
		/*
		 * Ignore these, as we don't necessarily have the entire
		 * packet, just its headers, and we don't want them
		 * reported as "Short Frame"s or "Malformed Packet"s.
		 */
		;
	}
	ENDTRY;

	col_set_writable(pinfo->cinfo, save_writable);
	pinfo->dl_src = save_dl_src;
	pinfo->dl_dst = save_dl_dst;
	pinfo->net_src = save_net_src;
	pinfo->net_dst = save_net_dst;
	pinfo->src = save_src;
	pinfo->dst = save_dst;

The exception catching is done so that if you get an exception thrown
(which you probably will, as, presumably, the entire sampled packet
isn't in the sFlow packet), we don't report it as a "Short Frame" or
"Malformed Packet", and we don't leave the addresses, etc. set by the
subdissector.

> Also, when I'm ready to submit the dissector (when I solve this
> problem, or possibly before :), should I attach the patch file, or send
> a pointer to where it can be retrieved?

Attaching the patch file is easiest.