diff options
author | Graham Bloice <graham.bloice@trihedral.com> | 2017-02-04 21:09:59 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2017-02-05 13:45:58 +0000 |
commit | a8ceeca444c97033e630d56d6a6fb096e696163b (patch) | |
tree | 6e00ba1bd3c74f3a59bf3b340598844f87e6af3c /epan/dissectors/packet-dnp.c | |
parent | fd2bd2b154730f88d968648cc5705c86681ca14c (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.c | 175 |
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); |