diff options
author | Stig Bjørlykke <stig@bjorlykke.org> | 2008-10-03 14:58:53 +0000 |
---|---|---|
committer | Stig Bjørlykke <stig@bjorlykke.org> | 2008-10-03 14:58:53 +0000 |
commit | 6882a5cd1ac04776ab4b94d270e03d96242812cd (patch) | |
tree | 5d7e69de5a90ffeacfb47834c583bffcc005199a /epan/dissectors/packet-p_mul.c | |
parent | 8a3dcb79225a7d7291ee1da25968cdaf241636a3 (diff) |
Several improvements:
- Split SEQ/ACK analysis into SEQ analysis (pr msg) and ACK analysis
(pr dest/ackinfo entry) to correctly handle multicast messages.
- Improved dump of timestamp (in units of 100ms).
- Show Address PDU with 0 dest entries as Ack-Ack PDU.
- Print correct number of missing sequence numbers in Ack.
- Indicate end of list entry in Ack.
- Message ID is unsigned.
svn path=/trunk/; revision=26345
Diffstat (limited to 'epan/dissectors/packet-p_mul.c')
-rw-r--r-- | epan/dissectors/packet-p_mul.c | 556 |
1 files changed, 371 insertions, 185 deletions
diff --git a/epan/dissectors/packet-p_mul.c b/epan/dissectors/packet-p_mul.c index 70f4358493..ec4e970a3d 100644 --- a/epan/dissectors/packet-p_mul.c +++ b/epan/dissectors/packet-p_mul.c @@ -69,6 +69,7 @@ #define FEC_Address_PDU 0x08 #define Extra_Address_PDU 0x12 #define Extra_FEC_Address_PDU 0x18 +#define Ack_Ack_PDU 0xFF /* Fake type to indicate Ack-Ack */ /* Type of content to decode from Data_PDU */ #define DECODE_NONE 0 @@ -149,7 +150,9 @@ static gint ett_dest_entry = -1; static gint ett_ack_entry = -1; static gint ett_range_entry = -1; static gint ett_checksum = -1; -static gint ett_analysis = -1; +static gint ett_seq_analysis = -1; +static gint ett_ack_analysis = -1; +static gint ett_seq_ack_analysis = -1; static gint ett_msg_fragment = -1; static gint ett_msg_fragments = -1; @@ -162,25 +165,33 @@ typedef struct _p_mul_id_key { address addr; } p_mul_id_key; -typedef struct _p_mul_id_val { - gint msg_type; /* Message type */ - guint32 prev_msg_id; /* Previous message package num */ - nstime_t prev_msg_time; /* Previous message receive time */ - guint32 addr_id; /* PDU package num for Address_PDU */ +typedef struct _p_mul_seq_val { + gint msg_type; /* Message type */ + guint32 prev_msg_id; /* Previous message package num */ + nstime_t prev_msg_time; /* Previous message receive time */ + guint32 addr_id; /* PDU package num for Address_PDU */ nstime_t addr_time; /* PDU received time for Address_PDU */ - guint32 pdu_id; /* PDU package num */ - nstime_t pdu_time; /* PDU receive time */ - guint32 prev_pdu_id; /* Previous PDU package num */ - nstime_t prev_pdu_time; /* Previous PDU receive time */ - guint32 ack_id; /* Ack PDU package num */ - guint16 last_found_pdu; /* Last PDU num */ - nstime_t first_msg_time; /* First message receive time */ - guint32 msg_resend_count; /* Message resend counter */ - guint32 ack_resend_count; /* Ack resend counter */ -} p_mul_id_val; - + guint32 pdu_id; /* PDU package num */ + nstime_t pdu_time; /* PDU receive time */ + guint32 prev_pdu_id; /* Previous PDU package num */ + nstime_t prev_pdu_time; /* Previous PDU receive time */ + guint16 last_found_pdu; /* Last PDU num */ + nstime_t first_msg_time; /* First message receive time */ + guint32 msg_resend_count; /* Message resend counter */ + GHashTable *ack_data; +} p_mul_seq_val; + +typedef struct _p_mul_ack_data { + guint32 ack_id; /* Ack PDU package num */ + guint32 ack_resend_count; /* Ack resend counter */ +} p_mul_ack_data; + +/* Hash table with current data for seq/ack analysis */ static GHashTable *p_mul_id_hash_table = NULL; +/* List of hash tables stored in each frame */ +static GList *p_mul_package_data_list = NULL; + /* User definable values to use for dissection */ static range_t *global_p_mul_port_range; static gboolean p_mul_reassemble = TRUE; @@ -223,6 +234,7 @@ static const value_string pdu_vals[] = { { FEC_Address_PDU, "FEC Address PDU" }, { Extra_Address_PDU, "Extra Address PDU" }, { Extra_FEC_Address_PDU, "Extra FEC Address PDU" }, + { Ack_Ack_PDU, "Ack-Ack PDU" }, { 0, NULL } }; @@ -285,25 +297,66 @@ static gint p_mul_id_hash_equal (gconstpointer k1, gconstpointer k2) { p_mul_id_key *p_mul1=(p_mul_id_key *)k1; p_mul_id_key *p_mul2=(p_mul_id_key *)k2; + if (p_mul1->id != p_mul2->id) return 0; if (p_mul1->seq != p_mul2->seq) return 0; - + return (ADDRESSES_EQUAL (&p_mul1->addr, &p_mul2->addr)); } -static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, - guint32 message_id, guint16 seq_no, - gint no_missing) +static p_mul_seq_val *lookup_seq_val (guint32 message_id, guint16 seq_no, + address *addr) +{ + p_mul_seq_val *pkg_data = NULL; + p_mul_id_key *p_mul_key = se_alloc (sizeof (p_mul_id_key)); + + p_mul_key->id = message_id; + p_mul_key->seq = seq_no; + SE_COPY_ADDRESS(&p_mul_key->addr, addr); + + pkg_data = (p_mul_seq_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); + + return pkg_data; +} + +static void p_mul_id_value_destroy (p_mul_seq_val *pkg_data) +{ + if (pkg_data->ack_data) { + g_hash_table_destroy (pkg_data->ack_data); + } +} + +static void p_mul_package_data_destroy (GHashTable *pkg_list, gpointer user_data _U_) +{ + g_hash_table_destroy (pkg_list); +} + +static void copy_hashtable_data (gpointer key, p_mul_ack_data *ack_data1, GHashTable *table) +{ + p_mul_ack_data *ack_data2; + + ack_data2 = se_alloc (sizeof (p_mul_ack_data)); + ack_data2->ack_id = ack_data1->ack_id; + ack_data2->ack_resend_count = ack_data1->ack_resend_count; + + g_hash_table_insert (table, key, ack_data2); +} + +static p_mul_seq_val *register_p_mul_id (packet_info *pinfo, address *addr, guint32 dstIP, + guint8 pdu_type, guint32 message_id, + guint16 seq_no, gint no_missing) { - p_mul_id_val *p_mul_data = NULL, *pkg_data = NULL; + p_mul_seq_val *p_mul_data = NULL, *pkg_data = NULL; p_mul_id_key *p_mul_key = NULL; + p_mul_ack_data *ack_data = NULL; nstime_t addr_time = { 0, 0 }, prev_time = { 0, 0 }; guint addr_id = 0, prev_id = 0; guint16 last_found_pdu = 0; gboolean missing_pdu = FALSE, set_address = FALSE; + GHashTable *pkg_list = NULL; if (pinfo->in_error_pkt) { /* No analysis of error packets */ @@ -318,10 +371,10 @@ static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, /* Try to match corresponding address PDU */ p_mul_key->id = message_id; p_mul_key->seq = 0; - SE_COPY_ADDRESS(&p_mul_key->addr, &(pinfo->src)); + SE_COPY_ADDRESS(&p_mul_key->addr, addr); set_address = TRUE; - p_mul_data = (p_mul_id_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); + p_mul_data = (p_mul_seq_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); if (p_mul_data) { /* Found address PDU */ @@ -329,7 +382,7 @@ static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, p_mul_data->last_found_pdu = seq_no; addr_id = p_mul_data->pdu_id; addr_time = p_mul_data->pdu_time; - + /* Save data for last found PDU */ p_mul_data->prev_pdu_id = pinfo->fd->num; p_mul_data->prev_pdu_time = pinfo->fd->abs_ts; @@ -342,7 +395,7 @@ static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, if (last_found_pdu) { /* Try to match previous data PDU */ p_mul_key->seq = last_found_pdu; - p_mul_data = (p_mul_id_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); + p_mul_data = (p_mul_seq_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); } if (p_mul_data) { @@ -356,28 +409,36 @@ static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, } } } - - p_mul_key->id = message_id; - p_mul_key->seq = seq_no; - if (pdu_type == Ack_PDU) { - SE_COPY_ADDRESS(&p_mul_key->addr, &(pinfo->dst)); - } else if (!set_address) { - SE_COPY_ADDRESS(&p_mul_key->addr, &(pinfo->src)); - } - p_mul_data = (p_mul_id_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); + pkg_list = p_get_proto_data (pinfo->fd, proto_p_mul); + if (!pkg_list) { + /* Never saved list for this packet, create a new */ + pkg_list = g_hash_table_new (NULL, NULL); + p_mul_package_data_list = g_list_append (p_mul_package_data_list, pkg_list); + p_add_proto_data (pinfo->fd, proto_p_mul, pkg_list); + } if (!pinfo->fd->flags.visited) { + p_mul_key->id = message_id; + p_mul_key->seq = seq_no; + if (!set_address) { + SE_COPY_ADDRESS(&p_mul_key->addr, addr); + } + p_mul_data = (p_mul_seq_val *) g_hash_table_lookup (p_mul_id_hash_table, p_mul_key); + if (p_mul_data) { if (pdu_type == Ack_PDU) { /* Only save this data if positive ack */ if (no_missing == 0) { - if (p_mul_data->ack_id == 0) { + ack_data = g_hash_table_lookup (p_mul_data->ack_data, (gpointer)dstIP); + if (!ack_data) { /* Only save reference to first ACK */ - p_mul_data->ack_id = pinfo->fd->num; + ack_data = se_alloc0 (sizeof (p_mul_ack_data)); + ack_data->ack_id = pinfo->fd->num; + g_hash_table_insert (p_mul_data->ack_data, (gpointer)dstIP, ack_data); } else { /* Only count when resending */ - p_mul_data->ack_resend_count++; + ack_data->ack_resend_count++; } } } else { @@ -394,13 +455,17 @@ static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, } } else { /* New message */ - p_mul_data = se_alloc (sizeof (p_mul_id_val)); - memset (p_mul_data, 0, sizeof (p_mul_id_val)); + p_mul_data = se_alloc0 (sizeof (p_mul_seq_val)); p_mul_data->msg_type = pdu_type; + if (pdu_type == Address_PDU || pdu_type == Ack_PDU) { + p_mul_data->ack_data = g_hash_table_new (NULL, NULL); + } if (pdu_type == Ack_PDU) { /* No matching message for this ack */ - p_mul_data->ack_id = pinfo->fd->num; + ack_data = se_alloc0 (sizeof (p_mul_ack_data)); + ack_data->ack_id = pinfo->fd->num; + g_hash_table_insert (p_mul_data->ack_data, (gpointer)dstIP, ack_data); } else { p_mul_data->pdu_id = pinfo->fd->num; p_mul_data->pdu_time = pinfo->fd->abs_ts; @@ -417,33 +482,160 @@ static p_mul_id_val *register_p_mul_id (packet_info *pinfo, guint8 pdu_type, } } - pkg_data = se_alloc (sizeof (p_mul_id_val)); + /* Copy the current package data to the frame */ + pkg_data = se_alloc (sizeof (p_mul_seq_val)); *pkg_data = *p_mul_data; - p_add_proto_data (pinfo->fd, proto_p_mul, pkg_data); + if (p_mul_data->ack_data) { + /* Copy the hash table for ack data */ + pkg_data->ack_data = g_hash_table_new (NULL, NULL); + g_hash_table_foreach (p_mul_data->ack_data, (GHFunc) copy_hashtable_data, pkg_data->ack_data); + } + g_hash_table_insert (pkg_list, (gpointer)message_id, pkg_data); } else { /* Fetch last values from data saved in packet */ - pkg_data = p_get_proto_data (pinfo->fd, proto_p_mul); - - if (p_mul_data && pdu_type != Ack_PDU && pkg_data->ack_id == 0) { - pkg_data->ack_id = p_mul_data->ack_id; - } + pkg_data = g_hash_table_lookup (pkg_list, (gpointer)message_id); } DISSECTOR_ASSERT (pkg_data); return pkg_data; } -static p_mul_id_val *p_mul_add_seq_ack (tvbuff_t *tvb, packet_info *pinfo, - proto_tree *p_mul_tree, gint offset, +static void add_ack_analysis (tvbuff_t *tvb, packet_info *pinfo, proto_tree *p_mul_tree, + gint offset, guint8 pdu_type, address *src, address *dst, + guint32 message_id, gint no_missing) +{ + proto_tree *analysis_tree = NULL; + proto_item *sa = NULL, *en = NULL; + p_mul_seq_val *pkg_data = NULL; + p_mul_ack_data *ack_data = NULL; + gboolean item_added = FALSE; + guint32 dstIp; + nstime_t ns; + + if (pinfo->in_error_pkt) { + /* No analysis of error packets */ + return; + } + + dstIp = *((guint32*) dst->data); + if (pdu_type == Address_PDU) { + sa = proto_tree_add_text (p_mul_tree, tvb, 0, 0, "ACK analysis"); + PROTO_ITEM_SET_GENERATED (sa); + analysis_tree = proto_item_add_subtree (sa, ett_ack_analysis); + + /* Fetch package data */ + if ((pkg_data = lookup_seq_val (message_id, 0, src)) == NULL) { + /* No need for seq/ack analysis yet */ + return; + } + if (pkg_data->ack_data) { + ack_data = g_hash_table_lookup (pkg_data->ack_data, (gpointer)dstIp); + } + + /* Add reference to Ack_PDU */ + if (ack_data && ack_data->ack_id) { + en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb, + 0, 0, ack_data->ack_id); + PROTO_ITEM_SET_GENERATED (en); + item_added = TRUE; + } else if (!pkg_data->msg_resend_count) { + en = proto_tree_add_item (analysis_tree, + hf_analysis_ack_missing, + tvb, offset, 0, FALSE); + if (pinfo->fd->flags.visited) { + /* We do not know this on first visit and we do not want to + add a entry in the "Expert Severity Info" for this note */ + expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, + "Ack PDU missing"); + PROTO_ITEM_SET_GENERATED (en); + } + item_added = TRUE; + } + + if (!item_added) { + PROTO_ITEM_SET_HIDDEN (sa); + } + } else if (pdu_type == Ack_PDU) { + sa = proto_tree_add_text (p_mul_tree, tvb, 0, 0, "SEQ/ACK analysis"); + PROTO_ITEM_SET_GENERATED (sa); + analysis_tree = proto_item_add_subtree (sa, ett_seq_ack_analysis); + + /* Fetch package data */ + if ((pkg_data = register_p_mul_id (pinfo, src, dstIp, pdu_type, message_id, 0, no_missing)) == NULL) { + /* No need for seq/ack analysis yet */ + return; + } + if (pkg_data->ack_data) { + ack_data = g_hash_table_lookup (pkg_data->ack_data, (gpointer)dstIp); + } + + /* Add reference to Address_PDU */ + if (pkg_data->msg_type != Ack_PDU) { + en = proto_tree_add_uint (analysis_tree, hf_analysis_addr_pdu_num, tvb, + 0, 0, pkg_data->pdu_id); + PROTO_ITEM_SET_GENERATED (en); + + if (no_missing == 0) { + nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->first_msg_time); + en = proto_tree_add_time (analysis_tree, hf_analysis_total_time, + tvb, 0, 0, &ns); + PROTO_ITEM_SET_GENERATED (en); + } + } else { + en = proto_tree_add_item (analysis_tree, + hf_analysis_addr_pdu_missing, + tvb, offset, 0, FALSE); + expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, + "Address PDU missing"); + PROTO_ITEM_SET_GENERATED (en); + } + + if (pkg_data->msg_type != Ack_PDU && pkg_data->prev_pdu_id) { + /* Add reference to previous PDU */ + en = proto_tree_add_uint (analysis_tree, hf_analysis_last_pdu_num, + tvb, 0, 0, pkg_data->prev_pdu_id); + PROTO_ITEM_SET_GENERATED (en); + + nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->prev_pdu_time); + en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time, + tvb, 0, 0, &ns); + PROTO_ITEM_SET_GENERATED (en); + } + + if (ack_data && ack_data->ack_resend_count) { + /* Add resend statistics */ + en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no, + tvb, 0, 0, ack_data->ack_resend_count); + PROTO_ITEM_SET_GENERATED (en); + + expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, + "Dup ACK #%d", ack_data->ack_resend_count); + + en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from, + tvb, 0, 0, ack_data->ack_id); + PROTO_ITEM_SET_GENERATED (en); + + if (check_col (pinfo->cinfo, COL_INFO)) { + col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ", + ack_data->ack_id, ack_data->ack_resend_count); + } + } + } +} + +static p_mul_seq_val *add_seq_analysis (tvbuff_t *tvb, packet_info *pinfo, + proto_tree *p_mul_tree, address *src, + gint offset, guint8 pdu_type, guint32 message_id, guint16 seq_no, gint no_missing) { - p_mul_id_val *pkg_data = NULL; + p_mul_seq_val *pkg_data = NULL; proto_tree *analysis_tree = NULL; - proto_item *en = NULL, *eh = NULL; + proto_item *sa = NULL, *en = NULL, *eh = NULL; + gboolean item_added = FALSE; nstime_t ns; - pkg_data = register_p_mul_id (pinfo, pdu_type, message_id, seq_no, + pkg_data = register_p_mul_id (pinfo, src, 0, pdu_type, message_id, seq_no, no_missing); if (!pkg_data) { @@ -451,70 +643,59 @@ static p_mul_id_val *p_mul_add_seq_ack (tvbuff_t *tvb, packet_info *pinfo, return NULL; } - en = proto_tree_add_text (p_mul_tree, tvb, 0, 0, "SEQ/ACK analysis"); - PROTO_ITEM_SET_GENERATED (en); - analysis_tree = proto_item_add_subtree (en, ett_analysis); + sa = proto_tree_add_text (p_mul_tree, tvb, 0, 0, "SEQ analysis"); + PROTO_ITEM_SET_GENERATED (sa); + analysis_tree = proto_item_add_subtree (sa, ett_seq_analysis); - if ((pdu_type == Address_PDU) || (pdu_type == Data_PDU) || - (pdu_type == Discard_Message_PDU)) - { - if (pdu_type == Address_PDU) { - if (pkg_data->ack_id) { - en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb, - 0, 0, pkg_data->ack_id); - PROTO_ITEM_SET_GENERATED (en); - } else if (!pkg_data->msg_resend_count) { - en = proto_tree_add_item (analysis_tree, - hf_analysis_ack_missing, - tvb, offset, 0, FALSE); - if (pinfo->fd->flags.visited) { - /* We do not know this on first visit and we do not want to - add a entry in the "Expert Severity Info" for this note */ - expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, - "Ack PDU missing"); - PROTO_ITEM_SET_GENERATED (en); - } - } - } else { - if (pkg_data->addr_id) { - en = proto_tree_add_uint (analysis_tree, hf_analysis_addr_pdu_num, tvb, - 0, 0, pkg_data->addr_id); - PROTO_ITEM_SET_GENERATED (en); - - nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->addr_time); - en = proto_tree_add_time (analysis_tree, hf_analysis_addr_pdu_time, - tvb, 0, 0, &ns); - PROTO_ITEM_SET_GENERATED (en); - } else if (!pkg_data->msg_resend_count) { - en = proto_tree_add_item (analysis_tree, - hf_analysis_addr_pdu_missing, - tvb, offset, 0, FALSE); - expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, - "Address PDU missing"); - PROTO_ITEM_SET_GENERATED (en); - } + if (pdu_type == Data_PDU || pdu_type == Discard_Message_PDU) { + /* Add reference to Address_PDU */ + if (pkg_data->addr_id) { + en = proto_tree_add_uint (analysis_tree, hf_analysis_addr_pdu_num, tvb, + 0, 0, pkg_data->addr_id); + PROTO_ITEM_SET_GENERATED (en); + + nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->addr_time); + en = proto_tree_add_time (analysis_tree, hf_analysis_addr_pdu_time, + tvb, 0, 0, &ns); + PROTO_ITEM_SET_GENERATED (en); + item_added = TRUE; + } else if (!pkg_data->msg_resend_count) { + en = proto_tree_add_item (analysis_tree, + hf_analysis_addr_pdu_missing, + tvb, offset, 0, FALSE); + expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, + "Address PDU missing"); + PROTO_ITEM_SET_GENERATED (en); + item_added = TRUE; + } + } - if ((pdu_type == Data_PDU) && (pkg_data->prev_pdu_id != pkg_data->addr_id)) { - if (pkg_data->prev_pdu_id) { - en = proto_tree_add_uint (analysis_tree, hf_analysis_prev_pdu_num, tvb, - 0, 0, pkg_data->prev_pdu_id); - PROTO_ITEM_SET_GENERATED (en); - - nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->prev_pdu_time); - en = proto_tree_add_time (analysis_tree, hf_analysis_prev_pdu_time, - tvb, 0, 0, &ns); - PROTO_ITEM_SET_GENERATED (en); - } else if (!pkg_data->msg_resend_count) { - en = proto_tree_add_item (analysis_tree, - hf_analysis_prev_pdu_missing, - tvb, offset, 0, FALSE); - expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, - "Previous PDU missing"); - PROTO_ITEM_SET_GENERATED (en); - } - } + if ((pdu_type == Data_PDU) && (pkg_data->prev_pdu_id != pkg_data->addr_id)) { + /* Add reference to previous Data_PDU */ + if (pkg_data->prev_pdu_id) { + en = proto_tree_add_uint (analysis_tree, hf_analysis_prev_pdu_num, tvb, + 0, 0, pkg_data->prev_pdu_id); + PROTO_ITEM_SET_GENERATED (en); + + nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->prev_pdu_time); + en = proto_tree_add_time (analysis_tree, hf_analysis_prev_pdu_time, + tvb, 0, 0, &ns); + PROTO_ITEM_SET_GENERATED (en); + item_added = TRUE; + } else if (!pkg_data->msg_resend_count) { + en = proto_tree_add_item (analysis_tree, + hf_analysis_prev_pdu_missing, + tvb, offset, 0, FALSE); + expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, + "Previous PDU missing"); + PROTO_ITEM_SET_GENERATED (en); + item_added = TRUE; } + } + if ((pdu_type == Address_PDU) || (pdu_type == Data_PDU) || + (pdu_type == Discard_Message_PDU)) { + /* Add resend statistics */ if (pkg_data->msg_resend_count) { en = proto_tree_add_uint (analysis_tree, hf_analysis_retrans_no, tvb, 0, 0, pkg_data->msg_resend_count); @@ -543,51 +724,17 @@ static p_mul_id_val *p_mul_add_seq_ack (tvbuff_t *tvb, packet_info *pinfo, /* Time values does not differ, hide the total time */ PROTO_ITEM_SET_HIDDEN (eh); } - } - } else if (pdu_type == Ack_PDU) { - if (pkg_data->msg_type != Ack_PDU) { - en = proto_tree_add_uint (analysis_tree, hf_analysis_addr_pdu_num, - tvb, 0, 0, pkg_data->pdu_id); - PROTO_ITEM_SET_GENERATED (en); - - if (no_missing == 0) { - nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->first_msg_time); - eh = proto_tree_add_time (analysis_tree, hf_analysis_total_time, - tvb, 0, 0, &ns); - PROTO_ITEM_SET_GENERATED (eh); - } + item_added = TRUE; - if (pkg_data->prev_pdu_id) { - en = proto_tree_add_uint (analysis_tree, hf_analysis_last_pdu_num, - tvb, 0, 0, pkg_data->prev_pdu_id); - PROTO_ITEM_SET_GENERATED (en); - - nstime_delta (&ns, &pinfo->fd->abs_ts, &pkg_data->prev_pdu_time); - en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time, - tvb, 0, 0, &ns); - PROTO_ITEM_SET_GENERATED (en); + if (check_col (pinfo->cinfo, COL_INFO)) { + col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ", + pkg_data->pdu_id, pkg_data->msg_resend_count); } - } else { - en = proto_tree_add_item (analysis_tree, hf_analysis_addr_pdu_missing, - tvb, 0, 0, FALSE); - PROTO_ITEM_SET_GENERATED (en); - - expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, - "Address PDU missing"); } - - if (pkg_data->ack_resend_count) { - en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no, - tvb, 0, 0, pkg_data->ack_resend_count); - PROTO_ITEM_SET_GENERATED (en); - - expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE, - "Dup ACK #%d", pkg_data->ack_resend_count); + } - en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from, - tvb, 0, 0, pkg_data->ack_id); - PROTO_ITEM_SET_GENERATED (en); - } + if (!item_added) { + PROTO_ITEM_SET_HIDDEN (sa); } return pkg_data; @@ -601,7 +748,7 @@ static void dissect_reassembled_data (tvbuff_t *tvb, packet_info *pinfo _U_, return; } - switch(decode_option) { + switch (decode_option) { case DECODE_BER: dissect_unknown_ber (pinfo, tvb, 0, tree); break; @@ -619,14 +766,15 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, { proto_tree *p_mul_tree = NULL, *field_tree = NULL, *checksum_tree = NULL; proto_item *ti = NULL, *en = NULL, *len_en = NULL; - p_mul_id_val *pkg_data = NULL; + p_mul_seq_val *pkg_data = NULL; gboolean save_fragmented; fragment_data *frag_msg = NULL; - guint32 message_id = 0; + guint32 message_id = 0, ip; guint16 no_dest = 0, count = 0, len = 0, data_len = 0; guint16 checksum1, checksum2, pdu_length = 0, no_pdus = 0, seq_no = 0; guint8 pdu_type = 0, *value = NULL, map = 0, fec_len; gint i, tot_no_missing = 0, no_missing = 0, offset = 0; + address src, dst; GString *message_id_list = NULL; nstime_t ts; @@ -766,6 +914,8 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, if (pdu_type == Ack_PDU) { /* Source ID of Ack Sender */ + ip = tvb_get_ipv4 (tvb, offset); + SET_ADDRESS (&dst, AT_IPv4, sizeof(ip), ep_memdup (&ip, 4)); proto_tree_add_item (p_mul_tree, hf_source_id_ack, tvb, offset, 4, FALSE); offset += 4; @@ -775,6 +925,8 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, offset += 2; } else { /* Source Id */ + ip = tvb_get_ipv4 (tvb, offset); + SET_ADDRESS (&src, AT_IPv4, sizeof(ip), ep_memdup (&ip, 4)); proto_tree_add_item (p_mul_tree, hf_source_id, tvb, offset, 4, FALSE); offset += 4; @@ -850,6 +1002,8 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, field_tree = proto_item_add_subtree (en, ett_dest_entry); /* Destination Id */ + ip = tvb_get_ipv4 (tvb, offset); + SET_ADDRESS (&dst, AT_IPv4, sizeof(ip), ep_memdup(&ip, 4)); proto_tree_add_item (field_tree, hf_dest_id, tvb, offset, 4, FALSE); offset += 4; @@ -864,6 +1018,11 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, len, plurality (len, "", "s")); offset += len; } + + if (use_seq_ack_analysis) { + add_ack_analysis (tvb, pinfo, field_tree, offset, pdu_type, &src, &dst, + message_id, 0); + } } proto_item_append_text (ti, ", Count of Dest: %u", no_dest); @@ -903,6 +1062,8 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, } /* Source Id */ + ip = tvb_get_ipv4 (tvb, offset); + SET_ADDRESS (&src, AT_IPv4, sizeof(ip), ep_memdup (&ip, 4)); proto_tree_add_item (field_tree, hf_source_id, tvb, offset, 4, FALSE); offset += 4; @@ -924,18 +1085,19 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, if (check_col (pinfo->cinfo, COL_INFO)) { if (i == 0) { - g_string_printf (message_id_list, "%d", message_id); + g_string_printf (message_id_list, "%u", message_id); } else { - g_string_append_printf (message_id_list, ",%d", message_id); + g_string_append_printf (message_id_list, ",%u", message_id); } } if (len > 10) { gint num_seq_no = (len - 10) / 2; + guint16 ack_seq_no, prev_ack_seq_no = 0; for (no_missing = 0; no_missing < num_seq_no; no_missing++) { /* Missing Data PDU Seq Number */ - seq_no = tvb_get_ntohs (tvb, offset); - if ((seq_no != 0) && (no_missing < num_seq_no - 2) && tvb_get_ntohs (tvb, offset + 2) == 0) { + ack_seq_no = tvb_get_ntohs (tvb, offset); + if ((ack_seq_no != 0) && (no_missing < num_seq_no - 2) && tvb_get_ntohs (tvb, offset + 2) == 0) { /* We are handling a range */ guint16 end_seq_no = tvb_get_ntohs (tvb, offset + 4); @@ -943,8 +1105,8 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, tvb, offset, 6, tvb_get_ptr (tvb, offset, 6), "Missing Data PDU Seq Range: %d - %d", - seq_no, end_seq_no); - if (seq_no >= end_seq_no) { + ack_seq_no, end_seq_no); + if (ack_seq_no >= end_seq_no) { proto_item_append_text (en, " (invalid)"); expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN, "Invalid missing sequence range"); @@ -954,37 +1116,55 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, missing_tree = proto_item_add_subtree (en, ett_range_entry); - for (sno = seq_no; sno <= end_seq_no; sno++) { + for (sno = ack_seq_no; sno <= end_seq_no; sno++) { en = proto_tree_add_uint_format (missing_tree, hf_miss_seq_no, tvb, offset, 6, sno, "Missing Data PDU Seq Number: %d", sno); PROTO_ITEM_SET_GENERATED (en); } - tot_no_missing += (end_seq_no - seq_no + 1); + tot_no_missing += (end_seq_no - ack_seq_no + 1); } offset += 6; no_missing += 2; /* Skip the next two */ + prev_ack_seq_no = end_seq_no; } else { /* No range, handle one seq no */ en = proto_tree_add_item (field_tree, hf_miss_seq_no, tvb,offset, 2, FALSE); offset += 2; - if (seq_no == 0) { + if (ack_seq_no == 0) { proto_item_append_text (en, " (invalid)"); expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN, "Invalid missing seq number"); + } else if (ack_seq_no <= prev_ack_seq_no) { + proto_item_append_text (en, " (end of list indicator)"); + } else { + tot_no_missing++; } - tot_no_missing++; + prev_ack_seq_no = ack_seq_no; } } } + + if (use_seq_ack_analysis) { + add_ack_analysis (tvb, pinfo, field_tree, offset, pdu_type, &src, &dst, + message_id, no_missing); + } } + proto_item_append_text (ti, ", Count of Ack: %u", count); if (tvb_length_remaining (tvb, offset) >= 8) { - /* Timestamp Option */ - proto_tree_add_item (p_mul_tree, hf_timestamp_option, tvb, offset, 8, FALSE); + /* Timestamp Option (in units of 100ms) */ + guint64 timestamp; + + timestamp = tvb_get_ntoh64 (tvb, offset); + proto_tree_add_uint64_format (p_mul_tree, hf_timestamp_option, tvb, + offset, 8, timestamp, + "Timestamp: %" G_GINT64_MODIFIER "d.%d second%s (%" G_GINT64_MODIFIER "u)", + timestamp / 10, (int) timestamp % 10, + (timestamp == 10) ? "" : "s", timestamp); offset += 8; } @@ -1029,23 +1209,19 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, /* Add SEQ/ACK analysis entry */ if (use_seq_ack_analysis && (pdu_type <= Discard_Message_PDU) && - (pdu_type != Address_PDU || no_dest != 0)) + (pdu_type != Ack_PDU) && (pdu_type != Address_PDU || no_dest != 0)) { - pkg_data = p_mul_add_seq_ack (tvb, pinfo, p_mul_tree, offset, pdu_type, - message_id, seq_no, tot_no_missing); + pkg_data = add_seq_analysis (tvb, pinfo, p_mul_tree, &src, offset, pdu_type, + message_id, seq_no, tot_no_missing); } if (check_col (pinfo->cinfo, COL_INFO)) { - if (pkg_data) { - if (pdu_type != Ack_PDU && pkg_data->msg_resend_count) { - col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ", - pkg_data->pdu_id, pkg_data->msg_resend_count); - } else if (pdu_type == Ack_PDU && pkg_data->ack_resend_count) { - col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ", - pkg_data->ack_id, pkg_data->ack_resend_count); - } + /* Check if printing Ack-Ack */ + if (pdu_type == Address_PDU && no_dest == 0) { + col_append_str (pinfo->cinfo, COL_INFO, get_type (Ack_Ack_PDU)); + } else { + col_append_str (pinfo->cinfo, COL_INFO, get_type (pdu_type)); } - col_append_str (pinfo->cinfo, COL_INFO, get_type (pdu_type)); if (pdu_type == Address_PDU || pdu_type == Extra_Address_PDU || pdu_type == FEC_Address_PDU || pdu_type == Extra_FEC_Address_PDU) { col_append_fstr (pinfo->cinfo, COL_INFO, ", No PDUs: %u", no_pdus); @@ -1054,7 +1230,9 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, } if (pdu_type == Address_PDU || pdu_type == Extra_Address_PDU || pdu_type == FEC_Address_PDU || pdu_type == Extra_FEC_Address_PDU) { - col_append_fstr (pinfo->cinfo, COL_INFO, ", Count of Dest: %u", no_dest); + if (no_dest > 0) { + col_append_fstr (pinfo->cinfo, COL_INFO, ", Count of Dest: %u", no_dest); + } } else if (pdu_type == Ack_PDU) { if (tot_no_missing) { col_append_fstr (pinfo->cinfo, COL_INFO, ", Missing seq numbers: %u", @@ -1063,7 +1241,7 @@ static void dissect_p_mul (tvbuff_t *tvb, packet_info *pinfo _U_, col_append_fstr (pinfo->cinfo, COL_INFO, ", Count of Ack: %u", count); } if (pdu_type != Ack_PDU) { - col_append_fstr (pinfo->cinfo, COL_INFO, ", MSID: %d", message_id); + col_append_fstr (pinfo->cinfo, COL_INFO, ", MSID: %u", message_id); } else { if (count > 0) { col_append_fstr (pinfo->cinfo, COL_INFO, ", MSID: %s", message_id_list->str); @@ -1128,7 +1306,13 @@ static void p_mul_init_routine (void) g_hash_table_destroy (p_mul_id_hash_table); } - p_mul_id_hash_table = g_hash_table_new (p_mul_id_hash, p_mul_id_hash_equal); + if (p_mul_package_data_list) { + g_list_foreach (p_mul_package_data_list, (GFunc)p_mul_package_data_destroy, NULL); + g_list_free (p_mul_package_data_list); + } + + p_mul_id_hash_table = g_hash_table_new_full (p_mul_id_hash, p_mul_id_hash_equal, NULL, (GDestroyNotify)p_mul_id_value_destroy); + p_mul_package_data_list = NULL; } void proto_register_p_mul (void) @@ -1341,7 +1525,9 @@ void proto_register_p_mul (void) &ett_ack_entry, &ett_range_entry, &ett_checksum, - &ett_analysis, + &ett_seq_analysis, + &ett_ack_analysis, + &ett_seq_ack_analysis, &ett_msg_fragment, &ett_msg_fragments }; |