def ttl_changed(self): query = dns.message.make_query(self.fqdn, self.module.params['type']) if self.keyring: query.use_tsig(keyring=self.keyring, algorithm=self.algorithm) try: if self.module.params['protocol'] == 'tcp': lookup = dns.query.tcp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) else: lookup = dns.query.udp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) except (dns.tsig.PeerBadKey, dns.tsig.PeerBadSignature) as e: self.module.fail_json(msg='TSIG update error (%s): %s' % (e.__class__.__name__, to_native(e))) except (socket_error, dns.exception.Timeout) as e: self.module.fail_json(msg='DNS server error: (%s): %s' % (e.__class__.__name__, to_native(e))) if lookup.rcode() != dns.rcode.NOERROR: self.module.fail_json( msg='Failed to lookup TTL of existing matching record.') current_ttl = lookup.answer[0].ttl return current_ttl != self.module.params['ttl']
def lookup_zone(self): name = dns.name.from_text(self.module.params['record']) while True: query = dns.message.make_query(name, dns.rdatatype.SOA) if self.keyring: query.use_tsig(keyring=self.keyring, algorithm=self.algorithm) try: if self.module.params['protocol'] == 'tcp': lookup = dns.query.tcp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) else: lookup = dns.query.udp(query, self.module.params['server'], timeout=10, port=self.module.params['port']) except (dns.tsig.PeerBadKey, dns.tsig.PeerBadSignature) as e: self.module.fail_json(msg='TSIG update error (%s): %s' % (e.__class__.__name__, to_native(e))) except (socket_error, dns.exception.Timeout) as e: self.module.fail_json(msg='DNS server error: (%s): %s' % (e.__class__.__name__, to_native(e))) if lookup.rcode() in [dns.rcode.SERVFAIL, dns.rcode.REFUSED]: self.module.fail_json(msg='Zone lookup failure: \'%s\' will not respond to queries regarding \'%s\'.' % ( self.module.params['server'], self.module.params['record'])) try: zone = lookup.authority[0].name if zone == name: return zone.to_text() except IndexError: pass try: name = name.parent() except dns.name.NoParent: self.module.fail_json(msg='Zone lookup of \'%s\' failed for unknown reason.' % (self.module.params['record']))
def dig(self, rname, rtype, rclass="IN", udp=None, serial=None, timeout=None, tries=3, flags="", bufsize=None, edns=None, nsid=False, dnssec=False, log_no_sep=False, tsig=None, addr=None, source=None): # Convert one item zone list to zone name. if isinstance(rname, list): if len(rname) != 1: raise Failed("One zone required") rname = rname[0].name rtype_str = rtype.upper() # Set port type. if rtype.upper() == "AXFR": # Always use TCP. udp = False elif rtype.upper() == "IXFR": # Use TCP if not specified. udp = udp if udp != None else False rtype_str += "=%i" % int(serial) else: # Use TCP or UDP at random if not specified. udp = udp if udp != None else random.choice([True, False]) if udp: dig_flags = "+notcp" else: dig_flags = "+tcp" dig_flags += " +retry=%i" % (tries - 1) # Set timeout. if timeout is None: timeout = self.DIG_TIMEOUT dig_flags += " +time=%i" % timeout # Prepare query (useless for XFR). query = dns.message.make_query(rname, rtype, rclass) # Remove implicit RD flag. query.flags &= ~dns.flags.RD # Set packet flags. flag_names = flags.split() for flag in flag_names: if flag == "AA": query.flags |= dns.flags.AA dig_flags += " +aa" elif flag == "TC": query.flags |= dns.flags.TC dig_flags += " +tc" elif flag == "RD": query.flags |= dns.flags.RD dig_flags += " +rd" elif flag == "RA": query.flags |= dns.flags.RA dig_flags += " +ra" elif flag == "AD": query.flags |= dns.flags.AD dig_flags += " +ad" elif flag == "CD": query.flags |= dns.flags.CD dig_flags += " +cd" elif flag == "Z": query.flags |= 64 dig_flags += " +z" # Set EDNS. if edns != None or bufsize or nsid: class NsidFix(object): '''Current pythondns doesn't implement NSID option.''' def __init__(self): self.otype = dns.edns.NSID def to_wire(self, file=None): pass if edns: edns = int(edns) else: edns = 0 dig_flags += " +edns=%i" % edns if bufsize: payload = int(bufsize) else: payload = 1280 dig_flags += " +bufsize=%i" % payload if nsid: options = [NsidFix()] dig_flags += " +nsid" else: options = None query.use_edns(edns=edns, payload=payload, options=options) # Set DO flag. if dnssec: query.want_dnssec() dig_flags += " +dnssec +bufsize=%i" % query.payload # Store function arguments for possible comparation. args = dict() params = inspect.getargvalues(inspect.currentframe()) for param in params.args: if param != "self": args[param] = params.locals[param] if addr is None: addr = self.addr # Add source to dig flags if present if source is not None: dig_flags += " -b " + source check_log("DIG %s %s %s @%s -p %i %s" % (rname, rtype_str, rclass, addr, self.port, dig_flags)) # Set TSIG for a normal query if explicitly specified. key_params = dict() if tsig != None: if type(tsig) is dnstest.keys.Tsig: key_params = tsig.key_params elif tsig and self.tsig_test: key_params = self.tsig_test.key_params if key_params: query.use_tsig(keyring=key_params["keyring"], keyname=key_params["keyname"], algorithm=key_params["keyalgorithm"]) # Set TSIG for a transfer if available. if rtype.upper() == "AXFR" or rtype.upper() == "IXFR": if self.tsig_test and tsig != False: key_params = self.tsig_test.key_params if key_params: detail_log("%s:%s:%s" % (key_params["keyalgorithm"], key_params["keyname"], base64.b64encode(list(key_params["keyring"].values())[0]).decode('ascii'))) for t in range(tries): try: if rtype.upper() == "AXFR": resp = dns.query.xfr(addr, rname, rtype, rclass, port=self.port, lifetime=timeout, use_udp=udp, **key_params) elif rtype.upper() == "IXFR": resp = dns.query.xfr(addr, rname, rtype, rclass, port=self.port, lifetime=timeout, use_udp=udp, serial=int(serial), **key_params) elif udp: resp = dns.query.udp(query, addr, port=self.port, timeout=timeout, source=source) else: resp = dns.query.tcp(query, addr, port=self.port, timeout=timeout, source=source) if not log_no_sep: detail_log(SEP) return dnstest.response.Response(self, resp, query, args) except dns.exception.Timeout: pass except: time.sleep(timeout) raise Failed("Can't query server='%s' for '%s %s %s'" % \ (self.name, rname, rclass, rtype))