#!/usr/bin/env python # Maintained at https://code.ffdn.org/zorun/dn42-scripts """This script generates DNS TXT records containing ASN information. The idea comes from asn.cymru.com. Example: dig +short AS1.asn.cymru.com TXT The output looks like this: "1 | US | arin | 2001-09-20 | LVLT-1 - Level 3 Communications, Inc." In dn42, we try to respect this format. Fields 2 and 3 are set to "DN42" and "dn42", respectively. The date field is left empty, as we currently do not record this information in the registry. For the last field, we use "[as-name] [descr]" from the registry. """ import sys import time import argparse from registry import AutNum def gen_zone(args): out = args.output # SOA and stuff out.write("$ORIGIN {}\n".format(args.zone)) out.write("$TTL {}\n".format(args.ttl)) serial = int(time.time()) out.write("@ IN SOA {0.ns[0]} {0.rname} " "({1} {0.refresh} {0.retry} {0.expire} {0.negative})\n".format(args, serial)) # NS for ns in args.ns: out.write("@ NS {}\n".format(ns)) # TXT data autnum = AutNum(args.registry) for (asn, data) in autnum.data.items(): comment = "" if "as-name" in data: comment = data["as-name"][0] if "descr" in data: comment += " " + data["descr"][0] comment.replace('"', '') # Bind and NSD are quite happy with UTF-8 in TXT records, but # KnotDNS isn't (at least Knot 1.4.7). This is a hack to work around this. comment = comment.encode('ascii', errors='xmlcharrefreplace').decode() out.write('{} TXT "{} | DN42 | dn42 | | {}"\n'.format(asn, asn[2:], comment)) def cleanup(args): def final_dot(s): if not s.endswith('.'): return s + "." else: return s args.zone = final_dot(args.zone) args.rname = args.rname.replace("@", ".") args.rname = final_dot(args.rname) for (i, ns) in enumerate(args.ns): args.ns[i] = final_dot(ns) if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("-n", "--ns", action="append", required=True, help="name server, can be passed multiple times (the first one will be listed as master in the SOA)") parser.add_argument("-r", "--rname", required=True, help="contact email of the administrator of the zone") parser.add_argument("-o", "--output", default=sys.stdout, type=argparse.FileType('w'), help="output file (default: stdout)") parser.add_argument("registry", help="path to the monotone registry") opt = parser.add_argument_group("Zone options") opt.add_argument("-z", "--zone", default="asn.dn42.", help="zone to generate data for (default: %(default)s)") opt.add_argument("-t", "--ttl", default="1h", help="TTL for all records (default: %(default)s)") opt.add_argument("--refresh", default="1d", help="refresh timer for slaves (default: %(default)s)") opt.add_argument("--retry", default="1h", help="retry timer for slaves (default: %(default)s)") opt.add_argument("--expire", default="4w", help="expire time for slaves (default: %(default)s)") opt.add_argument("--negative", default="5m", help="negative TTL (default: %(default)s)") args = parser.parse_args() # Sanity checks cleanup(args) gen_zone(args)