summaryrefslogtreecommitdiffstats
path: root/contrib/queryparse/queryparse
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/queryparse/queryparse')
-rwxr-xr-xcontrib/queryparse/queryparse135
1 files changed, 135 insertions, 0 deletions
diff --git a/contrib/queryparse/queryparse b/contrib/queryparse/queryparse
new file mode 100755
index 0000000..01edeaf
--- /dev/null
+++ b/contrib/queryparse/queryparse
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+#
+# Copyright 2019-2021 OARC, Inc.
+# Copyright 2017-2018 Akamai Technologies
+# Copyright 2006-2016 Nominum, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import dns.message
+import dns.rrset
+import dns.flags
+import dns.name
+import pcapy
+import socket
+import sys
+import struct
+from optparse import OptionParser
+
+
+__author__ = "Nominum, Inc."
+__version__ = "1.0.2.0"
+__date__ = "2007-05-14"
+
+IPHeader = '!BBHHHBBHLL'
+
+IPHDRLEN = 20
+UDPHDRLEN = 8
+LINKTYPE_C_HDLC = 104
+LINKTYPE_ETHERNET = 1
+qtypecount = {}
+
+
+def main(argv):
+ parser = OptionParser(usage="%prog [options]",
+ version = "%prog " + __version__ )
+ parser.add_option("-i", "--input", dest="fin",
+ help="name of tcpdump file to parse", metavar="FILE")
+ parser.add_option("-o", "--output", dest="fout",
+ help="file in which to save parsed DNS queries",
+ metavar="FILE")
+ parser.add_option("-r", "--recursion", dest="recurse", action="store_true",
+ default=False,
+ help="Keep queries whose RD flag is 0 (default: discard)")
+ parser.add_option("-R", "--responses", dest="responses",
+ action="store_true", default=False,
+ help="Parse query responses instead of queries")
+ (opts, args) = parser.parse_args()
+
+ if opts.fin:
+ pcap = pcapy.open_offline(opts.fin)
+ else:
+ pcap = pcapy.open_offline('-')
+ linktype = pcap.datalink()
+ if linktype == LINKTYPE_C_HDLC:
+ IPHDRSTART = 4
+ else:
+ IPHDRSTART = 14
+ if opts.fout:
+ outfile = open(opts.fout, "w")
+ else:
+ outfile = sys.stdout
+ while True:
+ try:
+ packet = pcap.next()
+ except Exception:
+ break
+
+ if packet[0] is None:
+ break
+ packet = packet[1]
+ # Toss the stuff before the IP header
+ packet = packet[IPHDRSTART:]
+
+ # Grab the rest of the packet so we can parse proto
+ iphdr = packet[0:IPHDRLEN]
+ if len(iphdr) < IPHDRLEN:
+ continue
+ (vhl, tos, tlen, ipid, fragoff, ttl, proto, cksum, srcip, dstip) = \
+ struct.unpack(IPHeader, iphdr)
+
+ # Toss the IP header, we're done with it. We need to account
+ # for any IP header options.
+ ihl = (vhl & 0xF) * 4
+ packet = packet[ihl:]
+
+ if proto == socket.IPPROTO_UDP: # UDP, 8-byte header
+ packet = packet[UDPHDRLEN:]
+ else:
+ continue
+
+ try:
+ msg = dns.message.from_wire(packet)
+ except Exception:
+ continue
+ if not opts.recurse and not dns.flags.RD:
+ continue
+ if opts.responses:
+ querytest = msg.flags & dns.flags.QR
+ else:
+ querytest = not (msg.flags & dns.flags.QR)
+ if querytest:
+ for query in msg.question: # handle multiple queries per packet
+ fqdn = query.name.to_text()
+ qtype = dns.rdatatype.to_text(query.rdtype)
+ outfile.write("%s %s\n" % (fqdn, qtype))
+ # add qtype to dict if not present, otherwise increment
+ qtypecount[query.rdtype] = qtypecount.get(query.rdtype, 0) + 1
+
+ if outfile is not sys.stdout:
+ outfile.close()
+ sum = 0
+ print("Statistics:")
+ qtypes = list(qtypecount.keys())
+ qtypes.sort()
+ for qtype in qtypes:
+ qtype_str = dns.rdatatype.to_text(qtype)
+ count = qtypecount[qtype]
+ print(" %10s:\t%d" % (qtype_str, count))
+ sum += count
+ print("-------------------------")
+ print(" TOTAL:\t%d" % sum)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])