Add negative response handling (RFC 2308)
Synthesize an SOA record for the zone, return it for direct SOA queries, and include it in the authority section of empty responses so resolvers can negative-cache properly. RCODE stays NOERROR rather than NXDOMAIN, since mDNS can't reliably prove non-existence.
This commit is contained in:
@@ -14,8 +14,15 @@ domain = sys.argv[1]
|
||||
port = int(sys.argv[2])
|
||||
ttl = 120
|
||||
timeout = 2
|
||||
negative_ttl = 10
|
||||
ipv6_ula_network = ipaddress.ip_network('fc00::/7')
|
||||
|
||||
def soa_record():
|
||||
return dns.RRHeader(name=domain, type=dns.SOA, ttl=negative_ttl, payload=dns.Record_SOA(
|
||||
mname=domain, rname="hostmaster." + domain,
|
||||
serial=1, refresh=1200, retry=180, expire=1209600, minimum=negative_ttl
|
||||
))
|
||||
|
||||
class DynamicResolver(object):
|
||||
def __init__(self):
|
||||
self.zeroconf = Zeroconf(ip_version=IPVersion.All)
|
||||
@@ -28,7 +35,7 @@ class DynamicResolver(object):
|
||||
|
||||
def _doDynamicResponse(self, query):
|
||||
if query.type == dns.SOA:
|
||||
return defer.succeed(([], [], []))
|
||||
return defer.succeed(([soa_record()], [], []))
|
||||
|
||||
localname = str(query.name)[:-len(domain)] + "local."
|
||||
|
||||
@@ -50,18 +57,18 @@ class DynamicResolver(object):
|
||||
#txt_ans, _, _ = txt(service)
|
||||
#srv_ans, _, a_ans = srv(service)
|
||||
#additional += a_ans + txt_ans + srv_ans
|
||||
return answers, [], additional
|
||||
return answers, ([] if answers else [soa_record()]), additional
|
||||
|
||||
def txt(localname):
|
||||
if localname.endswith('._device-info._tcp.local.'):
|
||||
info = ServiceInfo(localname, localname)
|
||||
info.request(self.zeroconf, timeout*1000)
|
||||
if not info.text:
|
||||
return [], [], []
|
||||
return [], [soa_record()], []
|
||||
else:
|
||||
info = self.zeroconf.get_service_info(localname, localname, timeout*1000)
|
||||
if info is None:
|
||||
return [], [], []
|
||||
return [], [soa_record()], []
|
||||
|
||||
order = []
|
||||
i = 0
|
||||
@@ -81,7 +88,7 @@ class DynamicResolver(object):
|
||||
def srv(localname):
|
||||
info = self.zeroconf.get_service_info(localname, localname, timeout*1000)
|
||||
if info is None:
|
||||
return [], [], []
|
||||
return [], [soa_record()], []
|
||||
|
||||
answers = [dns.RRHeader(name=localname[:-6] + domain, ttl=ttl, type=dns.SRV, payload=dns.Record_SRV(
|
||||
info.priority, info.weight, info.port, info.server[:-6] + domain
|
||||
@@ -128,7 +135,7 @@ class DynamicResolver(object):
|
||||
addr
|
||||
)) for addr in l.addrs]
|
||||
|
||||
return answers, [], []
|
||||
return answers, ([] if answers else [soa_record()]), []
|
||||
|
||||
d = defer.Deferred()
|
||||
|
||||
@@ -146,7 +153,7 @@ class DynamicResolver(object):
|
||||
return d
|
||||
else:
|
||||
print("Unsupported request", query)
|
||||
d.callback(([], [], []))
|
||||
d.callback(([], [soa_record()], []))
|
||||
return d
|
||||
|
||||
def query(self, query, timeout=None):
|
||||
|
||||
Reference in New Issue
Block a user