forked from osmocom/wireshark
tcp: support variable-length tcp_dissect_pdus
Originally suggested by Bill Meier for the MQTT protocol[1], but the Websocket protocol can also benefit from this. Since DESEGMENT_ONE_MORE_SEGMENT is a valid packet length, use the zero length instead as an indicator that the length is not yet known. Updated documentation too and remove the function documentation from packet-tcp.c since it is duplicated in packet-tcp.h. A noteworthy WSDG change is that the get_pdu_len parameter of tcp_dissect_pdus gained another void pointer since v1.99.2rc0-890-gceb8d95 ("Lua: Expose tcp_dissect_pdus() to Lua"). [1]: https://www.wireshark.org/lists/wireshark-dev/201405/msg00044.html Change-Id: I4eba380e00cd757635eb5639c2857356dae3171e Reviewed-on: https://code.wireshark.org/review/7279 Reviewed-by: Guy Harris <guy@alum.mit.edu> Reviewed-by: Michael Mann <mmann78@netscape.net> Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Evan Huus <eapache@gmail.com>
This commit is contained in:
parent
554c8fd7ca
commit
4ca3dbae94
|
@ -2972,16 +2972,17 @@ The arguments to tcp_dissect_pdus are:
|
|||
a routine that takes as arguments a packet_info pointer, a tvbuff
|
||||
pointer and an offset value representing the offset into the tvbuff
|
||||
at which a PDU begins, and a void pointer for user data, and should
|
||||
return - *without* throwing an exception (it is guaranteed that the
|
||||
return the total length of the PDU in bytes (or 0 if more bytes are
|
||||
needed to determine the message length).
|
||||
The routine must not throw exceptions (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;
|
||||
so don't refer to any data past that);
|
||||
|
||||
a new_dissector_t routine to dissect the pdu that's passed a tvbuff
|
||||
pointer, packet_info pointer, proto_tree pointer and a void pointer for
|
||||
user data, with the tvbuff containing a possibly-reassembled PDU. (The
|
||||
"reported_length" of the tvbuff will be the length of the PDU).
|
||||
"reported_length" of the tvbuff will be the length of the PDU);
|
||||
|
||||
a void pointer to user data that is passed to the length-determining
|
||||
routine, and the dissector routine referenced in the previous parameter.
|
||||
|
|
|
@ -594,7 +594,7 @@ effect.
|
|||
guchar *decompressed_buffer = (guchar*)g_malloc(orig_size);
|
||||
offset += 2;
|
||||
decompress_packet(tvb_get_ptr(tvb, offset, -1),
|
||||
tvb_length_remaining(tvb, offset),
|
||||
tvb_captured_length_remaining(tvb, offset),
|
||||
decompressed_buffer, orig_size);
|
||||
/* Now re-setup the tvb buffer to have the new data */
|
||||
next_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, orig_size, orig_size);
|
||||
|
@ -618,7 +618,7 @@ So armed with the size, a buffer is allocated to receive the uncompressed data
|
|||
using +g_malloc()+, and the packet is decompressed into it. The +tvb_get_ptr()+
|
||||
function is useful to get a pointer to the raw data of the packet from the
|
||||
offset onwards. In this case the decompression routine also needs to know the
|
||||
length, which is given by the +tvb_length_remaining()+ function.
|
||||
length, which is given by the +tvb_captured_length_remaining()+ function.
|
||||
|
||||
Next we build a new tvb buffer from this data, using the
|
||||
+tvb_new_child_real_data()+ call. This data is a child of our original data, so
|
||||
|
@ -700,7 +700,7 @@ if (flags & FL_FRAGMENT) { /* fragmented */
|
|||
msg_fragment_table, /* list of message fragments */
|
||||
msg_reassembled_table, /* list of reassembled messages */
|
||||
msg_num, /* fragment sequence number */
|
||||
tvb_length_remaining(tvb, offset), /* fragment length - to the end */
|
||||
tvb_captured_length_remaining(tvb, offset), /* fragment length - to the end */
|
||||
flags & FL_FRAG_LAST); /* More fragments? */
|
||||
----
|
||||
====
|
||||
|
@ -922,25 +922,28 @@ This function is implemented in 'epan/dissectors/packet-tcp.h'.
|
|||
#define FRAME_HEADER_LEN 8
|
||||
|
||||
/* This method dissects fully reassembled messages */
|
||||
static int dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
||||
static int
|
||||
dissect_foo_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
/* TODO: implement your dissecting code */
|
||||
return tvb_length(tvb);
|
||||
return tvb_captured_length(tvb);
|
||||
}
|
||||
|
||||
/* determine PDU length of protocol foo */
|
||||
static guint get_foo_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
|
||||
static guint
|
||||
get_foo_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
|
||||
{
|
||||
/* TODO: change this to your needs */
|
||||
return (guint)tvb_get_ntohl(tvb, offset+4); /* e.g. length is at offset 4 */
|
||||
}
|
||||
|
||||
/* The main dissecting routine */
|
||||
static int dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
|
||||
static int
|
||||
dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
||||
{
|
||||
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,
|
||||
get_foo_message_len, dissect_foo_message, data);
|
||||
return tvb_length(tvb);
|
||||
return tvb_captured_length(tvb);
|
||||
}
|
||||
|
||||
...
|
||||
|
@ -951,16 +954,20 @@ As you can see this is really simple. Just call +tcp_dissect_pdus()+ in your
|
|||
main dissection routine and move you message parsing code into another function.
|
||||
This function gets called whenever a message has been reassembled.
|
||||
|
||||
The parameters tvb, pinfo, treeand dataare just handed over to
|
||||
The parameters tvb, pinfo, tree and data are just handed over to
|
||||
+tcp_dissect_pdus()+. The 4th parameter is a flag to indicate if the data should
|
||||
be reassembled or not. This could be set according to a dissector preference as
|
||||
well. Parameter 5 indicates how much data has at least to be available to be
|
||||
able to determine the length of the foo message. Parameter 6 is a function
|
||||
pointer to a method that returns this length. It gets called when at least the
|
||||
number of bytes given in the previous parameter is available. Parameter 7 is a
|
||||
function pointer to your real message dissector. Parameter 8 is a the data
|
||||
function pointer to your real message dissector. Parameter 8 is the data
|
||||
passed in from parent dissector.
|
||||
|
||||
Protocols which need more data before the message length can be determined can
|
||||
return zero. Other values smaller than the fixed length will result in an
|
||||
exception.
|
||||
|
||||
[[ChDissectTap]]
|
||||
|
||||
=== How to tap protocols
|
||||
|
|
|
@ -2306,24 +2306,6 @@ again:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop for dissecting PDUs within a TCP stream; assumes that a PDU
|
||||
* consists of a fixed-length chunk of data that contains enough information
|
||||
* to determine the length of the PDU, followed by rest of the PDU.
|
||||
*
|
||||
* The first three arguments are the arguments passed to the dissector
|
||||
* that calls this routine.
|
||||
*
|
||||
* "proto_desegment" is the dissector's flag controlling whether it should
|
||||
* desegment PDUs that cross TCP segment boundaries.
|
||||
*
|
||||
* "fixed_len" is the length of the fixed-length part of the PDU.
|
||||
*
|
||||
* "get_pdu_len()" is a routine called to get the length of the PDU from
|
||||
* the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
|
||||
*
|
||||
* "dissect_pdu()" is the routine to dissect a PDU.
|
||||
*/
|
||||
void
|
||||
tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
||||
gboolean proto_desegment, guint fixed_len,
|
||||
|
@ -2379,6 +2361,16 @@ tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
|||
* Get the length of the PDU.
|
||||
*/
|
||||
plen = (*get_pdu_len)(pinfo, tvb, offset, dissector_data);
|
||||
if (plen == 0) {
|
||||
/*
|
||||
* Support protocols which have a variable length which cannot
|
||||
* always be determined within the given fixed_len.
|
||||
*/
|
||||
DISSECTOR_ASSERT(proto_desegment && pinfo->can_desegment);
|
||||
pinfo->desegment_offset = offset;
|
||||
pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
|
||||
return;
|
||||
}
|
||||
if (plen < fixed_len) {
|
||||
/*
|
||||
* Either:
|
||||
|
|
|
@ -99,7 +99,8 @@ struct tcpinfo {
|
|||
* "fixed_len" is the length of the fixed-length part of the PDU.
|
||||
*
|
||||
* "get_pdu_len()" is a routine called to get the length of the PDU from
|
||||
* the fixed-length part of the PDU; it's passed "pinfo", "tvb" and "offset".
|
||||
* the fixed-length part of the PDU; it's passed "pinfo", "tvb", "offset" and
|
||||
* "dissector_data".
|
||||
*
|
||||
* "dissect_pdu()" is the routine to dissect a PDU.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue