r""" Information needed to parse *both* tinydns and dnscache logs. """ from struct import pack # A pattern to match the timestamp format that the tai64nlocal program # produces. It appears in both dnscache and tinydns lines, after # they've been piped through tai64nlocal, of course. TIMESTAMP_PAT = r'[\d-]+ [\d:\.]+' # A dictionary mapping query type identifiers, in decimal, to their # friendly names for tinydns. Reference: # # https://en.wikipedia.org/wiki/List_of_DNS_record_types # # This list *should* be exhaustive, and we hope it is, because the log # parser will now crash if it encounters a type it doesn't know about. QUERY_TYPE_NAME = { 1: "a", 2: "ns", 3: "md", 4: "mf", 5: "cname", 6: "soa", 7: "mb", 8: "mg", 9: "mr", 10: "null", 11: "wks", 12: "ptr", 13: "hinfo", 14: "minfo", 15: "mx", 16: "txt", 17: "rp", 18: "afsdb", 19: "x25", 20: "isdn", 21: "rt", 22: "nsap", 23: "nsap-ptr", 24: "sig", 25: "key", 26: "px", 27: "gpos", 28: "aaaa", 29: "loc", 30: "nxt", 31: "eid", 32: "nimloc", 33: "srv", 34: "atma", 35: "naptr", 36: "kx", 37: "cert", 38: "a6", 39: "dname", 40: "sink", 41: "opt", 42: "apl", 43: "ds", 44: "sshfp", 45: "ipseckey", 46: "rrsig", 47: "nsec", 48: "dnskey", 49: "dhcid", 50: "nsec3", 51: "nsec3param", 52: "tlsa", 53: "smimea", 55: "hip", 56: "ninfo", 57: "rkey", 58: "talink", 59: "cds", 60: "cdnskey", 61: "openpgpkey", 62: "csync", 63: "zonemd", 64: "svcb", 65: "https", 99: "spf", 100: "uinfo", 101: "uid", 102: "gid", 103: "unspec", 104: "nid", 105: "l32", 106: "l64", 107: "lp", 108: "eui48", 109: "euc64", 249: "tkey", 250: "tsig", 251: "ixfr", 252: "axfr", 253: "mailb", 254: "maila", 255: "any", 256: "uri", 257: "caa", 259: "doa", 32768: "ta", 32769: "dlv" } def convert_ip(ip : str) -> str: r""" Convert a hex string representing an IP address to human-readable form. Parameters ---------- ip : str The hexadecimal representation of either an IPv4 or an IPv6 address. Returns ------- The usual decimal dotted-quad representation is returned for an IPv4 address. IPv6 addresses are returned almost as-is, but with colons inserted in the appropriate places, between every four characters. Examples -------- >>> convert_ip("7f000001") '127.0.0.1' >>> convert_ip("00000000000000000000ffff7f000001") '0000:0000:0000:0000:0000:ffff:7f00:0001' """ if len(ip) == 8: # IPv4, eg. "7f000001" -> "7f 00 00 01" -> "127.0.0.1" return ".".join(map(str, pack(">L", int(ip, 16)))) # IPv6 is actually simpler -- it's just a string-slicing operation. return ":".join([ip[(4*i) : (4*i+4)] for i in range(8)])