#!/usr/bin/python3
-"""
+r"""
Convert tinydns and dnscache logs to human-readable form
"""
import re, typing
from struct import pack
-from time import strftime, gmtime
-
## Regular expressions for matching tinydns/dnscache log lines. We
## compile these once here rather than within the corresponding
def convert_ip(ip : str) -> str:
- """
+ r"""
Convert a hex string representing an IP address to
human-readable form.
1. clientip:clientport, used by tcpopen/tcpclose entries,
2. clientip:clientport:id, used by "query" entries.
+ We convert each part from hex to decimal, and in the second
+ format, separate the packet id from the client information.
+
Parameters
----------
id = int(chunks[2], 16)
words[i] += f" (id {id})"
-def decode_ip(words, i):
+def decode_ip(words : list, i : int):
+ r"""
+ Helper function to decode the ip field in a dnscache log
+ entry.
+
+ A single "serverip" field is present in the lame, nodata,
+ nxdomain, and rr entry types. We convert it from hex to decimal.
+
+ Parameters
+ ----------
+
+ words : list
+ The ``words`` list (a list of fields) from
+ :func:`handle_dnscache_log`.
+
+ i : int
+ The index of the ip field within ``words``
+
+ Returns
+ -------
+
+ Nothing; the ``i``th entry in the ``words`` list is modified
+ in-place.
+
+ Examples
+ --------
+
+ >>> words = ["foo", "bar", "7f000001", "quux"]
+ >>> decode_ip(words, 2)
+ >>> words
+ ['foo', 'bar', '127.0.0.1', 'quux']
+
+ >>> words = ["foo", "00000000000000000000ffff7f000001", "bar", "quux"]
+ >>> decode_ip(words, 1)
+ >>> words
+ ['foo', '0000:0000:0000:0000:0000:ffff:7f00:0001', 'bar', 'quux']
+ """
words[i] = convert_ip(words[i])
-def decode_ttl(words, i):
+def decode_ttl(words : list, i : int):
+ r"""
+ Helper function to decode the ttl field in a dnscache log
+ entry.
+
+ A single "ttl" field is present in the nodata, nxdomain, and
+ rr entry types. We prefix it with "TTL=" so that its meaning
+ is clear in the human-readable logs.
+
+ Parameters
+ ----------
+
+ words : list
+ The ``words`` list (a list of fields) from
+ :func:`handle_dnscache_log`.
+
+ i : int
+ The index of the ttl field within ``words``
+
+ Returns
+ -------
+
+ Nothing; the ``i``th entry in the ``words`` list is modified
+ in-place.
+
+ Examples
+ --------
+
+ >>> words = ["c0a80101", "20865", "1", "www.example.com.", "5db8d822"]
+ >>> decode_ttl(words, 1)
+ >>> words
+ ['c0a80101', 'TTL=20865', '1', 'www.example.com.', '5db8d822']
+
+ """
words[i] = f"TTL={words[i]}"
-def decode_serial(words, i):
- serial = int(words[i])
- words[i] = f"#{serial}"
+def decode_serial(words : list, i : int):
+ r"""
+ Helper function to decode the serial field in a dnscache log
+ entry.
+
+ A single "serial" field is present in the drop and query entry
+ types. It's already in decimal; we simply prefix it with a hash.
+
+ Parameters
+ ----------
+
+ words : list
+ The ``words`` list (a list of fields) from
+ :func:`handle_dnscache_log`.
+
+ i : int
+ The index of the serial field within ``words``
-def decode_type(words, i):
+ Returns
+ -------
+
+ Nothing; the ``i``th entry in the ``words`` list is modified
+ in-place.
+
+ Examples
+ --------
+
+ >>> words = ["1", "7f000001:a3db:4fb9", "1", "www.example.com."]
+ >>> decode_serial(words, 0)
+ >>> words
+ ['#1', '7f000001:a3db:4fb9', '1', 'www.example.com.']
+
+ """
+ words[i] = f"#{words[i]}"
+
+def decode_type(words : list, i : int):
qt = words[i]
words[i] = query_type.get(int(qt), qt)
-def handle_dnscache_log(line) -> typing.Optional[str]:
- """
+def handle_dnscache_log(line : str) -> typing.Optional[str]:
+ r"""
Handle a single log line if it matches the ``dnscache_log_re`` regex.
Parameters
elif event in ("tcpopen", "tcpclose"):
decode_client(words, 0)
- return f"{timestamp} {event} " + " ".join(words)
+ # Reconstitute "data" (i.e. everything after the timestamp and the
+ # event) from "words", which was originally obtained by splitting
+ # "data".
+ data = " ".join(words)
+ return f"{timestamp} {event} {data}"
def handle_tinydns_log(line : str) -> typing.Optional[str]:
- """
+ r"""
Handle a single log line if it matches the ``tinydns_log_re`` regex.
Parameters