aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dns.c
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2017-11-21 14:47:21 -0500
committerAnders Broman <a.broman58@gmail.com>2017-11-22 09:07:30 +0000
commit8d5726dccc6851aa99707f4ff3cf9d11128cd822 (patch)
tree53a9263130569696f3ba3eecef8c6201ef970bd8 /epan/dissectors/packet-dns.c
parenta501321cbbe2a23faa04031ba1567be3d305daee (diff)
Add support to handle DNS retransmissions
Add a preference to the DNS dissector to specify how many seconds can elapse before a DNS query is considered a retransmission because the transaction ID is shared with a previous request. If retransmission is found, add expert info and hf_ field linking to the original request. If a retransmission of a response is found, add expert info and hf_ field linking to the original response. Bug: 14178 Bug: 13313 Change-Id: Idd77ab7f7638f5056d5690633c787a4d52285aee Reviewed-on: https://code.wireshark.org/review/24525 Reviewed-by: Michael Mann <mmann78@netscape.net> Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-dns.c')
-rw-r--r--epan/dissectors/packet-dns.c115
1 files changed, 95 insertions, 20 deletions
diff --git a/epan/dissectors/packet-dns.c b/epan/dissectors/packet-dns.c
index 2b184e2193..d3b8006dc4 100644
--- a/epan/dissectors/packet-dns.c
+++ b/epan/dissectors/packet-dns.c
@@ -340,6 +340,8 @@ static int hf_dns_tsig_other_len = -1;
static int hf_dns_tsig_other_data = -1;
static int hf_dns_response_in = -1;
static int hf_dns_response_to = -1;
+static int hf_dns_retransmit_request_in = -1;
+static int hf_dns_retransmit_response_in = -1;
static int hf_dns_time = -1;
static int hf_dns_sshfp_algorithm = -1;
static int hf_dns_sshfp_fingerprint_type = -1;
@@ -426,6 +428,8 @@ static expert_field ei_ttl_negative = EI_INIT;
static expert_field ei_dns_tsig_alg = EI_INIT;
static expert_field ei_dns_undecoded_option = EI_INIT;
static expert_field ei_dns_key_id_buffer_too_short = EI_INIT;
+static expert_field ei_dns_retransmit_request = EI_INIT;
+static expert_field ei_dns_retransmit_response = EI_INIT;
static dissector_table_t dns_tsig_dissector_table=NULL;
@@ -434,6 +438,11 @@ static dissector_handle_t dns_handle;
/* desegmentation of DNS over TCP */
static gboolean dns_desegment = TRUE;
+/* Maximum number of elapsed seconds between messages with the same
+ * transaction ID to be considered as a retransmission
+ */
+static guint32 retransmission_timer = 5;
+
/* Dissector handle for GSSAPI */
static dissector_handle_t gssapi_handle;
static dissector_handle_t ntlmssp_handle;
@@ -3646,7 +3655,7 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
int offset = is_tcp ? 2 : 0;
int dns_data_offset;
proto_tree *dns_tree, *field_tree;
- proto_item *ti, *tf;
+ proto_item *ti, *tf, *transaction_item;
guint16 flags, opcode, rcode, quest, ans, auth, add;
guint id;
int cur_off;
@@ -3658,6 +3667,7 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
struct DnsTap *dns_stats;
guint qtype = 0;
guint qclass = 0;
+ gboolean retransmission = FALSE;
const guchar *name;
int name_len;
@@ -3729,30 +3739,65 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (!pinfo->fd->flags.visited) {
if (!(flags&F_RESPONSE)) {
/* This is a request */
- dns_trans=wmem_new(wmem_file_scope(), dns_transaction_t);
- dns_trans->req_frame=pinfo->num;
- dns_trans->rep_frame=0;
- dns_trans->req_time=pinfo->abs_ts;
- dns_trans->id = id;
- wmem_tree_insert32_array(dns_info->pdus, key, (void *)dns_trans);
+ gboolean new_transaction = FALSE;
+
+ /* Check if we've seen this transaction before */
+ dns_trans=(dns_transaction_t *)wmem_tree_lookup32_array_le(dns_info->pdus, key);
+ if ((dns_trans == NULL) || (dns_trans->id != id) || (dns_trans->rep_frame > 0)) {
+ new_transaction = TRUE;
+ } else {
+ nstime_t request_delta;
+
+ /* Has not enough time elapsed that we consider this request a retransmission? */
+ nstime_delta(&request_delta, &pinfo->abs_ts, &dns_trans->req_time);
+ if ((guint32)nstime_to_sec(&request_delta) < retransmission_timer) {
+ retransmission = TRUE;
+ } else {
+ new_transaction = TRUE;
+ }
+ }
+
+ if (new_transaction) {
+ dns_trans=wmem_new(wmem_file_scope(), dns_transaction_t);
+ dns_trans->req_frame=pinfo->num;
+ dns_trans->rep_frame=0;
+ dns_trans->req_time=pinfo->abs_ts;
+ dns_trans->id = id;
+ wmem_tree_insert32_array(dns_info->pdus, key, (void *)dns_trans);
+ }
} else {
dns_trans=(dns_transaction_t *)wmem_tree_lookup32_array_le(dns_info->pdus, key);
if (dns_trans) {
if (dns_trans->id != id) {
dns_trans = NULL;
- } else {
+ } else if (dns_trans->rep_frame == 0) {
dns_trans->rep_frame=pinfo->num;
+ } else {
+ retransmission = TRUE;
}
}
}
} else {
dns_trans=(dns_transaction_t *)wmem_tree_lookup32_array_le(dns_info->pdus, key);
- if (dns_trans && dns_trans->id != id) {
- dns_trans = NULL;
+ if (dns_trans) {
+ if (dns_trans->id != id) {
+ dns_trans = NULL;
+ } else if ((!(flags & F_RESPONSE)) && (dns_trans->req_frame != pinfo->num)) {
+ /* This is a request retransmission, create a "fake" dns_trans structure*/
+ dns_transaction_t *retrans_dns = wmem_new(wmem_packet_scope(), dns_transaction_t);
+ retrans_dns->req_frame=dns_trans->req_frame;
+ retrans_dns->rep_frame=0;
+ retrans_dns->req_time=pinfo->abs_ts;
+ dns_trans = retrans_dns;
+
+ retransmission = TRUE;
+ } else if ((flags & F_RESPONSE) && (dns_trans->rep_frame != pinfo->num)) {
+ retransmission = TRUE;
+ }
}
}
if (!dns_trans) {
- /* create a "fake" pana_trans structure */
+ /* create a "fake" dns_trans structure */
dns_trans=wmem_new(wmem_packet_scope(), dns_transaction_t);
dns_trans->req_frame=0;
dns_trans->rep_frame=0;
@@ -3764,7 +3809,7 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, ENC_BIG_ENDIAN);
}
- proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
+ transaction_item = proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
offset + DNS_ID, 2, id);
tf = proto_tree_add_item(dns_tree, hf_dns_flags, tvb,
@@ -3888,9 +3933,14 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* print state tracking in the tree */
if (!(flags&F_RESPONSE)) {
+ proto_item *it;
/* This is a request */
- if (dns_trans->rep_frame) {
- proto_item *it;
+ if ((retransmission) && (dns_trans->req_frame)) {
+ expert_add_info_format(pinfo, transaction_item, &ei_dns_retransmit_request, "DNS query retransmission. Original request in frame %d", dns_trans->req_frame);
+
+ it=proto_tree_add_uint(dns_tree, hf_dns_retransmit_request_in, tvb, 0, 0, dns_trans->req_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+ } else if (dns_trans->rep_frame) {
it=proto_tree_add_uint(dns_tree, hf_dns_response_in, tvb, 0, 0, dns_trans->rep_frame);
PROTO_ITEM_SET_GENERATED(it);
@@ -3899,14 +3949,21 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* This is a reply */
if (dns_trans->req_frame) {
proto_item *it;
- nstime_t ns;
+ if ((retransmission) && (dns_trans->rep_frame)) {
+ expert_add_info_format(pinfo, transaction_item, &ei_dns_retransmit_response, "DNS response retransmission. Original response in frame %d", dns_trans->rep_frame);
- it=proto_tree_add_uint(dns_tree, hf_dns_response_to, tvb, 0, 0, dns_trans->req_frame);
- PROTO_ITEM_SET_GENERATED(it);
+ it=proto_tree_add_uint(dns_tree, hf_dns_retransmit_response_in, tvb, 0, 0, dns_trans->rep_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+ } else {
+ nstime_t ns;
- nstime_delta(&ns, &pinfo->abs_ts, &dns_trans->req_time);
- it=proto_tree_add_time(dns_tree, hf_dns_time, tvb, 0, 0, &ns);
- PROTO_ITEM_SET_GENERATED(it);
+ it=proto_tree_add_uint(dns_tree, hf_dns_response_to, tvb, 0, 0, dns_trans->req_frame);
+ PROTO_ITEM_SET_GENERATED(it);
+
+ nstime_delta(&ns, &pinfo->abs_ts, &dns_trans->req_time);
+ it=proto_tree_add_time(dns_tree, hf_dns_time, tvb, 0, 0, &ns);
+ PROTO_ITEM_SET_GENERATED(it);
+ }
}
}
@@ -5257,6 +5314,16 @@ proto_register_dns(void)
FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
"This is a response to the DNS query in this frame", HFILL }},
+ { &hf_dns_retransmit_request_in,
+ { "Retransmitted request. Original request in", "dns.retransmit_request_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This is a retransmitted DNS query", HFILL }},
+
+ { &hf_dns_retransmit_response_in,
+ { "Retransmitted response. Original response in", "dns.retransmit_response_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This is a retransmitted DNS response", HFILL }},
+
{ &hf_dns_time,
{ "Time", "dns.time",
FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
@@ -5575,6 +5642,8 @@ proto_register_dns(void)
{ &ei_ttl_negative, { "dns.ttl.negative", PI_PROTOCOL, PI_WARN, "TTL can't be negative", EXPFILL }},
{ &ei_dns_tsig_alg, { "dns.tsig.noalg", PI_UNDECODED, PI_WARN, "No dissector for algorithm", EXPFILL }},
{ &ei_dns_key_id_buffer_too_short, { "dns.key_id_buffer_too_short", PI_PROTOCOL, PI_WARN, "Buffer too short to compute a key id", EXPFILL }},
+ { &ei_dns_retransmit_request, { "dns.retransmit_request", PI_PROTOCOL, PI_WARN, "DNS query retransmission", EXPFILL }},
+ { &ei_dns_retransmit_response, { "dns.retransmit_response", PI_PROTOCOL, PI_WARN, "DNS response retransmission", EXPFILL }},
};
static gint *ett[] = {
@@ -5613,6 +5682,12 @@ proto_register_dns(void)
" To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
&dns_desegment);
+ prefs_register_uint_preference(dns_module, "retransmission_timer",
+ "Number of seconds allowed between retransmissions",
+ "Number of seconds allowed between DNS requests with the same transaction ID to consider it a retransmission."
+ " Otherwise its considered a new request.",
+ 10, &retransmission_timer);
+
prefs_register_obsolete_preference(dns_module, "use_for_addr_resolution");
prefs_register_static_text_preference(dns_module, "text_use_for_addr_resolution",