Imported Upstream version 1.10.0
SVN-Git Migration
8 years ago
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 | ||
0 | 79 | 2011-03-24 Bob Halley <halley@dnspython.org> |
1 | 80 | |
2 | 81 | * dns/rdata.py (Rdata._wire_cmp): We need to specify no |
0 | 0 | Metadata-Version: 1.1 |
1 | 1 | Name: dnspython |
2 | Version: 1.9.4 | |
2 | Version: 1.10.0 | |
3 | 3 | Summary: DNS toolkit |
4 | 4 | Home-page: http://www.dnspython.org |
5 | 5 | Author: Bob Halley |
6 | 6 | Author-email: halley@dnspython.org |
7 | 7 | 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 | |
9 | 9 | Description: dnspython is a DNS toolkit for Python. It supports almost all |
10 | 10 | record types. It can be used for queries, zone transfers, and dynamic |
11 | 11 | updates. It supports TSIG authenticated messages and EDNS0. |
21 | 21 | |
22 | 22 | ABOUT THIS RELEASE |
23 | 23 | |
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. | |
25 | 65 | |
26 | 66 | New since 1.9.3: |
27 | 67 |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
48 | 48 | 'rdtypes', |
49 | 49 | 'update', |
50 | 50 | 'version', |
51 | 'wiredata', | |
51 | 52 | 'zone', |
52 | 53 | ] |
0 | # Copyright (C) 2003-2007, 2009 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
98 | 98 | return (ord(rdata[-3]) << 8) + ord(rdata[-2]) |
99 | 99 | else: |
100 | 100 | total = 0 |
101 | for i in range(len(rdata) / 2): | |
101 | for i in range(len(rdata) // 2): | |
102 | 102 | total += (ord(rdata[2 * i]) << 8) + ord(rdata[2 * i + 1]) |
103 | 103 | if len(rdata) % 2 != 0: |
104 | 104 | total += ord(rdata[len(rdata) - 1]) << 8 |
298 | 298 | if _is_rsa(rrsig.algorithm): |
299 | 299 | # PKCS1 algorithm identifier goop |
300 | 300 | digest = _make_algorithm_id(rrsig.algorithm) + digest |
301 | padlen = keylen / 8 - len(digest) - 3 | |
301 | padlen = keylen // 8 - len(digest) - 3 | |
302 | 302 | digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest |
303 | 303 | elif _is_dsa(rrsig.algorithm): |
304 | 304 | pass |
0 | # Copyright (C) 2006, 2007, 2009 Nominum, Inc. | |
0 | # Copyright (C) 2006, 2007, 2009, 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
31 | 31 | @type text: str |
32 | 32 | @param origin: The domain in which the number should be constructed. |
33 | 33 | The default is e164.arpa. |
34 | @type: dns.name.Name object or None | |
34 | @type origin: dns.name.Name object or None | |
35 | 35 | @rtype: dns.name.Name object |
36 | 36 | """ |
37 | 37 | parts = [d for d in text if d.isdigit()] |
44 | 44 | @type name: dns.name.Name object. |
45 | 45 | @param origin: A domain containing the ENUM domain name. The |
46 | 46 | 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 | |
48 | 48 | @param want_plus_prefix: if True, add a '+' to the beginning of the |
49 | 49 | returned number. |
50 | 50 | @rtype: str |
0 | # Copyright (C) 2009 Nominum, Inc. | |
0 | # Copyright (C) 2009, 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
22 | 22 | |
23 | 23 | def __init__(self, otype): |
24 | 24 | """Initialize an option. |
25 | @param rdtype: The rdata type | |
26 | @type rdtype: int | |
25 | @param otype: The rdata type | |
26 | @type otype: int | |
27 | 27 | """ |
28 | 28 | self.otype = otype |
29 | 29 |
0 | # Copyright (C) 2009 Nominum, Inc. | |
0 | # Copyright (C) 2009, 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
0 | # Copyright (C) 2010 Nominum, Inc. | |
0 | # Copyright (C) 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
14 | 14 | |
15 | 15 | """IPv4 helper functions.""" |
16 | 16 | |
17 | import socket | |
18 | import sys | |
17 | import struct | |
19 | 18 | |
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 | |
34 | 20 | |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
88 | 88 | hex = ':'.join(chunks) |
89 | 89 | return hex |
90 | 90 | |
91 | _v4_ending = re.compile(r'(.*):(\d+)\.(\d+)\.(\d+)\.(\d+)$') | |
91 | _v4_ending = re.compile(r'(.*):(\d+\.\d+\.\d+\.\d+)$') | |
92 | 92 | _colon_colon_start = re.compile(r'::.*') |
93 | 93 | _colon_colon_end = re.compile(r'.*::$') |
94 | 94 | |
112 | 112 | # |
113 | 113 | m = _v4_ending.match(text) |
114 | 114 | 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])) | |
118 | 118 | # |
119 | 119 | # Try to turn '::<whatever>' into ':<whatever>'; if no match try to |
120 | 120 | # turn '<whatever>::' into '<whatever>:' |
0 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
33 | 33 | import dns.rrset |
34 | 34 | import dns.renderer |
35 | 35 | import dns.tsig |
36 | import dns.wiredata | |
36 | 37 | |
37 | 38 | class ShortHeader(dns.exception.FormError): |
38 | 39 | """Raised if the DNS packet passed to from_wire() is too short.""" |
569 | 570 | @type updating: bool |
570 | 571 | @ivar one_rr_per_rrset: Put each RR into its own RRset? |
571 | 572 | @type one_rr_per_rrset: bool |
573 | @ivar ignore_trailing: Ignore trailing junk at end of request? | |
574 | @type ignore_trailing: bool | |
572 | 575 | @ivar zone_rdclass: The class of the zone in messages which are |
573 | 576 | DNS dynamic updates. |
574 | 577 | @type zone_rdclass: int |
575 | 578 | """ |
576 | 579 | |
577 | 580 | 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) | |
580 | 583 | self.message = message |
581 | 584 | self.current = 0 |
582 | 585 | self.updating = False |
583 | 586 | self.zone_rdclass = dns.rdataclass.IN |
584 | 587 | self.question_only = question_only |
585 | 588 | self.one_rr_per_rrset = one_rr_per_rrset |
589 | self.ignore_trailing = ignore_trailing | |
586 | 590 | |
587 | 591 | def _get_question(self, qcount): |
588 | 592 | """Read the next I{qcount} records from the wire data and add them to |
720 | 724 | self._get_section(self.message.answer, ancount) |
721 | 725 | self._get_section(self.message.authority, aucount) |
722 | 726 | self._get_section(self.message.additional, adcount) |
723 | if self.current != l: | |
727 | if not self.ignore_trailing and self.current != l: | |
724 | 728 | raise TrailingJunk |
725 | 729 | if self.message.multi and self.message.tsig_ctx and \ |
726 | 730 | not self.message.had_tsig: |
729 | 733 | |
730 | 734 | def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None, |
731 | 735 | 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): | |
733 | 738 | """Convert a DNS wire format message into a message |
734 | 739 | object. |
735 | 740 | |
755 | 760 | @type question_only: bool |
756 | 761 | @param one_rr_per_rrset: Put each RR into its own RRset |
757 | 762 | @type one_rr_per_rrset: bool |
763 | @param ignore_trailing: Ignore trailing junk at end of request? | |
764 | @type ignore_trailing: bool | |
758 | 765 | @raises ShortHeader: The message is less than 12 octets long. |
759 | 766 | @raises TrailingJunk: There were octets in the message past the end |
760 | 767 | of the proper DNS message. |
773 | 780 | m.multi = multi |
774 | 781 | m.first = first |
775 | 782 | |
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) | |
777 | 785 | reader.read() |
778 | 786 | |
779 | 787 | return m |
1013 | 1021 | return m |
1014 | 1022 | |
1015 | 1023 | 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): | |
1017 | 1026 | """Make a query message. |
1018 | 1027 | |
1019 | 1028 | The query name, type, and class may all be specified either |
1034 | 1043 | @type use_edns: int or bool or None |
1035 | 1044 | @param want_dnssec: Should the query indicate that DNSSEC is desired? |
1036 | 1045 | @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 | |
1037 | 1057 | @rtype: dns.message.Message object""" |
1038 | 1058 | |
1039 | 1059 | if isinstance(qname, (str, unicode)): |
1046 | 1066 | m.flags |= dns.flags.RD |
1047 | 1067 | m.find_rrset(m.question, qname, rdclass, rdtype, create=True, |
1048 | 1068 | force_unique=True) |
1049 | m.use_edns(use_edns) | |
1069 | m.use_edns(use_edns, ednsflags, payload, request_payload, options) | |
1050 | 1070 | m.want_dnssec(want_dnssec) |
1051 | 1071 | return m |
1052 | 1072 |
0 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
28 | 28 | import encodings.idna |
29 | 29 | |
30 | 30 | import dns.exception |
31 | import dns.wiredata | |
31 | 32 | |
32 | 33 | NAMERELN_NONE = 0 |
33 | 34 | NAMERELN_SUPERDOMAIN = 1 |
669 | 670 | |
670 | 671 | if not isinstance(message, str): |
671 | 672 | raise ValueError("input to from_wire() must be a byte string") |
673 | message = dns.wiredata.maybe_wrap(message) | |
672 | 674 | labels = [] |
673 | 675 | biggest_pointer = current |
674 | 676 | hops = 0 |
677 | 679 | cused = 1 |
678 | 680 | while count != 0: |
679 | 681 | if count < 64: |
680 | labels.append(message[current : current + count]) | |
682 | labels.append(message[current : current + count].unwrap()) | |
681 | 683 | current += count |
682 | 684 | if hops == 0: |
683 | 685 | cused += count |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
166 | 166 | at the node, it stores I{replacement} itself. |
167 | 167 | """ |
168 | 168 | |
169 | if not isinstance(replacement, dns.rdataset.Rdataset): | |
170 | raise ValueError, 'replacement is not an rdataset' | |
169 | 171 | self.delete_rdataset(replacement.rdclass, replacement.rdtype, |
170 | 172 | replacement.covers) |
171 | 173 | self.rdatasets.append(replacement) |
0 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
45 | 45 | return time.time() + timeout |
46 | 46 | |
47 | 47 | 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 | |
54 | 57 | @return True on success, False on timeout |
55 | 58 | """ |
56 | 59 | event_mask = 0 |
72 | 75 | return bool(event_list) |
73 | 76 | |
74 | 77 | 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 | |
81 | 87 | @return True on success, False on timeout |
82 | 88 | """ |
83 | 89 | rset, wset, xset = [], [], [] |
143 | 149 | n2 = dns.inet.inet_pton(af, a2[0]) |
144 | 150 | return n1 == n2 and a1[1:] == a2[1:] |
145 | 151 | |
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 | ||
146 | 174 | def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0, |
147 | 175 | ignore_unexpected=False, one_rr_per_rrset=False): |
148 | 176 | """Return the response obtained after sending a query via UDP. |
161 | 189 | If the inference attempt fails, AF_INET is used. |
162 | 190 | @type af: int |
163 | 191 | @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. | |
165 | 193 | @type source: string |
166 | 194 | @param source_port: The port from which to send the message. |
167 | 195 | The default is 0. |
174 | 202 | """ |
175 | 203 | |
176 | 204 | 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) | |
190 | 207 | s = socket.socket(af, socket.SOCK_DGRAM, 0) |
191 | 208 | try: |
192 | 209 | expiration = _compute_expiration(timeout) |
269 | 286 | If the inference attempt fails, AF_INET is used. |
270 | 287 | @type af: int |
271 | 288 | @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. | |
273 | 290 | @type source: string |
274 | 291 | @param source_port: The port from which to send the message. |
275 | 292 | The default is 0. |
279 | 296 | """ |
280 | 297 | |
281 | 298 | 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) | |
295 | 301 | s = socket.socket(af, socket.SOCK_STREAM, 0) |
296 | 302 | try: |
297 | 303 | expiration = _compute_expiration(timeout) |
356 | 362 | take. |
357 | 363 | @type lifetime: float |
358 | 364 | @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. | |
360 | 366 | @type source: string |
361 | 367 | @param source_port: The port from which to send the message. |
362 | 368 | The default is 0. |
383 | 389 | if not keyring is None: |
384 | 390 | q.use_tsig(keyring, keyname, algorithm=keyalgorithm) |
385 | 391 | 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) | |
399 | 394 | if use_udp: |
400 | 395 | if rdtype != dns.rdatatype.IXFR: |
401 | 396 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
31 | 31 | import dns.rdataclass |
32 | 32 | import dns.rdatatype |
33 | 33 | import dns.tokenizer |
34 | import dns.wiredata | |
34 | 35 | |
35 | 36 | _hex_chunksize = 32 |
36 | 37 | |
411 | 412 | Once a class is chosen, its from_text() class method is called |
412 | 413 | with the parameters to this function. |
413 | 414 | |
415 | If I{tok} is a string, then a tokenizer is created and the string | |
416 | is used as its input. | |
417 | ||
414 | 418 | @param rdclass: The rdata class |
415 | 419 | @type rdclass: int |
416 | 420 | @param rdtype: The rdata type |
417 | 421 | @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 | |
420 | 424 | @param origin: The origin to use for relative names |
421 | 425 | @type origin: dns.name.Name |
422 | 426 | @param relativize: Should names be relativized? |
468 | 472 | @type origin: dns.name.Name |
469 | 473 | @rtype: dns.rdata.Rdata instance""" |
470 | 474 | |
475 | wire = dns.wiredata.maybe_wrap(wire) | |
471 | 476 | cls = get_rdata_class(rdclass, rdtype) |
472 | 477 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
73 | 73 | @param text: the text |
74 | 74 | @type text: string |
75 | 75 | @rtype: int |
76 | @raises dns.rdataclass.UnknownRdataClass: the class is unknown | |
76 | @raises dns.rdataclass.UnknownRdataclass: the class is unknown | |
77 | 77 | @raises ValueError: the rdata class value is not >= 0 and <= 65535 |
78 | 78 | """ |
79 | 79 |
0 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
105 | 105 | file.write(self.certificate) |
106 | 106 | |
107 | 107 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
108 | prefix = wire[current : current + 5] | |
108 | prefix = wire[current : current + 5].unwrap() | |
109 | 109 | current += 5 |
110 | 110 | rdlen -= 5 |
111 | 111 | if rdlen < 0: |
112 | 112 | raise dns.exception.FormError |
113 | 113 | (certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix) |
114 | certificate = wire[current : current + rdlen] | |
114 | certificate = wire[current : current + rdlen].unwrap() | |
115 | 115 | return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, |
116 | 116 | certificate) |
117 | 117 |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
12 | 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
13 | 13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | 14 | |
15 | import dns.rdtypes.keybase | |
15 | ||
16 | import struct | |
17 | ||
18 | import dns.exception | |
19 | import dns.dnssec | |
20 | import dns.rdata | |
16 | 21 | |
17 | 22 | # flag constants |
18 | 23 | SEP = 0x0001 |
19 | 24 | REVOKE = 0x0080 |
20 | 25 | ZONE = 0x0100 |
21 | 26 | |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
28 | 28 | raise dns.exception.FormError |
29 | 29 | if not right == '' and not right.isdigit(): |
30 | 30 | raise dns.exception.FormError |
31 | ||
31 | ||
32 | 32 | class GPOS(dns.rdata.Rdata): |
33 | 33 | """GPOS record |
34 | 34 | |
41 | 41 | @see: RFC 1712""" |
42 | 42 | |
43 | 43 | __slots__ = ['latitude', 'longitude', 'altitude'] |
44 | ||
44 | ||
45 | 45 | def __init__(self, rdclass, rdtype, latitude, longitude, altitude): |
46 | 46 | super(GPOS, self).__init__(rdclass, rdtype) |
47 | 47 | if isinstance(latitude, float) or \ |
65 | 65 | |
66 | 66 | def to_text(self, origin=None, relativize=True, **kw): |
67 | 67 | return '%s %s %s' % (self.latitude, self.longitude, self.altitude) |
68 | ||
68 | ||
69 | 69 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
70 | 70 | latitude = tok.get_string() |
71 | 71 | longitude = tok.get_string() |
72 | 72 | altitude = tok.get_string() |
73 | 73 | tok.get_eol() |
74 | 74 | return cls(rdclass, rdtype, latitude, longitude, altitude) |
75 | ||
75 | ||
76 | 76 | from_text = classmethod(from_text) |
77 | 77 | |
78 | 78 | def to_wire(self, file, compress = None, origin = None): |
91 | 91 | byte = chr(l) |
92 | 92 | file.write(byte) |
93 | 93 | file.write(self.altitude) |
94 | ||
94 | ||
95 | 95 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
96 | 96 | l = ord(wire[current]) |
97 | 97 | current += 1 |
98 | 98 | rdlen -= 1 |
99 | 99 | if l > rdlen: |
100 | 100 | raise dns.exception.FormError |
101 | latitude = wire[current : current + l] | |
101 | latitude = wire[current : current + l].unwrap() | |
102 | 102 | current += l |
103 | 103 | rdlen -= l |
104 | 104 | l = ord(wire[current]) |
106 | 106 | rdlen -= 1 |
107 | 107 | if l > rdlen: |
108 | 108 | raise dns.exception.FormError |
109 | longitude = wire[current : current + l] | |
109 | longitude = wire[current : current + l].unwrap() | |
110 | 110 | current += l |
111 | 111 | rdlen -= l |
112 | 112 | l = ord(wire[current]) |
114 | 114 | rdlen -= 1 |
115 | 115 | if l != rdlen: |
116 | 116 | raise dns.exception.FormError |
117 | altitude = wire[current : current + l] | |
117 | altitude = wire[current : current + l].unwrap() | |
118 | 118 | return cls(rdclass, rdtype, latitude, longitude, altitude) |
119 | 119 | |
120 | 120 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
26 | 26 | @see: RFC 1035""" |
27 | 27 | |
28 | 28 | __slots__ = ['cpu', 'os'] |
29 | ||
29 | ||
30 | 30 | def __init__(self, rdclass, rdtype, cpu, os): |
31 | 31 | super(HINFO, self).__init__(rdclass, rdtype) |
32 | 32 | self.cpu = cpu |
35 | 35 | def to_text(self, origin=None, relativize=True, **kw): |
36 | 36 | return '"%s" "%s"' % (dns.rdata._escapify(self.cpu), |
37 | 37 | dns.rdata._escapify(self.os)) |
38 | ||
38 | ||
39 | 39 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
40 | 40 | cpu = tok.get_string() |
41 | 41 | os = tok.get_string() |
42 | 42 | tok.get_eol() |
43 | 43 | return cls(rdclass, rdtype, cpu, os) |
44 | ||
44 | ||
45 | 45 | from_text = classmethod(from_text) |
46 | 46 | |
47 | 47 | def to_wire(self, file, compress = None, origin = None): |
55 | 55 | byte = chr(l) |
56 | 56 | file.write(byte) |
57 | 57 | file.write(self.os) |
58 | ||
58 | ||
59 | 59 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
60 | 60 | l = ord(wire[current]) |
61 | 61 | current += 1 |
62 | 62 | rdlen -= 1 |
63 | 63 | if l > rdlen: |
64 | 64 | raise dns.exception.FormError |
65 | cpu = wire[current : current + l] | |
65 | cpu = wire[current : current + l].unwrap() | |
66 | 66 | current += l |
67 | 67 | rdlen -= l |
68 | 68 | l = ord(wire[current]) |
70 | 70 | rdlen -= 1 |
71 | 71 | if l != rdlen: |
72 | 72 | raise dns.exception.FormError |
73 | os = wire[current : current + l] | |
73 | os = wire[current : current + l].unwrap() | |
74 | 74 | return cls(rdclass, rdtype, cpu, os) |
75 | 75 | |
76 | 76 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2010 Nominum, Inc. | |
0 | # Copyright (C) 2010, 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
85 | 85 | wire[current : current + 4]) |
86 | 86 | current += 4 |
87 | 87 | rdlen -= 4 |
88 | hit = wire[current : current + lh] | |
88 | hit = wire[current : current + lh].unwrap() | |
89 | 89 | current += lh |
90 | 90 | rdlen -= lh |
91 | key = wire[current : current + lk] | |
91 | key = wire[current : current + lk].unwrap() | |
92 | 92 | current += lk |
93 | 93 | rdlen -= lk |
94 | 94 | servers = [] |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
72 | 72 | rdlen -= 1 |
73 | 73 | if l > rdlen: |
74 | 74 | raise dns.exception.FormError |
75 | address = wire[current : current + l] | |
75 | address = wire[current : current + l].unwrap() | |
76 | 76 | current += l |
77 | 77 | rdlen -= l |
78 | 78 | if rdlen > 0: |
81 | 81 | rdlen -= 1 |
82 | 82 | if l != rdlen: |
83 | 83 | raise dns.exception.FormError |
84 | subaddress = wire[current : current + l] | |
84 | subaddress = wire[current : current + l].unwrap() | |
85 | 85 | else: |
86 | 86 | subaddress = '' |
87 | 87 | return cls(rdclass, rdtype, address, subaddress) |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
78 | 78 | bitmap = ['\0'] * 32 |
79 | 79 | window = new_window |
80 | 80 | offset = nrdtype % 256 |
81 | byte = offset / 8 | |
81 | byte = offset // 8 | |
82 | 82 | bit = offset % 8 |
83 | 83 | octets = byte + 1 |
84 | 84 | bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit)) |
110 | 110 | rdlen -= 2 |
111 | 111 | if rdlen < octets: |
112 | 112 | raise dns.exception.FormError("bad NSEC bitmap length") |
113 | bitmap = wire[current : current + octets] | |
113 | bitmap = wire[current : current + octets].unwrap() | |
114 | 114 | current += octets |
115 | 115 | rdlen -= octets |
116 | 116 | windows.append((window, bitmap)) |
0 | # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
117 | 117 | bitmap = ['\0'] * 32 |
118 | 118 | window = new_window |
119 | 119 | offset = nrdtype % 256 |
120 | byte = offset / 8 | |
120 | byte = offset // 8 | |
121 | 121 | bit = offset % 8 |
122 | 122 | octets = byte + 1 |
123 | 123 | bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit)) |
144 | 144 | wire[current : current + 5]) |
145 | 145 | current += 5 |
146 | 146 | rdlen -= 5 |
147 | salt = wire[current : current + slen] | |
147 | salt = wire[current : current + slen].unwrap() | |
148 | 148 | current += slen |
149 | 149 | rdlen -= slen |
150 | 150 | (nlen, ) = struct.unpack('!B', wire[current]) |
151 | 151 | current += 1 |
152 | 152 | rdlen -= 1 |
153 | next = wire[current : current + nlen] | |
153 | next = wire[current : current + nlen].unwrap() | |
154 | 154 | current += nlen |
155 | 155 | rdlen -= nlen |
156 | 156 | windows = [] |
165 | 165 | rdlen -= 2 |
166 | 166 | if rdlen < octets: |
167 | 167 | raise dns.exception.FormError("bad NSEC3 bitmap length") |
168 | bitmap = wire[current : current + octets] | |
168 | bitmap = wire[current : current + octets].unwrap() | |
169 | 169 | current += octets |
170 | 170 | rdlen -= octets |
171 | 171 | windows.append((window, bitmap)) |
0 | # Copyright (C) 2004-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
70 | 70 | wire[current : current + 5]) |
71 | 71 | current += 5 |
72 | 72 | rdlen -= 5 |
73 | salt = wire[current : current + slen] | |
73 | salt = wire[current : current + slen].unwrap() | |
74 | 74 | current += slen |
75 | 75 | rdlen -= slen |
76 | 76 | if rdlen != 0: |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
12 | 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
13 | 13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | 14 | |
15 | import dns.rdtypes.sigbase | |
15 | import calendar | |
16 | import struct | |
17 | import time | |
16 | 18 | |
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.""" | |
19 | 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 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
40 | 40 | |
41 | 41 | __slots__ = ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', |
42 | 42 | 'minimum'] |
43 | ||
43 | ||
44 | 44 | def __init__(self, rdclass, rdtype, mname, rname, serial, refresh, retry, |
45 | 45 | expire, minimum): |
46 | 46 | super(SOA, self).__init__(rdclass, rdtype) |
58 | 58 | return '%s %s %d %d %d %d %d' % ( |
59 | 59 | mname, rname, self.serial, self.refresh, self.retry, |
60 | 60 | self.expire, self.minimum ) |
61 | ||
61 | ||
62 | 62 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
63 | 63 | mname = tok.get_name() |
64 | 64 | rname = tok.get_name() |
72 | 72 | tok.get_eol() |
73 | 73 | return cls(rdclass, rdtype, mname, rname, serial, refresh, retry, |
74 | 74 | expire, minimum ) |
75 | ||
75 | ||
76 | 76 | from_text = classmethod(from_text) |
77 | 77 | |
78 | 78 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
29 | 29 | @see: draft-ietf-secsh-dns-05.txt""" |
30 | 30 | |
31 | 31 | __slots__ = ['algorithm', 'fp_type', 'fingerprint'] |
32 | ||
32 | ||
33 | 33 | def __init__(self, rdclass, rdtype, algorithm, fp_type, |
34 | 34 | fingerprint): |
35 | 35 | super(SSHFP, self).__init__(rdclass, rdtype) |
42 | 42 | self.fp_type, |
43 | 43 | dns.rdata._hexify(self.fingerprint, |
44 | 44 | chunksize=128)) |
45 | ||
45 | ||
46 | 46 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
47 | 47 | algorithm = tok.get_uint8() |
48 | 48 | 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) | |
50 | 58 | fingerprint = fingerprint.decode('hex_codec') |
51 | tok.get_eol() | |
52 | 59 | return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) |
53 | ||
60 | ||
54 | 61 | from_text = classmethod(from_text) |
55 | 62 | |
56 | 63 | def to_wire(self, file, compress = None, origin = None): |
57 | 64 | header = struct.pack("!BB", self.algorithm, self.fp_type) |
58 | 65 | file.write(header) |
59 | 66 | file.write(self.fingerprint) |
60 | ||
67 | ||
61 | 68 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
62 | 69 | header = struct.unpack("!BB", wire[current : current + 2]) |
63 | 70 | current += 2 |
64 | 71 | rdlen -= 2 |
65 | fingerprint = wire[current : current + rdlen] | |
72 | fingerprint = wire[current : current + rdlen].unwrap() | |
66 | 73 | return cls(rdclass, rdtype, header[0], header[1], fingerprint) |
67 | 74 | |
68 | 75 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
24 | 24 | @see: RFC 1183""" |
25 | 25 | |
26 | 26 | __slots__ = ['address'] |
27 | ||
27 | ||
28 | 28 | def __init__(self, rdclass, rdtype, address): |
29 | 29 | super(X25, self).__init__(rdclass, rdtype) |
30 | 30 | self.address = address |
31 | 31 | |
32 | 32 | def to_text(self, origin=None, relativize=True, **kw): |
33 | 33 | return '"%s"' % dns.rdata._escapify(self.address) |
34 | ||
34 | ||
35 | 35 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
36 | 36 | address = tok.get_string() |
37 | 37 | tok.get_eol() |
38 | 38 | return cls(rdclass, rdtype, address) |
39 | ||
39 | ||
40 | 40 | from_text = classmethod(from_text) |
41 | 41 | |
42 | 42 | def to_wire(self, file, compress = None, origin = None): |
45 | 45 | byte = chr(l) |
46 | 46 | file.write(byte) |
47 | 47 | file.write(self.address) |
48 | ||
48 | ||
49 | 49 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
50 | 50 | l = ord(wire[current]) |
51 | 51 | current += 1 |
52 | 52 | rdlen -= 1 |
53 | 53 | if l != rdlen: |
54 | 54 | raise dns.exception.FormError |
55 | address = wire[current : current + l] | |
55 | address = wire[current : current + l].unwrap() | |
56 | 56 | return cls(rdclass, rdtype, address) |
57 | 57 | |
58 | 58 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
26 | 26 | 'HINFO', |
27 | 27 | 'HIP', |
28 | 28 | 'ISDN', |
29 | 'KEY', | |
30 | 29 | 'LOC', |
31 | 30 | 'MX', |
32 | 31 | 'NS', |
33 | 32 | 'NSEC', |
34 | 33 | 'NSEC3', |
35 | 34 | 'NSEC3PARAM', |
36 | 'NXT', | |
37 | 35 | 'PTR', |
38 | 36 | 'RP', |
39 | 37 | 'RRSIG', |
40 | 38 | 'RT', |
41 | 'SIG', | |
42 | 39 | 'SOA', |
43 | 40 | 'SPF', |
44 | 41 | 'SSHFP', |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
130 | 130 | rdlen -= 4 |
131 | 131 | if rdlen < afdlen: |
132 | 132 | raise dns.exception.FormError |
133 | address = wire[current : current + afdlen] | |
133 | address = wire[current : current + afdlen].unwrap() | |
134 | 134 | l = len(address) |
135 | 135 | if header[0] == 1: |
136 | 136 | if l < 4: |
0 | # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
50 | 50 | file.write(self.data) |
51 | 51 | |
52 | 52 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
53 | data = wire[current : current + rdlen] | |
53 | data = wire[current : current + rdlen].unwrap() | |
54 | 54 | return cls(rdclass, rdtype, data) |
55 | 55 | |
56 | 56 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2006, 2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
139 | 139 | rdlen -= cused |
140 | 140 | else: |
141 | 141 | raise dns.exception.FormError('invalid IPSECKEY gateway type') |
142 | key = wire[current : current + rdlen] | |
142 | key = wire[current : current + rdlen].unwrap() | |
143 | 143 | return cls(rdclass, rdtype, header[0], gateway_type, header[2], |
144 | 144 | gateway, key) |
145 | 145 |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
44 | 44 | |
45 | 45 | __slots__ = ['order', 'preference', 'flags', 'service', 'regexp', |
46 | 46 | 'replacement'] |
47 | ||
47 | ||
48 | 48 | def __init__(self, rdclass, rdtype, order, preference, flags, service, |
49 | 49 | regexp, replacement): |
50 | 50 | super(NAPTR, self).__init__(rdclass, rdtype) |
75 | 75 | tok.get_eol() |
76 | 76 | return cls(rdclass, rdtype, order, preference, flags, service, |
77 | 77 | regexp, replacement) |
78 | ||
78 | ||
79 | 79 | from_text = classmethod(from_text) |
80 | 80 | |
81 | 81 | def to_wire(self, file, compress = None, origin = None): |
85 | 85 | _write_string(file, self.service) |
86 | 86 | _write_string(file, self.regexp) |
87 | 87 | self.replacement.to_wire(file, compress, origin) |
88 | ||
88 | ||
89 | 89 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
90 | 90 | (order, preference) = struct.unpack('!HH', wire[current : current + 4]) |
91 | 91 | current += 4 |
97 | 97 | rdlen -= 1 |
98 | 98 | if l > rdlen or rdlen < 0: |
99 | 99 | raise dns.exception.FormError |
100 | s = wire[current : current + l] | |
100 | s = wire[current : current + l].unwrap() | |
101 | 101 | current += l |
102 | 102 | rdlen -= l |
103 | 103 | strings.append(s) |
115 | 115 | def choose_relativity(self, origin = None, relativize = True): |
116 | 116 | self.replacement = self.replacement.choose_relativity(origin, |
117 | 117 | relativize) |
118 | ||
118 | ||
119 | 119 | def _cmp(self, other): |
120 | 120 | sp = struct.pack("!HH", self.order, self.preference) |
121 | 121 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
49 | 49 | file.write(self.address) |
50 | 50 | |
51 | 51 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
52 | address = wire[current : current + rdlen] | |
52 | address = wire[current : current + rdlen].unwrap() | |
53 | 53 | return cls(rdclass, rdtype, address) |
54 | 54 | |
55 | 55 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
30 | 30 | @see: RFC 2163""" |
31 | 31 | |
32 | 32 | __slots__ = ['preference', 'map822', 'mapx400'] |
33 | ||
33 | ||
34 | 34 | def __init__(self, rdclass, rdtype, preference, map822, mapx400): |
35 | 35 | super(PX, self).__init__(rdclass, rdtype) |
36 | 36 | self.preference = preference |
41 | 41 | map822 = self.map822.choose_relativity(origin, relativize) |
42 | 42 | mapx400 = self.mapx400.choose_relativity(origin, relativize) |
43 | 43 | return '%d %s %s' % (self.preference, map822, mapx400) |
44 | ||
44 | ||
45 | 45 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
46 | 46 | preference = tok.get_uint16() |
47 | 47 | map822 = tok.get_name() |
50 | 50 | mapx400 = mapx400.choose_relativity(origin, relativize) |
51 | 51 | tok.get_eol() |
52 | 52 | return cls(rdclass, rdtype, preference, map822, mapx400) |
53 | ||
53 | ||
54 | 54 | from_text = classmethod(from_text) |
55 | 55 | |
56 | 56 | def to_wire(self, file, compress = None, origin = None): |
58 | 58 | file.write(pref) |
59 | 59 | self.map822.to_wire(file, None, origin) |
60 | 60 | self.mapx400.to_wire(file, None, origin) |
61 | ||
61 | ||
62 | 62 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
63 | 63 | (preference, ) = struct.unpack('!H', wire[current : current + 2]) |
64 | 64 | current += 2 |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
94 | 94 | protocol, = struct.unpack('!B', wire[current + 4 : current + 5]) |
95 | 95 | current += 5 |
96 | 96 | rdlen -= 5 |
97 | bitmap = wire[current : current + rdlen] | |
97 | bitmap = wire[current : current + rdlen].unwrap() | |
98 | 98 | return cls(rdclass, rdtype, address, protocol, bitmap) |
99 | 99 | |
100 | 100 | from_wire = classmethod(from_wire) |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
19 | 19 | 'IN', |
20 | 20 | 'mxbase', |
21 | 21 | 'nsbase', |
22 | 'sigbase', | |
23 | 'keybase', | |
24 | 22 | ] |
0 | # Copyright (C) 2010 Nominum, Inc. | |
0 | # Copyright (C) 2010, 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
75 | 75 | header = struct.unpack("!HBB", wire[current : current + 4]) |
76 | 76 | current += 4 |
77 | 77 | rdlen -= 4 |
78 | digest = wire[current : current + rdlen] | |
78 | digest = wire[current : current + rdlen].unwrap() | |
79 | 79 | return cls(rdclass, rdtype, header[0], header[1], header[2], digest) |
80 | 80 | |
81 | 81 | from_wire = classmethod(from_wire) |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
74 | 74 | rdlen -= 1 |
75 | 75 | if l > rdlen: |
76 | 76 | raise dns.exception.FormError |
77 | s = wire[current : current + l] | |
77 | s = wire[current : current + l].unwrap() | |
78 | 78 | current += l |
79 | 79 | rdlen -= l |
80 | 80 | strings.append(s) |
0 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
266 | 266 | @type other_data: string |
267 | 267 | @param request_mac: This message is a response to the request which |
268 | 268 | had the specified MAC. |
269 | @type request_mac: string | |
269 | 270 | @param algorithm: the TSIG algorithm to use |
270 | @type request_mac: string | |
271 | @type algorithm: dns.name.Name object | |
271 | 272 | """ |
272 | 273 | |
273 | 274 | self._set_section(ADDITIONAL) |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
22 | 22 | import time |
23 | 23 | |
24 | 24 | import dns.exception |
25 | import dns.flags | |
26 | import dns.ipv4 | |
27 | import dns.ipv6 | |
25 | 28 | import dns.message |
26 | 29 | import dns.name |
27 | 30 | import dns.query |
28 | 31 | import dns.rcode |
29 | 32 | import dns.rdataclass |
30 | 33 | import dns.rdatatype |
34 | import dns.reversename | |
31 | 35 | |
32 | 36 | if sys.platform == 'win32': |
33 | 37 | import _winreg |
266 | 270 | self.data = {} |
267 | 271 | self.next_cleaning = time.time() + self.cleaning_interval |
268 | 272 | |
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 | ||
269 | 393 | class Resolver(object): |
270 | 394 | """DNS stub resolver |
271 | 395 | |
568 | 692 | return min(self.lifetime - duration, self.timeout) |
569 | 693 | |
570 | 694 | 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): | |
572 | 696 | """Query nameservers to find the answer to the question. |
573 | 697 | |
574 | 698 | The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects |
589 | 713 | @param raise_on_no_answer: raise NoAnswer if there's no answer |
590 | 714 | (defaults is True). |
591 | 715 | @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 | |
592 | 719 | @rtype: dns.resolver.Answer instance |
593 | 720 | @raises Timeout: no answers could be found in the specified lifetime |
594 | 721 | @raises NXDOMAIN: the query name does not exist |
623 | 750 | for qname in qnames_to_try: |
624 | 751 | if self.cache: |
625 | 752 | 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 | |
628 | 758 | request = dns.message.make_query(qname, rdtype, rdclass) |
629 | 759 | if not self.keyname is None: |
630 | 760 | request.use_tsig(self.keyring, self.keyname, |
645 | 775 | if tcp: |
646 | 776 | response = dns.query.tcp(request, nameserver, |
647 | 777 | timeout, self.port, |
648 | source=source) | |
778 | source=source, | |
779 | source_port=source_port) | |
649 | 780 | else: |
650 | 781 | response = dns.query.udp(request, nameserver, |
651 | 782 | 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) | |
653 | 792 | except (socket.error, dns.exception.Timeout): |
654 | 793 | # |
655 | 794 | # Communication failure or timeout. Go to the |
668 | 807 | # We don't understand what this server is |
669 | 808 | # saying. Take it out of the mix and |
670 | 809 | # 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. | |
671 | 820 | # |
672 | 821 | nameservers.remove(nameserver) |
673 | 822 | response = None |
758 | 907 | return default_resolver |
759 | 908 | |
760 | 909 | 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): | |
762 | 912 | """Query nameservers to find the answer to the question. |
763 | 913 | |
764 | 914 | This is a convenience function that uses the default resolver |
766 | 916 | @see: L{dns.resolver.Resolver.query} for more information on the |
767 | 917 | parameters.""" |
768 | 918 | return get_default_resolver().query(qname, rdtype, rdclass, tcp, source, |
769 | raise_on_no_answer) | |
919 | raise_on_no_answer, source_port) | |
770 | 920 | |
771 | 921 | def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None): |
772 | 922 | """Find the name of the zone which contains the specified name. |
799 | 949 | name = name.parent() |
800 | 950 | except dns.name.NoParent: |
801 | 951 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
61 | 61 | |
62 | 62 | @param ttype: The token type |
63 | 63 | @type ttype: int |
64 | @ivar value: The token value | |
64 | @param value: The token value | |
65 | 65 | @type value: string |
66 | @ivar has_escape: Does the token value contain escapes? | |
66 | @param has_escape: Does the token value contain escapes? | |
67 | 67 | @type has_escape: bool |
68 | 68 | """ |
69 | 69 | self.ttype = ttype |
0 | # Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
15 | 15 | """dnspython release version information.""" |
16 | 16 | |
17 | 17 | MAJOR = 1 |
18 | MINOR = 9 | |
19 | MICRO = 4 | |
18 | MINOR = 10 | |
19 | MICRO = 0 | |
20 | 20 | RELEASELEVEL = 0x0f |
21 | 21 | SERIAL = 0 |
22 | 22 |
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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
816 | 816 | f.close() |
817 | 817 | return z |
818 | 818 | |
819 | def from_xfr(xfr, zone_factory=Zone, relativize=True): | |
819 | def from_xfr(xfr, zone_factory=Zone, relativize=True, check_origin=True): | |
820 | 820 | """Convert the output of a zone transfer generator into a zone object. |
821 | 821 | |
822 | 822 | @param xfr: The xfr generator |
825 | 825 | It is essential that the relativize setting matches the one specified |
826 | 826 | to dns.query.xfr(). |
827 | 827 | @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 | |
828 | 831 | @raises dns.zone.NoSOA: No SOA RR was found at the zone origin |
829 | 832 | @raises dns.zone.NoNS: No NS RRset was found at the zone origin |
830 | 833 | @rtype: dns.zone.Zone object |
850 | 853 | for rd in rrset: |
851 | 854 | rd.choose_relativity(z.origin, relativize) |
852 | 855 | zrds.add(rd) |
853 | z.check_origin() | |
856 | if check_origin: | |
857 | z.check_origin() | |
854 | 858 | return z |
0 | 0 | #!/usr/bin/env python |
1 | 1 | |
2 | 2 | import dns.query |
3 | import dns.resolver | |
3 | 4 | import dns.zone |
4 | 5 | |
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')) | |
6 | 10 | names = z.nodes.keys() |
7 | 11 | names.sort() |
8 | 12 | for n in names: |
0 | 0 | #!/usr/bin/env python |
1 | 1 | # |
2 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
2 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
3 | 3 | # |
4 | 4 | # Permission to use, copy, modify, and distribute this software and its |
5 | 5 | # documentation for any purpose with or without fee is hereby granted, |
17 | 17 | import sys |
18 | 18 | from distutils.core import setup |
19 | 19 | |
20 | version = '1.9.4' | |
20 | version = '1.10.0' | |
21 | 21 | |
22 | 22 | kwargs = { |
23 | 23 | 'name' : 'dnspython', |
37 | 37 | 'license' : 'BSD-like', |
38 | 38 | 'url' : 'http://www.dnspython.org', |
39 | 39 | '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' : [ | |
47 | 43 | "Development Status :: 5 - Production/Stable", |
48 | 44 | "Intended Audience :: Developers", |
49 | 45 | "Intended Audience :: System Administrators", |
53 | 49 | "Programming Language :: Python", |
54 | 50 | "Topic :: Internet :: Name Service (DNS)", |
55 | 51 | "Topic :: Software Development :: Libraries :: Python Modules", |
56 | ] | |
52 | ], | |
53 | } | |
57 | 54 | |
58 | 55 | if sys.hexversion >= 0x02050000: |
59 | 56 | kwargs['requires'] = [] |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
0 | # Copyright (C) 2010 Nominum, Inc. | |
0 | # Copyright (C) 2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
100 | 100 | isdn02 ISDN "isdn-address" "subaddress" |
101 | 101 | isdn03 ISDN "isdn-address" |
102 | 102 | 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= ) | |
113 | 114 | kx01 KX 10 kdc |
114 | 115 | kx02 KX 10 . |
115 | 116 | loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m |
136 | 137 | NSAP-PTR . |
137 | 138 | nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100 |
138 | 139 | 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 ) | |
143 | 144 | ptr01 PTR example. |
144 | 145 | px01 PX 65535 foo. bar. |
145 | 146 | px02 PX 65535 . . |
153 | 154 | ns A 73.80.65.49 |
154 | 155 | $ORIGIN example. |
155 | 156 | $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= ) | |
161 | 162 | srv01 SRV 0 0 0 . |
162 | 163 | srv02 SRV 65535 65535 65535 old-slow-box.example.com. |
163 | 164 | $TTL 301 ; 5 minutes 1 second |
201 | 202 | yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 |
202 | 203 | GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o |
203 | 204 | jqf0BaqHT+8= ) |
204 | dnskey02 DNSKEY HOST|FLAG4 DNSSEC RSAMD5 ( | |
205 | dnskey02 DNSKEY 257 3 RSAMD5 ( | |
205 | 206 | AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR |
206 | 207 | yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 |
207 | 208 | GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o |
26 | 26 | dname02 3600 IN DNAME dname-target |
27 | 27 | dname03 3600 IN DNAME . |
28 | 28 | 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= | |
30 | 30 | ds01 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890 |
31 | 31 | e 300 IN MX 10 mail |
32 | 32 | e 300 IN TXT "one" |
50 | 50 | isdn02 3600 IN ISDN "isdn-address" "subaddress" |
51 | 51 | isdn03 3600 IN ISDN "isdn-address" |
52 | 52 | 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= | |
55 | 53 | kx01 3600 IN KX 10 kdc |
56 | 54 | kx02 3600 IN KX 10 . |
57 | 55 | loc01 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m |
76 | 74 | nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM |
77 | 75 | nsec3param01 3600 IN NSEC3PARAM 1 1 12 aabbccdd |
78 | 76 | 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 | |
83 | 77 | ptr01 3600 IN PTR @ |
84 | 78 | px01 3600 IN PX 65535 foo. bar. |
85 | 79 | px02 3600 IN PX 65535 . . |
90 | 84 | rt02 3600 IN RT 65535 . |
91 | 85 | s 300 IN NS ns.s |
92 | 86 | 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= | |
94 | 87 | spf 3600 IN SPF "v=spf1 mx -all" |
95 | 88 | srv01 3600 IN SRV 0 0 0 . |
96 | 89 | srv02 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. |
26 | 26 | dname02.example. 3600 IN DNAME dname-target.example. |
27 | 27 | dname03.example. 3600 IN DNAME . |
28 | 28 | 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= | |
30 | 30 | ds01.example. 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890 |
31 | 31 | e.example. 300 IN MX 10 mail.example. |
32 | 32 | e.example. 300 IN TXT "one" |
50 | 50 | isdn02.example. 3600 IN ISDN "isdn-address" "subaddress" |
51 | 51 | isdn03.example. 3600 IN ISDN "isdn-address" |
52 | 52 | 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= | |
55 | 53 | kx01.example. 3600 IN KX 10 kdc.example. |
56 | 54 | kx02.example. 3600 IN KX 10 . |
57 | 55 | loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m |
76 | 74 | nsec302.example. 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM |
77 | 75 | nsec3param01.example. 3600 IN NSEC3PARAM 1 1 12 aabbccdd |
78 | 76 | 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 | |
83 | 77 | ptr01.example. 3600 IN PTR example. |
84 | 78 | px01.example. 3600 IN PX 65535 foo. bar. |
85 | 79 | px02.example. 3600 IN PX 65535 . . |
90 | 84 | rt02.example. 3600 IN RT 65535 . |
91 | 85 | s.example. 300 IN NS ns.s.example. |
92 | 86 | 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= | |
94 | 87 | spf.example. 3600 IN SPF "v=spf1 mx -all" |
95 | 88 | srv01.example. 3600 IN SRV 0 0 0 . |
96 | 89 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
661 | 661 | def testBadReverseIPv4(self): |
662 | 662 | def bad(): |
663 | 663 | n = dns.reversename.from_address('127.0.foo.1') |
664 | self.failUnlessRaises(socket.error, bad) | |
664 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
665 | 665 | |
666 | 666 | def testBadReverseIPv6(self): |
667 | 667 | def bad(): |
668 | 668 | n = dns.reversename.from_address('::1::1') |
669 | self.failUnlessRaises(socket.error, bad) | |
669 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
670 | 670 | |
671 | 671 | def testForwardIPv4(self): |
672 | 672 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
15 | 15 | import unittest |
16 | 16 | |
17 | 17 | import dns.exception |
18 | import dns.ipv4 | |
18 | 19 | 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.'] | |
19 | 30 | |
20 | 31 | class NtoAAtoNTestCase(unittest.TestCase): |
21 | 32 | |
22 | 33 | def test_aton1(self): |
23 | a = dns.ipv6.inet_aton('::') | |
34 | a = aton6('::') | |
24 | 35 | self.failUnless(a == '\x00' * 16) |
25 | 36 | |
26 | 37 | def test_aton2(self): |
27 | a = dns.ipv6.inet_aton('::1') | |
38 | a = aton6('::1') | |
28 | 39 | self.failUnless(a == '\x00' * 15 + '\x01') |
29 | 40 | |
30 | 41 | def test_aton3(self): |
31 | a = dns.ipv6.inet_aton('::10.0.0.1') | |
42 | a = aton6('::10.0.0.1') | |
32 | 43 | self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01') |
33 | 44 | |
34 | 45 | def test_aton4(self): |
35 | a = dns.ipv6.inet_aton('abcd::dcba') | |
46 | a = aton6('abcd::dcba') | |
36 | 47 | self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba') |
37 | 48 | |
38 | 49 | 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') | |
40 | 51 | self.failUnless(a == \ |
41 | 52 | '00010002000300040005000600070008'.decode('hex_codec')) |
42 | 53 | |
43 | 54 | def test_bad_aton1(self): |
44 | 55 | def bad(): |
45 | a = dns.ipv6.inet_aton('abcd:dcba') | |
56 | a = aton6('abcd:dcba') | |
46 | 57 | self.failUnlessRaises(dns.exception.SyntaxError, bad) |
47 | 58 | |
48 | 59 | def test_bad_aton2(self): |
49 | 60 | def bad(): |
50 | a = dns.ipv6.inet_aton('abcd::dcba::1') | |
61 | a = aton6('abcd::dcba::1') | |
51 | 62 | self.failUnlessRaises(dns.exception.SyntaxError, bad) |
52 | 63 | |
53 | 64 | def test_bad_aton3(self): |
54 | 65 | 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') | |
56 | 67 | self.failUnlessRaises(dns.exception.SyntaxError, bad) |
57 | 68 | |
58 | 69 | def test_aton1(self): |
59 | a = dns.ipv6.inet_aton('::') | |
70 | a = aton6('::') | |
60 | 71 | self.failUnless(a == '\x00' * 16) |
61 | 72 | |
62 | 73 | def test_aton2(self): |
63 | a = dns.ipv6.inet_aton('::1') | |
74 | a = aton6('::1') | |
64 | 75 | self.failUnless(a == '\x00' * 15 + '\x01') |
65 | 76 | |
66 | 77 | def test_aton3(self): |
67 | a = dns.ipv6.inet_aton('::10.0.0.1') | |
78 | a = aton6('::10.0.0.1') | |
68 | 79 | self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01') |
69 | 80 | |
70 | 81 | def test_aton4(self): |
71 | a = dns.ipv6.inet_aton('abcd::dcba') | |
82 | a = aton6('abcd::dcba') | |
72 | 83 | self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba') |
73 | 84 | |
74 | 85 | def test_ntoa1(self): |
75 | 86 | b = '00010002000300040005000600070008'.decode('hex_codec') |
76 | t = dns.ipv6.inet_ntoa(b) | |
87 | t = ntoa6(b) | |
77 | 88 | self.failUnless(t == '1:2:3:4:5:6:7:8') |
78 | 89 | |
79 | 90 | def test_ntoa2(self): |
80 | 91 | b = '\x00' * 16 |
81 | t = dns.ipv6.inet_ntoa(b) | |
92 | t = ntoa6(b) | |
82 | 93 | self.failUnless(t == '::') |
83 | 94 | |
84 | 95 | def test_ntoa3(self): |
85 | 96 | b = '\x00' * 15 + '\x01' |
86 | t = dns.ipv6.inet_ntoa(b) | |
97 | t = ntoa6(b) | |
87 | 98 | self.failUnless(t == '::1') |
88 | 99 | |
89 | 100 | def test_ntoa4(self): |
90 | 101 | b = '\x80' + '\x00' * 15 |
91 | t = dns.ipv6.inet_ntoa(b) | |
102 | t = ntoa6(b) | |
92 | 103 | self.failUnless(t == '8000::') |
93 | 104 | |
94 | 105 | def test_ntoa5(self): |
95 | 106 | b = '\x01\xcd' + '\x00' * 12 + '\x03\xef' |
96 | t = dns.ipv6.inet_ntoa(b) | |
107 | t = ntoa6(b) | |
97 | 108 | self.failUnless(t == '1cd::3ef') |
98 | 109 | |
99 | 110 | def test_ntoa6(self): |
100 | 111 | b = 'ffff00000000ffff000000000000ffff'.decode('hex_codec') |
101 | t = dns.ipv6.inet_ntoa(b) | |
112 | t = ntoa6(b) | |
102 | 113 | self.failUnless(t == 'ffff:0:0:ffff::ffff') |
103 | 114 | |
104 | 115 | def test_ntoa7(self): |
105 | 116 | b = '00000000ffff000000000000ffffffff'.decode('hex_codec') |
106 | t = dns.ipv6.inet_ntoa(b) | |
117 | t = ntoa6(b) | |
107 | 118 | self.failUnless(t == '0:0:ffff::ffff:ffff') |
108 | 119 | |
109 | 120 | def test_ntoa8(self): |
110 | 121 | b = 'ffff0000ffff00000000ffff00000000'.decode('hex_codec') |
111 | t = dns.ipv6.inet_ntoa(b) | |
122 | t = ntoa6(b) | |
112 | 123 | self.failUnless(t == 'ffff:0:ffff::ffff:0:0') |
113 | 124 | |
114 | 125 | def test_ntoa9(self): |
115 | 126 | b = '0000000000000000000000000a000001'.decode('hex_codec') |
116 | t = dns.ipv6.inet_ntoa(b) | |
127 | t = ntoa6(b) | |
117 | 128 | self.failUnless(t == '::10.0.0.1') |
118 | 129 | |
119 | 130 | def test_ntoa10(self): |
120 | 131 | b = '0000000000000000000000010a000001'.decode('hex_codec') |
121 | t = dns.ipv6.inet_ntoa(b) | |
132 | t = ntoa6(b) | |
122 | 133 | self.failUnless(t == '::1:a00:1') |
123 | 134 | |
124 | 135 | def test_ntoa11(self): |
125 | 136 | b = '00000000000000000000ffff0a000001'.decode('hex_codec') |
126 | t = dns.ipv6.inet_ntoa(b) | |
137 | t = ntoa6(b) | |
127 | 138 | self.failUnless(t == '::ffff:10.0.0.1') |
128 | 139 | |
129 | 140 | def test_ntoa12(self): |
130 | 141 | b = '000000000000000000000000ffffffff'.decode('hex_codec') |
131 | t = dns.ipv6.inet_ntoa(b) | |
142 | t = ntoa6(b) | |
132 | 143 | self.failUnless(t == '::255.255.255.255') |
133 | 144 | |
134 | 145 | def test_ntoa13(self): |
135 | 146 | b = '00000000000000000000ffffffffffff'.decode('hex_codec') |
136 | t = dns.ipv6.inet_ntoa(b) | |
147 | t = ntoa6(b) | |
137 | 148 | self.failUnless(t == '::ffff:255.255.255.255') |
138 | 149 | |
139 | 150 | def test_ntoa14(self): |
140 | 151 | b = '0000000000000000000000000001ffff'.decode('hex_codec') |
141 | t = dns.ipv6.inet_ntoa(b) | |
152 | t = ntoa6(b) | |
142 | 153 | self.failUnless(t == '::0.1.255.255') |
143 | 154 | |
144 | 155 | def test_bad_ntoa1(self): |
145 | 156 | def bad(): |
146 | a = dns.ipv6.inet_ntoa('') | |
157 | a = ntoa6('') | |
147 | 158 | self.failUnlessRaises(ValueError, bad) |
148 | 159 | |
149 | 160 | def test_bad_ntoa2(self): |
150 | 161 | def bad(): |
151 | a = dns.ipv6.inet_ntoa('\x00' * 17) | |
162 | a = ntoa6('\x00' * 17) | |
152 | 163 | 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)) | |
153 | 194 | |
154 | 195 | if __name__ == '__main__': |
155 | 196 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. | |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |
45 | 45 | ;AUTHORITY |
46 | 46 | ;ADDITIONAL |
47 | 47 | """ |
48 | ||
49 | class FakeAnswer(object): | |
50 | def __init__(self, expiration): | |
51 | self.expiration = expiration | |
48 | 52 | |
49 | 53 | class BaseResolverTests(object): |
50 | 54 | |
101 | 105 | zname = dns.resolver.zone_for_name(name) |
102 | 106 | self.failUnlessRaises(dns.resolver.NotAbsolute, bad) |
103 | 107 | |
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 | ||
104 | 161 | class PollingMonkeyPatchMixin(object): |
105 | 162 | def setUp(self): |
106 | 163 | 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # 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. | |
1 | 1 | # |
2 | 2 | # Permission to use, copy, modify, and distribute this software and its |
3 | 3 | # documentation for any purpose with or without fee is hereby granted, |