Ausgabe der neuen DB Einträge
This commit is contained in:
parent
bad48e1627
commit
cfbbb9ee3d
2399 changed files with 843193 additions and 43 deletions
221
venv/lib/python3.9/site-packages/twisted/names/secondary.py
Normal file
221
venv/lib/python3.9/site-packages/twisted/names/secondary.py
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
# -*- test-case-name: twisted.names.test.test_names -*-
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
from __future__ import absolute_import, division
|
||||
|
||||
__all__ = ['SecondaryAuthority', 'SecondaryAuthorityService']
|
||||
|
||||
from twisted.internet import task, defer
|
||||
from twisted.names import dns
|
||||
from twisted.names import common
|
||||
from twisted.names import client
|
||||
from twisted.names import resolve
|
||||
from twisted.names.authority import FileAuthority
|
||||
|
||||
from twisted.python import log, failure
|
||||
from twisted.python.compat import nativeString
|
||||
from twisted.application import service
|
||||
|
||||
|
||||
|
||||
class SecondaryAuthorityService(service.Service):
|
||||
"""
|
||||
A service that keeps one or more authorities up to date by doing hourly
|
||||
zone transfers from a master.
|
||||
|
||||
@ivar primary: IP address of the master.
|
||||
@type primary: L{str}
|
||||
|
||||
@ivar domains: An authority for each domain mirrored from the master.
|
||||
@type domains: L{list} of L{SecondaryAuthority}
|
||||
"""
|
||||
calls = None
|
||||
|
||||
_port = 53
|
||||
|
||||
def __init__(self, primary, domains):
|
||||
"""
|
||||
@param primary: The IP address of the server from which to perform
|
||||
zone transfers.
|
||||
@type primary: L{str}
|
||||
|
||||
@param domains: A sequence of domain names for which to perform
|
||||
zone transfers.
|
||||
@type domains: L{list} of L{bytes}
|
||||
"""
|
||||
self.primary = nativeString(primary)
|
||||
self.domains = [SecondaryAuthority(primary, d) for d in domains]
|
||||
|
||||
|
||||
@classmethod
|
||||
def fromServerAddressAndDomains(cls, serverAddress, domains):
|
||||
"""
|
||||
Construct a new L{SecondaryAuthorityService} from a tuple giving a
|
||||
server address and a C{str} giving the name of a domain for which this
|
||||
is an authority.
|
||||
|
||||
@param serverAddress: A two-tuple, the first element of which is a
|
||||
C{str} giving an IP address and the second element of which is a
|
||||
C{int} giving a port number. Together, these define where zone
|
||||
transfers will be attempted from.
|
||||
|
||||
@param domain: A C{bytes} giving the domain to transfer.
|
||||
|
||||
@return: A new instance of L{SecondaryAuthorityService}.
|
||||
"""
|
||||
primary, port = serverAddress
|
||||
service = cls(primary, [])
|
||||
service._port = port
|
||||
service.domains = [
|
||||
SecondaryAuthority.fromServerAddressAndDomain(serverAddress, d)
|
||||
for d in domains]
|
||||
return service
|
||||
|
||||
|
||||
def getAuthority(self):
|
||||
"""
|
||||
Get a resolver for the transferred domains.
|
||||
|
||||
@rtype: L{ResolverChain}
|
||||
"""
|
||||
return resolve.ResolverChain(self.domains)
|
||||
|
||||
def startService(self):
|
||||
service.Service.startService(self)
|
||||
self.calls = [task.LoopingCall(d.transfer) for d in self.domains]
|
||||
i = 0
|
||||
from twisted.internet import reactor
|
||||
for c in self.calls:
|
||||
# XXX Add errbacks, respect proper timeouts
|
||||
reactor.callLater(i, c.start, 60 * 60)
|
||||
i += 1
|
||||
|
||||
def stopService(self):
|
||||
service.Service.stopService(self)
|
||||
for c in self.calls:
|
||||
c.stop()
|
||||
|
||||
|
||||
|
||||
class SecondaryAuthority(FileAuthority):
|
||||
"""
|
||||
An Authority that keeps itself updated by performing zone transfers.
|
||||
|
||||
@ivar primary: The IP address of the server from which zone transfers will
|
||||
be attempted.
|
||||
@type primary: C{str}
|
||||
|
||||
@ivar _port: The port number of the server from which zone transfers will
|
||||
be attempted.
|
||||
@type: C{int}
|
||||
|
||||
@ivar domain: The domain for which this is the secondary authority.
|
||||
@type: C{bytes}
|
||||
|
||||
@ivar _reactor: The reactor to use to perform the zone transfers, or
|
||||
L{None} to use the global reactor.
|
||||
"""
|
||||
|
||||
transferring = False
|
||||
soa = records = None
|
||||
_port = 53
|
||||
_reactor = None
|
||||
|
||||
def __init__(self, primaryIP, domain):
|
||||
"""
|
||||
@param domain: The domain for which this will be the secondary
|
||||
authority.
|
||||
@type domain: L{bytes} or L{str}
|
||||
"""
|
||||
# Yep. Skip over FileAuthority.__init__. This is a hack until we have
|
||||
# a good composition-based API for the complicated DNS record lookup
|
||||
# logic we want to share.
|
||||
common.ResolverBase.__init__(self)
|
||||
self.primary = nativeString(primaryIP)
|
||||
self.domain = dns.domainString(domain)
|
||||
|
||||
|
||||
@classmethod
|
||||
def fromServerAddressAndDomain(cls, serverAddress, domain):
|
||||
"""
|
||||
Construct a new L{SecondaryAuthority} from a tuple giving a server
|
||||
address and a C{bytes} giving the name of a domain for which this is an
|
||||
authority.
|
||||
|
||||
@param serverAddress: A two-tuple, the first element of which is a
|
||||
C{str} giving an IP address and the second element of which is a
|
||||
C{int} giving a port number. Together, these define where zone
|
||||
transfers will be attempted from.
|
||||
|
||||
@param domain: A C{bytes} giving the domain to transfer.
|
||||
@type domain: L{bytes}
|
||||
|
||||
@return: A new instance of L{SecondaryAuthority}.
|
||||
"""
|
||||
primary, port = serverAddress
|
||||
secondary = cls(primary, domain)
|
||||
secondary._port = port
|
||||
return secondary
|
||||
|
||||
|
||||
def transfer(self):
|
||||
"""
|
||||
Attempt a zone transfer.
|
||||
|
||||
@returns: A L{Deferred} that fires with L{None} when attempted zone
|
||||
transfer has completed.
|
||||
"""
|
||||
# FIXME: This logic doesn't avoid duplicate transfers
|
||||
# https://twistedmatrix.com/trac/ticket/9754
|
||||
if self.transferring: # <-- never true
|
||||
return
|
||||
self.transfering = True # <-- speling
|
||||
|
||||
reactor = self._reactor
|
||||
if reactor is None:
|
||||
from twisted.internet import reactor
|
||||
|
||||
resolver = client.Resolver(
|
||||
servers=[(self.primary, self._port)], reactor=reactor)
|
||||
return resolver.lookupZone(self.domain
|
||||
).addCallback(self._cbZone
|
||||
).addErrback(self._ebZone
|
||||
)
|
||||
|
||||
|
||||
def _lookup(self, name, cls, type, timeout=None):
|
||||
if not self.soa or not self.records:
|
||||
# No transfer has occurred yet. Fail non-authoritatively so that
|
||||
# the caller can try elsewhere.
|
||||
return defer.fail(failure.Failure(dns.DomainError(name)))
|
||||
return FileAuthority._lookup(self, name, cls, type, timeout)
|
||||
|
||||
|
||||
def _cbZone(self, zone):
|
||||
ans, _, _ = zone
|
||||
self.records = r = {}
|
||||
for rec in ans:
|
||||
if not self.soa and rec.type == dns.SOA:
|
||||
self.soa = (rec.name.name.lower(), rec.payload)
|
||||
else:
|
||||
r.setdefault(rec.name.name.lower(), []).append(rec.payload)
|
||||
|
||||
|
||||
def _ebZone(self, failure):
|
||||
log.msg("Updating %s from %s failed during zone transfer" % (self.domain, self.primary))
|
||||
log.err(failure)
|
||||
|
||||
|
||||
def update(self):
|
||||
self.transfer().addCallbacks(self._cbTransferred, self._ebTransferred)
|
||||
|
||||
|
||||
def _cbTransferred(self, result):
|
||||
self.transferring = False
|
||||
|
||||
|
||||
def _ebTransferred(self, failure):
|
||||
self.transferred = False
|
||||
log.msg("Transferring %s from %s failed after zone transfer" % (self.domain, self.primary))
|
||||
log.err(failure)
|
||||
Loading…
Add table
Add a link
Reference in a new issue