mirror of
https://github.com/Hopiu/linkchecker.git
synced 2026-03-17 06:20:27 +00:00
Move dnspython module into third_party directory.
This commit is contained in:
parent
dcd1318bce
commit
e1f724908d
122 changed files with 4740 additions and 3836 deletions
|
|
@ -52,5 +52,5 @@ include doc/de/*.1 doc/de/*.5
|
|||
include doc/Makefile
|
||||
include doc/examples/*.sh doc/examples/*.bat doc/examples/*.py
|
||||
include doc/examples/linkcheckerrc_loginurl
|
||||
include linkcheck/dns/changelog.txt
|
||||
recursive-include third_party *
|
||||
recursive-include tests *.py *.result *.html *.ico *.txt *.zip *.asc *.css *.xhtml *.sqlite *.adr *.swf
|
||||
|
|
|
|||
9
Makefile
9
Makefile
|
|
@ -15,10 +15,10 @@ PAGER ?= less
|
|||
BUILDDIR:=$(HOME)/packages/official
|
||||
DEB_ORIG_TARGET:=$(BUILDDIR)/linkchecker_$(VERSION).orig.tar.bz2
|
||||
# original dnspython repository module
|
||||
DNSPYTHON:=$(HOME)/src/dnspython-git/dns
|
||||
DNSPYTHON:=$(HOME)/src/dnspython-git
|
||||
# options to run the pep8 utility
|
||||
PEP8OPTS:=--repeat --ignore=E211,E501,E225,E301,E302,E241 \
|
||||
--exclude="dns,gzip2.py,httplib2.py,robotparser2.py,reindent.py"
|
||||
--exclude="gzip2.py,httplib2.py,robotparser2.py,reindent.py"
|
||||
PY2APPOPTS ?=
|
||||
|
||||
|
||||
|
|
@ -223,9 +223,12 @@ diff:
|
|||
diff -u linkcheck/$${f}2.py $(PYTHONSRC)/$${f}.py | $(PAGER); \
|
||||
done
|
||||
|
||||
# Compare dnspython files with the ones from upstream repository
|
||||
.PHONY: dnsdiff
|
||||
dnsdiff:
|
||||
diff -BurN --exclude=changelog.txt linkcheck/dns $(DNSPYTHON) | $(PAGER)
|
||||
@(for d in dns tests; do \
|
||||
diff -BurN --exclude=*.pyc third_party/dnspython/$$d $(DNSPYTHON)/$$d; \
|
||||
done) | $(PAGER)
|
||||
|
||||
.PHONY: changelog
|
||||
changelog:
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ def get_config_dir ():
|
|||
LOG_ROOT = "linkcheck"
|
||||
LOG_CMDLINE = "linkcheck.cmdline"
|
||||
LOG_CHECK = "linkcheck.check"
|
||||
LOG_DNS = "linkcheck.dns"
|
||||
LOG_CACHE = "linkcheck.cache"
|
||||
LOG_GUI = "linkcheck.gui"
|
||||
LOG_THREAD = "linkcheck.thread"
|
||||
|
|
@ -65,7 +64,6 @@ lognames = {
|
|||
"checking": LOG_CHECK,
|
||||
"cache": LOG_CACHE,
|
||||
"gui": LOG_GUI,
|
||||
"dns": LOG_DNS,
|
||||
"thread": LOG_THREAD,
|
||||
"all": LOG_ROOT,
|
||||
}
|
||||
|
|
@ -136,7 +134,7 @@ def init_i18n ():
|
|||
logging.addLevelName(logging.DEBUG, _('DEBUG'))
|
||||
logging.addLevelName(logging.NOTSET, _('NOTSET'))
|
||||
|
||||
# initialize i18n, puts _() function into global namespace
|
||||
# initialize i18n, puts _() and _n() function into global namespace
|
||||
init_i18n()
|
||||
|
||||
|
||||
|
|
@ -149,3 +147,13 @@ def drop_privileges ():
|
|||
"dropping privileges by changing user to nobody."))
|
||||
import pwd
|
||||
os.seteuid(pwd.getpwnam('nobody')[3])
|
||||
|
||||
|
||||
def find_third_party_modules ():
|
||||
"""Find third party modules and add them to the python path."""
|
||||
parent = os.path.dirname(os.path.dirname(__file__))
|
||||
third_party = os.path.join(parent, "third_party")
|
||||
if os.path.isdir(third_party):
|
||||
sys.path.append(os.path.join(third_party, "dnspython"))
|
||||
|
||||
find_third_party_modules()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import nntplib
|
|||
import ftplib
|
||||
import httplib as orighttplib
|
||||
from .. import LinkCheckerError, httplib2 as httplib
|
||||
from ..dns.exception import DNSException
|
||||
from dns.exception import DNSException
|
||||
|
||||
# Catch these exception on syntax checks.
|
||||
ExcSyntaxList = [
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ from email._parseaddr import AddressList
|
|||
|
||||
from . import urlbase
|
||||
from .. import log, LOG_CHECK, strformat, url as urlutil
|
||||
from ..dns import resolver
|
||||
from dns import resolver
|
||||
if False:
|
||||
# needed for py2exe to properly include all dns submodules
|
||||
from ..dns.rdtypes.ANY import *
|
||||
from ..dns.rdtypes.IN import *
|
||||
from dns.rdtypes.ANY import *
|
||||
from dns.rdtypes.IN import *
|
||||
from ..network import iputil
|
||||
from .const import WARN_MAIL_NO_MX_HOST, \
|
||||
WARN_MAIL_UNVERIFIED_ADDRESS, WARN_MAIL_NO_CONNECTION
|
||||
|
|
@ -249,7 +249,7 @@ class MailtoUrl (urlbase.UrlBase):
|
|||
"""
|
||||
Check a single mail address.
|
||||
"""
|
||||
from ..dns.exception import DNSException
|
||||
from dns.exception import DNSException
|
||||
log.debug(LOG_CHECK, "checking mail address %r", mail)
|
||||
mail = strformat.ascii_safe(mail)
|
||||
username, domain = mail.rsplit('@', 1)
|
||||
|
|
@ -275,7 +275,7 @@ class MailtoUrl (urlbase.UrlBase):
|
|||
mxdata = [(0, rdata.to_text(omit_final_dot=True))
|
||||
for rdata in answers]
|
||||
else:
|
||||
from linkcheck.dns.rdtypes.mxbase import MXBase
|
||||
from dns.rdtypes.mxbase import MXBase
|
||||
mxdata = [(rdata.preference,
|
||||
rdata.exchange.to_text(omit_final_dot=True))
|
||||
for rdata in answers if isinstance(rdata, MXBase)]
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""Common DNSSEC-related functions and constants."""
|
||||
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.rdataclass
|
||||
|
||||
RSAMD5 = 1
|
||||
DH = 2
|
||||
DSA = 3
|
||||
ECC = 4
|
||||
RSASHA1 = 5
|
||||
DSANSEC3SHA1 = 6
|
||||
RSASHA1NSEC3SHA1 = 7
|
||||
RSASHA256 = 8
|
||||
RSASHA512 = 10
|
||||
INDIRECT = 252
|
||||
PRIVATEDNS = 253
|
||||
PRIVATEOID = 254
|
||||
|
||||
_algorithm_by_text = {
|
||||
'RSAMD5' : RSAMD5,
|
||||
'DH' : DH,
|
||||
'DSA' : DSA,
|
||||
'ECC' : ECC,
|
||||
'RSASHA1' : RSASHA1,
|
||||
'DSANSEC3SHA1' : DSANSEC3SHA1,
|
||||
'RSASHA1NSEC3SHA1' : RSASHA1NSEC3SHA1,
|
||||
'RSASHA256' : RSASHA256,
|
||||
'RSASHA512' : RSASHA512,
|
||||
'INDIRECT' : INDIRECT,
|
||||
'PRIVATEDNS' : PRIVATEDNS,
|
||||
'PRIVATEOID' : PRIVATEOID,
|
||||
}
|
||||
|
||||
# We construct the inverse mapping programmatically to ensure that we
|
||||
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
|
||||
# would cause the mapping not to be true inverse.
|
||||
|
||||
_algorithm_by_value = dict([(y, x) for x, y in _algorithm_by_text.iteritems()])
|
||||
|
||||
class UnknownAlgorithm(StandardError):
|
||||
"""Raised if an algorithm is unknown."""
|
||||
pass
|
||||
|
||||
def algorithm_from_text(text):
|
||||
"""Convert text into a DNSSEC algorithm value
|
||||
@rtype: int"""
|
||||
|
||||
value = _algorithm_by_text.get(text.upper())
|
||||
if value is None:
|
||||
value = int(text)
|
||||
return value
|
||||
|
||||
def algorithm_to_text(value):
|
||||
"""Convert a DNSSEC algorithm value to text
|
||||
@rtype: string"""
|
||||
|
||||
text = _algorithm_by_value.get(value)
|
||||
if text is None:
|
||||
text = str(value)
|
||||
return text
|
||||
|
||||
def _to_rdata(record):
|
||||
from cStringIO import StringIO
|
||||
s = StringIO()
|
||||
record.to_wire(s)
|
||||
return s.getvalue()
|
||||
|
||||
def key_id(key):
|
||||
rdata = _to_rdata(key)
|
||||
if key.algorithm == RSAMD5:
|
||||
return (ord(rdata[-3]) << 8) + ord(rdata[-2])
|
||||
else:
|
||||
total = 0
|
||||
for i in range(len(rdata) / 2):
|
||||
total += (ord(rdata[2 * i]) << 8) + ord(rdata[2 * i + 1])
|
||||
if len(rdata) % 2 != 0:
|
||||
total += ord(rdata[len(rdata) - 1]) << 8
|
||||
total += ((total >> 16) & 0xffff);
|
||||
return total & 0xffff
|
||||
|
||||
def make_ds(name, key, algorithm):
|
||||
import hashlib
|
||||
import struct
|
||||
if algorithm.upper() == 'SHA1':
|
||||
dsalg = 1
|
||||
hash = hashlib.sha1()
|
||||
elif algorithm.upper() == 'SHA256':
|
||||
dsalg = 2
|
||||
hash = hashlib.sha256()
|
||||
else:
|
||||
raise ValueError, 'unsupported algorithm "%s"' % algorithm
|
||||
|
||||
if isinstance(name, basestring):
|
||||
name = linkcheck.dns.name.from_text(name)
|
||||
hash.update(name.canonicalize().to_wire())
|
||||
hash.update(_to_rdata(key))
|
||||
digest = hash.digest()
|
||||
|
||||
dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, dsalg) + digest
|
||||
return linkcheck.dns.rdata.from_wire(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.DS, dsrdata, 0, len(dsrdata))
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.keybase
|
||||
|
||||
# flag constants
|
||||
SEP = 0x0001
|
||||
REVOKE = 0x0080
|
||||
ZONE = 0x0100
|
||||
|
||||
class DNSKEY(linkcheck.dns.rdtypes.keybase.KEYBase):
|
||||
"""DNSKEY record"""
|
||||
pass
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.keybase
|
||||
|
||||
class KEY(linkcheck.dns.rdtypes.keybase.KEYBase):
|
||||
"""KEY record"""
|
||||
pass
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.name
|
||||
|
||||
class NXT(linkcheck.dns.rdata.Rdata):
|
||||
"""NXT record
|
||||
|
||||
@ivar next: the next name
|
||||
@type next: linkcheck.dns.name.Name object
|
||||
@ivar bitmap: the type bitmap
|
||||
@type bitmap: string
|
||||
@see: RFC 2535"""
|
||||
|
||||
__slots__ = ['next', 'bitmap']
|
||||
|
||||
def __init__(self, rdclass, rdtype, next, bitmap):
|
||||
super(NXT, self).__init__(rdclass, rdtype)
|
||||
self.next = next
|
||||
self.bitmap = bitmap
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
next = self.next.choose_relativity(origin, relativize)
|
||||
bits = []
|
||||
for i in xrange(0, len(self.bitmap)):
|
||||
byte = ord(self.bitmap[i])
|
||||
for j in xrange(0, 8):
|
||||
if byte & (0x80 >> j):
|
||||
bits.append(linkcheck.dns.rdatatype.to_text(i * 8 + j))
|
||||
text = ' '.join(bits)
|
||||
return '%s %s' % (next, text)
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
next = tok.get_name()
|
||||
next = next.choose_relativity(origin, relativize)
|
||||
bitmap = ['\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00',
|
||||
'\x00', '\x00', '\x00', '\x00' ]
|
||||
while 1:
|
||||
token = tok.get().unescape()
|
||||
if token.is_eol_or_eof():
|
||||
break
|
||||
if token.value.isdigit():
|
||||
nrdtype = int(token.value)
|
||||
else:
|
||||
nrdtype = linkcheck.dns.rdatatype.from_text(token.value)
|
||||
if nrdtype == 0:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("NXT with bit 0")
|
||||
if nrdtype > 127:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("NXT with bit > 127")
|
||||
i = nrdtype // 8
|
||||
bitmap[i] = chr(ord(bitmap[i]) | (0x80 >> (nrdtype % 8)))
|
||||
bitmap = linkcheck.dns.rdata._truncate_bitmap(bitmap)
|
||||
return cls(rdclass, rdtype, next, bitmap)
|
||||
|
||||
from_text = classmethod(from_text)
|
||||
|
||||
def to_wire(self, file, compress = None, origin = None):
|
||||
self.next.to_wire(file, None, origin)
|
||||
file.write(self.bitmap)
|
||||
|
||||
def to_digestable(self, origin = None):
|
||||
return self.next.to_digestable(origin) + self.bitmap
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
(next, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen], current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
bitmap = wire[current : current + rdlen]
|
||||
if not origin is None:
|
||||
next = next.relativize(origin)
|
||||
return cls(rdclass, rdtype, next, bitmap)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
||||
def choose_relativity(self, origin = None, relativize = True):
|
||||
self.next = self.next.choose_relativity(origin, relativize)
|
||||
|
||||
def _cmp(self, other):
|
||||
v = cmp(self.next, other.next)
|
||||
if v == 0:
|
||||
v = cmp(self.bitmap, other.bitmap)
|
||||
return v
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import struct
|
||||
import linkcheck.dns.rdtypes.sigbase
|
||||
|
||||
class SIG(linkcheck.dns.rdtypes.sigbase.SIGBase):
|
||||
"""SIG record"""
|
||||
def to_digestable(self, origin = None):
|
||||
return struct.pack('!HBBIIIH', self.type_covered,
|
||||
self.algorithm, self.labels,
|
||||
self.original_ttl, self.expiration,
|
||||
self.inception, self.key_tag) + \
|
||||
self.signer.to_digestable(origin) + \
|
||||
self.signature
|
||||
|
|
@ -8,7 +8,7 @@ import array
|
|||
import struct
|
||||
import subprocess
|
||||
from _network import ifreq_size
|
||||
from .. import log, LOG_DNS
|
||||
from .. import log, LOG_CHECK
|
||||
|
||||
|
||||
def pipecmd (cmd1, cmd2):
|
||||
|
|
@ -89,7 +89,7 @@ class IfConfig (object):
|
|||
try:
|
||||
result = self._ioctl(func, self._getifreq(ifname))
|
||||
except IOError, msg:
|
||||
log.warn(LOG_DNS,
|
||||
log.warn(LOG_CHECK,
|
||||
"error getting addr for interface %r: %s", ifname, msg)
|
||||
return None
|
||||
return socket.inet_ntoa(result[20:24])
|
||||
|
|
@ -140,7 +140,7 @@ class IfConfig (object):
|
|||
try:
|
||||
result = self._ioctl(self.SIOCGIFFLAGS, self._getifreq(ifname))
|
||||
except IOError, msg:
|
||||
log.warn(LOG_DNS,
|
||||
log.warn(LOG_CHECK,
|
||||
"error getting flags for interface %r: %s", ifname, msg)
|
||||
return 0
|
||||
# extract the interface's flags from the return value
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ Ip number related utility functions.
|
|||
import re
|
||||
import socket
|
||||
import struct
|
||||
from .. import log, LOG_DNS
|
||||
from .. import log, LOG_CHECK
|
||||
|
||||
|
||||
# IP Adress regular expressions
|
||||
|
|
@ -213,20 +213,20 @@ def hosts2map (hosts):
|
|||
host, mask = host.split("/")
|
||||
mask = int(mask)
|
||||
if not is_valid_cidrmask(mask):
|
||||
log.error(LOG_DNS,
|
||||
log.error(LOG_CHECK,
|
||||
"CIDR mask %d is not a valid network mask", mask)
|
||||
continue
|
||||
if not is_valid_ipv4(host):
|
||||
log.error(LOG_DNS, "host %r is not a valid ip address", host)
|
||||
log.error(LOG_CHECK, "host %r is not a valid ip address", host)
|
||||
continue
|
||||
nets.append(dq2net(host, cidr2mask(mask)))
|
||||
elif _host_netmask_re.match(host):
|
||||
host, mask = host.split("/")
|
||||
if not is_valid_ipv4(host):
|
||||
log.error(LOG_DNS, "host %r is not a valid ip address", host)
|
||||
log.error(LOG_CHECK, "host %r is not a valid ip address", host)
|
||||
continue
|
||||
if not is_valid_ipv4(mask):
|
||||
log.error(LOG_DNS,
|
||||
log.error(LOG_CHECK,
|
||||
"mask %r is not a valid ip network mask", mask)
|
||||
continue
|
||||
nets.append(dq2net(host, netmask2mask(mask)))
|
||||
|
|
@ -274,7 +274,7 @@ def resolve_host (host):
|
|||
# add first ip of socket address
|
||||
ips.add(res[4][0])
|
||||
except socket.error:
|
||||
log.info(LOG_DNS, "Ignored invalid host %r", host)
|
||||
log.info(LOG_CHECK, "Ignored invalid host %r", host)
|
||||
return ips
|
||||
|
||||
|
||||
|
|
|
|||
22
setup.py
22
setup.py
|
|
@ -680,13 +680,25 @@ o a (Fast)CGI web interface (requires HTTP server)
|
|||
'py2app': MyPy2app,
|
||||
'register': MyRegister,
|
||||
},
|
||||
package_dir = {
|
||||
'dns': 'third_party/dnspython/dns',
|
||||
},
|
||||
packages = [
|
||||
'linkcheck', 'linkcheck.logger', 'linkcheck.checker',
|
||||
'linkcheck.director', 'linkcheck.configuration', 'linkcheck.cache',
|
||||
'linkcheck.htmlutil', 'linkcheck.dns', 'linkcheck.dns.rdtypes',
|
||||
'linkcheck.dns.rdtypes.ANY', 'linkcheck.dns.rdtypes.IN',
|
||||
'linkcheck.HtmlParser', 'linkcheck.network', 'linkcheck.gui',
|
||||
'linkcheck',
|
||||
'linkcheck.bookmarks',
|
||||
'linkcheck.cache',
|
||||
'linkcheck.checker',
|
||||
'linkcheck.configuration',
|
||||
'linkcheck.director',
|
||||
'linkcheck.gui',
|
||||
'linkcheck.htmlutil',
|
||||
'linkcheck.HtmlParser',
|
||||
'linkcheck.logger',
|
||||
'linkcheck.network',
|
||||
'dns',
|
||||
'dns.rdtypes',
|
||||
'dns.rdtypes.ANY',
|
||||
'dns.rdtypes.IN',
|
||||
],
|
||||
ext_modules = [
|
||||
Extension('linkcheck.HtmlParser.htmlsax',
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.flags
|
||||
import linkcheck.dns.rcode
|
||||
import linkcheck.dns.opcode
|
||||
|
||||
class TestFlags (unittest.TestCase):
|
||||
|
||||
def test_rcode1(self):
|
||||
self.assertEqual(linkcheck.dns.rcode.from_text('FORMERR'),
|
||||
linkcheck.dns.rcode.FORMERR)
|
||||
|
||||
def test_rcode2(self):
|
||||
self.assertEqual(linkcheck.dns.rcode.to_text(linkcheck.dns.rcode.FORMERR),
|
||||
"FORMERR")
|
||||
|
||||
def test_rcode3(self):
|
||||
self.assertEqual(linkcheck.dns.rcode.to_flags(linkcheck.dns.rcode.FORMERR), (1, 0))
|
||||
|
||||
def test_rcode4(self):
|
||||
self.assertEqual(linkcheck.dns.rcode.to_flags(linkcheck.dns.rcode.BADVERS),
|
||||
(0, 0x01000000))
|
||||
|
||||
def test_rcode5(self):
|
||||
self.assertEqual(linkcheck.dns.rcode.from_flags(0, 0x01000000),
|
||||
linkcheck.dns.rcode.BADVERS)
|
||||
|
||||
def test_rcode6(self):
|
||||
self.assertEqual(linkcheck.dns.rcode.from_flags(5, 0), linkcheck.dns.rcode.REFUSED)
|
||||
|
||||
def test_rcode7(self):
|
||||
def bad():
|
||||
linkcheck.dns.rcode.to_flags(4096)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def test_flags1(self):
|
||||
self.assertEqual(linkcheck.dns.flags.from_text("RA RD AA QR"),
|
||||
linkcheck.dns.flags.QR|linkcheck.dns.flags.AA|linkcheck.dns.flags.RD|linkcheck.dns.flags.RA)
|
||||
|
||||
def test_flags2(self):
|
||||
flgs = linkcheck.dns.flags.QR|linkcheck.dns.flags.AA|linkcheck.dns.flags.RD|linkcheck.dns.flags.RA
|
||||
self.assertEqual(linkcheck.dns.flags.to_text(flgs), "QR AA RD RA")
|
||||
|
|
@ -1,704 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
import socket
|
||||
from cStringIO import StringIO
|
||||
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.reversename
|
||||
import linkcheck.dns.e164
|
||||
|
||||
|
||||
class TestName (unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.origin = linkcheck.dns.name.from_text('example.')
|
||||
|
||||
def testFromTextRel1(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar')
|
||||
self.assertEqual(n.labels, ('foo', 'bar', ''))
|
||||
|
||||
def testFromTextRel2(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar', origin=self.origin)
|
||||
self.assertEqual(n.labels, ('foo', 'bar', 'example', ''))
|
||||
|
||||
def testFromTextRel3(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar', origin=None)
|
||||
self.assertEqual(n.labels, ('foo', 'bar'))
|
||||
|
||||
def testFromTextRel4(self):
|
||||
n = linkcheck.dns.name.from_text('@', origin=None)
|
||||
self.assertEqual(n, linkcheck.dns.name.empty)
|
||||
|
||||
def testFromTextRel5(self):
|
||||
n = linkcheck.dns.name.from_text('@', origin=self.origin)
|
||||
self.assertEqual(n, self.origin)
|
||||
|
||||
def testFromTextAbs1(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
self.assertEqual(n.labels, ('foo', 'bar', ''))
|
||||
|
||||
def testTortureFromText(self):
|
||||
good = [
|
||||
r'.',
|
||||
r'a',
|
||||
r'a.',
|
||||
r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
r'\000.\008.\010.\032.\046.\092.\099.\255',
|
||||
r'\\',
|
||||
r'\..\.',
|
||||
r'\\.\\',
|
||||
r'!"#%&/()=+-',
|
||||
r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255',
|
||||
]
|
||||
bad = [
|
||||
r'..',
|
||||
r'.a',
|
||||
r'\\..',
|
||||
'\\', # yes, we don't want the 'r' prefix!
|
||||
r'\0',
|
||||
r'\00',
|
||||
r'\00Z',
|
||||
r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255',
|
||||
]
|
||||
for t in good:
|
||||
try:
|
||||
n = linkcheck.dns.name.from_text(t)
|
||||
except StandardError:
|
||||
self.fail("good test '%s' raised an exception" % t)
|
||||
for t in bad:
|
||||
caught = False
|
||||
try:
|
||||
n = linkcheck.dns.name.from_text(t)
|
||||
except StandardError:
|
||||
caught = True
|
||||
if not caught:
|
||||
self.fail("bad test '%s' did not raise an exception" % t)
|
||||
|
||||
def testImmutable1(self):
|
||||
def bad():
|
||||
self.origin.labels = ()
|
||||
self.assertRaises(TypeError, bad)
|
||||
|
||||
def testImmutable2(self):
|
||||
def bad():
|
||||
self.origin.labels[0] = 'foo'
|
||||
self.assertRaises(TypeError, bad)
|
||||
|
||||
def testAbs1(self):
|
||||
self.assertTrue(linkcheck.dns.name.root.is_absolute())
|
||||
|
||||
def testAbs2(self):
|
||||
self.assertTrue(not linkcheck.dns.name.empty.is_absolute())
|
||||
|
||||
def testAbs3(self):
|
||||
self.assertTrue(self.origin.is_absolute())
|
||||
|
||||
def testAbs4(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=None)
|
||||
self.assertTrue(not n.is_absolute())
|
||||
|
||||
def testWild1(self):
|
||||
n = linkcheck.dns.name.from_text('*.foo', origin=None)
|
||||
self.assertTrue(n.is_wild())
|
||||
|
||||
def testWild2(self):
|
||||
n = linkcheck.dns.name.from_text('*a.foo', origin=None)
|
||||
self.assertTrue(not n.is_wild())
|
||||
|
||||
def testWild3(self):
|
||||
n = linkcheck.dns.name.from_text('a.*.foo', origin=None)
|
||||
self.assertTrue(not n.is_wild())
|
||||
|
||||
def testWild4(self):
|
||||
self.assertTrue(not linkcheck.dns.name.root.is_wild())
|
||||
|
||||
def testWild5(self):
|
||||
self.assertTrue(not linkcheck.dns.name.empty.is_wild())
|
||||
|
||||
def testHash1(self):
|
||||
n1 = linkcheck.dns.name.from_text('fOo.COM')
|
||||
n2 = linkcheck.dns.name.from_text('foo.com')
|
||||
self.assertEqual(hash(n1), hash(n2))
|
||||
|
||||
def testCompare1(self):
|
||||
n1 = linkcheck.dns.name.from_text('a')
|
||||
n2 = linkcheck.dns.name.from_text('b')
|
||||
self.assertTrue(n1 < n2)
|
||||
self.assertTrue(n2 > n1)
|
||||
|
||||
def testCompare2(self):
|
||||
n1 = linkcheck.dns.name.from_text('')
|
||||
n2 = linkcheck.dns.name.from_text('b')
|
||||
self.assertTrue(n1 < n2)
|
||||
self.assertTrue(n2 > n1)
|
||||
|
||||
def testCompare3(self):
|
||||
self.assertTrue(linkcheck.dns.name.empty < linkcheck.dns.name.root)
|
||||
self.assertTrue(linkcheck.dns.name.root > linkcheck.dns.name.empty)
|
||||
|
||||
def testCompare4(self):
|
||||
self.assertNotEqual(linkcheck.dns.name.root, 1)
|
||||
|
||||
def testCompare5(self):
|
||||
self.assertTrue(linkcheck.dns.name.root < 1 or linkcheck.dns.name.root > 1)
|
||||
|
||||
def testSubdomain1(self):
|
||||
self.assertTrue(not linkcheck.dns.name.empty.is_subdomain(linkcheck.dns.name.root))
|
||||
|
||||
def testSubdomain2(self):
|
||||
self.assertTrue(not linkcheck.dns.name.root.is_subdomain(linkcheck.dns.name.empty))
|
||||
|
||||
def testSubdomain3(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=self.origin)
|
||||
self.assertTrue(n.is_subdomain(self.origin))
|
||||
|
||||
def testSubdomain4(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=self.origin)
|
||||
self.assertTrue(n.is_subdomain(linkcheck.dns.name.root))
|
||||
|
||||
def testSubdomain5(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=self.origin)
|
||||
self.assertTrue(n.is_subdomain(n))
|
||||
|
||||
def testSuperdomain1(self):
|
||||
self.assertTrue(not linkcheck.dns.name.empty.is_superdomain(linkcheck.dns.name.root))
|
||||
|
||||
def testSuperdomain2(self):
|
||||
self.assertTrue(not linkcheck.dns.name.root.is_superdomain(linkcheck.dns.name.empty))
|
||||
|
||||
def testSuperdomain3(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=self.origin)
|
||||
self.assertTrue(self.origin.is_superdomain(n))
|
||||
|
||||
def testSuperdomain4(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=self.origin)
|
||||
self.assertTrue(linkcheck.dns.name.root.is_superdomain(n))
|
||||
|
||||
def testSuperdomain5(self):
|
||||
n = linkcheck.dns.name.from_text('foo', origin=self.origin)
|
||||
self.assertTrue(n.is_superdomain(n))
|
||||
|
||||
def testCanonicalize1(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', origin=self.origin)
|
||||
c = n.canonicalize()
|
||||
self.assertEqual(c.labels, ('foo', 'bar', 'example', ''))
|
||||
|
||||
def testToText1(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', origin=self.origin)
|
||||
t = n.to_text()
|
||||
self.assertEqual(t, 'FOO.bar.example.')
|
||||
|
||||
def testToText2(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', origin=self.origin)
|
||||
t = n.to_text(True)
|
||||
self.assertEqual(t, 'FOO.bar.example')
|
||||
|
||||
def testToText3(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', origin=None)
|
||||
t = n.to_text()
|
||||
self.assertEqual(t, 'FOO.bar')
|
||||
|
||||
def testToText4(self):
|
||||
t = linkcheck.dns.name.empty.to_text()
|
||||
self.assertEqual(t, '@')
|
||||
|
||||
def testToText5(self):
|
||||
t = linkcheck.dns.name.root.to_text()
|
||||
self.assertEqual(t, '.')
|
||||
|
||||
def testToText6(self):
|
||||
n = linkcheck.dns.name.from_text('FOO bar', origin=None)
|
||||
t = n.to_text()
|
||||
self.assertEqual(t, r'FOO\032bar')
|
||||
|
||||
def testToText7(self):
|
||||
n = linkcheck.dns.name.from_text(r'FOO\.bar', origin=None)
|
||||
t = n.to_text()
|
||||
self.assertEqual(t, r'FOO\.bar')
|
||||
|
||||
def testToText8(self):
|
||||
n = linkcheck.dns.name.from_text(r'\070OO\.bar', origin=None)
|
||||
t = n.to_text()
|
||||
self.assertEqual(t, r'FOO\.bar')
|
||||
|
||||
def testSlice1(self):
|
||||
n = linkcheck.dns.name.from_text(r'a.b.c.', origin=None)
|
||||
s = n[:]
|
||||
self.assertEqual(s, ('a', 'b', 'c', ''))
|
||||
|
||||
def testSlice2(self):
|
||||
n = linkcheck.dns.name.from_text(r'a.b.c.', origin=None)
|
||||
s = n[:2]
|
||||
self.assertEqual(s, ('a', 'b'))
|
||||
|
||||
def testSlice3(self):
|
||||
n = linkcheck.dns.name.from_text(r'a.b.c.', origin=None)
|
||||
s = n[2:]
|
||||
self.assertEqual(s, ('c', ''))
|
||||
|
||||
def testEmptyLabel1(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.Name(['a', '', 'b'])
|
||||
self.assertRaises(linkcheck.dns.name.EmptyLabel, bad)
|
||||
|
||||
def testEmptyLabel2(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.Name(['', 'b'])
|
||||
self.assertRaises(linkcheck.dns.name.EmptyLabel, bad)
|
||||
|
||||
def testEmptyLabel3(self):
|
||||
n = linkcheck.dns.name.Name(['b', ''])
|
||||
self.assertTrue(n)
|
||||
|
||||
def testLongLabel(self):
|
||||
n = linkcheck.dns.name.Name(['a' * 63])
|
||||
self.assertTrue(n)
|
||||
|
||||
def testLabelTooLong(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.Name(['a' * 64, 'b'])
|
||||
self.assertRaises(linkcheck.dns.name.LabelTooLong, bad)
|
||||
|
||||
def testLongName(self):
|
||||
n = linkcheck.dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 62])
|
||||
self.assertTrue(n)
|
||||
|
||||
def testNameTooLong(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 63])
|
||||
self.assertRaises(linkcheck.dns.name.NameTooLong, bad)
|
||||
|
||||
def testConcat1(self):
|
||||
n1 = linkcheck.dns.name.Name(['a', 'b'])
|
||||
n2 = linkcheck.dns.name.Name(['c', 'd'])
|
||||
e = linkcheck.dns.name.Name(['a', 'b', 'c', 'd'])
|
||||
r = n1 + n2
|
||||
self.assertEqual(r, e)
|
||||
|
||||
def testConcat2(self):
|
||||
n1 = linkcheck.dns.name.Name(['a', 'b'])
|
||||
n2 = linkcheck.dns.name.Name([])
|
||||
e = linkcheck.dns.name.Name(['a', 'b'])
|
||||
r = n1 + n2
|
||||
self.assertEqual(r, e)
|
||||
|
||||
def testConcat2a(self):
|
||||
n1 = linkcheck.dns.name.Name([])
|
||||
n2 = linkcheck.dns.name.Name(['a', 'b'])
|
||||
e = linkcheck.dns.name.Name(['a', 'b'])
|
||||
r = n1 + n2
|
||||
self.assertEqual(r, e)
|
||||
|
||||
def testConcat3(self):
|
||||
n1 = linkcheck.dns.name.Name(['a', 'b', ''])
|
||||
n2 = linkcheck.dns.name.Name([])
|
||||
e = linkcheck.dns.name.Name(['a', 'b', ''])
|
||||
r = n1 + n2
|
||||
self.assertEqual(r, e)
|
||||
|
||||
def testConcat4(self):
|
||||
n1 = linkcheck.dns.name.Name(['a', 'b'])
|
||||
n2 = linkcheck.dns.name.Name(['c', ''])
|
||||
e = linkcheck.dns.name.Name(['a', 'b', 'c', ''])
|
||||
r = n1 + n2
|
||||
self.assertEqual(r, e)
|
||||
|
||||
def testConcat5(self):
|
||||
def bad():
|
||||
n1 = linkcheck.dns.name.Name(['a', 'b', ''])
|
||||
n2 = linkcheck.dns.name.Name(['c'])
|
||||
r = n1 + n2
|
||||
self.assertRaises(linkcheck.dns.name.AbsoluteConcatenation, bad)
|
||||
|
||||
def testBadEscape(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.from_text(r'a.b\0q1.c.')
|
||||
print n
|
||||
self.assertRaises(linkcheck.dns.name.BadEscape, bad)
|
||||
|
||||
def testDigestable1(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar')
|
||||
d = n.to_digestable()
|
||||
self.assertEqual(d, '\x03foo\x03bar\x00')
|
||||
|
||||
def testDigestable2(self):
|
||||
n1 = linkcheck.dns.name.from_text('FOO.bar')
|
||||
n2 = linkcheck.dns.name.from_text('foo.BAR.')
|
||||
d1 = n1.to_digestable()
|
||||
d2 = n2.to_digestable()
|
||||
self.assertEqual(d1, d2)
|
||||
|
||||
def testDigestable3(self):
|
||||
d = linkcheck.dns.name.root.to_digestable()
|
||||
self.assertEqual(d, '\x00')
|
||||
|
||||
def testDigestable4(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', None)
|
||||
d = n.to_digestable(linkcheck.dns.name.root)
|
||||
self.assertEqual(d, '\x03foo\x03bar\x00')
|
||||
|
||||
def testBadDigestable(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', None)
|
||||
d = n.to_digestable()
|
||||
self.assertRaises(linkcheck.dns.name.NeedAbsoluteNameOrOrigin, bad)
|
||||
|
||||
def testToWire1(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar')
|
||||
f = StringIO()
|
||||
compress = {}
|
||||
n.to_wire(f, compress)
|
||||
self.assertEqual(f.getvalue(), '\x03FOO\x03bar\x00')
|
||||
|
||||
def testToWire2(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar')
|
||||
f = StringIO()
|
||||
compress = {}
|
||||
n.to_wire(f, compress)
|
||||
n.to_wire(f, compress)
|
||||
self.assertEqual(f.getvalue(), '\x03FOO\x03bar\x00\xc0\x00')
|
||||
|
||||
def testToWire3(self):
|
||||
n1 = linkcheck.dns.name.from_text('FOO.bar')
|
||||
n2 = linkcheck.dns.name.from_text('foo.bar')
|
||||
f = StringIO()
|
||||
compress = {}
|
||||
n1.to_wire(f, compress)
|
||||
n2.to_wire(f, compress)
|
||||
self.assertEqual(f.getvalue(), '\x03FOO\x03bar\x00\xc0\x00')
|
||||
|
||||
def testToWire4(self):
|
||||
n1 = linkcheck.dns.name.from_text('FOO.bar')
|
||||
n2 = linkcheck.dns.name.from_text('a.foo.bar')
|
||||
f = StringIO()
|
||||
compress = {}
|
||||
n1.to_wire(f, compress)
|
||||
n2.to_wire(f, compress)
|
||||
self.assertEqual(f.getvalue(), '\x03FOO\x03bar\x00\x01\x61\xc0\x00')
|
||||
|
||||
def testToWire5(self):
|
||||
n1 = linkcheck.dns.name.from_text('FOO.bar')
|
||||
n2 = linkcheck.dns.name.from_text('a.foo.bar')
|
||||
f = StringIO()
|
||||
compress = {}
|
||||
n1.to_wire(f, compress)
|
||||
n2.to_wire(f, None)
|
||||
self.assertEqual(f.getvalue(),
|
||||
'\x03FOO\x03bar\x00\x01\x61\x03foo\x03bar\x00')
|
||||
|
||||
def testToWire6(self):
|
||||
n = linkcheck.dns.name.from_text('FOO.bar')
|
||||
v = n.to_wire()
|
||||
self.assertEqual(v, '\x03FOO\x03bar\x00')
|
||||
|
||||
def testBadToWire(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.from_text('FOO.bar', None)
|
||||
f = StringIO()
|
||||
compress = {}
|
||||
n.to_wire(f, compress)
|
||||
self.assertRaises(linkcheck.dns.name.NeedAbsoluteNameOrOrigin, bad)
|
||||
|
||||
def testSplit1(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
(prefix, suffix) = n.split(2)
|
||||
ep = linkcheck.dns.name.from_text('foo', None)
|
||||
es = linkcheck.dns.name.from_text('bar.', None)
|
||||
self.assertEqual(prefix, ep)
|
||||
self.assertEqual(suffix, es)
|
||||
|
||||
def testSplit2(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
(prefix, suffix) = n.split(1)
|
||||
ep = linkcheck.dns.name.from_text('foo.bar', None)
|
||||
es = linkcheck.dns.name.from_text('.', None)
|
||||
self.assertEqual(prefix, ep)
|
||||
self.assertEqual(suffix, es)
|
||||
|
||||
def testSplit3(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
(prefix, suffix) = n.split(0)
|
||||
ep = linkcheck.dns.name.from_text('foo.bar.', None)
|
||||
es = linkcheck.dns.name.from_text('', None)
|
||||
self.assertEqual(prefix, ep)
|
||||
self.assertEqual(suffix, es)
|
||||
|
||||
def testSplit4(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
(prefix, suffix) = n.split(3)
|
||||
ep = linkcheck.dns.name.from_text('', None)
|
||||
es = linkcheck.dns.name.from_text('foo.bar.', None)
|
||||
self.assertEqual(prefix, ep)
|
||||
self.assertEqual(suffix, es)
|
||||
|
||||
def testBadSplit1(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
(prefix, suffix) = n.split(-1)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def testBadSplit2(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
(prefix, suffix) = n.split(4)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def testRelativize1(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
o = linkcheck.dns.name.from_text('bar.', None)
|
||||
e = linkcheck.dns.name.from_text('a.foo', None)
|
||||
self.assertEqual(n.relativize(o), e)
|
||||
|
||||
def testRelativize2(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
o = n
|
||||
e = linkcheck.dns.name.empty
|
||||
self.assertEqual(n.relativize(o), e)
|
||||
|
||||
def testRelativize3(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
o = linkcheck.dns.name.from_text('blaz.', None)
|
||||
e = n
|
||||
self.assertEqual(n.relativize(o), e)
|
||||
|
||||
def testRelativize4(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo', None)
|
||||
o = linkcheck.dns.name.root
|
||||
e = n
|
||||
self.assertEqual(n.relativize(o), e)
|
||||
|
||||
def testDerelativize1(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo', None)
|
||||
o = linkcheck.dns.name.from_text('bar.', None)
|
||||
e = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
self.assertEqual(n.derelativize(o), e)
|
||||
|
||||
def testDerelativize2(self):
|
||||
n = linkcheck.dns.name.empty
|
||||
o = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
e = o
|
||||
self.assertEqual(n.derelativize(o), e)
|
||||
|
||||
def testDerelativize3(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
o = linkcheck.dns.name.from_text('blaz.', None)
|
||||
e = n
|
||||
self.assertEqual(n.derelativize(o), e)
|
||||
|
||||
def testChooseRelativity1(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
o = linkcheck.dns.name.from_text('bar.', None)
|
||||
e = linkcheck.dns.name.from_text('a.foo', None)
|
||||
self.assertEqual(n.choose_relativity(o, True), e)
|
||||
|
||||
def testChooseRelativity2(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
o = linkcheck.dns.name.from_text('bar.', None)
|
||||
e = n
|
||||
self.assertEqual(n.choose_relativity(o, False), e)
|
||||
|
||||
def testChooseRelativity3(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo', None)
|
||||
o = linkcheck.dns.name.from_text('bar.', None)
|
||||
e = linkcheck.dns.name.from_text('a.foo.bar.', None)
|
||||
self.assertEqual(n.choose_relativity(o, False), e)
|
||||
|
||||
def testChooseRelativity4(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo', None)
|
||||
o = None
|
||||
e = n
|
||||
self.assertEqual(n.choose_relativity(o, True), e)
|
||||
|
||||
def testChooseRelativity5(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo', None)
|
||||
o = None
|
||||
e = n
|
||||
self.assertEqual(n.choose_relativity(o, False), e)
|
||||
|
||||
def testChooseRelativity6(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.', None)
|
||||
o = None
|
||||
e = n
|
||||
self.assertEqual(n.choose_relativity(o, True), e)
|
||||
|
||||
def testChooseRelativity7(self):
|
||||
n = linkcheck.dns.name.from_text('a.foo.', None)
|
||||
o = None
|
||||
e = n
|
||||
self.assertEqual(n.choose_relativity(o, False), e)
|
||||
|
||||
def testFromWire1(self):
|
||||
w = '\x03foo\x00\xc0\x00'
|
||||
(n1, cused1) = linkcheck.dns.name.from_wire(w, 0)
|
||||
(n2, cused2) = linkcheck.dns.name.from_wire(w, cused1)
|
||||
en1 = linkcheck.dns.name.from_text('foo.')
|
||||
en2 = en1
|
||||
ecused1 = 5
|
||||
ecused2 = 2
|
||||
self.assertEqual(n1, en1)
|
||||
self.assertEqual(cused1, ecused1)
|
||||
self.assertEqual(n2, en2)
|
||||
self.assertEqual(cused2, ecused2)
|
||||
|
||||
def testFromWire2(self):
|
||||
w = '\x03foo\x00\x01a\xc0\x00\x01b\xc0\x05'
|
||||
current = 0
|
||||
(n1, cused1) = linkcheck.dns.name.from_wire(w, current)
|
||||
current += cused1
|
||||
(n2, cused2) = linkcheck.dns.name.from_wire(w, current)
|
||||
current += cused2
|
||||
(n3, cused3) = linkcheck.dns.name.from_wire(w, current)
|
||||
en1 = linkcheck.dns.name.from_text('foo.')
|
||||
en2 = linkcheck.dns.name.from_text('a.foo.')
|
||||
en3 = linkcheck.dns.name.from_text('b.a.foo.')
|
||||
ecused1 = 5
|
||||
ecused2 = 4
|
||||
ecused3 = 4
|
||||
self.assertEqual(n1, en1)
|
||||
self.assertEqual(cused1, ecused1)
|
||||
self.assertEqual(n2, en2)
|
||||
self.assertEqual(cused2, ecused2)
|
||||
self.assertEqual(n3, en3)
|
||||
self.assertEqual(cused3, ecused3)
|
||||
|
||||
def testBadFromWire1(self):
|
||||
def bad():
|
||||
w = '\x03foo\xc0\x04'
|
||||
(n, cused) = linkcheck.dns.name.from_wire(w, 0)
|
||||
self.assertRaises(linkcheck.dns.name.BadPointer, bad)
|
||||
|
||||
def testBadFromWire2(self):
|
||||
def bad():
|
||||
w = '\x03foo\xc0\x05'
|
||||
(n, cused) = linkcheck.dns.name.from_wire(w, 0)
|
||||
self.assertRaises(linkcheck.dns.name.BadPointer, bad)
|
||||
|
||||
def testBadFromWire3(self):
|
||||
def bad():
|
||||
w = '\xbffoo'
|
||||
(n, cused) = linkcheck.dns.name.from_wire(w, 0)
|
||||
self.assertRaises(linkcheck.dns.name.BadLabelType, bad)
|
||||
|
||||
def testBadFromWire4(self):
|
||||
def bad():
|
||||
w = '\x41foo'
|
||||
(n, cused) = linkcheck.dns.name.from_wire(w, 0)
|
||||
self.assertRaises(linkcheck.dns.name.BadLabelType, bad)
|
||||
|
||||
def testParent1(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar.')
|
||||
self.assertEqual(n.parent(), linkcheck.dns.name.from_text('bar.'))
|
||||
self.assertEqual(n.parent().parent(), linkcheck.dns.name.root)
|
||||
|
||||
def testParent2(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar', None)
|
||||
self.assertEqual(n.parent(), linkcheck.dns.name.from_text('bar', None))
|
||||
self.assertEqual(n.parent().parent(), linkcheck.dns.name.empty)
|
||||
|
||||
def testParent3(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.root
|
||||
n.parent()
|
||||
self.assertRaises(linkcheck.dns.name.NoParent, bad)
|
||||
|
||||
def testParent4(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.empty
|
||||
n.parent()
|
||||
self.assertRaises(linkcheck.dns.name.NoParent, bad)
|
||||
|
||||
def testFromUnicode1(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo.bar')
|
||||
self.assertEqual(n.labels, ('foo', 'bar', ''))
|
||||
|
||||
def testFromUnicode2(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo\u1234bar.bar')
|
||||
self.assertEqual(n.labels, ('xn--foobar-r5z', 'bar', ''))
|
||||
|
||||
def testFromUnicodeAlternateDot1(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo\u3002bar')
|
||||
self.assertEqual(n.labels, ('foo', 'bar', ''))
|
||||
|
||||
def testFromUnicodeAlternateDot2(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo\uff0ebar')
|
||||
self.assertEqual(n.labels, ('foo', 'bar', ''))
|
||||
|
||||
def testFromUnicodeAlternateDot3(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo\uff61bar')
|
||||
self.assertEqual(n.labels, ('foo', 'bar', ''))
|
||||
|
||||
def testToUnicode1(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo.bar')
|
||||
s = n.to_unicode()
|
||||
self.assertEqual(s, u'foo.bar.')
|
||||
|
||||
def testToUnicode2(self):
|
||||
n = linkcheck.dns.name.from_text(u'foo\u1234bar.bar')
|
||||
s = n.to_unicode()
|
||||
self.assertEqual(s, u'foo\u1234bar.bar.')
|
||||
|
||||
def testToUnicode3(self):
|
||||
n = linkcheck.dns.name.from_text('foo.bar')
|
||||
s = n.to_unicode()
|
||||
self.assertEqual(s, u'foo.bar.')
|
||||
|
||||
def testReverseIPv4(self):
|
||||
e = linkcheck.dns.name.from_text('1.0.0.127.in-addr.arpa.')
|
||||
n = linkcheck.dns.reversename.from_address('127.0.0.1')
|
||||
self.assertEqual(e, n)
|
||||
|
||||
def testReverseIPv6(self):
|
||||
e = linkcheck.dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.')
|
||||
n = linkcheck.dns.reversename.from_address('::1')
|
||||
self.assertEqual(e, n)
|
||||
|
||||
def testBadReverseIPv4(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.reversename.from_address('127.0.foo.1')
|
||||
self.assertRaises(socket.error, bad)
|
||||
|
||||
def testBadReverseIPv6(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.reversename.from_address('::1::1')
|
||||
self.assertRaises(socket.error, bad)
|
||||
|
||||
def testForwardIPv4(self):
|
||||
n = linkcheck.dns.name.from_text('1.0.0.127.in-addr.arpa.')
|
||||
e = '127.0.0.1'
|
||||
text = linkcheck.dns.reversename.to_address(n)
|
||||
self.assertEqual(text, e)
|
||||
|
||||
def testForwardIPv6(self):
|
||||
n = linkcheck.dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.')
|
||||
e = '::1'
|
||||
text = linkcheck.dns.reversename.to_address(n)
|
||||
self.assertEqual(text, e)
|
||||
|
||||
def testE164ToEnum(self):
|
||||
text = '+1 650 555 1212'
|
||||
e = linkcheck.dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.')
|
||||
n = linkcheck.dns.e164.from_e164(text)
|
||||
self.assertEqual(n, e)
|
||||
|
||||
def testEnumToE164(self):
|
||||
n = linkcheck.dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.')
|
||||
e = '+16505551212'
|
||||
text = linkcheck.dns.e164.to_e164(n)
|
||||
self.assertEqual(text, e)
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.namedict
|
||||
|
||||
class TestNameDict (unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.ndict = linkcheck.dns.namedict.NameDict()
|
||||
n1 = linkcheck.dns.name.from_text('foo.bar.')
|
||||
n2 = linkcheck.dns.name.from_text('bar.')
|
||||
self.ndict[n1] = 1
|
||||
self.ndict[n2] = 2
|
||||
self.rndict = linkcheck.dns.namedict.NameDict()
|
||||
n1 = linkcheck.dns.name.from_text('foo.bar', None)
|
||||
n2 = linkcheck.dns.name.from_text('bar', None)
|
||||
self.rndict[n1] = 1
|
||||
self.rndict[n2] = 2
|
||||
|
||||
def testDepth(self):
|
||||
self.assertEqual(self.ndict.max_depth, 3)
|
||||
|
||||
def testLookup1(self):
|
||||
k = linkcheck.dns.name.from_text('foo.bar.')
|
||||
self.assertEqual(self.ndict[k], 1)
|
||||
|
||||
def testLookup2(self):
|
||||
k = linkcheck.dns.name.from_text('foo.bar.')
|
||||
self.assertEqual(self.ndict.get_deepest_match(k)[1], 1)
|
||||
|
||||
def testLookup3(self):
|
||||
k = linkcheck.dns.name.from_text('a.b.c.foo.bar.')
|
||||
self.assertEqual(self.ndict.get_deepest_match(k)[1], 1)
|
||||
|
||||
def testLookup4(self):
|
||||
k = linkcheck.dns.name.from_text('a.b.c.bar.')
|
||||
self.assertEqual(self.ndict.get_deepest_match(k)[1], 2)
|
||||
|
||||
def testLookup5(self):
|
||||
def bad():
|
||||
n = linkcheck.dns.name.from_text('a.b.c.')
|
||||
(k, v) = self.ndict.get_deepest_match(n)
|
||||
self.assertRaises(KeyError, bad)
|
||||
|
||||
def testLookup6(self):
|
||||
def bad():
|
||||
(k, v) = self.ndict.get_deepest_match(linkcheck.dns.name.empty)
|
||||
self.assertRaises(KeyError, bad)
|
||||
|
||||
def testLookup7(self):
|
||||
self.ndict[linkcheck.dns.name.empty] = 100
|
||||
n = linkcheck.dns.name.from_text('a.b.c.')
|
||||
(k, v) = self.ndict.get_deepest_match(n)
|
||||
self.assertEqual(v, 100)
|
||||
|
||||
def testLookup8(self):
|
||||
def bad():
|
||||
self.ndict['foo'] = 100
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def testRelDepth(self):
|
||||
self.assertEqual(self.rndict.max_depth, 2)
|
||||
|
||||
def testRelLookup1(self):
|
||||
k = linkcheck.dns.name.from_text('foo.bar', None)
|
||||
self.assertEqual(self.rndict[k], 1)
|
||||
|
||||
def testRelLookup2(self):
|
||||
k = linkcheck.dns.name.from_text('foo.bar', None)
|
||||
self.assertEqual(self.rndict.get_deepest_match(k)[1], 1)
|
||||
|
||||
def testRelLookup3(self):
|
||||
k = linkcheck.dns.name.from_text('a.b.c.foo.bar', None)
|
||||
self.assertEqual(self.rndict.get_deepest_match(k)[1], 1)
|
||||
|
||||
def testRelLookup4(self):
|
||||
k = linkcheck.dns.name.from_text('a.b.c.bar', None)
|
||||
self.assertEqual(self.rndict.get_deepest_match(k)[1], 2)
|
||||
|
||||
def testRelLookup7(self):
|
||||
self.rndict[linkcheck.dns.name.empty] = 100
|
||||
n = linkcheck.dns.name.from_text('a.b.c', None)
|
||||
(k, v) = self.rndict.get_deepest_match(n)
|
||||
self.assertEqual(v, 100)
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.ipv6
|
||||
|
||||
class TestNtoAAtoN (unittest.TestCase):
|
||||
|
||||
def test_aton1(self):
|
||||
a = linkcheck.dns.ipv6.inet_aton('::')
|
||||
self.assertEqual(a, '\x00' * 16)
|
||||
|
||||
def test_aton2(self):
|
||||
a = linkcheck.dns.ipv6.inet_aton('::1')
|
||||
self.assertEqual(a, '\x00' * 15 + '\x01')
|
||||
|
||||
def test_aton3(self):
|
||||
a = linkcheck.dns.ipv6.inet_aton('::10.0.0.1')
|
||||
self.assertEqual(a, '\x00' * 12 + '\x0a\x00\x00\x01')
|
||||
|
||||
def test_aton4(self):
|
||||
a = linkcheck.dns.ipv6.inet_aton('abcd::dcba')
|
||||
self.assertEqual(a, '\xab\xcd' + '\x00' * 12 + '\xdc\xba')
|
||||
|
||||
def test_aton5(self):
|
||||
a = linkcheck.dns.ipv6.inet_aton('1:2:3:4:5:6:7:8')
|
||||
self.assertEqual(a,
|
||||
'00010002000300040005000600070008'.decode('hex_codec'))
|
||||
|
||||
def test_bad_aton1(self):
|
||||
def bad():
|
||||
a = linkcheck.dns.ipv6.inet_aton('abcd:dcba')
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def test_bad_aton2(self):
|
||||
def bad():
|
||||
a = linkcheck.dns.ipv6.inet_aton('abcd::dcba::1')
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def test_bad_aton3(self):
|
||||
def bad():
|
||||
a = linkcheck.dns.ipv6.inet_aton('1:2:3:4:5:6:7:8:9')
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def test_ntoa1(self):
|
||||
b = '00010002000300040005000600070008'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '1:2:3:4:5:6:7:8')
|
||||
|
||||
def test_ntoa2(self):
|
||||
b = '\x00' * 16
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::')
|
||||
|
||||
def test_ntoa3(self):
|
||||
b = '\x00' * 15 + '\x01'
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::1')
|
||||
|
||||
def test_ntoa4(self):
|
||||
b = '\x80' + '\x00' * 15
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '8000::')
|
||||
|
||||
def test_ntoa5(self):
|
||||
b = '\x01\xcd' + '\x00' * 12 + '\x03\xef'
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '1cd::3ef')
|
||||
|
||||
def test_ntoa6(self):
|
||||
b = 'ffff00000000ffff000000000000ffff'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, 'ffff:0:0:ffff::ffff')
|
||||
|
||||
def test_ntoa7(self):
|
||||
b = '00000000ffff000000000000ffffffff'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '0:0:ffff::ffff:ffff')
|
||||
|
||||
def test_ntoa8(self):
|
||||
b = 'ffff0000ffff00000000ffff00000000'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, 'ffff:0:ffff::ffff:0:0')
|
||||
|
||||
def test_ntoa9(self):
|
||||
b = '0000000000000000000000000a000001'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::10.0.0.1')
|
||||
|
||||
def test_ntoa10(self):
|
||||
b = '0000000000000000000000010a000001'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::1:a00:1')
|
||||
|
||||
def test_ntoa11(self):
|
||||
b = '00000000000000000000ffff0a000001'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::ffff:10.0.0.1')
|
||||
|
||||
def test_ntoa12(self):
|
||||
b = '000000000000000000000000ffffffff'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::255.255.255.255')
|
||||
|
||||
def test_ntoa13(self):
|
||||
b = '00000000000000000000ffffffffffff'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::ffff:255.255.255.255')
|
||||
|
||||
def test_ntoa14(self):
|
||||
b = '0000000000000000000000000001ffff'.decode('hex_codec')
|
||||
t = linkcheck.dns.ipv6.inet_ntoa(b)
|
||||
self.assertEqual(t, '::0.1.255.255')
|
||||
|
||||
def test_bad_ntoa1(self):
|
||||
def bad():
|
||||
a = linkcheck.dns.ipv6.inet_ntoa('')
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def test_bad_ntoa2(self):
|
||||
def bad():
|
||||
a = linkcheck.dns.ipv6.inet_ntoa('\x00' * 17)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
|
||||
class TestRdTypeAndClass (unittest.TestCase):
|
||||
|
||||
# Classes
|
||||
|
||||
def test_class_meta1(self):
|
||||
self.assertTrue(linkcheck.dns.rdataclass.is_metaclass(linkcheck.dns.rdataclass.ANY))
|
||||
|
||||
def test_class_meta2(self):
|
||||
self.assertTrue(not linkcheck.dns.rdataclass.is_metaclass(linkcheck.dns.rdataclass.IN))
|
||||
|
||||
def test_class_bytext1(self):
|
||||
self.assertEqual(linkcheck.dns.rdataclass.from_text('IN'),
|
||||
linkcheck.dns.rdataclass.IN)
|
||||
|
||||
def test_class_bytext2(self):
|
||||
self.assertEqual(linkcheck.dns.rdataclass.from_text('CLASS1'),
|
||||
linkcheck.dns.rdataclass.IN)
|
||||
|
||||
def test_class_bytext_bounds1(self):
|
||||
self.assertEqual(linkcheck.dns.rdataclass.from_text('CLASS0'), 0)
|
||||
self.assertEqual(linkcheck.dns.rdataclass.from_text('CLASS65535'), 65535)
|
||||
|
||||
def test_class_bytext_bounds2(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdataclass.from_text('CLASS65536')
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def test_class_bytext_unknown(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdataclass.from_text('XYZ')
|
||||
self.assertRaises(linkcheck.dns.rdataclass.UnknownRdataclass, bad)
|
||||
|
||||
def test_class_totext1(self):
|
||||
self.assertEqual(linkcheck.dns.rdataclass.to_text(linkcheck.dns.rdataclass.IN),
|
||||
'IN')
|
||||
|
||||
def test_class_totext2(self):
|
||||
self.assertEqual(linkcheck.dns.rdataclass.to_text(999), 'CLASS999')
|
||||
|
||||
def test_class_totext_bounds1(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdataclass.to_text(-1)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def test_class_totext_bounds2(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdataclass.to_text(65536)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
# Types
|
||||
|
||||
def test_type_meta1(self):
|
||||
self.assertTrue(linkcheck.dns.rdatatype.is_metatype(linkcheck.dns.rdatatype.ANY))
|
||||
|
||||
def test_type_meta2(self):
|
||||
self.assertTrue(linkcheck.dns.rdatatype.is_metatype(linkcheck.dns.rdatatype.OPT))
|
||||
|
||||
def test_type_meta3(self):
|
||||
self.assertTrue(not linkcheck.dns.rdatatype.is_metatype(linkcheck.dns.rdatatype.A))
|
||||
|
||||
def test_type_singleton1(self):
|
||||
self.assertTrue(linkcheck.dns.rdatatype.is_singleton(linkcheck.dns.rdatatype.SOA))
|
||||
|
||||
def test_type_singleton2(self):
|
||||
self.assertTrue(not linkcheck.dns.rdatatype.is_singleton(linkcheck.dns.rdatatype.A))
|
||||
|
||||
def test_type_bytext1(self):
|
||||
self.assertEqual(linkcheck.dns.rdatatype.from_text('A'), linkcheck.dns.rdatatype.A)
|
||||
|
||||
def test_type_bytext2(self):
|
||||
self.assertEqual(linkcheck.dns.rdatatype.from_text('TYPE1'),
|
||||
linkcheck.dns.rdatatype.A)
|
||||
|
||||
def test_type_bytext_bounds1(self):
|
||||
self.assertEqual(linkcheck.dns.rdatatype.from_text('TYPE0'), 0)
|
||||
self.assertEqual(linkcheck.dns.rdatatype.from_text('TYPE65535'), 65535)
|
||||
|
||||
def test_type_bytext_bounds2(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdatatype.from_text('TYPE65536')
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def test_type_bytext_unknown(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdatatype.from_text('XYZ')
|
||||
self.assertRaises(linkcheck.dns.rdatatype.UnknownRdatatype, bad)
|
||||
|
||||
def test_type_totext1(self):
|
||||
self.assertEqual(linkcheck.dns.rdatatype.to_text(linkcheck.dns.rdatatype.A), 'A')
|
||||
|
||||
def test_type_totext2(self):
|
||||
self.assertEqual(linkcheck.dns.rdatatype.to_text(999), 'TYPE999')
|
||||
|
||||
def test_type_totext_bounds1(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdatatype.to_text(-1)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
||||
def test_type_totext_bounds2(self):
|
||||
def bad():
|
||||
junk = linkcheck.dns.rdatatype.to_text(65536)
|
||||
self.assertRaises(ValueError, bad)
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.message
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.resolver
|
||||
|
||||
resolv_conf = """
|
||||
/t/t
|
||||
# comment 1
|
||||
; comment 2
|
||||
domain foo
|
||||
nameserver 10.0.0.1
|
||||
nameserver 10.0.0.2
|
||||
"""
|
||||
|
||||
message_text = """id 1234
|
||||
opcode QUERY
|
||||
rcode NOERROR
|
||||
flags QR AA RD
|
||||
;QUESTION
|
||||
example. IN A
|
||||
;ANSWER
|
||||
example. 1 IN A 10.0.0.1
|
||||
;AUTHORITY
|
||||
;ADDITIONAL
|
||||
"""
|
||||
|
||||
class TestResolver (unittest.TestCase):
|
||||
|
||||
if sys.platform != 'win32':
|
||||
def testRead(self):
|
||||
f = StringIO(resolv_conf)
|
||||
r = linkcheck.dns.resolver.Resolver(f)
|
||||
self.assertEqual(r.nameservers, ['10.0.0.1', '10.0.0.2'])
|
||||
self.assertEqual(r.domain, linkcheck.dns.name.from_text('foo'))
|
||||
|
||||
def testCacheExpiration(self):
|
||||
message = linkcheck.dns.message.from_text(message_text)
|
||||
name = linkcheck.dns.name.from_text('example.')
|
||||
answer = linkcheck.dns.resolver.Answer(name, linkcheck.dns.rdatatype.A, linkcheck.dns.rdataclass.IN,
|
||||
message)
|
||||
cache = linkcheck.dns.resolver.Cache()
|
||||
cache.put((name, linkcheck.dns.rdatatype.A, linkcheck.dns.rdataclass.IN), answer)
|
||||
time.sleep(2)
|
||||
self.assertTrue(cache.get((name, linkcheck.dns.rdatatype.A,
|
||||
linkcheck.dns.rdataclass.IN)) is None)
|
||||
|
||||
def testCacheCleaning(self):
|
||||
message = linkcheck.dns.message.from_text(message_text)
|
||||
name = linkcheck.dns.name.from_text('example.')
|
||||
answer = linkcheck.dns.resolver.Answer(name, linkcheck.dns.rdatatype.A, linkcheck.dns.rdataclass.IN,
|
||||
message)
|
||||
cache = linkcheck.dns.resolver.Cache(cleaning_interval=1.0)
|
||||
cache.put((name, linkcheck.dns.rdatatype.A, linkcheck.dns.rdataclass.IN), answer)
|
||||
time.sleep(2)
|
||||
self.assertTrue(cache.get((name, linkcheck.dns.rdatatype.A,
|
||||
linkcheck.dns.rdataclass.IN)) is None)
|
||||
|
||||
def testZoneForName1(self):
|
||||
name = linkcheck.dns.name.from_text('www.dnspython.org.')
|
||||
ezname = linkcheck.dns.name.from_text('dnspython.org.')
|
||||
zname = linkcheck.dns.resolver.zone_for_name(name)
|
||||
self.assertTrue(zname == ezname)
|
||||
|
||||
def testZoneForName2(self):
|
||||
name = linkcheck.dns.name.from_text('a.b.www.dnspython.org.')
|
||||
ezname = linkcheck.dns.name.from_text('dnspython.org.')
|
||||
zname = linkcheck.dns.resolver.zone_for_name(name)
|
||||
self.assertTrue(zname == ezname)
|
||||
|
||||
def testZoneForName3(self):
|
||||
name = linkcheck.dns.name.from_text('dnspython.org.')
|
||||
ezname = linkcheck.dns.name.from_text('dnspython.org.')
|
||||
zname = linkcheck.dns.resolver.zone_for_name(name)
|
||||
self.assertTrue(zname == ezname)
|
||||
|
||||
def testZoneForName4(self):
|
||||
def bad():
|
||||
name = linkcheck.dns.name.from_text('dnspython.org', None)
|
||||
zname = linkcheck.dns.resolver.zone_for_name(name)
|
||||
self.assertRaises(linkcheck.dns.resolver.NotAbsolute, bad)
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.rrset
|
||||
|
||||
class TestRRset (unittest.TestCase):
|
||||
|
||||
def testEqual1(self):
|
||||
r1 = linkcheck.dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2')
|
||||
r2 = linkcheck.dns.rrset.from_text('FOO', 300, 'in', 'a', '10.0.0.2', '10.0.0.1')
|
||||
self.assertEqual(r1, r2)
|
||||
|
||||
def testEqual2(self):
|
||||
r1 = linkcheck.dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2')
|
||||
r2 = linkcheck.dns.rrset.from_text('FOO', 600, 'in', 'a', '10.0.0.2', '10.0.0.1')
|
||||
self.assertEqual(r1, r2)
|
||||
|
||||
def testNotEqual1(self):
|
||||
r1 = linkcheck.dns.rrset.from_text('fooa', 30, 'in', 'a', '10.0.0.1', '10.0.0.2')
|
||||
r2 = linkcheck.dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
||||
def testNotEqual2(self):
|
||||
r1 = linkcheck.dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.3')
|
||||
r2 = linkcheck.dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
||||
def testNotEqual3(self):
|
||||
r1 = linkcheck.dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.2',
|
||||
'10.0.0.3')
|
||||
r2 = linkcheck.dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
||||
def testNotEqual4(self):
|
||||
r1 = linkcheck.dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1')
|
||||
r2 = linkcheck.dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1')
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import unittest
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.tokenizer
|
||||
|
||||
class TestTokenizer (unittest.TestCase):
|
||||
|
||||
def testQuotedString1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'"foo"')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertEqual(ttype, linkcheck.dns.tokenizer.QUOTED_STRING)
|
||||
self.assertEqual(value, 'foo')
|
||||
|
||||
def testQuotedString2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'""')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertEqual(ttype, linkcheck.dns.tokenizer.QUOTED_STRING)
|
||||
self.assertEqual(value, '')
|
||||
|
||||
def testQuotedString3(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'"\"foo\""')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertEqual(ttype, linkcheck.dns.tokenizer.QUOTED_STRING)
|
||||
self.assertEqual(value, '"foo"')
|
||||
|
||||
def testQuotedString4(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'"foo\010bar"')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertEqual(ttype, linkcheck.dns.tokenizer.QUOTED_STRING)
|
||||
self.assertEqual(value, 'foo\x0abar')
|
||||
|
||||
def testQuotedString5(self):
|
||||
def bad():
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'"foo')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertRaises(linkcheck.dns.exception.UnexpectedEnd, bad)
|
||||
|
||||
def testQuotedString6(self):
|
||||
def bad():
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'"foo\01')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def testQuotedString7(self):
|
||||
def bad():
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('"foo\nbar"')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def testEmpty1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('')
|
||||
(ttype, value) = tok.get()
|
||||
self.assertEqual(ttype, linkcheck.dns.tokenizer.EOF)
|
||||
|
||||
def testEmpty2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('')
|
||||
(ttype1, value1) = tok.get()
|
||||
(ttype2, value2) = tok.get()
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.EOF)
|
||||
self.assertEqual(ttype2, linkcheck.dns.tokenizer.EOF)
|
||||
|
||||
def testEOL(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('\n')
|
||||
(ttype1, value1) = tok.get()
|
||||
(ttype2, value2) = tok.get()
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.EOL)
|
||||
self.assertEqual(ttype2, linkcheck.dns.tokenizer.EOF)
|
||||
|
||||
def testWS1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(' \n')
|
||||
(ttype1, value1) = tok.get()
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.EOL)
|
||||
|
||||
def testWS2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(' \n')
|
||||
(ttype1, value1) = tok.get(want_leading=True)
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.WHITESPACE)
|
||||
|
||||
def testComment1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(' ;foo\n')
|
||||
(ttype1, value1) = tok.get()
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.EOL)
|
||||
|
||||
def testComment2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(' ;foo\n')
|
||||
(ttype1, value1) = tok.get(want_comment = True)
|
||||
(ttype2, value2) = tok.get()
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.COMMENT)
|
||||
self.assertEqual(value1, 'foo')
|
||||
self.assertEqual(ttype2, linkcheck.dns.tokenizer.EOL)
|
||||
|
||||
def testComment3(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(' ;foo bar\n')
|
||||
(ttype1, value1) = tok.get(want_comment = True)
|
||||
(ttype2, value2) = tok.get()
|
||||
self.assertEqual(ttype1, linkcheck.dns.tokenizer.COMMENT)
|
||||
self.assertEqual(value1, 'foo bar')
|
||||
self.assertEqual(ttype2, linkcheck.dns.tokenizer.EOL)
|
||||
|
||||
def testMultiline1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('( foo\n\n bar\n)')
|
||||
tokens = list(iter(tok))
|
||||
self.assertEqual(tokens, [(linkcheck.dns.tokenizer.IDENTIFIER, 'foo'),
|
||||
(linkcheck.dns.tokenizer.IDENTIFIER, 'bar')])
|
||||
|
||||
def testMultiline2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('( foo\n\n bar\n)\n')
|
||||
tokens = list(iter(tok))
|
||||
self.assertEqual(tokens, [(linkcheck.dns.tokenizer.IDENTIFIER, 'foo'),
|
||||
(linkcheck.dns.tokenizer.IDENTIFIER, 'bar'),
|
||||
(linkcheck.dns.tokenizer.EOL, '\n')])
|
||||
def testMultiline3(self):
|
||||
def bad():
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('foo)')
|
||||
tokens = list(iter(tok))
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def testMultiline4(self):
|
||||
def bad():
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('((foo)')
|
||||
tokens = list(iter(tok))
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
||||
def testUnget1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('foo')
|
||||
t1 = tok.get()
|
||||
tok.unget(t1)
|
||||
t2 = tok.get()
|
||||
self.assertEqual(t1, t2)
|
||||
self.assertEqual(t1, (linkcheck.dns.tokenizer.IDENTIFIER, 'foo'))
|
||||
|
||||
def testUnget2(self):
|
||||
def bad():
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('foo')
|
||||
t1 = tok.get()
|
||||
tok.unget(t1)
|
||||
tok.unget(t1)
|
||||
self.assertRaises(linkcheck.dns.tokenizer.UngetBufferFull, bad)
|
||||
|
||||
def testGetEOL1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('\n')
|
||||
t = tok.get_eol()
|
||||
self.assertEqual(t, '\n')
|
||||
|
||||
def testGetEOL2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer('')
|
||||
t = tok.get_eol()
|
||||
self.assertEqual(t, '')
|
||||
|
||||
def testEscapedDelimiter1(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'ch\ ld')
|
||||
t = tok.get()
|
||||
self.assertEqual(t, (linkcheck.dns.tokenizer.IDENTIFIER, r'ch ld'))
|
||||
|
||||
def testEscapedDelimiter2(self):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(r'ch\0ld')
|
||||
t = tok.get()
|
||||
self.assertEqual(t, (linkcheck.dns.tokenizer.IDENTIFIER, r'ch\0ld'))
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import os
|
||||
import unittest
|
||||
import difflib
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.rrset
|
||||
import linkcheck.dns.zone
|
||||
|
||||
_paths = ["tests", "dns"]
|
||||
|
||||
def fname (name, sep=None):
|
||||
args = tuple(_paths + [name])
|
||||
if sep is not None:
|
||||
return sep.join(args)
|
||||
else:
|
||||
return os.path.join(*args)
|
||||
|
||||
|
||||
example_text = """$TTL 3600
|
||||
$ORIGIN example.
|
||||
@ soa foo bar 1 2 3 4 5
|
||||
@ ns ns1
|
||||
@ ns ns2
|
||||
ns1 a 10.0.0.1
|
||||
ns2 a 10.0.0.2
|
||||
$TTL 300
|
||||
$ORIGIN foo.example.
|
||||
bar mx 0 blaz
|
||||
"""
|
||||
|
||||
example_text_output = """@ 3600 IN SOA foo bar 1 2 3 4 5
|
||||
@ 3600 IN NS ns1
|
||||
@ 3600 IN NS ns2
|
||||
bar.foo 300 IN MX 0 blaz.foo
|
||||
ns1 3600 IN A 10.0.0.1
|
||||
ns2 3600 IN A 10.0.0.2
|
||||
"""
|
||||
|
||||
something_quite_similar = """@ 3600 IN SOA foo bar 1 2 3 4 5
|
||||
@ 3600 IN NS ns1
|
||||
@ 3600 IN NS ns2
|
||||
bar.foo 300 IN MX 0 blaz.foo
|
||||
ns1 3600 IN A 10.0.0.1
|
||||
ns2 3600 IN A 10.0.0.3
|
||||
"""
|
||||
|
||||
something_different = """@ 3600 IN SOA fooa bar 1 2 3 4 5
|
||||
@ 3600 IN NS ns11
|
||||
@ 3600 IN NS ns21
|
||||
bar.fooa 300 IN MX 0 blaz.fooa
|
||||
ns11 3600 IN A 10.0.0.11
|
||||
ns21 3600 IN A 10.0.0.21
|
||||
"""
|
||||
|
||||
ttl_example_text = """$TTL 1h
|
||||
$ORIGIN example.
|
||||
@ soa foo bar 1 2 3 4 5
|
||||
@ ns ns1
|
||||
@ ns ns2
|
||||
ns1 1d1s a 10.0.0.1
|
||||
ns2 1w1D1h1m1S a 10.0.0.2
|
||||
"""
|
||||
|
||||
no_soa_text = """$TTL 1h
|
||||
$ORIGIN example.
|
||||
@ ns ns1
|
||||
@ ns ns2
|
||||
ns1 1d1s a 10.0.0.1
|
||||
ns2 1w1D1h1m1S a 10.0.0.2
|
||||
"""
|
||||
|
||||
no_ns_text = """$TTL 1h
|
||||
$ORIGIN example.
|
||||
@ soa foo bar 1 2 3 4 5
|
||||
"""
|
||||
|
||||
include_text = """$INCLUDE "%s"
|
||||
""" % fname("example", sep="/")
|
||||
|
||||
bad_directive_text = """$FOO bar
|
||||
$ORIGIN example.
|
||||
@ soa foo bar 1 2 3 4 5
|
||||
@ ns ns1
|
||||
@ ns ns2
|
||||
ns1 1d1s a 10.0.0.1
|
||||
ns2 1w1D1h1m1S a 10.0.0.2
|
||||
"""
|
||||
|
||||
def get_file_lines (fn):
|
||||
res = []
|
||||
with open(fn) as fd:
|
||||
for line in fd:
|
||||
res.append(line)
|
||||
return res
|
||||
|
||||
|
||||
def get_file_diff (fn1, fn2):
|
||||
res = []
|
||||
c1 = get_file_lines(fn1)
|
||||
c2 = get_file_lines(fn2)
|
||||
for line in difflib.unified_diff(c1, c2):
|
||||
if not isinstance(line, unicode):
|
||||
line = unicode(line, "iso8859-1", "ignore")
|
||||
res.append(line)
|
||||
return res
|
||||
|
||||
|
||||
class TestZone (unittest.TestCase):
|
||||
|
||||
def testFromFile1(self):
|
||||
z = linkcheck.dns.zone.from_file(fname('example'), 'example')
|
||||
diff = True
|
||||
try:
|
||||
z.to_file(fname('example1.out'), nl='\x0a')
|
||||
fn1 = fname('example1.out')
|
||||
fn2 = fname('example1.good')
|
||||
diff = get_file_diff(fn1, fn2)
|
||||
finally:
|
||||
os.unlink(fname('example1.out'))
|
||||
self.assertFalse(diff)
|
||||
|
||||
def testFromFile2(self):
|
||||
z = linkcheck.dns.zone.from_file(fname('example'), 'example',
|
||||
relativize=False)
|
||||
diff = True
|
||||
try:
|
||||
z.to_file(fname('example2.out'), relativize=False, nl='\x0a')
|
||||
fn1 = fname('example2.out')
|
||||
fn2 = fname('example2.good')
|
||||
diff = get_file_diff(fn1, fn2)
|
||||
finally:
|
||||
os.unlink(fname('example2.out'))
|
||||
self.assertFalse(diff)
|
||||
|
||||
def testFromText(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
f = StringIO()
|
||||
names = z.nodes.keys()
|
||||
names.sort()
|
||||
for n in names:
|
||||
print >> f, z[n].to_text(n)
|
||||
self.assertEqual(f.getvalue(), example_text_output)
|
||||
|
||||
def testTorture1(self):
|
||||
|
||||
# Read a zone containing all our supported RR types, and
|
||||
# for each RR in the zone, convert the rdata into wire format
|
||||
# and then back out, and see if we get equal rdatas.
|
||||
|
||||
f = StringIO()
|
||||
o = linkcheck.dns.name.from_text('example.')
|
||||
z = linkcheck.dns.zone.from_file(fname('example'), o)
|
||||
for (name, node) in z.iteritems():
|
||||
for rds in node:
|
||||
for rd in rds:
|
||||
f.seek(0)
|
||||
f.truncate()
|
||||
rd.to_wire(f, origin=o)
|
||||
wire = f.getvalue()
|
||||
rd2 = linkcheck.dns.rdata.from_wire(rds.rdclass, rds.rdtype,
|
||||
wire, 0, len(wire),
|
||||
origin = o)
|
||||
self.assertEqual(rd, rd2)
|
||||
|
||||
def testEqual(self):
|
||||
z1 = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
z2 = linkcheck.dns.zone.from_text(example_text_output, 'example.',
|
||||
relativize=True)
|
||||
self.assertEqual(z1, z2)
|
||||
|
||||
def testNotEqual1(self):
|
||||
z1 = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
z2 = linkcheck.dns.zone.from_text(something_quite_similar, 'example.',
|
||||
relativize=True)
|
||||
self.assertNotEqual(z1, z2)
|
||||
|
||||
def testNotEqual2(self):
|
||||
z1 = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
z2 = linkcheck.dns.zone.from_text(something_different, 'example.',
|
||||
relativize=True)
|
||||
self.assertNotEqual(z1, z2)
|
||||
|
||||
def testNotEqual3(self):
|
||||
z1 = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
z2 = linkcheck.dns.zone.from_text(something_different, 'example2.',
|
||||
relativize=True)
|
||||
self.assertNotEqual(z1, z2)
|
||||
|
||||
def testFindRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rds = z.find_rdataset('@', 'soa')
|
||||
exrds = linkcheck.dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
|
||||
self.assertEqual(rds, exrds)
|
||||
|
||||
def testFindRdataset2(self):
|
||||
def bad():
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rds = z.find_rdataset('@', 'loc')
|
||||
self.assertRaises(KeyError, bad)
|
||||
|
||||
def testFindRRset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rrs = z.find_rrset('@', 'soa')
|
||||
exrrs = linkcheck.dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5')
|
||||
self.assertEqual(rrs, exrrs)
|
||||
|
||||
def testFindRRset2(self):
|
||||
def bad():
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rrs = z.find_rrset('@', 'loc')
|
||||
self.assertRaises(KeyError, bad)
|
||||
|
||||
def testGetRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rds = z.get_rdataset('@', 'soa')
|
||||
exrds = linkcheck.dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
|
||||
self.assertEqual(rds, exrds)
|
||||
|
||||
def testGetRdataset2(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rds = z.get_rdataset('@', 'loc')
|
||||
self.assertEqual(rds, None)
|
||||
|
||||
def testGetRRset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rrs = z.get_rrset('@', 'soa')
|
||||
exrrs = linkcheck.dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5')
|
||||
self.assertEqual(rrs, exrrs)
|
||||
|
||||
def testGetRRset2(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rrs = z.get_rrset('@', 'loc')
|
||||
self.assertEqual(rrs, None)
|
||||
|
||||
def testReplaceRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rdataset = linkcheck.dns.rdataset.from_text('in', 'ns', 300, 'ns3', 'ns4')
|
||||
z.replace_rdataset('@', rdataset)
|
||||
rds = z.get_rdataset('@', 'ns')
|
||||
self.assertTrue(rds is rdataset)
|
||||
|
||||
def testReplaceRdataset2(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
rdataset = linkcheck.dns.rdataset.from_text('in', 'txt', 300, '"foo"')
|
||||
z.replace_rdataset('@', rdataset)
|
||||
rds = z.get_rdataset('@', 'txt')
|
||||
self.assertTrue(rds is rdataset)
|
||||
|
||||
def testDeleteRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
z.delete_rdataset('@', 'ns')
|
||||
rds = z.get_rdataset('@', 'ns')
|
||||
self.assertTrue(rds is None)
|
||||
|
||||
def testDeleteRdataset2(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
z.delete_rdataset('ns1', 'a')
|
||||
node = z.get_node('ns1')
|
||||
self.assertTrue(node is None)
|
||||
|
||||
def testNodeFindRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
node = z['@']
|
||||
rds = node.find_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.SOA)
|
||||
exrds = linkcheck.dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
|
||||
self.assertEqual(rds, exrds)
|
||||
|
||||
def testNodeFindRdataset2(self):
|
||||
def bad():
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
node = z['@']
|
||||
rds = node.find_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.LOC)
|
||||
self.assertRaises(KeyError, bad)
|
||||
|
||||
def testNodeGetRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
node = z['@']
|
||||
rds = node.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.SOA)
|
||||
exrds = linkcheck.dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
|
||||
self.assertEqual(rds, exrds)
|
||||
|
||||
def testNodeGetRdataset2(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
node = z['@']
|
||||
rds = node.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.LOC)
|
||||
self.assertEqual(rds, None)
|
||||
|
||||
def testNodeDeleteRdataset1(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
node = z['@']
|
||||
rds = node.delete_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.SOA)
|
||||
rds = node.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.SOA)
|
||||
self.assertEqual(rds, None)
|
||||
|
||||
def testNodeDeleteRdataset2(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
node = z['@']
|
||||
rds = node.delete_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.LOC)
|
||||
rds = node.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.LOC)
|
||||
self.assertEqual(rds, None)
|
||||
|
||||
def testIterateRdatasets(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
ns = [n for n, r in z.iterate_rdatasets('A')]
|
||||
ns.sort()
|
||||
self.assertEqual(ns, [linkcheck.dns.name.from_text('ns1', None),
|
||||
linkcheck.dns.name.from_text('ns2', None)])
|
||||
|
||||
def testIterateAllRdatasets(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
ns = [n for n, r in z.iterate_rdatasets()]
|
||||
ns.sort()
|
||||
self.assertTrue(ns == [linkcheck.dns.name.from_text('@', None),
|
||||
linkcheck.dns.name.from_text('@', None),
|
||||
linkcheck.dns.name.from_text('bar.foo', None),
|
||||
linkcheck.dns.name.from_text('ns1', None),
|
||||
linkcheck.dns.name.from_text('ns2', None)])
|
||||
|
||||
def testIterateRdatas(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
l = list(z.iterate_rdatas('A'))
|
||||
l.sort()
|
||||
exl = [(linkcheck.dns.name.from_text('ns1', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.A,
|
||||
'10.0.0.1')),
|
||||
(linkcheck.dns.name.from_text('ns2', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.A,
|
||||
'10.0.0.2'))]
|
||||
self.assertEqual(l, exl)
|
||||
|
||||
def testIterateAllRdatas(self):
|
||||
z = linkcheck.dns.zone.from_text(example_text, 'example.', relativize=True)
|
||||
l = list(z.iterate_rdatas())
|
||||
l.sort()
|
||||
exl = [(linkcheck.dns.name.from_text('@', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.NS, 'ns1')),
|
||||
(linkcheck.dns.name.from_text('@', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.NS, 'ns2')),
|
||||
(linkcheck.dns.name.from_text('@', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.SOA,
|
||||
'foo bar 1 2 3 4 5')),
|
||||
(linkcheck.dns.name.from_text('bar.foo', None),
|
||||
300,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.MX,
|
||||
'0 blaz.foo')),
|
||||
(linkcheck.dns.name.from_text('ns1', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.A,
|
||||
'10.0.0.1')),
|
||||
(linkcheck.dns.name.from_text('ns2', None),
|
||||
3600,
|
||||
linkcheck.dns.rdata.from_text(linkcheck.dns.rdataclass.IN,
|
||||
linkcheck.dns.rdatatype.A,
|
||||
'10.0.0.2'))]
|
||||
self.assertEqual(l, exl)
|
||||
|
||||
def testTTLs(self):
|
||||
z = linkcheck.dns.zone.from_text(ttl_example_text, 'example.', relativize=True)
|
||||
n = z['@']
|
||||
rds = n.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.SOA)
|
||||
self.assertEqual(rds.ttl, 3600)
|
||||
n = z['ns1']
|
||||
rds = n.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.A)
|
||||
self.assertEqual(rds.ttl, 86401)
|
||||
n = z['ns2']
|
||||
rds = n.get_rdataset(linkcheck.dns.rdataclass.IN, linkcheck.dns.rdatatype.A)
|
||||
self.assertEqual(rds.ttl, 694861)
|
||||
|
||||
def testNoSOA(self):
|
||||
def bad():
|
||||
z = linkcheck.dns.zone.from_text(no_soa_text, 'example.',
|
||||
relativize=True)
|
||||
self.assertRaises(linkcheck.dns.zone.NoSOA, bad)
|
||||
|
||||
def testNoNS(self):
|
||||
def bad():
|
||||
z = linkcheck.dns.zone.from_text(no_ns_text, 'example.',
|
||||
relativize=True)
|
||||
self.assertRaises(linkcheck.dns.zone.NoNS, bad)
|
||||
|
||||
def testInclude(self):
|
||||
z1 = linkcheck.dns.zone.from_text(include_text, 'example.', relativize=True,
|
||||
allow_include=True)
|
||||
z2 = linkcheck.dns.zone.from_file(fname('example'), 'example.',
|
||||
relativize=True)
|
||||
self.assertEqual(z1, z2)
|
||||
|
||||
def testBadDirective(self):
|
||||
def bad():
|
||||
z = linkcheck.dns.zone.from_text(bad_directive_text, 'example.',
|
||||
relativize=True)
|
||||
self.assertRaises(linkcheck.dns.exception.DNSSyntaxError, bad)
|
||||
|
|
@ -1,23 +1,20 @@
|
|||
The following changes were made to the original dnspython sources:
|
||||
|
||||
* moved everything into the linkcheck package
|
||||
* Replace bare "except:" with "except StandardError:" and
|
||||
make DNSException inherit from StandardError.
|
||||
Avoids catching StopIteration and Warning exceptions.
|
||||
Changed: *.py
|
||||
|
||||
* Replace "x.has_key(y)" with "y in x".
|
||||
Changed: *.py
|
||||
|
||||
* moved unittests and adapted them for the schooltool.org test runner
|
||||
Changed: tests/*.py
|
||||
|
||||
* fixed missing random import
|
||||
Changed: renderer.py
|
||||
|
||||
* honor EnableDHCP flag in Windows registry config
|
||||
* honor EnableDHCP flag in Windows registry config and add __str__()
|
||||
method
|
||||
Changed: resolver.py
|
||||
|
||||
* strip() lines from /etc/resolv.conf
|
||||
Changed: resolver.py
|
||||
|
||||
* minor syntax cleanups
|
||||
Changed: *.py
|
||||
|
||||
* added set of localhost addresses to resolver config
|
||||
Changed: resolver.py
|
||||
Added: ifconfig.py
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -23,6 +22,7 @@ __all__ = [
|
|||
'entropy',
|
||||
'exception',
|
||||
'flags',
|
||||
'hash',
|
||||
'inet',
|
||||
'ipv4',
|
||||
'ipv6',
|
||||
|
|
@ -49,5 +49,6 @@ __all__ = [
|
|||
'rdtypes',
|
||||
'update',
|
||||
'version',
|
||||
'wiredata',
|
||||
'zone',
|
||||
]
|
||||
372
third_party/dnspython/dns/dnssec.py
vendored
Normal file
372
third_party/dnspython/dns/dnssec.py
vendored
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""Common DNSSEC-related functions and constants."""
|
||||
|
||||
import cStringIO
|
||||
import struct
|
||||
import time
|
||||
|
||||
import dns.exception
|
||||
import dns.hash
|
||||
import dns.name
|
||||
import dns.node
|
||||
import dns.rdataset
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
import dns.rdataclass
|
||||
|
||||
class UnsupportedAlgorithm(dns.exception.DNSException):
|
||||
"""Raised if an algorithm is not supported."""
|
||||
pass
|
||||
|
||||
class ValidationFailure(dns.exception.DNSException):
|
||||
"""The DNSSEC signature is invalid."""
|
||||
pass
|
||||
|
||||
RSAMD5 = 1
|
||||
DH = 2
|
||||
DSA = 3
|
||||
ECC = 4
|
||||
RSASHA1 = 5
|
||||
DSANSEC3SHA1 = 6
|
||||
RSASHA1NSEC3SHA1 = 7
|
||||
RSASHA256 = 8
|
||||
RSASHA512 = 10
|
||||
INDIRECT = 252
|
||||
PRIVATEDNS = 253
|
||||
PRIVATEOID = 254
|
||||
|
||||
_algorithm_by_text = {
|
||||
'RSAMD5' : RSAMD5,
|
||||
'DH' : DH,
|
||||
'DSA' : DSA,
|
||||
'ECC' : ECC,
|
||||
'RSASHA1' : RSASHA1,
|
||||
'DSANSEC3SHA1' : DSANSEC3SHA1,
|
||||
'RSASHA1NSEC3SHA1' : RSASHA1NSEC3SHA1,
|
||||
'RSASHA256' : RSASHA256,
|
||||
'RSASHA512' : RSASHA512,
|
||||
'INDIRECT' : INDIRECT,
|
||||
'PRIVATEDNS' : PRIVATEDNS,
|
||||
'PRIVATEOID' : PRIVATEOID,
|
||||
}
|
||||
|
||||
# We construct the inverse mapping programmatically to ensure that we
|
||||
# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
|
||||
# would cause the mapping not to be true inverse.
|
||||
|
||||
_algorithm_by_value = dict([(y, x) for x, y in _algorithm_by_text.iteritems()])
|
||||
|
||||
def algorithm_from_text(text):
|
||||
"""Convert text into a DNSSEC algorithm value
|
||||
@rtype: int"""
|
||||
|
||||
value = _algorithm_by_text.get(text.upper())
|
||||
if value is None:
|
||||
value = int(text)
|
||||
return value
|
||||
|
||||
def algorithm_to_text(value):
|
||||
"""Convert a DNSSEC algorithm value to text
|
||||
@rtype: string"""
|
||||
|
||||
text = _algorithm_by_value.get(value)
|
||||
if text is None:
|
||||
text = str(value)
|
||||
return text
|
||||
|
||||
def _to_rdata(record, origin):
|
||||
s = cStringIO.StringIO()
|
||||
record.to_wire(s, origin=origin)
|
||||
return s.getvalue()
|
||||
|
||||
def key_id(key, origin=None):
|
||||
rdata = _to_rdata(key, origin)
|
||||
if key.algorithm == RSAMD5:
|
||||
return (ord(rdata[-3]) << 8) + ord(rdata[-2])
|
||||
else:
|
||||
total = 0
|
||||
for i in range(len(rdata) // 2):
|
||||
total += (ord(rdata[2 * i]) << 8) + ord(rdata[2 * i + 1])
|
||||
if len(rdata) % 2 != 0:
|
||||
total += ord(rdata[len(rdata) - 1]) << 8
|
||||
total += ((total >> 16) & 0xffff);
|
||||
return total & 0xffff
|
||||
|
||||
def make_ds(name, key, algorithm, origin=None):
|
||||
if algorithm.upper() == 'SHA1':
|
||||
dsalg = 1
|
||||
hash = dns.hash.get('SHA1')()
|
||||
elif algorithm.upper() == 'SHA256':
|
||||
dsalg = 2
|
||||
hash = dns.hash.get('SHA256')()
|
||||
else:
|
||||
raise UnsupportedAlgorithm, 'unsupported algorithm "%s"' % algorithm
|
||||
|
||||
if isinstance(name, (str, unicode)):
|
||||
name = dns.name.from_text(name, origin)
|
||||
hash.update(name.canonicalize().to_wire())
|
||||
hash.update(_to_rdata(key, origin))
|
||||
digest = hash.digest()
|
||||
|
||||
dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, dsalg) + digest
|
||||
return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0,
|
||||
len(dsrdata))
|
||||
|
||||
def _find_key(keys, rrsig):
|
||||
value = keys.get(rrsig.signer)
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, dns.node.Node):
|
||||
try:
|
||||
rdataset = node.find_rdataset(dns.rdataclass.IN,
|
||||
dns.rdatatype.DNSKEY)
|
||||
except KeyError:
|
||||
return None
|
||||
else:
|
||||
rdataset = value
|
||||
for rdata in rdataset:
|
||||
if rdata.algorithm == rrsig.algorithm and \
|
||||
key_id(rdata) == rrsig.key_tag:
|
||||
return rdata
|
||||
return None
|
||||
|
||||
def _is_rsa(algorithm):
|
||||
return algorithm in (RSAMD5, RSASHA1,
|
||||
RSASHA1NSEC3SHA1, RSASHA256,
|
||||
RSASHA512)
|
||||
|
||||
def _is_dsa(algorithm):
|
||||
return algorithm in (DSA, DSANSEC3SHA1)
|
||||
|
||||
def _is_md5(algorithm):
|
||||
return algorithm == RSAMD5
|
||||
|
||||
def _is_sha1(algorithm):
|
||||
return algorithm in (DSA, RSASHA1,
|
||||
DSANSEC3SHA1, RSASHA1NSEC3SHA1)
|
||||
|
||||
def _is_sha256(algorithm):
|
||||
return algorithm == RSASHA256
|
||||
|
||||
def _is_sha512(algorithm):
|
||||
return algorithm == RSASHA512
|
||||
|
||||
def _make_hash(algorithm):
|
||||
if _is_md5(algorithm):
|
||||
return dns.hash.get('MD5')()
|
||||
if _is_sha1(algorithm):
|
||||
return dns.hash.get('SHA1')()
|
||||
if _is_sha256(algorithm):
|
||||
return dns.hash.get('SHA256')()
|
||||
if _is_sha512(algorithm):
|
||||
return dns.hash.get('SHA512')()
|
||||
raise ValidationFailure, 'unknown hash for algorithm %u' % algorithm
|
||||
|
||||
def _make_algorithm_id(algorithm):
|
||||
if _is_md5(algorithm):
|
||||
oid = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05]
|
||||
elif _is_sha1(algorithm):
|
||||
oid = [0x2b, 0x0e, 0x03, 0x02, 0x1a]
|
||||
elif _is_sha256(algorithm):
|
||||
oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]
|
||||
elif _is_sha512(algorithm):
|
||||
oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]
|
||||
else:
|
||||
raise ValidationFailure, 'unknown algorithm %u' % algorithm
|
||||
olen = len(oid)
|
||||
dlen = _make_hash(algorithm).digest_size
|
||||
idbytes = [0x30] + [8 + olen + dlen] + \
|
||||
[0x30, olen + 4] + [0x06, olen] + oid + \
|
||||
[0x05, 0x00] + [0x04, dlen]
|
||||
return ''.join(map(chr, idbytes))
|
||||
|
||||
def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
|
||||
"""Validate an RRset against a single signature rdata
|
||||
|
||||
The owner name of the rrsig is assumed to be the same as the owner name
|
||||
of the rrset.
|
||||
|
||||
@param rrset: The RRset to validate
|
||||
@type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
|
||||
tuple
|
||||
@param rrsig: The signature rdata
|
||||
@type rrsig: dns.rrset.Rdata
|
||||
@param keys: The key dictionary.
|
||||
@type keys: a dictionary keyed by dns.name.Name with node or rdataset values
|
||||
@param origin: The origin to use for relative names
|
||||
@type origin: dns.name.Name or None
|
||||
@param now: The time to use when validating the signatures. The default
|
||||
is the current time.
|
||||
@type now: int
|
||||
"""
|
||||
|
||||
if isinstance(origin, (str, unicode)):
|
||||
origin = dns.name.from_text(origin, dns.name.root)
|
||||
|
||||
key = _find_key(keys, rrsig)
|
||||
if not key:
|
||||
raise ValidationFailure, 'unknown key'
|
||||
|
||||
# For convenience, allow the rrset to be specified as a (name, rdataset)
|
||||
# tuple as well as a proper rrset
|
||||
if isinstance(rrset, tuple):
|
||||
rrname = rrset[0]
|
||||
rdataset = rrset[1]
|
||||
else:
|
||||
rrname = rrset.name
|
||||
rdataset = rrset
|
||||
|
||||
if now is None:
|
||||
now = time.time()
|
||||
if rrsig.expiration < now:
|
||||
raise ValidationFailure, 'expired'
|
||||
if rrsig.inception > now:
|
||||
raise ValidationFailure, 'not yet valid'
|
||||
|
||||
hash = _make_hash(rrsig.algorithm)
|
||||
|
||||
if _is_rsa(rrsig.algorithm):
|
||||
keyptr = key.key
|
||||
(bytes,) = struct.unpack('!B', keyptr[0:1])
|
||||
keyptr = keyptr[1:]
|
||||
if bytes == 0:
|
||||
(bytes,) = struct.unpack('!H', keyptr[0:2])
|
||||
keyptr = keyptr[2:]
|
||||
rsa_e = keyptr[0:bytes]
|
||||
rsa_n = keyptr[bytes:]
|
||||
keylen = len(rsa_n) * 8
|
||||
pubkey = Crypto.PublicKey.RSA.construct(
|
||||
(Crypto.Util.number.bytes_to_long(rsa_n),
|
||||
Crypto.Util.number.bytes_to_long(rsa_e)))
|
||||
sig = (Crypto.Util.number.bytes_to_long(rrsig.signature),)
|
||||
elif _is_dsa(rrsig.algorithm):
|
||||
keyptr = key.key
|
||||
(t,) = struct.unpack('!B', keyptr[0:1])
|
||||
keyptr = keyptr[1:]
|
||||
octets = 64 + t * 8
|
||||
dsa_q = keyptr[0:20]
|
||||
keyptr = keyptr[20:]
|
||||
dsa_p = keyptr[0:octets]
|
||||
keyptr = keyptr[octets:]
|
||||
dsa_g = keyptr[0:octets]
|
||||
keyptr = keyptr[octets:]
|
||||
dsa_y = keyptr[0:octets]
|
||||
pubkey = Crypto.PublicKey.DSA.construct(
|
||||
(Crypto.Util.number.bytes_to_long(dsa_y),
|
||||
Crypto.Util.number.bytes_to_long(dsa_g),
|
||||
Crypto.Util.number.bytes_to_long(dsa_p),
|
||||
Crypto.Util.number.bytes_to_long(dsa_q)))
|
||||
(dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:])
|
||||
sig = (Crypto.Util.number.bytes_to_long(dsa_r),
|
||||
Crypto.Util.number.bytes_to_long(dsa_s))
|
||||
else:
|
||||
raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm
|
||||
|
||||
hash.update(_to_rdata(rrsig, origin)[:18])
|
||||
hash.update(rrsig.signer.to_digestable(origin))
|
||||
|
||||
if rrsig.labels < len(rrname) - 1:
|
||||
suffix = rrname.split(rrsig.labels + 1)[1]
|
||||
rrname = dns.name.from_text('*', suffix)
|
||||
rrnamebuf = rrname.to_digestable(origin)
|
||||
rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass,
|
||||
rrsig.original_ttl)
|
||||
rrlist = sorted(rdataset);
|
||||
for rr in rrlist:
|
||||
hash.update(rrnamebuf)
|
||||
hash.update(rrfixed)
|
||||
rrdata = rr.to_digestable(origin)
|
||||
rrlen = struct.pack('!H', len(rrdata))
|
||||
hash.update(rrlen)
|
||||
hash.update(rrdata)
|
||||
|
||||
digest = hash.digest()
|
||||
|
||||
if _is_rsa(rrsig.algorithm):
|
||||
# PKCS1 algorithm identifier goop
|
||||
digest = _make_algorithm_id(rrsig.algorithm) + digest
|
||||
padlen = keylen // 8 - len(digest) - 3
|
||||
digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest
|
||||
elif _is_dsa(rrsig.algorithm):
|
||||
pass
|
||||
else:
|
||||
# Raise here for code clarity; this won't actually ever happen
|
||||
# since if the algorithm is really unknown we'd already have
|
||||
# raised an exception above
|
||||
raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm
|
||||
|
||||
if not pubkey.verify(digest, sig):
|
||||
raise ValidationFailure, 'verify failure'
|
||||
|
||||
def _validate(rrset, rrsigset, keys, origin=None, now=None):
|
||||
"""Validate an RRset
|
||||
|
||||
@param rrset: The RRset to validate
|
||||
@type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
|
||||
tuple
|
||||
@param rrsigset: The signature RRset
|
||||
@type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
|
||||
tuple
|
||||
@param keys: The key dictionary.
|
||||
@type keys: a dictionary keyed by dns.name.Name with node or rdataset values
|
||||
@param origin: The origin to use for relative names
|
||||
@type origin: dns.name.Name or None
|
||||
@param now: The time to use when validating the signatures. The default
|
||||
is the current time.
|
||||
@type now: int
|
||||
"""
|
||||
|
||||
if isinstance(origin, (str, unicode)):
|
||||
origin = dns.name.from_text(origin, dns.name.root)
|
||||
|
||||
if isinstance(rrset, tuple):
|
||||
rrname = rrset[0]
|
||||
else:
|
||||
rrname = rrset.name
|
||||
|
||||
if isinstance(rrsigset, tuple):
|
||||
rrsigname = rrsigset[0]
|
||||
rrsigrdataset = rrsigset[1]
|
||||
else:
|
||||
rrsigname = rrsigset.name
|
||||
rrsigrdataset = rrsigset
|
||||
|
||||
rrname = rrname.choose_relativity(origin)
|
||||
rrsigname = rrname.choose_relativity(origin)
|
||||
if rrname != rrsigname:
|
||||
raise ValidationFailure, "owner names do not match"
|
||||
|
||||
for rrsig in rrsigrdataset:
|
||||
try:
|
||||
_validate_rrsig(rrset, rrsig, keys, origin, now)
|
||||
return
|
||||
except ValidationFailure, e:
|
||||
pass
|
||||
raise ValidationFailure, "no RRSIGs validated"
|
||||
|
||||
def _need_pycrypto(*args, **kwargs):
|
||||
raise NotImplementedError, "DNSSEC validation requires pycrypto"
|
||||
|
||||
try:
|
||||
import Crypto.PublicKey.RSA
|
||||
import Crypto.PublicKey.DSA
|
||||
import Crypto.Util.number
|
||||
validate = _validate
|
||||
validate_rrsig = _validate_rrsig
|
||||
except ImportError:
|
||||
validate = _need_pycrypto
|
||||
validate_rrsig = _need_pycrypto
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2006, 2007, 2009 Nominum, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,14 +16,14 @@
|
|||
"""DNS E.164 helpers
|
||||
|
||||
@var public_enum_domain: The DNS public ENUM domain, e164.arpa.
|
||||
@type public_enum_domain: linkcheck.dns.name.Name object
|
||||
@type public_enum_domain: dns.name.Name object
|
||||
"""
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.resolver
|
||||
import dns.exception
|
||||
import dns.name
|
||||
import dns.resolver
|
||||
|
||||
public_enum_domain = linkcheck.dns.name.from_text('e164.arpa.')
|
||||
public_enum_domain = dns.name.from_text('e164.arpa.')
|
||||
|
||||
def from_e164(text, origin=public_enum_domain):
|
||||
"""Convert an E.164 number in textual form into a Name object whose
|
||||
|
|
@ -32,20 +32,20 @@ def from_e164(text, origin=public_enum_domain):
|
|||
@type text: str
|
||||
@param origin: The domain in which the number should be constructed.
|
||||
The default is e164.arpa.
|
||||
@type: linkcheck.dns.name.Name object or None
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@type: dns.name.Name object or None
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
parts = [d for d in text if d.isdigit()]
|
||||
parts.reverse()
|
||||
return linkcheck.dns.name.from_text('.'.join(parts), origin=origin)
|
||||
return dns.name.from_text('.'.join(parts), origin=origin)
|
||||
|
||||
def to_e164(name, origin=public_enum_domain, want_plus_prefix=True):
|
||||
"""Convert an ENUM domain name into an E.164 number.
|
||||
@param name: the ENUM domain name.
|
||||
@type name: linkcheck.dns.name.Name object.
|
||||
@type name: dns.name.Name object.
|
||||
@param origin: A domain containing the ENUM domain name. The
|
||||
name is relativized to this domain before being converted to text.
|
||||
@type: linkcheck.dns.name.Name object or None
|
||||
@type: dns.name.Name object or None
|
||||
@param want_plus_prefix: if True, add a '+' to the beginning of the
|
||||
returned number.
|
||||
@rtype: str
|
||||
|
|
@ -54,7 +54,7 @@ def to_e164(name, origin=public_enum_domain, want_plus_prefix=True):
|
|||
name = name.relativize(origin)
|
||||
dlabels = [d for d in name.labels if (d.isdigit() and len(d) == 1)]
|
||||
if len(dlabels) != len(name.labels):
|
||||
raise linkcheck.dns.exception.SyntaxError('non-digit labels in ENUM domain name')
|
||||
raise dns.exception.SyntaxError('non-digit labels in ENUM domain name')
|
||||
dlabels.reverse()
|
||||
text = ''.join(dlabels)
|
||||
if want_plus_prefix:
|
||||
|
|
@ -67,13 +67,13 @@ def query(number, domains, resolver=None):
|
|||
e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
|
||||
"""
|
||||
if resolver is None:
|
||||
resolver = linkcheck.dns.resolver.get_default_resolver()
|
||||
resolver = dns.resolver.get_default_resolver()
|
||||
for domain in domains:
|
||||
if isinstance(domain, (str, unicode)):
|
||||
domain = linkcheck.dns.name.from_text(domain)
|
||||
qname = linkcheck.dns.e164.from_e164(number, domain)
|
||||
domain = dns.name.from_text(domain)
|
||||
qname = dns.e164.from_e164(number, domain)
|
||||
try:
|
||||
return linkcheck.dns.resolver.query(qname, 'NAPTR')
|
||||
except linkcheck.dns.resolver.NXDOMAIN:
|
||||
return resolver.query(qname, 'NAPTR')
|
||||
except dns.resolver.NXDOMAIN:
|
||||
pass
|
||||
raise linkcheck.dns.resolver.NXDOMAIN
|
||||
raise dns.resolver.NXDOMAIN
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2009 Nominum, Inc.
|
||||
# Copyright (C) 2009, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -44,7 +44,7 @@ class Option(object):
|
|||
@type current: int
|
||||
@param olen: The length of the wire-format option data
|
||||
@type olen: int
|
||||
@rtype: linkcheck.dns.ends.Option instance"""
|
||||
@rtype: dns.ends.Option instance"""
|
||||
raise NotImplementedError
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -114,7 +114,7 @@ class GenericOption(Option):
|
|||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
return cmp(self.data, other.data)
|
||||
return cmp(self.data, other.data)
|
||||
|
||||
_type_to_class = {
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ def option_from_wire(otype, wire, current, olen):
|
|||
@type current: int
|
||||
@param olen: The length of the wire-format option data
|
||||
@type olen: int
|
||||
@rtype: linkcheck.dns.ends.Option instance"""
|
||||
@rtype: dns.ends.Option instance"""
|
||||
|
||||
cls = get_option_class(otype)
|
||||
return cls.from_wire(otype, wire, current, olen)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2009 Nominum, Inc.
|
||||
# Copyright (C) 2009, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -30,12 +30,12 @@ class EntropyPool(object):
|
|||
import hashlib
|
||||
self.hash = hashlib.sha1()
|
||||
self.hash_len = 20
|
||||
except:
|
||||
except StandardError:
|
||||
try:
|
||||
import sha
|
||||
self.hash = sha.new()
|
||||
self.hash_len = 20
|
||||
except:
|
||||
except StandardError:
|
||||
import md5
|
||||
self.hash = md5.new()
|
||||
self.hash_len = 16
|
||||
|
|
@ -66,14 +66,14 @@ class EntropyPool(object):
|
|||
if not self.seeded:
|
||||
try:
|
||||
seed = os.urandom(16)
|
||||
except:
|
||||
except StandardError:
|
||||
try:
|
||||
r = file('/dev/urandom', 'r', 0)
|
||||
try:
|
||||
seed = r.read(16)
|
||||
finally:
|
||||
r.close()
|
||||
except:
|
||||
except StandardError:
|
||||
seed = str(time.time())
|
||||
self.seeded = True
|
||||
self.stir(seed, True)
|
||||
|
|
@ -112,7 +112,7 @@ class EntropyPool(object):
|
|||
else:
|
||||
rand = self.random_8
|
||||
max = 255
|
||||
return (first + size * rand() // (max + 1))
|
||||
return (first + size * rand() // (max + 1))
|
||||
|
||||
pool = EntropyPool()
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -24,11 +23,11 @@ class FormError(DNSException):
|
|||
"""DNS message is malformed."""
|
||||
pass
|
||||
|
||||
class DNSSyntaxError(DNSException):
|
||||
class SyntaxError(DNSException):
|
||||
"""Text input is malformed."""
|
||||
pass
|
||||
|
||||
class UnexpectedEnd(DNSSyntaxError):
|
||||
class UnexpectedEnd(SyntaxError):
|
||||
"""Raised if text input ends unexpectedly."""
|
||||
pass
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -90,7 +89,7 @@ def to_text(flags):
|
|||
@rtype: string"""
|
||||
|
||||
return _to_text(flags, _by_value, _flags_order)
|
||||
|
||||
|
||||
|
||||
def edns_from_text(text):
|
||||
"""Convert a space-separated list of EDNS flag text values into a EDNS
|
||||
67
third_party/dnspython/dns/hash.py
vendored
Normal file
67
third_party/dnspython/dns/hash.py
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Copyright (C) 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""Hashing backwards compatibility wrapper"""
|
||||
|
||||
import sys
|
||||
|
||||
_hashes = None
|
||||
|
||||
def _need_later_python(alg):
|
||||
def func(*args, **kwargs):
|
||||
raise NotImplementedError("TSIG algorithm " + alg +
|
||||
" requires Python 2.5.2 or later")
|
||||
return func
|
||||
|
||||
def _setup():
|
||||
global _hashes
|
||||
_hashes = {}
|
||||
try:
|
||||
import hashlib
|
||||
_hashes['MD5'] = hashlib.md5
|
||||
_hashes['SHA1'] = hashlib.sha1
|
||||
_hashes['SHA224'] = hashlib.sha224
|
||||
_hashes['SHA256'] = hashlib.sha256
|
||||
if sys.hexversion >= 0x02050200:
|
||||
_hashes['SHA384'] = hashlib.sha384
|
||||
_hashes['SHA512'] = hashlib.sha512
|
||||
else:
|
||||
_hashes['SHA384'] = _need_later_python('SHA384')
|
||||
_hashes['SHA512'] = _need_later_python('SHA512')
|
||||
|
||||
if sys.hexversion < 0x02050000:
|
||||
# hashlib doesn't conform to PEP 247: API for
|
||||
# Cryptographic Hash Functions, which hmac before python
|
||||
# 2.5 requires, so add the necessary items.
|
||||
class HashlibWrapper:
|
||||
def __init__(self, basehash):
|
||||
self.basehash = basehash
|
||||
self.digest_size = self.basehash().digest_size
|
||||
|
||||
def new(self, *args, **kwargs):
|
||||
return self.basehash(*args, **kwargs)
|
||||
|
||||
for name in _hashes:
|
||||
_hashes[name] = HashlibWrapper(_hashes[name])
|
||||
|
||||
except ImportError:
|
||||
import md5, sha
|
||||
_hashes['MD5'] = md5
|
||||
_hashes['SHA1'] = sha
|
||||
|
||||
def get(algorithm):
|
||||
if _hashes is None:
|
||||
_setup()
|
||||
return _hashes[algorithm.upper()]
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -18,8 +17,8 @@
|
|||
|
||||
import socket
|
||||
|
||||
import linkcheck.dns.ipv4
|
||||
import linkcheck.dns.ipv6
|
||||
import dns.ipv4
|
||||
import dns.ipv6
|
||||
|
||||
|
||||
# We assume that AF_INET is always defined.
|
||||
|
|
@ -46,11 +45,11 @@ def inet_pton(family, text):
|
|||
implemented.
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
|
||||
if family == AF_INET:
|
||||
return linkcheck.dns.ipv4.inet_aton(text)
|
||||
return dns.ipv4.inet_aton(text)
|
||||
elif family == AF_INET6:
|
||||
return linkcheck.dns.ipv6.inet_aton(text)
|
||||
return dns.ipv6.inet_aton(text)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
@ -66,9 +65,9 @@ def inet_ntop(family, address):
|
|||
@rtype: string
|
||||
"""
|
||||
if family == AF_INET:
|
||||
return linkcheck.dns.ipv4.inet_ntoa(address)
|
||||
return dns.ipv4.inet_ntoa(address)
|
||||
elif family == AF_INET6:
|
||||
return linkcheck.dns.ipv6.inet_ntoa(address)
|
||||
return dns.ipv6.inet_ntoa(address)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
|
@ -78,14 +77,14 @@ def af_for_address(text):
|
|||
@param text: the textual address
|
||||
@type text: string
|
||||
@raises ValueError: the address family cannot be determined from the input.
|
||||
@rtype int
|
||||
@rtype: int
|
||||
"""
|
||||
try:
|
||||
junk = linkcheck.dns.ipv4.inet_aton(text)
|
||||
junk = dns.ipv4.inet_aton(text)
|
||||
return AF_INET
|
||||
except StandardError:
|
||||
try:
|
||||
junk = linkcheck.dns.ipv6.inet_aton(text)
|
||||
junk = dns.ipv6.inet_aton(text)
|
||||
return AF_INET6
|
||||
except StandardError:
|
||||
raise ValueError
|
||||
|
|
@ -98,11 +97,12 @@ def is_multicast(text):
|
|||
@rtype: bool
|
||||
"""
|
||||
try:
|
||||
first = ord(linkcheck.dns.ipv4.inet_aton(text)[0])
|
||||
first = ord(dns.ipv4.inet_aton(text)[0])
|
||||
return (first >= 224 and first <= 239)
|
||||
except:
|
||||
except StandardError:
|
||||
try:
|
||||
first = ord(linkcheck.dns.ipv6.inet_aton(text)[0])
|
||||
first = ord(dns.ipv6.inet_aton(text)[0])
|
||||
return (first == 255)
|
||||
except:
|
||||
except StandardError:
|
||||
raise ValueError
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -18,8 +17,8 @@
|
|||
|
||||
import re
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.ipv4
|
||||
import dns.exception
|
||||
import dns.ipv4
|
||||
|
||||
_leading_zero = re.compile(r'0+([0-9a-f]+)')
|
||||
|
||||
|
|
@ -34,19 +33,19 @@ def inet_ntoa(address):
|
|||
|
||||
if len(address) != 16:
|
||||
raise ValueError("IPv6 addresses are 16 bytes long")
|
||||
hexip = address.encode('hex_codec')
|
||||
hex = address.encode('hex_codec')
|
||||
chunks = []
|
||||
i = 0
|
||||
l = len(hexip)
|
||||
l = len(hex)
|
||||
while i < l:
|
||||
ipchunk = hexip[i : i + 4]
|
||||
chunk = hex[i : i + 4]
|
||||
# strip leading zeros. we do this with an re instead of
|
||||
# with lstrip() because lstrip() didn't support chars until
|
||||
# python 2.2.2
|
||||
m = _leading_zero.match(ipchunk)
|
||||
m = _leading_zero.match(chunk)
|
||||
if not m is None:
|
||||
ipchunk = m.group(1)
|
||||
chunks.append(ipchunk)
|
||||
chunk = m.group(1)
|
||||
chunks.append(chunk)
|
||||
i += 4
|
||||
#
|
||||
# Compress the longest subsequence of 0-value chunks to ::
|
||||
|
|
@ -82,13 +81,13 @@ def inet_ntoa(address):
|
|||
prefix = '::'
|
||||
else:
|
||||
prefix = '::ffff:'
|
||||
hexip = prefix + linkcheck.dns.ipv4.inet_ntoa(address[12:])
|
||||
hex = prefix + dns.ipv4.inet_ntoa(address[12:])
|
||||
else:
|
||||
hexip = ':'.join(chunks[:best_start]) + '::' + \
|
||||
hex = ':'.join(chunks[:best_start]) + '::' + \
|
||||
':'.join(chunks[best_start + best_len:])
|
||||
else:
|
||||
hexip = ':'.join(chunks)
|
||||
return hexip
|
||||
hex = ':'.join(chunks)
|
||||
return hex
|
||||
|
||||
_v4_ending = re.compile(r'(.*):(\d+)\.(\d+)\.(\d+)\.(\d+)$')
|
||||
_colon_colon_start = re.compile(r'::.*')
|
||||
|
|
@ -100,7 +99,7 @@ def inet_aton(text):
|
|||
@param text: the textual address
|
||||
@type text: string
|
||||
@rtype: string
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError: the text was not properly formatted
|
||||
@raises dns.exception.SyntaxError: the text was not properly formatted
|
||||
"""
|
||||
|
||||
#
|
||||
|
|
@ -134,25 +133,25 @@ def inet_aton(text):
|
|||
chunks = text.split(':')
|
||||
l = len(chunks)
|
||||
if l > 8:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
seen_empty = False
|
||||
canonical = []
|
||||
for c in chunks:
|
||||
if c == '':
|
||||
if seen_empty:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
seen_empty = True
|
||||
for i in xrange(0, 8 - l + 1):
|
||||
canonical.append('0000')
|
||||
else:
|
||||
lc = len(c)
|
||||
if lc > 4:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
if lc != 4:
|
||||
c = ('0' * (4 - lc)) + c
|
||||
canonical.append(c)
|
||||
if l < 8 and not seen_empty:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
text = ''.join(canonical)
|
||||
|
||||
#
|
||||
|
|
@ -161,4 +160,4 @@ def inet_aton(text):
|
|||
try:
|
||||
return text.decode('hex_codec')
|
||||
except TypeError:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,49 +15,52 @@
|
|||
|
||||
"""DNS Messages"""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import random
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
|
||||
import linkcheck.dns.edns
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.flags
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.opcode
|
||||
import linkcheck.dns.entropy
|
||||
import linkcheck.dns.rcode
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.rrset
|
||||
import linkcheck.dns.renderer
|
||||
import linkcheck.dns.tsig
|
||||
import dns.edns
|
||||
import dns.exception
|
||||
import dns.flags
|
||||
import dns.name
|
||||
import dns.opcode
|
||||
import dns.entropy
|
||||
import dns.rcode
|
||||
import dns.rdata
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
import dns.renderer
|
||||
import dns.tsig
|
||||
import dns.wiredata
|
||||
|
||||
class ShortHeader(linkcheck.dns.exception.FormError):
|
||||
class ShortHeader(dns.exception.FormError):
|
||||
"""Raised if the DNS packet passed to from_wire() is too short."""
|
||||
pass
|
||||
|
||||
class TrailingJunk(linkcheck.dns.exception.FormError):
|
||||
class TrailingJunk(dns.exception.FormError):
|
||||
"""Raised if the DNS packet passed to from_wire() has extra junk
|
||||
at the end of it."""
|
||||
pass
|
||||
|
||||
class UnknownHeaderField(linkcheck.dns.exception.DNSException):
|
||||
class UnknownHeaderField(dns.exception.DNSException):
|
||||
"""Raised if a header field name is not recognized when converting from
|
||||
text into a message."""
|
||||
pass
|
||||
|
||||
class BadEDNS(linkcheck.dns.exception.FormError):
|
||||
class BadEDNS(dns.exception.FormError):
|
||||
"""Raised if an OPT record occurs somewhere other than the start of
|
||||
the additional data section."""
|
||||
pass
|
||||
|
||||
class BadTSIG(linkcheck.dns.exception.FormError):
|
||||
class BadTSIG(dns.exception.FormError):
|
||||
"""Raised if a TSIG record occurs somewhere other than the end of
|
||||
the additional data section."""
|
||||
pass
|
||||
|
||||
class UnknownTSIGKey(linkcheck.dns.exception.DNSException):
|
||||
class UnknownTSIGKey(dns.exception.DNSException):
|
||||
"""Raised if we got a TSIG but don't know the key."""
|
||||
pass
|
||||
|
||||
|
|
@ -71,36 +73,36 @@ class Message(object):
|
|||
explanation of these flags.
|
||||
@type flags: int
|
||||
@ivar question: The question section.
|
||||
@type question: list of linkcheck.dns.rrset.RRset objects
|
||||
@type question: list of dns.rrset.RRset objects
|
||||
@ivar answer: The answer section.
|
||||
@type answer: list of linkcheck.dns.rrset.RRset objects
|
||||
@type answer: list of dns.rrset.RRset objects
|
||||
@ivar authority: The authority section.
|
||||
@type authority: list of linkcheck.dns.rrset.RRset objects
|
||||
@type authority: list of dns.rrset.RRset objects
|
||||
@ivar additional: The additional data section.
|
||||
@type additional: list of linkcheck.dns.rrset.RRset objects
|
||||
@ivar edns: The EDNS level to use. The default is -1, no Elinkcheck.dns.
|
||||
@type additional: list of dns.rrset.RRset objects
|
||||
@ivar edns: The EDNS level to use. The default is -1, no Edns.
|
||||
@type edns: int
|
||||
@ivar ednsflags: The EDNS flags
|
||||
@type ednsflags: long
|
||||
@ivar payload: The EDNS payload size. The default is 0.
|
||||
@type payload: int
|
||||
@ivar options: The EDNS options
|
||||
@type options: list of linkcheck.dns.edns.Option objects
|
||||
@type options: list of dns.edns.Option objects
|
||||
@ivar request_payload: The associated request's EDNS payload size.
|
||||
@type request_payload: int
|
||||
@ivar keyring: The TSIG keyring to use. The default is None.
|
||||
@type keyring: dict
|
||||
@ivar keyname: The TSIG keyname to use. The default is None.
|
||||
@type keyname: linkcheck.dns.name.Name object
|
||||
@ivar request_mac: The TSIG MAC of the request message associated with
|
||||
this message; used when validating TSIG signatures. @see: RFC 2845 for
|
||||
more information on TSIG fields.
|
||||
@type keyname: dns.name.Name object
|
||||
@ivar keyalgorithm: The TSIG algorithm to use; defaults to
|
||||
linkcheck.dns.tsig.default_algorithm. Constants for TSIG algorithms are defined
|
||||
in linkcheck.dns.tsig, and the currently implemented algorithms are
|
||||
dns.tsig.default_algorithm. Constants for TSIG algorithms are defined
|
||||
in dns.tsig, and the currently implemented algorithms are
|
||||
HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
|
||||
HMAC_SHA512.
|
||||
@type keyalgorithm: string
|
||||
@ivar request_mac: The TSIG MAC of the request message associated with
|
||||
this message; used when validating TSIG signatures. @see: RFC 2845 for
|
||||
more information on TSIG fields.
|
||||
@type request_mac: string
|
||||
@ivar fudge: TSIG time fudge; default is 300 seconds.
|
||||
@type fudge: int
|
||||
|
|
@ -117,7 +119,7 @@ class Message(object):
|
|||
@type xfr: bool
|
||||
@ivar origin: The origin of the zone in messages which are used for
|
||||
zone transfers or for DNS dynamic updates. The default is None.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@ivar tsig_ctx: The TSIG signature context associated with this
|
||||
message. The default is None.
|
||||
@type tsig_ctx: hmac.HMAC object
|
||||
|
|
@ -140,7 +142,7 @@ class Message(object):
|
|||
|
||||
def __init__(self, id=None):
|
||||
if id is None:
|
||||
self.id = linkcheck.dns.entropy.random_16()
|
||||
self.id = dns.entropy.random_16()
|
||||
else:
|
||||
self.id = id
|
||||
self.flags = 0
|
||||
|
|
@ -155,7 +157,7 @@ class Message(object):
|
|||
self.request_payload = 0
|
||||
self.keyring = None
|
||||
self.keyname = None
|
||||
self.keyalgorithm = linkcheck.dns.tsig.default_algorithm
|
||||
self.keyalgorithm = dns.tsig.default_algorithm
|
||||
self.request_mac = ''
|
||||
self.other_data = ''
|
||||
self.tsig_error = 0
|
||||
|
|
@ -171,7 +173,7 @@ class Message(object):
|
|||
self.index = {}
|
||||
|
||||
def __repr__(self):
|
||||
return '<DNS message, ID %r>' % self.id
|
||||
return '<DNS message, ID ' + `self.id` + '>'
|
||||
|
||||
def __str__(self):
|
||||
return self.to_text()
|
||||
|
|
@ -185,20 +187,20 @@ class Message(object):
|
|||
@rtype: string
|
||||
"""
|
||||
|
||||
s = StringIO()
|
||||
s = cStringIO.StringIO()
|
||||
print >> s, 'id %d' % self.id
|
||||
print >> s, 'opcode %s' % \
|
||||
linkcheck.dns.opcode.to_text(linkcheck.dns.opcode.from_flags(self.flags))
|
||||
rc = linkcheck.dns.rcode.from_flags(self.flags, self.ednsflags)
|
||||
print >> s, 'rcode %s' % linkcheck.dns.rcode.to_text(rc)
|
||||
print >> s, 'flags %s' % linkcheck.dns.flags.to_text(self.flags)
|
||||
dns.opcode.to_text(dns.opcode.from_flags(self.flags))
|
||||
rc = dns.rcode.from_flags(self.flags, self.ednsflags)
|
||||
print >> s, 'rcode %s' % dns.rcode.to_text(rc)
|
||||
print >> s, 'flags %s' % dns.flags.to_text(self.flags)
|
||||
if self.edns >= 0:
|
||||
print >> s, 'edns %s' % self.edns
|
||||
if self.ednsflags != 0:
|
||||
print >> s, 'eflags %s' % \
|
||||
linkcheck.dns.flags.edns_to_text(self.ednsflags)
|
||||
dns.flags.edns_to_text(self.ednsflags)
|
||||
print >> s, 'payload', self.payload
|
||||
is_update = linkcheck.dns.opcode.is_update(self.flags)
|
||||
is_update = dns.opcode.is_update(self.flags)
|
||||
if is_update:
|
||||
print >> s, ';ZONE'
|
||||
else:
|
||||
|
|
@ -220,11 +222,11 @@ class Message(object):
|
|||
print >> s, ';ADDITIONAL'
|
||||
for rrset in self.additional:
|
||||
print >> s, rrset.to_text(origin, relativize, **kw)
|
||||
|
||||
#
|
||||
# We strip off the final \n so the caller can print the result without
|
||||
# doing weird things to get around eccentricities in Python print
|
||||
# formatting
|
||||
|
||||
#
|
||||
return s.getvalue()[:-1]
|
||||
|
||||
def __eq__(self, other):
|
||||
|
|
@ -265,15 +267,15 @@ class Message(object):
|
|||
def is_response(self, other):
|
||||
"""Is other a response to self?
|
||||
@rtype: bool"""
|
||||
if other.flags & linkcheck.dns.flags.QR == 0 or \
|
||||
if other.flags & dns.flags.QR == 0 or \
|
||||
self.id != other.id or \
|
||||
linkcheck.dns.opcode.from_flags(self.flags) != \
|
||||
linkcheck.dns.opcode.from_flags(other.flags):
|
||||
dns.opcode.from_flags(self.flags) != \
|
||||
dns.opcode.from_flags(other.flags):
|
||||
return False
|
||||
if linkcheck.dns.rcode.from_flags(other.flags, other.ednsflags) != \
|
||||
linkcheck.dns.rcode.NOERROR:
|
||||
if dns.rcode.from_flags(other.flags, other.ednsflags) != \
|
||||
dns.rcode.NOERROR:
|
||||
return True
|
||||
if linkcheck.dns.opcode.is_update(self.flags):
|
||||
if dns.opcode.is_update(self.flags):
|
||||
return True
|
||||
for n in self.question:
|
||||
if n not in other.question:
|
||||
|
|
@ -296,15 +298,15 @@ class Message(object):
|
|||
raise ValueError('unknown section')
|
||||
|
||||
def find_rrset(self, section, name, rdclass, rdtype,
|
||||
covers=linkcheck.dns.rdatatype.NONE, deleting=None, create=False,
|
||||
covers=dns.rdatatype.NONE, deleting=None, create=False,
|
||||
force_unique=False):
|
||||
"""Find the RRset with the given attributes in the specified section.
|
||||
|
||||
@param section: the section of the message to look in, e.g.
|
||||
self.answer.
|
||||
@type section: list of linkcheck.dns.rrset.RRset objects
|
||||
@type section: list of dns.rrset.RRset objects
|
||||
@param name: the name of the RRset
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@param rdclass: the class of the RRset
|
||||
@type rdclass: int
|
||||
@param rdtype: the type of the RRset
|
||||
|
|
@ -320,7 +322,7 @@ class Message(object):
|
|||
new RRset regardless of whether a matching RRset exists already.
|
||||
@type force_unique: bool
|
||||
@raises KeyError: the RRset was not found and create was False
|
||||
@rtype: linkcheck.dns.rrset.RRset object"""
|
||||
@rtype: dns.rrset.RRset object"""
|
||||
|
||||
key = (self.section_number(section),
|
||||
name, rdclass, rdtype, covers, deleting)
|
||||
|
|
@ -335,14 +337,14 @@ class Message(object):
|
|||
return rrset
|
||||
if not create:
|
||||
raise KeyError
|
||||
rrset = linkcheck.dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
|
||||
rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
|
||||
section.append(rrset)
|
||||
if not self.index is None:
|
||||
self.index[key] = rrset
|
||||
return rrset
|
||||
|
||||
def get_rrset(self, section, name, rdclass, rdtype,
|
||||
covers=linkcheck.dns.rdatatype.NONE, deleting=None, create=False,
|
||||
covers=dns.rdatatype.NONE, deleting=None, create=False,
|
||||
force_unique=False):
|
||||
"""Get the RRset with the given attributes in the specified section.
|
||||
|
||||
|
|
@ -350,9 +352,9 @@ class Message(object):
|
|||
|
||||
@param section: the section of the message to look in, e.g.
|
||||
self.answer.
|
||||
@type section: list of linkcheck.dns.rrset.RRset objects
|
||||
@type section: list of dns.rrset.RRset objects
|
||||
@param name: the name of the RRset
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@param rdclass: the class of the RRset
|
||||
@type rdclass: int
|
||||
@param rdtype: the type of the RRset
|
||||
|
|
@ -367,7 +369,7 @@ class Message(object):
|
|||
@param force_unique: If True and create is also True, create a
|
||||
new RRset regardless of whether a matching RRset exists already.
|
||||
@type force_unique: bool
|
||||
@rtype: linkcheck.dns.rrset.RRset object or None"""
|
||||
@rtype: dns.rrset.RRset object or None"""
|
||||
|
||||
try:
|
||||
rrset = self.find_rrset(section, name, rdclass, rdtype, covers,
|
||||
|
|
@ -384,12 +386,12 @@ class Message(object):
|
|||
method.
|
||||
|
||||
@param origin: The origin to be appended to any relative names.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@param max_size: The maximum size of the wire format output; default
|
||||
is 0, which means 'the message's request payload, if nonzero, or
|
||||
65536'.
|
||||
@type max_size: int
|
||||
@raises linkcheck.dns.exception.TooBig: max_size was exceeded
|
||||
@raises dns.exception.TooBig: max_size was exceeded
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
|
|
@ -402,17 +404,17 @@ class Message(object):
|
|||
max_size = 512
|
||||
elif max_size > 65535:
|
||||
max_size = 65535
|
||||
r = linkcheck.dns.renderer.Renderer(self.id, self.flags, max_size, origin)
|
||||
r = dns.renderer.Renderer(self.id, self.flags, max_size, origin)
|
||||
for rrset in self.question:
|
||||
r.add_question(rrset.name, rrset.rdtype, rrset.rdclass)
|
||||
for rrset in self.answer:
|
||||
r.add_rrset(linkcheck.dns.renderer.ANSWER, rrset, **kw)
|
||||
r.add_rrset(dns.renderer.ANSWER, rrset, **kw)
|
||||
for rrset in self.authority:
|
||||
r.add_rrset(linkcheck.dns.renderer.AUTHORITY, rrset, **kw)
|
||||
r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw)
|
||||
if self.edns >= 0:
|
||||
r.add_edns(self.edns, self.ednsflags, self.payload)
|
||||
r.add_edns(self.edns, self.ednsflags, self.payload, self.options)
|
||||
for rrset in self.additional:
|
||||
r.add_rrset(linkcheck.dns.renderer.ADDITIONAL, rrset, **kw)
|
||||
r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
|
||||
r.write_header()
|
||||
if not self.keyname is None:
|
||||
r.add_tsig(self.keyname, self.keyring[self.keyname],
|
||||
|
|
@ -422,9 +424,9 @@ class Message(object):
|
|||
self.mac = r.mac
|
||||
return r.get_wire()
|
||||
|
||||
def use_tsig(self, keyring, keyname=None, fudge=300, original_id=None,
|
||||
tsig_error=0, other_data='',
|
||||
algorithm=linkcheck.dns.tsig.default_algorithm):
|
||||
def use_tsig(self, keyring, keyname=None, fudge=300,
|
||||
original_id=None, tsig_error=0, other_data='',
|
||||
algorithm=dns.tsig.default_algorithm):
|
||||
"""When sending, a TSIG signature using the specified keyring
|
||||
and keyname should be added.
|
||||
|
||||
|
|
@ -436,7 +438,7 @@ class Message(object):
|
|||
keyring. Note that the order of keys in a dictionary is not defined,
|
||||
so applications should supply a keyname when a keyring is used, unless
|
||||
they know the keyring contains only one key.
|
||||
@type keyname: linkcheck.dns.name.Name or string
|
||||
@type keyname: dns.name.Name or string
|
||||
@param fudge: TSIG time fudge; default is 300 seconds.
|
||||
@type fudge: int
|
||||
@param original_id: TSIG original id; defaults to the message's id
|
||||
|
|
@ -446,15 +448,15 @@ class Message(object):
|
|||
@param other_data: TSIG other data.
|
||||
@type other_data: string
|
||||
@param algorithm: The TSIG algorithm to use; defaults to
|
||||
linkcheck.dns.tsig.default_algorithm
|
||||
dns.tsig.default_algorithm
|
||||
"""
|
||||
|
||||
self.keyring = keyring
|
||||
if keyname is None:
|
||||
self.keyname = self.keyring.keys()[0]
|
||||
else:
|
||||
if isinstance(keyname, basestring):
|
||||
keyname = linkcheck.dns.name.from_text(keyname)
|
||||
if isinstance(keyname, (str, unicode)):
|
||||
keyname = dns.name.from_text(keyname)
|
||||
self.keyname = keyname
|
||||
self.keyalgorithm = algorithm
|
||||
self.fudge = fudge
|
||||
|
|
@ -480,9 +482,9 @@ class Message(object):
|
|||
@param request_payload: The EDNS payload size to use when sending
|
||||
this message. If not specified, defaults to the value of payload.
|
||||
@type request_payload: int or None
|
||||
@see: RFC 2671
|
||||
@param options: The EDNS options
|
||||
@type options: None or list of linkcheck.dns.edns.Option objects
|
||||
@type options: None or list of dns.edns.Option objects
|
||||
@see: RFC 2671
|
||||
"""
|
||||
if edns is None or edns is False:
|
||||
edns = -1
|
||||
|
|
@ -517,22 +519,22 @@ class Message(object):
|
|||
if wanted:
|
||||
if self.edns < 0:
|
||||
self.use_edns()
|
||||
self.ednsflags |= linkcheck.dns.flags.DO
|
||||
self.ednsflags |= dns.flags.DO
|
||||
elif self.edns >= 0:
|
||||
self.ednsflags &= ~linkcheck.dns.flags.DO
|
||||
self.ednsflags &= ~dns.flags.DO
|
||||
|
||||
def rcode(self):
|
||||
"""Return the rcode.
|
||||
@rtype: int
|
||||
"""
|
||||
return linkcheck.dns.rcode.from_flags(self.flags, self.ednsflags)
|
||||
return dns.rcode.from_flags(self.flags, self.ednsflags)
|
||||
|
||||
def set_rcode(self, rcode):
|
||||
"""Set the rcode.
|
||||
@param rcode: the rcode
|
||||
@type rcode: int
|
||||
"""
|
||||
(value, evalue) = linkcheck.dns.rcode.to_flags(rcode)
|
||||
(value, evalue) = dns.rcode.to_flags(rcode)
|
||||
self.flags &= 0xFFF0
|
||||
self.flags |= value
|
||||
self.ednsflags &= 0x00FFFFFFL
|
||||
|
|
@ -544,7 +546,7 @@ class Message(object):
|
|||
"""Return the opcode.
|
||||
@rtype: int
|
||||
"""
|
||||
return linkcheck.dns.opcode.from_flags(self.flags)
|
||||
return dns.opcode.from_flags(self.flags)
|
||||
|
||||
def set_opcode(self, opcode):
|
||||
"""Set the opcode.
|
||||
|
|
@ -552,8 +554,7 @@ class Message(object):
|
|||
@type opcode: int
|
||||
"""
|
||||
self.flags &= 0x87FF
|
||||
self.flags |= linkcheck.dns.opcode.to_flags(opcode)
|
||||
|
||||
self.flags |= dns.opcode.to_flags(opcode)
|
||||
|
||||
class _WireReader(object):
|
||||
"""Wire format reader.
|
||||
|
|
@ -561,7 +562,7 @@ class _WireReader(object):
|
|||
@ivar wire: the wire-format message.
|
||||
@type wire: string
|
||||
@ivar message: The message object being built
|
||||
@type message: linkcheck.dns.message.Message object
|
||||
@type message: dns.message.Message object
|
||||
@ivar current: When building a message object from wire format, this
|
||||
variable contains the offset from the beginning of wire of the next octet
|
||||
to be read.
|
||||
|
|
@ -577,11 +578,11 @@ class _WireReader(object):
|
|||
|
||||
def __init__(self, wire, message, question_only=False,
|
||||
one_rr_per_rrset=False):
|
||||
self.wire = wire
|
||||
self.wire = dns.wiredata.maybe_wrap(wire)
|
||||
self.message = message
|
||||
self.current = 0
|
||||
self.updating = False
|
||||
self.zone_rdclass = linkcheck.dns.rdataclass.IN
|
||||
self.zone_rdclass = dns.rdataclass.IN
|
||||
self.question_only = question_only
|
||||
self.one_rr_per_rrset = one_rr_per_rrset
|
||||
|
||||
|
|
@ -592,10 +593,10 @@ class _WireReader(object):
|
|||
@type qcount: int"""
|
||||
|
||||
if self.updating and qcount > 1:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
|
||||
for i in xrange(0, qcount):
|
||||
(qname, used) = linkcheck.dns.name.from_wire(self.wire, self.current)
|
||||
(qname, used) = dns.name.from_wire(self.wire, self.current)
|
||||
if not self.message.origin is None:
|
||||
qname = qname.relativize(self.message.origin)
|
||||
self.current = self.current + used
|
||||
|
|
@ -613,7 +614,7 @@ class _WireReader(object):
|
|||
"""Read the next I{count} records from the wire data and add them to
|
||||
the specified section.
|
||||
@param section: the section of the message to which to add records
|
||||
@type section: list of linkcheck.dns.rrset.RRset objects
|
||||
@type section: list of dns.rrset.RRset objects
|
||||
@param count: the number of records to read
|
||||
@type count: int"""
|
||||
|
||||
|
|
@ -624,7 +625,7 @@ class _WireReader(object):
|
|||
seen_opt = False
|
||||
for i in xrange(0, count):
|
||||
rr_start = self.current
|
||||
(name, used) = linkcheck.dns.name.from_wire(self.wire, self.current)
|
||||
(name, used) = dns.name.from_wire(self.wire, self.current)
|
||||
absolute_name = name
|
||||
if not self.message.origin is None:
|
||||
name = name.relativize(self.message.origin)
|
||||
|
|
@ -633,7 +634,7 @@ class _WireReader(object):
|
|||
struct.unpack('!HHIH',
|
||||
self.wire[self.current:self.current + 10])
|
||||
self.current = self.current + 10
|
||||
if rdtype == linkcheck.dns.rdatatype.OPT:
|
||||
if rdtype == dns.rdatatype.OPT:
|
||||
if not section is self.message.additional or seen_opt:
|
||||
raise BadEDNS
|
||||
self.message.payload = rdclass
|
||||
|
|
@ -647,12 +648,12 @@ class _WireReader(object):
|
|||
struct.unpack('!HH',
|
||||
self.wire[current:current + 4])
|
||||
current = current + 4
|
||||
opt = linkcheck.dns.edns.option_from_wire(otype, self.wire, current, olen)
|
||||
opt = dns.edns.option_from_wire(otype, self.wire, current, olen)
|
||||
self.message.options.append(opt)
|
||||
current = current + olen
|
||||
optslen = optslen - 4 - olen
|
||||
seen_opt = True
|
||||
elif rdtype == linkcheck.dns.rdatatype.TSIG:
|
||||
elif rdtype == dns.rdatatype.TSIG:
|
||||
if not (section is self.message.additional and
|
||||
i == (count - 1)):
|
||||
raise BadTSIG
|
||||
|
|
@ -662,7 +663,7 @@ class _WireReader(object):
|
|||
if secret is None:
|
||||
raise UnknownTSIGKey("key '%s' unknown" % name)
|
||||
self.message.tsig_ctx = \
|
||||
linkcheck.dns.tsig.validate(self.wire,
|
||||
dns.tsig.validate(self.wire,
|
||||
absolute_name,
|
||||
secret,
|
||||
int(time.time()),
|
||||
|
|
@ -678,23 +679,23 @@ class _WireReader(object):
|
|||
if ttl < 0:
|
||||
ttl = 0
|
||||
if self.updating and \
|
||||
(rdclass == linkcheck.dns.rdataclass.ANY or
|
||||
rdclass == linkcheck.dns.rdataclass.NONE):
|
||||
(rdclass == dns.rdataclass.ANY or
|
||||
rdclass == dns.rdataclass.NONE):
|
||||
deleting = rdclass
|
||||
rdclass = self.zone_rdclass
|
||||
else:
|
||||
deleting = None
|
||||
if deleting == linkcheck.dns.rdataclass.ANY or \
|
||||
(deleting == linkcheck.dns.rdataclass.NONE and \
|
||||
section == self.message.answer):
|
||||
covers = linkcheck.dns.rdatatype.NONE
|
||||
if deleting == dns.rdataclass.ANY or \
|
||||
(deleting == dns.rdataclass.NONE and \
|
||||
section is self.message.answer):
|
||||
covers = dns.rdatatype.NONE
|
||||
rd = None
|
||||
else:
|
||||
rd = linkcheck.dns.rdata.from_wire(rdclass, rdtype, self.wire,
|
||||
rd = dns.rdata.from_wire(rdclass, rdtype, self.wire,
|
||||
self.current, rdlen,
|
||||
self.message.origin)
|
||||
covers = rd.covers()
|
||||
if self.message.xfr and rdtype == linkcheck.dns.rdatatype.SOA:
|
||||
if self.message.xfr and rdtype == dns.rdatatype.SOA:
|
||||
force_unique = True
|
||||
rrset = self.message.find_rrset(section, name,
|
||||
rdclass, rdtype, covers,
|
||||
|
|
@ -704,7 +705,7 @@ class _WireReader(object):
|
|||
self.current = self.current + rdlen
|
||||
|
||||
def read(self):
|
||||
"""Read a wire format DNS message and build a linkcheck.dns.message.Message
|
||||
"""Read a wire format DNS message and build a dns.message.Message
|
||||
object."""
|
||||
|
||||
l = len(self.wire)
|
||||
|
|
@ -713,7 +714,7 @@ class _WireReader(object):
|
|||
(self.message.id, self.message.flags, qcount, ancount,
|
||||
aucount, adcount) = struct.unpack('!HHHHHH', self.wire[:12])
|
||||
self.current = 12
|
||||
if linkcheck.dns.opcode.is_update(self.message.flags):
|
||||
if dns.opcode.is_update(self.message.flags):
|
||||
self.updating = True
|
||||
self._get_question(qcount)
|
||||
if self.question_only:
|
||||
|
|
@ -743,7 +744,7 @@ def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
|
|||
@type xfr: bool
|
||||
@param origin: If the message is part of a zone transfer, I{origin}
|
||||
should be the origin name of the zone.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@param tsig_ctx: The ongoing TSIG context, used when validating zone
|
||||
transfers.
|
||||
@type tsig_ctx: hmac.HMAC object
|
||||
|
|
@ -763,7 +764,7 @@ def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
|
|||
than once.
|
||||
@raises BadTSIG: A TSIG record was not the last record of the additional
|
||||
data section.
|
||||
@rtype: linkcheck.dns.message.Message object"""
|
||||
@rtype: dns.message.Message object"""
|
||||
|
||||
m = Message(id=0)
|
||||
m.keyring = keyring
|
||||
|
|
@ -784,9 +785,9 @@ class _TextReader(object):
|
|||
"""Text format reader.
|
||||
|
||||
@ivar tok: the tokenizer
|
||||
@type tok: linkcheck.dns.tokenizer.Tokenizer object
|
||||
@type tok: dns.tokenizer.Tokenizer object
|
||||
@ivar message: The message object being built
|
||||
@type message: linkcheck.dns.message.Message object
|
||||
@type message: dns.message.Message object
|
||||
@ivar updating: Is the message a dynamic update?
|
||||
@type updating: bool
|
||||
@ivar zone_rdclass: The class of the zone in messages which are
|
||||
|
|
@ -794,14 +795,14 @@ class _TextReader(object):
|
|||
@type zone_rdclass: int
|
||||
@ivar last_name: The most recently read name when building a message object
|
||||
from text format.
|
||||
@type last_name: linkcheck.dns.name.Name object
|
||||
@type last_name: dns.name.Name object
|
||||
"""
|
||||
|
||||
def __init__(self, text, message):
|
||||
self.message = message
|
||||
self.tok = linkcheck.dns.tokenizer.Tokenizer(text)
|
||||
self.tok = dns.tokenizer.Tokenizer(text)
|
||||
self.last_name = None
|
||||
self.zone_rdclass = linkcheck.dns.rdataclass.IN
|
||||
self.zone_rdclass = dns.rdataclass.IN
|
||||
self.updating = False
|
||||
|
||||
def _header_line(self, section):
|
||||
|
|
@ -818,8 +819,8 @@ class _TextReader(object):
|
|||
self.tok.unget(token)
|
||||
break
|
||||
self.message.flags = self.message.flags | \
|
||||
linkcheck.dns.flags.from_text(token[1])
|
||||
if linkcheck.dns.opcode.is_update(self.message.flags):
|
||||
dns.flags.from_text(token.value)
|
||||
if dns.opcode.is_update(self.message.flags):
|
||||
self.updating = True
|
||||
elif what == 'edns':
|
||||
self.message.edns = self.tok.get_int()
|
||||
|
|
@ -830,11 +831,11 @@ class _TextReader(object):
|
|||
self.message.edns = 0
|
||||
while True:
|
||||
token = self.tok.get()
|
||||
if token[0] != linkcheck.dns.tokenizer.IDENTIFIER:
|
||||
if not token.is_identifier():
|
||||
self.tok.unget(token)
|
||||
break
|
||||
self.message.ednsflags = self.message.ednsflags | \
|
||||
linkcheck.dns.flags.edns_from_text(token[1])
|
||||
dns.flags.edns_from_text(token.value)
|
||||
elif what == 'payload':
|
||||
self.message.payload = self.tok.get_int()
|
||||
if self.message.edns < 0:
|
||||
|
|
@ -842,10 +843,10 @@ class _TextReader(object):
|
|||
elif what == 'opcode':
|
||||
text = self.tok.get_string()
|
||||
self.message.flags = self.message.flags | \
|
||||
linkcheck.dns.opcode.to_flags(linkcheck.dns.opcode.from_text(text))
|
||||
dns.opcode.to_flags(dns.opcode.from_text(text))
|
||||
elif what == 'rcode':
|
||||
text = self.tok.get_string()
|
||||
self.message.set_rcode(linkcheck.dns.rcode.from_text(text))
|
||||
self.message.set_rcode(dns.rcode.from_text(text))
|
||||
else:
|
||||
raise UnknownHeaderField
|
||||
self.tok.get_eol()
|
||||
|
|
@ -855,23 +856,23 @@ class _TextReader(object):
|
|||
|
||||
token = self.tok.get(want_leading = True)
|
||||
if not token.is_whitespace():
|
||||
self.last_name = linkcheck.dns.name.from_text(token.value, None)
|
||||
self.last_name = dns.name.from_text(token.value, None)
|
||||
name = self.last_name
|
||||
token = self.tok.get()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
# Class
|
||||
try:
|
||||
rdclass = linkcheck.dns.rdataclass.from_text(token.value)
|
||||
rdclass = dns.rdataclass.from_text(token.value)
|
||||
token = self.tok.get()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
except linkcheck.dns.exception.DNSSyntaxError:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
except dns.exception.SyntaxError:
|
||||
raise dns.exception.SyntaxError
|
||||
except StandardError:
|
||||
rdclass = linkcheck.dns.rdataclass.IN
|
||||
rdclass = dns.rdataclass.IN
|
||||
# Type
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(token.value)
|
||||
rdtype = dns.rdatatype.from_text(token.value)
|
||||
self.message.find_rrset(self.message.question, name,
|
||||
rdclass, rdtype, create=True,
|
||||
force_unique=True)
|
||||
|
|
@ -883,48 +884,49 @@ class _TextReader(object):
|
|||
"""Process one line from the text format answer, authority, or
|
||||
additional data sections.
|
||||
"""
|
||||
|
||||
deleting = None
|
||||
# Name
|
||||
token = self.tok.get(want_leading = True)
|
||||
if not token.is_whitespace():
|
||||
self.last_name = linkcheck.dns.name.from_text(token.value, None)
|
||||
self.last_name = dns.name.from_text(token.value, None)
|
||||
name = self.last_name
|
||||
token = self.tok.get()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
# TTL
|
||||
try:
|
||||
ttl = int(token.value, 0)
|
||||
token = self.tok.get()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
except linkcheck.dns.exception.DNSSyntaxError:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
except dns.exception.SyntaxError:
|
||||
raise dns.exception.SyntaxError
|
||||
except StandardError:
|
||||
ttl = 0
|
||||
# Class
|
||||
try:
|
||||
rdclass = linkcheck.dns.rdataclass.from_text(token.value)
|
||||
rdclass = dns.rdataclass.from_text(token.value)
|
||||
token = self.tok.get()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
if rdclass == linkcheck.dns.rdataclass.ANY or rdclass == linkcheck.dns.rdataclass.NONE:
|
||||
raise dns.exception.SyntaxError
|
||||
if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE:
|
||||
deleting = rdclass
|
||||
rdclass = self.zone_rdclass
|
||||
except linkcheck.dns.exception.DNSSyntaxError:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
except dns.exception.SyntaxError:
|
||||
raise dns.exception.SyntaxError
|
||||
except StandardError:
|
||||
rdclass = linkcheck.dns.rdataclass.IN
|
||||
rdclass = dns.rdataclass.IN
|
||||
# Type
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(token.value)
|
||||
rdtype = dns.rdatatype.from_text(token.value)
|
||||
token = self.tok.get()
|
||||
if not token.is_eol_or_eof():
|
||||
self.tok.unget(token)
|
||||
rd = linkcheck.dns.rdata.from_text(rdclass, rdtype, self.tok, None)
|
||||
rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None)
|
||||
covers = rd.covers()
|
||||
else:
|
||||
rd = None
|
||||
covers = linkcheck.dns.rdatatype.NONE
|
||||
covers = dns.rdatatype.NONE
|
||||
rrset = self.message.find_rrset(section, name,
|
||||
rdclass, rdtype, covers,
|
||||
deleting, True, self.updating)
|
||||
|
|
@ -932,8 +934,9 @@ class _TextReader(object):
|
|||
rrset.add(rd, ttl)
|
||||
|
||||
def read(self):
|
||||
"""Read a text format DNS message and build a linkcheck.dns.message.Message
|
||||
"""Read a text format DNS message and build a dns.message.Message
|
||||
object."""
|
||||
|
||||
line_method = self._header_line
|
||||
section = None
|
||||
while 1:
|
||||
|
|
@ -968,8 +971,8 @@ def from_text(text):
|
|||
@param text: The text format message.
|
||||
@type text: string
|
||||
@raises UnknownHeaderField:
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@rtype: linkcheck.dns.message.Message object"""
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: dns.message.Message object"""
|
||||
|
||||
# 'text' can also be a file, but we don't publish that fact
|
||||
# since it's an implementation detail. The official file
|
||||
|
|
@ -982,19 +985,22 @@ def from_text(text):
|
|||
|
||||
return m
|
||||
|
||||
|
||||
def from_file(f):
|
||||
"""Read the next text format message from the specified file.
|
||||
|
||||
@param f: file or string. If I{f} is a string, it is treated
|
||||
as the name of a file to open.
|
||||
@raises UnknownHeaderField:
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@rtype: linkcheck.dns.message.Message object"""
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: dns.message.Message object"""
|
||||
|
||||
# allow Unicode filenames; turn on universal newline support
|
||||
str_type = basestring
|
||||
opts = 'rU'
|
||||
if sys.hexversion >= 0x02030000:
|
||||
# allow Unicode filenames; turn on universal newline support
|
||||
str_type = basestring
|
||||
opts = 'rU'
|
||||
else:
|
||||
str_type = str
|
||||
opts = 'r'
|
||||
if isinstance(f, str_type):
|
||||
f = file(f, opts)
|
||||
want_close = True
|
||||
|
|
@ -1008,46 +1014,44 @@ def from_file(f):
|
|||
f.close()
|
||||
return m
|
||||
|
||||
|
||||
def make_query(qname, rdtype, rdclass = linkcheck.dns.rdataclass.IN,
|
||||
use_edns=None, want_dnssec=False):
|
||||
def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns=None,
|
||||
want_dnssec=False):
|
||||
"""Make a query message.
|
||||
|
||||
The query name, type, and class may all be specified either
|
||||
as objects of the appropriate type, or as strings.
|
||||
|
||||
The query will have a randomly choosen query id, and its DNS flags
|
||||
will be set to linkcheck.dns.flags.RD.
|
||||
will be set to dns.flags.RD.
|
||||
|
||||
@param qname: The query name.
|
||||
@type qname: linkcheck.dns.name.Name object or string
|
||||
@type qname: dns.name.Name object or string
|
||||
@param rdtype: The desired rdata type.
|
||||
@type rdtype: int
|
||||
@param rdclass: The desired rdata class; the default is class IN.
|
||||
@type rdclass: int
|
||||
@param use_edns: The EDNS level to use; the default is None (no EDNS).
|
||||
See the description of linkcheck.dns.message.Message.use_edns() for the possible
|
||||
See the description of dns.message.Message.use_edns() for the possible
|
||||
values for use_edns and their meanings.
|
||||
@type use_edns: int or bool or None
|
||||
@param want_dnssec: Should the query indicate that DNSSEC is desired?
|
||||
@type want_dnssec: bool
|
||||
@rtype: linkcheck.dns.message.Message object"""
|
||||
@rtype: dns.message.Message object"""
|
||||
|
||||
if isinstance(qname, basestring):
|
||||
qname = linkcheck.dns.name.from_text(qname)
|
||||
if isinstance(rdtype, basestring):
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(rdtype)
|
||||
if isinstance(rdclass, basestring):
|
||||
rdclass = linkcheck.dns.rdataclass.from_text(rdclass)
|
||||
if isinstance(qname, (str, unicode)):
|
||||
qname = dns.name.from_text(qname)
|
||||
if isinstance(rdtype, (str, unicode)):
|
||||
rdtype = dns.rdatatype.from_text(rdtype)
|
||||
if isinstance(rdclass, (str, unicode)):
|
||||
rdclass = dns.rdataclass.from_text(rdclass)
|
||||
m = Message()
|
||||
m.flags |= linkcheck.dns.flags.RD
|
||||
m.flags |= dns.flags.RD
|
||||
m.find_rrset(m.question, qname, rdclass, rdtype, create=True,
|
||||
force_unique=True)
|
||||
m.use_edns(use_edns)
|
||||
m.want_dnssec(want_dnssec)
|
||||
return m
|
||||
|
||||
|
||||
def make_response(query, recursion_available=False, our_payload=8192):
|
||||
"""Make a message which is a response for the specified query.
|
||||
The message returned is really a response skeleton; it has all
|
||||
|
|
@ -1059,20 +1063,20 @@ def make_response(query, recursion_available=False, our_payload=8192):
|
|||
changed.
|
||||
|
||||
@param query: the query to respond to
|
||||
@type query: linkcheck.dns.message.Message object
|
||||
@type query: dns.message.Message object
|
||||
@param recursion_available: should RA be set in the response?
|
||||
@type recursion_available: bool
|
||||
@param our_payload: payload size to advertise in EDNS responses; default
|
||||
is 8192.
|
||||
@type our_payload: int
|
||||
@rtype: linkcheck.dns.message.Message object"""
|
||||
@rtype: dns.message.Message object"""
|
||||
|
||||
if query.flags & linkcheck.dns.flags.QR:
|
||||
raise linkcheck.dns.exception.FormError('specified query message is not a query')
|
||||
response = linkcheck.dns.message.Message(query.id)
|
||||
response.flags = linkcheck.dns.flags.QR | (query.flags & linkcheck.dns.flags.RD)
|
||||
if query.flags & dns.flags.QR:
|
||||
raise dns.exception.FormError('specified query message is not a query')
|
||||
response = dns.message.Message(query.id)
|
||||
response.flags = dns.flags.QR | (query.flags & dns.flags.RD)
|
||||
if recursion_available:
|
||||
response.flags |= linkcheck.dns.flags.RA
|
||||
response.flags |= dns.flags.RA
|
||||
response.set_opcode(query.opcode())
|
||||
response.question = list(query.question)
|
||||
if query.edns >= 0:
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -17,17 +16,20 @@
|
|||
"""DNS Names.
|
||||
|
||||
@var root: The DNS root name.
|
||||
@type root: linkcheck.dns.name.Name object
|
||||
@type root: dns.name.Name object
|
||||
@var empty: The empty DNS name.
|
||||
@type empty: linkcheck.dns.name.Name object
|
||||
@type empty: dns.name.Name object
|
||||
"""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import struct
|
||||
import sys
|
||||
|
||||
import encodings.idna
|
||||
import linkcheck.dns.exception
|
||||
if sys.hexversion >= 0x02030000:
|
||||
import encodings.idna
|
||||
|
||||
import dns.exception
|
||||
import dns.wiredata
|
||||
|
||||
NAMERELN_NONE = 0
|
||||
NAMERELN_SUPERDOMAIN = 1
|
||||
|
|
@ -35,41 +37,41 @@ NAMERELN_SUBDOMAIN = 2
|
|||
NAMERELN_EQUAL = 3
|
||||
NAMERELN_COMMONANCESTOR = 4
|
||||
|
||||
class EmptyLabel(linkcheck.dns.exception.DNSSyntaxError):
|
||||
class EmptyLabel(dns.exception.SyntaxError):
|
||||
"""Raised if a label is empty."""
|
||||
pass
|
||||
|
||||
class BadEscape(linkcheck.dns.exception.DNSSyntaxError):
|
||||
class BadEscape(dns.exception.SyntaxError):
|
||||
"""Raised if an escaped code in a text format name is invalid."""
|
||||
pass
|
||||
|
||||
class BadPointer(linkcheck.dns.exception.FormError):
|
||||
class BadPointer(dns.exception.FormError):
|
||||
"""Raised if a compression pointer points forward instead of backward."""
|
||||
pass
|
||||
|
||||
class BadLabelType(linkcheck.dns.exception.FormError):
|
||||
class BadLabelType(dns.exception.FormError):
|
||||
"""Raised if the label type of a wire format name is unknown."""
|
||||
pass
|
||||
|
||||
class NeedAbsoluteNameOrOrigin(linkcheck.dns.exception.DNSException):
|
||||
class NeedAbsoluteNameOrOrigin(dns.exception.DNSException):
|
||||
"""Raised if an attempt is made to convert a non-absolute name to
|
||||
wire when there is also a non-absolute (or missing) origin."""
|
||||
pass
|
||||
|
||||
class NameTooLong(linkcheck.dns.exception.FormError):
|
||||
class NameTooLong(dns.exception.FormError):
|
||||
"""Raised if a name is > 255 octets long."""
|
||||
pass
|
||||
|
||||
class LabelTooLong(linkcheck.dns.exception.DNSSyntaxError):
|
||||
class LabelTooLong(dns.exception.SyntaxError):
|
||||
"""Raised if a label is > 63 octets long."""
|
||||
pass
|
||||
|
||||
class AbsoluteConcatenation(linkcheck.dns.exception.DNSException):
|
||||
class AbsoluteConcatenation(dns.exception.DNSException):
|
||||
"""Raised if an attempt is made to append anything other than the
|
||||
empty name to an absolute name."""
|
||||
pass
|
||||
|
||||
class NoParent(linkcheck.dns.exception.DNSException):
|
||||
class NoParent(dns.exception.DNSException):
|
||||
"""Raised if an attempt is made to get the parent of the root name
|
||||
or the empty name."""
|
||||
pass
|
||||
|
|
@ -127,7 +129,7 @@ def _validate_labels(labels):
|
|||
class Name(object):
|
||||
"""A DNS name.
|
||||
|
||||
The linkcheck.dns.name.Name class represents a DNS name as a tuple of labels.
|
||||
The dns.name.Name class represents a DNS name as a tuple of labels.
|
||||
Instances of the class are immutable.
|
||||
|
||||
@ivar labels: The tuple of labels in the name. Each label is a string of
|
||||
|
|
@ -176,9 +178,9 @@ class Name(object):
|
|||
"""Compare two names, returning a 3-tuple (relation, order, nlabels).
|
||||
|
||||
I{relation} describes the relation ship beween the names,
|
||||
and is one of: linkcheck.dns.name.NAMERELN_NONE,
|
||||
linkcheck.dns.name.NAMERELN_SUPERDOMAIN, linkcheck.dns.name.NAMERELN_SUBDOMAIN,
|
||||
linkcheck.dns.name.NAMERELN_EQUAL, or linkcheck.dns.name.NAMERELN_COMMONANCESTOR
|
||||
and is one of: dns.name.NAMERELN_NONE,
|
||||
dns.name.NAMERELN_SUPERDOMAIN, dns.name.NAMERELN_SUBDOMAIN,
|
||||
dns.name.NAMERELN_EQUAL, or dns.name.NAMERELN_COMMONANCESTOR
|
||||
|
||||
I{order} is < 0 if self < other, > 0 if self > other, and ==
|
||||
0 if self == other. A relative name is always less than an
|
||||
|
|
@ -260,7 +262,7 @@ class Name(object):
|
|||
def canonicalize(self):
|
||||
"""Return a name which is equal to the current name, but is in
|
||||
DNSSEC canonical form.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
|
||||
return Name([x.lower() for x in self.labels])
|
||||
|
|
@ -353,7 +355,7 @@ class Name(object):
|
|||
|
||||
@param origin: If the name is relative and origin is not None, then
|
||||
origin will be appended to it.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@raises NeedAbsoluteNameOrOrigin: All names in wire format are
|
||||
absolute. If self is a relative name, then an origin must be supplied;
|
||||
if it is missing, then this exception is raised
|
||||
|
|
@ -373,8 +375,8 @@ class Name(object):
|
|||
def to_wire(self, file = None, compress = None, origin = None):
|
||||
"""Convert name to wire format, possibly compressing it.
|
||||
|
||||
@param file: the file where the compressed name is emitted (typically
|
||||
a cStringIO file) If None, a string containing the wire name
|
||||
@param file: the file where the name is emitted (typically
|
||||
a cStringIO file). If None, a string containing the wire name
|
||||
will be returned.
|
||||
@type file: file or None
|
||||
@param compress: The compression table. If None (the default) names
|
||||
|
|
@ -382,14 +384,14 @@ class Name(object):
|
|||
@type compress: dict
|
||||
@param origin: If the name is relative and origin is not None, then
|
||||
origin will be appended to it.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@raises NeedAbsoluteNameOrOrigin: All names in wire format are
|
||||
absolute. If self is a relative name, then an origin must be supplied;
|
||||
if it is missing, then this exception is raised
|
||||
"""
|
||||
|
||||
if file is None:
|
||||
file = StringIO()
|
||||
file = cStringIO.StringIO()
|
||||
want_return = True
|
||||
else:
|
||||
want_return = False
|
||||
|
|
@ -458,16 +460,16 @@ class Name(object):
|
|||
|
||||
l = len(self.labels)
|
||||
if depth == 0:
|
||||
return (self, linkcheck.dns.name.empty)
|
||||
return (self, dns.name.empty)
|
||||
elif depth == l:
|
||||
return (linkcheck.dns.name.empty, self)
|
||||
return (dns.name.empty, self)
|
||||
elif depth < 0 or depth > l:
|
||||
raise ValueError('depth must be >= 0 and <= the length of the name')
|
||||
return (Name(self[: -depth]), Name(self[-depth :]))
|
||||
|
||||
def concatenate(self, other):
|
||||
"""Return a new name which is the concatenation of self and other.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
@raises AbsoluteConcatenation: self is absolute and other is
|
||||
not the empty name
|
||||
"""
|
||||
|
|
@ -481,7 +483,7 @@ class Name(object):
|
|||
def relativize(self, origin):
|
||||
"""If self is a subdomain of origin, return a new name which is self
|
||||
relative to origin. Otherwise return self.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
|
||||
if not origin is None and self.is_subdomain(origin):
|
||||
|
|
@ -492,7 +494,7 @@ class Name(object):
|
|||
def derelativize(self, origin):
|
||||
"""If self is a relative name, return a new name which is the
|
||||
concatenation of self and origin. Otherwise return self.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
|
||||
if not self.is_absolute():
|
||||
|
|
@ -505,8 +507,9 @@ class Name(object):
|
|||
origin is None, then self is returned. Otherwise, if
|
||||
relativize is true the name is relativized, and if relativize is
|
||||
false the name is derelativized.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
|
||||
if origin:
|
||||
if relativize:
|
||||
return self.relativize(origin)
|
||||
|
|
@ -517,8 +520,8 @@ class Name(object):
|
|||
|
||||
def parent(self):
|
||||
"""Return the parent of the name.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@raises NoParent: the name is either the root name or the enpty name
|
||||
@rtype: dns.name.Name object
|
||||
@raises NoParent: the name is either the root name or the empty name,
|
||||
and thus has no parent.
|
||||
"""
|
||||
if self == root or self == empty:
|
||||
|
|
@ -533,7 +536,7 @@ def from_unicode(text, origin = root):
|
|||
|
||||
Lables are encoded in IDN ACE form.
|
||||
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
|
||||
if not isinstance(text, unicode):
|
||||
|
|
@ -549,7 +552,7 @@ def from_unicode(text, origin = root):
|
|||
text = u''
|
||||
if text:
|
||||
if text == u'.':
|
||||
return Name(['']) # no Unicode "u" on this constant!
|
||||
return Name(['']) # no Unicode "u" on this constant!
|
||||
for c in text:
|
||||
if escaping:
|
||||
if edigits == 0:
|
||||
|
|
@ -592,11 +595,11 @@ def from_unicode(text, origin = root):
|
|||
|
||||
def from_text(text, origin = root):
|
||||
"""Convert text into a Name object.
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
|
||||
if not isinstance(text, str):
|
||||
if isinstance(text, unicode):
|
||||
if isinstance(text, unicode) and sys.hexversion >= 0x02030000:
|
||||
return from_unicode(text, origin)
|
||||
else:
|
||||
raise ValueError("input to from_text() must be a string")
|
||||
|
|
@ -658,16 +661,17 @@ def from_wire(message, current):
|
|||
@param current: the offset of the beginning of the name from the start
|
||||
of the message
|
||||
@type current: int
|
||||
@raises linkcheck.dns.name.BadPointer: a compression pointer did not point backwards
|
||||
@raises dns.name.BadPointer: a compression pointer did not point backwards
|
||||
in the message
|
||||
@raises linkcheck.dns.name.BadLabelType: an invalid label type was encountered.
|
||||
@raises dns.name.BadLabelType: an invalid label type was encountered.
|
||||
@returns: a tuple consisting of the name that was read and the number
|
||||
of bytes of the wire format message which were consumed reading it
|
||||
@rtype: (linkcheck.dns.name.Name object, int) tuple
|
||||
@rtype: (dns.name.Name object, int) tuple
|
||||
"""
|
||||
|
||||
if not isinstance(message, str):
|
||||
raise ValueError("input to from_wire() must be a byte string")
|
||||
message = dns.wiredata.maybe_wrap(message)
|
||||
labels = []
|
||||
biggest_pointer = current
|
||||
hops = 0
|
||||
|
|
@ -676,7 +680,7 @@ def from_wire(message, current):
|
|||
cused = 1
|
||||
while count != 0:
|
||||
if count < 64:
|
||||
labels.append(message[current : current + count])
|
||||
labels.append(message[current : current + count].unwrap())
|
||||
current += count
|
||||
if hops == 0:
|
||||
cused += count
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,11 +15,11 @@
|
|||
|
||||
"""DNS name dictionary"""
|
||||
|
||||
import linkcheck.dns.name
|
||||
import dns.name
|
||||
|
||||
class NameDict(dict):
|
||||
|
||||
"""A dictionary whose keys are linkcheck.dns.name.Name objects.
|
||||
"""A dictionary whose keys are dns.name.Name objects.
|
||||
@ivar max_depth: the maximum depth of the keys that have ever been
|
||||
added to the dictionary.
|
||||
@type max_depth: int
|
||||
|
|
@ -31,7 +30,7 @@ class NameDict(dict):
|
|||
self.max_depth = 0
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if not isinstance(key, linkcheck.dns.name.Name):
|
||||
if not isinstance(key, dns.name.Name):
|
||||
raise ValueError('NameDict key must be a name')
|
||||
depth = len(key)
|
||||
if depth > self.max_depth:
|
||||
|
|
@ -45,7 +44,7 @@ class NameDict(dict):
|
|||
a superdomain of I{name}.
|
||||
|
||||
@param name: the name
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@rtype: (key, value) tuple
|
||||
"""
|
||||
|
||||
|
|
@ -53,8 +52,8 @@ class NameDict(dict):
|
|||
if depth > self.max_depth:
|
||||
depth = self.max_depth
|
||||
for i in xrange(-depth, 0):
|
||||
n = linkcheck.dns.name.Name(name[i:])
|
||||
n = dns.name.Name(name[i:])
|
||||
if n in self:
|
||||
return (n, self[n])
|
||||
v = self[linkcheck.dns.name.empty]
|
||||
return (linkcheck.dns.name.empty, v)
|
||||
v = self[dns.name.empty]
|
||||
return (dns.name.empty, v)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,11 +15,11 @@
|
|||
|
||||
"""DNS nodes. A node is a set of rdatasets."""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import StringIO
|
||||
|
||||
import linkcheck.dns.rdataset
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.renderer
|
||||
import dns.rdataset
|
||||
import dns.rdatatype
|
||||
import dns.renderer
|
||||
|
||||
class Node(object):
|
||||
"""A DNS node.
|
||||
|
|
@ -28,7 +27,7 @@ class Node(object):
|
|||
A node is a set of rdatasets
|
||||
|
||||
@ivar rdatasets: the node's rdatasets
|
||||
@type rdatasets: list of linkcheck.dns.rdataset.Rdataset objects"""
|
||||
@type rdatasets: list of dns.rdataset.Rdataset objects"""
|
||||
|
||||
__slots__ = ['rdatasets']
|
||||
|
||||
|
|
@ -44,11 +43,11 @@ class Node(object):
|
|||
Each rdataset at the node is printed. Any keyword arguments
|
||||
to this method are passed on to the rdataset's to_text() method.
|
||||
@param name: the owner name of the rdatasets
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
s = StringIO()
|
||||
s = StringIO.StringIO()
|
||||
for rds in self.rdatasets:
|
||||
print >> s, rds.to_text(name, **kw)
|
||||
return s.getvalue()[:-1]
|
||||
|
|
@ -81,7 +80,7 @@ class Node(object):
|
|||
def __iter__(self):
|
||||
return iter(self.rdatasets)
|
||||
|
||||
def find_rdataset(self, rdclass, rdtype, covers=linkcheck.dns.rdatatype.NONE,
|
||||
def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE,
|
||||
create=False):
|
||||
"""Find an rdataset matching the specified properties in the
|
||||
current node.
|
||||
|
|
@ -91,8 +90,8 @@ class Node(object):
|
|||
@param rdtype: The type of the rdataset
|
||||
@type rdtype: int
|
||||
@param covers: The covered type. Usually this value is
|
||||
linkcheck.dns.rdatatype.NONE, but if the rdtype is linkcheck.dns.rdatatype.SIG or
|
||||
linkcheck.dns.rdatatype.RRSIG, then the covers value will be the rdata
|
||||
dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
|
||||
dns.rdatatype.RRSIG, then the covers value will be the rdata
|
||||
type the SIG/RRSIG covers. The library treats the SIG and RRSIG
|
||||
types as if they were a family of
|
||||
types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
|
||||
|
|
@ -103,7 +102,7 @@ class Node(object):
|
|||
@type create: bool
|
||||
@raises KeyError: An rdataset of the desired type and class does
|
||||
not exist and I{create} is not True.
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object
|
||||
@rtype: dns.rdataset.Rdataset object
|
||||
"""
|
||||
|
||||
for rds in self.rdatasets:
|
||||
|
|
@ -111,11 +110,11 @@ class Node(object):
|
|||
return rds
|
||||
if not create:
|
||||
raise KeyError
|
||||
rds = linkcheck.dns.rdataset.Rdataset(rdclass, rdtype)
|
||||
rds = dns.rdataset.Rdataset(rdclass, rdtype)
|
||||
self.rdatasets.append(rds)
|
||||
return rds
|
||||
|
||||
def get_rdataset(self, rdclass, rdtype, covers=linkcheck.dns.rdatatype.NONE,
|
||||
def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE,
|
||||
create=False):
|
||||
"""Get an rdataset matching the specified properties in the
|
||||
current node.
|
||||
|
|
@ -131,7 +130,7 @@ class Node(object):
|
|||
@type covers: int
|
||||
@param create: If True, create the rdataset if it is not found.
|
||||
@type create: bool
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object or None
|
||||
@rtype: dns.rdataset.Rdataset object or None
|
||||
"""
|
||||
|
||||
try:
|
||||
|
|
@ -140,7 +139,7 @@ class Node(object):
|
|||
rds = None
|
||||
return rds
|
||||
|
||||
def delete_rdataset(self, rdclass, rdtype, covers=linkcheck.dns.rdatatype.NONE):
|
||||
def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
|
||||
"""Delete the rdataset matching the specified properties in the
|
||||
current node.
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,7 +15,7 @@
|
|||
|
||||
"""DNS Opcodes."""
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import dns.exception
|
||||
|
||||
QUERY = 0
|
||||
IQUERY = 1
|
||||
|
|
@ -39,7 +38,7 @@ _by_text = {
|
|||
_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
|
||||
|
||||
|
||||
class UnknownOpcode(linkcheck.dns.exception.DNSException):
|
||||
class UnknownOpcode(dns.exception.DNSException):
|
||||
"""Raised if an opcode is unknown."""
|
||||
pass
|
||||
|
||||
|
|
@ -67,7 +66,7 @@ def from_flags(flags):
|
|||
@param flags: int
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
|
||||
return (flags & 0x7800) >> 11
|
||||
|
||||
def to_flags(value):
|
||||
|
|
@ -75,9 +74,9 @@ def to_flags(value):
|
|||
flags.
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
|
||||
return (value << 11) & 0x7800
|
||||
|
||||
|
||||
def to_text(value):
|
||||
"""Convert an opcode to text.
|
||||
|
||||
|
|
@ -86,7 +85,7 @@ def to_text(value):
|
|||
@raises UnknownOpcode: the opcode is unknown
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
|
||||
text = _by_value.get(value)
|
||||
if text is None:
|
||||
text = str(value)
|
||||
|
|
@ -99,7 +98,7 @@ def is_update(flags):
|
|||
@type flags: int
|
||||
@rtype: bool
|
||||
"""
|
||||
|
||||
|
||||
if (from_flags(flags) == UPDATE):
|
||||
return True
|
||||
return False
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,6 +15,8 @@
|
|||
|
||||
"""Talk to a DNS server."""
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
import errno
|
||||
import select
|
||||
import socket
|
||||
|
|
@ -23,30 +24,80 @@ import struct
|
|||
import sys
|
||||
import time
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.inet
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.message
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.exception
|
||||
import dns.inet
|
||||
import dns.name
|
||||
import dns.message
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
|
||||
class UnexpectedSource(linkcheck.dns.exception.DNSException):
|
||||
class UnexpectedSource(dns.exception.DNSException):
|
||||
"""Raised if a query response comes from an unexpected address or port."""
|
||||
pass
|
||||
|
||||
class BadResponse(linkcheck.dns.exception.FormError):
|
||||
class BadResponse(dns.exception.FormError):
|
||||
"""Raised if a query response does not respond to the question asked."""
|
||||
pass
|
||||
|
||||
|
||||
def _compute_expiration(timeout):
|
||||
if timeout is None:
|
||||
return None
|
||||
else:
|
||||
return time.time() + timeout
|
||||
|
||||
def _poll_for(fd, readable, writable, error, timeout):
|
||||
"""
|
||||
@param fd: File descriptor (int).
|
||||
@param readable: Whether to wait for readability (bool).
|
||||
@param writable: Whether to wait for writability (bool).
|
||||
@param expiration: Deadline timeout (expiration time, in seconds (float)).
|
||||
|
||||
def _wait_for(ir, iw, ix, expiration):
|
||||
@return True on success, False on timeout
|
||||
"""
|
||||
event_mask = 0
|
||||
if readable:
|
||||
event_mask |= select.POLLIN
|
||||
if writable:
|
||||
event_mask |= select.POLLOUT
|
||||
if error:
|
||||
event_mask |= select.POLLERR
|
||||
|
||||
pollable = select.poll()
|
||||
pollable.register(fd, event_mask)
|
||||
|
||||
if timeout:
|
||||
event_list = pollable.poll(long(timeout * 1000))
|
||||
else:
|
||||
event_list = pollable.poll()
|
||||
|
||||
return bool(event_list)
|
||||
|
||||
def _select_for(fd, readable, writable, error, timeout):
|
||||
"""
|
||||
@param fd: File descriptor (int).
|
||||
@param readable: Whether to wait for readability (bool).
|
||||
@param writable: Whether to wait for writability (bool).
|
||||
@param expiration: Deadline timeout (expiration time, in seconds (float)).
|
||||
|
||||
@return True on success, False on timeout
|
||||
"""
|
||||
rset, wset, xset = [], [], []
|
||||
|
||||
if readable:
|
||||
rset = [fd]
|
||||
if writable:
|
||||
wset = [fd]
|
||||
if error:
|
||||
xset = [fd]
|
||||
|
||||
if timeout is None:
|
||||
(rcount, wcount, xcount) = select.select(rset, wset, xset)
|
||||
else:
|
||||
(rcount, wcount, xcount) = select.select(rset, wset, xset, timeout)
|
||||
|
||||
return bool((rcount or wcount or xcount))
|
||||
|
||||
def _wait_for(fd, readable, writable, error, expiration):
|
||||
done = False
|
||||
while not done:
|
||||
if expiration is None:
|
||||
|
|
@ -54,32 +105,43 @@ def _wait_for(ir, iw, ix, expiration):
|
|||
else:
|
||||
timeout = expiration - time.time()
|
||||
if timeout <= 0.0:
|
||||
raise linkcheck.dns.exception.Timeout
|
||||
raise dns.exception.Timeout
|
||||
try:
|
||||
if timeout is None:
|
||||
(r, w, x) = select.select(ir, iw, ix)
|
||||
else:
|
||||
(r, w, x) = select.select(ir, iw, ix, timeout)
|
||||
if not _polling_backend(fd, readable, writable, error, timeout):
|
||||
raise dns.exception.Timeout
|
||||
except select.error, e:
|
||||
if e.args[0] != errno.EINTR:
|
||||
raise e
|
||||
done = True
|
||||
if len(r) == 0 and len(w) == 0 and len(x) == 0:
|
||||
raise linkcheck.dns.exception.Timeout
|
||||
|
||||
def _set_polling_backend(fn):
|
||||
"""
|
||||
Internal API. Do not use.
|
||||
"""
|
||||
global _polling_backend
|
||||
|
||||
_polling_backend = fn
|
||||
|
||||
if hasattr(select, 'poll'):
|
||||
# Prefer poll() on platforms that support it because it has no
|
||||
# limits on the maximum value of a file descriptor (plus it will
|
||||
# be more efficient for high values).
|
||||
_polling_backend = _poll_for
|
||||
else:
|
||||
_polling_backend = _select_for
|
||||
|
||||
def _wait_for_readable(s, expiration):
|
||||
_wait_for([s], [], [s], expiration)
|
||||
|
||||
_wait_for(s, True, False, True, expiration)
|
||||
|
||||
def _wait_for_writable(s, expiration):
|
||||
_wait_for([], [s], [s], expiration)
|
||||
_wait_for(s, False, True, True, expiration)
|
||||
|
||||
def _addresses_equal(af, a1, a2):
|
||||
# Convert the first value of the tuple, which is a textual format
|
||||
# address into binary form, so that we are not confused by different
|
||||
# textual representations of the same address
|
||||
n1 = linkcheck.dns.inet.inet_pton(af, a1[0])
|
||||
n2 = linkcheck.dns.inet.inet_pton(af, a2[0])
|
||||
n1 = dns.inet.inet_pton(af, a1[0])
|
||||
n2 = dns.inet.inet_pton(af, a2[0])
|
||||
return n1 == n2 and a1[1:] == a2[1:]
|
||||
|
||||
def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
||||
|
|
@ -87,7 +149,7 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
"""Return the response obtained after sending a query via UDP.
|
||||
|
||||
@param q: the query
|
||||
@type q: linkcheck.dns.message.Message
|
||||
@type q: dns.message.Message
|
||||
@param where: where to send the message
|
||||
@type where: string containing an IPv4 or IPv6 address
|
||||
@param timeout: The number of seconds to wait before the query times out.
|
||||
|
|
@ -99,7 +161,7 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
causes the address family to use to be inferred from the form of of where.
|
||||
If the inference attempt fails, AF_INET is used.
|
||||
@type af: int
|
||||
@rtype: linkcheck.dns.message.Message object
|
||||
@rtype: dns.message.Message object
|
||||
@param source: source address. The default is the IPv4 wildcard address.
|
||||
@type source: string
|
||||
@param source_port: The port from which to send the message.
|
||||
|
|
@ -115,14 +177,14 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
wire = q.to_wire()
|
||||
if af is None:
|
||||
try:
|
||||
af = linkcheck.dns.inet.af_for_address(where)
|
||||
af = dns.inet.af_for_address(where)
|
||||
except StandardError:
|
||||
af = linkcheck.dns.inet.AF_INET
|
||||
if af == linkcheck.dns.inet.AF_INET:
|
||||
af = dns.inet.AF_INET
|
||||
if af == dns.inet.AF_INET:
|
||||
destination = (where, port)
|
||||
if source is not None:
|
||||
source = (source, source_port)
|
||||
elif af == linkcheck.dns.inet.AF_INET6:
|
||||
elif af == dns.inet.AF_INET6:
|
||||
destination = (where, port, 0, 0)
|
||||
if source is not None:
|
||||
source = (source, source_port, 0, 0)
|
||||
|
|
@ -138,8 +200,8 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
_wait_for_readable(s, expiration)
|
||||
(wire, from_address) = s.recvfrom(65535)
|
||||
if _addresses_equal(af, from_address, destination) or \
|
||||
(linkcheck.dns.inet.is_multicast(where) and \
|
||||
from_address[1:] == destination[1:]):
|
||||
(dns.inet.is_multicast(where) and \
|
||||
from_address[1:] == destination[1:]):
|
||||
break
|
||||
if not ignore_unexpected:
|
||||
raise UnexpectedSource('got a response from '
|
||||
|
|
@ -147,7 +209,7 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
destination))
|
||||
finally:
|
||||
s.close()
|
||||
r = linkcheck.dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
|
||||
r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
|
||||
one_rr_per_rrset=one_rr_per_rrset)
|
||||
if not q.is_response(r):
|
||||
raise BadResponse
|
||||
|
|
@ -165,8 +227,8 @@ def _net_read(sock, count, expiration):
|
|||
n = sock.recv(count)
|
||||
if n == '':
|
||||
raise EOFError
|
||||
count -= len(n)
|
||||
s += n
|
||||
count = count - len(n)
|
||||
s = s + n
|
||||
return s
|
||||
|
||||
def _net_write(sock, data, expiration):
|
||||
|
|
@ -195,7 +257,7 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
"""Return the response obtained after sending a query via TCP.
|
||||
|
||||
@param q: the query
|
||||
@type q: linkcheck.dns.message.Message object
|
||||
@type q: dns.message.Message object
|
||||
@param where: where to send the message
|
||||
@type where: string containing an IPv4 or IPv6 address
|
||||
@param timeout: The number of seconds to wait before the query times out.
|
||||
|
|
@ -207,7 +269,7 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
causes the address family to use to be inferred from the form of of where.
|
||||
If the inference attempt fails, AF_INET is used.
|
||||
@type af: int
|
||||
@rtype: linkcheck.dns.message.Message object
|
||||
@rtype: dns.message.Message object
|
||||
@param source: source address. The default is the IPv4 wildcard address.
|
||||
@type source: string
|
||||
@param source_port: The port from which to send the message.
|
||||
|
|
@ -220,14 +282,14 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
wire = q.to_wire()
|
||||
if af is None:
|
||||
try:
|
||||
af = linkcheck.dns.inet.af_for_address(where)
|
||||
af = dns.inet.af_for_address(where)
|
||||
except StandardError:
|
||||
af = linkcheck.dns.inet.AF_INET
|
||||
if af == linkcheck.dns.inet.AF_INET:
|
||||
af = dns.inet.AF_INET
|
||||
if af == dns.inet.AF_INET:
|
||||
destination = (where, port)
|
||||
if source is not None:
|
||||
source = (source, source_port)
|
||||
elif af == linkcheck.dns.inet.AF_INET6:
|
||||
elif af == dns.inet.AF_INET6:
|
||||
destination = (where, port, 0, 0)
|
||||
if source is not None:
|
||||
source = (source, source_port, 0, 0)
|
||||
|
|
@ -251,28 +313,27 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
|
|||
wire = _net_read(s, l, expiration)
|
||||
finally:
|
||||
s.close()
|
||||
r = linkcheck.dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
|
||||
r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
|
||||
one_rr_per_rrset=one_rr_per_rrset)
|
||||
if not q.is_response(r):
|
||||
raise BadResponse
|
||||
return r
|
||||
|
||||
def xfr (where, zone, rdtype=linkcheck.dns.rdatatype.AXFR,
|
||||
rdclass=linkcheck.dns.rdataclass.IN,
|
||||
timeout=None, port=53, keyring=None, keyname=None, relativize=True,
|
||||
af=None, lifetime=None, source=None, source_port=0, serial=0,
|
||||
use_udp=False, keyalgorithm=linkcheck.dns.tsig.default_algorithm):
|
||||
def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
|
||||
timeout=None, port=53, keyring=None, keyname=None, relativize=True,
|
||||
af=None, lifetime=None, source=None, source_port=0, serial=0,
|
||||
use_udp=False, keyalgorithm=dns.tsig.default_algorithm):
|
||||
"""Return a generator for the responses to a zone transfer.
|
||||
|
||||
@param where: where to send the message
|
||||
@type where: string containing an IPv4 or IPv6 address
|
||||
@param zone: The name of the zone to transfer
|
||||
@type zone: linkcheck.dns.name.Name object or string
|
||||
@type zone: dns.name.Name object or string
|
||||
@param rdtype: The type of zone transfer. The default is
|
||||
linkcheck.dns.rdatatype.AXFR.
|
||||
dns.rdatatype.AXFR.
|
||||
@type rdtype: int or string
|
||||
@param rdclass: The class of the zone transfer. The default is
|
||||
linkcheck.dns.rdatatype.IN.
|
||||
dns.rdatatype.IN.
|
||||
@type rdclass: int or string
|
||||
@param timeout: The number of seconds to wait for each response message.
|
||||
If None, the default, wait forever.
|
||||
|
|
@ -282,10 +343,10 @@ def xfr (where, zone, rdtype=linkcheck.dns.rdatatype.AXFR,
|
|||
@param keyring: The TSIG keyring to use
|
||||
@type keyring: dict
|
||||
@param keyname: The name of the TSIG key to use
|
||||
@type keyname: linkcheck.dns.name.Name object or string
|
||||
@type keyname: dns.name.Name object or string
|
||||
@param relativize: If True, all names in the zone will be relativized to
|
||||
the zone origin. It is essential that the relativize setting matches
|
||||
the one specified to linkcheck.dns.zone.from_xfr().
|
||||
the zone origin. It is essential that the relativize setting matches
|
||||
the one specified to dns.zone.from_xfr().
|
||||
@type relativize: bool
|
||||
@param af: the address family to use. The default is None, which
|
||||
causes the address family to use to be inferred from the form of of where.
|
||||
|
|
@ -295,49 +356,49 @@ def xfr (where, zone, rdtype=linkcheck.dns.rdatatype.AXFR,
|
|||
If None, the default, then there is no limit on the time the transfer may
|
||||
take.
|
||||
@type lifetime: float
|
||||
@rtype: generator of linkcheck.dns.message.Message objects.
|
||||
@rtype: generator of dns.message.Message objects.
|
||||
@param source: source address. The default is the IPv4 wildcard address.
|
||||
@type source: string
|
||||
@param source_port: The port from which to send the message.
|
||||
The default is 0.
|
||||
@type source_port: int
|
||||
@param serial: The SOA serial number to use as the base for an IXFR diff
|
||||
sequence (only meaningful if rdtype == linkcheck.dns.rdatatype.IXFR).
|
||||
sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
|
||||
@type serial: int
|
||||
@param use_udp: Use UDP (only meaningful for IXFR)
|
||||
@type use_udp: bool
|
||||
@param keyalgorithm: The TSIG algorithm to use; defaults to
|
||||
linkcheck.dns.tsig.default_algorithm
|
||||
dns.tsig.default_algorithm
|
||||
@type keyalgorithm: string
|
||||
"""
|
||||
|
||||
if isinstance(zone, basestring):
|
||||
zone = linkcheck.dns.name.from_text(zone)
|
||||
if isinstance(rdtype, basestring):
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(rdtype)
|
||||
q = linkcheck.dns.message.make_query(zone, rdtype, rdclass)
|
||||
if rdtype == linkcheck.dns.rdatatype.IXFR:
|
||||
rrset = linkcheck.dns.rrset.from_text(zone, 0, 'IN', 'SOA',
|
||||
'. . %u 0 0 0 0' % serial)
|
||||
if isinstance(zone, (str, unicode)):
|
||||
zone = dns.name.from_text(zone)
|
||||
if isinstance(rdtype, (str, unicode)):
|
||||
rdtype = dns.rdatatype.from_text(rdtype)
|
||||
q = dns.message.make_query(zone, rdtype, rdclass)
|
||||
if rdtype == dns.rdatatype.IXFR:
|
||||
rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA',
|
||||
'. . %u 0 0 0 0' % serial)
|
||||
q.authority.append(rrset)
|
||||
if not keyring is None:
|
||||
q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
|
||||
wire = q.to_wire()
|
||||
if af is None:
|
||||
try:
|
||||
af = linkcheck.dns.inet.af_for_address(where)
|
||||
af = dns.inet.af_for_address(where)
|
||||
except StandardError:
|
||||
af = linkcheck.dns.inet.AF_INET
|
||||
if af == linkcheck.dns.inet.AF_INET:
|
||||
af = dns.inet.AF_INET
|
||||
if af == dns.inet.AF_INET:
|
||||
destination = (where, port)
|
||||
if source is not None:
|
||||
source = (source, source_port)
|
||||
elif af == linkcheck.dns.inet.AF_INET6:
|
||||
elif af == dns.inet.AF_INET6:
|
||||
destination = (where, port, 0, 0)
|
||||
if source is not None:
|
||||
source = (source, source_port, 0, 0)
|
||||
if use_udp:
|
||||
if rdtype != linkcheck.dns.rdatatype.IXFR:
|
||||
if rdtype != dns.rdatatype.IXFR:
|
||||
raise ValueError('cannot do a UDP AXFR')
|
||||
s = socket.socket(af, socket.SOCK_DGRAM, 0)
|
||||
else:
|
||||
|
|
@ -359,7 +420,7 @@ def xfr (where, zone, rdtype=linkcheck.dns.rdatatype.AXFR,
|
|||
soa_count = 0
|
||||
if relativize:
|
||||
origin = zone
|
||||
oname = linkcheck.dns.name.empty
|
||||
oname = dns.name.empty
|
||||
else:
|
||||
origin = None
|
||||
oname = zone
|
||||
|
|
@ -376,10 +437,10 @@ def xfr (where, zone, rdtype=linkcheck.dns.rdatatype.AXFR,
|
|||
ldata = _net_read(s, 2, mexpiration)
|
||||
(l,) = struct.unpack("!H", ldata)
|
||||
wire = _net_read(s, l, mexpiration)
|
||||
r = linkcheck.dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
|
||||
r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
|
||||
xfr=True, origin=origin, tsig_ctx=tsig_ctx,
|
||||
multi=True, first=first,
|
||||
one_rr_per_rrset=(rdtype==linkcheck.dns.rdatatype.IXFR))
|
||||
one_rr_per_rrset=(rdtype==dns.rdatatype.IXFR))
|
||||
tsig_ctx = r.tsig_ctx
|
||||
first = False
|
||||
answer_index = 0
|
||||
|
|
@ -387,45 +448,45 @@ def xfr (where, zone, rdtype=linkcheck.dns.rdatatype.AXFR,
|
|||
expecting_SOA = False
|
||||
if soa_rrset is None:
|
||||
if not r.answer or r.answer[0].name != oname:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
rrset = r.answer[0]
|
||||
if rrset.rdtype != linkcheck.dns.rdatatype.SOA:
|
||||
raise linkcheck.dns.exception.FormError("first RRset is not an SOA")
|
||||
if rrset.rdtype != dns.rdatatype.SOA:
|
||||
raise dns.exception.FormError("first RRset is not an SOA")
|
||||
answer_index = 1
|
||||
soa_rrset = rrset.copy()
|
||||
if rdtype == linkcheck.dns.rdatatype.IXFR:
|
||||
if rdtype == dns.rdatatype.IXFR:
|
||||
if soa_rrset[0].serial == serial:
|
||||
|
||||
#
|
||||
# We're already up-to-date.
|
||||
|
||||
#
|
||||
done = True
|
||||
else:
|
||||
expecting_SOA = True
|
||||
|
||||
#
|
||||
# Process SOAs in the answer section (other than the initial
|
||||
# SOA in the first message).
|
||||
|
||||
#
|
||||
for rrset in r.answer[answer_index:]:
|
||||
if done:
|
||||
raise linkcheck.dns.exception.FormError("answers after final SOA")
|
||||
if rrset.rdtype == linkcheck.dns.rdatatype.SOA and rrset.name == oname:
|
||||
raise dns.exception.FormError("answers after final SOA")
|
||||
if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname:
|
||||
if expecting_SOA:
|
||||
if rrset[0].serial != serial:
|
||||
raise linkcheck.dns.exception.FormError("IXFR base serial mismatch")
|
||||
raise dns.exception.FormError("IXFR base serial mismatch")
|
||||
expecting_SOA = False
|
||||
elif rdtype == linkcheck.dns.rdatatype.IXFR:
|
||||
elif rdtype == dns.rdatatype.IXFR:
|
||||
delete_mode = not delete_mode
|
||||
if rrset == soa_rrset and not delete_mode:
|
||||
done = True
|
||||
elif expecting_SOA:
|
||||
|
||||
#
|
||||
# We made an IXFR request and are expecting another
|
||||
# SOA RR, but saw something else, so this must be an
|
||||
# AXFR response.
|
||||
|
||||
rdtype = linkcheck.dns.rdatatype.AXFR
|
||||
#
|
||||
rdtype = dns.rdatatype.AXFR
|
||||
expecting_SOA = False
|
||||
if done and q.keyring and not r.had_tsig:
|
||||
raise linkcheck.dns.exception.FormError("missing TSIG")
|
||||
raise dns.exception.FormError("missing TSIG")
|
||||
yield r
|
||||
s.close()
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,7 +15,7 @@
|
|||
|
||||
"""DNS Result Codes."""
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import dns.exception
|
||||
|
||||
NOERROR = 0
|
||||
FORMERR = 1
|
||||
|
|
@ -53,7 +52,7 @@ _by_text = {
|
|||
_by_value = dict([(y, x) for x, y in _by_text.iteritems()])
|
||||
|
||||
|
||||
class UnknownRcode(linkcheck.dns.exception.DNSException):
|
||||
class UnknownRcode(dns.exception.DNSException):
|
||||
"""Raised if an rcode is unknown."""
|
||||
pass
|
||||
|
||||
|
|
@ -101,7 +100,7 @@ def to_flags(value):
|
|||
"""
|
||||
|
||||
if value < 0 or value > 4095:
|
||||
raise ValueError, 'rcode must be >= 0 and <= 4095'
|
||||
raise ValueError('rcode must be >= 0 and <= 4095')
|
||||
v = value & 0xf
|
||||
ev = long(value & 0xff0) << 20
|
||||
return (v, ev)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -20,18 +19,20 @@
|
|||
the module which implements that type.
|
||||
@type _rdata_modules: dict
|
||||
@var _module_prefix: The prefix to use when forming modules names. The
|
||||
default is 'linkcheck.dns.rdtypes'. Changing this value will break the library.
|
||||
default is 'dns.rdtypes'. Changing this value will break the library.
|
||||
@type _module_prefix: string
|
||||
@var _hex_chunk: At most this many octets that will be represented in each
|
||||
chunk of hexstring that _hexify() produces before whitespace occurs.
|
||||
@type _hex_chunk: int"""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.name
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.tokenizer
|
||||
import dns.wiredata
|
||||
|
||||
_hex_chunksize = 32
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ def _hexify(data, chunksize=None):
|
|||
|
||||
@param data: the binary string
|
||||
@type data: string
|
||||
@param chunksize: the chunk size. Default is L{linkcheck.dns.rdata._hex_chunksize}
|
||||
@param chunksize: the chunk size. Default is L{dns.rdata._hex_chunksize}
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ def _base64ify(data, chunksize=None):
|
|||
@param data: the binary string
|
||||
@type data: string
|
||||
@param chunksize: the chunk size. Default is
|
||||
L{linkcheck.dns.rdata._base64_chunksize}
|
||||
L{dns.rdata._base64_chunksize}
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
|
|
@ -143,13 +144,13 @@ class Rdata(object):
|
|||
def covers(self):
|
||||
"""DNS SIG/RRSIG rdatas apply to a specific type; this type is
|
||||
returned by the covers() function. If the rdata type is not
|
||||
SIG or RRSIG, linkcheck.dns.rdatatype.NONE is returned. This is useful when
|
||||
SIG or RRSIG, dns.rdatatype.NONE is returned. This is useful when
|
||||
creating rdatasets, allowing the rdataset to contain only RRSIGs
|
||||
of a particular type, e.g. RRSIG(NS).
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
return linkcheck.dns.rdatatype.NONE
|
||||
return dns.rdatatype.NONE
|
||||
|
||||
def extended_rdatatype(self):
|
||||
"""Return a 32-bit type value, the least significant 16 bits of
|
||||
|
|
@ -176,7 +177,7 @@ class Rdata(object):
|
|||
def to_digestable(self, origin = None):
|
||||
"""Convert rdata to a format suitable for digesting in hashes. This
|
||||
is also the DNSSEC canonical form."""
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f, None, origin)
|
||||
return f.getvalue()
|
||||
|
||||
|
|
@ -186,16 +187,16 @@ class Rdata(object):
|
|||
it is a good idea to call validate() when you are done making
|
||||
changes.
|
||||
"""
|
||||
linkcheck.dns.rdata.from_text(self.rdclass, self.rdtype, self.to_text())
|
||||
dns.rdata.from_text(self.rdclass, self.rdtype, self.to_text())
|
||||
|
||||
def __repr__(self):
|
||||
covers = self.covers()
|
||||
if covers == linkcheck.dns.rdatatype.NONE:
|
||||
if covers == dns.rdatatype.NONE:
|
||||
ctext = ''
|
||||
else:
|
||||
ctext = '(' + linkcheck.dns.rdatatype.to_text(covers) + ')'
|
||||
return '<DNS ' + linkcheck.dns.rdataclass.to_text(self.rdclass) + ' ' + \
|
||||
linkcheck.dns.rdatatype.to_text(self.rdtype) + ctext + ' rdata: ' + \
|
||||
ctext = '(' + dns.rdatatype.to_text(covers) + ')'
|
||||
return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
|
||||
dns.rdatatype.to_text(self.rdtype) + ctext + ' rdata: ' + \
|
||||
str(self) + '>'
|
||||
|
||||
def __str__(self):
|
||||
|
|
@ -253,6 +254,22 @@ class Rdata(object):
|
|||
return NotImplemented
|
||||
return self._cmp(other) > 0
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.to_digestable(dns.name.root))
|
||||
|
||||
def _wire_cmp(self, other):
|
||||
# A number of types compare rdata in wire form, so we provide
|
||||
# the method here instead of duplicating it.
|
||||
#
|
||||
# We specifiy an arbitrary origin of '.' when doing the
|
||||
# comparison, since the rdata may have relative names and we
|
||||
# can't convert a relative name to wire without an origin.
|
||||
b1 = cStringIO.StringIO()
|
||||
self.to_wire(b1, None, dns.name.root)
|
||||
b2 = cStringIO.StringIO()
|
||||
other.to_wire(b2, None, dns.name.root)
|
||||
return cmp(b1.getvalue(), b2.getvalue())
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
"""Build an rdata object from text format.
|
||||
|
||||
|
|
@ -261,12 +278,12 @@ class Rdata(object):
|
|||
@param rdtype: The rdata type
|
||||
@type rdtype: int
|
||||
@param tok: The tokenizer
|
||||
@type tok: linkcheck.dns.tokenizer.Tokenizer
|
||||
@type tok: dns.tokenizer.Tokenizer
|
||||
@param origin: The origin to use for relative names
|
||||
@type origin: linkcheck.dns.name.Name
|
||||
@type origin: dns.name.Name
|
||||
@param relativize: should names be relativized?
|
||||
@type relativize: bool
|
||||
@rtype: linkcheck.dns.rdata.Rdata instance
|
||||
@rtype: dns.rdata.Rdata instance
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
|
@ -287,8 +304,8 @@ class Rdata(object):
|
|||
@param rdlen: The length of the wire-format rdata
|
||||
@type rdlen: int
|
||||
@param origin: The origin to use for relative names
|
||||
@type origin: linkcheck.dns.name.Name
|
||||
@rtype: linkcheck.dns.rdata.Rdata instance
|
||||
@type origin: dns.name.Name
|
||||
@rtype: dns.rdata.Rdata instance
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
|
@ -322,7 +339,7 @@ class GenericRdata(Rdata):
|
|||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
token = tok.get()
|
||||
if not token.is_identifier() or token.value != '\#':
|
||||
raise linkcheck.dns.exception.DNSSyntaxError(r'generic rdata does not start with \#')
|
||||
raise dns.exception.SyntaxError(r'generic rdata does not start with \#')
|
||||
length = tok.get_int()
|
||||
chunks = []
|
||||
while 1:
|
||||
|
|
@ -333,7 +350,7 @@ class GenericRdata(Rdata):
|
|||
hex = ''.join(chunks)
|
||||
data = hex.decode('hex_codec')
|
||||
if len(data) != length:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('generic rdata hex data has wrong length')
|
||||
raise dns.exception.SyntaxError('generic rdata hex data has wrong length')
|
||||
return cls(rdclass, rdtype, data)
|
||||
|
||||
from_text = classmethod(from_text)
|
||||
|
|
@ -350,7 +367,7 @@ class GenericRdata(Rdata):
|
|||
return cmp(self.data, other.data)
|
||||
|
||||
_rdata_modules = {}
|
||||
_module_prefix = 'linkcheck.dns.rdtypes'
|
||||
_module_prefix = 'dns.rdtypes'
|
||||
|
||||
def get_rdata_class(rdclass, rdtype):
|
||||
|
||||
|
|
@ -362,11 +379,11 @@ def get_rdata_class(rdclass, rdtype):
|
|||
return mod
|
||||
|
||||
mod = _rdata_modules.get((rdclass, rdtype))
|
||||
rdclass_text = linkcheck.dns.rdataclass.to_text(rdclass)
|
||||
rdtype_text = linkcheck.dns.rdatatype.to_text(rdtype)
|
||||
rdclass_text = dns.rdataclass.to_text(rdclass)
|
||||
rdtype_text = dns.rdatatype.to_text(rdtype)
|
||||
rdtype_text = rdtype_text.replace('-', '_')
|
||||
if not mod:
|
||||
mod = _rdata_modules.get((linkcheck.dns.rdatatype.ANY, rdtype))
|
||||
mod = _rdata_modules.get((dns.rdatatype.ANY, rdtype))
|
||||
if not mod:
|
||||
try:
|
||||
mod = import_module('.'.join([_module_prefix,
|
||||
|
|
@ -376,7 +393,7 @@ def get_rdata_class(rdclass, rdtype):
|
|||
try:
|
||||
mod = import_module('.'.join([_module_prefix,
|
||||
'ANY', rdtype_text]))
|
||||
_rdata_modules[(linkcheck.dns.rdataclass.ANY, rdtype)] = mod
|
||||
_rdata_modules[(dns.rdataclass.ANY, rdtype)] = mod
|
||||
except ImportError:
|
||||
mod = None
|
||||
if mod:
|
||||
|
|
@ -401,15 +418,15 @@ def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
|
|||
@param rdtype: The rdata type
|
||||
@type rdtype: int
|
||||
@param tok: The tokenizer
|
||||
@type tok: linkcheck.dns.tokenizer.Tokenizer
|
||||
@type tok: dns.tokenizer.Tokenizer
|
||||
@param origin: The origin to use for relative names
|
||||
@type origin: linkcheck.dns.name.Name
|
||||
@type origin: dns.name.Name
|
||||
@param relativize: Should names be relativized?
|
||||
@type relativize: bool
|
||||
@rtype: linkcheck.dns.rdata.Rdata instance"""
|
||||
@rtype: dns.rdata.Rdata instance"""
|
||||
|
||||
if isinstance(tok, str):
|
||||
tok = linkcheck.dns.tokenizer.Tokenizer(tok)
|
||||
tok = dns.tokenizer.Tokenizer(tok)
|
||||
cls = get_rdata_class(rdclass, rdtype)
|
||||
if cls != GenericRdata:
|
||||
# peek at first token
|
||||
|
|
@ -417,11 +434,11 @@ def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
|
|||
tok.unget(token)
|
||||
if token.is_identifier() and \
|
||||
token.value == r'\#':
|
||||
|
||||
#
|
||||
# Known type using the generic syntax. Extract the
|
||||
# wire form from the generic syntax, and then run
|
||||
# from_wire on it.
|
||||
|
||||
#
|
||||
rdata = GenericRdata.from_text(rdclass, rdtype, tok, origin,
|
||||
relativize)
|
||||
return from_wire(rdclass, rdtype, rdata.data, 0, len(rdata.data),
|
||||
|
|
@ -450,8 +467,9 @@ def from_wire(rdclass, rdtype, wire, current, rdlen, origin = None):
|
|||
@param rdlen: The length of the wire-format rdata
|
||||
@type rdlen: int
|
||||
@param origin: The origin to use for relative names
|
||||
@type origin: linkcheck.dns.name.Name
|
||||
@rtype: linkcheck.dns.rdata.Rdata instance"""
|
||||
@type origin: dns.name.Name
|
||||
@rtype: dns.rdata.Rdata instance"""
|
||||
|
||||
wire = dns.wiredata.maybe_wrap(wire)
|
||||
cls = get_rdata_class(rdclass, rdtype)
|
||||
return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -26,7 +25,7 @@ whose key is the rdatatype value and whose value is True in this dictionary.
|
|||
|
||||
import re
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import dns.exception
|
||||
|
||||
RESERVED0 = 0
|
||||
IN = 1
|
||||
|
|
@ -66,7 +65,7 @@ _metaclasses = {
|
|||
|
||||
_unknown_class_pattern = re.compile('CLASS([0-9]+)$', re.I);
|
||||
|
||||
class UnknownRdataclass(linkcheck.dns.exception.DNSException):
|
||||
class UnknownRdataclass(dns.exception.DNSException):
|
||||
"""Raised when a class is unknown."""
|
||||
pass
|
||||
|
||||
|
|
@ -75,14 +74,14 @@ def from_text(text):
|
|||
@param text: the text
|
||||
@type text: string
|
||||
@rtype: int
|
||||
@raises linkcheck.dns.rdataclass.UnknownRdataClass: the class is unknown
|
||||
@raises dns.rdataclass.UnknownRdataClass: the class is unknown
|
||||
@raises ValueError: the rdata class value is not >= 0 and <= 65535
|
||||
"""
|
||||
|
||||
value = _by_text.get(text.upper())
|
||||
if value is None:
|
||||
match = _unknown_class_pattern.match(text)
|
||||
if match is None:
|
||||
if match == None:
|
||||
raise UnknownRdataclass
|
||||
value = int(match.group(1))
|
||||
if value < 0 or value > 65535:
|
||||
|
|
@ -101,7 +100,7 @@ def to_text(value):
|
|||
raise ValueError("class must be between >= 0 and <= 65535")
|
||||
text = _by_value.get(value)
|
||||
if text is None:
|
||||
text = 'CLASS' + repr(value)
|
||||
text = 'CLASS' + `value`
|
||||
return text
|
||||
|
||||
def is_metaclass(rdclass):
|
||||
|
|
@ -110,4 +109,6 @@ def is_metaclass(rdclass):
|
|||
@type rdclass: int
|
||||
@rtype: bool"""
|
||||
|
||||
return rdclass in _metaclasses
|
||||
if rdclass in _metaclasses:
|
||||
return True
|
||||
return False
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -17,24 +16,28 @@
|
|||
"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)"""
|
||||
|
||||
import random
|
||||
from cStringIO import StringIO
|
||||
import StringIO
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdata
|
||||
import dns.exception
|
||||
import dns.rdatatype
|
||||
import dns.rdataclass
|
||||
import dns.rdata
|
||||
import dns.set
|
||||
|
||||
class DifferingCovers(linkcheck.dns.exception.DNSException):
|
||||
# define SimpleSet here for backwards compatibility
|
||||
SimpleSet = dns.set.Set
|
||||
|
||||
class DifferingCovers(dns.exception.DNSException):
|
||||
"""Raised if an attempt is made to add a SIG/RRSIG whose covered type
|
||||
is not the same as that of the other rdatas in the rdataset."""
|
||||
pass
|
||||
|
||||
class IncompatibleTypes(linkcheck.dns.exception.DNSException):
|
||||
class IncompatibleTypes(dns.exception.DNSException):
|
||||
"""Raised if an attempt is made to add rdata of an incompatible type."""
|
||||
pass
|
||||
|
||||
class Rdataset(set):
|
||||
class Rdataset(dns.set.Set):
|
||||
"""A DNS rdataset.
|
||||
|
||||
@ivar rdclass: The class of the rdataset
|
||||
|
|
@ -42,8 +45,8 @@ class Rdataset(set):
|
|||
@ivar rdtype: The type of the rdataset
|
||||
@type rdtype: int
|
||||
@ivar covers: The covered type. Usually this value is
|
||||
linkcheck.dns.rdatatype.NONE, but if the rdtype is linkcheck.dns.rdatatype.SIG or
|
||||
linkcheck.dns.rdatatype.RRSIG, then the covers value will be the rdata
|
||||
dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
|
||||
dns.rdatatype.RRSIG, then the covers value will be the rdata
|
||||
type the SIG/RRSIG covers. The library treats the SIG and RRSIG
|
||||
types as if they were a family of
|
||||
types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
|
||||
|
|
@ -56,7 +59,7 @@ class Rdataset(set):
|
|||
|
||||
__slots__ = ['rdclass', 'rdtype', 'covers', 'ttl']
|
||||
|
||||
def __init__(self, rdclass, rdtype, covers=linkcheck.dns.rdatatype.NONE):
|
||||
def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
|
||||
"""Create a new rdataset of the specified class and type.
|
||||
|
||||
@see: the description of the class instance variables for the
|
||||
|
|
@ -95,28 +98,28 @@ class Rdataset(set):
|
|||
self.update_ttl(ttl) will be called prior to adding the rdata.
|
||||
|
||||
@param rd: The rdata
|
||||
@type rd: linkcheck.dns.rdata.Rdata object
|
||||
@type rd: dns.rdata.Rdata object
|
||||
@param ttl: The TTL
|
||||
@type ttl: int"""
|
||||
|
||||
|
||||
#
|
||||
# If we're adding a signature, do some special handling to
|
||||
# check that the signature covers the same type as the
|
||||
# other rdatas in this rdataset. If this is the first rdata
|
||||
# in the set, initialize the covers field.
|
||||
|
||||
#
|
||||
if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype:
|
||||
raise IncompatibleTypes
|
||||
if not ttl is None:
|
||||
self.update_ttl(ttl)
|
||||
if self.rdtype == linkcheck.dns.rdatatype.RRSIG or \
|
||||
self.rdtype == linkcheck.dns.rdatatype.SIG:
|
||||
if self.rdtype == dns.rdatatype.RRSIG or \
|
||||
self.rdtype == dns.rdatatype.SIG:
|
||||
covers = rd.covers()
|
||||
if len(self) == 0 and self.covers == linkcheck.dns.rdatatype.NONE:
|
||||
if len(self) == 0 and self.covers == dns.rdatatype.NONE:
|
||||
self.covers = covers
|
||||
elif self.covers != covers:
|
||||
raise DifferingCovers
|
||||
if linkcheck.dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0:
|
||||
if dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0:
|
||||
self.clear()
|
||||
super(Rdataset, self).add(rd)
|
||||
|
||||
|
|
@ -132,7 +135,8 @@ class Rdataset(set):
|
|||
"""Add all rdatas in other to self.
|
||||
|
||||
@param other: The rdataset from which to update
|
||||
@type other: linkcheck.dns.rdataset.Rdataset object"""
|
||||
@type other: dns.rdataset.Rdataset object"""
|
||||
|
||||
self.update_ttl(other.ttl)
|
||||
super(Rdataset, self).update(other)
|
||||
|
||||
|
|
@ -140,9 +144,9 @@ class Rdataset(set):
|
|||
if self.covers == 0:
|
||||
ctext = ''
|
||||
else:
|
||||
ctext = '(' + linkcheck.dns.rdatatype.to_text(self.covers) + ')'
|
||||
return '<DNS ' + linkcheck.dns.rdataclass.to_text(self.rdclass) + ' ' + \
|
||||
linkcheck.dns.rdatatype.to_text(self.rdtype) + ctext + ' rdataset>'
|
||||
ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
|
||||
return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \
|
||||
dns.rdatatype.to_text(self.rdtype) + ctext + ' rdataset>'
|
||||
|
||||
def __str__(self):
|
||||
return self.to_text()
|
||||
|
|
@ -151,6 +155,7 @@ class Rdataset(set):
|
|||
"""Two rdatasets are equal if they have the same class, type, and
|
||||
covers, and contain the same rdata.
|
||||
@rtype: bool"""
|
||||
|
||||
if not isinstance(other, Rdataset):
|
||||
return False
|
||||
if self.rdclass != other.rdclass or \
|
||||
|
|
@ -166,7 +171,7 @@ class Rdataset(set):
|
|||
override_rdclass=None, **kw):
|
||||
"""Convert the rdataset into DNS master file format.
|
||||
|
||||
@see: L{linkcheck.dns.name.Name.choose_relativity} for more information
|
||||
@see: L{dns.name.Name.choose_relativity} for more information
|
||||
on how I{origin} and I{relativize} determine the way names
|
||||
are emitted.
|
||||
|
||||
|
|
@ -175,9 +180,9 @@ class Rdataset(set):
|
|||
|
||||
@param name: If name is not None, emit a RRs with I{name} as
|
||||
the owner name.
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@param origin: The origin for relative names, or None.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@param relativize: True if names should names be relativized
|
||||
@type relativize: bool"""
|
||||
if not name is None:
|
||||
|
|
@ -187,29 +192,29 @@ class Rdataset(set):
|
|||
else:
|
||||
ntext = ''
|
||||
pad = ''
|
||||
s = StringIO()
|
||||
s = StringIO.StringIO()
|
||||
if not override_rdclass is None:
|
||||
rdclass = override_rdclass
|
||||
else:
|
||||
rdclass = self.rdclass
|
||||
if len(self) == 0:
|
||||
|
||||
#
|
||||
# Empty rdatasets are used for the question section, and in
|
||||
# some dynamic updates, so we don't need to print out the TTL
|
||||
# (which is meaningless anyway).
|
||||
|
||||
#
|
||||
print >> s, '%s%s%s %s' % (ntext, pad,
|
||||
linkcheck.dns.rdataclass.to_text(rdclass),
|
||||
linkcheck.dns.rdatatype.to_text(self.rdtype))
|
||||
dns.rdataclass.to_text(rdclass),
|
||||
dns.rdatatype.to_text(self.rdtype))
|
||||
else:
|
||||
for rd in self:
|
||||
print >> s, '%s%s%d %s %s %s' % \
|
||||
(ntext, pad, self.ttl, linkcheck.dns.rdataclass.to_text(rdclass),
|
||||
linkcheck.dns.rdatatype.to_text(self.rdtype),
|
||||
(ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass),
|
||||
dns.rdatatype.to_text(self.rdtype),
|
||||
rd.to_text(origin=origin, relativize=relativize, **kw))
|
||||
|
||||
#
|
||||
# We strip off the final \n for the caller's convenience in printing
|
||||
|
||||
#
|
||||
return s.getvalue()[:-1]
|
||||
|
||||
def to_wire(self, name, file, compress=None, origin=None,
|
||||
|
|
@ -217,7 +222,7 @@ class Rdataset(set):
|
|||
"""Convert the rdataset to wire format.
|
||||
|
||||
@param name: The owner name of the RRset that will be emitted
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@param file: The file to which the wire format data will be appended
|
||||
@type file: file
|
||||
@param compress: The compression table to use; the default is None.
|
||||
|
|
@ -263,26 +268,27 @@ class Rdataset(set):
|
|||
def match(self, rdclass, rdtype, covers):
|
||||
"""Returns True if this rdataset matches the specified class, type,
|
||||
and covers"""
|
||||
return self.rdclass == rdclass and \
|
||||
if self.rdclass == rdclass and \
|
||||
self.rdtype == rdtype and \
|
||||
self.covers == covers
|
||||
|
||||
self.covers == covers:
|
||||
return True
|
||||
return False
|
||||
|
||||
def from_text_list(rdclass, rdtype, ttl, text_rdatas):
|
||||
"""Create an rdataset with the specified class, type, and TTL, and with
|
||||
the specified list of rdatas in text format.
|
||||
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object
|
||||
@rtype: dns.rdataset.Rdataset object
|
||||
"""
|
||||
|
||||
if isinstance(rdclass, basestring):
|
||||
rdclass = linkcheck.dns.rdataclass.from_text(rdclass)
|
||||
if isinstance(rdtype, basestring):
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(rdtype)
|
||||
if isinstance(rdclass, (str, unicode)):
|
||||
rdclass = dns.rdataclass.from_text(rdclass)
|
||||
if isinstance(rdtype, (str, unicode)):
|
||||
rdtype = dns.rdatatype.from_text(rdtype)
|
||||
r = Rdataset(rdclass, rdtype)
|
||||
r.update_ttl(ttl)
|
||||
for t in text_rdatas:
|
||||
rd = linkcheck.dns.rdata.from_text(r.rdclass, r.rdtype, t)
|
||||
rd = dns.rdata.from_text(r.rdclass, r.rdtype, t)
|
||||
r.add(rd)
|
||||
return r
|
||||
|
||||
|
|
@ -290,7 +296,7 @@ def from_text(rdclass, rdtype, ttl, *text_rdatas):
|
|||
"""Create an rdataset with the specified class, type, and TTL, and with
|
||||
the specified rdatas in text format.
|
||||
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object
|
||||
@rtype: dns.rdataset.Rdataset object
|
||||
"""
|
||||
|
||||
return from_text_list(rdclass, rdtype, ttl, text_rdatas)
|
||||
|
|
@ -299,7 +305,7 @@ def from_rdata_list(ttl, rdatas):
|
|||
"""Create an rdataset with the specified TTL, and with
|
||||
the specified list of rdata objects.
|
||||
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object
|
||||
@rtype: dns.rdataset.Rdataset object
|
||||
"""
|
||||
|
||||
if len(rdatas) == 0:
|
||||
|
|
@ -317,7 +323,7 @@ def from_rdata(ttl, *rdatas):
|
|||
"""Create an rdataset with the specified TTL, and with
|
||||
the specified rdata objects.
|
||||
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object
|
||||
@rtype: dns.rdataset.Rdataset object
|
||||
"""
|
||||
|
||||
return from_rdata_list(ttl, rdatas)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -29,7 +28,7 @@ whose key is the rdatatype value and whose value is True in this dictionary.
|
|||
|
||||
import re
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import dns.exception
|
||||
|
||||
NONE = 0
|
||||
A = 1
|
||||
|
|
@ -176,7 +175,7 @@ _singletons = {
|
|||
|
||||
_unknown_type_pattern = re.compile('TYPE([0-9]+)$', re.I);
|
||||
|
||||
class UnknownRdatatype(linkcheck.dns.exception.DNSException):
|
||||
class UnknownRdatatype(dns.exception.DNSException):
|
||||
"""Raised if a type is unknown."""
|
||||
pass
|
||||
|
||||
|
|
@ -184,14 +183,14 @@ def from_text(text):
|
|||
"""Convert text into a DNS rdata type value.
|
||||
@param text: the text
|
||||
@type text: string
|
||||
@raises linkcheck.dns.rdatatype.UnknownRdatatype: the type is unknown
|
||||
@raises dns.rdatatype.UnknownRdatatype: the type is unknown
|
||||
@raises ValueError: the rdata type value is not >= 0 and <= 65535
|
||||
@rtype: int"""
|
||||
|
||||
value = _by_text.get(text.upper())
|
||||
if value is None:
|
||||
match = _unknown_type_pattern.match(text)
|
||||
if match is None:
|
||||
if match == None:
|
||||
raise UnknownRdatatype
|
||||
value = int(match.group(1))
|
||||
if value < 0 or value > 65535:
|
||||
|
|
@ -209,7 +208,7 @@ def to_text(value):
|
|||
raise ValueError("type must be between >= 0 and <= 65535")
|
||||
text = _by_value.get(value)
|
||||
if text is None:
|
||||
text = 'TYPE' + repr(value)
|
||||
text = 'TYPE' + `value`
|
||||
return text
|
||||
|
||||
def is_metatype(rdtype):
|
||||
|
|
@ -218,7 +217,9 @@ def is_metatype(rdtype):
|
|||
@type rdtype: int
|
||||
@rtype: bool"""
|
||||
|
||||
return rdtype >= TKEY and rdtype <= ANY or rdtype in _metatypes
|
||||
if rdtype >= TKEY and rdtype <= ANY or rdtype in _metatypes:
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_singleton(rdtype):
|
||||
"""True if the type is a singleton.
|
||||
|
|
@ -226,4 +227,6 @@ def is_singleton(rdtype):
|
|||
@type rdtype: int
|
||||
@rtype: bool"""
|
||||
|
||||
return rdtype in _singletons
|
||||
if rdtype in _singletons:
|
||||
return True
|
||||
return False
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,15 +13,15 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.mxbase
|
||||
import dns.rdtypes.mxbase
|
||||
|
||||
class AFSDB(linkcheck.dns.rdtypes.mxbase.UncompressedDowncasingMX):
|
||||
class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX):
|
||||
"""AFSDB record
|
||||
|
||||
@ivar subtype: the subtype value
|
||||
@type subtype: int
|
||||
@ivar hostname: the hostname name
|
||||
@type hostname: linkcheck.dns.name.Name object"""
|
||||
@type hostname: dns.name.Name object"""
|
||||
|
||||
# Use the property mechanism to make "subtype" an alias for the
|
||||
# "preference" attribute, and "hostname" an alias for the "exchange"
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,13 +13,13 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.dnssec
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.dnssec
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
_ctype_by_value = {
|
||||
1 : 'PKIX',
|
||||
|
|
@ -50,7 +49,7 @@ def _ctype_to_text(what):
|
|||
return v
|
||||
return str(what)
|
||||
|
||||
class CERT(linkcheck.dns.rdata.Rdata):
|
||||
class CERT(dns.rdata.Rdata):
|
||||
"""CERT record
|
||||
|
||||
@ivar certificate_type: certificate type
|
||||
|
|
@ -76,22 +75,22 @@ class CERT(linkcheck.dns.rdata.Rdata):
|
|||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
certificate_type = _ctype_to_text(self.certificate_type)
|
||||
return "%s %d %s %s" % (certificate_type, self.key_tag,
|
||||
linkcheck.dns.dnssec.algorithm_to_text(self.algorithm),
|
||||
linkcheck.dns.rdata._base64ify(self.certificate))
|
||||
dns.dnssec.algorithm_to_text(self.algorithm),
|
||||
dns.rdata._base64ify(self.certificate))
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
certificate_type = _ctype_from_text(tok.get_string())
|
||||
key_tag = tok.get_uint16()
|
||||
algorithm = linkcheck.dns.dnssec.algorithm_from_text(tok.get_string())
|
||||
algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
|
||||
if algorithm < 0 or algorithm > 255:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("bad algorithm type")
|
||||
raise dns.exception.SyntaxError("bad algorithm type")
|
||||
chunks = []
|
||||
while 1:
|
||||
t = tok.get().unescape()
|
||||
if t.is_eol_or_eof():
|
||||
break
|
||||
if not t.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
chunks.append(t.value)
|
||||
b64 = ''.join(chunks)
|
||||
certificate = b64.decode('base64_codec')
|
||||
|
|
@ -107,20 +106,20 @@ class CERT(linkcheck.dns.rdata.Rdata):
|
|||
file.write(self.certificate)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
prefix = wire[current : current + 5]
|
||||
prefix = wire[current : current + 5].unwrap()
|
||||
current += 5
|
||||
rdlen -= 5
|
||||
if rdlen < 0:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
(certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix)
|
||||
certificate = wire[current : current + rdlen]
|
||||
certificate = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, certificate_type, key_tag, algorithm,
|
||||
certificate)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f)
|
||||
wire1 = f.getvalue()
|
||||
f.seek(0)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,9 +13,9 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.nsbase
|
||||
import dns.rdtypes.nsbase
|
||||
|
||||
class CNAME(linkcheck.dns.rdtypes.nsbase.NSBase):
|
||||
class CNAME(dns.rdtypes.nsbase.NSBase):
|
||||
"""CNAME record
|
||||
|
||||
Note: although CNAME is officially a singleton type, dnspython allows
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -13,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.dsbase
|
||||
import dns.rdtypes.dsbase
|
||||
|
||||
class DLV(linkcheck.dns.rdtypes.dsbase.DSBase):
|
||||
class DLV(dns.rdtypes.dsbase.DSBase):
|
||||
"""DLV record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -15,9 +14,9 @@
|
|||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
|
||||
import linkcheck.dns.rdtypes.nsbase
|
||||
import dns.rdtypes.nsbase
|
||||
|
||||
class DNAME(linkcheck.dns.rdtypes.nsbase.UncompressedNS):
|
||||
class DNAME(dns.rdtypes.nsbase.UncompressedNS):
|
||||
"""DNAME record"""
|
||||
def to_digestable(self, origin = None):
|
||||
return self.target.to_digestable(origin)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,55 +15,17 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.dnssec
|
||||
import linkcheck.dns.rdata
|
||||
import dns.exception
|
||||
import dns.dnssec
|
||||
import dns.rdata
|
||||
|
||||
_flags_from_text = {
|
||||
'NOCONF': (0x4000, 0xC000),
|
||||
'NOAUTH': (0x8000, 0xC000),
|
||||
'NOKEY': (0xC000, 0xC000),
|
||||
'FLAG2': (0x2000, 0x2000),
|
||||
'EXTEND': (0x1000, 0x1000),
|
||||
'FLAG4': (0x0800, 0x0800),
|
||||
'FLAG5': (0x0400, 0x0400),
|
||||
'USER': (0x0000, 0x0300),
|
||||
'ZONE': (0x0100, 0x0300),
|
||||
'HOST': (0x0200, 0x0300),
|
||||
'NTYP3': (0x0300, 0x0300),
|
||||
'FLAG8': (0x0080, 0x0080),
|
||||
'FLAG9': (0x0040, 0x0040),
|
||||
'FLAG10': (0x0020, 0x0020),
|
||||
'FLAG11': (0x0010, 0x0010),
|
||||
'SIG0': (0x0000, 0x000f),
|
||||
'SIG1': (0x0001, 0x000f),
|
||||
'SIG2': (0x0002, 0x000f),
|
||||
'SIG3': (0x0003, 0x000f),
|
||||
'SIG4': (0x0004, 0x000f),
|
||||
'SIG5': (0x0005, 0x000f),
|
||||
'SIG6': (0x0006, 0x000f),
|
||||
'SIG7': (0x0007, 0x000f),
|
||||
'SIG8': (0x0008, 0x000f),
|
||||
'SIG9': (0x0009, 0x000f),
|
||||
'SIG10': (0x000a, 0x000f),
|
||||
'SIG11': (0x000b, 0x000f),
|
||||
'SIG12': (0x000c, 0x000f),
|
||||
'SIG13': (0x000d, 0x000f),
|
||||
'SIG14': (0x000e, 0x000f),
|
||||
'SIG15': (0x000f, 0x000f),
|
||||
}
|
||||
# flag constants
|
||||
SEP = 0x0001
|
||||
REVOKE = 0x0080
|
||||
ZONE = 0x0100
|
||||
|
||||
_protocol_from_text = {
|
||||
'NONE' : 0,
|
||||
'TLS' : 1,
|
||||
'EMAIL' : 2,
|
||||
'DNSSEC' : 3,
|
||||
'IPSEC' : 4,
|
||||
'ALL' : 255,
|
||||
}
|
||||
|
||||
class KEYBase(linkcheck.dns.rdata.Rdata):
|
||||
"""KEY-like record base
|
||||
class DNSKEY(dns.rdata.Rdata):
|
||||
"""DNSKEY record
|
||||
|
||||
@ivar flags: the key flags
|
||||
@type flags: int
|
||||
|
|
@ -78,7 +39,7 @@ class KEYBase(linkcheck.dns.rdata.Rdata):
|
|||
__slots__ = ['flags', 'protocol', 'algorithm', 'key']
|
||||
|
||||
def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key):
|
||||
super(KEYBase, self).__init__(rdclass, rdtype)
|
||||
super(DNSKEY, self).__init__(rdclass, rdtype)
|
||||
self.flags = flags
|
||||
self.protocol = protocol
|
||||
self.algorithm = algorithm
|
||||
|
|
@ -86,37 +47,19 @@ class KEYBase(linkcheck.dns.rdata.Rdata):
|
|||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
|
||||
linkcheck.dns.rdata._base64ify(self.key))
|
||||
dns.rdata._base64ify(self.key))
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
flags = tok.get_string()
|
||||
if flags.isdigit():
|
||||
flags = int(flags)
|
||||
else:
|
||||
flag_names = flags.split('|')
|
||||
flags = 0
|
||||
for flag in flag_names:
|
||||
v = _flags_from_text.get(flag)
|
||||
if v is None:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('unknown flag %s' % flag)
|
||||
flags &= ~v[1]
|
||||
flags |= v[0]
|
||||
protocol = tok.get_string()
|
||||
if protocol.isdigit():
|
||||
protocol = int(protocol)
|
||||
else:
|
||||
protocol = _protocol_from_text.get(protocol)
|
||||
if protocol is None:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('unknown protocol %s' % protocol)
|
||||
|
||||
algorithm = linkcheck.dns.dnssec.algorithm_from_text(tok.get_string())
|
||||
flags = tok.get_uint16()
|
||||
protocol = tok.get_uint8()
|
||||
algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
|
||||
chunks = []
|
||||
while 1:
|
||||
t = tok.get().unescape()
|
||||
if t.is_eol_or_eof():
|
||||
break
|
||||
if not t.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
chunks.append(t.value)
|
||||
b64 = ''.join(chunks)
|
||||
key = b64.decode('base64_codec')
|
||||
|
|
@ -131,11 +74,11 @@ class KEYBase(linkcheck.dns.rdata.Rdata):
|
|||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
if rdlen < 4:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
header = struct.unpack('!HBB', wire[current : current + 4])
|
||||
current += 4
|
||||
rdlen -= 4
|
||||
key = wire[current : current + rdlen]
|
||||
key = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, header[0], header[1], header[2],
|
||||
key)
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.dsbase
|
||||
import dns.rdtypes.dsbase
|
||||
|
||||
class DS(linkcheck.dns.rdtypes.dsbase.DSBase):
|
||||
class DS(dns.rdtypes.dsbase.DSBase):
|
||||
"""DS record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,9 +13,9 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
def _validate_float_string(what):
|
||||
if what[0] == '-' or what[0] == '+':
|
||||
|
|
@ -25,13 +24,13 @@ def _validate_float_string(what):
|
|||
return
|
||||
(left, right) = what.split('.')
|
||||
if left == '' and right == '':
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not left == '' and not left.isdigit():
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not right == '' and not right.isdigit():
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
|
||||
class GPOS(linkcheck.dns.rdata.Rdata):
|
||||
class GPOS(dns.rdata.Rdata):
|
||||
"""GPOS record
|
||||
|
||||
@ivar latitude: latitude
|
||||
|
|
@ -99,24 +98,24 @@ class GPOS(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l > rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
latitude = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
latitude = wire[current : current + l].unwrap()
|
||||
current += l
|
||||
rdlen -= l
|
||||
l = ord(wire[current])
|
||||
current += 1
|
||||
rdlen -= 1
|
||||
if l > rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
longitude = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
longitude = wire[current : current + l].unwrap()
|
||||
current += l
|
||||
rdlen -= l
|
||||
l = ord(wire[current])
|
||||
current += 1
|
||||
rdlen -= 1
|
||||
if l != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
altitude = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
altitude = wire[current : current + l].unwrap()
|
||||
return cls(rdclass, rdtype, latitude, longitude, altitude)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,11 +13,11 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class HINFO(linkcheck.dns.rdata.Rdata):
|
||||
class HINFO(dns.rdata.Rdata):
|
||||
"""HINFO record
|
||||
|
||||
@ivar cpu: the CPU type
|
||||
|
|
@ -35,8 +34,8 @@ class HINFO(linkcheck.dns.rdata.Rdata):
|
|||
self.os = os
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return '"%s" "%s"' % (linkcheck.dns.rdata._escapify(self.cpu),
|
||||
linkcheck.dns.rdata._escapify(self.os))
|
||||
return '"%s" "%s"' % (dns.rdata._escapify(self.cpu),
|
||||
dns.rdata._escapify(self.os))
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
cpu = tok.get_string()
|
||||
|
|
@ -63,16 +62,16 @@ class HINFO(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l > rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
cpu = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
cpu = wire[current : current + l].unwrap()
|
||||
current += l
|
||||
rdlen -= l
|
||||
l = ord(wire[current])
|
||||
current += 1
|
||||
rdlen -= 1
|
||||
if l != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
os = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
os = wire[current : current + l].unwrap()
|
||||
return cls(rdclass, rdtype, cpu, os)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2010 Nominum, Inc.
|
||||
# Copyright (C) 2010, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,13 +14,14 @@
|
|||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import cStringIO
|
||||
import string
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
|
||||
class HIP(linkcheck.dns.rdata.Rdata):
|
||||
class HIP(dns.rdata.Rdata):
|
||||
"""HIP record
|
||||
|
||||
@ivar hit: the host identity tag
|
||||
|
|
@ -30,7 +31,7 @@ class HIP(linkcheck.dns.rdata.Rdata):
|
|||
@ivar key: the public key
|
||||
@type key: string
|
||||
@ivar servers: the rendezvous servers
|
||||
@type servers: list of linkcheck.dns.name.Name objects
|
||||
@type servers: list of dns.name.Name objects
|
||||
@see: RFC 5205"""
|
||||
|
||||
__slots__ = ['hit', 'algorithm', 'key', 'servers']
|
||||
|
|
@ -57,14 +58,14 @@ class HIP(linkcheck.dns.rdata.Rdata):
|
|||
algorithm = tok.get_uint8()
|
||||
hit = tok.get_string().decode('hex-codec')
|
||||
if len(hit) > 255:
|
||||
raise linkcheck.dns.exception.SyntaxError("HIT too long")
|
||||
raise dns.exception.SyntaxError("HIT too long")
|
||||
key = tok.get_string().decode('base64-codec')
|
||||
servers = []
|
||||
while 1:
|
||||
token = tok.get()
|
||||
if token.is_eol_or_eof():
|
||||
break
|
||||
server = linkcheck.dns.name.from_text(token.value, origin)
|
||||
server = dns.name.from_text(token.value, origin)
|
||||
server.choose_relativity(origin, relativize)
|
||||
servers.append(server)
|
||||
return cls(rdclass, rdtype, hit, algorithm, key, servers)
|
||||
|
|
@ -85,15 +86,15 @@ class HIP(linkcheck.dns.rdata.Rdata):
|
|||
wire[current : current + 4])
|
||||
current += 4
|
||||
rdlen -= 4
|
||||
hit = wire[current : current + lh]
|
||||
hit = wire[current : current + lh].unwrap()
|
||||
current += lh
|
||||
rdlen -= lh
|
||||
key = wire[current : current + lk]
|
||||
key = wire[current : current + lk].unwrap()
|
||||
current += lk
|
||||
rdlen -= lk
|
||||
servers = []
|
||||
while rdlen > 0:
|
||||
(server, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(server, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,11 +13,11 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class ISDN(linkcheck.dns.rdata.Rdata):
|
||||
class ISDN(dns.rdata.Rdata):
|
||||
"""ISDN record
|
||||
|
||||
@ivar address: the ISDN address
|
||||
|
|
@ -36,10 +35,10 @@ class ISDN(linkcheck.dns.rdata.Rdata):
|
|||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
if self.subaddress:
|
||||
return '"%s" "%s"' % (linkcheck.dns.rdata._escapify(self.address),
|
||||
linkcheck.dns.rdata._escapify(self.subaddress))
|
||||
return '"%s" "%s"' % (dns.rdata._escapify(self.address),
|
||||
dns.rdata._escapify(self.subaddress))
|
||||
else:
|
||||
return '"%s"' % linkcheck.dns.rdata._escapify(self.address)
|
||||
return '"%s"' % dns.rdata._escapify(self.address)
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
address = tok.get_string()
|
||||
|
|
@ -73,8 +72,8 @@ class ISDN(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l > rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
address = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
address = wire[current : current + l].unwrap()
|
||||
current += l
|
||||
rdlen -= l
|
||||
if rdlen > 0:
|
||||
|
|
@ -82,8 +81,8 @@ class ISDN(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
subaddress = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
subaddress = wire[current : current + l].unwrap()
|
||||
else:
|
||||
subaddress = ''
|
||||
return cls(rdclass, rdtype, address, subaddress)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,11 +13,11 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
|
||||
_pows = (1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L,
|
||||
100000000L, 1000000000L, 10000000000L)
|
||||
|
|
@ -30,7 +29,7 @@ def _exponent_of(what, desc):
|
|||
exp = i - 1
|
||||
break
|
||||
if exp is None or exp < 0:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("%s value out of bounds" % desc)
|
||||
raise dns.exception.SyntaxError("%s value out of bounds" % desc)
|
||||
return exp
|
||||
|
||||
def _float_to_tuple(what):
|
||||
|
|
@ -70,13 +69,13 @@ def _encode_size(what, desc):
|
|||
def _decode_size(what, desc):
|
||||
exponent = what & 0x0F
|
||||
if exponent > 9:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("bad %s exponent" % desc)
|
||||
raise dns.exception.SyntaxError("bad %s exponent" % desc)
|
||||
base = (what & 0xF0) >> 4
|
||||
if base > 9:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("bad %s base" % desc)
|
||||
raise dns.exception.SyntaxError("bad %s base" % desc)
|
||||
return long(base) * pow(10, exponent)
|
||||
|
||||
class LOC(linkcheck.dns.rdata.Rdata):
|
||||
class LOC(dns.rdata.Rdata):
|
||||
"""LOC record
|
||||
|
||||
@ivar latitude: latitude
|
||||
|
|
@ -165,13 +164,13 @@ class LOC(linkcheck.dns.rdata.Rdata):
|
|||
if '.' in t:
|
||||
(seconds, milliseconds) = t.split('.')
|
||||
if not seconds.isdigit():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('bad latitude seconds value')
|
||||
raise dns.exception.SyntaxError('bad latitude seconds value')
|
||||
latitude[2] = int(seconds)
|
||||
if latitude[2] >= 60:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('latitude seconds >= 60')
|
||||
raise dns.exception.SyntaxError('latitude seconds >= 60')
|
||||
l = len(milliseconds)
|
||||
if l == 0 or l > 3 or not milliseconds.isdigit():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('bad latitude milliseconds value')
|
||||
raise dns.exception.SyntaxError('bad latitude milliseconds value')
|
||||
if l == 1:
|
||||
m = 100
|
||||
elif l == 2:
|
||||
|
|
@ -186,7 +185,7 @@ class LOC(linkcheck.dns.rdata.Rdata):
|
|||
if t == 'S':
|
||||
latitude[0] *= -1
|
||||
elif t != 'N':
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('bad latitude hemisphere value')
|
||||
raise dns.exception.SyntaxError('bad latitude hemisphere value')
|
||||
|
||||
longitude[0] = tok.get_int()
|
||||
t = tok.get_string()
|
||||
|
|
@ -196,13 +195,13 @@ class LOC(linkcheck.dns.rdata.Rdata):
|
|||
if '.' in t:
|
||||
(seconds, milliseconds) = t.split('.')
|
||||
if not seconds.isdigit():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('bad longitude seconds value')
|
||||
raise dns.exception.SyntaxError('bad longitude seconds value')
|
||||
longitude[2] = int(seconds)
|
||||
if longitude[2] >= 60:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('longitude seconds >= 60')
|
||||
raise dns.exception.SyntaxError('longitude seconds >= 60')
|
||||
l = len(milliseconds)
|
||||
if l == 0 or l > 3 or not milliseconds.isdigit():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('bad longitude milliseconds value')
|
||||
raise dns.exception.SyntaxError('bad longitude milliseconds value')
|
||||
if l == 1:
|
||||
m = 100
|
||||
elif l == 2:
|
||||
|
|
@ -217,31 +216,31 @@ class LOC(linkcheck.dns.rdata.Rdata):
|
|||
if t == 'W':
|
||||
longitude[0] *= -1
|
||||
elif t != 'E':
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('bad longitude hemisphere value')
|
||||
raise dns.exception.SyntaxError('bad longitude hemisphere value')
|
||||
|
||||
t = tok.get_string()
|
||||
if t[-1] == 'm':
|
||||
t = t[0 : -1]
|
||||
altitude = float(t) * 100.0 # m -> cm
|
||||
altitude = float(t) * 100.0 # m -> cm
|
||||
|
||||
token = tok.get().unescape()
|
||||
if not token.is_eol_or_eof():
|
||||
value = token.value
|
||||
if value[-1] == 'm':
|
||||
value = value[0 : -1]
|
||||
size = float(value) * 100.0 # m -> cm
|
||||
size = float(value) * 100.0 # m -> cm
|
||||
token = tok.get().unescape()
|
||||
if not token.is_eol_or_eof():
|
||||
value = token.value
|
||||
if value[-1] == 'm':
|
||||
value = value[0 : -1]
|
||||
hprec = float(value) * 100.0 # m -> cm
|
||||
hprec = float(value) * 100.0 # m -> cm
|
||||
token = tok.get().unescape()
|
||||
if not token.is_eol_or_eof():
|
||||
value = token.value
|
||||
if value[-1] == 'm':
|
||||
value = value[0 : -1]
|
||||
vprec = float(value) * 100.0 # m -> cm
|
||||
vprec = float(value) * 100.0 # m -> cm
|
||||
tok.get_eol()
|
||||
|
||||
return cls(rdclass, rdtype, latitude, longitude, altitude,
|
||||
|
|
@ -288,13 +287,13 @@ class LOC(linkcheck.dns.rdata.Rdata):
|
|||
else:
|
||||
latitude = -1 * float(0x80000000L - latitude) / 3600000
|
||||
if latitude < -90.0 or latitude > 90.0:
|
||||
raise linkcheck.dns.exception.FormError("bad latitude")
|
||||
raise dns.exception.FormError("bad latitude")
|
||||
if longitude > 0x80000000L:
|
||||
longitude = float(longitude - 0x80000000L) / 3600000
|
||||
else:
|
||||
longitude = -1 * float(0x80000000L - longitude) / 3600000
|
||||
if longitude < -180.0 or longitude > 180.0:
|
||||
raise linkcheck.dns.exception.FormError("bad longitude")
|
||||
raise dns.exception.FormError("bad longitude")
|
||||
altitude = float(altitude) - 10000000.0
|
||||
size = _decode_size(size, "size")
|
||||
hprec = _decode_size(hprec, "horizontal precision")
|
||||
|
|
@ -305,7 +304,7 @@ class LOC(linkcheck.dns.rdata.Rdata):
|
|||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f)
|
||||
wire1 = f.getvalue()
|
||||
f.seek(0)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.mxbase
|
||||
import dns.rdtypes.mxbase
|
||||
|
||||
class MX(linkcheck.dns.rdtypes.mxbase.MXBase):
|
||||
class MX(dns.rdtypes.mxbase.MXBase):
|
||||
"""MX record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.nsbase
|
||||
import dns.rdtypes.nsbase
|
||||
|
||||
class NS(linkcheck.dns.rdtypes.nsbase.NSBase):
|
||||
class NS(dns.rdtypes.nsbase.NSBase):
|
||||
"""NS record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,18 +13,18 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
import dns.name
|
||||
|
||||
class NSEC(linkcheck.dns.rdata.Rdata):
|
||||
class NSEC(dns.rdata.Rdata):
|
||||
"""NSEC record
|
||||
|
||||
@ivar next: the next name
|
||||
@type next: linkcheck.dns.name.Name object
|
||||
@type next: dns.name.Name object
|
||||
@ivar windows: the windowed bitmap list
|
||||
@type windows: list of (window number, string) tuples"""
|
||||
|
||||
|
|
@ -45,7 +44,7 @@ class NSEC(linkcheck.dns.rdata.Rdata):
|
|||
byte = ord(bitmap[i])
|
||||
for j in xrange(0, 8):
|
||||
if byte & (0x80 >> j):
|
||||
bits.append(linkcheck.dns.rdatatype.to_text(window * 256 + \
|
||||
bits.append(dns.rdatatype.to_text(window * 256 + \
|
||||
i * 8 + j))
|
||||
text += (' ' + ' '.join(bits))
|
||||
return '%s%s' % (next, text)
|
||||
|
|
@ -58,11 +57,11 @@ class NSEC(linkcheck.dns.rdata.Rdata):
|
|||
token = tok.get().unescape()
|
||||
if token.is_eol_or_eof():
|
||||
break
|
||||
nrdtype = linkcheck.dns.rdatatype.from_text(token.value)
|
||||
nrdtype = dns.rdatatype.from_text(token.value)
|
||||
if nrdtype == 0:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError, "NSEC with bit 0"
|
||||
raise dns.exception.SyntaxError("NSEC with bit 0")
|
||||
if nrdtype > 65535:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError, "NSEC with bit > 65535"
|
||||
raise dns.exception.SyntaxError("NSEC with bit > 65535")
|
||||
rdtypes.append(nrdtype)
|
||||
rdtypes.sort()
|
||||
window = 0
|
||||
|
|
@ -80,7 +79,7 @@ class NSEC(linkcheck.dns.rdata.Rdata):
|
|||
bitmap = ['\0'] * 32
|
||||
window = new_window
|
||||
offset = nrdtype % 256
|
||||
byte = offset / 8
|
||||
byte = offset // 8
|
||||
bit = offset % 8
|
||||
octets = byte + 1
|
||||
bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
|
||||
|
|
@ -97,22 +96,22 @@ class NSEC(linkcheck.dns.rdata.Rdata):
|
|||
file.write(bitmap)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
(next, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen], current)
|
||||
(next, cused) = dns.name.from_wire(wire[: current + rdlen], current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
windows = []
|
||||
while rdlen > 0:
|
||||
if rdlen < 3:
|
||||
raise linkcheck.dns.exception.FormError, "NSEC too short"
|
||||
raise dns.exception.FormError("NSEC too short")
|
||||
window = ord(wire[current])
|
||||
octets = ord(wire[current + 1])
|
||||
if octets == 0 or octets > 32:
|
||||
raise linkcheck.dns.exception.FormError, "bad NSEC octets"
|
||||
raise dns.exception.FormError("bad NSEC octets")
|
||||
current += 2
|
||||
rdlen -= 2
|
||||
if rdlen < octets:
|
||||
raise linkcheck.dns.exception.FormError, "bad NSEC bitmap length"
|
||||
bitmap = wire[current : current + octets]
|
||||
raise dns.exception.FormError("bad NSEC bitmap length")
|
||||
bitmap = wire[current : current + octets].unwrap()
|
||||
current += octets
|
||||
rdlen -= octets
|
||||
windows.append((window, bitmap))
|
||||
|
|
@ -126,17 +125,4 @@ class NSEC(linkcheck.dns.rdata.Rdata):
|
|||
self.next = self.next.choose_relativity(origin, relativize)
|
||||
|
||||
def _cmp(self, other):
|
||||
v = cmp(self.next, other.next)
|
||||
if v == 0:
|
||||
b1 = StringIO()
|
||||
for (window, bitmap) in self.windows:
|
||||
b1.write(chr(window))
|
||||
b1.write(chr(len(bitmap)))
|
||||
b1.write(bitmap)
|
||||
b2 = StringIO()
|
||||
for (window, bitmap) in other.windows:
|
||||
b2.write(chr(window))
|
||||
b2.write(chr(len(bitmap)))
|
||||
b2.write(bitmap)
|
||||
v = cmp(b1.getvalue(), b2.getvalue())
|
||||
return v
|
||||
return self._wire_cmp(other)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -18,9 +18,9 @@ import cStringIO
|
|||
import string
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
|
||||
b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV',
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
|
||||
|
|
@ -33,7 +33,7 @@ SHA1 = 1
|
|||
# flag constants
|
||||
OPTOUT = 1
|
||||
|
||||
class NSEC3(linkcheck.dns.rdata.Rdata):
|
||||
class NSEC3(dns.rdata.Rdata):
|
||||
"""NSEC3 record
|
||||
|
||||
@ivar algorithm: the hash algorithm number
|
||||
|
|
@ -74,7 +74,7 @@ class NSEC3(linkcheck.dns.rdata.Rdata):
|
|||
byte = ord(bitmap[i])
|
||||
for j in xrange(0, 8):
|
||||
if byte & (0x80 >> j):
|
||||
bits.append(linkcheck.dns.rdatatype.to_text(window * 256 + \
|
||||
bits.append(dns.rdatatype.to_text(window * 256 + \
|
||||
i * 8 + j))
|
||||
text += (' ' + ' '.join(bits))
|
||||
return '%u %u %u %s %s%s' % (self.algorithm, self.flags, self.iterations,
|
||||
|
|
@ -96,11 +96,11 @@ class NSEC3(linkcheck.dns.rdata.Rdata):
|
|||
token = tok.get().unescape()
|
||||
if token.is_eol_or_eof():
|
||||
break
|
||||
nrdtype = linkcheck.dns.rdatatype.from_text(token.value)
|
||||
nrdtype = dns.rdatatype.from_text(token.value)
|
||||
if nrdtype == 0:
|
||||
raise linkcheck.dns.exception.SyntaxError("NSEC3 with bit 0")
|
||||
raise dns.exception.SyntaxError("NSEC3 with bit 0")
|
||||
if nrdtype > 65535:
|
||||
raise linkcheck.dns.exception.SyntaxError("NSEC3 with bit > 65535")
|
||||
raise dns.exception.SyntaxError("NSEC3 with bit > 65535")
|
||||
rdtypes.append(nrdtype)
|
||||
rdtypes.sort()
|
||||
window = 0
|
||||
|
|
@ -118,7 +118,7 @@ class NSEC3(linkcheck.dns.rdata.Rdata):
|
|||
bitmap = ['\0'] * 32
|
||||
window = new_window
|
||||
offset = nrdtype % 256
|
||||
byte = offset / 8
|
||||
byte = offset // 8
|
||||
bit = offset % 8
|
||||
octets = byte + 1
|
||||
bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
|
||||
|
|
@ -145,28 +145,28 @@ class NSEC3(linkcheck.dns.rdata.Rdata):
|
|||
wire[current : current + 5])
|
||||
current += 5
|
||||
rdlen -= 5
|
||||
salt = wire[current : current + slen]
|
||||
salt = wire[current : current + slen].unwrap()
|
||||
current += slen
|
||||
rdlen -= slen
|
||||
(nlen, ) = struct.unpack('!B', wire[current])
|
||||
current += 1
|
||||
rdlen -= 1
|
||||
next = wire[current : current + nlen]
|
||||
next = wire[current : current + nlen].unwrap()
|
||||
current += nlen
|
||||
rdlen -= nlen
|
||||
windows = []
|
||||
while rdlen > 0:
|
||||
if rdlen < 3:
|
||||
raise linkcheck.dns.exception.FormError("NSEC3 too short")
|
||||
raise dns.exception.FormError("NSEC3 too short")
|
||||
window = ord(wire[current])
|
||||
octets = ord(wire[current + 1])
|
||||
if octets == 0 or octets > 32:
|
||||
raise linkcheck.dns.exception.FormError("bad NSEC3 octets")
|
||||
raise dns.exception.FormError("bad NSEC3 octets")
|
||||
current += 2
|
||||
rdlen -= 2
|
||||
if rdlen < octets:
|
||||
raise linkcheck.dns.exception.FormError("bad NSEC3 bitmap length")
|
||||
bitmap = wire[current : current + octets]
|
||||
raise dns.exception.FormError("bad NSEC3 bitmap length")
|
||||
bitmap = wire[current : current + octets].unwrap()
|
||||
current += octets
|
||||
rdlen -= octets
|
||||
windows.append((window, bitmap))
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,10 +16,10 @@
|
|||
import cStringIO
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
|
||||
class NSEC3PARAM(linkcheck.dns.rdata.Rdata):
|
||||
class NSEC3PARAM(dns.rdata.Rdata):
|
||||
"""NSEC3PARAM record
|
||||
|
||||
@ivar algorithm: the hash algorithm number
|
||||
|
|
@ -71,11 +71,11 @@ class NSEC3PARAM(linkcheck.dns.rdata.Rdata):
|
|||
wire[current : current + 5])
|
||||
current += 5
|
||||
rdlen -= 5
|
||||
salt = wire[current : current + slen]
|
||||
salt = wire[current : current + slen].unwrap()
|
||||
current += slen
|
||||
rdlen -= slen
|
||||
if rdlen != 0:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.nsbase
|
||||
import dns.rdtypes.nsbase
|
||||
|
||||
class PTR(linkcheck.dns.rdtypes.nsbase.NSBase):
|
||||
class PTR(dns.rdtypes.nsbase.NSBase):
|
||||
"""PTR record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,18 +13,18 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.name
|
||||
|
||||
class RP(linkcheck.dns.rdata.Rdata):
|
||||
class RP(dns.rdata.Rdata):
|
||||
"""RP record
|
||||
|
||||
@ivar mbox: The responsible person's mailbox
|
||||
@type mbox: linkcheck.dns.name.Name object
|
||||
@type mbox: dns.name.Name object
|
||||
@ivar txt: The owner name of a node with TXT records, or the root name
|
||||
if no TXT records are associated with this RP.
|
||||
@type txt: linkcheck.dns.name.Name object
|
||||
@type txt: dns.name.Name object
|
||||
@see: RFC 1183"""
|
||||
|
||||
__slots__ = ['mbox', 'txt']
|
||||
|
|
@ -59,16 +58,16 @@ class RP(linkcheck.dns.rdata.Rdata):
|
|||
self.txt.to_digestable(origin)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
(mbox, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(mbox, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
if rdlen <= 0:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
(txt, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
raise dns.exception.FormError
|
||||
(txt, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not origin is None:
|
||||
mbox = mbox.relativize(origin)
|
||||
txt = txt.relativize(origin)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -18,12 +17,12 @@ import calendar
|
|||
import struct
|
||||
import time
|
||||
|
||||
import linkcheck.dns.dnssec
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.dnssec
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
|
||||
class BadSigTime(linkcheck.dns.exception.DNSException):
|
||||
class BadSigTime(dns.exception.DNSException):
|
||||
"""Raised when a SIG or RRSIG RR's time cannot be parsed."""
|
||||
pass
|
||||
|
||||
|
|
@ -42,8 +41,8 @@ def sigtime_to_posixtime(what):
|
|||
def posixtime_to_sigtime(what):
|
||||
return time.strftime('%Y%m%d%H%M%S', time.gmtime(what))
|
||||
|
||||
class SIGBase(linkcheck.dns.rdata.Rdata):
|
||||
"""SIG-like record base
|
||||
class RRSIG(dns.rdata.Rdata):
|
||||
"""RRSIG record
|
||||
|
||||
@ivar type_covered: the rdata type this signature covers
|
||||
@type type_covered: int
|
||||
|
|
@ -60,7 +59,7 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
@ivar key_tag: the key tag
|
||||
@type key_tag: int
|
||||
@ivar signer: the signer
|
||||
@type signer: linkcheck.dns.name.Name object
|
||||
@type signer: dns.name.Name object
|
||||
@ivar signature: the signature
|
||||
@type signature: string"""
|
||||
|
||||
|
|
@ -71,7 +70,7 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
def __init__(self, rdclass, rdtype, type_covered, algorithm, labels,
|
||||
original_ttl, expiration, inception, key_tag, signer,
|
||||
signature):
|
||||
super(SIGBase, self).__init__(rdclass, rdtype)
|
||||
super(RRSIG, self).__init__(rdclass, rdtype)
|
||||
self.type_covered = type_covered
|
||||
self.algorithm = algorithm
|
||||
self.labels = labels
|
||||
|
|
@ -87,7 +86,7 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return '%s %d %d %d %s %s %d %s %s' % (
|
||||
linkcheck.dns.rdatatype.to_text(self.type_covered),
|
||||
dns.rdatatype.to_text(self.type_covered),
|
||||
self.algorithm,
|
||||
self.labels,
|
||||
self.original_ttl,
|
||||
|
|
@ -95,12 +94,12 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
posixtime_to_sigtime(self.inception),
|
||||
self.key_tag,
|
||||
self.signer,
|
||||
linkcheck.dns.rdata._base64ify(self.signature)
|
||||
dns.rdata._base64ify(self.signature)
|
||||
)
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
type_covered = linkcheck.dns.rdatatype.from_text(tok.get_string())
|
||||
algorithm = linkcheck.dns.dnssec.algorithm_from_text(tok.get_string())
|
||||
type_covered = dns.rdatatype.from_text(tok.get_string())
|
||||
algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
|
||||
labels = tok.get_int()
|
||||
original_ttl = tok.get_ttl()
|
||||
expiration = sigtime_to_posixtime(tok.get_string())
|
||||
|
|
@ -114,7 +113,7 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
if t.is_eol_or_eof():
|
||||
break
|
||||
if not t.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
chunks.append(t.value)
|
||||
b64 = ''.join(chunks)
|
||||
signature = b64.decode('base64_codec')
|
||||
|
|
@ -137,12 +136,12 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
header = struct.unpack('!HBBIIIH', wire[current : current + 18])
|
||||
current += 18
|
||||
rdlen -= 18
|
||||
(signer, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen], current)
|
||||
(signer, cused) = dns.name.from_wire(wire[: current + rdlen], current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
if not origin is None:
|
||||
signer = signer.relativize(origin)
|
||||
signature = wire[current : current + rdlen]
|
||||
signature = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, header[0], header[1], header[2],
|
||||
header[3], header[4], header[5], header[6], signer,
|
||||
signature)
|
||||
|
|
@ -153,17 +152,5 @@ class SIGBase(linkcheck.dns.rdata.Rdata):
|
|||
self.signer = self.signer.choose_relativity(origin, relativize)
|
||||
|
||||
def _cmp(self, other):
|
||||
hs = struct.pack('!HBBIIIH', self.type_covered,
|
||||
self.algorithm, self.labels,
|
||||
self.original_ttl, self.expiration,
|
||||
self.inception, self.key_tag)
|
||||
ho = struct.pack('!HBBIIIH', other.type_covered,
|
||||
other.algorithm, other.labels,
|
||||
other.original_ttl, other.expiration,
|
||||
other.inception, other.key_tag)
|
||||
v = cmp(hs, ho)
|
||||
if v == 0:
|
||||
v = cmp(self.signer, other.signer)
|
||||
if v == 0:
|
||||
v = cmp(self.signature, other.signature)
|
||||
return v
|
||||
return self._wire_cmp(other)
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.mxbase
|
||||
import dns.rdtypes.mxbase
|
||||
|
||||
class RT(linkcheck.dns.rdtypes.mxbase.UncompressedDowncasingMX):
|
||||
class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX):
|
||||
"""RT record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,25 +15,25 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.name
|
||||
|
||||
class SOA(linkcheck.dns.rdata.Rdata):
|
||||
class SOA(dns.rdata.Rdata):
|
||||
"""SOA record
|
||||
|
||||
@ivar mname: the SOA MNAME (master name) field
|
||||
@type mname: linkcheck.dns.name.Name object
|
||||
@type mname: dns.name.Name object
|
||||
@ivar rname: the SOA RNAME (responsible name) field
|
||||
@type rname: linkcheck.dns.name.Name object
|
||||
@type rname: dns.name.Name object
|
||||
@ivar serial: The zone's serial number
|
||||
@type serial: int
|
||||
@ivar refresh: The zone's refresh value (in seconds)
|
||||
@type refresh: int
|
||||
@ivar retry: The zone's retry value (in seconds)
|
||||
@type retry: int
|
||||
@ivar expiration: The zone's expiration value (in seconds)
|
||||
@type expiration: int
|
||||
@ivar expire: The zone's expiration value (in seconds)
|
||||
@type expire: int
|
||||
@ivar minimum: The zone's negative caching time (in seconds, called
|
||||
"minimum" for historical reasons)
|
||||
@type minimum: int
|
||||
|
|
@ -91,14 +90,14 @@ class SOA(linkcheck.dns.rdata.Rdata):
|
|||
self.retry, self.expire, self.minimum)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
(mname, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen], current)
|
||||
(mname, cused) = dns.name.from_wire(wire[: current + rdlen], current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
(rname, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen], current)
|
||||
(rname, cused) = dns.name.from_wire(wire[: current + rdlen], current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
if rdlen != 20:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
five_ints = struct.unpack('!IIIII',
|
||||
wire[current : current + rdlen])
|
||||
if not origin is None:
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -13,9 +13,9 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.txtbase
|
||||
import dns.rdtypes.txtbase
|
||||
|
||||
class SPF(linkcheck.dns.rdtypes.txtbase.TXTBase):
|
||||
class SPF(dns.rdtypes.txtbase.TXTBase):
|
||||
"""SPF record
|
||||
|
||||
@see: RFC 4408"""
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2005-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,10 +15,10 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
|
||||
class SSHFP(linkcheck.dns.rdata.Rdata):
|
||||
class SSHFP(dns.rdata.Rdata):
|
||||
"""SSHFP record
|
||||
|
||||
@ivar algorithm: the algorithm
|
||||
|
|
@ -42,7 +41,7 @@ class SSHFP(linkcheck.dns.rdata.Rdata):
|
|||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return '%d %d %s' % (self.algorithm,
|
||||
self.fp_type,
|
||||
linkcheck.dns.rdata._hexify(self.fingerprint,
|
||||
dns.rdata._hexify(self.fingerprint,
|
||||
chunksize=128))
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
|
|
@ -64,7 +63,7 @@ class SSHFP(linkcheck.dns.rdata.Rdata):
|
|||
header = struct.unpack("!BB", wire[current : current + 2])
|
||||
current += 2
|
||||
rdlen -= 2
|
||||
fingerprint = wire[current : current + rdlen]
|
||||
fingerprint = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, header[0], header[1], fingerprint)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.txtbase
|
||||
import dns.rdtypes.txtbase
|
||||
|
||||
class TXT(linkcheck.dns.rdtypes.txtbase.TXTBase):
|
||||
class TXT(dns.rdtypes.txtbase.TXTBase):
|
||||
"""TXT record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,11 +13,11 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class X25(linkcheck.dns.rdata.Rdata):
|
||||
class X25(dns.rdata.Rdata):
|
||||
"""X25 record
|
||||
|
||||
@ivar address: the PSDN address
|
||||
|
|
@ -32,7 +31,7 @@ class X25(linkcheck.dns.rdata.Rdata):
|
|||
self.address = address
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return '"%s"' % linkcheck.dns.rdata._escapify(self.address)
|
||||
return '"%s"' % dns.rdata._escapify(self.address)
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
address = tok.get_string()
|
||||
|
|
@ -53,8 +52,8 @@ class X25(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
address = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
address = wire[current : current + l].unwrap()
|
||||
return cls(rdclass, rdtype, address)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -28,19 +27,16 @@ __all__ = [
|
|||
'HINFO',
|
||||
'HIP',
|
||||
'ISDN',
|
||||
'KEY',
|
||||
'LOC',
|
||||
'MX',
|
||||
'NS',
|
||||
'NSEC',
|
||||
'NSEC3',
|
||||
'NSEC3PARAM',
|
||||
'NXT',
|
||||
'PTR',
|
||||
'RP',
|
||||
'RRSIG',
|
||||
'RT',
|
||||
'SIG',
|
||||
'SOA',
|
||||
'SPF',
|
||||
'SSHFP',
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,12 +13,12 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.ipv4
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.ipv4
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class A(linkcheck.dns.rdata.Rdata):
|
||||
class A(dns.rdata.Rdata):
|
||||
"""A record.
|
||||
|
||||
@ivar address: an IPv4 address
|
||||
|
|
@ -30,7 +29,7 @@ class A(linkcheck.dns.rdata.Rdata):
|
|||
def __init__(self, rdclass, rdtype, address):
|
||||
super(A, self).__init__(rdclass, rdtype)
|
||||
# check that it's OK
|
||||
junk = linkcheck.dns.ipv4.inet_aton(address)
|
||||
junk = dns.ipv4.inet_aton(address)
|
||||
self.address = address
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
|
|
@ -44,15 +43,15 @@ class A(linkcheck.dns.rdata.Rdata):
|
|||
from_text = classmethod(from_text)
|
||||
|
||||
def to_wire(self, file, compress = None, origin = None):
|
||||
file.write(linkcheck.dns.ipv4.inet_aton(self.address))
|
||||
file.write(dns.ipv4.inet_aton(self.address))
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
address = linkcheck.dns.ipv4.inet_ntoa(wire[current : current + rdlen])
|
||||
address = dns.ipv4.inet_ntoa(wire[current : current + rdlen])
|
||||
return cls(rdclass, rdtype, address)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
sa = linkcheck.dns.ipv4.inet_aton(self.address)
|
||||
oa = linkcheck.dns.ipv4.inet_aton(other.address)
|
||||
sa = dns.ipv4.inet_aton(self.address)
|
||||
oa = dns.ipv4.inet_aton(other.address)
|
||||
return cmp(sa, oa)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,12 +13,12 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.inet
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.inet
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class AAAA(linkcheck.dns.rdata.Rdata):
|
||||
class AAAA(dns.rdata.Rdata):
|
||||
"""AAAA record.
|
||||
|
||||
@ivar address: an IPv6 address
|
||||
|
|
@ -30,7 +29,7 @@ class AAAA(linkcheck.dns.rdata.Rdata):
|
|||
def __init__(self, rdclass, rdtype, address):
|
||||
super(AAAA, self).__init__(rdclass, rdtype)
|
||||
# check that it's OK
|
||||
junk = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, address)
|
||||
junk = dns.inet.inet_pton(dns.inet.AF_INET6, address)
|
||||
self.address = address
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
|
|
@ -44,16 +43,16 @@ class AAAA(linkcheck.dns.rdata.Rdata):
|
|||
from_text = classmethod(from_text)
|
||||
|
||||
def to_wire(self, file, compress = None, origin = None):
|
||||
file.write(linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, self.address))
|
||||
file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.address))
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
address = linkcheck.dns.inet.inet_ntop(linkcheck.dns.inet.AF_INET6,
|
||||
address = dns.inet.inet_ntop(dns.inet.AF_INET6,
|
||||
wire[current : current + rdlen])
|
||||
return cls(rdclass, rdtype, address)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
sa = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, self.address)
|
||||
oa = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, other.address)
|
||||
sa = dns.inet.inet_pton(dns.inet.AF_INET6, self.address)
|
||||
oa = dns.inet.inet_pton(dns.inet.AF_INET6, other.address)
|
||||
return cmp(sa, oa)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,13 +13,13 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.inet
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.inet
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class APLItem(object):
|
||||
"""An APL list item.
|
||||
|
|
@ -51,9 +50,9 @@ class APLItem(object):
|
|||
|
||||
def to_wire(self, file):
|
||||
if self.family == 1:
|
||||
address = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET, self.address)
|
||||
address = dns.inet.inet_pton(dns.inet.AF_INET, self.address)
|
||||
elif self.family == 2:
|
||||
address = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, self.address)
|
||||
address = dns.inet.inet_pton(dns.inet.AF_INET6, self.address)
|
||||
else:
|
||||
address = self.address.decode('hex_codec')
|
||||
#
|
||||
|
|
@ -73,7 +72,7 @@ class APLItem(object):
|
|||
file.write(header)
|
||||
file.write(address)
|
||||
|
||||
class APL(linkcheck.dns.rdata.Rdata):
|
||||
class APL(dns.rdata.Rdata):
|
||||
"""APL record.
|
||||
|
||||
@ivar items: a list of APL items
|
||||
|
|
@ -120,7 +119,7 @@ class APL(linkcheck.dns.rdata.Rdata):
|
|||
items = []
|
||||
while 1:
|
||||
if rdlen < 4:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
header = struct.unpack('!HBB', wire[current : current + 4])
|
||||
afdlen = header[2]
|
||||
if afdlen > 127:
|
||||
|
|
@ -131,17 +130,17 @@ class APL(linkcheck.dns.rdata.Rdata):
|
|||
current += 4
|
||||
rdlen -= 4
|
||||
if rdlen < afdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
address = wire[current : current + afdlen]
|
||||
raise dns.exception.FormError
|
||||
address = wire[current : current + afdlen].unwrap()
|
||||
l = len(address)
|
||||
if header[0] == 1:
|
||||
if l < 4:
|
||||
address += '\x00' * (4 - l)
|
||||
address = linkcheck.dns.inet.inet_ntop(linkcheck.dns.inet.AF_INET, address)
|
||||
address = dns.inet.inet_ntop(dns.inet.AF_INET, address)
|
||||
elif header[0] == 2:
|
||||
if l < 16:
|
||||
address += '\x00' * (16 - l)
|
||||
address = linkcheck.dns.inet.inet_ntop(linkcheck.dns.inet.AF_INET6, address)
|
||||
address = dns.inet.inet_ntop(dns.inet.AF_INET6, address)
|
||||
else:
|
||||
#
|
||||
# This isn't really right according to the RFC, but it
|
||||
|
|
@ -159,7 +158,7 @@ class APL(linkcheck.dns.rdata.Rdata):
|
|||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f)
|
||||
wire1 = f.getvalue()
|
||||
f.seek(0)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,9 +13,9 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import dns.exception
|
||||
|
||||
class DHCID(linkcheck.dns.rdata.Rdata):
|
||||
class DHCID(dns.rdata.Rdata):
|
||||
"""DHCID record
|
||||
|
||||
@ivar data: the data (the content of the RR is opaque as far as the
|
||||
|
|
@ -31,7 +30,7 @@ class DHCID(linkcheck.dns.rdata.Rdata):
|
|||
self.data = data
|
||||
|
||||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return linkcheck.dns.rdata._base64ify(self.data)
|
||||
return dns.rdata._base64ify(self.data)
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
chunks = []
|
||||
|
|
@ -40,7 +39,7 @@ class DHCID(linkcheck.dns.rdata.Rdata):
|
|||
if t.is_eol_or_eof():
|
||||
break
|
||||
if not t.is_identifier():
|
||||
raise linkcheck.dns.exception.SyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
chunks.append(t.value)
|
||||
b64 = ''.join(chunks)
|
||||
data = b64.decode('base64_codec')
|
||||
|
|
@ -52,7 +51,7 @@ class DHCID(linkcheck.dns.rdata.Rdata):
|
|||
file.write(self.data)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
data = wire[current : current + rdlen]
|
||||
data = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, data)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,14 +13,14 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.inet
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.inet
|
||||
import dns.name
|
||||
|
||||
class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
||||
class IPSECKEY(dns.rdata.Rdata):
|
||||
"""IPSECKEY record
|
||||
|
||||
@ivar precedence: the precedence for this key data
|
||||
|
|
@ -47,10 +46,10 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
gateway = None
|
||||
elif gateway_type == 1:
|
||||
# check that it's OK
|
||||
junk = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET, gateway)
|
||||
junk = dns.inet.inet_pton(dns.inet.AF_INET, gateway)
|
||||
elif gateway_type == 2:
|
||||
# check that it's OK
|
||||
junk = linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, gateway)
|
||||
junk = dns.inet.inet_pton(dns.inet.AF_INET6, gateway)
|
||||
elif gateway_type == 3:
|
||||
pass
|
||||
else:
|
||||
|
|
@ -74,7 +73,7 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
raise ValueError('invalid gateway type')
|
||||
return '%d %d %d %s %s' % (self.precedence, self.gateway_type,
|
||||
self.algorithm, gateway,
|
||||
linkcheck.dns.rdata._base64ify(self.key))
|
||||
dns.rdata._base64ify(self.key))
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
precedence = tok.get_uint8()
|
||||
|
|
@ -90,7 +89,7 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
if t.is_eol_or_eof():
|
||||
break
|
||||
if not t.is_identifier():
|
||||
raise linkcheck.dns.exception.SyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
chunks.append(t.value)
|
||||
b64 = ''.join(chunks)
|
||||
key = b64.decode('base64_codec')
|
||||
|
|
@ -106,9 +105,9 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
if self.gateway_type == 0:
|
||||
pass
|
||||
elif self.gateway_type == 1:
|
||||
file.write(linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET, self.gateway))
|
||||
file.write(dns.inet.inet_pton(dns.inet.AF_INET, self.gateway))
|
||||
elif self.gateway_type == 2:
|
||||
file.write(linkcheck.dns.inet.inet_pton(linkcheck.dns.inet.AF_INET6, self.gateway))
|
||||
file.write(dns.inet.inet_pton(dns.inet.AF_INET6, self.gateway))
|
||||
elif self.gateway_type == 3:
|
||||
self.gateway.to_wire(file, None, origin)
|
||||
else:
|
||||
|
|
@ -117,7 +116,7 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
if rdlen < 3:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
header = struct.unpack('!BBB', wire[current : current + 3])
|
||||
gateway_type = header[1]
|
||||
current += 3
|
||||
|
|
@ -125,30 +124,30 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
if gateway_type == 0:
|
||||
gateway = None
|
||||
elif gateway_type == 1:
|
||||
gateway = linkcheck.dns.inet.inet_ntop(linkcheck.dns.inet.AF_INET,
|
||||
gateway = dns.inet.inet_ntop(dns.inet.AF_INET,
|
||||
wire[current : current + 4])
|
||||
current += 4
|
||||
rdlen -= 4
|
||||
elif gateway_type == 2:
|
||||
gateway = linkcheck.dns.inet.inet_ntop(linkcheck.dns.inet.AF_INET6,
|
||||
gateway = dns.inet.inet_ntop(dns.inet.AF_INET6,
|
||||
wire[current : current + 16])
|
||||
current += 16
|
||||
rdlen -= 16
|
||||
elif gateway_type == 3:
|
||||
(gateway, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(gateway, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
else:
|
||||
raise linkcheck.dns.exception.FormError('invalid IPSECKEY gateway type')
|
||||
key = wire[current : current + rdlen]
|
||||
raise dns.exception.FormError('invalid IPSECKEY gateway type')
|
||||
key = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, header[0], gateway_type, header[2],
|
||||
gateway, key)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f)
|
||||
wire1 = f.getvalue()
|
||||
f.seek(0)
|
||||
|
|
@ -156,4 +155,5 @@ class IPSECKEY(linkcheck.dns.rdata.Rdata):
|
|||
other.to_wire(f)
|
||||
wire2 = f.getvalue()
|
||||
f.close()
|
||||
|
||||
return cmp(wire1, wire2)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.mxbase
|
||||
import dns.rdtypes.mxbase
|
||||
|
||||
class KX(linkcheck.dns.rdtypes.mxbase.UncompressedMX):
|
||||
class KX(dns.rdtypes.mxbase.UncompressedMX):
|
||||
"""KX record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,9 +15,9 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.rdata
|
||||
import dns.exception
|
||||
import dns.name
|
||||
import dns.rdata
|
||||
|
||||
def _write_string(file, s):
|
||||
l = len(s)
|
||||
|
|
@ -27,7 +26,7 @@ def _write_string(file, s):
|
|||
file.write(byte)
|
||||
file.write(s)
|
||||
|
||||
class NAPTR(linkcheck.dns.rdata.Rdata):
|
||||
class NAPTR(dns.rdata.Rdata):
|
||||
"""NAPTR record
|
||||
|
||||
@ivar order: order
|
||||
|
|
@ -41,7 +40,7 @@ class NAPTR(linkcheck.dns.rdata.Rdata):
|
|||
@ivar regexp: regular expression
|
||||
@type regexp: string
|
||||
@ivar replacement: replacement name
|
||||
@type replacement: linkcheck.dns.name.Name object
|
||||
@type replacement: dns.name.Name object
|
||||
@see: RFC 3403"""
|
||||
|
||||
__slots__ = ['order', 'preference', 'flags', 'service', 'regexp',
|
||||
|
|
@ -61,9 +60,9 @@ class NAPTR(linkcheck.dns.rdata.Rdata):
|
|||
replacement = self.replacement.choose_relativity(origin, relativize)
|
||||
return '%d %d "%s" "%s" "%s" %s' % \
|
||||
(self.order, self.preference,
|
||||
linkcheck.dns.rdata._escapify(self.flags),
|
||||
linkcheck.dns.rdata._escapify(self.service),
|
||||
linkcheck.dns.rdata._escapify(self.regexp),
|
||||
dns.rdata._escapify(self.flags),
|
||||
dns.rdata._escapify(self.service),
|
||||
dns.rdata._escapify(self.regexp),
|
||||
self.replacement)
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
|
|
@ -98,15 +97,15 @@ class NAPTR(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l > rdlen or rdlen < 0:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
s = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
s = wire[current : current + l].unwrap()
|
||||
current += l
|
||||
rdlen -= l
|
||||
strings.append(s)
|
||||
(replacement, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(replacement, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not origin is None:
|
||||
replacement = replacement.relativize(origin)
|
||||
return cls(rdclass, rdtype, order, preference, strings[0], strings[1],
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,11 +13,11 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class NSAP(linkcheck.dns.rdata.Rdata):
|
||||
class NSAP(dns.rdata.Rdata):
|
||||
"""NSAP record.
|
||||
|
||||
@ivar address: a NASP
|
||||
|
|
@ -38,10 +37,10 @@ class NSAP(linkcheck.dns.rdata.Rdata):
|
|||
address = tok.get_string()
|
||||
t = tok.get_eol()
|
||||
if address[0:2] != '0x':
|
||||
raise linkcheck.dns.exception.DNSSyntaxError, 'string does not start with 0x'
|
||||
raise dns.exception.SyntaxError('string does not start with 0x')
|
||||
address = address[2:].replace('.', '')
|
||||
if len(address) % 2 != 0:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError, 'hexstring has odd length'
|
||||
raise dns.exception.SyntaxError('hexstring has odd length')
|
||||
address = address.decode('hex_codec')
|
||||
return cls(rdclass, rdtype, address)
|
||||
|
||||
|
|
@ -51,7 +50,7 @@ class NSAP(linkcheck.dns.rdata.Rdata):
|
|||
file.write(self.address)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
address = wire[current : current + rdlen]
|
||||
address = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, address)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -14,8 +13,8 @@
|
|||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import linkcheck.dns.rdtypes.nsbase
|
||||
import dns.rdtypes.nsbase
|
||||
|
||||
class NSAP_PTR(linkcheck.dns.rdtypes.nsbase.UncompressedNS):
|
||||
class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS):
|
||||
"""NSAP-PTR record"""
|
||||
pass
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,19 +15,19 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.name
|
||||
|
||||
class PX(linkcheck.dns.rdata.Rdata):
|
||||
class PX(dns.rdata.Rdata):
|
||||
"""PX record.
|
||||
|
||||
@ivar preference: the preference value
|
||||
@type preference: int
|
||||
@ivar map822: the map822 name
|
||||
@type map822: linkcheck.dns.name.Name object
|
||||
@type map822: dns.name.Name object
|
||||
@ivar mapx400: the mapx400 name
|
||||
@type mapx400: linkcheck.dns.name.Name object
|
||||
@type mapx400: dns.name.Name object
|
||||
@see: RFC 2163"""
|
||||
|
||||
__slots__ = ['preference', 'map822', 'mapx400']
|
||||
|
|
@ -65,18 +64,18 @@ class PX(linkcheck.dns.rdata.Rdata):
|
|||
(preference, ) = struct.unpack('!H', wire[current : current + 2])
|
||||
current += 2
|
||||
rdlen -= 2
|
||||
(map822, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(map822, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused > rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
current += cused
|
||||
rdlen -= cused
|
||||
if not origin is None:
|
||||
map822 = map822.relativize(origin)
|
||||
(mapx400, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(mapx400, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not origin is None:
|
||||
mapx400 = mapx400.relativize(origin)
|
||||
return cls(rdclass, rdtype, preference, map822, mapx400)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,11 +15,11 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.name
|
||||
|
||||
class SRV(linkcheck.dns.rdata.Rdata):
|
||||
class SRV(dns.rdata.Rdata):
|
||||
"""SRV record
|
||||
|
||||
@ivar priority: the priority
|
||||
|
|
@ -30,7 +29,7 @@ class SRV(linkcheck.dns.rdata.Rdata):
|
|||
@ivar port: the port of the service
|
||||
@type port: int
|
||||
@ivar target: the target host
|
||||
@type target: linkcheck.dns.name.Name object
|
||||
@type target: dns.name.Name object
|
||||
@see: RFC 2782"""
|
||||
|
||||
__slots__ = ['priority', 'weight', 'port', 'target']
|
||||
|
|
@ -68,10 +67,10 @@ class SRV(linkcheck.dns.rdata.Rdata):
|
|||
wire[current : current + 6])
|
||||
current += 6
|
||||
rdlen -= 6
|
||||
(target, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(target, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not origin is None:
|
||||
target = target.relativize(origin)
|
||||
return cls(rdclass, rdtype, priority, weight, port, target)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -17,13 +16,13 @@
|
|||
import socket
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.ipv4
|
||||
import linkcheck.dns.rdata
|
||||
import dns.ipv4
|
||||
import dns.rdata
|
||||
|
||||
_proto_tcp = socket.getprotobyname('tcp')
|
||||
_proto_udp = socket.getprotobyname('udp')
|
||||
|
||||
class WKS(linkcheck.dns.rdata.Rdata):
|
||||
class WKS(dns.rdata.Rdata):
|
||||
"""WKS record
|
||||
|
||||
@ivar address: the address
|
||||
|
|
@ -80,30 +79,30 @@ class WKS(linkcheck.dns.rdata.Rdata):
|
|||
for j in xrange(l, i + 1):
|
||||
bitmap.append('\x00')
|
||||
bitmap[i] = chr(ord(bitmap[i]) | (0x80 >> (serv % 8)))
|
||||
bitmap = linkcheck.dns.rdata._truncate_bitmap(bitmap)
|
||||
bitmap = dns.rdata._truncate_bitmap(bitmap)
|
||||
return cls(rdclass, rdtype, address, protocol, bitmap)
|
||||
|
||||
from_text = classmethod(from_text)
|
||||
|
||||
def to_wire(self, file, compress = None, origin = None):
|
||||
file.write(linkcheck.dns.ipv4.inet_aton(self.address))
|
||||
file.write(dns.ipv4.inet_aton(self.address))
|
||||
protocol = struct.pack('!B', self.protocol)
|
||||
file.write(protocol)
|
||||
file.write(self.bitmap)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
address = linkcheck.dns.ipv4.inet_ntoa(wire[current : current + 4])
|
||||
address = dns.ipv4.inet_ntoa(wire[current : current + 4])
|
||||
protocol, = struct.unpack('!B', wire[current + 4 : current + 5])
|
||||
current += 5
|
||||
rdlen -= 5
|
||||
bitmap = wire[current : current + rdlen]
|
||||
bitmap = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, address, protocol, bitmap)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
||||
def _cmp(self, other):
|
||||
sa = linkcheck.dns.ipv4.inet_aton(self.address)
|
||||
oa = linkcheck.dns.ipv4.inet_aton(other.address)
|
||||
sa = dns.ipv4.inet_aton(self.address)
|
||||
oa = dns.ipv4.inet_aton(other.address)
|
||||
v = cmp(sa, oa)
|
||||
if v == 0:
|
||||
sp = struct.pack('!B', self.protocol)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -21,6 +20,4 @@ __all__ = [
|
|||
'IN',
|
||||
'mxbase',
|
||||
'nsbase',
|
||||
'sigbase',
|
||||
'keybase',
|
||||
]
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2010 Nominum, Inc.
|
||||
# Copyright (C) 2010, 2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -15,10 +15,10 @@
|
|||
|
||||
import struct
|
||||
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.rdata
|
||||
import dns.rdatatype
|
||||
|
||||
class DSBase(linkcheck.dns.rdata.Rdata):
|
||||
class DSBase(dns.rdata.Rdata):
|
||||
"""Base class for rdata that is like a DS record
|
||||
|
||||
@ivar key_tag: the key tag
|
||||
|
|
@ -44,7 +44,7 @@ class DSBase(linkcheck.dns.rdata.Rdata):
|
|||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
return '%d %d %d %s' % (self.key_tag, self.algorithm,
|
||||
self.digest_type,
|
||||
linkcheck.dns.rdata._hexify(self.digest,
|
||||
dns.rdata._hexify(self.digest,
|
||||
chunksize=128))
|
||||
|
||||
def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
|
||||
|
|
@ -57,7 +57,7 @@ class DSBase(linkcheck.dns.rdata.Rdata):
|
|||
if t.is_eol_or_eof():
|
||||
break
|
||||
if not t.is_identifier():
|
||||
raise linkcheck.dns.exception.SyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
chunks.append(t.value)
|
||||
digest = ''.join(chunks)
|
||||
digest = digest.decode('hex_codec')
|
||||
|
|
@ -76,7 +76,7 @@ class DSBase(linkcheck.dns.rdata.Rdata):
|
|||
header = struct.unpack("!HBB", wire[current : current + 4])
|
||||
current += 4
|
||||
rdlen -= 4
|
||||
digest = wire[current : current + rdlen]
|
||||
digest = wire[current : current + rdlen].unwrap()
|
||||
return cls(rdclass, rdtype, header[0], header[1], header[2], digest)
|
||||
|
||||
from_wire = classmethod(from_wire)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,20 +15,20 @@
|
|||
|
||||
"""MX-like base classes."""
|
||||
|
||||
import cStringIO
|
||||
import struct
|
||||
from cStringIO import StringIO
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.name
|
||||
|
||||
class MXBase(linkcheck.dns.rdata.Rdata):
|
||||
class MXBase(dns.rdata.Rdata):
|
||||
"""Base class for rdata that is like an MX record.
|
||||
|
||||
@ivar preference: the preference value
|
||||
@type preference: int
|
||||
@ivar exchange: the exchange name
|
||||
@type exchange: linkcheck.dns.name.Name object"""
|
||||
@type exchange: dns.name.Name object"""
|
||||
|
||||
__slots__ = ['preference', 'exchange']
|
||||
|
||||
|
|
@ -64,10 +63,10 @@ class MXBase(linkcheck.dns.rdata.Rdata):
|
|||
(preference, ) = struct.unpack('!H', wire[current : current + 2])
|
||||
current += 2
|
||||
rdlen -= 2
|
||||
(exchange, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(exchange, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not origin is None:
|
||||
exchange = exchange.relativize(origin)
|
||||
return cls(rdclass, rdtype, preference, exchange)
|
||||
|
|
@ -87,14 +86,14 @@ class MXBase(linkcheck.dns.rdata.Rdata):
|
|||
|
||||
class UncompressedMX(MXBase):
|
||||
"""Base class for rdata that is like an MX record, but whose name
|
||||
is not compressed when convert to DNS wire format, and whose
|
||||
is not compressed when converted to DNS wire format, and whose
|
||||
digestable form is not downcased."""
|
||||
|
||||
def to_wire(self, file, compress = None, origin = None):
|
||||
super(UncompressedMX, self).to_wire(file, None, origin)
|
||||
|
||||
def to_digestable(self, origin = None):
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f, None, origin)
|
||||
return f.getvalue()
|
||||
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,17 +15,17 @@
|
|||
|
||||
"""NS-like base classes."""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.name
|
||||
|
||||
class NSBase(linkcheck.dns.rdata.Rdata):
|
||||
class NSBase(dns.rdata.Rdata):
|
||||
"""Base class for rdata that is like an NS record.
|
||||
|
||||
@ivar target: the target name of the rdata
|
||||
@type target: linkcheck.dns.name.Name object"""
|
||||
@type target: dns.name.Name object"""
|
||||
|
||||
__slots__ = ['target']
|
||||
|
||||
|
|
@ -53,10 +52,10 @@ class NSBase(linkcheck.dns.rdata.Rdata):
|
|||
return self.target.to_digestable(origin)
|
||||
|
||||
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
|
||||
(target, cused) = linkcheck.dns.name.from_wire(wire[: current + rdlen],
|
||||
(target, cused) = dns.name.from_wire(wire[: current + rdlen],
|
||||
current)
|
||||
if cused != rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if not origin is None:
|
||||
target = target.relativize(origin)
|
||||
return cls(rdclass, rdtype, target)
|
||||
|
|
@ -78,6 +77,6 @@ class UncompressedNS(NSBase):
|
|||
super(UncompressedNS, self).to_wire(file, None, origin)
|
||||
|
||||
def to_digestable(self, origin = None):
|
||||
f = StringIO()
|
||||
f = cStringIO.StringIO()
|
||||
self.to_wire(f, None, origin)
|
||||
return f.getvalue()
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,11 +15,11 @@
|
|||
|
||||
"""TXT-like base class."""
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdata
|
||||
import linkcheck.dns.tokenizer
|
||||
import dns.exception
|
||||
import dns.rdata
|
||||
import dns.tokenizer
|
||||
|
||||
class TXTBase(linkcheck.dns.rdata.Rdata):
|
||||
class TXTBase(dns.rdata.Rdata):
|
||||
"""Base class for rdata that is like a TXT record
|
||||
|
||||
@ivar strings: the text strings
|
||||
|
|
@ -39,7 +38,7 @@ class TXTBase(linkcheck.dns.rdata.Rdata):
|
|||
txt = ''
|
||||
prefix = ''
|
||||
for s in self.strings:
|
||||
txt += '%s"%s"' % (prefix, linkcheck.dns.rdata._escapify(s))
|
||||
txt += '%s"%s"' % (prefix, dns.rdata._escapify(s))
|
||||
prefix = ' '
|
||||
return txt
|
||||
|
||||
|
|
@ -50,12 +49,12 @@ class TXTBase(linkcheck.dns.rdata.Rdata):
|
|||
if token.is_eol_or_eof():
|
||||
break
|
||||
if not (token.is_quoted_string() or token.is_identifier()):
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("expected a string")
|
||||
raise dns.exception.SyntaxError("expected a string")
|
||||
if len(token.value) > 255:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError("string too long")
|
||||
raise dns.exception.SyntaxError("string too long")
|
||||
strings.append(token.value)
|
||||
if len(strings) == 0:
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
return cls(rdclass, rdtype, strings)
|
||||
|
||||
from_text = classmethod(from_text)
|
||||
|
|
@ -75,8 +74,8 @@ class TXTBase(linkcheck.dns.rdata.Rdata):
|
|||
current += 1
|
||||
rdlen -= 1
|
||||
if l > rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
s = wire[current : current + l]
|
||||
raise dns.exception.FormError
|
||||
s = wire[current : current + l].unwrap()
|
||||
current += l
|
||||
rdlen -= l
|
||||
strings.append(s)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,13 +15,13 @@
|
|||
|
||||
"""Help for building DNS wire format messages"""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import struct
|
||||
import random
|
||||
import time
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.tsig
|
||||
import dns.exception
|
||||
import dns.tsig
|
||||
|
||||
QUESTION = 0
|
||||
ANSWER = 1
|
||||
|
|
@ -32,27 +31,27 @@ ADDITIONAL = 3
|
|||
class Renderer(object):
|
||||
"""Helper class for building DNS wire-format messages.
|
||||
|
||||
Most applications can use the higher-level L{linkcheck.dns.message.Message}
|
||||
Most applications can use the higher-level L{dns.message.Message}
|
||||
class and its to_wire() method to generate wire-format messages.
|
||||
This class is for those applications which need finer control
|
||||
over the generation of messages.
|
||||
|
||||
Typical use::
|
||||
|
||||
r = linkcheck.dns.renderer.Renderer(id=1, flags=0x80, max_size=512)
|
||||
r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512)
|
||||
r.add_question(qname, qtype, qclass)
|
||||
r.add_rrset(linkcheck.dns.renderer.ANSWER, rrset_1)
|
||||
r.add_rrset(linkcheck.dns.renderer.ANSWER, rrset_2)
|
||||
r.add_rrset(linkcheck.dns.renderer.AUTHORITY, ns_rrset)
|
||||
r.add_rrset(dns.renderer.ANSWER, rrset_1)
|
||||
r.add_rrset(dns.renderer.ANSWER, rrset_2)
|
||||
r.add_rrset(dns.renderer.AUTHORITY, ns_rrset)
|
||||
r.add_edns(0, 0, 4096)
|
||||
r.add_rrset(linkcheck.dns.renderer.ADDTIONAL, ad_rrset_1)
|
||||
r.add_rrset(linkcheck.dns.renderer.ADDTIONAL, ad_rrset_2)
|
||||
r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_1)
|
||||
r.add_rrset(dns.renderer.ADDTIONAL, ad_rrset_2)
|
||||
r.write_header()
|
||||
r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac)
|
||||
wire = r.get_wire()
|
||||
|
||||
@ivar output: where rendering is written
|
||||
@type output: StringIO object
|
||||
@type output: cStringIO.StringIO object
|
||||
@ivar id: the message id
|
||||
@type id: int
|
||||
@ivar flags: the message flags
|
||||
|
|
@ -60,12 +59,12 @@ class Renderer(object):
|
|||
@ivar max_size: the maximum size of the message
|
||||
@type max_size: int
|
||||
@ivar origin: the origin to use when rendering relative names
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@ivar compress: the compression table
|
||||
@type compress: dict
|
||||
@ivar section: the section currently being rendered
|
||||
@type section: int (linkcheck.dns.renderer.QUESTION, linkcheck.dns.renderer.ANSWER,
|
||||
linkcheck.dns.renderer.AUTHORITY, or linkcheck.dns.renderer.ADDITIONAL)
|
||||
@type section: int (dns.renderer.QUESTION, dns.renderer.ANSWER,
|
||||
dns.renderer.AUTHORITY, or dns.renderer.ADDITIONAL)
|
||||
@ivar counts: list of the number of RRs in each section
|
||||
@type counts: int list of length 4
|
||||
@ivar mac: the MAC of the rendered message (if TSIG was used)
|
||||
|
|
@ -81,13 +80,13 @@ class Renderer(object):
|
|||
@type flags: int
|
||||
@param max_size: the maximum message size; the default is 65535.
|
||||
If rendering results in a message greater than I{max_size},
|
||||
then L{linkcheck.dns.exception.TooBig} will be raised.
|
||||
then L{dns.exception.TooBig} will be raised.
|
||||
@type max_size: int
|
||||
@param origin: the origin to use when rendering relative names
|
||||
@type origin: linkcheck.dns.name.Namem or None.
|
||||
@type origin: dns.name.Namem or None.
|
||||
"""
|
||||
|
||||
self.output = StringIO()
|
||||
self.output = cStringIO.StringIO()
|
||||
if id is None:
|
||||
self.id = random.randint(0, 65535)
|
||||
else:
|
||||
|
|
@ -127,20 +126,20 @@ class Renderer(object):
|
|||
|
||||
@param section: the section
|
||||
@type section: int
|
||||
@raises linkcheck.dns.exception.FormError: an attempt was made to set
|
||||
@raises dns.exception.FormError: an attempt was made to set
|
||||
a section value less than the current section.
|
||||
"""
|
||||
|
||||
if self.section != section:
|
||||
if self.section > section:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
self.section = section
|
||||
|
||||
def add_question(self, qname, rdtype, rdclass=linkcheck.dns.rdataclass.IN):
|
||||
def add_question(self, qname, rdtype, rdclass=dns.rdataclass.IN):
|
||||
"""Add a question to the message.
|
||||
|
||||
@param qname: the question name
|
||||
@type qname: linkcheck.dns.name.Name
|
||||
@type qname: dns.name.Name
|
||||
@param rdtype: the question rdata type
|
||||
@type rdtype: int
|
||||
@param rdclass: the question rdata class
|
||||
|
|
@ -154,7 +153,7 @@ class Renderer(object):
|
|||
after = self.output.tell()
|
||||
if after >= self.max_size:
|
||||
self._rollback(before)
|
||||
raise linkcheck.dns.exception.TooBig
|
||||
raise dns.exception.TooBig
|
||||
self.counts[QUESTION] += 1
|
||||
|
||||
def add_rrset(self, section, rrset, **kw):
|
||||
|
|
@ -166,7 +165,7 @@ class Renderer(object):
|
|||
@param section: the section
|
||||
@type section: int
|
||||
@param rrset: the rrset
|
||||
@type rrset: linkcheck.dns.rrset.RRset object
|
||||
@type rrset: dns.rrset.RRset object
|
||||
"""
|
||||
|
||||
self._set_section(section)
|
||||
|
|
@ -175,7 +174,7 @@ class Renderer(object):
|
|||
after = self.output.tell()
|
||||
if after >= self.max_size:
|
||||
self._rollback(before)
|
||||
raise linkcheck.dns.exception.TooBig
|
||||
raise dns.exception.TooBig
|
||||
self.counts[section] += n
|
||||
|
||||
def add_rdataset(self, section, name, rdataset, **kw):
|
||||
|
|
@ -188,9 +187,9 @@ class Renderer(object):
|
|||
@param section: the section
|
||||
@type section: int
|
||||
@param name: the owner name
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@param rdataset: the rdataset
|
||||
@type rdataset: linkcheck.dns.rdataset.Rdataset object
|
||||
@type rdataset: dns.rdataset.Rdataset object
|
||||
"""
|
||||
|
||||
self._set_section(section)
|
||||
|
|
@ -200,7 +199,7 @@ class Renderer(object):
|
|||
after = self.output.tell()
|
||||
if after >= self.max_size:
|
||||
self._rollback(before)
|
||||
raise linkcheck.dns.exception.TooBig
|
||||
raise dns.exception.TooBig
|
||||
self.counts[section] += n
|
||||
|
||||
def add_edns(self, edns, ednsflags, payload, options=None):
|
||||
|
|
@ -214,7 +213,7 @@ class Renderer(object):
|
|||
size of UDP datagram the sender can handle.
|
||||
@type payload: int
|
||||
@param options: The EDNS options list
|
||||
@type options: list of linkcheck.dns.edns.Option instances
|
||||
@type options: list of dns.edns.Option instances
|
||||
@see: RFC 2671
|
||||
"""
|
||||
|
||||
|
|
@ -223,7 +222,7 @@ class Renderer(object):
|
|||
ednsflags |= (edns << 16)
|
||||
self._set_section(ADDITIONAL)
|
||||
before = self.output.tell()
|
||||
self.output.write(struct.pack('!BHHIH', 0, linkcheck.dns.rdatatype.OPT, payload,
|
||||
self.output.write(struct.pack('!BHHIH', 0, dns.rdatatype.OPT, payload,
|
||||
ednsflags, 0))
|
||||
if not options is None:
|
||||
lstart = self.output.tell()
|
||||
|
|
@ -247,18 +246,18 @@ class Renderer(object):
|
|||
after = self.output.tell()
|
||||
if after >= self.max_size:
|
||||
self._rollback(before)
|
||||
raise linkcheck.dns.exception.TooBig
|
||||
raise dns.exception.TooBig
|
||||
self.counts[ADDITIONAL] += 1
|
||||
|
||||
def add_tsig(self, keyname, secret, fudge, id, tsig_error, other_data,
|
||||
request_mac, algorithm=linkcheck.dns.tsig.default_algorithm):
|
||||
request_mac, algorithm=dns.tsig.default_algorithm):
|
||||
"""Add a TSIG signature to the message.
|
||||
|
||||
@param keyname: the TSIG key name
|
||||
@type keyname: linkcheck.dns.name.Name object
|
||||
@type keyname: dns.name.Name object
|
||||
@param secret: the secret to use
|
||||
@type secret: string
|
||||
@param fudge: TSIG time fudge; default is 300 seconds.
|
||||
@param fudge: TSIG time fudge
|
||||
@type fudge: int
|
||||
@param id: the message id to encode in the tsig signature
|
||||
@type id: int
|
||||
|
|
@ -270,12 +269,13 @@ class Renderer(object):
|
|||
had the specified MAC.
|
||||
@type request_mac: string
|
||||
@param algorithm: the TSIG algorithm to use
|
||||
@type algorithm: dns.name.Name object
|
||||
"""
|
||||
|
||||
self._set_section(ADDITIONAL)
|
||||
before = self.output.tell()
|
||||
s = self.output.getvalue()
|
||||
(tsig_rdata, self.mac, ctx) = linkcheck.dns.tsig.sign(s,
|
||||
(tsig_rdata, self.mac, ctx) = dns.tsig.sign(s,
|
||||
keyname,
|
||||
secret,
|
||||
int(time.time()),
|
||||
|
|
@ -286,15 +286,15 @@ class Renderer(object):
|
|||
request_mac,
|
||||
algorithm=algorithm)
|
||||
keyname.to_wire(self.output, self.compress, self.origin)
|
||||
self.output.write(struct.pack('!HHIH', linkcheck.dns.rdatatype.TSIG,
|
||||
linkcheck.dns.rdataclass.ANY, 0, 0))
|
||||
self.output.write(struct.pack('!HHIH', dns.rdatatype.TSIG,
|
||||
dns.rdataclass.ANY, 0, 0))
|
||||
rdata_start = self.output.tell()
|
||||
self.output.write(tsig_rdata)
|
||||
after = self.output.tell()
|
||||
assert after - rdata_start < 65536
|
||||
if after >= self.max_size:
|
||||
self._rollback(before)
|
||||
raise linkcheck.dns.exception.TooBig
|
||||
raise dns.exception.TooBig
|
||||
self.output.seek(rdata_start - 2)
|
||||
self.output.write(struct.pack('!H', after - rdata_start))
|
||||
self.counts[ADDITIONAL] += 1
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -17,53 +16,56 @@
|
|||
"""DNS stub resolver.
|
||||
|
||||
@var default_resolver: The default resolver object
|
||||
@type default_resolver: linkcheck.dns.resolver.Resolver object"""
|
||||
@type default_resolver: dns.resolver.Resolver object"""
|
||||
|
||||
import socket
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
|
||||
from .. import log, LOG_DNS
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.message
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.query
|
||||
import linkcheck.dns.rcode
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.rdatatype
|
||||
import dns.exception
|
||||
import dns.message
|
||||
import dns.name
|
||||
import dns.query
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
|
||||
if sys.platform == 'win32':
|
||||
import _winreg
|
||||
|
||||
class NXDOMAIN(linkcheck.dns.exception.DNSException):
|
||||
class NXDOMAIN(dns.exception.DNSException):
|
||||
"""The query name does not exist."""
|
||||
pass
|
||||
|
||||
# The definition of the Timeout exception has moved from here to the
|
||||
# linkcheck.dns.exception module. We keep linkcheck.dns.resolver.Timeout defined for
|
||||
# dns.exception module. We keep dns.resolver.Timeout defined for
|
||||
# backwards compatibility.
|
||||
|
||||
Timeout = linkcheck.dns.exception.Timeout
|
||||
Timeout = dns.exception.Timeout
|
||||
|
||||
class NoAnswer(linkcheck.dns.exception.DNSException):
|
||||
class NoAnswer(dns.exception.DNSException):
|
||||
"""The response did not contain an answer to the question."""
|
||||
pass
|
||||
|
||||
class NoNameservers(linkcheck.dns.exception.DNSException):
|
||||
class NoNameservers(dns.exception.DNSException):
|
||||
"""No non-broken nameservers are available to answer the query."""
|
||||
pass
|
||||
|
||||
class NotAbsolute(linkcheck.dns.exception.DNSException):
|
||||
class NotAbsolute(dns.exception.DNSException):
|
||||
"""Raised if an absolute domain name is required but a relative name
|
||||
was provided."""
|
||||
pass
|
||||
|
||||
class NoRootSOA(linkcheck.dns.exception.DNSException):
|
||||
class NoRootSOA(dns.exception.DNSException):
|
||||
"""Raised if for some reason there is no SOA at the root name.
|
||||
This should never happen!"""
|
||||
pass
|
||||
|
||||
class NoMetaqueries(dns.exception.DNSException):
|
||||
"""Metaqueries are not allowed."""
|
||||
pass
|
||||
|
||||
|
||||
class Answer(object):
|
||||
"""DNS stub resolver answer
|
||||
|
|
@ -81,19 +83,22 @@ class Answer(object):
|
|||
node's name might not be the query name.
|
||||
|
||||
@ivar qname: The query name
|
||||
@type qname: linkcheck.dns.name.Name object
|
||||
@type qname: dns.name.Name object
|
||||
@ivar rdtype: The query type
|
||||
@type rdtype: int
|
||||
@ivar rdclass: The query class
|
||||
@type rdclass: int
|
||||
@ivar response: The response message
|
||||
@type response: linkcheck.dns.message.Message object
|
||||
@type response: dns.message.Message object
|
||||
@ivar rrset: The answer
|
||||
@type rrset: linkcheck.dns.rrset.RRset object
|
||||
@type rrset: dns.rrset.RRset object
|
||||
@ivar expiration: The time when the answer expires
|
||||
@type expiration: float (seconds since the epoch)
|
||||
@ivar canonical_name: The canonical name of the query name
|
||||
@type canonical_name: dns.name.Name object
|
||||
"""
|
||||
def __init__(self, qname, rdtype, rdclass, response):
|
||||
def __init__(self, qname, rdtype, rdclass, response,
|
||||
raise_on_no_answer=True):
|
||||
self.qname = qname
|
||||
self.rdtype = rdtype
|
||||
self.rdclass = rdclass
|
||||
|
|
@ -108,12 +113,12 @@ class Answer(object):
|
|||
min_ttl = rrset.ttl
|
||||
break
|
||||
except KeyError:
|
||||
if rdtype != linkcheck.dns.rdatatype.CNAME:
|
||||
if rdtype != dns.rdatatype.CNAME:
|
||||
try:
|
||||
crrset = response.find_rrset(response.answer,
|
||||
qname,
|
||||
rdclass,
|
||||
linkcheck.dns.rdatatype.CNAME)
|
||||
dns.rdatatype.CNAME)
|
||||
if min_ttl == -1 or crrset.ttl < min_ttl:
|
||||
min_ttl = crrset.ttl
|
||||
for rd in crrset:
|
||||
|
|
@ -121,11 +126,31 @@ class Answer(object):
|
|||
break
|
||||
continue
|
||||
except KeyError:
|
||||
raise NoAnswer("DNS response had no answer")
|
||||
raise NoAnswer("DNS response had no answer")
|
||||
if rrset is None:
|
||||
if raise_on_no_answer:
|
||||
raise NoAnswer("DNS response had no answer")
|
||||
if raise_on_no_answer:
|
||||
raise NoAnswer("DNS response had no answer")
|
||||
if rrset is None and raise_on_no_answer:
|
||||
raise NoAnswer("DNS response had no answer")
|
||||
self.canonical_name = qname
|
||||
self.rrset = rrset
|
||||
if rrset is None:
|
||||
while 1:
|
||||
# Look for a SOA RR whose owner name is a superdomain
|
||||
# of qname.
|
||||
try:
|
||||
srrset = response.find_rrset(response.authority, qname,
|
||||
rdclass, dns.rdatatype.SOA)
|
||||
if min_ttl == -1 or srrset.ttl < min_ttl:
|
||||
min_ttl = srrset.ttl
|
||||
if srrset[0].minimum < min_ttl:
|
||||
min_ttl = srrset[0].minimum
|
||||
break
|
||||
except KeyError:
|
||||
try:
|
||||
qname = qname.parent()
|
||||
except dns.name.NoParent:
|
||||
break
|
||||
self.expiration = time.time() + min_ttl
|
||||
|
||||
def __str__ (self):
|
||||
|
|
@ -207,9 +232,9 @@ class Cache(object):
|
|||
"""Get the answer associated with I{key}. Returns None if
|
||||
no answer is cached for the key.
|
||||
@param key: the key
|
||||
@type key: (linkcheck.dns.name.Name, int, int) tuple whose values are the
|
||||
@type key: (dns.name.Name, int, int) tuple whose values are the
|
||||
query name, rdtype, and rdclass.
|
||||
@rtype: linkcheck.dns.resolver.Answer object or None
|
||||
@rtype: dns.resolver.Answer object or None
|
||||
"""
|
||||
|
||||
self.maybe_clean()
|
||||
|
|
@ -221,10 +246,10 @@ class Cache(object):
|
|||
def put(self, key, value):
|
||||
"""Associate key and value in the cache.
|
||||
@param key: the key
|
||||
@type key: (linkcheck.dns.name.Name, int, int) tuple whose values are the
|
||||
@type key: (dns.name.Name, int, int) tuple whose values are the
|
||||
query name, rdtype, and rdclass.
|
||||
@param value: The answer being cached
|
||||
@type value: linkcheck.dns.resolver.Answer object
|
||||
@type value: dns.resolver.Answer object
|
||||
"""
|
||||
|
||||
self.maybe_clean()
|
||||
|
|
@ -237,7 +262,7 @@ class Cache(object):
|
|||
the entire cache is flushed.
|
||||
|
||||
@param key: the key to flush
|
||||
@type key: (linkcheck.dns.name.Name, int, int) tuple or None
|
||||
@type key: (dns.name.Name, int, int) tuple or None
|
||||
"""
|
||||
|
||||
if not key is None:
|
||||
|
|
@ -252,14 +277,14 @@ class Resolver(object):
|
|||
"""DNS stub resolver
|
||||
|
||||
@ivar domain: The domain of this host
|
||||
@type domain: linkcheck.dns.name.Name object
|
||||
@type domain: dns.name.Name object
|
||||
@ivar nameservers: A list of nameservers to query. Each nameserver is
|
||||
a string which contains the IP address of a nameserver.
|
||||
@type nameservers: list of strings
|
||||
@ivar search: The search list. If the query name is a relative name,
|
||||
the resolver will construct an absolute query name by appending the search
|
||||
names one by one to the query name.
|
||||
@type search: list of linkcheck.dns.name.Name objects
|
||||
@type search: list of dns.name.Name objects
|
||||
@ivar port: The port to which to send queries. The default is 53.
|
||||
@type port: int
|
||||
@ivar timeout: The number of seconds to wait for a response from a
|
||||
|
|
@ -272,18 +297,18 @@ class Resolver(object):
|
|||
@ivar keyring: The TSIG keyring to use. The default is None.
|
||||
@type keyring: dict
|
||||
@ivar keyname: The TSIG keyname to use. The default is None.
|
||||
@type keyname: linkcheck.dns.name.Name object
|
||||
@type keyname: dns.name.Name object
|
||||
@ivar keyalgorithm: The TSIG key algorithm to use. The default is
|
||||
linkcheck.dns.tsig.default_algorithm.
|
||||
dns.tsig.default_algorithm.
|
||||
@type keyalgorithm: string
|
||||
@ivar edns: The EDNS level to use. The default is -1, no Elinkcheck.dns.
|
||||
@ivar edns: The EDNS level to use. The default is -1, no Edns.
|
||||
@type edns: int
|
||||
@ivar ednsflags: The EDNS flags
|
||||
@type ednsflags: int
|
||||
@ivar payload: The EDNS payload size. The default is 0.
|
||||
@type payload: int
|
||||
@ivar cache: The cache to use. The default is None.
|
||||
@type cache: linkcheck.dns.resolver.Cache object
|
||||
@type cache: dns.resolver.Cache object
|
||||
"""
|
||||
def __init__(self, filename='/etc/resolv.conf', configure=True):
|
||||
"""Initialize a resolver instance.
|
||||
|
|
@ -311,9 +336,9 @@ class Resolver(object):
|
|||
def reset(self):
|
||||
"""Reset all resolver configuration to the defaults."""
|
||||
self.domain = \
|
||||
linkcheck.dns.name.Name(linkcheck.dns.name.from_text(socket.gethostname())[1:])
|
||||
dns.name.Name(dns.name.from_text(socket.gethostname())[1:])
|
||||
if len(self.domain) == 0:
|
||||
self.domain = linkcheck.dns.name.root
|
||||
self.domain = dns.name.root
|
||||
self.nameservers = []
|
||||
self.localhosts = set([
|
||||
'localhost',
|
||||
|
|
@ -333,7 +358,7 @@ class Resolver(object):
|
|||
self.lifetime = 30.0
|
||||
self.keyring = None
|
||||
self.keyname = None
|
||||
self.keyalgorithm = linkcheck.dns.tsig.default_algorithm
|
||||
self.keyalgorithm = dns.tsig.default_algorithm
|
||||
self.edns = -1
|
||||
self.ednsflags = 0
|
||||
self.payload = 0
|
||||
|
|
@ -365,10 +390,10 @@ class Resolver(object):
|
|||
if tokens[0] == 'nameserver':
|
||||
self.nameservers.append(tokens[1])
|
||||
elif tokens[0] == 'domain':
|
||||
self.domain = linkcheck.dns.name.from_text(tokens[1])
|
||||
self.domain = dns.name.from_text(tokens[1])
|
||||
elif tokens[0] == 'search':
|
||||
for suffix in tokens[1:]:
|
||||
self.search.add(linkcheck.dns.name.from_text(suffix))
|
||||
self.search.add(dns.name.from_text(suffix))
|
||||
finally:
|
||||
if want_close:
|
||||
f.close()
|
||||
|
|
@ -391,9 +416,12 @@ class Resolver(object):
|
|||
if os.name != 'posix':
|
||||
# only POSIX is supported right now
|
||||
return []
|
||||
from linkcheck.network import IfConfig
|
||||
ifc = IfConfig()
|
||||
try:
|
||||
from linkcheck.network import IfConfig
|
||||
except ImportError:
|
||||
return []
|
||||
ifaddrs = []
|
||||
ifc = IfConfig()
|
||||
for iface in ifc.getInterfaceList(flags=IfConfig.IFF_UP):
|
||||
addr = ifc.getAddr(iface)
|
||||
if addr:
|
||||
|
|
@ -431,7 +459,7 @@ class Resolver(object):
|
|||
split_char = ' '
|
||||
return split_char
|
||||
|
||||
def _config_win32_nameservers (self, nameservers, split_char=','):
|
||||
def _config_win32_nameservers(self, nameservers):
|
||||
"""Configure a NameServer registry entry."""
|
||||
# we call str() on nameservers to convert it from unicode to ascii
|
||||
nameservers = str(nameservers)
|
||||
|
|
@ -441,12 +469,12 @@ class Resolver(object):
|
|||
if not ns in self.nameservers:
|
||||
self.nameservers.append(ns)
|
||||
|
||||
def _config_win32_domain (self, domain):
|
||||
def _config_win32_domain(self, domain):
|
||||
"""Configure a Domain registry entry."""
|
||||
# we call str() on domain to convert it from unicode to ascii
|
||||
self.domain = linkcheck.dns.name.from_text(str(domain))
|
||||
self.domain = dns.name.from_text(str(domain))
|
||||
|
||||
def _config_win32_search (self, search):
|
||||
def _config_win32_search(self, search):
|
||||
"""Configure a Search registry entry."""
|
||||
# we call str() on search to convert it from unicode to ascii
|
||||
search = str(search)
|
||||
|
|
@ -454,7 +482,7 @@ class Resolver(object):
|
|||
search_list = search.split(split_char)
|
||||
for s in search_list:
|
||||
if not s in self.search:
|
||||
self.search.add(linkcheck.dns.name.from_text(s))
|
||||
self.search.add(dns.name.from_text(s))
|
||||
|
||||
def _config_win32_add_ifaddr (self, key, name):
|
||||
"""Add interface ip address to self.localhosts."""
|
||||
|
|
@ -467,7 +495,7 @@ class Resolver(object):
|
|||
except WindowsError:
|
||||
pass
|
||||
|
||||
def _config_win32_fromkey (self, key):
|
||||
def _config_win32_fromkey(self, key):
|
||||
"""Extract DNS info from a registry key."""
|
||||
try:
|
||||
enable_dhcp, rtype = _winreg.QueryValueEx(key, 'EnableDHCP')
|
||||
|
|
@ -508,7 +536,7 @@ class Resolver(object):
|
|||
except WindowsError:
|
||||
search = None
|
||||
if search:
|
||||
self._config_win32_search(servers)
|
||||
self._config_win32_search(search)
|
||||
|
||||
def read_registry(self):
|
||||
"""Extract resolver configuration from the Windows registry."""
|
||||
|
|
@ -626,8 +654,8 @@ class Resolver(object):
|
|||
raise Timeout
|
||||
return min(self.lifetime - duration, self.timeout)
|
||||
|
||||
def query(self, qname, rdtype=linkcheck.dns.rdatatype.A,
|
||||
rdclass=linkcheck.dns.rdataclass.IN, tcp=False, source=None):
|
||||
def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
|
||||
tcp=False, source=None, raise_on_no_answer=True):
|
||||
"""Query nameservers to find the answer to the question.
|
||||
|
||||
The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
|
||||
|
|
@ -636,7 +664,7 @@ class Resolver(object):
|
|||
the string 'NS' both mean to query for records with DNS rdata type NS.
|
||||
|
||||
@param qname: the query name
|
||||
@type qname: linkcheck.dns.name.Name object or string
|
||||
@type qname: dns.name.Name object or string
|
||||
@param rdtype: the query type
|
||||
@type rdtype: int or string
|
||||
@param rdclass: the query class
|
||||
|
|
@ -645,25 +673,33 @@ class Resolver(object):
|
|||
@type tcp: bool
|
||||
@param source: bind to this IP address (defaults to machine default IP).
|
||||
@type source: IP address in dotted quad notation
|
||||
@rtype: linkcheck.dns.resolver.Answer instance
|
||||
@param raise_on_no_answer: raise NoAnswer if there's no answer
|
||||
(defaults is True).
|
||||
@type raise_on_no_answer: bool
|
||||
@rtype: dns.resolver.Answer instance
|
||||
@raises Timeout: no answers could be found in the specified lifetime
|
||||
@raises NXDOMAIN: the query name does not exist
|
||||
@raises NoAnswer: the response did not contain an answer
|
||||
@raises NoAnswer: the response did not contain an answer and
|
||||
raise_on_no_answer is True.
|
||||
@raises NoNameservers: no non-broken nameservers are available to
|
||||
answer the question."""
|
||||
|
||||
if isinstance(qname, basestring):
|
||||
qname = linkcheck.dns.name.from_text(qname, None)
|
||||
qname = dns.name.from_text(qname, None)
|
||||
if isinstance(rdtype, basestring):
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(rdtype)
|
||||
rdtype = dns.rdatatype.from_text(rdtype)
|
||||
if dns.rdatatype.is_metatype(rdtype):
|
||||
raise NoMetaqueries
|
||||
if isinstance(rdclass, basestring):
|
||||
rdclass = linkcheck.dns.rdataclass.from_text(rdclass)
|
||||
rdclass = dns.rdataclass.from_text(rdclass)
|
||||
if dns.rdataclass.is_metaclass(rdclass):
|
||||
raise NoMetaqueries
|
||||
qnames_to_try = []
|
||||
if qname.is_absolute():
|
||||
qnames_to_try.append(qname)
|
||||
else:
|
||||
if len(qname) > 1:
|
||||
qnames_to_try.append(qname.concatenate(linkcheck.dns.name.root))
|
||||
qnames_to_try.append(qname.concatenate(dns.name.root))
|
||||
if self.search:
|
||||
for suffix in self.search:
|
||||
qnames_to_try.append(qname.concatenate(suffix))
|
||||
|
|
@ -676,7 +712,7 @@ class Resolver(object):
|
|||
answer = self.cache.get((qname, rdtype, rdclass))
|
||||
if answer:
|
||||
return answer
|
||||
request = linkcheck.dns.message.make_query(qname, rdtype, rdclass)
|
||||
request = dns.message.make_query(qname, rdtype, rdclass)
|
||||
if not self.keyname is None:
|
||||
request.use_tsig(self.keyring, self.keyname,
|
||||
algorithm=self.keyalgorithm)
|
||||
|
|
@ -695,27 +731,27 @@ class Resolver(object):
|
|||
timeout = self._compute_timeout(start)
|
||||
try:
|
||||
if tcp:
|
||||
response = linkcheck.dns.query.tcp(request, nameserver,
|
||||
response = dns.query.tcp(request, nameserver,
|
||||
timeout, self.port,
|
||||
source=source)
|
||||
else:
|
||||
response = linkcheck.dns.query.udp(request, nameserver,
|
||||
response = dns.query.udp(request, nameserver,
|
||||
timeout, self.port,
|
||||
source=source)
|
||||
except (socket.error, linkcheck.dns.exception.Timeout):
|
||||
except (socket.error, dns.exception.Timeout):
|
||||
|
||||
# Communication failure or timeout. Go to the
|
||||
# next server
|
||||
|
||||
response = None
|
||||
continue
|
||||
except linkcheck.dns.query.UnexpectedSource:
|
||||
except dns.query.UnexpectedSource:
|
||||
|
||||
# Who knows? Keep going.
|
||||
|
||||
response = None
|
||||
continue
|
||||
except linkcheck.dns.exception.FormError:
|
||||
except dns.exception.FormError:
|
||||
|
||||
# We don't understand what this server is
|
||||
# saying. Take it out of the mix and
|
||||
|
|
@ -725,15 +761,15 @@ class Resolver(object):
|
|||
response = None
|
||||
continue
|
||||
rcode = response.rcode()
|
||||
if rcode == linkcheck.dns.rcode.NOERROR or \
|
||||
rcode == linkcheck.dns.rcode.NXDOMAIN:
|
||||
if rcode == dns.rcode.NOERROR or \
|
||||
rcode == dns.rcode.NXDOMAIN:
|
||||
break
|
||||
|
||||
# We got a response, but we're not happy with the
|
||||
# rcode in it. Remove the server from the mix if
|
||||
# the rcode isn't SERVFAIL.
|
||||
|
||||
if rcode != linkcheck.dns.rcode.SERVFAIL:
|
||||
if rcode != dns.rcode.SERVFAIL:
|
||||
nameservers.remove(nameserver)
|
||||
response = None
|
||||
|
||||
|
|
@ -750,19 +786,20 @@ class Resolver(object):
|
|||
sleep_time = min(timeout, backoff)
|
||||
backoff *= 2
|
||||
time.sleep(sleep_time)
|
||||
if response.rcode() == linkcheck.dns.rcode.NXDOMAIN:
|
||||
if response.rcode() == dns.rcode.NXDOMAIN:
|
||||
continue
|
||||
all_nxdomain = False
|
||||
break
|
||||
if all_nxdomain:
|
||||
raise NXDOMAIN("Domain does not exist")
|
||||
answer = Answer(qname, rdtype, rdclass, response)
|
||||
answer = Answer(qname, rdtype, rdclass, response,
|
||||
raise_on_no_answer)
|
||||
if self.cache:
|
||||
self.cache.put((qname, rdtype, rdclass), answer)
|
||||
return answer
|
||||
|
||||
def use_tsig(self, keyring, keyname=None,
|
||||
algorithm=linkcheck.dns.tsig.default_algorithm):
|
||||
algorithm=dns.tsig.default_algorithm):
|
||||
"""Add a TSIG signature to the query.
|
||||
|
||||
@param keyring: The TSIG keyring to use; defaults to None.
|
||||
|
|
@ -774,7 +811,7 @@ class Resolver(object):
|
|||
so applications should supply a keyname when a keyring is used, unless
|
||||
they know the keyring contains only one key.
|
||||
@param algorithm: The TSIG key algorithm to use. The default
|
||||
is linkcheck.dns.tsig.default_algorithm.
|
||||
is dns.tsig.default_algorithm.
|
||||
@type algorithm: string"""
|
||||
self.keyring = keyring
|
||||
if keyname is None:
|
||||
|
|
@ -784,9 +821,9 @@ class Resolver(object):
|
|||
self.keyalgorithm = algorithm
|
||||
|
||||
def use_edns(self, edns, ednsflags, payload):
|
||||
"""Configure Elinkcheck.dns.
|
||||
"""Configure Edns.
|
||||
|
||||
@param edns: The EDNS level to use. The default is -1, no Elinkcheck.dns.
|
||||
@param edns: The EDNS level to use. The default is -1, no Edns.
|
||||
@type edns: int
|
||||
@param ednsflags: The EDNS flags
|
||||
@type ednsflags: int
|
||||
|
|
@ -808,45 +845,46 @@ def get_default_resolver():
|
|||
default_resolver = Resolver()
|
||||
return default_resolver
|
||||
|
||||
def query(qname, rdtype=linkcheck.dns.rdatatype.A, rdclass=linkcheck.dns.rdataclass.IN,
|
||||
tcp=False, source=None, resolver=None):
|
||||
def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
|
||||
tcp=False, source=None, raise_on_no_answer=True, resolver=None):
|
||||
"""Query nameservers to find the answer to the question.
|
||||
|
||||
This is a convenience function that uses the default resolver
|
||||
object to make the query.
|
||||
@see: L{linkcheck.dns.resolver.Resolver.query} for more information on the
|
||||
@see: L{dns.resolver.Resolver.query} for more information on the
|
||||
parameters."""
|
||||
log.debug(LOG_DNS, "Query %s %s %s", qname, rdtype, rdclass)
|
||||
if resolver is None:
|
||||
resolver = get_default_resolver()
|
||||
return resolver.query(qname, rdtype, rdclass, tcp, source)
|
||||
return resolver.query(qname, rdtype, rdclass, tcp, source, raise_on_no_answer)
|
||||
|
||||
def zone_for_name(name, rdclass=linkcheck.dns.rdataclass.IN,
|
||||
tcp=False, resolver=None):
|
||||
def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
|
||||
"""Find the name of the zone which contains the specified name.
|
||||
|
||||
@param name: the query name
|
||||
@type name: absolute linkcheck.dns.name.Name object or string
|
||||
@ivar rdclass: The query class
|
||||
@type name: absolute dns.name.Name object or string
|
||||
@param rdclass: The query class
|
||||
@type rdclass: int
|
||||
@param tcp: use TCP to make the query (default is False).
|
||||
@type tcp: bool
|
||||
@param resolver: the resolver to use
|
||||
@type resolver: linkcheck.dns.resolver.Resolver object or None
|
||||
@rtype: linkcheck.dns.name.Name"""
|
||||
@type resolver: dns.resolver.Resolver object or None
|
||||
@rtype: dns.name.Name"""
|
||||
|
||||
if isinstance(name, str):
|
||||
name = linkcheck.dns.name.from_text(name, linkcheck.dns.name.root)
|
||||
if isinstance(name, basestring):
|
||||
name = dns.name.from_text(name, dns.name.root)
|
||||
if resolver is None:
|
||||
resolver = get_default_resolver()
|
||||
if not name.is_absolute():
|
||||
raise NotAbsolute(name)
|
||||
while 1:
|
||||
try:
|
||||
answer = resolver.query(name, linkcheck.dns.rdatatype.SOA, rdclass, tcp)
|
||||
return name
|
||||
except (linkcheck.dns.resolver.NXDOMAIN, linkcheck.dns.resolver.NoAnswer):
|
||||
try:
|
||||
name = name.parent()
|
||||
except linkcheck.dns.name.NoParent:
|
||||
raise NoRootSOA
|
||||
answer = resolver.query(name, dns.rdatatype.SOA, rdclass, tcp)
|
||||
if answer.rrset.name == name:
|
||||
return name
|
||||
# otherwise we were CNAMEd or DNAMEd and need to look higher
|
||||
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
||||
pass
|
||||
try:
|
||||
name = name.parent()
|
||||
except dns.name.NoParent:
|
||||
raise NoRootSOA
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -17,17 +16,17 @@
|
|||
"""DNS Reverse Map Names.
|
||||
|
||||
@var ipv4_reverse_domain: The DNS IPv4 reverse-map domain, in-addr.arpa.
|
||||
@type ipv4_reverse_domain: linkcheck.dns.name.Name object
|
||||
@type ipv4_reverse_domain: dns.name.Name object
|
||||
@var ipv6_reverse_domain: The DNS IPv6 reverse-map domain, ip6.arpa.
|
||||
@type ipv6_reverse_domain: linkcheck.dns.name.Name object
|
||||
@type ipv6_reverse_domain: dns.name.Name object
|
||||
"""
|
||||
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.ipv6
|
||||
import linkcheck.dns.ipv4
|
||||
import dns.name
|
||||
import dns.ipv6
|
||||
import dns.ipv4
|
||||
|
||||
ipv4_reverse_domain = linkcheck.dns.name.from_text('in-addr.arpa.')
|
||||
ipv6_reverse_domain = linkcheck.dns.name.from_text('ip6.arpa.')
|
||||
ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.')
|
||||
ipv6_reverse_domain = dns.name.from_text('ip6.arpa.')
|
||||
|
||||
def from_address(text):
|
||||
"""Convert an IPv4 or IPv6 address in textual form into a Name object whose
|
||||
|
|
@ -35,21 +34,21 @@ def from_address(text):
|
|||
@param text: an IPv4 or IPv6 address in textual form (e.g. '127.0.0.1',
|
||||
'::1')
|
||||
@type text: str
|
||||
@rtype: linkcheck.dns.name.Name object
|
||||
@rtype: dns.name.Name object
|
||||
"""
|
||||
try:
|
||||
parts = list(linkcheck.dns.ipv6.inet_aton(text).encode('hex_codec'))
|
||||
parts = list(dns.ipv6.inet_aton(text).encode('hex_codec'))
|
||||
origin = ipv6_reverse_domain
|
||||
except:
|
||||
parts = ['%d' % ord(byte) for byte in linkcheck.dns.ipv4.inet_aton(text)]
|
||||
except StandardError:
|
||||
parts = ['%d' % ord(byte) for byte in dns.ipv4.inet_aton(text)]
|
||||
origin = ipv4_reverse_domain
|
||||
parts.reverse()
|
||||
return linkcheck.dns.name.from_text('.'.join(parts), origin=origin)
|
||||
return dns.name.from_text('.'.join(parts), origin=origin)
|
||||
|
||||
def to_address(name):
|
||||
"""Convert a reverse map domain name into textual address form.
|
||||
@param name: an IPv4 or IPv6 address in reverse-map form.
|
||||
@type name: linkcheck.dns.name.Name object
|
||||
@type name: dns.name.Name object
|
||||
@rtype: str
|
||||
"""
|
||||
if name.is_subdomain(ipv4_reverse_domain):
|
||||
|
|
@ -58,7 +57,7 @@ def to_address(name):
|
|||
labels.reverse()
|
||||
text = '.'.join(labels)
|
||||
# run through inet_aton() to check syntax and make pretty.
|
||||
return linkcheck.dns.ipv4.inet_ntoa(linkcheck.dns.ipv4.inet_aton(text))
|
||||
return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text))
|
||||
elif name.is_subdomain(ipv6_reverse_domain):
|
||||
name = name.relativize(ipv6_reverse_domain)
|
||||
labels = list(name.labels)
|
||||
|
|
@ -71,6 +70,6 @@ def to_address(name):
|
|||
i += 4
|
||||
text = ':'.join(parts)
|
||||
# run through inet_aton() to check syntax and make pretty.
|
||||
return linkcheck.dns.ipv6.inet_ntoa(linkcheck.dns.ipv6.inet_aton(text))
|
||||
return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text))
|
||||
else:
|
||||
raise linkcheck.dns.exception.SyntaxError('unknown reverse-map address family')
|
||||
raise dns.exception.SyntaxError('unknown reverse-map address family')
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,12 +15,12 @@
|
|||
|
||||
"""DNS RRsets (an RRset is a named rdataset)"""
|
||||
|
||||
import linkcheck.dns.name
|
||||
import linkcheck.dns.rdataset
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.renderer
|
||||
import dns.name
|
||||
import dns.rdataset
|
||||
import dns.rdataclass
|
||||
import dns.renderer
|
||||
|
||||
class RRset(linkcheck.dns.rdataset.Rdataset):
|
||||
class RRset(dns.rdataset.Rdataset):
|
||||
"""A DNS RRset (named rdataset).
|
||||
|
||||
RRset inherits from Rdataset, and RRsets can be treated as
|
||||
|
|
@ -33,7 +32,7 @@ class RRset(linkcheck.dns.rdataset.Rdataset):
|
|||
|
||||
__slots__ = ['name', 'deleting']
|
||||
|
||||
def __init__(self, name, rdclass, rdtype, covers=linkcheck.dns.rdatatype.NONE,
|
||||
def __init__(self, name, rdclass, rdtype, covers=dns.rdatatype.NONE,
|
||||
deleting=None):
|
||||
"""Create a new RRset."""
|
||||
|
||||
|
|
@ -51,14 +50,14 @@ class RRset(linkcheck.dns.rdataset.Rdataset):
|
|||
if self.covers == 0:
|
||||
ctext = ''
|
||||
else:
|
||||
ctext = '(' + linkcheck.dns.rdatatype.to_text(self.covers) + ')'
|
||||
ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
|
||||
if not self.deleting is None:
|
||||
dtext = ' delete=' + linkcheck.dns.rdataclass.to_text(self.deleting)
|
||||
dtext = ' delete=' + dns.rdataclass.to_text(self.deleting)
|
||||
else:
|
||||
dtext = ''
|
||||
return '<DNS ' + str(self.name) + ' ' + \
|
||||
linkcheck.dns.rdataclass.to_text(self.rdclass) + ' ' + \
|
||||
linkcheck.dns.rdatatype.to_text(self.rdtype) + ctext + dtext + ' RRset>'
|
||||
dns.rdataclass.to_text(self.rdclass) + ' ' + \
|
||||
dns.rdatatype.to_text(self.rdtype) + ctext + dtext + ' RRset>'
|
||||
|
||||
def __str__(self):
|
||||
return self.to_text()
|
||||
|
|
@ -87,7 +86,7 @@ class RRset(linkcheck.dns.rdataset.Rdataset):
|
|||
def to_text(self, origin=None, relativize=True, **kw):
|
||||
"""Convert the RRset into DNS master file format.
|
||||
|
||||
@see: L{linkcheck.dns.name.Name.choose_relativity} for more information
|
||||
@see: L{dns.name.Name.choose_relativity} for more information
|
||||
on how I{origin} and I{relativize} determine the way names
|
||||
are emitted.
|
||||
|
||||
|
|
@ -95,7 +94,7 @@ class RRset(linkcheck.dns.rdataset.Rdataset):
|
|||
to_text() method.
|
||||
|
||||
@param origin: The origin for relative names, or None.
|
||||
@type origin: linkcheck.dns.name.Name object
|
||||
@type origin: dns.name.Name object
|
||||
@param relativize: True if names should names be relativized
|
||||
@type relativize: bool"""
|
||||
|
||||
|
|
@ -111,28 +110,28 @@ class RRset(linkcheck.dns.rdataset.Rdataset):
|
|||
def to_rdataset(self):
|
||||
"""Convert an RRset into an Rdataset.
|
||||
|
||||
@rtype: linkcheck.dns.rdataset.Rdataset object
|
||||
@rtype: dns.rdataset.Rdataset object
|
||||
"""
|
||||
return linkcheck.dns.rdataset.from_rdata_list(self.ttl, list(self))
|
||||
return dns.rdataset.from_rdata_list(self.ttl, list(self))
|
||||
|
||||
|
||||
def from_text_list(name, ttl, rdclass, rdtype, text_rdatas):
|
||||
"""Create an RRset with the specified name, TTL, class, and type, and with
|
||||
the specified list of rdatas in text format.
|
||||
|
||||
@rtype: linkcheck.dns.rrset.RRset object
|
||||
@rtype: dns.rrset.RRset object
|
||||
"""
|
||||
|
||||
if isinstance(name, basestring):
|
||||
name = linkcheck.dns.name.from_text(name, None)
|
||||
if isinstance(rdclass, basestring):
|
||||
rdclass = linkcheck.dns.rdataclass.from_text(rdclass)
|
||||
if isinstance(rdtype, basestring):
|
||||
rdtype = linkcheck.dns.rdatatype.from_text(rdtype)
|
||||
if isinstance(name, (str, unicode)):
|
||||
name = dns.name.from_text(name, None)
|
||||
if isinstance(rdclass, (str, unicode)):
|
||||
rdclass = dns.rdataclass.from_text(rdclass)
|
||||
if isinstance(rdtype, (str, unicode)):
|
||||
rdtype = dns.rdatatype.from_text(rdtype)
|
||||
r = RRset(name, rdclass, rdtype)
|
||||
r.update_ttl(ttl)
|
||||
for t in text_rdatas:
|
||||
rd = linkcheck.dns.rdata.from_text(r.rdclass, r.rdtype, t)
|
||||
rd = dns.rdata.from_text(r.rdclass, r.rdtype, t)
|
||||
r.add(rd)
|
||||
return r
|
||||
|
||||
|
|
@ -140,7 +139,7 @@ def from_text(name, ttl, rdclass, rdtype, *text_rdatas):
|
|||
"""Create an RRset with the specified name, TTL, class, and type and with
|
||||
the specified rdatas in text format.
|
||||
|
||||
@rtype: linkcheck.dns.rrset.RRset object
|
||||
@rtype: dns.rrset.RRset object
|
||||
"""
|
||||
|
||||
return from_text_list(name, ttl, rdclass, rdtype, text_rdatas)
|
||||
|
|
@ -149,11 +148,11 @@ def from_rdata_list(name, ttl, rdatas):
|
|||
"""Create an RRset with the specified name and TTL, and with
|
||||
the specified list of rdata objects.
|
||||
|
||||
@rtype: linkcheck.dns.rrset.RRset object
|
||||
@rtype: dns.rrset.RRset object
|
||||
"""
|
||||
|
||||
if isinstance(name, basestring):
|
||||
name = linkcheck.dns.name.from_text(name, None)
|
||||
if isinstance(name, (str, unicode)):
|
||||
name = dns.name.from_text(name, None)
|
||||
|
||||
if len(rdatas) == 0:
|
||||
raise ValueError("rdata list must not be empty")
|
||||
|
|
@ -170,7 +169,7 @@ def from_rdata(name, ttl, *rdatas):
|
|||
"""Create an RRset with the specified name and TTL, and with
|
||||
the specified rdata objects.
|
||||
|
||||
@rtype: linkcheck.dns.rrset.RRset object
|
||||
@rtype: dns.rrset.RRset object
|
||||
"""
|
||||
|
||||
return from_rdata_list(name, ttl, rdatas)
|
||||
263
third_party/dnspython/dns/set.py
vendored
Normal file
263
third_party/dnspython/dns/set.py
vendored
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
# provided that the above copyright notice and this permission notice
|
||||
# appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""A simple Set class."""
|
||||
|
||||
class Set(object):
|
||||
"""A simple set class.
|
||||
|
||||
Sets are not in Python until 2.3, and rdata are not immutable so
|
||||
we cannot use sets.Set anyway. This class implements subset of
|
||||
the 2.3 Set interface using a list as the container.
|
||||
|
||||
@ivar items: A list of the items which are in the set
|
||||
@type items: list"""
|
||||
|
||||
__slots__ = ['items']
|
||||
|
||||
def __init__(self, items=None):
|
||||
"""Initialize the set.
|
||||
|
||||
@param items: the initial set of items
|
||||
@type items: any iterable or None
|
||||
"""
|
||||
|
||||
self.items = []
|
||||
if not items is None:
|
||||
for item in items:
|
||||
self.add(item)
|
||||
|
||||
def __repr__(self):
|
||||
return "dns.simpleset.Set(%s)" % repr(self.items)
|
||||
|
||||
def add(self, item):
|
||||
"""Add an item to the set."""
|
||||
if not item in self.items:
|
||||
self.items.append(item)
|
||||
|
||||
def remove(self, item):
|
||||
"""Remove an item from the set."""
|
||||
self.items.remove(item)
|
||||
|
||||
def discard(self, item):
|
||||
"""Remove an item from the set if present."""
|
||||
try:
|
||||
self.items.remove(item)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def _clone(self):
|
||||
"""Make a (shallow) copy of the set.
|
||||
|
||||
There is a 'clone protocol' that subclasses of this class
|
||||
should use. To make a copy, first call your super's _clone()
|
||||
method, and use the object returned as the new instance. Then
|
||||
make shallow copies of the attributes defined in the subclass.
|
||||
|
||||
This protocol allows us to write the set algorithms that
|
||||
return new instances (e.g. union) once, and keep using them in
|
||||
subclasses.
|
||||
"""
|
||||
|
||||
cls = self.__class__
|
||||
obj = cls.__new__(cls)
|
||||
obj.items = list(self.items)
|
||||
return obj
|
||||
|
||||
def __copy__(self):
|
||||
"""Make a (shallow) copy of the set."""
|
||||
return self._clone()
|
||||
|
||||
def copy(self):
|
||||
"""Make a (shallow) copy of the set."""
|
||||
return self._clone()
|
||||
|
||||
def union_update(self, other):
|
||||
"""Update the set, adding any elements from other which are not
|
||||
already in the set.
|
||||
@param other: the collection of items with which to update the set
|
||||
@type other: Set object
|
||||
"""
|
||||
if not isinstance(other, Set):
|
||||
raise ValueError('other must be a Set instance')
|
||||
if self is other:
|
||||
return
|
||||
for item in other.items:
|
||||
self.add(item)
|
||||
|
||||
def intersection_update(self, other):
|
||||
"""Update the set, removing any elements from other which are not
|
||||
in both sets.
|
||||
@param other: the collection of items with which to update the set
|
||||
@type other: Set object
|
||||
"""
|
||||
if not isinstance(other, Set):
|
||||
raise ValueError('other must be a Set instance')
|
||||
if self is other:
|
||||
return
|
||||
# we make a copy of the list so that we can remove items from
|
||||
# the list without breaking the iterator.
|
||||
for item in list(self.items):
|
||||
if item not in other.items:
|
||||
self.items.remove(item)
|
||||
|
||||
def difference_update(self, other):
|
||||
"""Update the set, removing any elements from other which are in
|
||||
the set.
|
||||
@param other: the collection of items with which to update the set
|
||||
@type other: Set object
|
||||
"""
|
||||
if not isinstance(other, Set):
|
||||
raise ValueError('other must be a Set instance')
|
||||
if self is other:
|
||||
self.items = []
|
||||
else:
|
||||
for item in other.items:
|
||||
self.discard(item)
|
||||
|
||||
def union(self, other):
|
||||
"""Return a new set which is the union of I{self} and I{other}.
|
||||
|
||||
@param other: the other set
|
||||
@type other: Set object
|
||||
@rtype: the same type as I{self}
|
||||
"""
|
||||
|
||||
obj = self._clone()
|
||||
obj.union_update(other)
|
||||
return obj
|
||||
|
||||
def intersection(self, other):
|
||||
"""Return a new set which is the intersection of I{self} and I{other}.
|
||||
|
||||
@param other: the other set
|
||||
@type other: Set object
|
||||
@rtype: the same type as I{self}
|
||||
"""
|
||||
|
||||
obj = self._clone()
|
||||
obj.intersection_update(other)
|
||||
return obj
|
||||
|
||||
def difference(self, other):
|
||||
"""Return a new set which I{self} - I{other}, i.e. the items
|
||||
in I{self} which are not also in I{other}.
|
||||
|
||||
@param other: the other set
|
||||
@type other: Set object
|
||||
@rtype: the same type as I{self}
|
||||
"""
|
||||
|
||||
obj = self._clone()
|
||||
obj.difference_update(other)
|
||||
return obj
|
||||
|
||||
def __or__(self, other):
|
||||
return self.union(other)
|
||||
|
||||
def __and__(self, other):
|
||||
return self.intersection(other)
|
||||
|
||||
def __add__(self, other):
|
||||
return self.union(other)
|
||||
|
||||
def __sub__(self, other):
|
||||
return self.difference(other)
|
||||
|
||||
def __ior__(self, other):
|
||||
self.union_update(other)
|
||||
return self
|
||||
|
||||
def __iand__(self, other):
|
||||
self.intersection_update(other)
|
||||
return self
|
||||
|
||||
def __iadd__(self, other):
|
||||
self.union_update(other)
|
||||
return self
|
||||
|
||||
def __isub__(self, other):
|
||||
self.difference_update(other)
|
||||
return self
|
||||
|
||||
def update(self, other):
|
||||
"""Update the set, adding any elements from other which are not
|
||||
already in the set.
|
||||
@param other: the collection of items with which to update the set
|
||||
@type other: any iterable type"""
|
||||
for item in other:
|
||||
self.add(item)
|
||||
|
||||
def clear(self):
|
||||
"""Make the set empty."""
|
||||
self.items = []
|
||||
|
||||
def __eq__(self, other):
|
||||
# Yes, this is inefficient but the sets we're dealing with are
|
||||
# usually quite small, so it shouldn't hurt too much.
|
||||
for item in self.items:
|
||||
if not item in other.items:
|
||||
return False
|
||||
for item in other.items:
|
||||
if not item in self.items:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.items)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.items)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.items[i]
|
||||
|
||||
def __delitem__(self, i):
|
||||
del self.items[i]
|
||||
|
||||
def __getslice__(self, i, j):
|
||||
return self.items[i:j]
|
||||
|
||||
def __delslice__(self, i, j):
|
||||
del self.items[i:j]
|
||||
|
||||
def issubset(self, other):
|
||||
"""Is I{self} a subset of I{other}?
|
||||
|
||||
@rtype: bool
|
||||
"""
|
||||
|
||||
if not isinstance(other, Set):
|
||||
raise ValueError('other must be a Set instance')
|
||||
for item in self.items:
|
||||
if not item in other.items:
|
||||
return False
|
||||
return True
|
||||
|
||||
def issuperset(self, other):
|
||||
"""Is I{self} a superset of I{other}?
|
||||
|
||||
@rtype: bool
|
||||
"""
|
||||
|
||||
if not isinstance(other, Set):
|
||||
raise ValueError('other must be a Set instance')
|
||||
for item in other.items:
|
||||
if not item in self.items:
|
||||
return False
|
||||
return True
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,11 +15,12 @@
|
|||
|
||||
"""Tokenize DNS master file format"""
|
||||
|
||||
from cStringIO import StringIO
|
||||
import cStringIO
|
||||
import sys
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.name
|
||||
import dns.ttl
|
||||
|
||||
_DELIMITERS = {
|
||||
' ' : True,
|
||||
|
|
@ -41,7 +41,7 @@ QUOTED_STRING = 4
|
|||
COMMENT = 5
|
||||
DELIMITER = 6
|
||||
|
||||
class UngetBufferFull(linkcheck.dns.exception.DNSException):
|
||||
class UngetBufferFull(dns.exception.DNSException):
|
||||
"""Raised when an attempt is made to unget a token when the unget
|
||||
buffer is full."""
|
||||
pass
|
||||
|
|
@ -121,20 +121,20 @@ class Token(object):
|
|||
i += 1
|
||||
if c == '\\':
|
||||
if i >= l:
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
c = self.value[i]
|
||||
i += 1
|
||||
if c.isdigit():
|
||||
if i >= l:
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
c2 = self.value[i]
|
||||
i += 1
|
||||
if i >= l:
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
c3 = self.value[i]
|
||||
i += 1
|
||||
if not (c2.isdigit() and c3.isdigit()):
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
c = chr(int(c) * 100 + int(c2) * 10 + int(c3))
|
||||
unescaped += c
|
||||
return Token(self.ttype, unescaped)
|
||||
|
|
@ -198,7 +198,7 @@ class Tokenizer(object):
|
|||
"""
|
||||
|
||||
if isinstance(f, str):
|
||||
f = StringIO(f)
|
||||
f = cStringIO.StringIO(f)
|
||||
if filename is None:
|
||||
filename = '<string>'
|
||||
else:
|
||||
|
|
@ -290,9 +290,9 @@ class Tokenizer(object):
|
|||
@param want_comment: If True, return a COMMENT token if the
|
||||
first token read is a comment. The default is False.
|
||||
@type want_comment: bool
|
||||
@rtype: (int, string) tuple
|
||||
@raises linkcheck.dns.exception.UnexpectedEnd: input ended prematurely
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError: input was badly formed
|
||||
@rtype: Token object
|
||||
@raises dns.exception.UnexpectedEnd: input ended prematurely
|
||||
@raises dns.exception.SyntaxError: input was badly formed
|
||||
"""
|
||||
|
||||
if not self.ungotten_token is None:
|
||||
|
|
@ -316,7 +316,7 @@ class Tokenizer(object):
|
|||
c = self._get_char()
|
||||
if c == '' or c in self.delimiters:
|
||||
if c == '' and self.quoting:
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
if token == '' and ttype != QUOTED_STRING:
|
||||
if c == '(':
|
||||
self.multiline += 1
|
||||
|
|
@ -324,7 +324,7 @@ class Tokenizer(object):
|
|||
continue
|
||||
elif c == ')':
|
||||
if not self.multiline > 0:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
self.multiline -= 1
|
||||
self.skip_whitespace()
|
||||
continue
|
||||
|
|
@ -352,7 +352,7 @@ class Tokenizer(object):
|
|||
return Token(COMMENT, token)
|
||||
elif c == '':
|
||||
if self.multiline:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('unbalanced parentheses')
|
||||
raise dns.exception.SyntaxError('unbalanced parentheses')
|
||||
return Token(EOF)
|
||||
elif self.multiline:
|
||||
self.skip_whitespace()
|
||||
|
|
@ -373,33 +373,33 @@ class Tokenizer(object):
|
|||
if c == '\\':
|
||||
c = self._get_char()
|
||||
if c == '':
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
if c.isdigit():
|
||||
c2 = self._get_char()
|
||||
if c2 == '':
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
c3 = self._get_char()
|
||||
if c == '':
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
if not (c2.isdigit() and c3.isdigit()):
|
||||
raise linkcheck.dns.exception.DNSSyntaxError
|
||||
raise dns.exception.SyntaxError
|
||||
c = chr(int(c) * 100 + int(c2) * 10 + int(c3))
|
||||
elif c == '\n':
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('newline in quoted string')
|
||||
raise dns.exception.SyntaxError('newline in quoted string')
|
||||
elif c == '\\':
|
||||
|
||||
#
|
||||
# It's an escape. Put it and the next character into
|
||||
# the token; it will be checked later for goodness.
|
||||
|
||||
#
|
||||
token += c
|
||||
has_escape = True
|
||||
c = self._get_char()
|
||||
if c == '' or c == '\n':
|
||||
raise linkcheck.dns.exception.UnexpectedEnd
|
||||
raise dns.exception.UnexpectedEnd
|
||||
token += c
|
||||
if token == '' and ttype != QUOTED_STRING:
|
||||
if self.multiline:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('unbalanced parentheses')
|
||||
raise dns.exception.SyntaxError('unbalanced parentheses')
|
||||
ttype = EOF
|
||||
return Token(ttype, token, has_escape)
|
||||
|
||||
|
|
@ -437,107 +437,111 @@ class Tokenizer(object):
|
|||
def get_int(self):
|
||||
"""Read the next token and interpret it as an integer.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
token = self.get().unescape()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an identifier')
|
||||
raise dns.exception.SyntaxError('expecting an identifier')
|
||||
if not token.value.isdigit():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an integer')
|
||||
raise dns.exception.SyntaxError('expecting an integer')
|
||||
return int(token.value)
|
||||
|
||||
def get_uint8(self):
|
||||
"""Read the next token and interpret it as an 8-bit unsigned
|
||||
integer.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
value = self.get_int()
|
||||
if value < 0 or value > 255:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('%d is not an unsigned 8-bit integer' % value)
|
||||
raise dns.exception.SyntaxError('%d is not an unsigned 8-bit integer' % value)
|
||||
return value
|
||||
|
||||
def get_uint16(self):
|
||||
"""Read the next token and interpret it as a 16-bit unsigned
|
||||
integer.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
value = self.get_int()
|
||||
if value < 0 or value > 65535:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('%d is not an unsigned 16-bit integer' % value)
|
||||
raise dns.exception.SyntaxError('%d is not an unsigned 16-bit integer' % value)
|
||||
return value
|
||||
|
||||
def get_uint32(self):
|
||||
"""Read the next token and interpret it as a 32-bit unsigned
|
||||
integer.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
token = self.get().unescape()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an identifier')
|
||||
raise dns.exception.SyntaxError('expecting an identifier')
|
||||
if not token.value.isdigit():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an integer')
|
||||
raise dns.exception.SyntaxError('expecting an integer')
|
||||
value = long(token.value)
|
||||
if value < 0 or value > 4294967296L:
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('%d is not an unsigned 32-bit integer' % value)
|
||||
raise dns.exception.SyntaxError('%d is not an unsigned 32-bit integer' % value)
|
||||
return value
|
||||
|
||||
def get_string(self, origin=None):
|
||||
"""Read the next token and interpret it as a string.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
token = self.get().unescape()
|
||||
if not (token.is_identifier() or token.is_quoted_string()):
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting a string')
|
||||
raise dns.exception.SyntaxError('expecting a string')
|
||||
return token.value
|
||||
|
||||
def get_identifier(self, origin=None):
|
||||
"""Read the next token and raise an exception if it is not an identifier.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
token = self.get().unescape()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an identifier')
|
||||
raise dns.exception.SyntaxError('expecting an identifier')
|
||||
return token.value
|
||||
|
||||
def get_name(self, origin=None):
|
||||
"""Read the next token and interpret it as a DNS name.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@rtype: linkcheck.dns.name.Name object"""
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: dns.name.Name object"""
|
||||
|
||||
token = self.get()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an identifier')
|
||||
return linkcheck.dns.name.from_text(token.value, origin)
|
||||
raise dns.exception.SyntaxError('expecting an identifier')
|
||||
return dns.name.from_text(token.value, origin)
|
||||
|
||||
def get_eol(self):
|
||||
"""Read the next token and raise an exception if it isn't EOL or
|
||||
EOF.
|
||||
|
||||
@raises linkcheck.dns.exception.DNSSyntaxError:
|
||||
@raises dns.exception.SyntaxError:
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
token = self.get()
|
||||
if not token.is_eol_or_eof():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expected EOL or EOF, got %d "%s"' % (token.ttype, token.value))
|
||||
raise dns.exception.SyntaxError('expected EOL or EOF, got %d "%s"' % (token.ttype, token.value))
|
||||
return token.value
|
||||
|
||||
def get_ttl(self):
|
||||
token = self.get().unescape()
|
||||
if not token.is_identifier():
|
||||
raise linkcheck.dns.exception.DNSSyntaxError('expecting an identifier')
|
||||
return linkcheck.dns.ttl.from_text(token.value)
|
||||
raise dns.exception.SyntaxError('expecting an identifier')
|
||||
return dns.ttl.from_text(token.value)
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -18,20 +17,22 @@
|
|||
|
||||
import hmac
|
||||
import struct
|
||||
import sys
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import linkcheck.dns.rdataclass
|
||||
import linkcheck.dns.name
|
||||
import dns.exception
|
||||
import dns.hash
|
||||
import dns.rdataclass
|
||||
import dns.name
|
||||
|
||||
class BadTime(linkcheck.dns.exception.DNSException):
|
||||
class BadTime(dns.exception.DNSException):
|
||||
"""Raised if the current time is not within the TSIG's validity time."""
|
||||
pass
|
||||
|
||||
class BadSignature(linkcheck.dns.exception.DNSException):
|
||||
class BadSignature(dns.exception.DNSException):
|
||||
"""Raised if the TSIG signature fails to verify."""
|
||||
pass
|
||||
|
||||
class PeerError(linkcheck.dns.exception.DNSException):
|
||||
class PeerError(dns.exception.DNSException):
|
||||
"""Base class for all TSIG errors generated by the remote peer"""
|
||||
pass
|
||||
|
||||
|
|
@ -53,12 +54,12 @@ class PeerBadTruncation(PeerError):
|
|||
|
||||
# TSIG Algorithms
|
||||
|
||||
HMAC_MD5 = linkcheck.dns.name.from_text("HMAC-MD5.SIG-ALG.REG.INT")
|
||||
HMAC_SHA1 = linkcheck.dns.name.from_text("hmac-sha1")
|
||||
HMAC_SHA224 = linkcheck.dns.name.from_text("hmac-sha224")
|
||||
HMAC_SHA256 = linkcheck.dns.name.from_text("hmac-sha256")
|
||||
HMAC_SHA384 = linkcheck.dns.name.from_text("hmac-sha384")
|
||||
HMAC_SHA512 = linkcheck.dns.name.from_text("hmac-sha512")
|
||||
HMAC_MD5 = dns.name.from_text("HMAC-MD5.SIG-ALG.REG.INT")
|
||||
HMAC_SHA1 = dns.name.from_text("hmac-sha1")
|
||||
HMAC_SHA224 = dns.name.from_text("hmac-sha224")
|
||||
HMAC_SHA256 = dns.name.from_text("hmac-sha256")
|
||||
HMAC_SHA384 = dns.name.from_text("hmac-sha384")
|
||||
HMAC_SHA512 = dns.name.from_text("hmac-sha512")
|
||||
|
||||
default_algorithm = HMAC_MD5
|
||||
|
||||
|
|
@ -90,7 +91,7 @@ def sign(wire, keyname, secret, time, fudge, original_id, error,
|
|||
ctx.update(wire[2:])
|
||||
if first:
|
||||
ctx.update(keyname.to_digestable())
|
||||
ctx.update(struct.pack('!H', linkcheck.dns.rdataclass.ANY))
|
||||
ctx.update(struct.pack('!H', dns.rdataclass.ANY))
|
||||
ctx.update(struct.pack('!I', 0))
|
||||
long_time = time + 0L
|
||||
upper_time = (long_time >> 32) & 0xffffL
|
||||
|
|
@ -136,11 +137,11 @@ def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
|
|||
|
||||
(adcount,) = struct.unpack("!H", wire[10:12])
|
||||
if adcount == 0:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
adcount -= 1
|
||||
new_wire = wire[0:10] + struct.pack("!H", adcount) + wire[12:tsig_start]
|
||||
current = tsig_rdata
|
||||
(aname, used) = linkcheck.dns.name.from_wire(wire, current)
|
||||
(aname, used) = dns.name.from_wire(wire, current)
|
||||
current = current + used
|
||||
(upper_time, lower_time, fudge, mac_size) = \
|
||||
struct.unpack("!HIHH", wire[current:current + 10])
|
||||
|
|
@ -154,7 +155,7 @@ def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
|
|||
other_data = wire[current:current + other_size]
|
||||
current += other_size
|
||||
if current != tsig_rdata + tsig_rdlen:
|
||||
raise linkcheck.dns.exception.FormError
|
||||
raise dns.exception.FormError
|
||||
if error != 0:
|
||||
if error == BADSIG:
|
||||
raise PeerBadSignature
|
||||
|
|
@ -179,22 +180,21 @@ def validate(wire, keyname, secret, now, request_mac, tsig_start, tsig_rdata,
|
|||
|
||||
_hashes = None
|
||||
|
||||
def _maybe_add_hash(tsig_alg, hash_alg):
|
||||
try:
|
||||
_hashes[tsig_alg] = dns.hash.get(hash_alg)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def _setup_hashes():
|
||||
global _hashes
|
||||
_hashes = {}
|
||||
try:
|
||||
import hashlib
|
||||
_hashes[HMAC_SHA224] = hashlib.sha224
|
||||
_hashes[HMAC_SHA256] = hashlib.sha256
|
||||
_hashes[HMAC_SHA384] = hashlib.sha384
|
||||
_hashes[HMAC_SHA512] = hashlib.sha512
|
||||
_hashes[HMAC_SHA1] = hashlib.sha1
|
||||
_hashes[HMAC_MD5] = hashlib.md5
|
||||
|
||||
except ImportError:
|
||||
import md5, sha
|
||||
_hashes[HMAC_MD5] = md5
|
||||
_hashes[HMAC_SHA1] = sha
|
||||
_maybe_add_hash(HMAC_SHA224, 'SHA224')
|
||||
_maybe_add_hash(HMAC_SHA256, 'SHA256')
|
||||
_maybe_add_hash(HMAC_SHA384, 'SHA384')
|
||||
_maybe_add_hash(HMAC_SHA512, 'SHA512')
|
||||
_maybe_add_hash(HMAC_SHA1, 'SHA1')
|
||||
_maybe_add_hash(HMAC_MD5, 'MD5')
|
||||
|
||||
def get_algorithm(algorithm):
|
||||
"""Returns the wire format string and the hash module to use for the
|
||||
|
|
@ -208,8 +208,13 @@ def get_algorithm(algorithm):
|
|||
if _hashes is None:
|
||||
_setup_hashes()
|
||||
|
||||
if isinstance(algorithm, basestring):
|
||||
algorithm = linkcheck.dns.name.from_text(algorithm)
|
||||
if isinstance(algorithm, (str, unicode)):
|
||||
algorithm = dns.name.from_text(algorithm)
|
||||
|
||||
if sys.hexversion < 0x02050200 and \
|
||||
(algorithm == HMAC_SHA384 or algorithm == HMAC_SHA512):
|
||||
raise NotImplementedError("TSIG algorithm " + str(algorithm) +
|
||||
" requires Python 2.5.2 or later")
|
||||
|
||||
try:
|
||||
return (algorithm.to_digestable(), _hashes[algorithm])
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -18,28 +17,28 @@
|
|||
|
||||
import base64
|
||||
|
||||
import linkcheck.dns.name
|
||||
import dns.name
|
||||
|
||||
def from_text(textring):
|
||||
"""Convert a dictionary containing (textual DNS name, base64 secret) pairs
|
||||
into a binary keyring which has (linkcheck.dns.name.Name, binary secret) pairs.
|
||||
into a binary keyring which has (dns.name.Name, binary secret) pairs.
|
||||
@rtype: dict"""
|
||||
|
||||
|
||||
keyring = {}
|
||||
for keytext in textring:
|
||||
keyname = linkcheck.dns.name.from_text(keytext)
|
||||
keyname = dns.name.from_text(keytext)
|
||||
secret = base64.decodestring(textring[keytext])
|
||||
keyring[keyname] = secret
|
||||
return keyring
|
||||
|
||||
def to_text(keyring):
|
||||
"""Convert a dictionary containing (linkcheck.dns.name.Name, binary secret) pairs
|
||||
"""Convert a dictionary containing (dns.name.Name, binary secret) pairs
|
||||
into a text keyring which has (textual DNS name, base64 secret) pairs.
|
||||
@rtype: dict"""
|
||||
|
||||
|
||||
textring = {}
|
||||
for keyname in keyring:
|
||||
keytext = linkcheck.dns.name.to_text(keyname)
|
||||
keytext = dns.name.to_text(keyname)
|
||||
secret = base64.encodestring(keyring[keyname])
|
||||
textring[keytext] = secret
|
||||
return textring
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
|
||||
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and its
|
||||
# documentation for any purpose with or without fee is hereby granted,
|
||||
|
|
@ -16,9 +15,9 @@
|
|||
|
||||
"""DNS TTL conversion."""
|
||||
|
||||
import linkcheck.dns.exception
|
||||
import dns.exception
|
||||
|
||||
class BadTTL(linkcheck.dns.exception.DNSSyntaxError):
|
||||
class BadTTL(dns.exception.SyntaxError):
|
||||
pass
|
||||
|
||||
def from_text(text):
|
||||
|
|
@ -28,7 +27,7 @@ def from_text(text):
|
|||
|
||||
@param text: the textual TTL
|
||||
@type text: string
|
||||
@raises linkcheck.dns.ttl.BadTTL: the TTL is not well-formed
|
||||
@raises dns.ttl.BadTTL: the TTL is not well-formed
|
||||
@rtype: int
|
||||
"""
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue