Update: Added MIT License
The zone configuration format for BIND has a number of short-cuts that make writing DNS zone files easy, but also make them hard to read. Here is an example:
$TTL 3D
@ SOA server1.example.com. hostmaster.example.com. (1 8H 2H 4W 1D)
NS server1
NS server2
MX 10 server1
MX 20 server2
server1 A 127.0.0.1
server2 A 127.0.0.2
www CNAME server1
Python to the rescue. The dnspython module has support for parsing BIND zones, and rendering them without the shortcuts:
#!/usr/bin/python # bindnorm.py - "normalise" a bind zone file by expanding relative names. # Simeon Miteff <simeon@localloop.co.za> # Tue Sep 23 10:03:35 SAST 2008 # #Copyright (c) 2008 Simeon Miteff # #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to #deal in the Software without restriction, including without limitation the #rights to use, copy, modify, merge, publish, distribute, sublicense, and/or #sell copies of the Software, and to permit persons to whom the Software is #furnished to do so, subject to the following conditions: # #The above copyright notice and this permission notice shall be included in #all copies or substantial portions of the Software. # #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL #THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS #IN THE SOFTWARE. import dns.zone import sys if len(sys.argv)<2: sys.stderr.write("Usage: %s [zone fqdn]\n" % sys.argv[0]) sys.stderr.write("Example: %s example.com < db.example.com > norm.db.example.com\n" % sys.argv[0]) sys.exit(1) zone = dns.zone.from_text(sys.stdin.read(), sys.argv[1], relativize=False, check_origin=False) zone.to_file(sys.stdout, relativize=False)
To use it, you’ll need to install dnspython first. Fortunately, on Debian or Ubuntu, it’s just an apt-get install python-dnspython away. Running this little script with the example zone above as input yields:
example.com. 259200 IN SOA server1.example.com. hostmaster.example.com. 1 28800 7200 2419200 86400
example.com. 259200 IN NS server1.example.com.
example.com. 259200 IN NS server2.example.com.
example.com. 259200 IN MX 10 server1.example.com.
example.com. 259200 IN MX 20 server2.example.com.
server1.example.com. 259200 IN A 127.0.0.1
server2.example.com. 259200 IN A 127.0.0.2
www.example.com. 259200 IN CNAME server1.example.com.
This format is less canonical, but at least each line is context-free. Now you can proceed to grep the output to your heart’s desire :-)

Post a Comment