Codebase list dnspython / fdc503e
Imported Upstream version 1.10.0 SVN-Git Migration 8 years ago
109 changed file(s) with 1250 addition(s) and 833 deletion(s). Raw diff Collapse all Expand all
0 2012-04-08 Bob Halley <halley@dnspython.org>
1
2 * (Version 1.10.0 released)
3
4 2012-04-08 Bob Halley <halley@dnspython.org>
5
6 * dns/message.py (make_query): All EDNS values may now be
7 specified when calling make_query()
8
9 * dns/query.py: Specifying source_port had no effect if source was
10 not specified. We now use the appropriate wildcard source in
11 that case.
12
13 * dns/resolver.py (Resolver.query): source_port may now be
14 specified.
15
16 * dns/resolver.py (Resolver.query): Switch to TCP when a UDP
17 response is truncated. Handle nameservers that serve on UDP
18 but not TCP.
19
20 2012-04-07 Bob Halley <halley@dnspython.org>
21
22 * dns/zone.py (from_xfr): dns.zone.from_xfr() now takes a
23 'check_origin' parameter which defaults to True. If set to
24 False, then dnspython will not make origin checks on the zone.
25 Thanks to Carlos Perez for the report.
26
27 * dns/rdtypes/ANY/SSHFP.py (SSHFP.from_text): Allow whitespace in
28 the text string. Thanks to Jan Andres for the report and the
29 patch.
30
31 * dns/message.py (from_wire): dns.message.from_wire() now takes
32 an 'ignore_trailing' parameter which defaults to False. If set
33 to True, then trailing junk will be ignored instead of causing
34 TrailingJunk to be raised. Thanks to Shane Huntley for
35 contributing the patch.
36
37 2011-08-22 Bob Halley <halley@dnspython.org>
38
39 * dns/resolver.py: Added LRUCache. In this cache implementation,
40 the cache size is limited to a user-specified number of nodes, and
41 when adding a new node to a full cache the least-recently used
42 node is removed.
43
44 2011-07-13 Bob Halley <halley@dnspython.org>
45
46 * dns/resolver.py: dns.resolver.override_system_resolver()
47 overrides the socket module's versions of getaddrinfo(),
48 getnameinfo(), getfqdn(), gethostbyname(), gethostbyname_ex() and
49 gethostbyaddr() with an implementation which uses a dnspython stub
50 resolver instead of the system's stub resolver. This can be
51 useful in testing situations where you want to control the
52 resolution behavior of python code without having to change the
53 system's resolver settings (e.g. /etc/resolv.conf).
54 dns.resolver.restore_system_resolver() undoes the change.
55
56 2011-07-08 Bob Halley <halley@dnspython.org>
57
58 * dns/ipv4.py: dnspython now provides its own, stricter, versions
59 of IPv4 inet_ntoa() and inet_aton() instead of using the OS's
60 versions.
61
62 * dns/ipv6.py: inet_aton() now bounds checks embedded IPv4 addresses
63 more strictly. Also, now only dns.exception.SyntaxError can be
64 raised on bad input.
65
66 2011-04-05 Bob Halley <halley@dnspython.org>
67
68 * Old DNSSEC types (KEY, NXT, and SIG) have been removed.
69
70 * Bounds checking of slices in rdata wire processing is now more
71 strict, and bounds errors (e.g. we got less data than was
72 expected) now raise dns.exception.FormError rather than
73 IndexError.
74
75 2011-03-28 Bob Halley <halley@dnspython.org>
76
77 * (Version 1.9.4 released)
78
079 2011-03-24 Bob Halley <halley@dnspython.org>
180
281 * dns/rdata.py (Rdata._wire_cmp): We need to specify no
00 Metadata-Version: 1.1
11 Name: dnspython
2 Version: 1.9.4
2 Version: 1.10.0
33 Summary: DNS toolkit
44 Home-page: http://www.dnspython.org
55 Author: Bob Halley
66 Author-email: halley@dnspython.org
77 License: BSD-like
8 Download-URL: http://www.dnspython.org/kits/1.9.4/dnspython-1.9.4.tar.gz
8 Download-URL: http://www.dnspython.org/kits/1.10.0/dnspython-1.10.0.tar.gz
99 Description: dnspython is a DNS toolkit for Python. It supports almost all
1010 record types. It can be used for queries, zone transfers, and dynamic
1111 updates. It supports TSIG authenticated messages and EDNS0.
2121
2222 ABOUT THIS RELEASE
2323
24 This is dnspython 1.9.4
24 This is dnspython 1.10.0
25
26 New since 1.9.4:
27
28 Added dns.resolver.LRUCache. In this cache implementation,
29 the cache size is limited to a user-specified number of nodes,
30 and when adding a new node to a full cache the least-recently
31 used node is removed. If you're crawling the web or otherwise
32 doing lots of resolutions and you are using a cache, switching
33 to the LRUCache is recommended.
34
35 dns.resolver.query() will try TCP if a UDP response is
36 truncated.
37
38 The python socket module's DNS methods can be now be overriden
39 with implementations that use dnspython's resolver.
40
41 Old DNSSEC types KEY, NXT, and SIG have been removed.
42
43 Whitespace is allowed in SSHFP fingerprints.
44
45 Origin checking in dns.zone.from_xfr() can be disabled.
46
47 Trailing junk checking can be disabled.
48
49 A source port can be specified when creating a resolver query.
50
51 All EDNS values may now be specified to dns.message.make_query().
52
53 Bugs fixed since 1.9.4:
54
55 IPv4 and IPv6 address processing is now stricter.
56
57 Bounds checking of slices in rdata wire processing is now more
58 strict, and bounds errors (e.g. we got less data than was
59 expected) now raise dns.exception.FormError rather than
60 IndexError.
61
62 Specifying a source port without specifying source used to
63 have no effect, but now uses the wildcard address and the
64 specified port.
2565
2666 New since 1.9.3:
2767
+0
-17
TODO less more
0 Tutorial documentation
1
2 More examples
3
4 It would be nice to have a tokenizer that used regular expressions
5 because it would be faster.
6
7 Teach the resolver about DNAME (right now it relies on the server adding
8 synthesized CNAMEs)
9
10 Add TKEY support.
11
12 TSIG works, but needs cleaning up -- probably better encapsulation of
13 TSIG state to make things much simpler and easier to use.
14
15 Pickling support.
16
0 # Copyright (C) 2003-2007, 2009 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
4848 'rdtypes',
4949 'update',
5050 'version',
51 'wiredata',
5152 'zone',
5253 ]
0 # Copyright (C) 2003-2007, 2009 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
9898 return (ord(rdata[-3]) << 8) + ord(rdata[-2])
9999 else:
100100 total = 0
101 for i in range(len(rdata) / 2):
101 for i in range(len(rdata) // 2):
102102 total += (ord(rdata[2 * i]) << 8) + ord(rdata[2 * i + 1])
103103 if len(rdata) % 2 != 0:
104104 total += ord(rdata[len(rdata) - 1]) << 8
298298 if _is_rsa(rrsig.algorithm):
299299 # PKCS1 algorithm identifier goop
300300 digest = _make_algorithm_id(rrsig.algorithm) + digest
301 padlen = keylen / 8 - len(digest) - 3
301 padlen = keylen // 8 - len(digest) - 3
302302 digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest
303303 elif _is_dsa(rrsig.algorithm):
304304 pass
0 # Copyright (C) 2006, 2007, 2009 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
3131 @type text: str
3232 @param origin: The domain in which the number should be constructed.
3333 The default is e164.arpa.
34 @type: dns.name.Name object or None
34 @type origin: dns.name.Name object or None
3535 @rtype: dns.name.Name object
3636 """
3737 parts = [d for d in text if d.isdigit()]
4444 @type name: dns.name.Name object.
4545 @param origin: A domain containing the ENUM domain name. The
4646 name is relativized to this domain before being converted to text.
47 @type: dns.name.Name object or None
47 @type origin: dns.name.Name object or None
4848 @param want_plus_prefix: if True, add a '+' to the beginning of the
4949 returned number.
5050 @rtype: str
0 # Copyright (C) 2009 Nominum, Inc.
0 # Copyright (C) 2009, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2222
2323 def __init__(self, otype):
2424 """Initialize an option.
25 @param rdtype: The rdata type
26 @type rdtype: int
25 @param otype: The rdata type
26 @type otype: int
2727 """
2828 self.otype = otype
2929
0 # Copyright (C) 2009 Nominum, Inc.
0 # Copyright (C) 2009, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2010 Nominum, Inc.
0 # Copyright (C) 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
1414
1515 """IPv4 helper functions."""
1616
17 import socket
18 import sys
17 import struct
1918
20 if sys.hexversion < 0x02030000 or sys.platform == 'win32':
21 #
22 # Some versions of Python 2.2 have an inet_aton which rejects
23 # the valid IP address '255.255.255.255'. It appears this
24 # problem is still present on the Win32 platform even in 2.3.
25 # We'll work around the problem.
26 #
27 def inet_aton(text):
28 if text == '255.255.255.255':
29 return '\xff' * 4
30 else:
31 return socket.inet_aton(text)
32 else:
33 inet_aton = socket.inet_aton
19 import dns.exception
3420
35 inet_ntoa = socket.inet_ntoa
21 def inet_ntoa(address):
22 """Convert an IPv4 address in network form to text form.
23
24 @param address: The IPv4 address
25 @type address: string
26 @returns: string
27 """
28 if len(address) != 4:
29 raise dns.exception.SyntaxError
30 return '%u.%u.%u.%u' % (ord(address[0]), ord(address[1]),
31 ord(address[2]), ord(address[3]))
32
33 def inet_aton(text):
34 """Convert an IPv4 address in text form to network form.
35
36 @param text: The IPv4 address
37 @type text: string
38 @returns: string
39 """
40 parts = text.split('.')
41 if len(parts) != 4:
42 raise dns.exception.SyntaxError
43 for part in parts:
44 if not part.isdigit():
45 raise dns.exception.SyntaxError
46 if len(part) > 1 and part[0] == '0':
47 # No leading zeros
48 raise dns.exception.SyntaxError
49 try:
50 bytes = [int(part) for part in parts]
51 return struct.pack('BBBB', *bytes)
52 except:
53 raise dns.exception.SyntaxError
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
8888 hex = ':'.join(chunks)
8989 return hex
9090
91 _v4_ending = re.compile(r'(.*):(\d+)\.(\d+)\.(\d+)\.(\d+)$')
91 _v4_ending = re.compile(r'(.*):(\d+\.\d+\.\d+\.\d+)$')
9292 _colon_colon_start = re.compile(r'::.*')
9393 _colon_colon_end = re.compile(r'.*::$')
9494
112112 #
113113 m = _v4_ending.match(text)
114114 if not m is None:
115 text = "%s:%04x:%04x" % (m.group(1),
116 int(m.group(2)) * 256 + int(m.group(3)),
117 int(m.group(4)) * 256 + int(m.group(5)))
115 b = dns.ipv4.inet_aton(m.group(2))
116 text = "%s:%02x%02x:%02x%02x" % (m.group(1), ord(b[0]), ord(b[1]),
117 ord(b[2]), ord(b[3]))
118118 #
119119 # Try to turn '::<whatever>' into ':<whatever>'; if no match try to
120120 # turn '<whatever>::' into '<whatever>:'
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
3333 import dns.rrset
3434 import dns.renderer
3535 import dns.tsig
36 import dns.wiredata
3637
3738 class ShortHeader(dns.exception.FormError):
3839 """Raised if the DNS packet passed to from_wire() is too short."""
569570 @type updating: bool
570571 @ivar one_rr_per_rrset: Put each RR into its own RRset?
571572 @type one_rr_per_rrset: bool
573 @ivar ignore_trailing: Ignore trailing junk at end of request?
574 @type ignore_trailing: bool
572575 @ivar zone_rdclass: The class of the zone in messages which are
573576 DNS dynamic updates.
574577 @type zone_rdclass: int
575578 """
576579
577580 def __init__(self, wire, message, question_only=False,
578 one_rr_per_rrset=False):
579 self.wire = wire
581 one_rr_per_rrset=False, ignore_trailing=False):
582 self.wire = dns.wiredata.maybe_wrap(wire)
580583 self.message = message
581584 self.current = 0
582585 self.updating = False
583586 self.zone_rdclass = dns.rdataclass.IN
584587 self.question_only = question_only
585588 self.one_rr_per_rrset = one_rr_per_rrset
589 self.ignore_trailing = ignore_trailing
586590
587591 def _get_question(self, qcount):
588592 """Read the next I{qcount} records from the wire data and add them to
720724 self._get_section(self.message.answer, ancount)
721725 self._get_section(self.message.authority, aucount)
722726 self._get_section(self.message.additional, adcount)
723 if self.current != l:
727 if not self.ignore_trailing and self.current != l:
724728 raise TrailingJunk
725729 if self.message.multi and self.message.tsig_ctx and \
726730 not self.message.had_tsig:
729733
730734 def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
731735 tsig_ctx = None, multi = False, first = True,
732 question_only = False, one_rr_per_rrset = False):
736 question_only = False, one_rr_per_rrset = False,
737 ignore_trailing = False):
733738 """Convert a DNS wire format message into a message
734739 object.
735740
755760 @type question_only: bool
756761 @param one_rr_per_rrset: Put each RR into its own RRset
757762 @type one_rr_per_rrset: bool
763 @param ignore_trailing: Ignore trailing junk at end of request?
764 @type ignore_trailing: bool
758765 @raises ShortHeader: The message is less than 12 octets long.
759766 @raises TrailingJunk: There were octets in the message past the end
760767 of the proper DNS message.
773780 m.multi = multi
774781 m.first = first
775782
776 reader = _WireReader(wire, m, question_only, one_rr_per_rrset)
783 reader = _WireReader(wire, m, question_only, one_rr_per_rrset,
784 ignore_trailing)
777785 reader.read()
778786
779787 return m
10131021 return m
10141022
10151023 def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns=None,
1016 want_dnssec=False):
1024 want_dnssec=False, ednsflags=0, payload=1280,
1025 request_payload=None, options=None):
10171026 """Make a query message.
10181027
10191028 The query name, type, and class may all be specified either
10341043 @type use_edns: int or bool or None
10351044 @param want_dnssec: Should the query indicate that DNSSEC is desired?
10361045 @type want_dnssec: bool
1046 @param ednsflags: EDNS flag values.
1047 @type ednsflags: int
1048 @param payload: The EDNS sender's payload field, which is the maximum
1049 size of UDP datagram the sender can handle.
1050 @type payload: int
1051 @param request_payload: The EDNS payload size to use when sending
1052 this message. If not specified, defaults to the value of payload.
1053 @type request_payload: int or None
1054 @param options: The EDNS options
1055 @type options: None or list of dns.edns.Option objects
1056 @see: RFC 2671
10371057 @rtype: dns.message.Message object"""
10381058
10391059 if isinstance(qname, (str, unicode)):
10461066 m.flags |= dns.flags.RD
10471067 m.find_rrset(m.question, qname, rdclass, rdtype, create=True,
10481068 force_unique=True)
1049 m.use_edns(use_edns)
1069 m.use_edns(use_edns, ednsflags, payload, request_payload, options)
10501070 m.want_dnssec(want_dnssec)
10511071 return m
10521072
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2828 import encodings.idna
2929
3030 import dns.exception
31 import dns.wiredata
3132
3233 NAMERELN_NONE = 0
3334 NAMERELN_SUPERDOMAIN = 1
669670
670671 if not isinstance(message, str):
671672 raise ValueError("input to from_wire() must be a byte string")
673 message = dns.wiredata.maybe_wrap(message)
672674 labels = []
673675 biggest_pointer = current
674676 hops = 0
677679 cused = 1
678680 while count != 0:
679681 if count < 64:
680 labels.append(message[current : current + count])
682 labels.append(message[current : current + count].unwrap())
681683 current += count
682684 if hops == 0:
683685 cused += count
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
166166 at the node, it stores I{replacement} itself.
167167 """
168168
169 if not isinstance(replacement, dns.rdataset.Rdataset):
170 raise ValueError, 'replacement is not an rdataset'
169171 self.delete_rdataset(replacement.rdclass, replacement.rdtype,
170172 replacement.covers)
171173 self.rdatasets.append(replacement)
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
4545 return time.time() + timeout
4646
4747 def _poll_for(fd, readable, writable, error, timeout):
48 """
49 @param fd: File descriptor (int).
50 @param readable: Whether to wait for readability (bool).
51 @param writable: Whether to wait for writability (bool).
52 @param expiration: Deadline timeout (expiration time, in seconds (float)).
53
48 """Poll polling backend.
49 @param fd: File descriptor
50 @type fd: int
51 @param readable: Whether to wait for readability
52 @type readable: bool
53 @param writable: Whether to wait for writability
54 @type writable: bool
55 @param timeout: Deadline timeout (expiration time, in seconds)
56 @type timeout: float
5457 @return True on success, False on timeout
5558 """
5659 event_mask = 0
7275 return bool(event_list)
7376
7477 def _select_for(fd, readable, writable, error, timeout):
75 """
76 @param fd: File descriptor (int).
77 @param readable: Whether to wait for readability (bool).
78 @param writable: Whether to wait for writability (bool).
79 @param expiration: Deadline timeout (expiration time, in seconds (float)).
80
78 """Select polling backend.
79 @param fd: File descriptor
80 @type fd: int
81 @param readable: Whether to wait for readability
82 @type readable: bool
83 @param writable: Whether to wait for writability
84 @type writable: bool
85 @param timeout: Deadline timeout (expiration time, in seconds)
86 @type timeout: float
8187 @return True on success, False on timeout
8288 """
8389 rset, wset, xset = [], [], []
143149 n2 = dns.inet.inet_pton(af, a2[0])
144150 return n1 == n2 and a1[1:] == a2[1:]
145151
152 def _destination_and_source(af, where, port, source, source_port):
153 # Apply defaults and compute destination and source tuples
154 # suitable for use in connect(), sendto(), or bind().
155 if af is None:
156 try:
157 af = dns.inet.af_for_address(where)
158 except:
159 af = dns.inet.AF_INET
160 if af == dns.inet.AF_INET:
161 destination = (where, port)
162 if source is not None or source_port != 0:
163 if source is None:
164 source = '0.0.0.0'
165 source = (source, source_port)
166 elif af == dns.inet.AF_INET6:
167 destination = (where, port, 0, 0)
168 if source is not None or source_port != 0:
169 if source is None:
170 source = '::'
171 source = (source, source_port, 0, 0)
172 return (af, destination, source)
173
146174 def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
147175 ignore_unexpected=False, one_rr_per_rrset=False):
148176 """Return the response obtained after sending a query via UDP.
161189 If the inference attempt fails, AF_INET is used.
162190 @type af: int
163191 @rtype: dns.message.Message object
164 @param source: source address. The default is the IPv4 wildcard address.
192 @param source: source address. The default is the wildcard address.
165193 @type source: string
166194 @param source_port: The port from which to send the message.
167195 The default is 0.
174202 """
175203
176204 wire = q.to_wire()
177 if af is None:
178 try:
179 af = dns.inet.af_for_address(where)
180 except:
181 af = dns.inet.AF_INET
182 if af == dns.inet.AF_INET:
183 destination = (where, port)
184 if source is not None:
185 source = (source, source_port)
186 elif af == dns.inet.AF_INET6:
187 destination = (where, port, 0, 0)
188 if source is not None:
189 source = (source, source_port, 0, 0)
205 (af, destination, source) = _destination_and_source(af, where, port, source,
206 source_port)
190207 s = socket.socket(af, socket.SOCK_DGRAM, 0)
191208 try:
192209 expiration = _compute_expiration(timeout)
269286 If the inference attempt fails, AF_INET is used.
270287 @type af: int
271288 @rtype: dns.message.Message object
272 @param source: source address. The default is the IPv4 wildcard address.
289 @param source: source address. The default is the wildcard address.
273290 @type source: string
274291 @param source_port: The port from which to send the message.
275292 The default is 0.
279296 """
280297
281298 wire = q.to_wire()
282 if af is None:
283 try:
284 af = dns.inet.af_for_address(where)
285 except:
286 af = dns.inet.AF_INET
287 if af == dns.inet.AF_INET:
288 destination = (where, port)
289 if source is not None:
290 source = (source, source_port)
291 elif af == dns.inet.AF_INET6:
292 destination = (where, port, 0, 0)
293 if source is not None:
294 source = (source, source_port, 0, 0)
299 (af, destination, source) = _destination_and_source(af, where, port, source,
300 source_port)
295301 s = socket.socket(af, socket.SOCK_STREAM, 0)
296302 try:
297303 expiration = _compute_expiration(timeout)
356362 take.
357363 @type lifetime: float
358364 @rtype: generator of dns.message.Message objects.
359 @param source: source address. The default is the IPv4 wildcard address.
365 @param source: source address. The default is the wildcard address.
360366 @type source: string
361367 @param source_port: The port from which to send the message.
362368 The default is 0.
383389 if not keyring is None:
384390 q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
385391 wire = q.to_wire()
386 if af is None:
387 try:
388 af = dns.inet.af_for_address(where)
389 except:
390 af = dns.inet.AF_INET
391 if af == dns.inet.AF_INET:
392 destination = (where, port)
393 if source is not None:
394 source = (source, source_port)
395 elif af == dns.inet.AF_INET6:
396 destination = (where, port, 0, 0)
397 if source is not None:
398 source = (source, source_port, 0, 0)
392 (af, destination, source) = _destination_and_source(af, where, port, source,
393 source_port)
399394 if use_udp:
400395 if rdtype != dns.rdatatype.IXFR:
401396 raise ValueError('cannot do a UDP AXFR')
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
3131 import dns.rdataclass
3232 import dns.rdatatype
3333 import dns.tokenizer
34 import dns.wiredata
3435
3536 _hex_chunksize = 32
3637
411412 Once a class is chosen, its from_text() class method is called
412413 with the parameters to this function.
413414
415 If I{tok} is a string, then a tokenizer is created and the string
416 is used as its input.
417
414418 @param rdclass: The rdata class
415419 @type rdclass: int
416420 @param rdtype: The rdata type
417421 @type rdtype: int
418 @param tok: The tokenizer
419 @type tok: dns.tokenizer.Tokenizer
422 @param tok: The tokenizer or input text
423 @type tok: dns.tokenizer.Tokenizer or string
420424 @param origin: The origin to use for relative names
421425 @type origin: dns.name.Name
422426 @param relativize: Should names be relativized?
468472 @type origin: dns.name.Name
469473 @rtype: dns.rdata.Rdata instance"""
470474
475 wire = dns.wiredata.maybe_wrap(wire)
471476 cls = get_rdata_class(rdclass, rdtype)
472477 return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin)
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
7373 @param text: the text
7474 @type text: string
7575 @rtype: int
76 @raises dns.rdataclass.UnknownRdataClass: the class is unknown
76 @raises dns.rdataclass.UnknownRdataclass: the class is unknown
7777 @raises ValueError: the rdata class value is not >= 0 and <= 65535
7878 """
7979
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
105105 file.write(self.certificate)
106106
107107 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
108 prefix = wire[current : current + 5]
108 prefix = wire[current : current + 5].unwrap()
109109 current += 5
110110 rdlen -= 5
111111 if rdlen < 0:
112112 raise dns.exception.FormError
113113 (certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix)
114 certificate = wire[current : current + rdlen]
114 certificate = wire[current : current + rdlen].unwrap()
115115 return cls(rdclass, rdtype, certificate_type, key_tag, algorithm,
116116 certificate)
117117
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414
15 import dns.rdtypes.keybase
15
16 import struct
17
18 import dns.exception
19 import dns.dnssec
20 import dns.rdata
1621
1722 # flag constants
1823 SEP = 0x0001
1924 REVOKE = 0x0080
2025 ZONE = 0x0100
2126
22 class DNSKEY(dns.rdtypes.keybase.KEYBase):
23 """DNSKEY record"""
24 pass
27 class DNSKEY(dns.rdata.Rdata):
28 """DNSKEY record
29
30 @ivar flags: the key flags
31 @type flags: int
32 @ivar protocol: the protocol for which this key may be used
33 @type protocol: int
34 @ivar algorithm: the algorithm used for the key
35 @type algorithm: int
36 @ivar key: the public key
37 @type key: string"""
38
39 __slots__ = ['flags', 'protocol', 'algorithm', 'key']
40
41 def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key):
42 super(DNSKEY, self).__init__(rdclass, rdtype)
43 self.flags = flags
44 self.protocol = protocol
45 self.algorithm = algorithm
46 self.key = key
47
48 def to_text(self, origin=None, relativize=True, **kw):
49 return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
50 dns.rdata._base64ify(self.key))
51
52 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
53 flags = tok.get_uint16()
54 protocol = tok.get_uint8()
55 algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
56 chunks = []
57 while 1:
58 t = tok.get().unescape()
59 if t.is_eol_or_eof():
60 break
61 if not t.is_identifier():
62 raise dns.exception.SyntaxError
63 chunks.append(t.value)
64 b64 = ''.join(chunks)
65 key = b64.decode('base64_codec')
66 return cls(rdclass, rdtype, flags, protocol, algorithm, key)
67
68 from_text = classmethod(from_text)
69
70 def to_wire(self, file, compress = None, origin = None):
71 header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
72 file.write(header)
73 file.write(self.key)
74
75 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
76 if rdlen < 4:
77 raise dns.exception.FormError
78 header = struct.unpack('!HBB', wire[current : current + 4])
79 current += 4
80 rdlen -= 4
81 key = wire[current : current + rdlen].unwrap()
82 return cls(rdclass, rdtype, header[0], header[1], header[2],
83 key)
84
85 from_wire = classmethod(from_wire)
86
87 def _cmp(self, other):
88 hs = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
89 ho = struct.pack("!HBB", other.flags, other.protocol, other.algorithm)
90 v = cmp(hs, ho)
91 if v == 0:
92 v = cmp(self.key, other.key)
93 return v
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2828 raise dns.exception.FormError
2929 if not right == '' and not right.isdigit():
3030 raise dns.exception.FormError
31
31
3232 class GPOS(dns.rdata.Rdata):
3333 """GPOS record
3434
4141 @see: RFC 1712"""
4242
4343 __slots__ = ['latitude', 'longitude', 'altitude']
44
44
4545 def __init__(self, rdclass, rdtype, latitude, longitude, altitude):
4646 super(GPOS, self).__init__(rdclass, rdtype)
4747 if isinstance(latitude, float) or \
6565
6666 def to_text(self, origin=None, relativize=True, **kw):
6767 return '%s %s %s' % (self.latitude, self.longitude, self.altitude)
68
68
6969 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
7070 latitude = tok.get_string()
7171 longitude = tok.get_string()
7272 altitude = tok.get_string()
7373 tok.get_eol()
7474 return cls(rdclass, rdtype, latitude, longitude, altitude)
75
75
7676 from_text = classmethod(from_text)
7777
7878 def to_wire(self, file, compress = None, origin = None):
9191 byte = chr(l)
9292 file.write(byte)
9393 file.write(self.altitude)
94
94
9595 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
9696 l = ord(wire[current])
9797 current += 1
9898 rdlen -= 1
9999 if l > rdlen:
100100 raise dns.exception.FormError
101 latitude = wire[current : current + l]
101 latitude = wire[current : current + l].unwrap()
102102 current += l
103103 rdlen -= l
104104 l = ord(wire[current])
106106 rdlen -= 1
107107 if l > rdlen:
108108 raise dns.exception.FormError
109 longitude = wire[current : current + l]
109 longitude = wire[current : current + l].unwrap()
110110 current += l
111111 rdlen -= l
112112 l = ord(wire[current])
114114 rdlen -= 1
115115 if l != rdlen:
116116 raise dns.exception.FormError
117 altitude = wire[current : current + l]
117 altitude = wire[current : current + l].unwrap()
118118 return cls(rdclass, rdtype, latitude, longitude, altitude)
119119
120120 from_wire = classmethod(from_wire)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2626 @see: RFC 1035"""
2727
2828 __slots__ = ['cpu', 'os']
29
29
3030 def __init__(self, rdclass, rdtype, cpu, os):
3131 super(HINFO, self).__init__(rdclass, rdtype)
3232 self.cpu = cpu
3535 def to_text(self, origin=None, relativize=True, **kw):
3636 return '"%s" "%s"' % (dns.rdata._escapify(self.cpu),
3737 dns.rdata._escapify(self.os))
38
38
3939 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
4040 cpu = tok.get_string()
4141 os = tok.get_string()
4242 tok.get_eol()
4343 return cls(rdclass, rdtype, cpu, os)
44
44
4545 from_text = classmethod(from_text)
4646
4747 def to_wire(self, file, compress = None, origin = None):
5555 byte = chr(l)
5656 file.write(byte)
5757 file.write(self.os)
58
58
5959 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
6060 l = ord(wire[current])
6161 current += 1
6262 rdlen -= 1
6363 if l > rdlen:
6464 raise dns.exception.FormError
65 cpu = wire[current : current + l]
65 cpu = wire[current : current + l].unwrap()
6666 current += l
6767 rdlen -= l
6868 l = ord(wire[current])
7070 rdlen -= 1
7171 if l != rdlen:
7272 raise dns.exception.FormError
73 os = wire[current : current + l]
73 os = wire[current : current + l].unwrap()
7474 return cls(rdclass, rdtype, cpu, os)
7575
7676 from_wire = classmethod(from_wire)
0 # Copyright (C) 2010 Nominum, Inc.
0 # Copyright (C) 2010, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
8585 wire[current : current + 4])
8686 current += 4
8787 rdlen -= 4
88 hit = wire[current : current + lh]
88 hit = wire[current : current + lh].unwrap()
8989 current += lh
9090 rdlen -= lh
91 key = wire[current : current + lk]
91 key = wire[current : current + lk].unwrap()
9292 current += lk
9393 rdlen -= lk
9494 servers = []
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
7272 rdlen -= 1
7373 if l > rdlen:
7474 raise dns.exception.FormError
75 address = wire[current : current + l]
75 address = wire[current : current + l].unwrap()
7676 current += l
7777 rdlen -= l
7878 if rdlen > 0:
8181 rdlen -= 1
8282 if l != rdlen:
8383 raise dns.exception.FormError
84 subaddress = wire[current : current + l]
84 subaddress = wire[current : current + l].unwrap()
8585 else:
8686 subaddress = ''
8787 return cls(rdclass, rdtype, address, subaddress)
+0
-20
dns/rdtypes/ANY/KEY.py less more
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
1 #
2 # Permission to use, copy, modify, and distribute this software and its
3 # documentation for any purpose with or without fee is hereby granted,
4 # provided that the above copyright notice and this permission notice
5 # appear in all copies.
6 #
7 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import dns.rdtypes.keybase
16
17 class KEY(dns.rdtypes.keybase.KEYBase):
18 """KEY record"""
19 pass
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
7878 bitmap = ['\0'] * 32
7979 window = new_window
8080 offset = nrdtype % 256
81 byte = offset / 8
81 byte = offset // 8
8282 bit = offset % 8
8383 octets = byte + 1
8484 bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
110110 rdlen -= 2
111111 if rdlen < octets:
112112 raise dns.exception.FormError("bad NSEC bitmap length")
113 bitmap = wire[current : current + octets]
113 bitmap = wire[current : current + octets].unwrap()
114114 current += octets
115115 rdlen -= octets
116116 windows.append((window, bitmap))
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
117117 bitmap = ['\0'] * 32
118118 window = new_window
119119 offset = nrdtype % 256
120 byte = offset / 8
120 byte = offset // 8
121121 bit = offset % 8
122122 octets = byte + 1
123123 bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
144144 wire[current : current + 5])
145145 current += 5
146146 rdlen -= 5
147 salt = wire[current : current + slen]
147 salt = wire[current : current + slen].unwrap()
148148 current += slen
149149 rdlen -= slen
150150 (nlen, ) = struct.unpack('!B', wire[current])
151151 current += 1
152152 rdlen -= 1
153 next = wire[current : current + nlen]
153 next = wire[current : current + nlen].unwrap()
154154 current += nlen
155155 rdlen -= nlen
156156 windows = []
165165 rdlen -= 2
166166 if rdlen < octets:
167167 raise dns.exception.FormError("bad NSEC3 bitmap length")
168 bitmap = wire[current : current + octets]
168 bitmap = wire[current : current + octets].unwrap()
169169 current += octets
170170 rdlen -= octets
171171 windows.append((window, bitmap))
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
7070 wire[current : current + 5])
7171 current += 5
7272 rdlen -= 5
73 salt = wire[current : current + slen]
73 salt = wire[current : current + slen].unwrap()
7474 current += slen
7575 rdlen -= slen
7676 if rdlen != 0:
+0
-99
dns/rdtypes/ANY/NXT.py less more
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
1 #
2 # Permission to use, copy, modify, and distribute this software and its
3 # documentation for any purpose with or without fee is hereby granted,
4 # provided that the above copyright notice and this permission notice
5 # appear in all copies.
6 #
7 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import dns.exception
16 import dns.rdata
17 import dns.rdatatype
18 import dns.name
19
20 class NXT(dns.rdata.Rdata):
21 """NXT record
22
23 @ivar next: the next name
24 @type next: dns.name.Name object
25 @ivar bitmap: the type bitmap
26 @type bitmap: string
27 @see: RFC 2535"""
28
29 __slots__ = ['next', 'bitmap']
30
31 def __init__(self, rdclass, rdtype, next, bitmap):
32 super(NXT, self).__init__(rdclass, rdtype)
33 self.next = next
34 self.bitmap = bitmap
35
36 def to_text(self, origin=None, relativize=True, **kw):
37 next = self.next.choose_relativity(origin, relativize)
38 bits = []
39 for i in xrange(0, len(self.bitmap)):
40 byte = ord(self.bitmap[i])
41 for j in xrange(0, 8):
42 if byte & (0x80 >> j):
43 bits.append(dns.rdatatype.to_text(i * 8 + j))
44 text = ' '.join(bits)
45 return '%s %s' % (next, text)
46
47 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
48 next = tok.get_name()
49 next = next.choose_relativity(origin, relativize)
50 bitmap = ['\x00', '\x00', '\x00', '\x00',
51 '\x00', '\x00', '\x00', '\x00',
52 '\x00', '\x00', '\x00', '\x00',
53 '\x00', '\x00', '\x00', '\x00' ]
54 while 1:
55 token = tok.get().unescape()
56 if token.is_eol_or_eof():
57 break
58 if token.value.isdigit():
59 nrdtype = int(token.value)
60 else:
61 nrdtype = dns.rdatatype.from_text(token.value)
62 if nrdtype == 0:
63 raise dns.exception.SyntaxError("NXT with bit 0")
64 if nrdtype > 127:
65 raise dns.exception.SyntaxError("NXT with bit > 127")
66 i = nrdtype // 8
67 bitmap[i] = chr(ord(bitmap[i]) | (0x80 >> (nrdtype % 8)))
68 bitmap = dns.rdata._truncate_bitmap(bitmap)
69 return cls(rdclass, rdtype, next, bitmap)
70
71 from_text = classmethod(from_text)
72
73 def to_wire(self, file, compress = None, origin = None):
74 self.next.to_wire(file, None, origin)
75 file.write(self.bitmap)
76
77 def to_digestable(self, origin = None):
78 return self.next.to_digestable(origin) + self.bitmap
79
80 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
81 (next, cused) = dns.name.from_wire(wire[: current + rdlen], current)
82 current += cused
83 rdlen -= cused
84 bitmap = wire[current : current + rdlen]
85 if not origin is None:
86 next = next.relativize(origin)
87 return cls(rdclass, rdtype, next, bitmap)
88
89 from_wire = classmethod(from_wire)
90
91 def choose_relativity(self, origin = None, relativize = True):
92 self.next = self.next.choose_relativity(origin, relativize)
93
94 def _cmp(self, other):
95 v = cmp(self.next, other.next)
96 if v == 0:
97 v = cmp(self.bitmap, other.bitmap)
98 return v
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414
15 import dns.rdtypes.sigbase
15 import calendar
16 import struct
17 import time
1618
17 class RRSIG(dns.rdtypes.sigbase.SIGBase):
18 """RRSIG record"""
19 import dns.dnssec
20 import dns.exception
21 import dns.rdata
22 import dns.rdatatype
23
24 class BadSigTime(dns.exception.DNSException):
25 """Raised when a SIG or RRSIG RR's time cannot be parsed."""
1926 pass
27
28 def sigtime_to_posixtime(what):
29 if len(what) != 14:
30 raise BadSigTime
31 year = int(what[0:4])
32 month = int(what[4:6])
33 day = int(what[6:8])
34 hour = int(what[8:10])
35 minute = int(what[10:12])
36 second = int(what[12:14])
37 return calendar.timegm((year, month, day, hour, minute, second,
38 0, 0, 0))
39
40 def posixtime_to_sigtime(what):
41 return time.strftime('%Y%m%d%H%M%S', time.gmtime(what))
42
43 class RRSIG(dns.rdata.Rdata):
44 """RRSIG record
45
46 @ivar type_covered: the rdata type this signature covers
47 @type type_covered: int
48 @ivar algorithm: the algorithm used for the sig
49 @type algorithm: int
50 @ivar labels: number of labels
51 @type labels: int
52 @ivar original_ttl: the original TTL
53 @type original_ttl: long
54 @ivar expiration: signature expiration time
55 @type expiration: long
56 @ivar inception: signature inception time
57 @type inception: long
58 @ivar key_tag: the key tag
59 @type key_tag: int
60 @ivar signer: the signer
61 @type signer: dns.name.Name object
62 @ivar signature: the signature
63 @type signature: string"""
64
65 __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl',
66 'expiration', 'inception', 'key_tag', 'signer',
67 'signature']
68
69 def __init__(self, rdclass, rdtype, type_covered, algorithm, labels,
70 original_ttl, expiration, inception, key_tag, signer,
71 signature):
72 super(RRSIG, self).__init__(rdclass, rdtype)
73 self.type_covered = type_covered
74 self.algorithm = algorithm
75 self.labels = labels
76 self.original_ttl = original_ttl
77 self.expiration = expiration
78 self.inception = inception
79 self.key_tag = key_tag
80 self.signer = signer
81 self.signature = signature
82
83 def covers(self):
84 return self.type_covered
85
86 def to_text(self, origin=None, relativize=True, **kw):
87 return '%s %d %d %d %s %s %d %s %s' % (
88 dns.rdatatype.to_text(self.type_covered),
89 self.algorithm,
90 self.labels,
91 self.original_ttl,
92 posixtime_to_sigtime(self.expiration),
93 posixtime_to_sigtime(self.inception),
94 self.key_tag,
95 self.signer,
96 dns.rdata._base64ify(self.signature)
97 )
98
99 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
100 type_covered = dns.rdatatype.from_text(tok.get_string())
101 algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
102 labels = tok.get_int()
103 original_ttl = tok.get_ttl()
104 expiration = sigtime_to_posixtime(tok.get_string())
105 inception = sigtime_to_posixtime(tok.get_string())
106 key_tag = tok.get_int()
107 signer = tok.get_name()
108 signer = signer.choose_relativity(origin, relativize)
109 chunks = []
110 while 1:
111 t = tok.get().unescape()
112 if t.is_eol_or_eof():
113 break
114 if not t.is_identifier():
115 raise dns.exception.SyntaxError
116 chunks.append(t.value)
117 b64 = ''.join(chunks)
118 signature = b64.decode('base64_codec')
119 return cls(rdclass, rdtype, type_covered, algorithm, labels,
120 original_ttl, expiration, inception, key_tag, signer,
121 signature)
122
123 from_text = classmethod(from_text)
124
125 def to_wire(self, file, compress = None, origin = None):
126 header = struct.pack('!HBBIIIH', self.type_covered,
127 self.algorithm, self.labels,
128 self.original_ttl, self.expiration,
129 self.inception, self.key_tag)
130 file.write(header)
131 self.signer.to_wire(file, None, origin)
132 file.write(self.signature)
133
134 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
135 header = struct.unpack('!HBBIIIH', wire[current : current + 18])
136 current += 18
137 rdlen -= 18
138 (signer, cused) = dns.name.from_wire(wire[: current + rdlen], current)
139 current += cused
140 rdlen -= cused
141 if not origin is None:
142 signer = signer.relativize(origin)
143 signature = wire[current : current + rdlen].unwrap()
144 return cls(rdclass, rdtype, header[0], header[1], header[2],
145 header[3], header[4], header[5], header[6], signer,
146 signature)
147
148 from_wire = classmethod(from_wire)
149
150 def choose_relativity(self, origin = None, relativize = True):
151 self.signer = self.signer.choose_relativity(origin, relativize)
152
153 def _cmp(self, other):
154 return self._wire_cmp(other)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
+0
-43
dns/rdtypes/ANY/SIG.py less more
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
1 #
2 # Permission to use, copy, modify, and distribute this software and its
3 # documentation for any purpose with or without fee is hereby granted,
4 # provided that the above copyright notice and this permission notice
5 # appear in all copies.
6 #
7 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import struct
16
17 import dns.rdtypes.sigbase
18
19 class SIG(dns.rdtypes.sigbase.SIGBase):
20 """SIG record"""
21 def to_digestable(self, origin = None):
22 return struct.pack('!HBBIIIH', self.type_covered,
23 self.algorithm, self.labels,
24 self.original_ttl, self.expiration,
25 self.inception, self.key_tag) + \
26 self.signer.to_digestable(origin) + \
27 self.signature
28 def _cmp(self, other):
29 hs = struct.pack('!HBBIIIH', self.type_covered,
30 self.algorithm, self.labels,
31 self.original_ttl, self.expiration,
32 self.inception, self.key_tag)
33 ho = struct.pack('!HBBIIIH', other.type_covered,
34 other.algorithm, other.labels,
35 other.original_ttl, other.expiration,
36 other.inception, other.key_tag)
37 v = cmp(hs, ho)
38 if v == 0:
39 v = cmp(self.signer, other.signer)
40 if v == 0:
41 v = cmp(self.signature, other.signature)
42 return v
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
4040
4141 __slots__ = ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire',
4242 'minimum']
43
43
4444 def __init__(self, rdclass, rdtype, mname, rname, serial, refresh, retry,
4545 expire, minimum):
4646 super(SOA, self).__init__(rdclass, rdtype)
5858 return '%s %s %d %d %d %d %d' % (
5959 mname, rname, self.serial, self.refresh, self.retry,
6060 self.expire, self.minimum )
61
61
6262 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
6363 mname = tok.get_name()
6464 rname = tok.get_name()
7272 tok.get_eol()
7373 return cls(rdclass, rdtype, mname, rname, serial, refresh, retry,
7474 expire, minimum )
75
75
7676 from_text = classmethod(from_text)
7777
7878 def to_wire(self, file, compress = None, origin = None):
0 # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2005-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2005-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2929 @see: draft-ietf-secsh-dns-05.txt"""
3030
3131 __slots__ = ['algorithm', 'fp_type', 'fingerprint']
32
32
3333 def __init__(self, rdclass, rdtype, algorithm, fp_type,
3434 fingerprint):
3535 super(SSHFP, self).__init__(rdclass, rdtype)
4242 self.fp_type,
4343 dns.rdata._hexify(self.fingerprint,
4444 chunksize=128))
45
45
4646 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
4747 algorithm = tok.get_uint8()
4848 fp_type = tok.get_uint8()
49 fingerprint = tok.get_string()
49 chunks = []
50 while 1:
51 t = tok.get().unescape()
52 if t.is_eol_or_eof():
53 break
54 if not t.is_identifier():
55 raise dns.exception.SyntaxError
56 chunks.append(t.value)
57 fingerprint = ''.join(chunks)
5058 fingerprint = fingerprint.decode('hex_codec')
51 tok.get_eol()
5259 return cls(rdclass, rdtype, algorithm, fp_type, fingerprint)
53
60
5461 from_text = classmethod(from_text)
5562
5663 def to_wire(self, file, compress = None, origin = None):
5764 header = struct.pack("!BB", self.algorithm, self.fp_type)
5865 file.write(header)
5966 file.write(self.fingerprint)
60
67
6168 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
6269 header = struct.unpack("!BB", wire[current : current + 2])
6370 current += 2
6471 rdlen -= 2
65 fingerprint = wire[current : current + rdlen]
72 fingerprint = wire[current : current + rdlen].unwrap()
6673 return cls(rdclass, rdtype, header[0], header[1], fingerprint)
6774
6875 from_wire = classmethod(from_wire)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2424 @see: RFC 1183"""
2525
2626 __slots__ = ['address']
27
27
2828 def __init__(self, rdclass, rdtype, address):
2929 super(X25, self).__init__(rdclass, rdtype)
3030 self.address = address
3131
3232 def to_text(self, origin=None, relativize=True, **kw):
3333 return '"%s"' % dns.rdata._escapify(self.address)
34
34
3535 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
3636 address = tok.get_string()
3737 tok.get_eol()
3838 return cls(rdclass, rdtype, address)
39
39
4040 from_text = classmethod(from_text)
4141
4242 def to_wire(self, file, compress = None, origin = None):
4545 byte = chr(l)
4646 file.write(byte)
4747 file.write(self.address)
48
48
4949 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
5050 l = ord(wire[current])
5151 current += 1
5252 rdlen -= 1
5353 if l != rdlen:
5454 raise dns.exception.FormError
55 address = wire[current : current + l]
55 address = wire[current : current + l].unwrap()
5656 return cls(rdclass, rdtype, address)
5757
5858 from_wire = classmethod(from_wire)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2626 'HINFO',
2727 'HIP',
2828 'ISDN',
29 'KEY',
3029 'LOC',
3130 'MX',
3231 'NS',
3332 'NSEC',
3433 'NSEC3',
3534 'NSEC3PARAM',
36 'NXT',
3735 'PTR',
3836 'RP',
3937 'RRSIG',
4038 'RT',
41 'SIG',
4239 'SOA',
4340 'SPF',
4441 'SSHFP',
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
130130 rdlen -= 4
131131 if rdlen < afdlen:
132132 raise dns.exception.FormError
133 address = wire[current : current + afdlen]
133 address = wire[current : current + afdlen].unwrap()
134134 l = len(address)
135135 if header[0] == 1:
136136 if l < 4:
0 # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
5050 file.write(self.data)
5151
5252 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
53 data = wire[current : current + rdlen]
53 data = wire[current : current + rdlen].unwrap()
5454 return cls(rdclass, rdtype, data)
5555
5656 from_wire = classmethod(from_wire)
0 # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
139139 rdlen -= cused
140140 else:
141141 raise dns.exception.FormError('invalid IPSECKEY gateway type')
142 key = wire[current : current + rdlen]
142 key = wire[current : current + rdlen].unwrap()
143143 return cls(rdclass, rdtype, header[0], gateway_type, header[2],
144144 gateway, key)
145145
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
4444
4545 __slots__ = ['order', 'preference', 'flags', 'service', 'regexp',
4646 'replacement']
47
47
4848 def __init__(self, rdclass, rdtype, order, preference, flags, service,
4949 regexp, replacement):
5050 super(NAPTR, self).__init__(rdclass, rdtype)
7575 tok.get_eol()
7676 return cls(rdclass, rdtype, order, preference, flags, service,
7777 regexp, replacement)
78
78
7979 from_text = classmethod(from_text)
8080
8181 def to_wire(self, file, compress = None, origin = None):
8585 _write_string(file, self.service)
8686 _write_string(file, self.regexp)
8787 self.replacement.to_wire(file, compress, origin)
88
88
8989 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
9090 (order, preference) = struct.unpack('!HH', wire[current : current + 4])
9191 current += 4
9797 rdlen -= 1
9898 if l > rdlen or rdlen < 0:
9999 raise dns.exception.FormError
100 s = wire[current : current + l]
100 s = wire[current : current + l].unwrap()
101101 current += l
102102 rdlen -= l
103103 strings.append(s)
115115 def choose_relativity(self, origin = None, relativize = True):
116116 self.replacement = self.replacement.choose_relativity(origin,
117117 relativize)
118
118
119119 def _cmp(self, other):
120120 sp = struct.pack("!HH", self.order, self.preference)
121121 op = struct.pack("!HH", other.order, other.preference)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
4949 file.write(self.address)
5050
5151 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
52 address = wire[current : current + rdlen]
52 address = wire[current : current + rdlen].unwrap()
5353 return cls(rdclass, rdtype, address)
5454
5555 from_wire = classmethod(from_wire)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
3030 @see: RFC 2163"""
3131
3232 __slots__ = ['preference', 'map822', 'mapx400']
33
33
3434 def __init__(self, rdclass, rdtype, preference, map822, mapx400):
3535 super(PX, self).__init__(rdclass, rdtype)
3636 self.preference = preference
4141 map822 = self.map822.choose_relativity(origin, relativize)
4242 mapx400 = self.mapx400.choose_relativity(origin, relativize)
4343 return '%d %s %s' % (self.preference, map822, mapx400)
44
44
4545 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
4646 preference = tok.get_uint16()
4747 map822 = tok.get_name()
5050 mapx400 = mapx400.choose_relativity(origin, relativize)
5151 tok.get_eol()
5252 return cls(rdclass, rdtype, preference, map822, mapx400)
53
53
5454 from_text = classmethod(from_text)
5555
5656 def to_wire(self, file, compress = None, origin = None):
5858 file.write(pref)
5959 self.map822.to_wire(file, None, origin)
6060 self.mapx400.to_wire(file, None, origin)
61
61
6262 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
6363 (preference, ) = struct.unpack('!H', wire[current : current + 2])
6464 current += 2
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
9494 protocol, = struct.unpack('!B', wire[current + 4 : current + 5])
9595 current += 5
9696 rdlen -= 5
97 bitmap = wire[current : current + rdlen]
97 bitmap = wire[current : current + rdlen].unwrap()
9898 return cls(rdclass, rdtype, address, protocol, bitmap)
9999
100100 from_wire = classmethod(from_wire)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
1919 'IN',
2020 'mxbase',
2121 'nsbase',
22 'sigbase',
23 'keybase',
2422 ]
0 # Copyright (C) 2010 Nominum, Inc.
0 # Copyright (C) 2010, 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
7575 header = struct.unpack("!HBB", wire[current : current + 4])
7676 current += 4
7777 rdlen -= 4
78 digest = wire[current : current + rdlen]
78 digest = wire[current : current + rdlen].unwrap()
7979 return cls(rdclass, rdtype, header[0], header[1], header[2], digest)
8080
8181 from_wire = classmethod(from_wire)
+0
-149
dns/rdtypes/keybase.py less more
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
1 #
2 # Permission to use, copy, modify, and distribute this software and its
3 # documentation for any purpose with or without fee is hereby granted,
4 # provided that the above copyright notice and this permission notice
5 # appear in all copies.
6 #
7 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import struct
16
17 import dns.exception
18 import dns.dnssec
19 import dns.rdata
20
21 _flags_from_text = {
22 'NOCONF': (0x4000, 0xC000),
23 'NOAUTH': (0x8000, 0xC000),
24 'NOKEY': (0xC000, 0xC000),
25 'FLAG2': (0x2000, 0x2000),
26 'EXTEND': (0x1000, 0x1000),
27 'FLAG4': (0x0800, 0x0800),
28 'FLAG5': (0x0400, 0x0400),
29 'USER': (0x0000, 0x0300),
30 'ZONE': (0x0100, 0x0300),
31 'HOST': (0x0200, 0x0300),
32 'NTYP3': (0x0300, 0x0300),
33 'FLAG8': (0x0080, 0x0080),
34 'FLAG9': (0x0040, 0x0040),
35 'FLAG10': (0x0020, 0x0020),
36 'FLAG11': (0x0010, 0x0010),
37 'SIG0': (0x0000, 0x000f),
38 'SIG1': (0x0001, 0x000f),
39 'SIG2': (0x0002, 0x000f),
40 'SIG3': (0x0003, 0x000f),
41 'SIG4': (0x0004, 0x000f),
42 'SIG5': (0x0005, 0x000f),
43 'SIG6': (0x0006, 0x000f),
44 'SIG7': (0x0007, 0x000f),
45 'SIG8': (0x0008, 0x000f),
46 'SIG9': (0x0009, 0x000f),
47 'SIG10': (0x000a, 0x000f),
48 'SIG11': (0x000b, 0x000f),
49 'SIG12': (0x000c, 0x000f),
50 'SIG13': (0x000d, 0x000f),
51 'SIG14': (0x000e, 0x000f),
52 'SIG15': (0x000f, 0x000f),
53 }
54
55 _protocol_from_text = {
56 'NONE' : 0,
57 'TLS' : 1,
58 'EMAIL' : 2,
59 'DNSSEC' : 3,
60 'IPSEC' : 4,
61 'ALL' : 255,
62 }
63
64 class KEYBase(dns.rdata.Rdata):
65 """KEY-like record base
66
67 @ivar flags: the key flags
68 @type flags: int
69 @ivar protocol: the protocol for which this key may be used
70 @type protocol: int
71 @ivar algorithm: the algorithm used for the key
72 @type algorithm: int
73 @ivar key: the public key
74 @type key: string"""
75
76 __slots__ = ['flags', 'protocol', 'algorithm', 'key']
77
78 def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key):
79 super(KEYBase, self).__init__(rdclass, rdtype)
80 self.flags = flags
81 self.protocol = protocol
82 self.algorithm = algorithm
83 self.key = key
84
85 def to_text(self, origin=None, relativize=True, **kw):
86 return '%d %d %d %s' % (self.flags, self.protocol, self.algorithm,
87 dns.rdata._base64ify(self.key))
88
89 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
90 flags = tok.get_string()
91 if flags.isdigit():
92 flags = int(flags)
93 else:
94 flag_names = flags.split('|')
95 flags = 0
96 for flag in flag_names:
97 v = _flags_from_text.get(flag)
98 if v is None:
99 raise dns.exception.SyntaxError('unknown flag %s' % flag)
100 flags &= ~v[1]
101 flags |= v[0]
102 protocol = tok.get_string()
103 if protocol.isdigit():
104 protocol = int(protocol)
105 else:
106 protocol = _protocol_from_text.get(protocol)
107 if protocol is None:
108 raise dns.exception.SyntaxError('unknown protocol %s' % protocol)
109
110 algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
111 chunks = []
112 while 1:
113 t = tok.get().unescape()
114 if t.is_eol_or_eof():
115 break
116 if not t.is_identifier():
117 raise dns.exception.SyntaxError
118 chunks.append(t.value)
119 b64 = ''.join(chunks)
120 key = b64.decode('base64_codec')
121 return cls(rdclass, rdtype, flags, protocol, algorithm, key)
122
123 from_text = classmethod(from_text)
124
125 def to_wire(self, file, compress = None, origin = None):
126 header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
127 file.write(header)
128 file.write(self.key)
129
130 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
131 if rdlen < 4:
132 raise dns.exception.FormError
133 header = struct.unpack('!HBB', wire[current : current + 4])
134 current += 4
135 rdlen -= 4
136 key = wire[current : current + rdlen]
137 return cls(rdclass, rdtype, header[0], header[1], header[2],
138 key)
139
140 from_wire = classmethod(from_wire)
141
142 def _cmp(self, other):
143 hs = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
144 ho = struct.pack("!HBB", other.flags, other.protocol, other.algorithm)
145 v = cmp(hs, ho)
146 if v == 0:
147 v = cmp(self.key, other.key)
148 return v
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
+0
-155
dns/rdtypes/sigbase.py less more
0 # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc.
1 #
2 # Permission to use, copy, modify, and distribute this software and its
3 # documentation for any purpose with or without fee is hereby granted,
4 # provided that the above copyright notice and this permission notice
5 # appear in all copies.
6 #
7 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import calendar
16 import struct
17 import time
18
19 import dns.dnssec
20 import dns.exception
21 import dns.rdata
22 import dns.rdatatype
23
24 class BadSigTime(dns.exception.DNSException):
25 """Raised when a SIG or RRSIG RR's time cannot be parsed."""
26 pass
27
28 def sigtime_to_posixtime(what):
29 if len(what) != 14:
30 raise BadSigTime
31 year = int(what[0:4])
32 month = int(what[4:6])
33 day = int(what[6:8])
34 hour = int(what[8:10])
35 minute = int(what[10:12])
36 second = int(what[12:14])
37 return calendar.timegm((year, month, day, hour, minute, second,
38 0, 0, 0))
39
40 def posixtime_to_sigtime(what):
41 return time.strftime('%Y%m%d%H%M%S', time.gmtime(what))
42
43 class SIGBase(dns.rdata.Rdata):
44 """SIG-like record base
45
46 @ivar type_covered: the rdata type this signature covers
47 @type type_covered: int
48 @ivar algorithm: the algorithm used for the sig
49 @type algorithm: int
50 @ivar labels: number of labels
51 @type labels: int
52 @ivar original_ttl: the original TTL
53 @type original_ttl: long
54 @ivar expiration: signature expiration time
55 @type expiration: long
56 @ivar inception: signature inception time
57 @type inception: long
58 @ivar key_tag: the key tag
59 @type key_tag: int
60 @ivar signer: the signer
61 @type signer: dns.name.Name object
62 @ivar signature: the signature
63 @type signature: string"""
64
65 __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl',
66 'expiration', 'inception', 'key_tag', 'signer',
67 'signature']
68
69 def __init__(self, rdclass, rdtype, type_covered, algorithm, labels,
70 original_ttl, expiration, inception, key_tag, signer,
71 signature):
72 super(SIGBase, self).__init__(rdclass, rdtype)
73 self.type_covered = type_covered
74 self.algorithm = algorithm
75 self.labels = labels
76 self.original_ttl = original_ttl
77 self.expiration = expiration
78 self.inception = inception
79 self.key_tag = key_tag
80 self.signer = signer
81 self.signature = signature
82
83 def covers(self):
84 return self.type_covered
85
86 def to_text(self, origin=None, relativize=True, **kw):
87 return '%s %d %d %d %s %s %d %s %s' % (
88 dns.rdatatype.to_text(self.type_covered),
89 self.algorithm,
90 self.labels,
91 self.original_ttl,
92 posixtime_to_sigtime(self.expiration),
93 posixtime_to_sigtime(self.inception),
94 self.key_tag,
95 self.signer,
96 dns.rdata._base64ify(self.signature)
97 )
98
99 def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
100 type_covered = dns.rdatatype.from_text(tok.get_string())
101 algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
102 labels = tok.get_int()
103 original_ttl = tok.get_ttl()
104 expiration = sigtime_to_posixtime(tok.get_string())
105 inception = sigtime_to_posixtime(tok.get_string())
106 key_tag = tok.get_int()
107 signer = tok.get_name()
108 signer = signer.choose_relativity(origin, relativize)
109 chunks = []
110 while 1:
111 t = tok.get().unescape()
112 if t.is_eol_or_eof():
113 break
114 if not t.is_identifier():
115 raise dns.exception.SyntaxError
116 chunks.append(t.value)
117 b64 = ''.join(chunks)
118 signature = b64.decode('base64_codec')
119 return cls(rdclass, rdtype, type_covered, algorithm, labels,
120 original_ttl, expiration, inception, key_tag, signer,
121 signature)
122
123 from_text = classmethod(from_text)
124
125 def to_wire(self, file, compress = None, origin = None):
126 header = struct.pack('!HBBIIIH', self.type_covered,
127 self.algorithm, self.labels,
128 self.original_ttl, self.expiration,
129 self.inception, self.key_tag)
130 file.write(header)
131 self.signer.to_wire(file, None, origin)
132 file.write(self.signature)
133
134 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
135 header = struct.unpack('!HBBIIIH', wire[current : current + 18])
136 current += 18
137 rdlen -= 18
138 (signer, cused) = dns.name.from_wire(wire[: current + rdlen], current)
139 current += cused
140 rdlen -= cused
141 if not origin is None:
142 signer = signer.relativize(origin)
143 signature = wire[current : current + rdlen]
144 return cls(rdclass, rdtype, header[0], header[1], header[2],
145 header[3], header[4], header[5], header[6], signer,
146 signature)
147
148 from_wire = classmethod(from_wire)
149
150 def choose_relativity(self, origin = None, relativize = True):
151 self.signer = self.signer.choose_relativity(origin, relativize)
152
153 def _cmp(self, other):
154 return self._wire_cmp(other)
0 # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
7474 rdlen -= 1
7575 if l > rdlen:
7676 raise dns.exception.FormError
77 s = wire[current : current + l]
77 s = wire[current : current + l].unwrap()
7878 current += l
7979 rdlen -= l
8080 strings.append(s)
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
266266 @type other_data: string
267267 @param request_mac: This message is a response to the request which
268268 had the specified MAC.
269 @type request_mac: string
269270 @param algorithm: the TSIG algorithm to use
270 @type request_mac: string
271 @type algorithm: dns.name.Name object
271272 """
272273
273274 self._set_section(ADDITIONAL)
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
2222 import time
2323
2424 import dns.exception
25 import dns.flags
26 import dns.ipv4
27 import dns.ipv6
2528 import dns.message
2629 import dns.name
2730 import dns.query
2831 import dns.rcode
2932 import dns.rdataclass
3033 import dns.rdatatype
34 import dns.reversename
3135
3236 if sys.platform == 'win32':
3337 import _winreg
266270 self.data = {}
267271 self.next_cleaning = time.time() + self.cleaning_interval
268272
273 class LRUCacheNode(object):
274 """LRUCache node.
275 """
276 def __init__(self, key, value):
277 self.key = key
278 self.value = value
279 self.prev = self
280 self.next = self
281
282 def link_before(self, node):
283 self.prev = node.prev
284 self.next = node
285 node.prev.next = self
286 node.prev = self
287
288 def link_after(self, node):
289 self.prev = node
290 self.next = node.next
291 node.next.prev = self
292 node.next = self
293
294 def unlink(self):
295 self.next.prev = self.prev
296 self.prev.next = self.next
297
298 class LRUCache(object):
299 """Bounded least-recently-used DNS answer cache.
300
301 This cache is better than the simple cache (above) if you're
302 running a web crawler or other process that does a lot of
303 resolutions. The LRUCache has a maximum number of nodes, and when
304 it is full, the least-recently used node is removed to make space
305 for a new one.
306
307 @ivar data: A dictionary of cached data
308 @type data: dict
309 @ivar sentinel: sentinel node for circular doubly linked list of nodes
310 @type sentinel: LRUCacheNode object
311 @ivar max_size: The maximum number of nodes
312 @type max_size: int
313 """
314
315 def __init__(self, max_size=100000):
316 """Initialize a DNS cache.
317
318 @param max_size: The maximum number of nodes to cache; the default is 100000. Must be > 1.
319 @type max_size: int
320 """
321 self.data = {}
322 self.set_max_size(max_size)
323 self.sentinel = LRUCacheNode(None, None)
324
325 def set_max_size(self, max_size):
326 if max_size < 1:
327 max_size = 1
328 self.max_size = max_size
329
330 def get(self, key):
331 """Get the answer associated with I{key}. Returns None if
332 no answer is cached for the key.
333 @param key: the key
334 @type key: (dns.name.Name, int, int) tuple whose values are the
335 query name, rdtype, and rdclass.
336 @rtype: dns.resolver.Answer object or None
337 """
338 node = self.data.get(key)
339 if node is None:
340 return None
341 # Unlink because we're either going to move the node to the front
342 # of the LRU list or we're going to free it.
343 node.unlink()
344 if node.value.expiration <= time.time():
345 del self.data[node.key]
346 return None
347 node.link_after(self.sentinel)
348 return node.value
349
350 def put(self, key, value):
351 """Associate key and value in the cache.
352 @param key: the key
353 @type key: (dns.name.Name, int, int) tuple whose values are the
354 query name, rdtype, and rdclass.
355 @param value: The answer being cached
356 @type value: dns.resolver.Answer object
357 """
358 node = self.data.get(key)
359 if not node is None:
360 node.unlink()
361 del self.data[node.key]
362 while len(self.data) >= self.max_size:
363 node = self.sentinel.prev
364 node.unlink()
365 del self.data[node.key]
366 node = LRUCacheNode(key, value)
367 node.link_after(self.sentinel)
368 self.data[key] = node
369
370 def flush(self, key=None):
371 """Flush the cache.
372
373 If I{key} is specified, only that item is flushed. Otherwise
374 the entire cache is flushed.
375
376 @param key: the key to flush
377 @type key: (dns.name.Name, int, int) tuple or None
378 """
379 if not key is None:
380 node = self.data.get(key)
381 if not node is None:
382 node.unlink()
383 del self.data[node.key]
384 else:
385 node = self.sentinel.next
386 while node != self.sentinel:
387 next = node.next
388 node.prev = None
389 node.next = None
390 node = next
391 self.data = {}
392
269393 class Resolver(object):
270394 """DNS stub resolver
271395
568692 return min(self.lifetime - duration, self.timeout)
569693
570694 def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
571 tcp=False, source=None, raise_on_no_answer=True):
695 tcp=False, source=None, raise_on_no_answer=True, source_port=0):
572696 """Query nameservers to find the answer to the question.
573697
574698 The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
589713 @param raise_on_no_answer: raise NoAnswer if there's no answer
590714 (defaults is True).
591715 @type raise_on_no_answer: bool
716 @param source_port: The port from which to send the message.
717 The default is 0.
718 @type source_port: int
592719 @rtype: dns.resolver.Answer instance
593720 @raises Timeout: no answers could be found in the specified lifetime
594721 @raises NXDOMAIN: the query name does not exist
623750 for qname in qnames_to_try:
624751 if self.cache:
625752 answer = self.cache.get((qname, rdtype, rdclass))
626 if answer:
627 return answer
753 if not answer is None:
754 if answer.rrset is None and raise_on_no_answer:
755 raise NoAnswer
756 else:
757 return answer
628758 request = dns.message.make_query(qname, rdtype, rdclass)
629759 if not self.keyname is None:
630760 request.use_tsig(self.keyring, self.keyname,
645775 if tcp:
646776 response = dns.query.tcp(request, nameserver,
647777 timeout, self.port,
648 source=source)
778 source=source,
779 source_port=source_port)
649780 else:
650781 response = dns.query.udp(request, nameserver,
651782 timeout, self.port,
652 source=source)
783 source=source,
784 source_port=source_port)
785 if response.flags & dns.flags.TC:
786 # Response truncated; retry with TCP.
787 timeout = self._compute_timeout(start)
788 response = dns.query.tcp(request, nameserver,
789 timeout, self.port,
790 source=source,
791 source_port=source_port)
653792 except (socket.error, dns.exception.Timeout):
654793 #
655794 # Communication failure or timeout. Go to the
668807 # We don't understand what this server is
669808 # saying. Take it out of the mix and
670809 # continue.
810 #
811 nameservers.remove(nameserver)
812 response = None
813 continue
814 except EOFError:
815 #
816 # We're using TCP and they hung up on us.
817 # Probably they don't support TCP (though
818 # they're supposed to!). Take it out of the
819 # mix and continue.
671820 #
672821 nameservers.remove(nameserver)
673822 response = None
758907 return default_resolver
759908
760909 def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
761 tcp=False, source=None, raise_on_no_answer=True):
910 tcp=False, source=None, raise_on_no_answer=True,
911 source_port=0):
762912 """Query nameservers to find the answer to the question.
763913
764914 This is a convenience function that uses the default resolver
766916 @see: L{dns.resolver.Resolver.query} for more information on the
767917 parameters."""
768918 return get_default_resolver().query(qname, rdtype, rdclass, tcp, source,
769 raise_on_no_answer)
919 raise_on_no_answer, source_port)
770920
771921 def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
772922 """Find the name of the zone which contains the specified name.
799949 name = name.parent()
800950 except dns.name.NoParent:
801951 raise NoRootSOA
952
953 #
954 # Support for overriding the system resolver for all python code in the
955 # running process.
956 #
957
958 _protocols_for_socktype = {
959 socket.SOCK_DGRAM : [socket.SOL_UDP],
960 socket.SOCK_STREAM : [socket.SOL_TCP],
961 }
962
963 _resolver = None
964 _original_getaddrinfo = socket.getaddrinfo
965 _original_getnameinfo = socket.getnameinfo
966 _original_getfqdn = socket.getfqdn
967 _original_gethostbyname = socket.gethostbyname
968 _original_gethostbyname_ex = socket.gethostbyname_ex
969 _original_gethostbyaddr = socket.gethostbyaddr
970
971 def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
972 proto=0, flags=0):
973 if flags & (socket.AI_ADDRCONFIG|socket.AI_V4MAPPED) != 0:
974 raise NotImplementedError
975 if host is None and service is None:
976 raise socket.gaierror(socket.EAI_NONAME)
977 v6addrs = []
978 v4addrs = []
979 canonical_name = None
980 try:
981 # Is host None or a V6 address literal?
982 if host is None:
983 canonical_name = 'localhost'
984 if flags & socket.AI_PASSIVE != 0:
985 v6addrs.append('::')
986 v4addrs.append('0.0.0.0')
987 else:
988 v6addrs.append('::1')
989 v4addrs.append('127.0.0.1')
990 else:
991 parts = host.split('%')
992 if len(parts) == 2:
993 ahost = parts[0]
994 else:
995 ahost = host
996 addr = dns.ipv6.inet_aton(ahost)
997 v6addrs.append(host)
998 canonical_name = host
999 except:
1000 try:
1001 # Is it a V4 address literal?
1002 addr = dns.ipv4.inet_aton(host)
1003 v4addrs.append(host)
1004 canonical_name = host
1005 except:
1006 if flags & socket.AI_NUMERICHOST == 0:
1007 try:
1008 qname = None
1009 if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
1010 v6 = _resolver.query(host, dns.rdatatype.AAAA,
1011 raise_on_no_answer=False)
1012 # Note that setting host ensures we query the same name
1013 # for A as we did for AAAA.
1014 host = v6.qname
1015 canonical_name = v6.canonical_name.to_text(True)
1016 if v6.rrset is not None:
1017 for rdata in v6.rrset:
1018 v6addrs.append(rdata.address)
1019 if family == socket.AF_INET or family == socket.AF_UNSPEC:
1020 v4 = _resolver.query(host, dns.rdatatype.A,
1021 raise_on_no_answer=False)
1022 host = v4.qname
1023 canonical_name = v4.canonical_name.to_text(True)
1024 if v4.rrset is not None:
1025 for rdata in v4.rrset:
1026 v4addrs.append(rdata.address)
1027 except dns.resolver.NXDOMAIN:
1028 raise socket.gaierror(socket.EAI_NONAME)
1029 except:
1030 raise socket.gaierror(socket.EAI_SYSTEM)
1031 port = None
1032 try:
1033 # Is it a port literal?
1034 if service is None:
1035 port = 0
1036 else:
1037 port = int(service)
1038 except:
1039 if flags & socket.AI_NUMERICSERV == 0:
1040 try:
1041 port = socket.getservbyname(service)
1042 except:
1043 pass
1044 if port is None:
1045 raise socket.gaierror(socket.EAI_NONAME)
1046 tuples = []
1047 if socktype == 0:
1048 socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM]
1049 else:
1050 socktypes = [socktype]
1051 if flags & socket.AI_CANONNAME != 0:
1052 cname = canonical_name
1053 else:
1054 cname = ''
1055 if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
1056 for addr in v6addrs:
1057 for socktype in socktypes:
1058 for proto in _protocols_for_socktype[socktype]:
1059 tuples.append((socket.AF_INET6, socktype, proto,
1060 cname, (addr, port, 0, 0)))
1061 if family == socket.AF_INET or family == socket.AF_UNSPEC:
1062 for addr in v4addrs:
1063 for socktype in socktypes:
1064 for proto in _protocols_for_socktype[socktype]:
1065 tuples.append((socket.AF_INET, socktype, proto,
1066 cname, (addr, port)))
1067 if len(tuples) == 0:
1068 raise socket.gaierror(socket.EAI_NONAME)
1069 return tuples
1070
1071 def _getnameinfo(sockaddr, flags=0):
1072 host = sockaddr[0]
1073 port = sockaddr[1]
1074 if len(sockaddr) == 4:
1075 scope = sockaddr[3]
1076 family = socket.AF_INET6
1077 else:
1078 scope = None
1079 family = socket.AF_INET
1080 tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM,
1081 socket.SOL_TCP, 0)
1082 if len(tuples) > 1:
1083 raise socket.error('sockaddr resolved to multiple addresses')
1084 addr = tuples[0][4][0]
1085 if flags & socket.NI_DGRAM:
1086 pname = 'udp'
1087 else:
1088 pname = 'tcp'
1089 qname = dns.reversename.from_address(addr)
1090 if flags & socket.NI_NUMERICHOST == 0:
1091 try:
1092 answer = _resolver.query(qname, 'PTR')
1093 hostname = answer.rrset[0].target.to_text(True)
1094 except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
1095 if flags & socket.NI_NAMEREQD:
1096 raise socket.gaierror(socket.EAI_NONAME)
1097 hostname = addr
1098 if scope is not None:
1099 hostname += '%' + str(scope)
1100 else:
1101 hostname = addr
1102 if scope is not None:
1103 hostname += '%' + str(scope)
1104 if flags & socket.NI_NUMERICSERV:
1105 service = str(port)
1106 else:
1107 service = socket.getservbyport(port, pname)
1108 return (hostname, service)
1109
1110 def _getfqdn(name=None):
1111 if name is None:
1112 name = socket.gethostname()
1113 return _getnameinfo(_getaddrinfo(name, 80)[0][4])[0]
1114
1115 def _gethostbyname(name):
1116 return _gethostbyname_ex(name)[2][0]
1117
1118 def _gethostbyname_ex(name):
1119 aliases = []
1120 addresses = []
1121 tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM,
1122 socket.SOL_TCP, socket.AI_CANONNAME)
1123 canonical = tuples[0][3]
1124 for item in tuples:
1125 addresses.append(item[4][0])
1126 # XXX we just ignore aliases
1127 return (canonical, aliases, addresses)
1128
1129 def _gethostbyaddr(ip):
1130 try:
1131 addr = dns.ipv6.inet_aton(ip)
1132 sockaddr = (ip, 80, 0, 0)
1133 family = socket.AF_INET6
1134 except:
1135 sockaddr = (ip, 80)
1136 family = socket.AF_INET
1137 (name, port) = _getnameinfo(sockaddr, socket.NI_NAMEREQD)
1138 aliases = []
1139 addresses = []
1140 tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP,
1141 socket.AI_CANONNAME)
1142 canonical = tuples[0][3]
1143 for item in tuples:
1144 addresses.append(item[4][0])
1145 # XXX we just ignore aliases
1146 return (canonical, aliases, addresses)
1147
1148 def override_system_resolver(resolver=None):
1149 """Override the system resolver routines in the socket module with
1150 versions which use dnspython's resolver.
1151
1152 This can be useful in testing situations where you want to control
1153 the resolution behavior of python code without having to change
1154 the system's resolver settings (e.g. /etc/resolv.conf).
1155
1156 The resolver to use may be specified; if it's not, the default
1157 resolver will be used.
1158
1159 @param resolver: the resolver to use
1160 @type resolver: dns.resolver.Resolver object or None
1161 """
1162 if resolver is None:
1163 resolver = get_default_resolver()
1164 global _resolver
1165 _resolver = resolver
1166 socket.getaddrinfo = _getaddrinfo
1167 socket.getnameinfo = _getnameinfo
1168 socket.getfqdn = _getfqdn
1169 socket.gethostbyname = _gethostbyname
1170 socket.gethostbyname_ex = _gethostbyname_ex
1171 socket.gethostbyaddr = _gethostbyaddr
1172
1173 def restore_system_resolver():
1174 """Undo the effects of override_system_resolver().
1175 """
1176 global _resolver
1177 _resolver = None
1178 socket.getaddrinfo = _original_getaddrinfo
1179 socket.getnameinfo = _original_getnameinfo
1180 socket.getfqdn = _original_getfqdn
1181 socket.gethostbyname = _original_gethostbyname
1182 socket.gethostbyname_ex = _original_gethostbyname_ex
1183 socket.gethostbyaddr = _original_gethostbyaddr
0 # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
6161
6262 @param ttype: The token type
6363 @type ttype: int
64 @ivar value: The token value
64 @param value: The token value
6565 @type value: string
66 @ivar has_escape: Does the token value contain escapes?
66 @param has_escape: Does the token value contain escapes?
6767 @type has_escape: bool
6868 """
6969 self.ttype = ttype
0 # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
1515 """dnspython release version information."""
1616
1717 MAJOR = 1
18 MINOR = 9
19 MICRO = 4
18 MINOR = 10
19 MICRO = 0
2020 RELEASELEVEL = 0x0f
2121 SERIAL = 0
2222
0 # Copyright (C) 2011 Nominum, Inc.
1 #
2 # Permission to use, copy, modify, and distribute this software and its
3 # documentation for any purpose with or without fee is hereby granted,
4 # provided that the above copyright notice and this permission notice
5 # appear in all copies.
6 #
7 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 """DNS Wire Data Helper"""
16
17 import sys
18
19 import dns.exception
20
21 class WireData(str):
22 # WireData is a string with stricter slicing
23 def __getitem__(self, key):
24 try:
25 return WireData(super(WireData, self).__getitem__(key))
26 except IndexError:
27 raise dns.exception.FormError
28 def __getslice__(self, i, j):
29 try:
30 if j == sys.maxint:
31 # handle the case where the right bound is unspecified
32 j = len(self)
33 if i < 0 or j < 0:
34 raise dns.exception.FormError
35 # If it's not an empty slice, access left and right bounds
36 # to make sure they're valid
37 if i != j:
38 super(WireData, self).__getitem__(i)
39 super(WireData, self).__getitem__(j - 1)
40 return WireData(super(WireData, self).__getslice__(i, j))
41 except IndexError:
42 raise dns.exception.FormError
43 def __iter__(self):
44 i = 0
45 while 1:
46 try:
47 yield self[i]
48 i += 1
49 except dns.exception.FormError:
50 raise StopIteration
51 def unwrap(self):
52 return str(self)
53
54 def maybe_wrap(wire):
55 if not isinstance(wire, WireData):
56 return WireData(wire)
57 else:
58 return wire
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
816816 f.close()
817817 return z
818818
819 def from_xfr(xfr, zone_factory=Zone, relativize=True):
819 def from_xfr(xfr, zone_factory=Zone, relativize=True, check_origin=True):
820820 """Convert the output of a zone transfer generator into a zone object.
821821
822822 @param xfr: The xfr generator
825825 It is essential that the relativize setting matches the one specified
826826 to dns.query.xfr().
827827 @type relativize: bool
828 @param check_origin: should sanity checks of the origin node be done?
829 The default is True.
830 @type check_origin: bool
828831 @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
829832 @raises dns.zone.NoNS: No NS RRset was found at the zone origin
830833 @rtype: dns.zone.Zone object
850853 for rd in rrset:
851854 rd.choose_relativity(z.origin, relativize)
852855 zrds.add(rd)
853 z.check_origin()
856 if check_origin:
857 z.check_origin()
854858 return z
00 #!/usr/bin/env python
11
22 import dns.query
3 import dns.resolver
34 import dns.zone
45
5 z = dns.zone.from_xfr(dns.query.xfr('204.152.189.147', 'dnspython.org'))
6 soa_answer = dns.resolver.query('dnspython.org', 'SOA')
7 master_answer = dns.resolver.query(soa_answer[0].mname, 'A')
8
9 z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, 'dnspython.org'))
610 names = z.nodes.keys()
711 names.sort()
812 for n in names:
00 #!/usr/bin/env python
11 #
2 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
2 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
33 #
44 # Permission to use, copy, modify, and distribute this software and its
55 # documentation for any purpose with or without fee is hereby granted,
1717 import sys
1818 from distutils.core import setup
1919
20 version = '1.9.4'
20 version = '1.10.0'
2121
2222 kwargs = {
2323 'name' : 'dnspython',
3737 'license' : 'BSD-like',
3838 'url' : 'http://www.dnspython.org',
3939 'packages' : ['dns', 'dns.rdtypes', 'dns.rdtypes.IN', 'dns.rdtypes.ANY'],
40 }
41
42 if sys.hexversion >= 0x02020300:
43 kwargs['download_url'] = \
44 'http://www.dnspython.org/kits/%s/dnspython-%s.tar.gz' % (version,
45 version)
46 kwargs['classifiers'] = [
40 'download_url' : \
41 'http://www.dnspython.org/kits/%s/dnspython-%s.tar.gz' % (version, version),
42 'classifiers' : [
4743 "Development Status :: 5 - Production/Stable",
4844 "Intended Audience :: Developers",
4945 "Intended Audience :: System Administrators",
5349 "Programming Language :: Python",
5450 "Topic :: Internet :: Name Service (DNS)",
5551 "Topic :: Software Development :: Libraries :: Python Modules",
56 ]
52 ],
53 }
5754
5855 if sys.hexversion >= 0x02050000:
5956 kwargs['requires'] = []
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2010 Nominum, Inc.
0 # Copyright (C) 2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
100100 isdn02 ISDN "isdn-address" "subaddress"
101101 isdn03 ISDN "isdn-address"
102102 isdn04 ISDN "isdn-address" "subaddress"
103 key01 KEY 512 255 1 (
104 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
105 yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
106 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
107 jqf0BaqHT+8= )
108 key02 KEY HOST|FLAG4 DNSSEC RSAMD5 (
109 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
110 yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
111 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
112 jqf0BaqHT+8= )
103 ;; dnspython no longer supports old DNSSEC
104 ;;key01 KEY 512 255 1 (
105 ;; AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
106 ;; yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
107 ;; GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
108 ;; jqf0BaqHT+8= )
109 ;;key02 KEY HOST|FLAG4 DNSSEC RSAMD5 (
110 ;; AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
111 ;; yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
112 ;; GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
113 ;; jqf0BaqHT+8= )
113114 kx01 KX 10 kdc
114115 kx02 KX 10 .
115116 loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
136137 NSAP-PTR .
137138 nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
138139 nsap02 NSAP 0x47.000580005a0000000001e133ffffff000161.00
139 nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
140 nxt02 NXT . ( NSAP-PTR NXT )
141 nxt03 NXT . ( A )
142 nxt04 NXT . ( 127 )
140 ;;nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
141 ;;nxt02 NXT . ( NSAP-PTR NXT )
142 ;;nxt03 NXT . ( A )
143 ;;nxt04 NXT . ( 127 )
143144 ptr01 PTR example.
144145 px01 PX 65535 foo. bar.
145146 px02 PX 65535 . .
153154 ns A 73.80.65.49
154155 $ORIGIN example.
155156 $TTL 3600 ; 1 hour
156 sig01 SIG NXT 1 3 3600 (
157 20200101000000 20030101000000 2143 foo
158 MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
159 WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
160 d80jEeC8aTrO+KKmCaY= )
157 ;;sig01 SIG NXT 1 3 3600 (
158 ;; 20200101000000 20030101000000 2143 foo
159 ;; MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
160 ;; WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
161 ;; d80jEeC8aTrO+KKmCaY= )
161162 srv01 SRV 0 0 0 .
162163 srv02 SRV 65535 65535 65535 old-slow-box.example.com.
163164 $TTL 301 ; 5 minutes 1 second
201202 yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
202203 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
203204 jqf0BaqHT+8= )
204 dnskey02 DNSKEY HOST|FLAG4 DNSSEC RSAMD5 (
205 dnskey02 DNSKEY 257 3 RSAMD5 (
205206 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
206207 yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
207208 GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
2626 dname02 3600 IN DNAME dname-target
2727 dname03 3600 IN DNAME .
2828 dnskey01 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
29 dnskey02 3600 IN DNSKEY 2560 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
29 dnskey02 3600 IN DNSKEY 257 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
3030 ds01 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890
3131 e 300 IN MX 10 mail
3232 e 300 IN TXT "one"
5050 isdn02 3600 IN ISDN "isdn-address" "subaddress"
5151 isdn03 3600 IN ISDN "isdn-address"
5252 isdn04 3600 IN ISDN "isdn-address" "subaddress"
53 key01 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
54 key02 3600 IN KEY 2560 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
5553 kx01 3600 IN KX 10 kdc
5654 kx02 3600 IN KX 10 .
5755 loc01 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m
7674 nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
7775 nsec3param01 3600 IN NSEC3PARAM 1 1 12 aabbccdd
7876 nsec3param02 3600 IN NSEC3PARAM 1 1 12 -
79 nxt01 3600 IN NXT a.secure NS SOA MX SIG KEY LOC NXT
80 nxt02 3600 IN NXT . NSAP-PTR NXT
81 nxt03 3600 IN NXT . A
82 nxt04 3600 IN NXT . TYPE127
8377 ptr01 3600 IN PTR @
8478 px01 3600 IN PX 65535 foo. bar.
8579 px02 3600 IN PX 65535 . .
9084 rt02 3600 IN RT 65535 .
9185 s 300 IN NS ns.s
9286 ns.s 300 IN A 73.80.65.49
93 sig01 3600 IN SIG NXT 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY=
9487 spf 3600 IN SPF "v=spf1 mx -all"
9588 srv01 3600 IN SRV 0 0 0 .
9689 srv02 3600 IN SRV 65535 65535 65535 old-slow-box.example.com.
2626 dname02.example. 3600 IN DNAME dname-target.example.
2727 dname03.example. 3600 IN DNAME .
2828 dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
29 dnskey02.example. 3600 IN DNSKEY 2560 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
29 dnskey02.example. 3600 IN DNSKEY 257 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
3030 ds01.example. 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890
3131 e.example. 300 IN MX 10 mail.example.
3232 e.example. 300 IN TXT "one"
5050 isdn02.example. 3600 IN ISDN "isdn-address" "subaddress"
5151 isdn03.example. 3600 IN ISDN "isdn-address"
5252 isdn04.example. 3600 IN ISDN "isdn-address" "subaddress"
53 key01.example. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
54 key02.example. 3600 IN KEY 2560 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8=
5553 kx01.example. 3600 IN KX 10 kdc.example.
5654 kx02.example. 3600 IN KX 10 .
5755 loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m
7674 nsec302.example. 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
7775 nsec3param01.example. 3600 IN NSEC3PARAM 1 1 12 aabbccdd
7876 nsec3param02.example. 3600 IN NSEC3PARAM 1 1 12 -
79 nxt01.example. 3600 IN NXT a.secure.example. NS SOA MX SIG KEY LOC NXT
80 nxt02.example. 3600 IN NXT . NSAP-PTR NXT
81 nxt03.example. 3600 IN NXT . A
82 nxt04.example. 3600 IN NXT . TYPE127
8377 ptr01.example. 3600 IN PTR example.
8478 px01.example. 3600 IN PX 65535 foo. bar.
8579 px02.example. 3600 IN PX 65535 . .
9084 rt02.example. 3600 IN RT 65535 .
9185 s.example. 300 IN NS ns.s.example.
9286 ns.s.example. 300 IN A 73.80.65.49
93 sig01.example. 3600 IN SIG NXT 1 3 3600 20200101000000 20030101000000 2143 foo.example. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY=
9487 spf.example. 3600 IN SPF "v=spf1 mx -all"
9588 srv01.example. 3600 IN SRV 0 0 0 .
9689 srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com.
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
661661 def testBadReverseIPv4(self):
662662 def bad():
663663 n = dns.reversename.from_address('127.0.foo.1')
664 self.failUnlessRaises(socket.error, bad)
664 self.failUnlessRaises(dns.exception.SyntaxError, bad)
665665
666666 def testBadReverseIPv6(self):
667667 def bad():
668668 n = dns.reversename.from_address('::1::1')
669 self.failUnlessRaises(socket.error, bad)
669 self.failUnlessRaises(dns.exception.SyntaxError, bad)
670670
671671 def testForwardIPv4(self):
672672 n = dns.name.from_text('1.0.0.127.in-addr.arpa.')
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
1515 import unittest
1616
1717 import dns.exception
18 import dns.ipv4
1819 import dns.ipv6
20
21 # for convenience
22 aton4 = dns.ipv4.inet_aton
23 ntoa4 = dns.ipv4.inet_ntoa
24 aton6 = dns.ipv6.inet_aton
25 ntoa6 = dns.ipv6.inet_ntoa
26
27 v4_bad_addrs = ['256.1.1.1', '1.1.1', '1.1.1.1.1', '01.1.1.1',
28 '+1.1.1.1', '1.1.1.1+', '1..2.3.4', '.1.2.3.4',
29 '1.2.3.4.']
1930
2031 class NtoAAtoNTestCase(unittest.TestCase):
2132
2233 def test_aton1(self):
23 a = dns.ipv6.inet_aton('::')
34 a = aton6('::')
2435 self.failUnless(a == '\x00' * 16)
2536
2637 def test_aton2(self):
27 a = dns.ipv6.inet_aton('::1')
38 a = aton6('::1')
2839 self.failUnless(a == '\x00' * 15 + '\x01')
2940
3041 def test_aton3(self):
31 a = dns.ipv6.inet_aton('::10.0.0.1')
42 a = aton6('::10.0.0.1')
3243 self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01')
3344
3445 def test_aton4(self):
35 a = dns.ipv6.inet_aton('abcd::dcba')
46 a = aton6('abcd::dcba')
3647 self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba')
3748
3849 def test_aton5(self):
39 a = dns.ipv6.inet_aton('1:2:3:4:5:6:7:8')
50 a = aton6('1:2:3:4:5:6:7:8')
4051 self.failUnless(a == \
4152 '00010002000300040005000600070008'.decode('hex_codec'))
4253
4354 def test_bad_aton1(self):
4455 def bad():
45 a = dns.ipv6.inet_aton('abcd:dcba')
56 a = aton6('abcd:dcba')
4657 self.failUnlessRaises(dns.exception.SyntaxError, bad)
4758
4859 def test_bad_aton2(self):
4960 def bad():
50 a = dns.ipv6.inet_aton('abcd::dcba::1')
61 a = aton6('abcd::dcba::1')
5162 self.failUnlessRaises(dns.exception.SyntaxError, bad)
5263
5364 def test_bad_aton3(self):
5465 def bad():
55 a = dns.ipv6.inet_aton('1:2:3:4:5:6:7:8:9')
66 a = aton6('1:2:3:4:5:6:7:8:9')
5667 self.failUnlessRaises(dns.exception.SyntaxError, bad)
5768
5869 def test_aton1(self):
59 a = dns.ipv6.inet_aton('::')
70 a = aton6('::')
6071 self.failUnless(a == '\x00' * 16)
6172
6273 def test_aton2(self):
63 a = dns.ipv6.inet_aton('::1')
74 a = aton6('::1')
6475 self.failUnless(a == '\x00' * 15 + '\x01')
6576
6677 def test_aton3(self):
67 a = dns.ipv6.inet_aton('::10.0.0.1')
78 a = aton6('::10.0.0.1')
6879 self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01')
6980
7081 def test_aton4(self):
71 a = dns.ipv6.inet_aton('abcd::dcba')
82 a = aton6('abcd::dcba')
7283 self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba')
7384
7485 def test_ntoa1(self):
7586 b = '00010002000300040005000600070008'.decode('hex_codec')
76 t = dns.ipv6.inet_ntoa(b)
87 t = ntoa6(b)
7788 self.failUnless(t == '1:2:3:4:5:6:7:8')
7889
7990 def test_ntoa2(self):
8091 b = '\x00' * 16
81 t = dns.ipv6.inet_ntoa(b)
92 t = ntoa6(b)
8293 self.failUnless(t == '::')
8394
8495 def test_ntoa3(self):
8596 b = '\x00' * 15 + '\x01'
86 t = dns.ipv6.inet_ntoa(b)
97 t = ntoa6(b)
8798 self.failUnless(t == '::1')
8899
89100 def test_ntoa4(self):
90101 b = '\x80' + '\x00' * 15
91 t = dns.ipv6.inet_ntoa(b)
102 t = ntoa6(b)
92103 self.failUnless(t == '8000::')
93104
94105 def test_ntoa5(self):
95106 b = '\x01\xcd' + '\x00' * 12 + '\x03\xef'
96 t = dns.ipv6.inet_ntoa(b)
107 t = ntoa6(b)
97108 self.failUnless(t == '1cd::3ef')
98109
99110 def test_ntoa6(self):
100111 b = 'ffff00000000ffff000000000000ffff'.decode('hex_codec')
101 t = dns.ipv6.inet_ntoa(b)
112 t = ntoa6(b)
102113 self.failUnless(t == 'ffff:0:0:ffff::ffff')
103114
104115 def test_ntoa7(self):
105116 b = '00000000ffff000000000000ffffffff'.decode('hex_codec')
106 t = dns.ipv6.inet_ntoa(b)
117 t = ntoa6(b)
107118 self.failUnless(t == '0:0:ffff::ffff:ffff')
108119
109120 def test_ntoa8(self):
110121 b = 'ffff0000ffff00000000ffff00000000'.decode('hex_codec')
111 t = dns.ipv6.inet_ntoa(b)
122 t = ntoa6(b)
112123 self.failUnless(t == 'ffff:0:ffff::ffff:0:0')
113124
114125 def test_ntoa9(self):
115126 b = '0000000000000000000000000a000001'.decode('hex_codec')
116 t = dns.ipv6.inet_ntoa(b)
127 t = ntoa6(b)
117128 self.failUnless(t == '::10.0.0.1')
118129
119130 def test_ntoa10(self):
120131 b = '0000000000000000000000010a000001'.decode('hex_codec')
121 t = dns.ipv6.inet_ntoa(b)
132 t = ntoa6(b)
122133 self.failUnless(t == '::1:a00:1')
123134
124135 def test_ntoa11(self):
125136 b = '00000000000000000000ffff0a000001'.decode('hex_codec')
126 t = dns.ipv6.inet_ntoa(b)
137 t = ntoa6(b)
127138 self.failUnless(t == '::ffff:10.0.0.1')
128139
129140 def test_ntoa12(self):
130141 b = '000000000000000000000000ffffffff'.decode('hex_codec')
131 t = dns.ipv6.inet_ntoa(b)
142 t = ntoa6(b)
132143 self.failUnless(t == '::255.255.255.255')
133144
134145 def test_ntoa13(self):
135146 b = '00000000000000000000ffffffffffff'.decode('hex_codec')
136 t = dns.ipv6.inet_ntoa(b)
147 t = ntoa6(b)
137148 self.failUnless(t == '::ffff:255.255.255.255')
138149
139150 def test_ntoa14(self):
140151 b = '0000000000000000000000000001ffff'.decode('hex_codec')
141 t = dns.ipv6.inet_ntoa(b)
152 t = ntoa6(b)
142153 self.failUnless(t == '::0.1.255.255')
143154
144155 def test_bad_ntoa1(self):
145156 def bad():
146 a = dns.ipv6.inet_ntoa('')
157 a = ntoa6('')
147158 self.failUnlessRaises(ValueError, bad)
148159
149160 def test_bad_ntoa2(self):
150161 def bad():
151 a = dns.ipv6.inet_ntoa('\x00' * 17)
162 a = ntoa6('\x00' * 17)
152163 self.failUnlessRaises(ValueError, bad)
164
165 def test_good_v4_aton(self):
166 pairs = [('1.2.3.4', '\x01\x02\x03\x04'),
167 ('255.255.255.255', '\xff\xff\xff\xff'),
168 ('0.0.0.0', '\x00\x00\x00\x00')]
169 for (t, b) in pairs:
170 b1 = aton4(t)
171 t1 = ntoa4(b1)
172 self.failUnless(b1 == b)
173 self.failUnless(t1 == t)
174
175 def test_bad_v4_aton(self):
176 def make_bad(a):
177 def bad():
178 return aton4(a)
179 return bad
180 for addr in v4_bad_addrs:
181 self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr))
182
183 def test_bad_v6_aton(self):
184 addrs = ['+::0', '0::0::', '::0::', '1:2:3:4:5:6:7:8:9',
185 ':::::::']
186 embedded = ['::' + x for x in v4_bad_addrs]
187 addrs.extend(embedded)
188 def make_bad(a):
189 def bad():
190 x = aton6(a)
191 return bad
192 for addr in addrs:
193 self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr))
153194
154195 if __name__ == '__main__':
155196 unittest.main()
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
4545 ;AUTHORITY
4646 ;ADDITIONAL
4747 """
48
49 class FakeAnswer(object):
50 def __init__(self, expiration):
51 self.expiration = expiration
4852
4953 class BaseResolverTests(object):
5054
101105 zname = dns.resolver.zone_for_name(name)
102106 self.failUnlessRaises(dns.resolver.NotAbsolute, bad)
103107
108 def testLRUReplace(self):
109 cache = dns.resolver.LRUCache(4)
110 for i in xrange(0, 5):
111 name = dns.name.from_text('example%d.' % i)
112 answer = FakeAnswer(time.time() + 1)
113 cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
114 for i in xrange(0, 5):
115 name = dns.name.from_text('example%d.' % i)
116 if i == 0:
117 self.failUnless(cache.get((name, dns.rdatatype.A,
118 dns.rdataclass.IN))
119 is None)
120 else:
121 self.failUnless(not cache.get((name, dns.rdatatype.A,
122 dns.rdataclass.IN))
123 is None)
124
125 def testLRUDoesLRU(self):
126 cache = dns.resolver.LRUCache(4)
127 for i in xrange(0, 4):
128 name = dns.name.from_text('example%d.' % i)
129 answer = FakeAnswer(time.time() + 1)
130 cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
131 name = dns.name.from_text('example0.')
132 cache.get((name, dns.rdatatype.A, dns.rdataclass.IN))
133 # The LRU is now example1.
134 name = dns.name.from_text('example4.')
135 answer = FakeAnswer(time.time() + 1)
136 cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
137 for i in xrange(0, 5):
138 name = dns.name.from_text('example%d.' % i)
139 if i == 1:
140 self.failUnless(cache.get((name, dns.rdatatype.A,
141 dns.rdataclass.IN))
142 is None)
143 else:
144 self.failUnless(not cache.get((name, dns.rdatatype.A,
145 dns.rdataclass.IN))
146 is None)
147
148 def testLRUExpiration(self):
149 cache = dns.resolver.LRUCache(4)
150 for i in xrange(0, 4):
151 name = dns.name.from_text('example%d.' % i)
152 answer = FakeAnswer(time.time() + 1)
153 cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer)
154 time.sleep(2)
155 for i in xrange(0, 4):
156 name = dns.name.from_text('example%d.' % i)
157 self.failUnless(cache.get((name, dns.rdatatype.A,
158 dns.rdataclass.IN))
159 is None)
160
104161 class PollingMonkeyPatchMixin(object):
105162 def setUp(self):
106163 self.__native_polling_backend = dns.query._polling_backend
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,
0 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
11 #
22 # Permission to use, copy, modify, and distribute this software and its
33 # documentation for any purpose with or without fee is hereby granted,