forked from osmocom/wireshark
From Lo�c Minier: information on how to do reassembly of PDUs atop TCP.
svn path=/trunk/; revision=8651
This commit is contained in:
parent
33d2ce9a74
commit
dca567002e
|
@ -1,4 +1,4 @@
|
||||||
$Id: README.developer,v 1.80 2003/10/09 18:57:37 guy Exp $
|
$Id: README.developer,v 1.81 2003/10/09 21:18:41 guy Exp $
|
||||||
|
|
||||||
This file is a HOWTO for Ethereal developers. It describes how to start coding
|
This file is a HOWTO for Ethereal developers. It describes how to start coding
|
||||||
a Ethereal protocol dissector and the use some of the important functions and
|
a Ethereal protocol dissector and the use some of the important functions and
|
||||||
|
@ -231,7 +231,7 @@ code inside
|
||||||
|
|
||||||
is needed only if you are using the "snprintf()" function.
|
is needed only if you are using the "snprintf()" function.
|
||||||
|
|
||||||
The "$Id: README.developer,v 1.80 2003/10/09 18:57:37 guy Exp $"
|
The "$Id: README.developer,v 1.81 2003/10/09 21:18:41 guy Exp $"
|
||||||
in the comment will be updated by CVS when the file is
|
in the comment will be updated by CVS when the file is
|
||||||
checked in; it will allow the RCS "ident" command to report which
|
checked in; it will allow the RCS "ident" command to report which
|
||||||
version of the file is currently checked out.
|
version of the file is currently checked out.
|
||||||
|
@ -241,7 +241,7 @@ version of the file is currently checked out.
|
||||||
* Routines for PROTONAME dissection
|
* Routines for PROTONAME dissection
|
||||||
* Copyright 2000, YOUR_NAME <YOUR_EMAIL_ADDRESS>
|
* Copyright 2000, YOUR_NAME <YOUR_EMAIL_ADDRESS>
|
||||||
*
|
*
|
||||||
* $Id: README.developer,v 1.80 2003/10/09 18:57:37 guy Exp $
|
* $Id: README.developer,v 1.81 2003/10/09 21:18:41 guy Exp $
|
||||||
*
|
*
|
||||||
* Ethereal - Network traffic analyzer
|
* Ethereal - Network traffic analyzer
|
||||||
* By Gerald Combs <gerald@ethereal.com>
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
@ -2152,6 +2152,95 @@ This will create preferences "beep.tcp.port" and
|
||||||
"beep.strict_header_terminator", the first of which is an unsigned
|
"beep.strict_header_terminator", the first of which is an unsigned
|
||||||
integer and the second of which is a Boolean.
|
integer and the second of which is a Boolean.
|
||||||
|
|
||||||
|
2.7 Reassembly/desegmentation for protocols running atop TCP
|
||||||
|
|
||||||
|
There are two main ways of reassembling PDUs spanning across multiple
|
||||||
|
TCP segmentss. The first one is simpler, but assumes you are running
|
||||||
|
atop of TCP when this occurs (but your dissector might run atop of UDP,
|
||||||
|
too, for example), and that your PDUs consist of a fixed amount of data
|
||||||
|
that includes enough information to determine the PDU length, possibly
|
||||||
|
followed by additional data. The second one is more generic but
|
||||||
|
requires more code and is less efficient.
|
||||||
|
|
||||||
|
For the first method, you register two different dissection methods, on
|
||||||
|
for the TCP case, and one for the other cases. It is a good idea to
|
||||||
|
have a dissect_PROTO_common function which will parse the generic
|
||||||
|
content that you can find in all PDUs which is called from
|
||||||
|
dissect_PROTO_tcp when the reassembly is complete and from
|
||||||
|
dissect_PROTO_udp (or dissect_PROTO_other).
|
||||||
|
|
||||||
|
To register the distinct dissector functions, consider the following
|
||||||
|
example, stolen from packet-dns.c:
|
||||||
|
|
||||||
|
dissector_handle_t dns_udp_handle;
|
||||||
|
dissector_handle_t dns_tcp_handle;
|
||||||
|
dissector_handle_t mdns_udp_handle;
|
||||||
|
|
||||||
|
dns_udp_handle = create_dissector_handle(dissect_dns_udp,
|
||||||
|
proto_dns);
|
||||||
|
dns_tcp_handle = create_dissector_handle(dissect_dns_tcp,
|
||||||
|
proto_dns);
|
||||||
|
mdns_udp_handle = create_dissector_handle(dissect_mdns_udp,
|
||||||
|
proto_dns);
|
||||||
|
|
||||||
|
dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
|
||||||
|
dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
|
||||||
|
dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
|
||||||
|
dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
|
||||||
|
|
||||||
|
The dissect_dns_udp function does very little work and calls
|
||||||
|
dissect_dns_common, while dissect_dns_tcp calls tcp_dissect_pdus with a
|
||||||
|
reference to a callback which will be called with reassembled data:
|
||||||
|
|
||||||
|
static void
|
||||||
|
dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||||
|
{
|
||||||
|
tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2,
|
||||||
|
get_dns_pdu_len, dissect_dns_tcp_pdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
(The dissect_dns_tcp_pdu function acts similarly to dissect_dns_udp.)
|
||||||
|
The arguments to tcp_dissect_pdus are:
|
||||||
|
|
||||||
|
the tvbuff pointer, packet_info pointer, and proto_tree pointer
|
||||||
|
passed to the dissector;
|
||||||
|
|
||||||
|
a gboolean flag indicating whether desegmentation is enabled for
|
||||||
|
your protocol;
|
||||||
|
|
||||||
|
the number of bytes of PDU data required to determine the length
|
||||||
|
of the PDU;
|
||||||
|
|
||||||
|
a routine that takes as arguments a tvbuff pointer and an offset
|
||||||
|
value representing the offset into the tvbuff at which a PDU
|
||||||
|
begins and should return - *without* throwing an exception (it
|
||||||
|
is guaranteed that the number of bytes specified by the previous
|
||||||
|
argument to tcp_dissect_pdus is available, but more data might
|
||||||
|
not be available, so don't refer to any data past that) - the
|
||||||
|
total length of the PDU, in bytes;
|
||||||
|
|
||||||
|
a routine that's passed a tvbuff pointer, packet_info pointer,
|
||||||
|
and proto_tree pointer, with the tvbuff containing a
|
||||||
|
possibly-reassembled PDU, and that should dissect that PDU.
|
||||||
|
|
||||||
|
The second method is to return a modified pinfo structure when
|
||||||
|
dissect_PROTO is called. In this case, you have to check if you have
|
||||||
|
collected enough bytes: if you have enough, you parse the PDU, and if
|
||||||
|
don't have enough bytes, you return from the dissector supplying
|
||||||
|
information to the caller on how many bytes you need to proceed. This
|
||||||
|
is done by indicating the offset where you would like to start again and
|
||||||
|
the number of bytes that you need in pinfo->desegment_*:
|
||||||
|
|
||||||
|
if (i_miss_five_bytes) {
|
||||||
|
pinfo->desegment_offset = offset;
|
||||||
|
pinfo->desegment_len = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
You can repeat this procedure until you've got enough bytes; for
|
||||||
|
example, you can request one byte more until you've got the byte you're
|
||||||
|
searching for if the data to be dissected consists of a sequence of
|
||||||
|
bytes ending with a particular byte value.
|
||||||
|
|
||||||
3. Plugins
|
3. Plugins
|
||||||
|
|
||||||
See the README.plugins for more information on how to "pluginize"
|
See the README.plugins for more information on how to "pluginize"
|
||||||
|
|
Loading…
Reference in New Issue