From 0d2772aa1eb32c87726da2f8add69216f2511c5f Mon Sep 17 00:00:00 2001 From: grahamb Date: Mon, 6 Jun 2011 22:32:37 +0000 Subject: Added code to distinguish conversations between different RTUs that happen to use the same address\port pair. Based on patch supplied by Kelvin Proctor. https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=3626 git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@37584 f5534014-38df-0310-8fa8-9805f1628bb7 --- epan/dissectors/packet-dnp.c | 78 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 9 deletions(-) (limited to 'epan/dissectors/packet-dnp.c') diff --git a/epan/dissectors/packet-dnp.c b/epan/dissectors/packet-dnp.c index 31424a5019..8699379a6f 100644 --- a/epan/dissectors/packet-dnp.c +++ b/epan/dissectors/packet-dnp.c @@ -1027,6 +1027,44 @@ static gint ett_dnp3_al_obj_point_perms = -1; /* Tables for reassembly of fragments. */ static GHashTable *al_fragment_table = NULL; static GHashTable *al_reassembled_table = NULL; +static GHashTable *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 gint +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 1; + } + + return 0; +} + +/* 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 */ @@ -2693,6 +2731,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) gboolean update_col_info = TRUE; conversation_t *conversation; dnp3_conv_t *conv_data_ptr; + dl_conversation_key_t dl_conversation_key; @@ -2902,17 +2941,32 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* Look up the conversation to get the fragment reassembly id */ conversation = find_or_create_conversation(pinfo); - conv_data_ptr = (dnp3_conv_t*)conversation_get_proto_data(conversation, proto_dnp3); + /* + * 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 + */ - if (conv_data_ptr == NULL) { - /* New data structure required */ - conv_data_ptr = se_alloc(sizeof(dnp3_conv_t)); + dl_conversation_key.conversation = conversation->index; + dl_conversation_key.src = dl_src; + dl_conversation_key.dst = dl_dst; + + conv_data_ptr = (dnp3_conv_t*)g_hash_table_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 = se_alloc(sizeof(dl_conversation_key_t)); + *new_dl_conversation_key = dl_conversation_key; + + conv_data_ptr = se_alloc(sizeof(dnp3_conv_t)); + /*** Increment static global fragment reassembly id ***/ conv_data_ptr->conv_seq_number = seq_number++; - conversation_add_proto_data(conversation, proto_dnp3, (void *)conv_data_ptr); - } + g_hash_table_insert(dl_conversation_table, new_dl_conversation_key, conv_data_ptr); + } + conv_seq_number = conv_data_ptr->conv_seq_number; /* @@ -2940,7 +2994,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* We don't have the complete reassembled payload. */ if (check_col (pinfo->cinfo, COL_INFO)) - col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Application Layer fragment %u ", tr_seq); + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Transport Layer fragment %u ", tr_seq); } } @@ -3016,8 +3070,14 @@ dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } static void -al_defragment_init(void) +dnp3_init(void) { + if (dl_conversation_table) + { + g_hash_table_destroy(dl_conversation_table); + } + dl_conversation_table = g_hash_table_new(dl_conversation_hash, dl_conversation_equal); + fragment_table_init(&al_fragment_table); reassembled_table_init(&al_reassembled_table); } @@ -3472,7 +3532,7 @@ proto_register_dnp3(void) module_t *dnp3_module; /* Register protocol init routine */ - register_init_routine(&al_defragment_init); + register_init_routine(&dnp3_init); /* Register the protocol name and description */ proto_dnp3 = proto_register_protocol("Distributed Network Protocol 3.0", -- cgit v1.2.3