aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dnp.c
diff options
context:
space:
mode:
authorGraham Bloice <graham.bloice@trihedral.com>2017-02-04 21:09:59 +0000
committerMichael Mann <mmann78@netscape.net>2017-02-05 13:45:58 +0000
commita8ceeca444c97033e630d56d6a6fb096e696163b (patch)
tree6e00ba1bd3c74f3a59bf3b340598844f87e6af3c /epan/dissectors/packet-dnp.c
parentfd2bd2b154730f88d968648cc5705c86681ca14c (diff)
DNP3: Fix reassembly of out of order fragments
Rework Application Layer fragment reassembly to handle out of order fragments (seen over UDP). Change-Id: Ifd2bffba30f0a419a5f82ea6b9d2d221f7d6d276 Reviewed-on: https://code.wireshark.org/review/19947 Petri-Dish: Graham Bloice <graham.bloice@trihedral.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Graham Bloice <graham.bloice@trihedral.com>
Diffstat (limited to 'epan/dissectors/packet-dnp.c')
-rw-r--r--epan/dissectors/packet-dnp.c175
1 files changed, 45 insertions, 130 deletions
diff --git a/epan/dissectors/packet-dnp.c b/epan/dissectors/packet-dnp.c
index 1705caa9e7..596c16c013 100644
--- a/epan/dissectors/packet-dnp.c
+++ b/epan/dissectors/packet-dnp.c
@@ -602,6 +602,7 @@ static int hf_dnp3_data_chunk = -1;
static int hf_dnp3_data_chunk_len = -1;
static int hf_dnp3_data_chunk_crc = -1;
static int hf_dnp3_data_chunk_crc_status = -1;
+
/* Added for Application Layer Decoding */
static int hf_dnp3_al_ctl = -1;
static int hf_dnp3_al_fir = -1;
@@ -1301,48 +1302,11 @@ static expert_field ei_dnp3_buffering_user_data_until_final_frame_is_received =
/* Tables for reassembly of fragments. */
static reassembly_table al_reassembly_table;
-static wmem_map_t *dl_conversation_table = NULL;
-
-/* Data-Link-Layer Conversation Key Structure */
-typedef struct _dl_conversation_key
-{
- guint32 conversation; /* TCP / UDP conversation index */
- guint16 src; /* DNP3.0 Source Address */
- guint16 dst; /* DNP3.0 Destination Address */
-} dl_conversation_key_t;
-
-/* Data-Link-Layer conversation key equality function */
-static gboolean
-dl_conversation_equal(gconstpointer v, gconstpointer w)
-{
- const dl_conversation_key_t* v1 = (const dl_conversation_key_t*)v;
- const dl_conversation_key_t* v2 = (const dl_conversation_key_t*)w;
-
- if ((v1->conversation == v2->conversation) &&
- (v1->src == v2->src) &&
- (v1->dst == v2->dst))
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* Data-Link-Layer conversation key hash function */
-static guint
-dl_conversation_hash(gconstpointer v)
-{
- const dl_conversation_key_t *key = (const dl_conversation_key_t*)v;
- guint val;
-
- val = key->conversation + (key->src << 16) + key->dst;
-
- return val;
-}
/* ************************************************************************* */
/* Header values for reassembly */
/* ************************************************************************* */
+static int hf_al_frag_data = -1;
static int hf_dnp3_fragment = -1;
static int hf_dnp3_fragments = -1;
static int hf_dnp3_fragment_overlap = -1;
@@ -1374,18 +1338,6 @@ static const fragment_items dnp3_frag_items = {
"DNP 3.0 fragments"
};
-/* Conversation stuff, used for tracking application message fragments */
-/* the number of entries in the memory chunk array */
-#define dnp3_conv_init_count 50
-
-/* Conversation structure */
-typedef struct {
- guint conv_seq_number;
-} dnp3_conv_t;
-
-/* The conversation sequence number */
-static guint seq_number = 0;
-
/* desegmentation of DNP3 over TCP */
static gboolean dnp3_desegment = TRUE;
@@ -3302,82 +3254,56 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void*
/* Check for fragmented packet */
save_fragmented = pinfo->fragmented;
- if (! (tr_fir && tr_fin))
- {
- guint conv_seq_number;
- fragment_head *frag_msg;
- conversation_t *conversation;
- dnp3_conv_t *conv_data_ptr;
- dl_conversation_key_t dl_conversation_key;
-
- /* A fragmented packet */
- pinfo->fragmented = TRUE;
-
- /* Look up the conversation to get the fragment reassembly id */
- conversation = find_or_create_conversation(pinfo);
-
- /*
- * The TCP/UDP conversation is not sufficient to identify a conversation
- * on a multi-drop DNP network. Lookup conversation data based on TCP/UDP
- * conversation and the DNP src and dst addresses
- */
-
- dl_conversation_key.conversation = conversation->conv_index;
- dl_conversation_key.src = dl_src;
- dl_conversation_key.dst = dl_dst;
- conv_data_ptr = (dnp3_conv_t*)wmem_map_lookup(dl_conversation_table, &dl_conversation_key);
-
- if (!pinfo->fd->flags.visited && conv_data_ptr == NULL)
- {
- dl_conversation_key_t* new_dl_conversation_key = NULL;
- new_dl_conversation_key = wmem_new(wmem_file_scope(), dl_conversation_key_t);
- *new_dl_conversation_key = dl_conversation_key;
-
- conv_data_ptr = wmem_new(wmem_file_scope(), dnp3_conv_t);
-
- /*** Increment static global fragment reassembly id ***/
- conv_data_ptr->conv_seq_number = seq_number++;
-
- wmem_map_insert(dl_conversation_table, new_dl_conversation_key, conv_data_ptr);
- }
-
- conv_seq_number = conv_data_ptr->conv_seq_number;
-
- /*
- * Add the frame to
- * whatever reassembly is in progress, if any, and see
- * if it's done.
- */
-
- frag_msg = fragment_add_seq_next(&al_reassembly_table,
- al_tvb, 0, pinfo, conv_seq_number, NULL,
+ /* Reassemble AL fragments */
+ static guint al_max_fragments = 60;
+ static guint al_fragment_aging = 64; /* sequence numbers only 6 bit */
+ fragment_head *frag_al = NULL;
+ pinfo->fragmented = TRUE;
+ if (!pinfo->fd->flags.visited)
+ {
+ frag_al = fragment_add_seq_single_aging(&al_reassembly_table,
+ al_tvb, 0, pinfo, tr_seq, NULL,
tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
- !tr_fin);
-
- next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
- "Reassembled DNP 3.0 Application Layer message", frag_msg, &dnp3_frag_items,
- NULL, dnp3_tree);
+ tr_fir, tr_fin,
+ al_max_fragments, al_fragment_aging);
+ }
+ else
+ {
+ frag_al = fragment_get_reassembled_id(&al_reassembly_table, pinfo, tr_seq);
+ }
+ next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
+ "Reassembled DNP 3.0 Application Layer message", frag_al, &dnp3_frag_items,
+ NULL, dnp3_tree);
- if (next_tvb) /* Reassembled */
+ if (frag_al)
+ {
+ if (pinfo->num == frag_al->reassembled_in)
{
- /* We have the complete payload, zap the info column as the AL info takes precedence */
- col_clear(pinfo->cinfo, COL_INFO);
+ /* As a complete AL message will have cleared the info column,
+ make sure source and dest are always in the info column */
+ //col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
+ //col_set_fence(pinfo->cinfo, COL_INFO);
+ dissect_dnp3_al(next_tvb, pinfo, dnp3_tree);
}
else
{
- /* We don't have the complete reassembled payload. */
- col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "TL fragment %u ", tr_seq);
+ /* Lock any column info set by the DL and TL */
+ col_set_fence(pinfo->cinfo, COL_INFO);
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (Application Layer fragment %u, reassembled in packet %u)",
+ tr_seq, frag_al->reassembled_in);
+ proto_tree_add_item(dnp3_tree, hf_al_frag_data, al_tvb, 0, -1, ENC_NA);
}
-
}
else
{
- /* No reassembly required */
- next_tvb = al_tvb;
- add_new_data_source(pinfo, next_tvb, "DNP 3.0 Application Layer message");
- col_clear(pinfo->cinfo, COL_INFO);
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (Application Layer Unreassembled fragment %u)",
+ tr_seq);
+ proto_tree_add_item(dnp3_tree, hf_al_frag_data, al_tvb, 0, -1, ENC_NA);
}
+
pinfo->fragmented = save_fragmented;
}
else
@@ -3385,21 +3311,6 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void*
/* CRC error - throw away the data. */
next_tvb = NULL;
}
-
- /* Dissect any completed Application Layer message */
- if (next_tvb && tr_fin)
- {
- /* As a complete AL message will have cleared the info column,
- make sure source and dest are always in the info column */
- col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
- col_set_fence(pinfo->cinfo, COL_INFO);
- dissect_dnp3_al(next_tvb, pinfo, dnp3_tree);
- }
- else
- {
- /* Lock any column info set by the DL and TL */
- col_set_fence(pinfo->cinfo, COL_INFO);
- }
}
/* Set the length of the message */
@@ -4428,6 +4339,11 @@ proto_register_dnp3(void)
NULL, HFILL }
},
+ { &hf_al_frag_data,
+ {"DNP3.0 AL Fragment Data", "dnp3.al.frag_data",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "DNP 3.0 Application Layer Fragment Data", HFILL }},
+
{ &hf_dnp3_fragment,
{ "DNP 3.0 AL Fragment", "dnp3.al.fragment",
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
@@ -4539,7 +4455,6 @@ proto_register_dnp3(void)
module_t *dnp3_module;
expert_module_t* expert_dnp3;
- dl_conversation_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), dl_conversation_hash, dl_conversation_equal);
reassembly_table_register(&al_reassembly_table,
&addresses_reassembly_table_functions);