Extend reassembly documentation
Documentation changes only (comments and docbook). Update WSDG with the fragment_add_seq_check API that was introduced in Wireshark 1.10. Fix typos and clarify the many functions we have for adding reassembling fragments. Change-Id: I38715a8f58e9cf1fe3e34ee4b1a4ae339630282b Reviewed-on: https://code.wireshark.org/review/14066 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
9ff932bf5e
commit
c2f85b6925
|
@ -653,6 +653,10 @@ and the subsequent packets don't have the expect format.
|
|||
To dissect these packets you need to wait until all the parts have
|
||||
arrived and then start the dissection.
|
||||
|
||||
The following sections will guide you through two common cases. For a
|
||||
description of all possible functions, structures and parameters, see
|
||||
'epan/reassemble.h'.
|
||||
|
||||
[[ChDissectReassembleUdp]]
|
||||
|
||||
==== How to reassemble split UDP packets
|
||||
|
@ -699,10 +703,9 @@ if (flags & FL_FRAGMENT) { /* fragmented */
|
|||
guint16 msg_num = tvb_get_ntohs(tvb, offset); offset += 2;
|
||||
|
||||
pinfo->fragmented = TRUE;
|
||||
frag_msg = fragment_add_seq_check(tvb, offset, pinfo,
|
||||
msg_seqid, /* ID for fragments belonging together */
|
||||
msg_fragment_table, /* list of message fragments */
|
||||
msg_reassembled_table, /* list of reassembled messages */
|
||||
frag_msg = fragment_add_seq_check(msg_reassembly_table,
|
||||
tvb, offset, pinfo,
|
||||
msg_seqid, NULL, /* ID for fragments belonging together */
|
||||
msg_num, /* fragment sequence number */
|
||||
tvb_captured_length_remaining(tvb, offset), /* fragment length - to the end */
|
||||
flags & FL_FRAG_LAST); /* More fragments? */
|
||||
|
@ -713,7 +716,9 @@ We start by saving the fragmented state of this packet, so we can restore it
|
|||
later. Next comes some protocol specific stuff, to dig the fragment data out of
|
||||
the stream if it's present. Having decided it is present, we let the function
|
||||
+fragment_add_seq_check()+ do its work. We need to provide this with a certain
|
||||
amount of data.
|
||||
amount of parameters:
|
||||
|
||||
* The +msg_reassembly_table+ table is for bookkeeping and is described later.
|
||||
|
||||
* The tvb buffer we are dissecting.
|
||||
|
||||
|
@ -725,8 +730,8 @@ amount of data.
|
|||
fragments in flight, and this is used to key the relevant one to be used for
|
||||
reassembly.
|
||||
|
||||
* The +msg_fragment_table+ and the +msg_reassembled_table+ are variables we need
|
||||
to declare. We'll consider these in detail later.
|
||||
* Optional additional data for identifying the fragment. Can be set to +NULL+
|
||||
(as is done in the example) for most dissectors.
|
||||
|
||||
* msg_num is the packet number within the sequence.
|
||||
|
||||
|
@ -781,25 +786,29 @@ Now the mysterious data we passed into the +fragment_add_seq_check()+.
|
|||
.Reassembling fragments - Initialisation
|
||||
====
|
||||
----
|
||||
static GHashTable *msg_fragment_table = NULL;
|
||||
static GHashTable *msg_reassembled_table = NULL;
|
||||
static reassembly_table reassembly_table;
|
||||
|
||||
static void
|
||||
msg_init_protocol(void)
|
||||
{
|
||||
fragment_table_init(&msg_fragment_table);
|
||||
reassembled_table_init(&msg_reassembled_table);
|
||||
reassembly_table_init(&msg_reassemble_table,
|
||||
&addresses_ports_reassembly_table_functions);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
First a couple of hash tables are declared, and these are initialised in the
|
||||
protocol initialisation routine. Following that, a +fragment_items+ structure is
|
||||
allocated and filled in with a series of ett items, hf data items, and a string
|
||||
tag. The ett and hf values should be included in the relevant tables like all
|
||||
the other variables your protocol may use. The hf variables need to be placed in
|
||||
the structure something like the following. Of course the names may need to be
|
||||
adjusted.
|
||||
First a +reassembly_table+ structure is declared and initialised in the protocol
|
||||
initialisation routine. The second parameter specifies the functions that should
|
||||
be used for identifying fragments. We will use
|
||||
+addresses_ports_reassembly_table_functions+ in order to identify fragments by
|
||||
the given sequence number (+msg_seqid+), the source and destination addresses
|
||||
and ports from the packet.
|
||||
|
||||
Following that, a +fragment_items+ structure is allocated and filled in with a
|
||||
series of ett items, hf data items, and a string tag. The ett and hf values
|
||||
should be included in the relevant tables like all the other variables your
|
||||
protocol may use. The hf variables need to be placed in the structure something
|
||||
like the following. Of course the names may need to be adjusted.
|
||||
|
||||
.Reassembling fragments - Data
|
||||
====
|
||||
|
|
|
@ -1960,11 +1960,11 @@ fragment_add_seq(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
|||
* This function assumes frag_number being a block sequence number.
|
||||
* The bsn for the first block is 0.
|
||||
*
|
||||
* If "no_frag_number" is TRUE, it uses the next expected fragment number
|
||||
* If REASSEMBLE_FLAGS_NO_FRAG_NUMBER, it uses the next expected fragment number
|
||||
* as the fragment number if there is a reassembly in progress, otherwise
|
||||
* it uses 0.
|
||||
*
|
||||
* If "no_frag_number" is FALSE, it uses the "frag_number" argument as
|
||||
* If not REASSEMBLE_FLAGS_NO_FRAG_NUMBER, it uses the "frag_number" argument as
|
||||
* the fragment number.
|
||||
*
|
||||
* If this is the first fragment seen for this datagram, a new
|
||||
|
@ -2077,6 +2077,8 @@ fragment_add_seq_next(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
|||
const void *data, const guint32 frag_data_len,
|
||||
const gboolean more_frags)
|
||||
{
|
||||
/* Use a dummy frag_number (0), it is ignored since
|
||||
* REASSEMBLE_FLAGS_NO_FRAG_NUMBER is set. */
|
||||
return fragment_add_seq_check_work(table, tvb, offset, pinfo, id, data,
|
||||
0, frag_data_len, more_frags,
|
||||
REASSEMBLE_FLAGS_NO_FRAG_NUMBER);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* reassemble.h
|
||||
* Declarations of outines for {fragment,segment} reassembly
|
||||
* Declarations of routines for {fragment,segment} reassembly
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
|
@ -77,10 +77,12 @@ typedef struct _fragment_item {
|
|||
* provided fragment number of the first fragment does
|
||||
* not start with 0
|
||||
* XXX - does this apply only to reassembly heads? */
|
||||
guint32 datalen; /**< Only valid in first item of list and when
|
||||
* flags&FD_DATALEN_SET is set;
|
||||
* number of bytes or (if flags&FD_BLOCKSEQUENCE set)
|
||||
* segments in the datagram */
|
||||
guint32 datalen; /**< When flags&FD_BLOCKSEQUENCE is set, the
|
||||
index of the last block (segments in
|
||||
datagram + 1); otherwise the number of
|
||||
bytes of the full datagram. Only valid in
|
||||
the first item of the fragments list when
|
||||
flags&FD_DATALEN is set.*/
|
||||
guint32 reassembled_in; /**< frame where this PDU was reassembled,
|
||||
only valid in the first item of the list
|
||||
and when FD_DEFRAGMENTED is set*/
|
||||
|
@ -119,11 +121,20 @@ typedef struct _fragment_item {
|
|||
* in the tvb, and if not, do something a bit odd. */
|
||||
#define REASSEMBLE_FLAGS_CHECK_DATA_PRESENT 0x0004
|
||||
|
||||
/* a function for creating temporary hash keys */
|
||||
/*
|
||||
* Generates a fragment identifier based on the given parameters. "data" is an
|
||||
* opaque type whose interpretation is up to the caller of fragment_add*
|
||||
* functions and the fragment key function (possibly NULL if you do not care).
|
||||
*
|
||||
* Keys returned by this function are only used within this packet scope.
|
||||
*/
|
||||
typedef gpointer (*fragment_temporary_key)(const packet_info *pinfo,
|
||||
const guint32 id, const void *data);
|
||||
|
||||
/* a function for creating persistent hash keys */
|
||||
/*
|
||||
* Like fragment_temporary_key, but used for identifying reassembled fragments
|
||||
* which may persist through multiple packets.
|
||||
*/
|
||||
typedef gpointer (*fragment_persistent_key)(const packet_info *pinfo,
|
||||
const guint32 id, const void *data);
|
||||
|
||||
|
@ -181,14 +192,27 @@ reassembly_table_destroy(reassembly_table *table);
|
|||
* The list of fragments for a specific datagram is kept sorted for
|
||||
* easier handling.
|
||||
*
|
||||
* Datagrams (messages) are identified by a key generated by
|
||||
* fragment_temporary_key or fragment_persistent_key, based on the "pinfo", "id"
|
||||
* and "data" pairs. (This is the sole purpose of "data".)
|
||||
*
|
||||
* Fragments are identified by "frag_offset".
|
||||
*
|
||||
* Returns a pointer to the head of the fragment data list if we have all the
|
||||
* fragments, NULL otherwise.
|
||||
* fragments, NULL otherwise. Note that the reassembled fragments list may have
|
||||
* a non-zero fragment offset, the only guarantee is that no gaps exist within
|
||||
* the list.
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_add(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
||||
const packet_info *pinfo, const guint32 id, const void *data,
|
||||
const guint32 frag_offset, const guint32 frag_data_len,
|
||||
const gboolean more_frags);
|
||||
/*
|
||||
* Like fragment_add, except that the fragment may be added to multiple
|
||||
* reassembly tables. This is needed when multiple protocol layers try
|
||||
* to add the same packet to the reassembly table.
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_add_multiple_ok(reassembly_table *table, tvbuff_t *tvb,
|
||||
const int offset, const packet_info *pinfo,
|
||||
|
@ -198,13 +222,18 @@ fragment_add_multiple_ok(reassembly_table *table, tvbuff_t *tvb,
|
|||
const gboolean more_frags);
|
||||
|
||||
/*
|
||||
* This routine extends fragment_add to use a "reassembled_table"
|
||||
* included in the reassembly table.
|
||||
* Like fragment_add, but maintains a table for completed reassemblies.
|
||||
*
|
||||
* If, after processing this fragment, we have all the fragments, they
|
||||
* remove that from the fragment hash table if necessary and add it
|
||||
* to the table of reassembled fragments, and return a pointer to the
|
||||
* head of the fragment list.
|
||||
* If the packet was seen before, return the head of the fully reassembled
|
||||
* fragments list (NULL if there was none).
|
||||
*
|
||||
* Otherwise (if reassembly was not possible before), try to to add the new
|
||||
* fragment to the fragments table. If reassembly is now possible, remove all
|
||||
* (reassembled) fragments from the fragments table and store it as a completed
|
||||
* reassembly. The head of this reassembled fragments list is returned.
|
||||
*
|
||||
* Otherwise (if reassembly is still not possible after adding this fragment),
|
||||
* return NULL.
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_add_check(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
||||
|
@ -212,22 +241,19 @@ fragment_add_check(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
|||
const void *data, const guint32 frag_offset,
|
||||
const guint32 frag_data_len, const gboolean more_frags);
|
||||
|
||||
/* same as fragment_add() but this one assumes frag_number is a block
|
||||
sequence number. note that frag_number is 0 for the first fragment. */
|
||||
|
||||
/*
|
||||
* These functions add a new fragment to the fragment hash table,
|
||||
* assuming that frag_number is a block sequence number (starting from zero for
|
||||
* the first fragment of each datagram).
|
||||
* Like fragment_add, but fragments have a block sequence number starting from
|
||||
* zero (for the first fragment of each datagram). This differs from
|
||||
* fragment_add for which the fragment may start at any offset.
|
||||
*
|
||||
* If this is the first fragment seen for this datagram, a new
|
||||
* "fragment_head" structure is allocated to refer to the reassembled
|
||||
* packet, and:
|
||||
*
|
||||
* if "more_frags" is false, and either we have no sequence numbers, or
|
||||
* are using the 802.11 hack, it is assumed that this is the only fragment
|
||||
* in the datagram. The structure is not added to the hash
|
||||
* table, and not given any fragments to refer to, but is just returned.
|
||||
* are using the 802.11 hack (via fragment_add_seq_802_11), it is assumed that
|
||||
* this is the only fragment in the datagram. The structure is not added to the
|
||||
* hash table, and not given any fragments to refer to, but is just returned.
|
||||
*
|
||||
* In this latter case reassembly wasn't done (since there was only one
|
||||
* fragment in the packet); dissectors can check the 'next' pointer on the
|
||||
|
@ -247,12 +273,8 @@ fragment_add_seq(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
|||
const gboolean more_frags, const guint32 flags);
|
||||
|
||||
/*
|
||||
* These routines extend fragment_add_seq to use the "reassembled_table".
|
||||
*
|
||||
* If, after processing this fragment, we have all the fragments, they
|
||||
* remove that from the fragment hash table if necessary and add it
|
||||
* to the table of reassembled fragments, and return a pointer to the
|
||||
* head of the fragment list.
|
||||
* Like fragment_add_seq, but maintains a table for completed reassemblies
|
||||
* just like fragment_add_check.
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_add_seq_check(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
||||
|
@ -261,6 +283,11 @@ fragment_add_seq_check(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
|||
const guint32 frag_number, const guint32 frag_data_len,
|
||||
const gboolean more_frags);
|
||||
|
||||
/*
|
||||
* Like fragment_add_seq_check, but immediately returns a fragment list for a
|
||||
* new fragment. This is a workaround specific for the 802.11 dissector, do not
|
||||
* use it elsewhere.
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_add_seq_802_11(reassembly_table *table, tvbuff_t *tvb,
|
||||
const int offset, const packet_info *pinfo,
|
||||
|
@ -268,17 +295,31 @@ fragment_add_seq_802_11(reassembly_table *table, tvbuff_t *tvb,
|
|||
const guint32 frag_number, const guint32 frag_data_len,
|
||||
const gboolean more_frags);
|
||||
|
||||
/*
|
||||
* Like fragment_add_seq_check, but without explicit fragment number. Fragments
|
||||
* are simply appended until no "more_frags" is false.
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_add_seq_next(reassembly_table *table, tvbuff_t *tvb, const int offset,
|
||||
const packet_info *pinfo, const guint32 id,
|
||||
const void *data, const guint32 frag_data_len,
|
||||
const gboolean more_frags);
|
||||
|
||||
/*
|
||||
* Start a reassembly, expecting "tot_len" as the number of given fragments (not
|
||||
* the number of bytes). Data can be added later using fragment_add_seq_check.
|
||||
*/
|
||||
WS_DLL_PUBLIC void
|
||||
fragment_start_seq_check(reassembly_table *table, const packet_info *pinfo,
|
||||
const guint32 id, const void *data,
|
||||
const guint32 tot_len);
|
||||
|
||||
/*
|
||||
* Mark end of reassembly and returns the reassembled fragment (if completed).
|
||||
* Use it when fragments were added with "more_flags" set while you discovered
|
||||
* that no more fragments have to be added.
|
||||
* XXX rename to fragment_finish as it works also for fragment_add?
|
||||
*/
|
||||
WS_DLL_PUBLIC fragment_head *
|
||||
fragment_end_seq_next(reassembly_table *table, const packet_info *pinfo,
|
||||
const guint32 id, const void *data);
|
||||
|
@ -290,18 +331,23 @@ WS_DLL_PUBLIC void
|
|||
fragment_add_seq_offset(reassembly_table *table, const packet_info *pinfo, const guint32 id,
|
||||
const void *data, const guint32 fragment_offset);
|
||||
|
||||
/* to specify how much to reassemble, for fragmentation where last fragment can not be
|
||||
* identified by flags or such.
|
||||
* note that for FD_BLOCKSEQUENCE tot_len is the index for the tail fragment.
|
||||
/*
|
||||
* Sets the expected index for the last block (for fragment_add_seq functions)
|
||||
* or the expected number of bytes (for fragment_add functions). A reassembly
|
||||
* must already have started.
|
||||
*
|
||||
* Note that for FD_BLOCKSEQUENCE tot_len is the index for the tail fragment.
|
||||
* i.e. since the block numbers start at 0, if we specify tot_len==2, that
|
||||
* actually means we want to defragment 3 blocks, block 0, 1 and 2.
|
||||
*
|
||||
*/
|
||||
WS_DLL_PUBLIC void
|
||||
fragment_set_tot_len(reassembly_table *table, const packet_info *pinfo,
|
||||
const guint32 id, const void *data, const guint32 tot_len);
|
||||
|
||||
/* to resad whatever totlen previously set */
|
||||
/*
|
||||
* Return the expected index for the last block (for fragment_add_seq functions)
|
||||
* or the expected number of bytes (for fragment_add functions).
|
||||
*/
|
||||
WS_DLL_PUBLIC guint32
|
||||
fragment_get_tot_len(reassembly_table *table, const packet_info *pinfo,
|
||||
const guint32 id, const void *data);
|
||||
|
|
Loading…
Reference in New Issue