From Richard van der Hoff:

I've had a good look at the code in packet-tcp.c, and whilst it's
somewhat impenetrable, I've come to the conclusion that it just doesn't
support multiple pdus as described.

That's not entirely unreasonable in itself; my objection is solely to
the fact that README.developer is completely misleading. In fact, even
the example dissect_cstr won't work on the tcp dissector, because if you
set desegment_len=1 the tcp dissector believes that you know what you
are doing and doesn't let you change your mind later.

Furthermore, 2.7.2 says that you can set desegment_len=-1; that doesn't
work either, because the tcp dissector expects
DESEGMENT_ONE_MORE_SEGMENT, which is 0x0fffffff, which is nowhere near -1.

In short, I think the relevant section of README.developer needs a
rewrite. I attach a patch - comments welcome.

svn path=/trunk/; revision=20974
This commit is contained in:
Jaap Keuter 2007-03-05 20:25:54 +00:00
parent 1cbc97b03d
commit 88a508d407
1 changed files with 51 additions and 49 deletions

View File

@ -3297,37 +3297,33 @@ The arguments to tcp_dissect_pdus are:
The second reassembly mode is preferred when the dissector cannot determine
how many bytes it will need to read in order to determine the size of a PDU.
It may also be useful if your dissector needs to support reassembly from
protocols other than TCP.
This reassembly mode relies on Wireshark's mechanism for processing
multiple PDUs per frame. When a dissector processes a PDU from a tvbuff
the PDU may not be aligned to a frame of the underlying protocol.
Wireshark allows dissectors to process PDUs in an idempotent
way--dissectors only need to consider one PDU at a time. If your
dissector discovers that it can not process a complete PDU from the
current tvbuff the dissector should halt processing and request
additional bytes from the lower level dissector.
Your dissect_PROTO will initially be passed a tvbuff containing the payload of
the first packet. It should dissect as much data as it can, noting that it may
contain more than one complete PDU. If the end of the provided tvbuff coincides
with the end of a PDU then all is well and your dissector can just return as
normal. (If it is a new-style dissector, it should return the number of bytes
successfully processed.)
Your dissect_PROTO will be called by the lower level dissector whenever
sufficient new bytes become available. Each time your dissector is called it is
provided a different tvbuff, though the tvbuffs may contain data that your
dissector declined to process during a previous call. When called a dissector
should examine the tvbuff provided and determine if an entire PDU is available.
If sufficient bytes are available the dissector processes the PDU and returns
the length of the PDU from your dissect_PROTO.
If the dissector discovers that the end of the tvbuff does /not/ coincide with
the end of a PDU, (ie, there is half of a PDU at the end of the tvbuff), it can
indicate this to the parent dissector, by updating the pinfo struct. The
desegment_offset field is the offset in the tvbuff at which the dissector will
continue processing when next called. The desegment_len field should contain
the estimated number of additional bytes required for completing the PDU. Next
time your dissect_PROTO is called, it will be passed a tvbuff composed of the
end of the data from the previous tvbuff together with desegment_len more bytes.
Completion of a PDU is signified by dissect_PROTO returning a positive
value. The value is the number of bytes which were processed from the
tvbuff. If there were insufficient bytes in the tvbuff to complete a
PDU then dissect_PROTO must update the pinfo structure to indicate that
more bytes are required. The desegment_offset field is the offset in
the tvbuff at which the dissector will continue processing when next
called. The desegment_len field should contain the estimated number of
additional bytes required for completing the PDU. The dissect_PROTO
will not be called again until the specified number of bytes are
available. pinfo->desegment_len may be set to -1 if dissect_PROTO
cannot determine how many additional bytes are required. Dissectors
should set the desegment_len to a reasonable value when possible rather
than always setting -1 as it will generally be more efficient.
If the dissector cannot tell how many more bytes it will need, it should set
desegment_len=DESEGMENT_ONE_MORE_SEGMENT; it will then be called again as soon
as any more data becomes available. Dissectors should set the desegment_len to a
reasonable value when possible rather than always setting
DESEGMENT_ONE_MORE_SEGMENT as it will generally be more efficient. Also, you
*must not* set desegment_len=1 in this case, in the hope that you can change
your mind later: once you return a positive value from desegment_len, your PDU
boundary is set in stone.
static hf_register_info hf[] = {
{&hf_cstring,
@ -3337,7 +3333,7 @@ static hf_register_info hf[] = {
};
/**
* Dissect a buffer containing a C string.
* Dissect a buffer containing C strings.
*
* @param tvb The buffer to dissect.
* @param pinfo Packet Info.
@ -3346,32 +3342,38 @@ static hf_register_info hf[] = {
static void dissect_cstr(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
guint offset = 0;
gint available = tvb_reported_length_remaining(tvb, offset);
gint len = tvb_strnlen(tvb, offset, available);
while(offset < tvb_reported_length(tvb)) {
gint available = tvb_reported_length_remaining(tvb, offset);
gint len = tvb_strnlen(tvb, offset, available);
if( -1 == len ) {
/* No '\0' found, ask for another byte. */
pinfo->desegment_offset = offset;
pinfo->desegment_len = 1;
return;
}
if( -1 == len ) {
/* we ran out of data: ask for more */
pinfo->desegment_offset = offset;
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
return;
}
if (check_col(pinfo->cinfo, COL_INFO)) {
col_set_str(pinfo->cinfo, COL_INFO, "C String");
}
len += 1; /* Add one for the '\0' */
if (check_col(pinfo->cinfo, COL_INFO)) {
col_set_str(pinfo->cinfo, COL_INFO, "C String");
if (tree) {
proto_tree_add_item(tree, hf_cstring, tvb, offset, len, FALSE);
}
offset += (guint)len;
}
len += 1; /* Add one for the '\0' */
if (tree) {
proto_tree_add_item(tree, hf_cstring, tvb, offset, len, FALSE);
}
/* if we get here, then the end of the tvb coincided with the end of a
string. Happy days. */
}
This simple dissector will repeatedly return -1 requesting one more byte until
the tvbuff contains a complete C string. The C string will then be added to the
protocol tree. Unfortunately since there is no way to guess the size of C
String without seeing the entire string this dissector can never request more
than one additional byte.
This simple dissector will repeatedly return DESEGMENT_ONE_MORE_SEGMENT
requesting more data until the tvbuff contains a complete C string. The C string
will then be added to the protocol tree. Note that there may be more
than one complete C string in the tvbuff, so the dissection is done in a
loop.
2.8 ptvcursors.