aboutsummaryrefslogtreecommitdiffstats
path: root/bin/get_catalog
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-07-12 11:50:39 +0100
committerLexi Winter <lexi@le-fay.org>2025-07-12 11:50:39 +0100
commit801796549782295f49217badfbd7d4ac222cb37a (patch)
tree4f50ff87fc33175ff562c560aa27dafcb0f312c3 /bin/get_catalog
parent2a043adc93836284236ea073362fe6ca232e8474 (diff)
downloaddns-801796549782295f49217badfbd7d4ac222cb37a.tar.gz
dns-801796549782295f49217badfbd7d4ac222cb37a.tar.bz2
bin/get_catalog: use dnspython
Diffstat (limited to 'bin/get_catalog')
-rwxr-xr-xbin/get_catalog95
1 files changed, 54 insertions, 41 deletions
diff --git a/bin/get_catalog b/bin/get_catalog
index d9e744b..772d5b4 100755
--- a/bin/get_catalog
+++ b/bin/get_catalog
@@ -1,41 +1,54 @@
-#! /bin/sh
-#
-# Fetch the catalog zone '$1' from the server '$2' and print a list of zones.
-
-set -e
-
-catalog="$1"
-server="$2"
-
-tempfile="$(mktemp -t catalog)"
-trap 'rm $tempfile' 0
-
-if ! dig "$catalog" axfr @"$server" +noall +answer >"$tempfile"; then
- printf >&2 '%s: query failed\n' "$0"
- exit 1
-fi
-
-# Make sure the result has an SOA, otherwise the query failed.
-if ! awk <"$tempfile" "
-BEGIN {
- exitcode=1
-}
-
-\$1 == \"$catalog.\" && \$4 == \"SOA\" {
- exitcode=0
-}
-
-END {
- exit exitcode
-}
-"; then
- printf >&2 '%s: no SOA found in zone; transfer failed?\n' "$0"
- exit 1
-fi
-
-awk <"$tempfile" "
-\$1 ~ /zones.$catalog/ && \$4 == \"PTR\" {
- zone = \$5
- sub(/\\.$/, \"\", zone)
- print zone
-}"
+#! /usr/bin/env python3
+# vim:set noet sw=8 ts=8 sts=8:
+
+import sys, socket
+import dns.query
+import dns.zone
+import dns.rdatatype
+
+def resolve(hostname):
+ try:
+ addrs = socket.getaddrinfo(
+ hostname, 53, proto=socket.IPPROTO_UDP)
+ return list(dict.fromkeys([addr[4][0] for addr in addrs]))
+ except Exception as e:
+ raise (Exception(f"resolving {hostname}: {e}"))
+
+def axfr(zone, hostname):
+ addrs = resolve(hostname)
+ last_exc = None
+
+ for addr in addrs:
+ try:
+ return dns.zone.from_xfr(dns.query.xfr(addr, zone))
+ except Exception as e:
+ last_exc = e
+ raise (Exception(str(last_exc)))
+
+def print_catalog(zone):
+ for name, node in zone.nodes.items():
+ for rdata in node.rdatasets:
+ if rdata.rdtype == dns.rdatatype.PTR:
+ for ptr in rdata:
+ print(str(ptr.target).rstrip('.'))
+
+
+def main():
+ if len(sys.argv) != 3:
+ print(f"Usage: {sys.argv[0]} <zone> <server>")
+ return 1
+
+ zone_name = sys.argv[1]
+ server = sys.argv[2]
+
+ try:
+ zone = axfr(zone_name, server)
+ print_catalog(zone)
+ except Exception as e:
+ print(f"Zone transfer failed: {e}")
+ return 1
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())