1*00b67f09SDavid van Moolenbroek#!@PYTHON@ 2*00b67f09SDavid van Moolenbroek############################################################################ 3*00b67f09SDavid van Moolenbroek# Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC") 4*00b67f09SDavid van Moolenbroek# 5*00b67f09SDavid van Moolenbroek# Permission to use, copy, modify, and/or distribute this software for any 6*00b67f09SDavid van Moolenbroek# purpose with or without fee is hereby granted, provided that the above 7*00b67f09SDavid van Moolenbroek# copyright notice and this permission notice appear in all copies. 8*00b67f09SDavid van Moolenbroek# 9*00b67f09SDavid van Moolenbroek# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10*00b67f09SDavid van Moolenbroek# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11*00b67f09SDavid van Moolenbroek# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12*00b67f09SDavid van Moolenbroek# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13*00b67f09SDavid van Moolenbroek# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14*00b67f09SDavid van Moolenbroek# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15*00b67f09SDavid van Moolenbroek# PERFORMANCE OF THIS SOFTWARE. 16*00b67f09SDavid van Moolenbroek############################################################################ 17*00b67f09SDavid van Moolenbroek 18*00b67f09SDavid van Moolenbroekimport argparse 19*00b67f09SDavid van Moolenbroekimport pprint 20*00b67f09SDavid van Moolenbroekimport os 21*00b67f09SDavid van Moolenbroek 22*00b67f09SDavid van Moolenbroekprog='dnssec-checkds' 23*00b67f09SDavid van Moolenbroek 24*00b67f09SDavid van Moolenbroek# These routines permit platform-independent location of BIND 9 tools 25*00b67f09SDavid van Moolenbroekif os.name == 'nt': 26*00b67f09SDavid van Moolenbroek import win32con 27*00b67f09SDavid van Moolenbroek import win32api 28*00b67f09SDavid van Moolenbroek 29*00b67f09SDavid van Moolenbroekdef prefix(bindir = ''): 30*00b67f09SDavid van Moolenbroek if os.name != 'nt': 31*00b67f09SDavid van Moolenbroek return os.path.join('@prefix@', bindir) 32*00b67f09SDavid van Moolenbroek 33*00b67f09SDavid van Moolenbroek bind_subkey = "Software\\ISC\\BIND" 34*00b67f09SDavid van Moolenbroek hKey = None 35*00b67f09SDavid van Moolenbroek keyFound = True 36*00b67f09SDavid van Moolenbroek try: 37*00b67f09SDavid van Moolenbroek hKey = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, bind_subkey) 38*00b67f09SDavid van Moolenbroek except: 39*00b67f09SDavid van Moolenbroek keyFound = False 40*00b67f09SDavid van Moolenbroek if keyFound: 41*00b67f09SDavid van Moolenbroek try: 42*00b67f09SDavid van Moolenbroek (namedBase, _) = win32api.RegQueryValueEx(hKey, "InstallDir") 43*00b67f09SDavid van Moolenbroek except: 44*00b67f09SDavid van Moolenbroek keyFound = False 45*00b67f09SDavid van Moolenbroek win32api.RegCloseKey(hKey) 46*00b67f09SDavid van Moolenbroek if keyFound: 47*00b67f09SDavid van Moolenbroek return os.path.join(namedBase, bindir) 48*00b67f09SDavid van Moolenbroek return os.path.join(win32api.GetSystemDirectory(), bindir) 49*00b67f09SDavid van Moolenbroek 50*00b67f09SDavid van Moolenbroekdef shellquote(s): 51*00b67f09SDavid van Moolenbroek if os.name == 'nt': 52*00b67f09SDavid van Moolenbroek return '"' + s.replace('"', '"\\"') + '"' 53*00b67f09SDavid van Moolenbroek return "'" + s.replace("'", "'\\''") + "'" 54*00b67f09SDavid van Moolenbroek 55*00b67f09SDavid van Moolenbroek############################################################################ 56*00b67f09SDavid van Moolenbroek# DSRR class: 57*00b67f09SDavid van Moolenbroek# Delegation Signer (DS) resource record 58*00b67f09SDavid van Moolenbroek############################################################################ 59*00b67f09SDavid van Moolenbroekclass DSRR: 60*00b67f09SDavid van Moolenbroek hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST', 4: 'SHA-384' } 61*00b67f09SDavid van Moolenbroek rrname='' 62*00b67f09SDavid van Moolenbroek rrclass='IN' 63*00b67f09SDavid van Moolenbroek rrtype='DS' 64*00b67f09SDavid van Moolenbroek keyid=None 65*00b67f09SDavid van Moolenbroek keyalg=None 66*00b67f09SDavid van Moolenbroek hashalg=None 67*00b67f09SDavid van Moolenbroek digest='' 68*00b67f09SDavid van Moolenbroek ttl=0 69*00b67f09SDavid van Moolenbroek 70*00b67f09SDavid van Moolenbroek def __init__(self, rrtext): 71*00b67f09SDavid van Moolenbroek if not rrtext: 72*00b67f09SDavid van Moolenbroek return 73*00b67f09SDavid van Moolenbroek 74*00b67f09SDavid van Moolenbroek fields = rrtext.split() 75*00b67f09SDavid van Moolenbroek if len(fields) < 7: 76*00b67f09SDavid van Moolenbroek return 77*00b67f09SDavid van Moolenbroek 78*00b67f09SDavid van Moolenbroek self.rrname = fields[0].lower() 79*00b67f09SDavid van Moolenbroek fields = fields[1:] 80*00b67f09SDavid van Moolenbroek if fields[0].upper() in ['IN','CH','HS']: 81*00b67f09SDavid van Moolenbroek self.rrclass = fields[0].upper() 82*00b67f09SDavid van Moolenbroek fields = fields[1:] 83*00b67f09SDavid van Moolenbroek else: 84*00b67f09SDavid van Moolenbroek self.ttl = int(fields[0]) 85*00b67f09SDavid van Moolenbroek self.rrclass = fields[1].upper() 86*00b67f09SDavid van Moolenbroek fields = fields[2:] 87*00b67f09SDavid van Moolenbroek 88*00b67f09SDavid van Moolenbroek if fields[0].upper() != 'DS': 89*00b67f09SDavid van Moolenbroek raise Exception 90*00b67f09SDavid van Moolenbroek 91*00b67f09SDavid van Moolenbroek self.rrtype = 'DS' 92*00b67f09SDavid van Moolenbroek self.keyid = int(fields[1]) 93*00b67f09SDavid van Moolenbroek self.keyalg = int(fields[2]) 94*00b67f09SDavid van Moolenbroek self.hashalg = int(fields[3]) 95*00b67f09SDavid van Moolenbroek self.digest = ''.join(fields[4:]).upper() 96*00b67f09SDavid van Moolenbroek 97*00b67f09SDavid van Moolenbroek def __repr__(self): 98*00b67f09SDavid van Moolenbroek return('%s %s %s %d %d %d %s' % 99*00b67f09SDavid van Moolenbroek (self.rrname, self.rrclass, self.rrtype, self.keyid, 100*00b67f09SDavid van Moolenbroek self.keyalg, self.hashalg, self.digest)) 101*00b67f09SDavid van Moolenbroek 102*00b67f09SDavid van Moolenbroek def __eq__(self, other): 103*00b67f09SDavid van Moolenbroek return self.__repr__() == other.__repr__() 104*00b67f09SDavid van Moolenbroek 105*00b67f09SDavid van Moolenbroek############################################################################ 106*00b67f09SDavid van Moolenbroek# DLVRR class: 107*00b67f09SDavid van Moolenbroek# DNSSEC Lookaside Validation (DLV) resource record 108*00b67f09SDavid van Moolenbroek############################################################################ 109*00b67f09SDavid van Moolenbroekclass DLVRR: 110*00b67f09SDavid van Moolenbroek hashalgs = {1: 'SHA-1', 2: 'SHA-256', 3: 'GOST', 4: 'SHA-384' } 111*00b67f09SDavid van Moolenbroek parent='' 112*00b67f09SDavid van Moolenbroek dlvname='' 113*00b67f09SDavid van Moolenbroek rrname='IN' 114*00b67f09SDavid van Moolenbroek rrclass='IN' 115*00b67f09SDavid van Moolenbroek rrtype='DLV' 116*00b67f09SDavid van Moolenbroek keyid=None 117*00b67f09SDavid van Moolenbroek keyalg=None 118*00b67f09SDavid van Moolenbroek hashalg=None 119*00b67f09SDavid van Moolenbroek digest='' 120*00b67f09SDavid van Moolenbroek ttl=0 121*00b67f09SDavid van Moolenbroek 122*00b67f09SDavid van Moolenbroek def __init__(self, rrtext, dlvname): 123*00b67f09SDavid van Moolenbroek if not rrtext: 124*00b67f09SDavid van Moolenbroek return 125*00b67f09SDavid van Moolenbroek 126*00b67f09SDavid van Moolenbroek fields = rrtext.split() 127*00b67f09SDavid van Moolenbroek if len(fields) < 7: 128*00b67f09SDavid van Moolenbroek return 129*00b67f09SDavid van Moolenbroek 130*00b67f09SDavid van Moolenbroek self.dlvname = dlvname.lower() 131*00b67f09SDavid van Moolenbroek parent = fields[0].lower().strip('.').split('.') 132*00b67f09SDavid van Moolenbroek parent.reverse() 133*00b67f09SDavid van Moolenbroek dlv = dlvname.split('.') 134*00b67f09SDavid van Moolenbroek dlv.reverse() 135*00b67f09SDavid van Moolenbroek while len(dlv) != 0 and len(parent) != 0 and parent[0] == dlv[0]: 136*00b67f09SDavid van Moolenbroek parent = parent[1:] 137*00b67f09SDavid van Moolenbroek dlv = dlv[1:] 138*00b67f09SDavid van Moolenbroek if len(dlv) != 0: 139*00b67f09SDavid van Moolenbroek raise Exception 140*00b67f09SDavid van Moolenbroek parent.reverse() 141*00b67f09SDavid van Moolenbroek self.parent = '.'.join(parent) 142*00b67f09SDavid van Moolenbroek self.rrname = self.parent + '.' + self.dlvname + '.' 143*00b67f09SDavid van Moolenbroek 144*00b67f09SDavid van Moolenbroek fields = fields[1:] 145*00b67f09SDavid van Moolenbroek if fields[0].upper() in ['IN','CH','HS']: 146*00b67f09SDavid van Moolenbroek self.rrclass = fields[0].upper() 147*00b67f09SDavid van Moolenbroek fields = fields[1:] 148*00b67f09SDavid van Moolenbroek else: 149*00b67f09SDavid van Moolenbroek self.ttl = int(fields[0]) 150*00b67f09SDavid van Moolenbroek self.rrclass = fields[1].upper() 151*00b67f09SDavid van Moolenbroek fields = fields[2:] 152*00b67f09SDavid van Moolenbroek 153*00b67f09SDavid van Moolenbroek if fields[0].upper() != 'DLV': 154*00b67f09SDavid van Moolenbroek raise Exception 155*00b67f09SDavid van Moolenbroek 156*00b67f09SDavid van Moolenbroek self.rrtype = 'DLV' 157*00b67f09SDavid van Moolenbroek self.keyid = int(fields[1]) 158*00b67f09SDavid van Moolenbroek self.keyalg = int(fields[2]) 159*00b67f09SDavid van Moolenbroek self.hashalg = int(fields[3]) 160*00b67f09SDavid van Moolenbroek self.digest = ''.join(fields[4:]).upper() 161*00b67f09SDavid van Moolenbroek 162*00b67f09SDavid van Moolenbroek def __repr__(self): 163*00b67f09SDavid van Moolenbroek return('%s %s %s %d %d %d %s' % 164*00b67f09SDavid van Moolenbroek (self.rrname, self.rrclass, self.rrtype, 165*00b67f09SDavid van Moolenbroek self.keyid, self.keyalg, self.hashalg, self.digest)) 166*00b67f09SDavid van Moolenbroek 167*00b67f09SDavid van Moolenbroek def __eq__(self, other): 168*00b67f09SDavid van Moolenbroek return self.__repr__() == other.__repr__() 169*00b67f09SDavid van Moolenbroek 170*00b67f09SDavid van Moolenbroek############################################################################ 171*00b67f09SDavid van Moolenbroek# checkds: 172*00b67f09SDavid van Moolenbroek# Fetch DS RRset for the given zone from the DNS; fetch DNSKEY 173*00b67f09SDavid van Moolenbroek# RRset from the masterfile if specified, or from DNS if not. 174*00b67f09SDavid van Moolenbroek# Generate a set of expected DS records from the DNSKEY RRset, 175*00b67f09SDavid van Moolenbroek# and report on congruency. 176*00b67f09SDavid van Moolenbroek############################################################################ 177*00b67f09SDavid van Moolenbroekdef checkds(zone, masterfile = None): 178*00b67f09SDavid van Moolenbroek dslist=[] 179*00b67f09SDavid van Moolenbroek fp=os.popen("%s +noall +answer -t ds -q %s" % 180*00b67f09SDavid van Moolenbroek (shellquote(args.dig), shellquote(zone))) 181*00b67f09SDavid van Moolenbroek for line in fp: 182*00b67f09SDavid van Moolenbroek dslist.append(DSRR(line)) 183*00b67f09SDavid van Moolenbroek dslist = sorted(dslist, key=lambda ds: (ds.keyid, ds.keyalg, ds.hashalg)) 184*00b67f09SDavid van Moolenbroek fp.close() 185*00b67f09SDavid van Moolenbroek 186*00b67f09SDavid van Moolenbroek dsklist=[] 187*00b67f09SDavid van Moolenbroek 188*00b67f09SDavid van Moolenbroek if masterfile: 189*00b67f09SDavid van Moolenbroek fp = os.popen("%s -f %s %s " % 190*00b67f09SDavid van Moolenbroek (shellquote(args.dsfromkey), shellquote(masterfile), 191*00b67f09SDavid van Moolenbroek shellquote(zone))) 192*00b67f09SDavid van Moolenbroek else: 193*00b67f09SDavid van Moolenbroek fp = os.popen("%s +noall +answer -t dnskey -q %s | %s -f - %s" % 194*00b67f09SDavid van Moolenbroek (shellquote(args.dig), shellquote(zone), 195*00b67f09SDavid van Moolenbroek shellquote(args.dsfromkey), shellquote(zone))) 196*00b67f09SDavid van Moolenbroek 197*00b67f09SDavid van Moolenbroek for line in fp: 198*00b67f09SDavid van Moolenbroek dsklist.append(DSRR(line)) 199*00b67f09SDavid van Moolenbroek 200*00b67f09SDavid van Moolenbroek fp.close() 201*00b67f09SDavid van Moolenbroek 202*00b67f09SDavid van Moolenbroek if (len(dsklist) < 1): 203*00b67f09SDavid van Moolenbroek print ("No DNSKEY records found in zone apex") 204*00b67f09SDavid van Moolenbroek return False 205*00b67f09SDavid van Moolenbroek 206*00b67f09SDavid van Moolenbroek found = False 207*00b67f09SDavid van Moolenbroek for ds in dsklist: 208*00b67f09SDavid van Moolenbroek if ds in dslist: 209*00b67f09SDavid van Moolenbroek print ("DS for KSK %s/%03d/%05d (%s) found in parent" % 210*00b67f09SDavid van Moolenbroek (ds.rrname.strip('.'), ds.keyalg, 211*00b67f09SDavid van Moolenbroek ds.keyid, DSRR.hashalgs[ds.hashalg])) 212*00b67f09SDavid van Moolenbroek found = True 213*00b67f09SDavid van Moolenbroek else: 214*00b67f09SDavid van Moolenbroek print ("DS for KSK %s/%03d/%05d (%s) missing from parent" % 215*00b67f09SDavid van Moolenbroek (ds.rrname.strip('.'), ds.keyalg, 216*00b67f09SDavid van Moolenbroek ds.keyid, DSRR.hashalgs[ds.hashalg])) 217*00b67f09SDavid van Moolenbroek 218*00b67f09SDavid van Moolenbroek if not found: 219*00b67f09SDavid van Moolenbroek print ("No DS records were found for any DNSKEY") 220*00b67f09SDavid van Moolenbroek 221*00b67f09SDavid van Moolenbroek return found 222*00b67f09SDavid van Moolenbroek 223*00b67f09SDavid van Moolenbroek############################################################################ 224*00b67f09SDavid van Moolenbroek# checkdlv: 225*00b67f09SDavid van Moolenbroek# Fetch DLV RRset for the given zone from the DNS; fetch DNSKEY 226*00b67f09SDavid van Moolenbroek# RRset from the masterfile if specified, or from DNS if not. 227*00b67f09SDavid van Moolenbroek# Generate a set of expected DLV records from the DNSKEY RRset, 228*00b67f09SDavid van Moolenbroek# and report on congruency. 229*00b67f09SDavid van Moolenbroek############################################################################ 230*00b67f09SDavid van Moolenbroekdef checkdlv(zone, lookaside, masterfile = None): 231*00b67f09SDavid van Moolenbroek dlvlist=[] 232*00b67f09SDavid van Moolenbroek fp=os.popen("%s +noall +answer -t dlv -q %s" % 233*00b67f09SDavid van Moolenbroek (shellquote(args.dig), shellquote(zone + '.' + lookaside))) 234*00b67f09SDavid van Moolenbroek for line in fp: 235*00b67f09SDavid van Moolenbroek dlvlist.append(DLVRR(line, lookaside)) 236*00b67f09SDavid van Moolenbroek dlvlist = sorted(dlvlist, 237*00b67f09SDavid van Moolenbroek key=lambda dlv: (dlv.keyid, dlv.keyalg, dlv.hashalg)) 238*00b67f09SDavid van Moolenbroek fp.close() 239*00b67f09SDavid van Moolenbroek 240*00b67f09SDavid van Moolenbroek # 241*00b67f09SDavid van Moolenbroek # Fetch DNSKEY records from DNS and generate DLV records from them 242*00b67f09SDavid van Moolenbroek # 243*00b67f09SDavid van Moolenbroek dlvklist=[] 244*00b67f09SDavid van Moolenbroek if masterfile: 245*00b67f09SDavid van Moolenbroek fp = os.popen("%s -f %s -l %s %s " % 246*00b67f09SDavid van Moolenbroek (args.dsfromkey, masterfile, lookaside, zone)) 247*00b67f09SDavid van Moolenbroek else: 248*00b67f09SDavid van Moolenbroek fp = os.popen("%s +noall +answer -t dnskey %s | %s -f - -l %s %s" 249*00b67f09SDavid van Moolenbroek % (shellquote(args.dig), shellquote(zone), 250*00b67f09SDavid van Moolenbroek shellquote(args.dsfromkey), shellquote(lookaside), 251*00b67f09SDavid van Moolenbroek shellquote(zone))) 252*00b67f09SDavid van Moolenbroek 253*00b67f09SDavid van Moolenbroek for line in fp: 254*00b67f09SDavid van Moolenbroek dlvklist.append(DLVRR(line, lookaside)) 255*00b67f09SDavid van Moolenbroek 256*00b67f09SDavid van Moolenbroek fp.close() 257*00b67f09SDavid van Moolenbroek 258*00b67f09SDavid van Moolenbroek if (len(dlvklist) < 1): 259*00b67f09SDavid van Moolenbroek print ("No DNSKEY records found in zone apex") 260*00b67f09SDavid van Moolenbroek return False 261*00b67f09SDavid van Moolenbroek 262*00b67f09SDavid van Moolenbroek found = False 263*00b67f09SDavid van Moolenbroek for dlv in dlvklist: 264*00b67f09SDavid van Moolenbroek if dlv in dlvlist: 265*00b67f09SDavid van Moolenbroek print ("DLV for KSK %s/%03d/%05d (%s) found in %s" % 266*00b67f09SDavid van Moolenbroek (dlv.parent, dlv.keyalg, dlv.keyid, 267*00b67f09SDavid van Moolenbroek DLVRR.hashalgs[dlv.hashalg], dlv.dlvname)) 268*00b67f09SDavid van Moolenbroek found = True 269*00b67f09SDavid van Moolenbroek else: 270*00b67f09SDavid van Moolenbroek print ("DLV for KSK %s/%03d/%05d (%s) missing from %s" % 271*00b67f09SDavid van Moolenbroek (dlv.parent, dlv.keyalg, dlv.keyid, 272*00b67f09SDavid van Moolenbroek DLVRR.hashalgs[dlv.hashalg], dlv.dlvname)) 273*00b67f09SDavid van Moolenbroek 274*00b67f09SDavid van Moolenbroek if not found: 275*00b67f09SDavid van Moolenbroek print ("No DLV records were found for any DNSKEY") 276*00b67f09SDavid van Moolenbroek 277*00b67f09SDavid van Moolenbroek return found 278*00b67f09SDavid van Moolenbroek 279*00b67f09SDavid van Moolenbroek 280*00b67f09SDavid van Moolenbroek############################################################################ 281*00b67f09SDavid van Moolenbroek# parse_args: 282*00b67f09SDavid van Moolenbroek# Read command line arguments, set global 'args' structure 283*00b67f09SDavid van Moolenbroek############################################################################ 284*00b67f09SDavid van Moolenbroekdef parse_args(): 285*00b67f09SDavid van Moolenbroek global args 286*00b67f09SDavid van Moolenbroek parser = argparse.ArgumentParser(description=prog + ': checks DS coverage') 287*00b67f09SDavid van Moolenbroek 288*00b67f09SDavid van Moolenbroek bindir = 'bin' 289*00b67f09SDavid van Moolenbroek if os.name == 'nt': 290*00b67f09SDavid van Moolenbroek sbindir = 'bin' 291*00b67f09SDavid van Moolenbroek else: 292*00b67f09SDavid van Moolenbroek sbindir = 'sbin' 293*00b67f09SDavid van Moolenbroek 294*00b67f09SDavid van Moolenbroek parser.add_argument('zone', type=str, help='zone to check') 295*00b67f09SDavid van Moolenbroek parser.add_argument('-f', '--file', dest='masterfile', type=str, 296*00b67f09SDavid van Moolenbroek help='zone master file') 297*00b67f09SDavid van Moolenbroek parser.add_argument('-l', '--lookaside', dest='lookaside', type=str, 298*00b67f09SDavid van Moolenbroek help='DLV lookaside zone') 299*00b67f09SDavid van Moolenbroek parser.add_argument('-d', '--dig', dest='dig', 300*00b67f09SDavid van Moolenbroek default=os.path.join(prefix(bindir), 'dig'), 301*00b67f09SDavid van Moolenbroek type=str, help='path to \'dig\'') 302*00b67f09SDavid van Moolenbroek parser.add_argument('-D', '--dsfromkey', dest='dsfromkey', 303*00b67f09SDavid van Moolenbroek default=os.path.join(prefix(sbindir), 304*00b67f09SDavid van Moolenbroek 'dnssec-dsfromkey'), 305*00b67f09SDavid van Moolenbroek type=str, help='path to \'dig\'') 306*00b67f09SDavid van Moolenbroek parser.add_argument('-v', '--version', action='version', version='9.9.1') 307*00b67f09SDavid van Moolenbroek args = parser.parse_args() 308*00b67f09SDavid van Moolenbroek 309*00b67f09SDavid van Moolenbroek args.zone = args.zone.strip('.') 310*00b67f09SDavid van Moolenbroek if args.lookaside: 311*00b67f09SDavid van Moolenbroek lookaside = args.lookaside.strip('.') 312*00b67f09SDavid van Moolenbroek 313*00b67f09SDavid van Moolenbroek############################################################################ 314*00b67f09SDavid van Moolenbroek# Main 315*00b67f09SDavid van Moolenbroek############################################################################ 316*00b67f09SDavid van Moolenbroekdef main(): 317*00b67f09SDavid van Moolenbroek parse_args() 318*00b67f09SDavid van Moolenbroek 319*00b67f09SDavid van Moolenbroek if args.lookaside: 320*00b67f09SDavid van Moolenbroek found = checkdlv(args.zone, args.lookaside, args.masterfile) 321*00b67f09SDavid van Moolenbroek else: 322*00b67f09SDavid van Moolenbroek found = checkds(args.zone, args.masterfile) 323*00b67f09SDavid van Moolenbroek 324*00b67f09SDavid van Moolenbroek exit(0 if found else 1) 325*00b67f09SDavid van Moolenbroek 326*00b67f09SDavid van Moolenbroekif __name__ == "__main__": 327*00b67f09SDavid van Moolenbroek main() 328