# routines om de DNS zone files te genereren uit de exodus configuratie from common import * import time import types def get_soa(): return time.strftime("%Y%m%d%M") # gegeven een lijst met regels, waarbij een regel of een string of een 3-tuple # van strings is, plak de boel achter elkaar en zorg dat de 3-tuples goed # uitlijnen. dit is een beetje gepruts en gehack. ge-evolueerd, niet # ontworpen. def serialize(lines): maxlen = 0 for t in filter(lambda l: type(l) == tuple, lines): if len(t[0]) > maxlen: maxlen = len(t[0]) if (maxlen % 8) == 0: maxlen = maxlen + 1 maxlen = 8 * ((1 + maxlen) / 8) result = '' for l in lines: if type(l) == tuple: first_multiple_of_8 = 8 * (1 + len(l[0]) / 8) extratabs = "\t" * ((maxlen - first_multiple_of_8 + 8) / 8) l = "%s%s %s %s" % (l[0], extratabs, l[1], l[2]) result = result + l + "\n" return result def zoneheader(zone): fname = "%d.172.in-addr.arpa." % zone return "$ORIGIN %s\n" % fname + gen_header(fname).replace('#', ';') + """ $TTL 86400 @ 1D IN SOA ns1.wLeiden.NET. hostmaster.wLeiden.NET. ( %s ; serial (d. adams) 3H ; refresh 15M ; retry 1W ; expiry 1D ) ; minimum IN NS ns1.wLeiden.NET. IN NS ns2.wLeiden.NET. IN NS ns3.wLeiden.NET. IN NS ns4.wLeiden.NET. ns1 IN A 172.21.16.99 ;rambo (lcpl) ns2 IN A 172.17.8.68 ;proxy1 ns3 IN A 172.17.143.4 ;proxy2 ns4 IN A 172.20.128.98 ;proxy3 IN DNSKEY 256 3 1 AQOj9KXND1OcEeFtlHpUXyXpwQTcID3DqUoAt76k3Bbybug9U qUwqTrk fvCjw5R4OVlW9G01YsaN16D9JvvSjr/0d0mPpv3ydL3yTJpyq8gVjS/f jLVcepe+gu1HHf8 p8EWA/Zq1elb/9ZFnzwCMRSSFzKr+DhnLRvIY6Y2Q En83WQ== """ % get_soa() def print_sub_zone_part(addr): return "%d.%d" % (addr & 0xff, (addr >> 8) & 0xff) def sort_on_sub_zone(x, y): t = x[0].split('.') addr1 = (int(t[1]), int(t[0])) t = y[0].split('.') addr2 = (int(t[1]), int(t[0])) return cmp(addr1, addr2) def extract_zone(addr): return (addr >> 16) & 0xff def extract_net(addr): return (addr >> 8) & 0xff def filter_for_zone(nodes, zone): return filter(lambda n: extract_zone(n.master_ip) == zone, nodes) # gegeven een numeriek IP nummer, geef een string met alleen de eerste # drie componenten. dus chop_ip(parseaddr('172.17.136.1')) == '172.17.136' def chop_ip(ip): return '.'.join(showaddr(ip).split('.')[:3]) def interlink_zone(root): lines = [] for node in root.nodes: for link in node.links: if extract_zone(link.ip) != 16: continue lines.append( (print_sub_zone_part(link.ip), "PTR", "%s.%s.wleiden.net." % (link.sdesc, node.name)) ) lines.sort(sort_on_sub_zone) return zoneheader(16) + serialize(lines) def finish_section(lines, rows): rows.sort() rows.append("") lines.extend(rows) def reverse_zone(root, zone): lines = [] static_addresses = root.static_addressess[0].static_addresss nodes = filter_for_zone(root.nodes, zone) netaddr_gehad = {} for node in nodes: netaddr = "0.%d" % extract_net(node.master_ip) if not netaddr_gehad.has_key(netaddr): lines.append( (netaddr, "PTR", "network-%s.wleiden.net." % node.name) ) lines.append( (print_sub_zone_part(node.master_ip), "PTR", "%s%s.wleiden.net." % (node.type, node.name) ) ) netaddr_gehad[netaddr] = 1 for link in node.links: if has_attr(link, 'dhcp'): lines.append("$GENERATE %s $.%d PTR dhcp-%s$.%s%s.wLeiden.NET." % (link.dhcp, extract_net(link.ip), link.sdesc, node.type, node.name) ) # de ethernetten if extract_zone(link.ip) == zone and \ link.ip != node.master_ip: lines.append( (print_sub_zone_part(link.ip), "PTR", "%s.%s%s.wleiden.net." % (link.sdesc, node.type, node.name)) ) for s in filter(lambda s: s.node == node.name, static_addresses): for link in node.links: if s.sdesc != link.sdesc: continue lines.append( ("%s.%s" % (s.addr, extract_net(link.ip)), "PTR", "%s.wleiden.net." % s.name) ) lines.append("") #lines.sort(sort_on_sub_zone) return zoneheader(zone) + "\n" + serialize(lines) def wleiden_net(root): wleiden_net = "$ORIGIN wLeiden.NET.\n" + gen_header("wleiden.net").replace('#', ';') + """ $TTL 86400 @ IN SOA ns2.wLeiden.NET. hostmaster.wLeiden.NET. ( %s 7200 3599 60480 86400 ) IN NS ns0.wLeiden.NET. IN NS ns2.wLeiden.NET. IN MX 10 Fallback1 IN DNSKEY 256 3 1 AQOj9KXND1OcEeFtlHpUXyXpwQTcID3DqUoAt76k3Bbybug9U qUwqTrk fvCjw5R4OVlW9G01YsaN16D9JvvSjr/0d0mPpv3ydL3yTJpyq8gVjS/f jLVcepe+gu1HHf8 p8EWA/Zq1elb/9ZFnzwCMRSSFzKr+DhnLRvIY6Y2Q En83WQ== ns0.wleiden.net. IN A 212.61.66.38 ns2.wleiden.net. IN A 213.84.43.3 """ % get_soa() try: extra_addresses = root.static_addressess[0].extra_addresss except: extra_addresses = [] try: static_addresses = root.static_addressess[0].static_addresss except: static_addresses = [] lines = [] if len(extra_addresses) > 0: lines.append("; addresses not associated with a node") for ea in extra_addresses: lines.append ( (ea.name, "A", ea.addr) ) lines.append("") # network names lines.append("; the network names") nodes = root.nodes[:] nodes.sort(lambda n1, n2: cmp(n1.name, n2.name)) for node in nodes: if node.name[:5] == 'proxy': continue for link in node.links: (nw, bcast) = decode_mask(link.ip, int(link.mask)) for peer in link.peers: nodename = node.name.lower() peername = peer[0].name.lower() if peername < nodename: continue lines.append( ("%s-%s" % (nodename, peername), 'A', showaddr(nw)) ) lines.append("") for node in nodes: lines.append("""; ; ============= %s ============== ; """ % node.name.upper()) if node.name[:5] == 'proxy': lines.append( (node.name, "A", showaddr(node.master_ip)) ) else: lines.append( (node.name, "CNAME", "%s%s" % (node.type, node.name) ) ) lines.append( ("%s%s" % (node.type, node.name), "A", showaddr(node.master_ip)) ) (nw, bcast) = decode_mask(node.master_ip, 24) lines.append( ("network.%s" % node.name, 'A', showaddr(nw)) ) lines.append( ("bcast.%s" % node.name, 'A', showaddr(bcast)) ) rows = [] for link in node.links: if has_attr(link, "dhcp"): chopped_ip = chop_ip(link.ip) (range_begin, range_end) = link.dhcp.split('-') rows.append("$GENERATE %d-%d dhcp-%s$.%s%s A %s.$" % ( int(range_begin) + 1, int(range_end) + 1, link.sdesc, node.type, node.name, chopped_ip) ) finish_section(lines, rows) rows = [] for link in node.links: name = "%s.%s%s" % (link.sdesc, node.type, node.name) if link.ip == node.master_ip: rows.append( (name, "CNAME", "%s%s" % (node.type, node.name) ) ) else: rows.append( ("%s.%s%s" % (link.sdesc, node.type, node.name), "A", showaddr(link.ip)) ) finish_section(lines, rows) # now the static addresses rows = [] chopped_ips = {} for link in node.links: chopped_ips[link.sdesc] = chop_ip(link.ip) for a in filter(lambda a: a.node == node.name, static_addresses): if not chopped_ips.has_key(a.sdesc): print "ouch, static address refers to unknown iface!" print "\t", a.name rows.append( ("%s.%s%s" % (a.name, node.type, node.name), 'A', "%s.%s" % (chopped_ips[a.sdesc], a.addr)) ) if not has_attr(a, 'scope') or a.scope == 'net': rows.append( (a.name, "CNAME", "%s.%s%s" % (a.name, node.type, node.name)) ) if not has_attr(a, 'aliass'): continue for alias in a.aliass: rows.append( (alias.name, "CNAME", "%s.%s%s" % (a.name, node.type, node.name)) ) finish_section(lines, rows) return wleiden_net + serialize(lines) if __name__ == "__main__": nodes = xml_to_obj_hierarchy(sys.argv[1]) ready_nodes_dtd_hierarchy(nodes) print reverse_zone(nodes, 17) if len(sys.argv) == 3: open("%sys.argv[2]" % i, 'w').write(dns.reverse_zone(root, i))