aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--doc/tshark.pod5
-rw-r--r--epan/dissectors/packet-dns.c196
-rw-r--r--epan/stats_tree.h2
-rw-r--r--ui/gtk/main_menubar.c4
-rw-r--r--ui/qt/main_window.h1
-rw-r--r--ui/qt/main_window.ui11
-rw-r--r--ui/qt/main_window_slots.cpp6
8 files changed, 214 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index e8bd538bc5..f80120bc8a 100644
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,12 @@ What's New
+ The VoIP Calls and SIP Flows dialogs have been added.
+ Support for HiDPI / Retina displays has been improved in the
official packages.
+ * DNS stats:
+ + A new stats tree has been added to the Statistics menu. Now it
+ is possible to collect stats such as qtype/qclass distribution,
+ number of resource record per response section, and stats data
+ (min, max, avg) for values such as query name length or DNS
+ payload.
The following features are new (or have been significantly updated)
since version 1.12.0:
diff --git a/doc/tshark.pod b/doc/tshark.pod
index c1a9aa6f67..c7b79e61cc 100644
--- a/doc/tshark.pod
+++ b/doc/tshark.pod
@@ -958,6 +958,11 @@ Several fields with same name within one diameter message are supported, e.g. I<
Note: B<tshark -q> option is recommended to suppress default B<tshark> output.
+=item B<-z> dns,tree[,I<filter>]
+
+Create a summary of the captured DNS packets. General information are collected such as qtype and qclass distribution.
+For some data (as qname length or DNS payload) max, min and average values are also displayed.
+
=item B<-z> endpoints,I<type>[,I<filter>]
Create a table that lists all endpoints that could be seen in the
diff --git a/epan/dissectors/packet-dns.c b/epan/dissectors/packet-dns.c
index 5f2eed4ed1..cb9ce44781 100644
--- a/epan/dissectors/packet-dns.c
+++ b/epan/dissectors/packet-dns.c
@@ -42,10 +42,68 @@
#include <epan/strutil.h>
#include <epan/expert.h>
#include <epan/afn.h>
+#include <epan/tap.h>
+#include <epan/stats_tree.h>
void proto_register_dns(void);
void proto_reg_handoff_dns(void);
+struct DnsTap {
+ guint packet_qr;
+ guint packet_qtype;
+ guint packet_qclass;
+ guint packet_rcode;
+ guint packet_opcode;
+ guint payload_size;
+ guint qname_len;
+ guint qname_labels;
+ guint nquestions;
+ guint nanswers;
+ guint nauthorities;
+ guint nadditionals;
+};
+
+static int dns_tap = -1;
+
+static const guint8* st_str_packets = "Total Packets";
+static const guint8* st_str_packet_qr = "Query/Response";
+static const guint8* st_str_packet_qtypes = "Query Type";
+static const guint8* st_str_packet_qclasses = "Class";
+static const guint8* st_str_packet_rcodes = "rcode";
+static const guint8* st_str_packet_opcodes = "opcodes";
+static const guint8* st_str_packets_avg_size = "Payload size";
+static const guint8* st_str_query_stats = "Query Stats";
+static const guint8* st_str_query_qname_len = "Qname Len";
+static const guint8* st_str_query_domains = "Label Stats";
+static const guint8* st_str_query_domains_l1 = "1st Level";
+static const guint8* st_str_query_domains_l2 = "2nd Level";
+static const guint8* st_str_query_domains_l3 = "3rd Level";
+static const guint8* st_str_query_domains_lmore = "4th Level or more";
+static const guint8* st_str_response_stats = "Response Stats";
+static const guint8* st_str_response_nquestions = "no. of questions";
+static const guint8* st_str_response_nanswers = "no. of answers";
+static const guint8* st_str_response_nauthorities = "no. of authorities";
+static const guint8* st_str_response_nadditionals = "no. of additionals";
+static int st_node_packets = -1;
+static int st_node_packet_qr = -1;
+static int st_node_packet_qtypes = -1;
+static int st_node_packet_qclasses = -1;
+static int st_node_packet_rcodes = -1;
+static int st_node_packet_opcodes = -1;
+static int st_node_packets_avg_size = -1;
+static int st_node_query_stats = -1;
+static int st_node_query_qname_len = -1;
+static int st_node_query_domains = -1;
+static int st_node_query_domains_l1 = -1;
+static int st_node_query_domains_l2 = -1;
+static int st_node_query_domains_l3 = -1;
+static int st_node_query_domains_lmore = -1;
+static int st_node_response_stats = -1;
+static int st_node_response_nquestions = -1;
+static int st_node_response_nanswers = -1;
+static int st_node_response_nauthorities = -1;
+static int st_node_response_nadditionals = -1;
+
static int proto_dns = -1;
static int hf_dns_length = -1;
static int hf_dns_flags = -1;
@@ -742,6 +800,11 @@ http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cnc
which discuss them to some extent. */
/* http://www.iana.org/assignments/dns-parameters (last updated 2014-08-12)*/
+static const value_string dns_qr_vals[] = {
+ { 0, "Query" },
+ { 1, "Response" },
+ { 0, NULL }
+};
static const value_string dns_types_vals[] = {
{ 0, "Unused" },
{ T_A, "A" },
@@ -1004,6 +1067,27 @@ const value_string dns_classes[] = {
{0,NULL}
};
+
+/* This function counts how many '.' are in the string, plus 1, in order to count the number
+ * of labels
+ */
+guint
+qname_labels_count(const guchar* name, guint name_len)
+{
+ guint labels = 0;
+ unsigned i;
+
+ if (name_len > 1) {
+ /* it was not a Zero-length name */
+ for (i = 0; i < strlen(name); i++) {
+ if (name[i] == '.')
+ labels++;
+ }
+ labels++;
+ }
+ return labels;
+}
+
/* This function returns the number of bytes consumed and the expanded string
* in *name.
* The string is allocated with wmem_packet_scope scope and does not need to be freed.
@@ -1280,7 +1364,6 @@ dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
int type;
int dns_class;
int qu;
- unsigned i;
const char *type_name;
int data_start;
guint16 labels;
@@ -1291,6 +1374,7 @@ dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
len = get_dns_name_type_class(tvb, offset, dns_data_offset, &name, &name_len,
&type, &dns_class);
+
if (is_mdns) {
/* Split the QU flag and the class */
qu = dns_class & C_QU;
@@ -1325,17 +1409,7 @@ dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
tq = proto_tree_add_uint(q_tree, hf_dns_qry_name_len, tvb, offset, name_len, name_len > 1 ? (guint32)strlen(name) : 0);
PROTO_ITEM_SET_GENERATED(tq);
- /* Count how many '.' are in the string, plus 1, in order to count the number
- of labels */
- labels = 0;
- if (name_len > 1) {
- /* it was not a Zero-length name */
- for (i = 0; i < strlen(name); i++) {
- if (name[i] == '.')
- labels++;
- }
- labels++;
- }
+ labels = qname_labels_count(name, name_len);
tq = proto_tree_add_uint(q_tree, hf_dns_count_labels, tvb, offset, name_len, labels);
PROTO_ITEM_SET_GENERATED(tq);
@@ -1652,6 +1726,7 @@ dissect_dns_answer(tvbuff_t *tvb, int offsetx, int dns_data_offset,
len = get_dns_name_type_class(tvb, offsetx, dns_data_offset, &name, &name_len,
&dns_type, &dns_class);
+
data_offset += len;
cur_offset += len;
if (is_mdns) {
@@ -3582,12 +3657,16 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
dns_conv_info_t *dns_info;
dns_transaction_t *dns_trans;
wmem_tree_key_t key[3];
+ struct DnsTap *dns_stats;
+ guint qtype = 0;
+ guint qclass = 0;
+ const guchar *name;
+ int name_len;
dns_data_offset = offset;
col_clear(pinfo->cinfo, COL_INFO);
-
/* To do: check for errs, etc. */
id = tvb_get_ntohs(tvb, offset + DNS_ID);
flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
@@ -3809,12 +3888,28 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
cur_off = offset + DNS_HDRLEN;
+ /* Collect stats */
+ dns_stats = wmem_new0(wmem_packet_scope(), struct DnsTap);
+ dns_stats->packet_rcode = rcode;
+ dns_stats->packet_opcode = opcode;
+ dns_stats->packet_qr = flags >> 15;
+ get_dns_name_type_class(tvb, cur_off, dns_data_offset, &name, &name_len, &qtype, &qclass);
+ dns_stats->packet_qtype = qtype;
+ dns_stats->packet_qclass = qclass;
+ dns_stats->payload_size = tvb_captured_length(tvb);
+ dns_stats->nquestions = quest;
+ dns_stats->nanswers = ans;
+ dns_stats->nauthorities = auth;
+ dns_stats->nadditionals = add;
+
if (quest > 0) {
/* If this is a response, don't add information about the queries
to the summary, just add information about the answers. */
cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
(!(flags & F_RESPONSE) ? pinfo->cinfo : NULL),
dns_tree, isupdate, is_mdns);
+ dns_stats->qname_len = name_len;
+ dns_stats->qname_labels = qname_labels_count(name, name_len);
}
if (ans > 0) {
@@ -3842,6 +3937,7 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
NULL, dns_tree, "Additional records",
pinfo, is_mdns);
}
+ tap_queue_packet(dns_tap, pinfo, dns_stats);
}
static void
@@ -3909,6 +4005,76 @@ dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
return tvb_reported_length(tvb);
}
+static void dns_stats_tree_init(stats_tree* st)
+{
+ st_node_packets = stats_tree_create_node(st, st_str_packets, 0, TRUE);
+ st_node_packet_qr = stats_tree_create_pivot(st, st_str_packet_qr, st_node_packets);
+ st_node_packet_qtypes = stats_tree_create_pivot(st, st_str_packet_qtypes, st_node_packets);
+ st_node_packet_qclasses = stats_tree_create_pivot(st, st_str_packet_qclasses, st_node_packets);
+ st_node_packet_rcodes = stats_tree_create_pivot(st, st_str_packet_rcodes, st_node_packets);
+ st_node_packet_opcodes = stats_tree_create_pivot(st, st_str_packet_opcodes, st_node_packets);
+ st_node_packets_avg_size = stats_tree_create_node(st, st_str_packets_avg_size, 0, FALSE);
+ st_node_query_stats = stats_tree_create_node(st, st_str_query_stats, 0, TRUE);
+ st_node_query_qname_len = stats_tree_create_node(st, st_str_query_qname_len, st_node_query_stats, FALSE);
+ st_node_query_domains = stats_tree_create_node(st, st_str_query_domains, st_node_query_stats, TRUE);
+ st_node_query_domains_l1 = stats_tree_create_node(st, st_str_query_domains_l1, st_node_query_domains, FALSE);
+ st_node_query_domains_l2 = stats_tree_create_node(st, st_str_query_domains_l2, st_node_query_domains, FALSE);
+ st_node_query_domains_l3 = stats_tree_create_node(st, st_str_query_domains_l3, st_node_query_domains, FALSE);
+ st_node_query_domains_lmore = stats_tree_create_node(st, st_str_query_domains_lmore, st_node_query_domains, FALSE);
+ st_node_response_stats = stats_tree_create_node(st, st_str_response_stats, 0, TRUE);
+ st_node_response_nquestions = stats_tree_create_node(st, st_str_response_nquestions,
+ st_node_response_stats, FALSE);
+ st_node_response_nanswers = stats_tree_create_node(st, st_str_response_nanswers,
+ st_node_response_stats, FALSE);
+ st_node_response_nauthorities = stats_tree_create_node(st, st_str_response_nauthorities,
+ st_node_response_stats, FALSE);
+ st_node_response_nadditionals = stats_tree_create_node(st, st_str_response_nadditionals,
+ st_node_response_stats, FALSE);
+}
+
+static int dns_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p)
+{
+ struct DnsTap *pi = (struct DnsTap *)p;
+ tick_stat_node(st, st_str_packets, 0, FALSE);
+ stats_tree_tick_pivot(st, st_node_packet_qr,
+ val_to_str(pi->packet_qr, dns_qr_vals, "Unknown qr (%d)"));
+ stats_tree_tick_pivot(st, st_node_packet_qtypes,
+ val_to_str(pi->packet_qtype, dns_types_description_vals, "Unknown packet type (%d)"));
+ stats_tree_tick_pivot(st, st_node_packet_qclasses,
+ val_to_str(pi->packet_qclass, dns_classes, "Unknown class (%d)"));
+ stats_tree_tick_pivot(st, st_node_packet_rcodes,
+ val_to_str(pi->packet_rcode, rcode_vals, "Unknown rcode (%d)"));
+ stats_tree_tick_pivot(st, st_node_packet_opcodes,
+ val_to_str(pi->packet_opcode, opcode_vals, "Unknown opcode (%d)"));
+ avg_stat_node_add_value(st, st_str_packets_avg_size, 0, FALSE,
+ pi->payload_size);
+
+ /* split up stats for queries and responses */
+ if (pi->packet_qr == 0) {
+ avg_stat_node_add_value(st, st_str_query_qname_len, 0, FALSE, pi->qname_len);
+ switch(pi->qname_labels) {
+ case 1:
+ tick_stat_node(st, st_str_query_domains_l1, 0, FALSE);
+ break;
+ case 2:
+ tick_stat_node(st, st_str_query_domains_l2, 0, FALSE);
+ break;
+ case 3:
+ tick_stat_node(st, st_str_query_domains_l3, 0, FALSE);
+ break;
+ default:
+ tick_stat_node(st, st_str_query_domains_lmore, 0, FALSE);
+ break;
+ }
+ } else {
+ avg_stat_node_add_value(st, st_str_response_nquestions, 0, FALSE, pi->nquestions);
+ avg_stat_node_add_value(st, st_str_response_nanswers, 0, FALSE, pi->nanswers);
+ avg_stat_node_add_value(st, st_str_response_nauthorities, 0, FALSE, pi->nauthorities);
+ avg_stat_node_add_value(st, st_str_response_nadditionals, 0, FALSE, pi->nadditionals);
+ }
+ return 1;
+}
+
void
proto_reg_handoff_dns(void)
{
@@ -3924,6 +4090,7 @@ proto_reg_handoff_dns(void)
if (!Initialized) {
dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
dns_tcp_handle = new_create_dissector_handle(dissect_dns_tcp, proto_dns);
+ stats_tree_register("dns", "dns", "DNS", 0, dns_stats_tree_packet, dns_stats_tree_init, NULL);
Initialized = TRUE;
} else {
@@ -5389,7 +5556,10 @@ proto_register_dns(void)
&dns_use_for_addr_resolution);
dns_tsig_dissector_table = register_dissector_table("dns.tsig.mac", "DNS TSIG MAC Dissectors", FT_STRING, BASE_NONE);
+
+ dns_tap = register_tap("dns");
}
+
/*
* Editor modelines
*
diff --git a/epan/stats_tree.h b/epan/stats_tree.h
index 15a150e6d3..ce0beeb098 100644
--- a/epan/stats_tree.h
+++ b/epan/stats_tree.h
@@ -33,7 +33,7 @@
#define STAT_TREE_ROOT "root"
-#define ST_FLG_AVERAGE 0x10000000 /* Calculate overages for nodes, rather than totals */
+#define ST_FLG_AVERAGE 0x10000000 /* Calculate averages for nodes, rather than totals */
#define ST_FLG_ROOTCHILD 0x20000000 /* This node is a direct child of the root node */
#define ST_FLG_DEF_NOEXPAND 0x01000000 /* This node should not be expanded by default */
#define ST_FLG_SORT_DESC 0x00800000 /* When sorting, sort ascending instead of decending */
diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c
index 0c43918ae2..e98795bbfd 100644
--- a/ui/gtk/main_menubar.c
+++ b/ui/gtk/main_menubar.c
@@ -1043,6 +1043,7 @@ static const char *ui_desc_menubar =
" </menu>\n"
" <menuitem name='Collectd' action='/Statistics/collectd'/>\n"
" <menuitem name='Compare' action='/Statistics/compare'/>\n"
+" <menuitem name= 'DNS' action='/Statistics/dns'/>\n"
" <menuitem name='FlowGraph' action='/Statistics/FlowGraph'/>\n"
" <menuitem name='HART-IP' action='/Statistics/hart_ip'/>\n"
" <menu name= 'HTTPMenu' action='/Statistics/HTTP'>\n"
@@ -1473,16 +1474,15 @@ static const GtkActionEntry main_menu_bar_entries[] = {
{ "/Statistics/BACnet/bacapp_ip", NULL, "Packets sorted by IP", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/BACnet/bacapp_objectid", NULL, "Packets sorted by Object Type", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/BACnet/bacapp_service", NULL, "Packets sorted by Service", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
-
{ "/Statistics/collectd", NULL, "Collectd...", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/compare", NULL, "Compare...", NULL, NULL, G_CALLBACK(gtk_comparestat_cb) },
+ { "/Statistics/dns", NULL, "DNS", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/FlowGraph", WIRESHARK_STOCK_FLOW_GRAPH, "Flo_w Graph...", NULL, NULL, G_CALLBACK(flow_graph_launch) },
{ "/Statistics/hart_ip", NULL, "HART-IP", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/HTTP", NULL, "HTTP", NULL, NULL, NULL },
{ "/Statistics/HTTP/http", NULL, "Packet Counter", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/HTTP/http_req", NULL, "Requests", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
{ "/Statistics/HTTP/http_srv", NULL, "Load Distribution", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
-
{ "/Statistics/ONC-RPC-Programs", NULL, "ONC-RPC Programs", NULL, NULL, G_CALLBACK(gtk_rpcprogs_cb) },
{ "/Statistics/Sametime", NULL, "Sametime", NULL, NULL, NULL },
{ "/Statistics/Sametime/sametime", NULL, "Messages", NULL, NULL, G_CALLBACK(gtk_stats_tree_cb) },
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 3047f27290..4bf11a30d7 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -417,6 +417,7 @@ private slots:
void statCommandIOGraph(const char *arg = NULL, void *userdata = NULL);
void on_actionStatisticsIOGraph_triggered();
void on_actionStatisticsSametime_triggered();
+ void on_actionStatisticsDNS_triggered();
void openVoipCallsDialog(bool all_flows = false);
void on_actionTelephonyVoipCalls_triggered();
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 4425a0ab7b..d9e8b78b55 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -434,6 +434,7 @@
<addaction name="actionStatisticsANCP"/>
<addaction name="menuBACnet"/>
<addaction name="actionStatisticsCollectd"/>
+ <addaction name="actionStatisticsDNS"/>
<addaction name="actionStatisticsFlowGraph"/>
<addaction name="actionStatisticsHART_IP"/>
<addaction name="menuHTTP"/>
@@ -1559,6 +1560,14 @@
<string>Collectd statistics</string>
</property>
</action>
+ <action name="actionStatisticsDNS">
+ <property name="text">
+ <string>DNS</string>
+ </property>
+ <property name="toolTip">
+ <string>DNS statistics</string>
+ </property>
+ </action>
<action name="actionStatisticsHART_IP">
<property name="text">
<string>HART-IP</string>
@@ -1606,7 +1615,7 @@
<property name="toolTip">
<string>Sametime statistics</string>
</property>
- </action>
+ </action>
<action name="actionTelephonyISUPMessages">
<property name="text">
<string>&amp;ISUP Messages</string>
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index 4407290688..a9579e9290 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -2365,11 +2365,17 @@ void MainWindow::on_actionStatisticsIOGraph_triggered()
{
statCommandIOGraph(NULL, NULL);
}
+
void MainWindow::on_actionStatisticsSametime_triggered()
{
openStatisticsTreeDialog("sametime");
}
+void MainWindow::on_actionStatisticsDNS_triggered()
+{
+ openStatisticsTreeDialog("dns");
+}
+
// Telephony Menu
void MainWindow::openVoipCallsDialog(bool all_flows)