Codebase list dnspython / ec833c1
Merge tag 'upstream/1.16.0' into debian/master Upstream version 1.16.0 Scott Kitterman 5 years ago
209 changed file(s) with 6596 addition(s) and 3910 deletion(s). Raw diff Collapse all Expand all
0 [run]
1 branch = True
2 source = dns
0 build
1 dist
2 MANIFEST
3 html
4 html.zip
5 html.tar.gz
6 tests/*.out
7 *.pyc
8 .coverage
9 .tox
10 dnspython.egg-info/
11 .eggs/
0 language: python
1 python:
2 - "2.7"
3 - "3.4"
4 - "3.5"
5 - "3.6"
6 #- "nightly"
7 matrix:
8 include:
9 - python: 3.7 # https://github.com/travis-ci/travis-ci/issues/9815
10 dist: xenial
11 sudo: true
12 allow_failures:
13 - python: nightly
14 branches:
15 except:
16 - python3
17 install:
18 - pip install typing pylint pycryptodome ecdsa idna
19 script:
20 - make typecheck
21 - make lint
22 - make test
+0
-1487
ChangeLog less more
0 2016-09-29 Bob Halley <halley@dnspython.org>
1
2 * IDNA 2008 support is now available if the "idna" module has been
3 installed and IDNA 2008 is requested. The default IDNA behavior
4 is still IDNA 2003. The new IDNA codec mechanism is currently
5 only useful for direct calls to dns.name.from_text() or
6 dns.name.from_unicode(), but in future releases it will be
7 deployed throughout dnspython, e.g. so that you can read a
8 masterfile with an IDNA 2008 codec in force.
9
10 * By default, dns.name.to_unicode() is not strict about which
11 version of IDNA the input complies with. Strictness can be
12 requested by using one of the strict IDNA codecs.
13
14 * Add AVC RR support.
15
16 * Some problems with newlines in various output modes have been
17 addressed.
18
19 * dns.name.to_text() now returns text and not bytes on Python 3.x
20
21 * More miscellaneous fixes for the Python 2/3 codeline merge.
22
23 2016-05-27 Bob Halley <halley@dnspython.org>
24
25 * (Version 1.14.0 released)
26
27 * Add CSYNC RR support
28
29 * Fix bug in LOC which destroyed N/S and E/W distinctions within
30 a degree of the equator or prime merdian respectively.
31
32 * Misc. fixes to deal with fallout from the Python 2 & 3 merge.
33 [issue #156], [issue #157], [issue #158], [issue #159],
34 [issue #160].
35
36 * Running with python optimization on caused issues when
37 stripped docstrings were referenced. [issue #154]
38
39 * dns.zone.from_text() erroneously required the zone to be provided.
40 [issue #153]
41
42 2016-05-13 Bob Halley <halley@dnspython.org>
43
44 * dns/message.py (make_query): Setting any value which implies
45 EDNS will turn on EDNS if 'use_edns' has not been specified.
46
47 2016-05-12 Bob Halley <halley@dnspython.org>
48
49 * TSIG signature algorithm setting was broken by the Python 2
50 and Python 3 code line merge. Fixed.
51
52 2016-05-10 Bob Halley <halley@dnspython.org>
53
54 * (Version 1.13.0 released)
55
56 2016-05-10 Bob Halley <halley@dnspython.org>
57
58 * Dropped support for Python 2.4 and 2.5.
59
60 * Zone origin can be specified as a string.
61
62 * Support string representation for all DNSExceptions.
63
64 * Use setuptools not distutils
65
66 * A number of Unicode name bug fixes.
67
68 * Added support for CAA, CDS, CDNSKEY, EUI48, EUI64, and URI RR
69 types.
70
71 * Names now support the pickle protocol.
72
73 * NameDicts now keep the max-depth value correct, and update
74 properly.
75
76 * resolv.conf processing rejects lines with too few tokens.
77
78 * Ports can be specified per-nameserver in the stub resolver.
79
80 2016-05-03 Arthur Gautier
81
82 * Single source support for python 2.6+ and 3.3+
83
84 2014-09-04 Bob Halley <halley@dnspython.org>
85
86 * Comparing two rdata is now always done by comparing the binary
87 data of the DNSSEC digestable forms. This corrects a number of
88 errors where dnspython's rdata comparison order was not the
89 DNSSEC order.
90
91 * Add CAA implementation. Thanks to Brian Wellington for the
92 patch.
93
94 2014-09-01 Bob Halley <halley@dnspython.org>
95
96 * (Version 1.12.0 released)
97
98 2014-08-31 Bob Halley <halley@dnspython.org>
99
100 * The test system can now run the tests without requiring dnspython
101 to be installed.
102
103 2014-07-24 Bob Halley <halley@dnspython.org>
104
105 * The 64-bit version of Python on Windows has sys.maxint set to
106 2^31-1, yet passes 2^63-1 as the "unspecified bound" value in
107 slices. This is a bug in Python as the documentation says the
108 unspecified bound value should be sys.maxint. We now cope with
109 this. Thanks to Matthäus Wander for reporting the problem.
110
111 2014-06-21 Bob Halley <halley@dnspython.org>
112
113 * When reading from a masterfile, if the first content line
114 started with leading whitespace, we raised an ugly exception
115 instead of doing the right thing, namely using the zone origin as
116 the name. [#73] Thanks to Tassatux for reporting the issue.
117
118 * Added dns.zone.to_text() convenience method. Thanks to Brandon
119 Whaley <redkrieg@gmail.com> for the patch.
120
121 * The /etc/resolv.conf setting "options rotate" is now understood
122 by the resolver. If present, the resolver will shuffle the
123 nameserver list each time dns.resolver.query() is called. Thanks
124 to underrun for the patch. Note that you don't want to add
125 "options rotate" to your /etc/resolv.conf if your system's
126 resolver library does not understand it. In this case, just set
127 resolver.rotate = True by hand.
128
129 2014-06-19 Bob Halley <halley@dnspython.org>
130
131 * Escaping of Unicode has been corrected. Previously we escaped
132 and then converted to Unicode, but the right thing to do is
133 convert to Unicode, then escape. Also, characters > 0x7f should
134 NOT be escaped in Unicode mode. Thanks to Martin Basti for the
135 patch.
136
137 * dns.rdtypes.ANY.DNSKEY now has helpers functions to convert
138 between the numeric form of the flags and a set of human-friendly
139 strings. Thanks to Petr Spacek for the patch.
140
141 * RRSIGs did not respect relativization settings in to_text().
142 Thanks to Brian Smith for reporting the bug and submitting a
143 (slightly different) patch.
144
145 2014-06-18 Bob Halley <halley@dnspython.org>
146
147 * dns/rdtypes/IN/APL.py: The APL from_wire() method did not accept an
148 rdata length of 0 as valid. Thanks to salzmdan for reporting the
149 problem.
150
151 2014-05-31 Bob Halley <halley@dnspython.org>
152
153 * dns/ipv6.py: Add is_mapped()
154
155 * dns/reversename.py: Lookup IPv6 mapped IPv4 addresses in the v4
156 reverse namespace. Thanks to Devin Bayer. Yes, I finally fixed
157 this one :)
158
159 2014-04-11 Bob Halley <halley@dnspython.org>
160
161 * dns/zone.py: Do not put back an unescaped token. This was
162 causing escape processing for domain names to break. Thanks to
163 connormclaud for reporting the problem.
164
165 2014-04-04 Bob Halley <halley@dnspython.org>
166
167 * dns/message.py: Making a response didn't work correctly if the
168 query was signed with TSIG and we knew the key. Thanks to Jeffrey
169 Stiles for reporting the problem.
170
171 2013-12-11 Bob Halley <halley@dnspython.org>
172
173 * dns/query.py: Fix problems with the IXFR state machine which caused
174 long diffs to fail. Thanks to James Raftery for the fix and the
175 repeated prodding to get it applied :)
176
177 2013-09-02 Bob Halley <halley@dnspython.org>
178
179 * (Version 1.11.1 released)
180
181 2013-09-01 Bob Halley <halley@dnspython.org>
182
183 * dns/tsigkeyring.py (to_text): we want keyname.to_text(), not
184 dns.name.to_text(keyname). Thangs to wangwang for the fix.
185
186 2013-08-26 Bob Halley <halley@dnspython.org>
187
188 * dns/tsig.py (sign): multi-message TSIGs were broken for
189 algorithms other than HMAC-MD5 because we weren't passing the
190 right digest module to the HMAC code. Thanks to salzmdan for
191 reporting the bug.
192
193 2013-08-09 Bob Halley <halley@dnspython.org>
194
195 * dns/dnssec.py (_find_candidate_keys): we tried to extract the
196 key from the wrong variable name. Thanks to Andrei Fokau for the
197 fix.
198
199 2013-07-08 Bob Halley <halley@dnspython.org>
200
201 * dns/resolver.py: we want 'self.retry_servfail' not just
202 retry_servfail. Reported by many, thanks! Thanks to
203 Jeffrey C. Ollie for the fix.
204
205 2013-07-08 Bob Halley <halley@dnspython.org>
206
207 * tests/grange.py: fix tests to use older-style print formatting
208 for backwards compatibility with python 2.4. Thanks to
209 Jeffrey C. Ollie for the fix.
210
211 2013-07-01 Bob Halley <halley@dnspython.org>
212
213 * (Version 1.11.0 released)
214
215 2013-04-28 Bob Halley <halley@dnspython.org>
216
217 * dns/name.py (Name.to_wire): Do not add items with offsets >= 2^14
218 to the compression table. Thanks to Casey Deccio for discovering
219 this bug.
220
221 2013-04-26 Bob Halley <halley@dnspython.org>
222
223 * dns/ipv6.py (inet_ntoa): We now comply with RFC 5952 section
224 5.2.2, by *not* using the :: syntax to shorten just one 16-bit
225 field. Thanks to David Waitzman for reporting the bug and
226 suggesting the fix.
227
228 2013-03-31 Bob Halley <halley@dnspython.org>
229
230 * lock caches in case they are shared
231
232 * raise YXDOMAIN if we see one
233
234 * do not print empty rdatasets
235
236 * Add contributed $GENERATE support (thanks uberj)
237
238 * Remove DNSKEY keytag uniqueness assumption (RFC 4034, section 8)
239 (thanks James Dempsey)
240
241 2012-09-25 Sean Leach
242
243 * added set_flags() method to dns.resolver.Resolver
244
245 2012-09-25 Pieter Lexis
246
247 * added support for TLSA RR
248
249 2012-08-28 Bob Halley <halley@dnspython.org>
250
251 * dns/rdtypes/ANY/NSEC3.py (NSEC3.from_text): The NSEC3 from_text()
252 method could erroneously emit empty bitmap windows (i.e. windows
253 with a count of 0 bytes); such bitmaps are illegal.
254
255 2012-04-08 Bob Halley <halley@dnspython.org>
256
257 * (Version 1.10.0 released)
258
259 2012-04-08 Bob Halley <halley@dnspython.org>
260
261 * dns/message.py (make_query): All EDNS values may now be
262 specified when calling make_query()
263
264 * dns/query.py: Specifying source_port had no effect if source was
265 not specified. We now use the appropriate wildcard source in
266 that case.
267
268 * dns/resolver.py (Resolver.query): source_port may now be
269 specified.
270
271 * dns/resolver.py (Resolver.query): Switch to TCP when a UDP
272 response is truncated. Handle nameservers that serve on UDP
273 but not TCP.
274
275 2012-04-07 Bob Halley <halley@dnspython.org>
276
277 * dns/zone.py (from_xfr): dns.zone.from_xfr() now takes a
278 'check_origin' parameter which defaults to True. If set to
279 False, then dnspython will not make origin checks on the zone.
280 Thanks to Carlos Perez for the report.
281
282 * dns/rdtypes/ANY/SSHFP.py (SSHFP.from_text): Allow whitespace in
283 the text string. Thanks to Jan Andres for the report and the
284 patch.
285
286 * dns/message.py (from_wire): dns.message.from_wire() now takes
287 an 'ignore_trailing' parameter which defaults to False. If set
288 to True, then trailing junk will be ignored instead of causing
289 TrailingJunk to be raised. Thanks to Shane Huntley for
290 contributing the patch.
291
292 2011-08-22 Bob Halley <halley@dnspython.org>
293
294 * dns/resolver.py: Added LRUCache. In this cache implementation,
295 the cache size is limited to a user-specified number of nodes, and
296 when adding a new node to a full cache the least-recently used
297 node is removed.
298
299 2011-07-13 Bob Halley <halley@dnspython.org>
300
301 * dns/resolver.py: dns.resolver.override_system_resolver()
302 overrides the socket module's versions of getaddrinfo(),
303 getnameinfo(), getfqdn(), gethostbyname(), gethostbyname_ex() and
304 gethostbyaddr() with an implementation which uses a dnspython stub
305 resolver instead of the system's stub resolver. This can be
306 useful in testing situations where you want to control the
307 resolution behavior of python code without having to change the
308 system's resolver settings (e.g. /etc/resolv.conf).
309 dns.resolver.restore_system_resolver() undoes the change.
310
311 2011-07-08 Bob Halley <halley@dnspython.org>
312
313 * dns/ipv4.py: dnspython now provides its own, stricter, versions
314 of IPv4 inet_ntoa() and inet_aton() instead of using the OS's
315 versions.
316
317 * dns/ipv6.py: inet_aton() now bounds checks embedded IPv4 addresses
318 more strictly. Also, now only dns.exception.SyntaxError can be
319 raised on bad input.
320
321 2011-04-05 Bob Halley <halley@dnspython.org>
322
323 * Old DNSSEC types (KEY, NXT, and SIG) have been removed.
324
325 * Bounds checking of slices in rdata wire processing is now more
326 strict, and bounds errors (e.g. we got less data than was
327 expected) now raise dns.exception.FormError rather than
328 IndexError.
329
330 2011-03-28 Bob Halley <halley@dnspython.org>
331
332 * (Version 1.9.4 released)
333
334 2011-03-24 Bob Halley <halley@dnspython.org>
335
336 * dns/rdata.py (Rdata._wire_cmp): We need to specify no
337 compression and an origin to _wire_cmp() in case names in the
338 rdata are relative names.
339
340 * dns/rdtypes/ANY/SIG.py (SIG._cmp): Add missing 'import struct'.
341 Thanks to Arfrever Frehtes Taifersar Arahesis for reporting the
342 problem.
343
344 2011-03-24 Bob Halley <halley@dnspython.org>
345
346 * (Version 1.9.3 released)
347
348 2011-03-22 Bob Halley <halley@dnspython.org>
349
350 * dns/resolver.py: a boolean parameter, 'raise_on_no_answer', has
351 been added to the query() methods. In no-error, no-data
352 situations, this parameter determines whether NoAnswer should be
353 raised or not. If True, NoAnswer is raised. If False, then an
354 Answer() object with a None rrset will be returned.
355
356 * dns/resolver.py: Answer() objects now have a canonical_name field.
357
358 2011-01-11 Bob Halley <halley@dnspython.org>
359
360 * Dnspython was erroneously doing case-insensitive comparisons
361 of the names in NSEC and RRSIG RRs. Thanks to Casey Deccio for
362 reporting this bug.
363
364 2010-12-17 Bob Halley <halley@dnspython.org>
365
366 * dns/message.py (_WireReader._get_section): use "is" and not "=="
367 when testing what section an RR is in. Thanks to James Raftery
368 for reporting this bug.
369
370 2010-12-10 Bob Halley <halley@dnspython.org>
371
372 * dns/resolver.py (Resolver.query): disallow metaqueries.
373
374 * dns/rdata.py (Rdata.__hash__): Added a __hash__ method for rdata.
375
376 2010-11-23 Bob Halley <halley@dnspython.org>
377
378 * (Version 1.9.2 released)
379
380 2010-11-23 Bob Halley <halley@dnspython.org>
381
382 * dns/dnssec.py (_need_pycrypto): DSA and RSA are modules, not
383 functions, and I didn't notice because the test suite masked
384 the bug! *sigh*
385
386 2010-11-22 Bob Halley <halley@dnspython.org>
387
388 * (Version 1.9.1 released)
389
390 2010-11-22 Bob Halley <halley@dnspython.org>
391
392 * dns/dnssec.py: the "from" style import used to get DSA from
393 PyCrypto trashed a DSA constant. Now a normal import is used
394 to avoid namespace contamination.
395
396 2010-11-20 Bob Halley <halley@dnspython.org>
397
398 * (Version 1.9.0 released)
399
400 2010-11-07 Bob Halley <halley@dnspython.org>
401
402 * dns/dnssec.py: Added validate() to do basic DNSSEC validation
403 (requires PyCrypto). Thanks to Brian Wellington for the patch.
404
405 * dns/hash.py: Hash compatibility handling is now its own module.
406
407 2010-10-31 Bob Halley <halley@dnspython.org>
408
409 * dns/resolver.py (zone_for_name): A query name resulting in a
410 CNAME or DNAME response to a node which had an SOA was incorrectly
411 treated as a zone origin. In these cases, we should just look
412 higher. Thanks to Gert Berger for reporting this problem.
413
414 * Added zonediff.py to examples. This program compares two zones
415 and shows the differences either in diff-like plain text, or
416 HTML. Thanks to Dennis Kaarsemaker for contributing this
417 useful program.
418
419 2010-10-27 Bob Halley <halley@dnspython.org>
420
421 * Incorporate a patch to use poll() instead of select() by
422 default on platforms which support it. Thanks to
423 Peter Schüller and Spotify for the contribution.
424
425 2010-10-17 Bob Halley <halley@dnspython.org>
426
427 * Python prior to 2.5.2 doesn't compute the correct values for
428 HMAC-SHA384 and HMAC-SHA512. We now detect attempts to use
429 them and raise NotImplemented if the Python version is too old.
430 Thanks to Kevin Chen for reporting the problem.
431
432 * Various routines that took the string forms of rdata types and
433 classes did not permit the strings to be Unicode strings.
434 Thanks to Ryan Workman for reporting the issue.
435
436 * dns/tsig.py: Added symbolic constants for the algorithm strings.
437 E.g. you can now say dns.tsig.HMAC_MD5 instead of
438 "HMAC-MD5.SIG-ALG.REG.INT". Thanks to Cillian Sharkey for
439 suggesting this improvement.
440
441 * dns/tsig.py (get_algorithm): fix hashlib compatibility; thanks to
442 Kevin Chen for the patch.
443
444 * dns/dnssec.py: Added key_id() and make_ds().
445
446 * dns/message.py: message.py needs to import dns.edns since it uses
447 it.
448
449 2010-05-04 Bob Halley <halley@dnspython.org>
450
451 * dns/rrset.py (RRset.__init__): "covers" was not passed to the
452 superclass __init__(). Thanks to Shanmuga Rajan for reporting
453 the problem.
454
455 2010-03-10 Bob Halley <halley@dnspython.org>
456
457 * The TSIG algorithm value was passed to use_tsig() incorrectly
458 in some cases. Thanks to 'ducciovigolo' for reporting the problem.
459
460 2010-01-26 Bob Halley <halley@dnspython.org>
461
462 * (Version 1.8.0 released)
463
464 2010-01-13 Bob Halley <halley@dnspython.org>
465
466 * dns/dnssec.py: Added RSASHA256 and RSASHA512 codepoints; added
467 other missing codepoints to _algorithm_by_text.
468
469 2010-01-12 Bob Halley <halley@dnspython.org>
470
471 * Escapes in masterfiles now work correctly. Previously they were
472 only working correctly when the text involved was part of a domain
473 name.
474
475 * dns/tokenizer.py: The tokenizer's get() method now returns Token
476 objects, not (type, text) tuples.
477
478 2009-11-13 Bob Halley <halley@dnspython.org>
479
480 * Support has been added for hmac-sha1, hmac-sha224, hmac-sha256,
481 hmac-sha384 and hmac-sha512. Thanks to Kevin Chen for a
482 thoughtful, high quality patch.
483
484 * dns/update.py (Update::present): A zero TTL was not added if
485 present() was called with a single rdata, causing _add() to be
486 unhappy. Thanks to Eugene Kim for reporting the problem and
487 submitting a patch.
488
489 * dns/entropy.py: Use os.urandom() if present. Don't seed until
490 someone wants randomness.
491
492 2009-09-16 Bob Halley <halley@dnspython.org>
493
494 * dns/entropy.py: The entropy module needs locking in order to be
495 used safely in a multithreaded environment. Thanks to Beda Kosata
496 for reporting the problem.
497
498 2009-07-27 Bob Halley <halley@dnspython.org>
499
500 * dns/query.py (xfr): The socket was not set to nonblocking mode.
501 Thanks to Erik Romijn for reporting this problem.
502
503 2009-07-23 Bob Halley <halley@dnspython.org>
504
505 * dns/rdtypes/IN/SRV.py (SRV._cmp): SRV records were compared
506 incorrectly due to a cut-and-paste error. Thanks to Tommie
507 Gannert for reporting this bug.
508
509 * dns/e164.py (query): The resolver parameter was not used.
510 Thanks to Matías Bellone for reporting this bug.
511
512 2009-06-23 Bob Halley <halley@dnspython.org>
513
514 * dns/entropy.py (EntropyPool.__init__): open /dev/random unbuffered;
515 there's no need to consume more randomness than we need. Thanks
516 to Brian Wellington for the patch.
517
518 2009-06-19 Bob Halley <halley@dnspython.org>
519
520 * (Version 1.7.1 released)
521
522 2009-06-19 Bob Halley <halley@dnspython.org>
523
524 * DLV.py was omitted from the kit
525
526 * Negative prerequisites were not handled correctly in _get_section().
527
528 2009-06-19 Bob Halley <halley@dnspython.org>
529
530 * (Version 1.7.0 released)
531
532 2009-06-19 Bob Halley <halley@dnspython.org>
533
534 * On Windows, the resolver set the domain incorrectly. Thanks
535 to Brandon Carpenter for reporting this bug.
536
537 * Added a to_digestable() method to rdata classes; it returns the
538 digestable form (i.e. DNSSEC canonical form) of the rdata. For
539 most rdata types this is the same uncompressed wire form. For
540 certain older DNS RR types, however, domain names in the rdata
541 are downcased.
542
543 * Added support for the HIP RR type.
544
545 2009-06-18 Bob Halley <halley@dnspython.org>
546
547 * Added support for the DLV RR type.
548
549 * Added various DNSSEC related constants (e.g. algorithm identifiers,
550 flag values).
551
552 * dns/tsig.py: Added support for BADTRUNC result code.
553
554 * dns/query.py (udp): When checking that addresses are the same,
555 use the binary form of the address in the comparison. This
556 ensures that we don't treat addresses as different if they have
557 equivalent but differing textual representations. E.g. "1:00::1"
558 and "1::1" represent the same address but are not textually equal.
559 Thanks to Kim Davies for reporting this bug.
560
561 * The resolver's query() method now has an optional 'source' parameter,
562 allowing the source IP address to be specified. Thanks to
563 Alexander Lind for suggesting the change and sending a patch.
564
565 * Added NSEC3 and NSEC3PARAM support.
566
567 2009-06-17 Bob Halley <halley@dnspython.org>
568
569 * Fixed NSEC.to_text(), which was only printing the last window.
570 Thanks to Brian Wellington for finding the problem and fixing it.
571
572 2009-03-30 Bob Halley <halley@dnspython.org>
573
574 * dns/query.py (xfr): Allow UDP IXFRs. Use "one_rr_per_rrset" mode when
575 doing IXFR.
576
577 2009-03-30 Bob Halley <halley@dnspython.org>
578
579 * Add "one_rr_per_rrset" mode switch to methods which parse
580 messages from wire format (e.g. dns.message.from_wire(),
581 dns.query.udp(), dns.query.tcp()). If set, each RR read is
582 placed in its own RRset (instead of being coalesced).
583
584 2009-03-30 Bob Halley <halley@dnspython.org>
585
586 * Added EDNS option support.
587
588 2008-10-16 Bob Halley <halley@dnspython.org>
589
590 * dns/rdtypes/ANY/DS.py: The from_text() parser for DS RRs did not
591 allow multiple Base64 chunks. Thanks to Rakesh Banka for
592 finding this bug and submitting a patch.
593
594 2008-10-08 Bob Halley <halley@dnspython.org>
595
596 * Add entropy module.
597
598 * When validating TSIGs, we need to use the absolute name.
599
600 2008-06-03 Bob Halley <halley@dnspython.org>
601
602 * dns/message.py (Message.set_rcode): The mask used preserved the
603 extended rcode, instead of everything else in ednsflags.
604
605 * dns/message.py (Message.use_edns): ednsflags was not kept
606 coherent with the specified edns version.
607
608 2008-02-06 Bob Halley <halley@dnspython.org>
609
610 * dns/ipv6.py (inet_aton): We could raise an exception other than
611 dns.exception.SyntaxError in some cases.
612
613 * dns/tsig.py: Raise an exception when the peer has set a non-zero
614 TSIG error.
615
616 2007-11-25 Bob Halley <halley@dnspython.org>
617
618 * (Version 1.6.0 released)
619
620 2007-11-25 Bob Halley <halley@dnspython.org>
621
622 * dns/query.py (_wait_for): if select() raises an exception due to
623 EINTR, we should just select() again.
624
625 2007-06-13 Bob Halley <halley@dnspython.org>
626
627 * dns/inet.py: Added is_multicast().
628
629 * dns/query.py (udp): If the queried address is a multicast address, then
630 don't check that the address of the response is the same as the address
631 queried.
632
633 2007-05-24 Bob Halley <halley@dnspython.org>
634
635 * dns/rdtypes/IN/NAPTR.py: NAPTR comparisons didn't compare the
636 preference field due to a typo.
637
638 2007-02-07 Bob Halley <halley@dnspython.org>
639
640 * dns/resolver.py: Integrate code submitted by Paul Marks to
641 determine whether a Windows NIC is enabled. The way dnspython
642 used to do this does not work on Windows Vista.
643
644 2006-12-10 Bob Halley <halley@dnspython.org>
645
646 * (Version 1.5.0 released)
647
648 2006-11-03 Bob Halley <halley@dnspython.org>
649
650 * dns/rdtypes/IN/DHCID.py: Added support for the DHCID RR type.
651
652 2006-11-02 Bob Halley <halley@dnspython.org>
653
654 * dns/query.py (udp): Messages from unexpected sources can now be
655 ignored by setting ignore_unexpected to True.
656
657 2006-10-31 Bob Halley <halley@dnspython.org>
658
659 * dns/query.py (udp): When raising UnexpectedSource, add more
660 detail about what went wrong to the exception.
661
662 2006-09-22 Bob Halley <halley@dnspython.org>
663
664 * dns/message.py (Message.use_edns): add reasonable defaults for
665 the ednsflags, payload, and request_payload parameters.
666
667 * dns/message.py (Message.want_dnssec): add a convenience method for
668 enabling/disabling the "DNSSEC desired" flag in requests.
669
670 * dns/message.py (make_query): add "use_edns" and "want_dnssec"
671 parameters.
672
673 2006-08-17 Bob Halley <halley@dnspython.org>
674
675 * dns/resolver.py (Resolver.read_resolv_conf): If /etc/resolv.conf
676 doesn't exist, just use the default resolver configuration (i.e.
677 the same thing we would have used if resolv.conf had existed and
678 been empty).
679
680 2006-07-26 Bob Halley <halley@dnspython.org>
681
682 * dns/resolver.py (Resolver._config_win32_fromkey): fix
683 cut-and-paste error where we passed the wrong variable to
684 self._config_win32_search(). Thanks to David Arnold for finding
685 the bug and submitting a patch.
686
687 2006-07-20 Bob Halley <halley@dnspython.org>
688
689 * dns/resolver.py (Answer): Add more support for the sequence
690 protocol, forwarding requests to the answer object's rrset.
691 E.g. "for a in answer" is equivalent to "for a in answer.rrset",
692 "answer[i]" is equivalent to "answer.rrset[i]", and
693 "answer[i:j]" is equivalent to "answer.rrset[i:j]".
694
695 2006-07-19 Bob Halley <halley@dnspython.org>
696
697 * dns/query.py (xfr): Add IXFR support.
698
699 2006-06-22 Bob Halley <halley@dnspython.org>
700
701 * dns/rdtypes/IN/IPSECKEY.py: Added support for the IPSECKEY RR type.
702
703 2006-06-21 Bob Halley <halley@dnspython.org>
704
705 * dns/rdtypes/ANY/SPF.py: Added support for the SPF RR type.
706
707 2006-06-02 Bob Halley <halley@dnspython.org>
708
709 * (Version 1.4.0 released)
710
711 2006-04-25 Bob Halley <halley@dnspython.org>
712
713 * dns/rrset.py (RRset.to_rdataset): Added a convenience method
714 to convert an rrset into an rdataset.
715
716 2006-03-27 Bob Halley <halley@dnspython.org>
717
718 * Added dns.e164.query(). This function can be used to look for
719 NAPTR RRs for a specified number in several domains, e.g.:
720
721 dns.e164.query('16505551212',
722 ['e164.dnspython.org.', 'e164.arpa.'])
723
724 2006-03-26 Bob Halley <halley@dnspython.org>
725
726 * dns/resolver.py (Resolver.query): The resolver deleted from
727 a list while iterating it, which makes the iterator unhappy.
728
729 2006-03-17 Bob Halley <halley@dnspython.org>
730
731 * dns/resolver.py (Resolver.query): The resolver needlessly
732 delayed responses for successful queries.
733
734 2006-01-18 Bob Halley <halley@dnspython.org>
735
736 * dns/rdata.py: added a validate() method to the rdata class. If
737 you change an rdata by assigning to its fields, it is a good
738 idea to call validate() when you are done making changes.
739 For example, if 'r' is an MX record and then you execute:
740
741 r.preference = 100000 # invalid, because > 65535
742 r.validate()
743
744 The validation will fail and an exception will be raised.
745
746 2006-01-11 Bob Halley <halley@dnspython.org>
747
748 * dns/ttl.py: TTLs are now bounds checked to be within the closed
749 interval [0, 2^31 - 1].
750
751 * The BIND 8 TTL syntax is now accepted in the SOA refresh, retry,
752 expire, and minimum fields, and in the original_ttl field of
753 SIG and RRSIG records.
754
755 2006-01-04 Bob Halley <halley@dnspython.org>
756
757 * dns/resolver.py: The windows registry irritatingly changes the
758 list element delimiter in between ' ' and ',' (and vice-versa)
759 in various versions of windows. We now cope by always looking
760 for either one (' ' first).
761
762 2005-12-27 Bob Halley <halley@dnspython.org>
763
764 * dns/e164.py: Added routines to convert between E.164 numbers and
765 their ENUM domain name equivalents.
766
767 * dns/reversename.py: Added routines to convert between IPv4 and
768 IPv6 addresses and their DNS reverse-map equivalents.
769
770 2005-12-18 Bob Halley <halley@dnspython.org>
771
772 * dns/rdtypes/ANY/LOC.py (_tuple_to_float): The sign was lost when
773 converting a tuple into a float, which broke conversions of
774 south latitudes and west longitudes.
775
776 2005-11-17 Bob Halley <halley@dnspython.org>
777
778 * dns/zone.py: The 'origin' parameter to from_text() and from_file()
779 is now optional. If not specified, dnspython will use the
780 first $ORIGIN in the text as the zone's origin.
781
782 * dns/zone.py: Sanity checks of the zone's origin node can now
783 be disabled.
784
785 2005-11-12 Bob Halley <halley@dnspython.org>
786
787 * dns/name.py: Preliminary Unicode support has been added for
788 domain names. Running dns.name.from_text() on a Unicode string
789 will now encode each label using the IDN ACE encoding. The
790 to_unicode() method may be used to convert a dns.name.Name with
791 IDN ACE labels back into a Unicode string. This functionality
792 requires Python 2.3 or greater.
793
794 2005-10-31 Bob Halley <halley@dnspython.org>
795
796 * (Version 1.3.5 released)
797
798 2005-10-12 Bob Halley <halley@dnspython.org>
799
800 * dns/zone.py: Zone.iterate_rdatasets() and Zone.iterate_rdatas()
801 did not have a default rdtype of dns.rdatatype.ANY as their
802 docstrings said they did. They do now.
803
804 2005-10-06 Bob Halley <halley@dnspython.org>
805
806 * dns/name.py: Added the parent() method, which returns the
807 parent of a name.
808
809 2005-10-01 Bob Halley <halley@dnspython.org>
810
811 * dns/resolver.py: Added zone_for_name() helper, which returns
812 the name of the zone which contains the specified name.
813
814 * dns/resolver.py: Added get_default_resolver(), which returns
815 the default resolver, initializing it if necessary.
816
817 2005-09-29 Bob Halley <halley@dnspython.org>
818
819 * dns/resolver.py (Resolver._compute_timeout): If time goes
820 backwards a little bit, ignore it.
821
822 2005-07-31 Bob Halley <halley@dnspython.org>
823
824 * (Version 1.3.4 released)
825
826 2005-07-31 Bob Halley <halley@dnspython.org>
827
828 * dns/message.py (make_response): Trying to respond to a response
829 threw a NameError while trying to throw a FormErr since it used
830 the wrong name for the FormErr exception.
831
832 * dns/query.py (_connect): We needed to ignore EALREADY too.
833
834 * dns/query.py: Optional "source" and "source_port" parameters
835 have been added to udp(), tcp(), and xfr(). Thanks to Ralf
836 Weber for suggesting the change and providing a patch.
837
838 2005-06-05 Bob Halley <halley@dnspython.org>
839
840 * dns/query.py: The requirement that the "where" parameter be
841 an IPv4 or IPv6 address is now documented.
842
843 2005-06-04 Bob Halley <halley@dnspython.org>
844
845 * dns/resolver.py: The resolver now does exponential backoff
846 each time it runs through all of the nameservers.
847
848 * dns/resolver.py: rcodes which indicate a nameserver is likely
849 to be a "permanent failure" for a query cause the nameserver
850 to be removed from the mix for that query.
851
852 2005-01-30 Bob Halley <halley@dnspython.org>
853
854 * (Version 1.3.3 released)
855
856 2004-10-25 Bob Halley <halley@dnspython.org>
857
858 * dns/rdtypes/ANY/TXT.py (TXT.from_text): The masterfile parser
859 incorrectly rejected TXT records where a value was not quoted.
860
861 2004-10-11 Bob Halley <halley@dnspython.org>
862
863 * dns/message.py: Added make_response(), which creates a skeletal
864 response for the specified query. Added opcode() and set_opcode()
865 convenience methods to the Message class. Added the request_payload
866 attribute to the Message class.
867
868 2004-10-10 Bob Halley <halley@dnspython.org>
869
870 * dns/zone.py (from_xfr): dns.zone.from_xfr() in relativization
871 mode incorrectly set zone.origin to the empty name.
872
873 2004-09-02 Bob Halley <halley@dnspython.org>
874
875 * dns/name.py (Name.to_wire): The 'file' parameter to
876 Name.to_wire() is now optional; if omitted, the wire form will
877 be returned as the value of the function.
878
879 2004-08-14 Bob Halley <halley@dnspython.org>
880
881 * dns/message.py (Message.find_rrset): find_rrset() now uses an
882 index, vastly improving the from_wire() performance of large
883 messages such as zone transfers.
884
885 2004-08-07 Bob Halley <halley@dnspython.org>
886
887 * (Version 1.3.2 released)
888
889 2004-08-04 Bob Halley <halley@dnspython.org>
890
891 * dns/query.py: sending queries to a nameserver via IPv6 now
892 works.
893
894 * dns/inet.py (af_for_address): Add af_for_address(), which looks
895 at a textual-form address and attempts to determine which address
896 family it is.
897
898 * dns/query.py: the default for the 'af' parameter of the udp(),
899 tcp(), and xfr() functions has been changed from AF_INET to None,
900 which causes dns.inet.af_for_address() to be used to determine the
901 address family. If dns.inet.af_for_address() can't figure it out,
902 we fall back to AF_INET and hope for the best.
903
904 2004-07-31 Bob Halley <halley@dnspython.org>
905
906 * dns/rdtypes/ANY/NSEC.py (NSEC.from_text): The NSEC text format
907 does not allow specifying types by number, so we shouldn't either.
908
909 * dns/renderer.py: the renderer module didn't import random,
910 causing an exception to be raised if a query id wasn't provided
911 when a Renderer was created.
912
913 * dns/resolver.py (Resolver.query): the resolver wasn't catching
914 dns.exception.Timeout, so a timeout erroneously caused the whole
915 resolution to fail instead of just going on to the next server.
916
917 2004-06-16 Bob Halley <halley@dnspython.org>
918
919 * dns/rdtypes/ANY/LOC.py (LOC.from_text): LOC milliseconds values
920 were converted incorrectly if the length of the milliseconds
921 string was less than 3.
922
923 2004-06-06 Bob Halley <halley@dnspython.org>
924
925 * (Version 1.3.1 released)
926
927 2004-05-22 Bob Halley <halley@dnspython.org>
928
929 * dns/update.py (Update.delete): We erroneously specified a
930 "deleting" value of dns.rdatatype.NONE instead of
931 dns.rdataclass.NONE when the thing being deleted was either an
932 Rdataset instance or an Rdata instance.
933
934 * dns/rdtypes/ANY/SSHFP.py: Added support for the proposed SSHFP
935 RR type.
936
937 2004-05-14 Bob Halley <halley@dnspython.org>
938
939 * dns/rdata.py (from_text): The masterfile reader did not
940 accept the unknown RR syntax when used with a known RR type.
941
942 2004-05-08 Bob Halley <halley@dnspython.org>
943
944 * dns/name.py (from_text): dns.name.from_text() did not raise
945 an exception if a backslash escape ended prematurely.
946
947 2004-04-09 Bob Halley <halley@dnspython.org>
948
949 * dns/zone.py (_MasterReader._rr_line): The masterfile reader
950 erroneously treated lines starting with leading whitespace but
951 not having any RR definition as an error. It now treats
952 them like a blank line (which is not an error).
953
954 2004-04-01 Bob Halley <halley@dnspython.org>
955
956 * (Version 1.3.0 released)
957
958 2004-03-19 Bob Halley <halley@dnspython.org>
959
960 * Added support for new DNSSEC types RRSIG, NSEC, and DNSKEY.
961
962 2004-01-16 Bob Halley <halley@dnspython.org>
963
964 * dns/query.py (_connect): Windows returns EWOULDBLOCK instead
965 of EINPROGRESS when trying to connect a nonblocking socket.
966
967 2003-11-13 Bob Halley <halley@dnspython.org>
968
969 * dns/rdtypes/ANY/LOC.py (LOC.to_wire): We encoded and decoded LOC
970 incorrectly, since we were interpreting the values of altitude,
971 size, hprec, and vprec in meters instead of centimeters.
972
973 * dns/rdtypes/IN/WKS.py (WKS.from_wire): The WKS protocol value is
974 encoded with just one octet, not two!
975
976 2003-11-09 Bob Halley <halley@dnspython.org>
977
978 * dns/resolver.py (Cache.maybe_clean): The cleaner deleted items
979 from the dictionary while iterating it, causing a RuntimeError
980 to be raised. Thanks to Mark R. Levinson for the bug report,
981 regression test, and fix.
982
983 2003-11-07 Bob Halley <halley@dnspython.org>
984
985 * (Version 1.2.0 released)
986
987 2003-11-03 Bob Halley <halley@dnspython.org>
988
989 * dns/zone.py (_MasterReader.read): The saved_state now includes
990 the default TTL.
991
992 2003-11-01 Bob Halley <halley@dnspython.org>
993
994 * dns/tokenizer.py (Tokenizer.get): The tokenizer didn't
995 handle escaped delimiters.
996
997 2003-10-27 Bob Halley <halley@dnspython.org>
998
999 * dns/resolver.py (Resolver.read_resolv_conf): If no nameservers
1000 are configured in /etc/resolv.conf, the default nameserver
1001 list should be ['127.0.0.1'].
1002
1003 2003-09-08 Bob Halley <halley@dnspython.org>
1004
1005 * dns/resolver.py (Resolver._config_win32_fromkey): We didn't
1006 catch WindowsError, which can happen if a key is not defined
1007 in the registry.
1008
1009 2003-09-06 Bob Halley <halley@dnspython.org>
1010
1011 * (Version 1.2.0b1 released)
1012
1013 2003-09-05 Bob Halley <halley@dnspython.org>
1014
1015 * dns/query.py: Timeout support has been overhauled to provide
1016 timeouts under Python 2.2 as well as 2.3, and to provide more
1017 accurate expiration.
1018
1019 2003-08-30 Bob Halley <halley@dnspython.org>
1020
1021 * dns/zone.py: dns.exception.SyntaxError is raised for unknown
1022 master file directives.
1023
1024 2003-08-28 Bob Halley <halley@dnspython.org>
1025
1026 * dns/zone.py: $INCLUDE processing is now enabled/disabled using
1027 the allow_include parameter. The default is to process $INCLUDE
1028 for from_file(), and to disallow $INCLUDE for from_text(). The
1029 master reader now calls zone.check_origin_node() by default after
1030 the zone has been read. find_rdataset() called get_node() instead
1031 of find_node(), which result in an incorrect exception. The
1032 relativization state of a zone is now remembered and applied
1033 consistently when looking up names. from_xfr() now supports
1034 relativization like the _MasterReader.
1035
1036 2003-08-22 Bob Halley <halley@dnspython.org>
1037
1038 * dns/zone.py: The _MasterReader now understands $INCLUDE.
1039
1040 2003-08-12 Bob Halley <halley@dnspython.org>
1041
1042 * dns/zone.py: The _MasterReader now specifies the file and line
1043 number when a syntax error occurs. The BIND 8 TTL format is now
1044 understood when loading a zone, though it will never be emitted.
1045 The from_file() function didn't pass the zone_factory parameter
1046 to from_text().
1047
1048 2003-08-10 Bob Halley <halley@dnspython.org>
1049
1050 * (Version 1.1.0 released)
1051
1052 2003-08-07 Bob Halley <halley@dnspython.org>
1053
1054 * dns/update.py (Update._add): A typo meant that _add would
1055 fail if the thing being added was an Rdata object (as
1056 opposed to an Rdataset or the textual form of an Rdata).
1057
1058 2003-08-05 Bob Halley <halley@dnspython.org>
1059
1060 * dns/set.py: the simple Set class has been moved to its
1061 own module, and augmented to support more set operations.
1062
1063 2003-08-04 Bob Halley <halley@dnspython.org>
1064
1065 * Node and all rdata types have been "slotted". This speeds
1066 things up a little and reduces memory usage noticeably.
1067
1068 2003-08-02 Bob Halley <halley@dnspython.org>
1069
1070 * (Version 1.1.0c1 released)
1071
1072 2003-08-02 Bob Halley <halley@dnspython.org>
1073
1074 * dns/rdataset.py: SimpleSets now support more set options.
1075
1076 * dns/message.py: Added the get_rrset() method. from_file() now
1077 allows Unicode filenames and turns on universal newline support if
1078 it opens the file itself.
1079
1080 * dns/node.py: Added the delete_rdataset() and replace_rdataset()
1081 methods.
1082
1083 * dns/zone.py: Added the delete_node(), delete_rdataset(), and
1084 replace_rdataset() methods. from_file() now allows Unicode
1085 filenames and turns on universal newline support if it opens the
1086 file itself. Added a to_file() method.
1087
1088 2003-08-01 Bob Halley <halley@dnspython.org>
1089
1090 * dns/opcode.py: Opcode from/to text converters now understand
1091 numeric opcodes. The to_text() method will return a numeric opcode
1092 string if it doesn't know a text name for the opcode.
1093
1094 * dns/message.py: Added set_rcode(). Fixed code where ednsflags
1095 wasn't treated as a long.
1096
1097 * dns/rcode.py: ednsflags wasn't treated as a long. Rcode from/to
1098 text converters now understand numeric rcodes. The to_text()
1099 method will return a numeric rcode string if it doesn't know
1100 a text name for the rcode.
1101
1102 * examples/reverse.py: Added a new example program that builds a
1103 reverse (address-to-name) mapping table from the name-to-address
1104 mapping specified by A RRs in zone files.
1105
1106 * dns/node.py: Added get_rdataset() method.
1107
1108 * dns/zone.py: Added get_rdataset() and get_rrset() methods. Added
1109 iterate_rdatas().
1110
1111 2003-07-31 Bob Halley <halley@dnspython.org>
1112
1113 * dns/zone.py: Added the iterate_rdatasets() method which returns
1114 a generator which yields (name, rdataset) tuples for all the
1115 rdatasets in the zone matching the specified rdatatype.
1116
1117 2003-07-30 Bob Halley <halley@dnspython.org>
1118
1119 * (Version 1.1.0b2 released)
1120
1121 2003-07-30 Bob Halley <halley@dnspython.org>
1122
1123 * dns/zone.py: Added find_rrset() and find_rdataset() convenience
1124 methods. They let you retrieve rdata with the specified name
1125 and type in one call.
1126
1127 * dns/node.py: Nodes no longer have names; owner names are
1128 associated with nodes in the Zone object's nodes dictionary.
1129
1130 * dns/zone.py: Zone objects now implement more of the standard
1131 mapping interface. __iter__ has been changed to iterate the keys
1132 rather than values to match the standard mapping interface's
1133 behavior.
1134
1135 2003-07-20 Bob Halley <halley@dnspython.org>
1136
1137 * dns/ipv6.py (inet_ntoa): Handle embedded IPv4 addresses.
1138
1139 2003-07-19 Bob Halley <halley@dnspython.org>
1140
1141 * (Version 1.1.0b1 released)
1142
1143 2003-07-18 Bob Halley <halley@dnspython.org>
1144
1145 * dns/tsig.py: The TSIG validation of TCP streams where not
1146 every message is signed now works correctly.
1147
1148 * dns/zone.py: Zones can now be compared for equality and
1149 inequality. If the other object in the comparison is also
1150 a zone, then "the right thing" happens; i.e. the zones are
1151 equal iff.: they have the same rdclass, origin, and nodes.
1152
1153 2003-07-17 Bob Halley <halley@dnspython.org>
1154
1155 * dns/message.py (Message.use_tsig): The method now allows for
1156 greater control over the various fields in the generated signature
1157 (e.g. fudge).
1158 (_WireReader._get_section): UnknownTSIGKey is now raised if an
1159 unknown key is encountered, or if a signed message has no keyring.
1160
1161 2003-07-16 Bob Halley <halley@dnspython.org>
1162
1163 * dns/tokenizer.py (Tokenizer._get_char): get_char and unget_char
1164 have been renamed to _get_char and _unget_char since they are not
1165 useful to clients of the tokenizer.
1166
1167 2003-07-15 Bob Halley <halley@dnspython.org>
1168
1169 * dns/zone.py (_MasterReader._rr_line): owner names were being
1170 unconditionally relativized; it makes much more sense for them
1171 to be relativized according to the relativization setting of
1172 the reader.
1173
1174 2003-07-12 Bob Halley <halley@dnspython.org>
1175
1176 * dns/resolver.py (Resolver.read_resolv_conf): The resolv.conf
1177 parser did not allow blank / whitespace-only lines, nor did it
1178 allow comments. Both are now supported.
1179
1180 2003-07-11 Bob Halley <halley@dnspython.org>
1181
1182 * dns/name.py (Name.to_digestable): to_digestable() now
1183 requires an origin to be specified if the name is relative.
1184 It will raise NeedAbsoluteNameOrOrigin if the name is
1185 relative and there is either no origin or the origin is
1186 itself relative.
1187 (Name.split): returned the wrong answer if depth was 0 or depth
1188 was the length of the name. split() now does bounds checking
1189 on depth, and raises ValueError if depth < 0 or depth > the length
1190 of the name.
1191
1192 2003-07-10 Bob Halley <halley@dnspython.org>
1193
1194 * dns/ipv6.py (inet_ntoa): The routine now minimizes its output
1195 strings. E.g. the IPv6 address
1196 "0000:0000:0000:0000:0000:0000:0000:0001" is minimized to "::1".
1197 We do not, however, make any effort to display embedded IPv4
1198 addresses in the dot-quad notation.
1199
1200 2003-07-09 Bob Halley <halley@dnspython.org>
1201
1202 * dns/inet.py: We now supply our own AF_INET and AF_INET6
1203 constants since AF_INET6 may not always be available. If the
1204 socket module has AF_INET6, we will use it. If not, we will
1205 use our own value for the constant.
1206
1207 * dns/query.py: the functions now take an optional af argument
1208 specifying the address family to use when creating the socket.
1209
1210 * dns/rdatatype.py (is_metatype): a typo caused the function
1211 return true only for type OPT.
1212
1213 * dns/message.py: message section list elements are now RRsets
1214 instead of Nodes. This API change makes processing messages
1215 easier for many applications.
1216
1217 2003-07-07 Bob Halley <halley@dnspython.org>
1218
1219 * dns/rrset.py: added. An RRset is a named rdataset.
1220
1221 * dns/rdataset.py (Rdataset.__eq__): rdatasets may now be compared
1222 for equality and inequality with other objects. Rdataset instance
1223 variables are now slotted.
1224
1225 * dns/message.py: The wire format and text format readers are now
1226 classes. Variables related to reader state have been moved out
1227 of the message class.
1228
1229 2003-07-06 Bob Halley <halley@dnspython.org>
1230
1231 * dns/name.py (from_text): '@' was not interpreted as the empty
1232 name.
1233
1234 * dns/zone.py: the master file reader derelativized names in rdata
1235 relative to the zone's origin, not relative to the current origin.
1236 The reader now deals with relativization in two steps. The rdata
1237 is read and derelativized using the current origin. The rdata's
1238 relativity is then chosen using the zone origin and the relativize
1239 boolean. Here's an example.
1240
1241 $ORIGIN foo.example.
1242 $TTL 300
1243 bar MX 0 blaz
1244
1245 If the zone origin is example., and relativization is on, then
1246 This fragment will become:
1247
1248 bar.foo.example. 300 IN MX 0 blaz.foo.example.
1249
1250 after the first step (derelativization to current origin), and
1251
1252 bar.foo 300 IN MX 0 blaz.foo
1253
1254 after the second step (relativization to zone origin).
1255
1256 * dns/namedict.py: added.
1257
1258 * dns/zone.py: The master file reader has been made into its
1259 own class. Reader-related instance variables have been moved
1260 form the zone class into the reader class.
1261
1262 * dns/zone.py: Add node_factory class attribute. An application
1263 can now subclass Zone and Node and have a zone whose nodes are of
1264 the subclassed Node type. The from_text(), from_file(), and
1265 from_xfr() algorithms now take an optional zone_factory argument.
1266 This allows the algorithms to be used to create zones whose class
1267 is a subclass of Zone.
1268
1269
1270 2003-07-04 Bob Halley <halley@dnspython.org>
1271
1272 * dns/renderer.py: added new wire format rendering module and
1273 converted message.py to use it. Applications which want
1274 fine-grained control over the conversion to wire format may call
1275 the renderer directly, instead of having it called on their behalf
1276 by the message code.
1277
1278 2003-07-02 Bob Halley <halley@dnspython.org>
1279
1280 * dns/name.py (_validate_labels): The NameTooLong test was
1281 incorrect.
1282
1283 * dns/message.py (Message.to_wire): dns.exception.TooBig is
1284 now raised if the wire encoding exceeds the specified
1285 maximum size.
1286
1287 2003-07-01 Bob Halley <halley@dnspython.org>
1288
1289 * dns/message.py: EDNS encoding was broken. from_text()
1290 didn't parse rcodes, flags, or eflags correctly. Comparing
1291 messages with other types of objects didn't work.
1292
1293 2003-06-30 Bob Halley <halley@dnspython.org>
1294
1295 * (Version 1.0.0 released)
1296
1297 2003-06-30 Bob Halley <halley@dnspython.org>
1298
1299 * dns/rdata.py: Rdatas now implement rich comparisons instead of
1300 __cmp__.
1301
1302 * dns/name.py: Names now implement rich comparisons instead of
1303 __cmp__.
1304
1305 * dns/inet.py (inet_ntop): Always use our code, since the code
1306 in the socket module doesn't support AF_INET6 conversions if
1307 IPv6 sockets are not available on the system.
1308
1309 * dns/resolver.py (Answer.__init__): A dangling CNAME chain was
1310 not raising NoAnswer.
1311
1312 * Added a simple resolver Cache class.
1313
1314 * Added an expiration attribute to answer instances.
1315
1316 2003-06-24 Bob Halley <halley@dnspython.org>
1317
1318 * (Version 1.0.0b3 released)
1319
1320 2003-06-24 Bob Halley <halley@dnspython.org>
1321
1322 * Renamed module "DNS" to "dns" to avoid conflicting with
1323 PyDNS.
1324
1325 2003-06-23 Bob Halley <halley@dnspython.org>
1326
1327 * The from_text() relativization controls now work the same way as
1328 the to_text() controls.
1329
1330 * DNS/rdata.py: The parsing of generic rdata was broken.
1331
1332 2003-06-21 Bob Halley <halley@dnspython.org>
1333
1334 * (Version 1.0.0b2 released)
1335
1336 2003-06-21 Bob Halley <halley@dnspython.org>
1337
1338 * The Python 2.2 socket.inet_aton() doesn't seem to like
1339 '255.255.255.255'. We work around this.
1340
1341 * Fixed bugs in rdata to_wire() and from_wire() routines of a few
1342 types. These bugs were discovered by running the tests/zone.py
1343 Torture1 test.
1344
1345 * Added implementation of type APL.
1346
1347 2003-06-20 Bob Halley <halley@dnspython.org>
1348
1349 * DNS/rdtypes/IN/AAAA.py: Use our own versions of inet_ntop and
1350 inet_pton if the socket module doesn't provide them for us.
1351
1352 * The resolver now does a better job handling exceptions. In
1353 particular, it no longer eats all exceptions; rather it handles
1354 those exceptions it understands, and leaves the rest uncaught.
1355
1356 * Exceptions have been pulled into their own module. Almost all
1357 exceptions raised by the code are now subclasses of
1358 DNS.exception.DNSException. All form errors are subclasses of
1359 DNS.exception.FormError (which is itself a subclass of
1360 DNS.exception.DNSException).
1361
1362 2003-06-19 Bob Halley <halley@dnspython.org>
1363
1364 * Added implementations of types DS, NXT, SIG, and WKS.
1365
1366 * __cmp__ for type A and AAAA could produce incorrect results.
1367
1368 2003-06-18 Bob Halley <halley@dnspython.org>
1369
1370 * Started test suites for zone.py and tokenizer.py.
1371
1372 * Added implementation of type KEY.
1373
1374 * DNS/rdata.py(_base64ify): \n could be emitted erroneously.
1375
1376 * DNS/rdtypes/ANY/SOA.py (SOA.from_text): The SOA RNAME field could
1377 be set to the value of MNAME in common cases.
1378
1379 * DNS/rdtypes/ANY/X25.py: __init__ was broken.
1380
1381 * DNS/zone.py (from_text): $TTL handling erroneously caused the
1382 next line to be eaten.
1383
1384 * DNS/tokenizer.py (Tokenizer.get): parsing was broken for empty
1385 quoted strings. Quoted strings didn't handle \ddd escapes. Such
1386 escapes are appear not to comply with RFC 1035, but BIND allows
1387 them and they seem useful, so we allow them too.
1388
1389 * DNS/rdtypes/ANY/ISDN.py (ISDN.from_text): parsing was
1390 broken for ISDN RRs without subaddresses.
1391
1392 * DNS/zone.py (from_file): from_file() didn't work because
1393 some required parameters were not passed to from_text().
1394
1395 2003-06-17 Bob Halley <halley@dnspython.org>
1396
1397 * (Version 1.0.0b1 released)
1398
1399 2003-06-17 Bob Halley <halley@dnspython.org>
1400
1401 * Added implementation of type PX.
1402
1403 2003-06-16 Bob Halley <halley@dnspython.org>
1404
1405 * Added implementation of types CERT, GPOS, LOC, NSAP, NSAP-PTR.
1406
1407 * DNS/rdatatype.py (_by_value): A cut-and-paste error had broken
1408 NSAP and NSAP-PTR.
1409
1410 2003-06-12 Bob Halley <halley@dnspython.org>
1411
1412 * Created a tests directory and started adding tests.
1413
1414 * Added "and its documentation" to the permission grant in the
1415 license.
1416
1417 2003-06-12 Bob Halley <halley@dnspython.org>
1418
1419 * DNS/name.py (Name.is_wild): is_wild() erroneously raised IndexError
1420 if the name was empty.
1421
1422 2003-06-10 Bob Halley <halley@dnspython.org>
1423
1424 * Added implementations of types AFSDB, X25, and ISDN.
1425
1426 * The documentation associated with the various rdata types has been
1427 improved. In particular, instance variables are now described.
1428
1429 2003-06-09 Bob Halley <halley@dnspython.org>
1430
1431 * Added implementations of types HINFO, RP, and RT.
1432
1433 * DNS/message.py (make_query): Document that make_query() sets
1434 flags to DNS.flags.RD, and chooses a random query id.
1435
1436 2003-06-05 Bob Halley <halley@dnspython.org>
1437
1438 * (Version 1.0.0a2 released)
1439
1440 2003-06-05 Bob Halley <halley@dnspython.org>
1441
1442 * DNS/node.py: removed __getitem__ and __setitem__, since
1443 they are not used by the codebase and were not useful in
1444 general either.
1445
1446 * DNS/message.py (from_file): from_file() now allows a
1447 filename to be specified instead of a file object.
1448
1449 * DNS/rdataset.py: The is_compatible() method of the
1450 DNS.rdataset.Rdataset class was deleted.
1451
1452 2003-06-04 Bob Halley <halley@dnspython.org>
1453
1454 * DNS/name.py (class Name): Names are now immutable.
1455
1456 * DNS/name.py: the is_comparable() method has been removed, since
1457 names are always comparable.
1458
1459 * DNS/resolver.py (Resolver.query): A query could run for up
1460 to the lifetime + the timeout. This has been corrected and the
1461 query will now only run up to the lifetime.
1462
1463 2003-06-03 Bob Halley <halley@dnspython.org>
1464
1465 * DNS/resolver.py: removed the 'new' function since it is not the
1466 style of the library to have such a function. Call
1467 DNS.resolver.Resolver() to make a new resolver.
1468
1469 2003-06-03 Bob Halley <halley@dnspython.org>
1470
1471 * DNS/resolver.py (Resolver._config_win32_fromkey): The DhcpServer
1472 list is space separated, not comma separated.
1473
1474 2003-06-03 Bob Halley <halley@dnspython.org>
1475
1476 * DNS/update.py: Added an update module to make generating updates
1477 easier.
1478
1479 2003-06-03 Bob Halley <halley@dnspython.org>
1480
1481 * Commas were missing in some of the __all__ entries in various
1482 __init__.py files.
1483
1484 2003-05-30 Bob Halley <halley@dnspython.org>
1485
1486 * (Version 1.0.0a1 released)
00 ISC License
11
2 Copyright (C) 2001-2003 Nominum, Inc.
2 Copyright (C) Dnspython Contributors
3
4 Permission to use, copy, modify, and/or distribute this software for
5 any purpose with or without fee is hereby granted, provided that the
6 above copyright notice and this permission notice appear in all
7 copies.
8
9 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 PERFORMANCE OF THIS SOFTWARE.
17
18
19
20 Copyright (C) 2001-2017 Nominum, Inc.
21 Copyright (C) Google Inc.
322
423 Permission to use, copy, modify, and distribute this software and its
524 documentation for any purpose with or without fee is hereby granted,
0 include LICENSE ChangeLog TODO
0 include LICENSE ChangeLog README.md
11 recursive-include examples *.txt *.py
22 recursive-include tests *.txt *.py Makefile *.good example
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
3 #
4 # Permission to use, copy, modify, and distribute this software and its
5 # documentation for any purpose with or without fee is hereby granted,
6 # provided that the above copyright notice and this permission notice
7 # appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 # $Id: Makefile,v 1.16 2004/03/19 00:17:27 halley Exp $
18
19 PYTHON=python
20 PYTHON3=python3
21
22 all:
23 ${PYTHON} ./setup.py build
24
25 install:
26 ${PYTHON} ./setup.py install
27
28 clean:
29 ${PYTHON} ./setup.py clean --all
30 find . -name '*.pyc' -exec rm {} \;
31 find . -name '*.pyo' -exec rm {} \;
32 rm -f TAGS
33
34 distclean: clean docclean
35 rm -rf build dist
36 rm -f MANIFEST
37
38 doco:
39 epydoc -v -n dnspython -u http://www.dnspython.org \
40 dns/*.py dns/rdtypes/*.py dns/rdtypes/ANY/*.py \
41 dns/rdtypes/CH/*.py \
42 dns/rdtypes/IN/*.py
43
44 dockits: doco
45 mv html dnspython-html
46 tar czf html.tar.gz dnspython-html
47 zip -r html.zip dnspython-html
48 mv dnspython-html html
49
50 docclean:
51 rm -rf html.tar.gz html.zip html
52
53 kits:
54 ${PYTHON3} ./setup.py sdist --formats=gztar,zip bdist_wheel
55
56 tags:
57 find . -name '*.py' -print | etags -
58
59 check: test
60
61 test:
62 cd tests; make PYTHON=${PYTHON} test
63
64 test2:
65 cd tests; make PYTHON=python test
66
67 test3:
68 cd tests; make PYTHON=${PYTHON3} test
69
70 lint:
71 pylint dns tests examples/*.py
72
73 lint3:
74 pylint3 dns tests examples/*.py
75
76 typecheck:
77 if [ $(shell python -c "import sys; print(sys.version_info[0])") -ne 2 ]; then pip install mypy; mypy examples tests; else echo Skipping typecheck on Python 2; fi
+0
-35
PKG-INFO less more
0 Metadata-Version: 1.1
1 Name: dnspython
2 Version: 1.15.0
3 Summary: DNS toolkit
4 Home-page: http://www.dnspython.org
5 Author: Bob Halley
6 Author-email: halley@dnspython.org
7 License: BSD-like
8 Download-URL: http://www.dnspython.org/kits/1.15.0/dnspython-1.15.0.tar.gz
9 Description: dnspython is a DNS toolkit for Python. It supports almost all
10 record types. It can be used for queries, zone transfers, and dynamic
11 updates. It supports TSIG authenticated messages and EDNS0.
12
13 dnspython provides both high and low level access to DNS. The high
14 level classes perform queries for data of a given name, type, and
15 class, and return an answer set. The low level classes allow
16 direct manipulation of DNS zones, messages, names, and records.
17 Platform: UNKNOWN
18 Classifier: Development Status :: 5 - Production/Stable
19 Classifier: Intended Audience :: Developers
20 Classifier: Intended Audience :: System Administrators
21 Classifier: License :: Freeware
22 Classifier: Operating System :: Microsoft :: Windows :: Windows 95/98/2000
23 Classifier: Operating System :: POSIX
24 Classifier: Programming Language :: Python
25 Classifier: Topic :: Internet :: Name Service (DNS)
26 Classifier: Topic :: Software Development :: Libraries :: Python Modules
27 Classifier: Programming Language :: Python :: 2
28 Classifier: Programming Language :: Python :: 2.6
29 Classifier: Programming Language :: Python :: 2.7
30 Classifier: Programming Language :: Python :: 3
31 Classifier: Programming Language :: Python :: 3.3
32 Classifier: Programming Language :: Python :: 3.4
33 Classifier: Programming Language :: Python :: 3.5
34 Provides: dns
0 # dnspython
1
2 [![Build Status](https://travis-ci.org/rthalley/dnspython.svg?branch=master)](https://travis-ci.org/rthalley/dnspython)
3
4 ## INTRODUCTION
5
6 dnspython is a DNS toolkit for Python. It supports almost all record types. It
7 can be used for queries, zone transfers, and dynamic updates. It supports TSIG
8 authenticated messages and EDNS0.
9
10 dnspython provides both high and low level access to DNS. The high level classes
11 perform queries for data of a given name, type, and class, and return an answer
12 set. The low level classes allow direct manipulation of DNS zones, messages,
13 names, and records.
14
15 To see a few of the ways dnspython can be used, look in the `examples/` directory.
16
17 dnspython is a utility to work with DNS, `/etc/hosts` is thus not used. For
18 simple forward DNS lookups, it's better to use `socket.gethostbyname()`.
19
20 dnspython originated at Nominum where it was developed
21 to facilitate the testing of DNS software.
22
23 ## INSTALLATION
24
25 * Many distributions have dnspython packaged for you, so you should
26 check there first.
27 * If you have pip installed, you can do `pip install dnspython`
28 * If not just download the source file and unzip it, then run
29 `sudo python setup.py install`
30
31 ## ABOUT THIS RELEASE
32
33 This is dnspython 1.16.0
34
35 ### Notices
36
37 Python 2.x support ends with the release of 1.16.0, unless there are
38 critical bugs in 1.16.0. Future versions of dnspython will only
39 support Python 3.
40
41 Version numbering of future dnspython releases will also start at 2.0, as
42 incompatible changes will be permitted. We're not planning huge changes at
43 this time, but we'd like to do a better job at IDNA, and there are other
44 API improvements to be made.
45
46 The ChangeLog has been discontinued. Please see the git history for detailed
47 change information.
48
49 ### New since 1.15.0:
50
51 * Much of the internals of dns.query.udp() and dns.query.tcp() have
52 been factored out into dns.query.send_udp(),
53 dns.query.receive_udp(), dns.query.send_tcp(), and
54 dns.query.receive_tcp(). Applications which want more control over
55 the socket may find the new routines helpful; for example it would
56 be easy to send multiple queries over a single TCP connection.
57
58 * The OPENPGPKEY RR, and the CHAOS class A RR are now supported.
59
60 * EDNS0 client-subnet is supported.
61
62 * dns.resover.query() now has a lifetime timeout optional parameter.
63
64 * pycryptodome and pycryptodomex are now supported and recommended for use
65 instead of pycrypto.
66
67 * dns.message.from_wire() now has an ignore_trailing option.
68
69 * type signatures have been provided.
70
71 * module dns.hash is now deprecated, use standard Python libraries instead.
72
73 * setup.py supports Cythonization to improve performance.
74
75 ### Bugs fixed since 1.15.0:
76
77 * DNSSEC signature validation didn't check names correctly. [Issue #295]
78
79 * The NXDOMAIN exception should not use its docstring. [Issue #253]
80
81 * Fixed regression where trailing zeros in APL RRs were not
82 suppressed, and then fixed the problem where trailing zeros
83 were not added back properly on python 3 when needed.
84
85 * Masterfile TTL defaulting is now harmonized with BIND practice.
86
87 * dns.query.xfr() now raises on a non-zero rcode.
88
89 * Rdata module importing is now locked to avoid races.
90
91 * Several Python 3 incompatibilities have been fixed.
92
93 * NSEC3 bitmap parsing now works with mulitple NSEC3 windows.
94
95 * dns.renderer.Render supports TSIG on DNS envelope sequences.
96
97 * DNSSEC validation now checks names properly [Issue #295]
98
99 ### New since 1.14.0:
100
101 * IDNA 2008 support is now available if the "idna" module has been
102 installed and IDNA 2008 is requested. The default IDNA behavior is
103 still IDNA 2003. The new IDNA codec mechanism is currently only
104 useful for direct calls to dns.name.from_text() or
105 dns.name.from_unicode(), but in future releases it will be deployed
106 throughout dnspython, e.g. so that you can read a masterfile with an
107 IDNA 2008 codec in force.
108
109 * By default, dns.name.to_unicode() is not strict about which
110 version of IDNA the input complies with. Strictness can be
111 requested by using one of the strict IDNA codecs.
112
113 * The AVC RR is now supported.
114
115 ### Bugs fixed since 1.14.0:
116
117 * Some problems with newlines in various output modes have been
118 addressed.
119
120 * dns.name.to_text() now returns text and not bytes on Python 3.x
121
122 * Miscellaneous fixes for the Python 2/3 codeline merge.
123
124 * Many "lint" fixes after the addition of pylint support.
125
126 * The random number generator reseeds after a fork().
127
128
129 ## REQUIREMENTS
130
131 Python 2.7 or 3.4+.
132
133
134 ## HOME PAGE
135
136 For the latest in releases, documentation, and information, visit the dnspython
137 home page at http://www.dnspython.org/
138
139
140 ## BUG REPORTS
141
142 Bug reports may be opened at
143 https://github.com/rthalley/dnspython/issues or sent to
144 bugs@dnspython.org
145
146
147 ## MAILING LISTS
148
149 A number of mailing lists are available. Visit the dnspython home page to
150 subscribe or unsubscribe.
151
152
153 ## PRIOR RELEASE INFORMATION
154
155 ### New since 1.13.0:
156
157 * CSYNC RRs are now supported.
158
159 * `dns/message.py` (`make_query`): Setting any value which implies EDNS will
160 turn on EDNS if `use_edns` has not been specified.
161
162 ### Bugs fixed since 1.13.0:
163
164 * TSIG signature algorithm setting was broken by the Python 2 and Python 3 code
165 line merge.
166
167 * A bug in the LOC RR destroyed N/S and E/W distinctions within a degree of the
168 equator or prime merdian respectively.
169
170 * Misc. fixes to deal with fallout from the Python 2 & 3 merge.
171 Fixes #156, #157, #158, #159, #160.
172
173 * Running with python optimization on caused issues when stripped docstrings
174 were referenced. Fixes #154
175
176 * `dns.zone.from_text()` erroneously required the zone to be provided.
177 Fixes #153
178
179 ### New since 1.12.0:
180
181 * Dnspython now uses a single source for Python 2 and Python 3, eliminating the
182 painful merging between the Python 2 and Python 3 branches. Thank you so much
183 to Arthur Gautier for taking on this challenge and making it work! It was a
184 big job!
185
186 * Support for Python older than 2.6 dropped.
187
188 * Support for Python older than 3.3 dropped.
189
190 * Zone origin can be specified as a string.
191
192 * A rich string representation for all DNSExceptions.
193
194 * setuptools has replaced distutils
195
196 * Added support for CAA, CDS, CDNSKEY, EUI48, EUI64, and URI RR types.
197
198 * Names now support the pickle protocol.
199
200 * Ports can be specified per-nameserver in the stub resolver.
201
202 ### Bugs fixed since 1.12.0:
203
204 * A number of Unicode name bugs have been fixed.
205
206 * `resolv.conf` processing now rejects lines with too few tokens.
207
208 * NameDicts now keep the max-depth value correct, and update properly.
209
210 ### New since 1.11.1:
211
212 * Added `dns.zone.to_text()`.
213
214 * Added support for "options rotate" in `/etc/resolv.conf`.
215
216 * `dns.rdtypes.ANY.DNSKEY` now has helpers functions to convert between the
217 numeric form of the flags and a set of human-friendly strings
218
219 * The reverse name of an IPv6 mapped IPv4 address is now in the IPv4 reverse
220 namespace.
221
222 * The test system can now run the tests without requiring dnspython to be
223 installed.
224
225 * Preliminary Elliptic Curve DNSSEC Validation (requires ecdsa module)
226
227 ### Bugs fixed since 1.11.1:
228
229 * dnspython raised an exception when reading a masterfile starting with leading
230 whitespace
231
232 * dnspython was affected by a python slicing API bug present on 64-bit windows.
233
234 * Unicode escaping was applied at the wrong time.
235
236 * RRSIG `to_text()` did not respect the relativize setting.
237
238 * APL RRs with zero rdlength were rejected.
239
240 * The tokenizer could put back an unescaped token.
241
242 * Making a response to a message signed with TSIG was broken.
243
244 * The IXFR state machine didn't handle long IXFR diffs.
245
246 ### New since 1.11.0:
247
248 * Nothing
249
250 ### Bugs fixed since 1.11.0:
251
252 * `dns.resolver.Resolver` erroneously referred to `retry_servfail`
253 instead of `self.retry_servfail`.
254
255 * `dns.tsigkeyring.to_text()` would fail trying to convert the keyname to text.
256
257 * Multi-message TSIGs were broken for algorithms other than HMAC-MD5 because we
258 weren't passing the right digest module to the HMAC code.
259
260 * `dns.dnssec._find_candidate_keys()` tried to extract the key from the wrong
261 variable name.
262
263 * $GENERATE tests were not backward compatible with python 2.4.
264
265 ### New since 1.10.0:
266
267 * $GENERATE support
268
269 * TLSA RR support
270
271 * Added set_flags() method to dns.resolver.Resolver
272
273 ### Bugs fixed since 1.10.0:
274
275 * Names with offsets >= 2^14 are no longer added to the compression table.
276
277 * The "::" syntax is not used to shorten a single 16-bit section of the text
278 form an IPv6 address.
279
280 * Caches are now locked.
281
282 * YXDOMAIN is raised if seen by the resolver.
283
284 * Empty rdatasets are not printed.
285
286 * DNSKEY key tags are no longer assumed to be unique.
287
288 ### New since 1.9.4:
289
290 * Added dns.resolver.LRUCache. In this cache implementation, the cache size is
291 limited to a user-specified number of nodes, and when adding a new node to a
292 full cache the least-recently used node is removed. If you're crawling the web
293 or otherwise doing lots of resolutions and you are using a cache, switching
294 to the LRUCache is recommended.
295
296 * `dns.resolver.query()` will try TCP if a UDP response is truncated.
297
298 * The python socket module's DNS methods can be now be overridden with
299 implementations that use dnspython's resolver.
300
301 * Old DNSSEC types KEY, NXT, and SIG have been removed.
302
303 * Whitespace is allowed in SSHFP fingerprints.
304
305 * Origin checking in `dns.zone.from_xfr()` can be disabled.
306
307 * Trailing junk checking can be disabled.
308
309 * A source port can be specified when creating a resolver query.
310
311 * All EDNS values may now be specified to `dns.message.make_query()`.
312
313 ### Bugs fixed since 1.9.4:
314
315 * IPv4 and IPv6 address processing is now stricter.
316
317 * Bounds checking of slices in rdata wire processing is now more strict, and
318 bounds errors (e.g. we got less data than was expected) now raise
319 `dns.exception.FormError` rather than `IndexError`.
320
321 * Specifying a source port without specifying source used to have no effect, but
322 now uses the wildcard address and the specified port.
323
324 ### New since 1.9.3:
325
326 * Nothing.
327
328 ### Bugs fixed since 1.9.3:
329
330 * The rdata `_wire_cmp()` routine now handles relative names.
331
332 * The SIG RR implementation was missing `import struct`.
333
334 ### New since 1.9.2:
335
336 * A boolean parameter, `raise_on_no_answer`, has been added to the `query()`
337 methods. In no-error, no-data situations, this parameter determines whether
338 `NoAnswer` should be raised or not. If True, `NoAnswer` is raised. If False,
339 then an `Answer()` object with a None rrset will be returned.
340
341 * Resolver `Answer()` objects now have a canonical_name field.
342
343 * Rdata now has a `__hash__` method.
344
345 ### Bugs fixed since 1.9.2:
346
347 * Dnspython was erroneously doing case-insensitive comparisons of the names in
348 NSEC and RRSIG RRs.
349
350 * We now use `is` and not `==` when testing what section an RR is in.
351
352 * The resolver now disallows metaqueries.
353
354 ### New since 1.9.1:
355
356 * Nothing.
357
358 ### Bugs fixed since 1.9.1:
359
360 * The `dns.dnssec` module didn't work at all due to missing imports that escaped
361 detection in testing because the test suite also did the imports. The third
362 time is the charm!
363
364 ### New since 1.9.0:
365
366 * Nothing.
367
368 ### Bugs fixed since 1.9.0:
369
370 * The `dns.dnssec` module didn't work with DSA due to namespace contamination
371 from a "from"-style import.
372
373 ### New since 1.8.0:
374
375 * dnspython now uses `poll()` instead of `select()` when available.
376
377 * Basic DNSSEC validation can be done using `dns.dnsec.validate()` and
378 `dns.dnssec.validate_rrsig()` if you have PyCrypto 2.3 or later installed.
379 Complete secure resolution is not yet available.
380
381 * Added `key_id()` to the DNSSEC module, which computes the DNSSEC key id of a
382 DNSKEY rdata.
383
384 * Added `make_ds()` to the DNSSEC module, which returns the DS RR for a given
385 DNSKEY rdata.
386
387 * dnspython now raises an exception if HMAC-SHA284 or HMAC-SHA512 are used with
388 a Python older than 2.5.2. (Older Pythons do not compute the correct value.)
389
390 * Symbolic constants are now available for TSIG algorithm names.
391
392 ### Bugs fixed since 1.8.0
393
394 * `dns.resolver.zone_for_name()` didn't handle a query response with a CNAME or
395 DNAME correctly in some cases.
396
397 * When specifying rdata types and classes as text, Unicode strings may now be
398 used.
399
400 * Hashlib compatibility issues have been fixed.
401
402 * `dns.message` now imports `dns.edns`.
403
404 * The TSIG algorithm value was passed incorrectly to `use_tsig()` in some cases.
405
406 ### New since 1.7.1:
407
408 * Support for hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384 and hmac-sha512
409 has been contributed by Kevin Chen.
410
411 * The tokenizer's tokens are now Token objects instead of (type, value) tuples.
412
413 ### Bugs fixed since 1.7.1:
414
415 * Escapes in masterfiles now work correctly. Previously they were only working
416 correctly when the text involved was part of a domain name.
417
418 * When constructing a DDNS update, if the `present()` method was used with a
419 single rdata, a zero TTL was not added.
420
421 * The entropy pool needed locking to be thread safe.
422
423 * The entropy pool's reading of `/dev/random` could cause dnspython to block.
424
425 * The entropy pool did buffered reads, potentially consuming more randomness
426 than we needed.
427
428 * The entropy pool did not seed with high quality randomness on Windows.
429
430 * SRV records were compared incorrectly.
431
432 * In the e164 query function, the resolver parameter was not used.
433
434 ### New since 1.7.0:
435
436 * Nothing
437
438 ### Bugs fixed since 1.7.0:
439
440 * The 1.7.0 kitting process inadvertently omitted the code for the DLV RR.
441
442 * Negative DDNS prerequisites are now handled correctly.
443
444 ### New since 1.6.0:
445
446 * Rdatas now have a `to_digestable()` method, which returns the DNSSEC canonical
447 form of the rdata, suitable for use in signature computations.
448
449 * The NSEC3, NSEC3PARAM, DLV, and HIP RR types are now supported.
450
451 * An entropy module has been added and is used to randomize query ids.
452
453 * EDNS0 options are now supported.
454
455 * UDP IXFR is now supported.
456
457 * The wire format parser now has a `one_rr_per_rrset` mode, which suppresses the
458 usual coalescing of all RRs of a given type into a single RRset.
459
460 * Various helpful DNSSEC-related constants are now defined.
461
462 * The resolver's `query()` method now has an optional `source` parameter,
463 allowing the source IP address to be specified.
464
465 ### Bugs fixed since 1.6.0:
466
467 * On Windows, the resolver set the domain incorrectly.
468
469 * DS RR parsing only allowed one Base64 chunk.
470
471 * TSIG validation didn't always use absolute names.
472
473 * `NSEC.to_text()` only printed the last window.
474
475 * We did not canonicalize IPv6 addresses before comparing them; we
476 would thus treat equivalent but different textual forms, e.g.
477 "1:00::1" and "1::1" as being non-equivalent.
478
479 * If the peer set a TSIG error, we didn't raise an exception.
480
481 * Some EDNS bugs in the message code have been fixed (see the ChangeLog
482 for details).
483
484 ### New since 1.5.0:
485
486 * Added dns.inet.is_multicast().
487
488 ### Bugs fixed since 1.5.0:
489
490 * If `select()` raises an exception due to EINTR, we should just `select()`
491 again.
492
493 * If the queried address is a multicast address, then don't check that the
494 address of the response is the same as the address queried.
495
496 * NAPTR comparisons didn't compare the preference field due to a typo.
497
498 * Testing of whether a Windows NIC is enabled now works on Vista thanks to code
499 contributed by Paul Marks.
500
501 ### New since 1.4.0:
502
503 * Answer objects now support more of the python sequence protocol, forwarding
504 the requests to the answer rrset. E.g. `for a in answer` is equivalent to
505 `for a in answer.rrset`, `answer[i]` is equivalent to `answer.rrset[i]`, and
506 `answer[i:j]` is equivalent to `answer.rrset[i:j]`.
507
508 * Making requests using EDNS, including indicating DNSSEC awareness,
509 is now easier. For example, you can now say:
510 `q = dns.message.make_query('www.dnspython.org', 'MX', want_dnssec=True)`
511
512 * `dns.query.xfr()` can now be used for IXFR.
513
514 * Support has been added for the DHCID, IPSECKEY, and SPF RR types.
515
516 * UDP messages from unexpected sources can now be ignored by setting
517 `ignore_unexpected` to True when calling `dns.query.udp`.
518
519 ### Bugs fixed since 1.4.0:
520
521 * If `/etc/resolv.conf` didn't exist, we raised an exception instead of simply
522 using the default resolver configuration.
523
524 * In `dns.resolver.Resolver._config_win32_fromkey()`, we were passing the wrong
525 variable to `self._config_win32_search()`.
526
527 ### New since 1.3.5:
528
529 * You can now convert E.164 numbers to/from their ENUM name forms:
530 ```python
531 >>> import dns.e164
532 >>> n = dns.e164.from_e164("+1 555 1212")
533 >>> n
534 <DNS name 2.1.2.1.5.5.5.1.e164.arpa.>
535 >>> dns.e164.to_e164(n)
536 '+15551212'
537 ```
538
539 * You can now convert IPv4 and IPv6 address to/from their corresponding DNS
540 reverse map names:
541 ```python
542 >>> import dns.reversename
543 >>> n = dns.reversename.from_address("127.0.0.1")
544 >>> n
545 <DNS name 1.0.0.127.in-addr.arpa.>
546 >>> dns.reversename.to_address(n)
547 '127.0.0.1'
548 ```
549
550 * You can now convert between Unicode strings and their IDN ACE form:
551 ```python
552 >>> n = dns.name.from_text(u'les-\u00e9l\u00e8ves.example.')
553 >>> n
554 <DNS name xn--les-lves-50ai.example.>
555 >>> n.to_unicode()
556 u'les-\xe9l\xe8ves.example.'
557 ```
558
559 * The origin parameter to `dns.zone.from_text()` and `dns.zone.to_text()` is now
560 optional. If not specified, the origin will be taken from the first $ORIGIN
561 statement in the master file.
562
563 * Sanity checking of a zone can be disabled; this is useful when working with
564 files which are zone fragments.
565
566 ### Bugs fixed since 1.3.5:
567
568 * The correct delimiter was not used when retrieving the list of nameservers
569 from the registry in certain versions of windows.
570
571 * The floating-point version of latitude and longitude in LOC RRs
572 (`float_latitude` and `float_longitude`) had incorrect signs for south
573 latitudes and west longitudes.
574
575 * BIND 8 TTL syntax is now accepted in all TTL-like places (i.e. SOA fields
576 refresh, retry, expire, and minimum; SIG/RRSIG field original_ttl).
577
578 * TTLs are now bounds checked when their text form is parsed, and their values
579 must be in the closed interval `[0, 2^31 - 1]`.
580
581 ### New since 1.3.4:
582
583 * In the resolver, if time goes backward a little bit, ignore it.
584
585 * `zone_for_name()` has been added to the resolver module. It returns the zone
586 which is authoritative for the specified name, which is handy for dynamic
587 update. E.g.
588
589 import dns.resolver
590 print dns.resolver.zone_for_name('www.dnspython.org')
591
592 will output `"dnspython.org."` and
593 `print dns.resolver.zone_for_name('a.b.c.d.e.f.example.')`
594 will output `"."`.
595
596 * The default resolver can be fetched with the `get_default_resolver()` method.
597
598 * You can now get the parent (immediate superdomain) of a name by using the
599 `parent()` method.
600
601 * `Zone.iterate_rdatasets()` and `Zone.iterate_rdatas()` now have a default
602 rdtype of `dns.rdatatype.ANY` like the documentation says.
603
604 * A Dynamic DNS example, ddns.py, has been added.
605
606 ### New since 1.3.3:
607
608 * The source address and port may now be specified when calling
609 `dns.query.{udp,tcp,xfr}`.
610
611 * The resolver now does exponential backoff each time it runs through all of the
612 nameservers.
613
614 * Rcodes which indicate a nameserver is likely to be a "permanent failure" for a
615 query cause the nameserver to be removed from the mix for that query.
616
617 ### New since 1.3.2:
618
619 * `dns.message.Message.find_rrset()` now uses an index, vastly improving the
620 `from_wire()` performance of large messages such as zone transfers.
621
622 * Added `dns.message.make_response()`, which creates a skeletal response for the
623 specified query.
624
625 * Added `opcode()` and `set_opcode()` convenience methods to the
626 `dns.message.Message` class. Added the `request_payload` attribute to the
627 Message class.
628
629 * The `file` parameter of `dns.name.Name.to_wire()` is now optional; if omitted,
630 the wire form will be returned as the value of the function.
631
632 * `dns.zone.from_xfr()` in relativization mode incorrectly set `zone.origin` to
633 the empty name.
634
635 * The masterfile parser incorrectly rejected TXT records where a value was not
636 quoted.
637
638 ### New since 1.3.1:
639
640 * The NSEC format doesn't allow specifying types by number, so we shouldn't
641 either. (Using the unknown type format is still OK though.)
642
643 * The resolver wasn't catching `dns.exception.Timeout`, so a timeout erroneously
644 caused the whole resolution to fail instead of just going on to the next
645 server.
646
647 * The renderer module didn't import random, causing an exception to be raised if
648 a query id wasn't provided when a Renderer was created.
649
650 * The conversion of LOC milliseconds values from text to binary was incorrect if
651 the length of the milliseconds string was not 3.
652
653 ### New since 1.3.0:
654
655 * Added support for the SSHFP type.
656
657 ### New since 1.2.0:
658
659 * Added support for new DNSSEC types RRSIG, NSEC, and DNSKEY.
660
661 * This release fixes all known bugs.
662
663 * See the ChangeLog file for more detailed information on changes since the
664 prior release.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
11 import decimal
22 from decimal import Context
33
4 if sys.version_info > (3,):
4 PY3 = sys.version_info[0] == 3
5 PY2 = sys.version_info[0] == 2
6
7
8 if PY3:
59 long = int
610 xrange = range
711 else:
913 xrange = xrange # pylint: disable=xrange-builtin
1014
1115 # unicode / binary types
12 if sys.version_info > (3,):
16 if PY3:
1317 text_type = str
1418 binary_type = bytes
1519 string_types = (str,)
1822 return x.decode()
1923 def maybe_encode(x):
2024 return x.encode()
25 def maybe_chr(x):
26 return x
27 def maybe_ord(x):
28 return x
2129 else:
2230 text_type = unicode # pylint: disable=unicode-builtin, undefined-variable
2331 binary_type = str
2937 return x
3038 def maybe_encode(x):
3139 return x
40 def maybe_chr(x):
41 return chr(x)
42 def maybe_ord(x):
43 return ord(x)
3244
3345
3446 def round_py2_compat(what):
0 # Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1921 import time
2022
2123 import dns.exception
22 import dns.hash
2324 import dns.name
2425 import dns.node
2526 import dns.rdataset
3031
3132
3233 class UnsupportedAlgorithm(dns.exception.DNSException):
33
3434 """The DNSSEC algorithm is not supported."""
3535
3636
3737 class ValidationFailure(dns.exception.DNSException):
38
3938 """The DNSSEC signature is invalid."""
4039
40
41 #: RSAMD5
4142 RSAMD5 = 1
43 #: DH
4244 DH = 2
45 #: DSA
4346 DSA = 3
47 #: ECC
4448 ECC = 4
49 #: RSASHA1
4550 RSASHA1 = 5
51 #: DSANSEC3SHA1
4652 DSANSEC3SHA1 = 6
53 #: RSASHA1NSEC3SHA1
4754 RSASHA1NSEC3SHA1 = 7
55 #: RSASHA256
4856 RSASHA256 = 8
57 #: RSASHA512
4958 RSASHA512 = 10
59 #: ECDSAP256SHA256
5060 ECDSAP256SHA256 = 13
61 #: ECDSAP384SHA384
5162 ECDSAP384SHA384 = 14
63 #: INDIRECT
5264 INDIRECT = 252
65 #: PRIVATEDNS
5366 PRIVATEDNS = 253
67 #: PRIVATEOID
5468 PRIVATEOID = 254
5569
5670 _algorithm_by_text = {
7488 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
7589 # would cause the mapping not to be true inverse.
7690
77 _algorithm_by_value = dict((y, x) for x, y in _algorithm_by_text.items())
91 _algorithm_by_value = {y: x for x, y in _algorithm_by_text.items()}
7892
7993
8094 def algorithm_from_text(text):
81 """Convert text into a DNSSEC algorithm value
82 @rtype: int"""
95 """Convert text into a DNSSEC algorithm value.
96
97 Returns an ``int``.
98 """
8399
84100 value = _algorithm_by_text.get(text.upper())
85101 if value is None:
89105
90106 def algorithm_to_text(value):
91107 """Convert a DNSSEC algorithm value to text
92 @rtype: string"""
108
109 Returns a ``str``.
110 """
93111
94112 text = _algorithm_by_value.get(value)
95113 if text is None:
104122
105123
106124 def key_id(key, origin=None):
125 """Return the key id (a 16-bit number) for the specified key.
126
127 Note the *origin* parameter of this function is historical and
128 is not needed.
129
130 Returns an ``int`` between 0 and 65535.
131 """
132
107133 rdata = _to_rdata(key, origin)
108134 rdata = bytearray(rdata)
109135 if key.algorithm == RSAMD5:
120146
121147
122148 def make_ds(name, key, algorithm, origin=None):
149 """Create a DS record for a DNSSEC key.
150
151 *name* is the owner name of the DS record.
152
153 *key* is a ``dns.rdtypes.ANY.DNSKEY``.
154
155 *algorithm* is a string describing which hash algorithm to use. The
156 currently supported hashes are "SHA1" and "SHA256". Case does not
157 matter for these strings.
158
159 *origin* is a ``dns.name.Name`` and will be used as the origin
160 if *key* is a relative name.
161
162 Returns a ``dns.rdtypes.ANY.DS``.
163 """
164
123165 if algorithm.upper() == 'SHA1':
124166 dsalg = 1
125 hash = dns.hash.hashes['SHA1']()
167 hash = SHA1.new()
126168 elif algorithm.upper() == 'SHA256':
127169 dsalg = 2
128 hash = dns.hash.hashes['SHA256']()
170 hash = SHA256.new()
129171 else:
130172 raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm)
131173
197239
198240 def _make_hash(algorithm):
199241 if _is_md5(algorithm):
200 return dns.hash.hashes['MD5']()
242 return MD5.new()
201243 if _is_sha1(algorithm):
202 return dns.hash.hashes['SHA1']()
244 return SHA1.new()
203245 if _is_sha256(algorithm):
204 return dns.hash.hashes['SHA256']()
246 return SHA256.new()
205247 if _is_sha384(algorithm):
206 return dns.hash.hashes['SHA384']()
248 return SHA384.new()
207249 if _is_sha512(algorithm):
208 return dns.hash.hashes['SHA512']()
250 return SHA512.new()
209251 raise ValidationFailure('unknown hash for algorithm %u' % algorithm)
210252
211253
231273 def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
232274 """Validate an RRset against a single signature rdata
233275
234 The owner name of the rrsig is assumed to be the same as the owner name
235 of the rrset.
236
237 @param rrset: The RRset to validate
238 @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
239 tuple
240 @param rrsig: The signature rdata
241 @type rrsig: dns.rrset.Rdata
242 @param keys: The key dictionary.
243 @type keys: a dictionary keyed by dns.name.Name with node or rdataset
244 values
245 @param origin: The origin to use for relative names
246 @type origin: dns.name.Name or None
247 @param now: The time to use when validating the signatures. The default
248 is the current time.
249 @type now: int
276 The owner name of *rrsig* is assumed to be the same as the owner name
277 of *rrset*.
278
279 *rrset* is the RRset to validate. It can be a ``dns.rrset.RRset`` or
280 a ``(dns.name.Name, dns.rdataset.Rdataset)`` tuple.
281
282 *rrsig* is a ``dns.rdata.Rdata``, the signature to validate.
283
284 *keys* is the key dictionary, used to find the DNSKEY associated with
285 a given name. The dictionary is keyed by a ``dns.name.Name``, and has
286 ``dns.node.Node`` or ``dns.rdataset.Rdataset`` values.
287
288 *origin* is a ``dns.name.Name``, the origin to use for relative names.
289
290 *now* is an ``int``, the time to use when validating the signatures,
291 in seconds since the UNIX epoch. The default is the current time.
250292 """
251293
252294 if isinstance(origin, string_types):
253295 origin = dns.name.from_text(origin, dns.name.root)
254296
255 for candidate_key in _find_candidate_keys(keys, rrsig):
256 if not candidate_key:
257 raise ValidationFailure('unknown key')
258
297 candidate_keys = _find_candidate_keys(keys, rrsig)
298 if candidate_keys is None:
299 raise ValidationFailure('unknown key')
300
301 for candidate_key in candidate_keys:
259302 # For convenience, allow the rrset to be specified as a (name,
260303 # rdataset) tuple as well as a proper rrset
261304 if isinstance(rrset, tuple):
283326 keyptr = keyptr[2:]
284327 rsa_e = keyptr[0:bytes_]
285328 rsa_n = keyptr[bytes_:]
286 keylen = len(rsa_n) * 8
287 pubkey = Crypto.PublicKey.RSA.construct(
288 (Crypto.Util.number.bytes_to_long(rsa_n),
289 Crypto.Util.number.bytes_to_long(rsa_e)))
290 sig = (Crypto.Util.number.bytes_to_long(rrsig.signature),)
329 try:
330 pubkey = CryptoRSA.construct(
331 (number.bytes_to_long(rsa_n),
332 number.bytes_to_long(rsa_e)))
333 except ValueError:
334 raise ValidationFailure('invalid public key')
335 sig = rrsig.signature
291336 elif _is_dsa(rrsig.algorithm):
292337 keyptr = candidate_key.key
293338 (t,) = struct.unpack('!B', keyptr[0:1])
300345 dsa_g = keyptr[0:octets]
301346 keyptr = keyptr[octets:]
302347 dsa_y = keyptr[0:octets]
303 pubkey = Crypto.PublicKey.DSA.construct(
304 (Crypto.Util.number.bytes_to_long(dsa_y),
305 Crypto.Util.number.bytes_to_long(dsa_g),
306 Crypto.Util.number.bytes_to_long(dsa_p),
307 Crypto.Util.number.bytes_to_long(dsa_q)))
308 (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:])
309 sig = (Crypto.Util.number.bytes_to_long(dsa_r),
310 Crypto.Util.number.bytes_to_long(dsa_s))
348 pubkey = CryptoDSA.construct(
349 (number.bytes_to_long(dsa_y),
350 number.bytes_to_long(dsa_g),
351 number.bytes_to_long(dsa_p),
352 number.bytes_to_long(dsa_q)))
353 sig = rrsig.signature[1:]
311354 elif _is_ecdsa(rrsig.algorithm):
355 # use ecdsa for NIST-384p -- not currently supported by pycryptodome
356
357 keyptr = candidate_key.key
358
312359 if rrsig.algorithm == ECDSAP256SHA256:
313360 curve = ecdsa.curves.NIST256p
314361 key_len = 32
315362 elif rrsig.algorithm == ECDSAP384SHA384:
316363 curve = ecdsa.curves.NIST384p
317364 key_len = 48
318 else:
319 # shouldn't happen
320 raise ValidationFailure('unknown ECDSA curve')
321 keyptr = candidate_key.key
322 x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len])
323 y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2])
324 assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y)
365
366 x = number.bytes_to_long(keyptr[0:key_len])
367 y = number.bytes_to_long(keyptr[key_len:key_len * 2])
368 if not ecdsa.ecdsa.point_is_valid(curve.generator, x, y):
369 raise ValidationFailure('invalid ECDSA key')
325370 point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order)
326371 verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point,
327372 curve)
328373 pubkey = ECKeyWrapper(verifying_key, key_len)
329374 r = rrsig.signature[:key_len]
330375 s = rrsig.signature[key_len:]
331 sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r),
332 Crypto.Util.number.bytes_to_long(s))
376 sig = ecdsa.ecdsa.Signature(number.bytes_to_long(r),
377 number.bytes_to_long(s))
378
333379 else:
334380 raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
335381
351397 hash.update(rrlen)
352398 hash.update(rrdata)
353399
354 digest = hash.digest()
355
356 if _is_rsa(rrsig.algorithm):
357 # PKCS1 algorithm identifier goop
358 digest = _make_algorithm_id(rrsig.algorithm) + digest
359 padlen = keylen // 8 - len(digest) - 3
360 digest = struct.pack('!%dB' % (2 + padlen + 1),
361 *([0, 1] + [0xFF] * padlen + [0])) + digest
362 elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm):
363 pass
364 else:
365 # Raise here for code clarity; this won't actually ever happen
366 # since if the algorithm is really unknown we'd already have
367 # raised an exception above
368 raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
369
370 if pubkey.verify(digest, sig):
400 try:
401 if _is_rsa(rrsig.algorithm):
402 verifier = pkcs1_15.new(pubkey)
403 # will raise ValueError if verify fails:
404 verifier.verify(hash, sig)
405 elif _is_dsa(rrsig.algorithm):
406 verifier = DSS.new(pubkey, 'fips-186-3')
407 verifier.verify(hash, sig)
408 elif _is_ecdsa(rrsig.algorithm):
409 digest = hash.digest()
410 if not pubkey.verify(digest, sig):
411 raise ValueError
412 else:
413 # Raise here for code clarity; this won't actually ever happen
414 # since if the algorithm is really unknown we'd already have
415 # raised an exception above
416 raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
417 # If we got here, we successfully verified so we can return without error
371418 return
419 except ValueError:
420 # this happens on an individual validation failure
421 continue
422 # nothing verified -- raise failure:
372423 raise ValidationFailure('verify failure')
373424
374425
375426 def _validate(rrset, rrsigset, keys, origin=None, now=None):
376 """Validate an RRset
377
378 @param rrset: The RRset to validate
379 @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
380 tuple
381 @param rrsigset: The signature RRset
382 @type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset)
383 tuple
384 @param keys: The key dictionary.
385 @type keys: a dictionary keyed by dns.name.Name with node or rdataset
386 values
387 @param origin: The origin to use for relative names
388 @type origin: dns.name.Name or None
389 @param now: The time to use when validating the signatures. The default
390 is the current time.
391 @type now: int
427 """Validate an RRset.
428
429 *rrset* is the RRset to validate. It can be a ``dns.rrset.RRset`` or
430 a ``(dns.name.Name, dns.rdataset.Rdataset)`` tuple.
431
432 *rrsigset* is the signature RRset to be validated. It can be a
433 ``dns.rrset.RRset`` or a ``(dns.name.Name, dns.rdataset.Rdataset)`` tuple.
434
435 *keys* is the key dictionary, used to find the DNSKEY associated with
436 a given name. The dictionary is keyed by a ``dns.name.Name``, and has
437 ``dns.node.Node`` or ``dns.rdataset.Rdataset`` values.
438
439 *origin* is a ``dns.name.Name``, the origin to use for relative names.
440
441 *now* is an ``int``, the time to use when validating the signatures,
442 in seconds since the UNIX epoch. The default is the current time.
392443 """
393444
394445 if isinstance(origin, string_types):
407458 rrsigrdataset = rrsigset
408459
409460 rrname = rrname.choose_relativity(origin)
410 rrsigname = rrname.choose_relativity(origin)
461 rrsigname = rrsigname.choose_relativity(origin)
411462 if rrname != rrsigname:
412463 raise ValidationFailure("owner names do not match")
413464
421472
422473
423474 def _need_pycrypto(*args, **kwargs):
424 raise NotImplementedError("DNSSEC validation requires pycrypto")
475 raise NotImplementedError("DNSSEC validation requires pycryptodome/pycryptodomex")
476
425477
426478 try:
427 import Crypto.PublicKey.RSA
428 import Crypto.PublicKey.DSA
429 import Crypto.Util.number
430 validate = _validate
431 validate_rrsig = _validate_rrsig
432 _have_pycrypto = True
479 try:
480 # test we're using pycryptodome, not pycrypto (which misses SHA1 for example)
481 from Crypto.Hash import MD5, SHA1, SHA256, SHA384, SHA512
482 from Crypto.PublicKey import RSA as CryptoRSA, DSA as CryptoDSA
483 from Crypto.Signature import pkcs1_15, DSS
484 from Crypto.Util import number
485 except ImportError:
486 from Cryptodome.Hash import MD5, SHA1, SHA256, SHA384, SHA512
487 from Cryptodome.PublicKey import RSA as CryptoRSA, DSA as CryptoDSA
488 from Cryptodome.Signature import pkcs1_15, DSS
489 from Cryptodome.Util import number
433490 except ImportError:
434491 validate = _need_pycrypto
435492 validate_rrsig = _need_pycrypto
436493 _have_pycrypto = False
437
438 try:
439 import ecdsa
440 import ecdsa.ecdsa
441 import ecdsa.ellipticcurve
442 import ecdsa.keys
443 _have_ecdsa = True
444
445 class ECKeyWrapper(object):
446
447 def __init__(self, key, key_len):
448 self.key = key
449 self.key_len = key_len
450
451 def verify(self, digest, sig):
452 diglong = Crypto.Util.number.bytes_to_long(digest)
453 return self.key.pubkey.verifies(diglong, sig)
454
455 except ImportError:
456494 _have_ecdsa = False
495 else:
496 validate = _validate
497 validate_rrsig = _validate_rrsig
498 _have_pycrypto = True
499
500 try:
501 import ecdsa
502 import ecdsa.ecdsa
503 import ecdsa.ellipticcurve
504 import ecdsa.keys
505 except ImportError:
506 _have_ecdsa = False
507 else:
508 _have_ecdsa = True
509
510 class ECKeyWrapper(object):
511
512 def __init__(self, key, key_len):
513 self.key = key
514 self.key_len = key_len
515
516 def verify(self, digest, sig):
517 diglong = number.bytes_to_long(digest)
518 return self.key.pubkey.verifies(diglong, sig)
0 from typing import Union, Dict, Tuple, Optional
1 from . import rdataset, rrset, exception, name, rdtypes, rdata, node
2 import dns.rdtypes.ANY.DS as DS
3 import dns.rdtypes.ANY.DNSKEY as DNSKEY
4
5 _have_ecdsa : bool
6 _have_pycrypto : bool
7
8 def validate_rrsig(rrset : Union[Tuple[name.Name, rdataset.Rdataset], rrset.RRset], rrsig : rdata.Rdata, keys : Dict[name.Name, Union[node.Node, rdataset.Rdataset]], origin : Optional[name.Name] = None, now : Optional[int] = None) -> None:
9 ...
10
11 def validate(rrset: Union[Tuple[name.Name, rdataset.Rdataset], rrset.RRset], rrsigset : Union[Tuple[name.Name, rdataset.Rdataset], rrset.RRset], keys : Dict[name.Name, Union[node.Node, rdataset.Rdataset]], origin=None, now=None) -> None:
12 ...
13
14 class ValidationFailure(exception.DNSException):
15 ...
16
17 def make_ds(name : name.Name, key : DNSKEY.DNSKEY, algorithm : str, origin : Optional[name.Name] = None) -> DS.DS:
18 ...
0 # Copyright (C) 2006, 2007, 2009, 2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2006-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """DNS E.164 helpers
16
17 @var public_enum_domain: The DNS public ENUM domain, e164.arpa.
18 @type public_enum_domain: dns.name.Name object
19 """
20
17 """DNS E.164 helpers."""
2118
2219 import dns.exception
2320 import dns.name
2421 import dns.resolver
25 from ._compat import string_types
22 from ._compat import string_types, maybe_decode
2623
24 #: The public E.164 domain.
2725 public_enum_domain = dns.name.from_text('e164.arpa.')
2826
2927
3028 def from_e164(text, origin=public_enum_domain):
3129 """Convert an E.164 number in textual form into a Name object whose
3230 value is the ENUM domain name for that number.
33 @param text: an E.164 number in textual form.
34 @type text: str
35 @param origin: The domain in which the number should be constructed.
36 The default is e164.arpa.
37 @type origin: dns.name.Name object or None
38 @rtype: dns.name.Name object
31
32 Non-digits in the text are ignored, i.e. "16505551212",
33 "+1.650.555.1212" and "1 (650) 555-1212" are all the same.
34
35 *text*, a ``text``, is an E.164 number in textual form.
36
37 *origin*, a ``dns.name.Name``, the domain in which the number
38 should be constructed. The default is ``e164.arpa.``.
39
40 Returns a ``dns.name.Name``.
3941 """
42
4043 parts = [d for d in text if d.isdigit()]
4144 parts.reverse()
4245 return dns.name.from_text('.'.join(parts), origin=origin)
4447
4548 def to_e164(name, origin=public_enum_domain, want_plus_prefix=True):
4649 """Convert an ENUM domain name into an E.164 number.
47 @param name: the ENUM domain name.
48 @type name: dns.name.Name object.
49 @param origin: A domain containing the ENUM domain name. The
50 name is relativized to this domain before being converted to text.
51 @type origin: dns.name.Name object or None
52 @param want_plus_prefix: if True, add a '+' to the beginning of the
53 returned number.
54 @rtype: str
50
51 Note that dnspython does not have any information about preferred
52 number formats within national numbering plans, so all numbers are
53 emitted as a simple string of digits, prefixed by a '+' (unless
54 *want_plus_prefix* is ``False``).
55
56 *name* is a ``dns.name.Name``, the ENUM domain name.
57
58 *origin* is a ``dns.name.Name``, a domain containing the ENUM
59 domain name. The name is relativized to this domain before being
60 converted to text. If ``None``, no relativization is done.
61
62 *want_plus_prefix* is a ``bool``. If True, add a '+' to the beginning of
63 the returned number.
64
65 Returns a ``text``.
66
5567 """
5668 if origin is not None:
5769 name = name.relativize(origin)
6274 text = b''.join(dlabels)
6375 if want_plus_prefix:
6476 text = b'+' + text
65 return text
77 return maybe_decode(text)
6678
6779
6880 def query(number, domains, resolver=None):
6981 """Look for NAPTR RRs for the specified number in the specified domains.
7082
7183 e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.'])
84
85 *number*, a ``text`` is the number to look for.
86
87 *domains* is an iterable containing ``dns.name.Name`` values.
88
89 *resolver*, a ``dns.resolver.Resolver``, is the resolver to use. If
90 ``None``, the default resolver is used.
7291 """
92
7393 if resolver is None:
7494 resolver = dns.resolver.get_default_resolver()
7595 e_nx = dns.resolver.NXDOMAIN()
0 from typing import Optional, Iterable
1 from . import name, resolver
2 def from_e164(text : str, origin=name.Name(".")) -> name.Name:
3 ...
4
5 def to_e164(name : name.Name, origin : Optional[name.Name] = None, want_plus_prefix=True) -> str:
6 ...
7
8 def query(number : str, domains : Iterable[str], resolver : Optional[resolver.Resolver] = None) -> resolver.Answer:
9 ...
0 # Copyright (C) 2009, 2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2009-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1416
1517 """EDNS Options"""
1618
19 from __future__ import absolute_import
20
21 import math
22 import struct
23
24 import dns.inet
25
26 #: NSID
1727 NSID = 3
18
28 #: DAU
29 DAU = 5
30 #: DHU
31 DHU = 6
32 #: N3U
33 N3U = 7
34 #: ECS (client-subnet)
35 ECS = 8
36 #: EXPIRE
37 EXPIRE = 9
38 #: COOKIE
39 COOKIE = 10
40 #: KEEPALIVE
41 KEEPALIVE = 11
42 #: PADDING
43 PADDING = 12
44 #: CHAIN
45 CHAIN = 13
1946
2047 class Option(object):
2148
22 """Base class for all EDNS option types.
23 """
49 """Base class for all EDNS option types."""
2450
2551 def __init__(self, otype):
2652 """Initialize an option.
27 @param otype: The rdata type
28 @type otype: int
53
54 *otype*, an ``int``, is the option type.
2955 """
3056 self.otype = otype
3157
3662
3763 @classmethod
3864 def from_wire(cls, otype, wire, current, olen):
39 """Build an EDNS option object from wire format
40
41 @param otype: The option type
42 @type otype: int
43 @param wire: The wire-format message
44 @type wire: string
45 @param current: The offset in wire of the beginning of the rdata.
46 @type current: int
47 @param olen: The length of the wire-format option data
48 @type olen: int
49 @rtype: dns.edns.Option instance"""
65 """Build an EDNS option object from wire format.
66
67 *otype*, an ``int``, is the option type.
68
69 *wire*, a ``binary``, is the wire-format message.
70
71 *current*, an ``int``, is the offset in *wire* of the beginning
72 of the rdata.
73
74 *olen*, an ``int``, is the length of the wire-format option data
75
76 Returns a ``dns.edns.Option``.
77 """
78
5079 raise NotImplementedError
5180
5281 def _cmp(self, other):
5382 """Compare an EDNS option with another option of the same type.
54 Return < 0 if self < other, 0 if self == other,
55 and > 0 if self > other.
83
84 Returns < 0 if < *other*, 0 if == *other*, and > 0 if > *other*.
5685 """
5786 raise NotImplementedError
5887
97126
98127 class GenericOption(Option):
99128
100 """Generate Rdata Class
129 """Generic Option Class
101130
102131 This class is used for EDNS option types for which we have no better
103132 implementation.
109138
110139 def to_wire(self, file):
111140 file.write(self.data)
141
142 def to_text(self):
143 return "Generic %d" % self.otype
112144
113145 @classmethod
114146 def from_wire(cls, otype, wire, current, olen):
121153 return 1
122154 return -1
123155
156
157 class ECSOption(Option):
158 """EDNS Client Subnet (ECS, RFC7871)"""
159
160 def __init__(self, address, srclen=None, scopelen=0):
161 """*address*, a ``text``, is the client address information.
162
163 *srclen*, an ``int``, the source prefix length, which is the
164 leftmost number of bits of the address to be used for the
165 lookup. The default is 24 for IPv4 and 56 for IPv6.
166
167 *scopelen*, an ``int``, the scope prefix length. This value
168 must be 0 in queries, and should be set in responses.
169 """
170
171 super(ECSOption, self).__init__(ECS)
172 af = dns.inet.af_for_address(address)
173
174 if af == dns.inet.AF_INET6:
175 self.family = 2
176 if srclen is None:
177 srclen = 56
178 elif af == dns.inet.AF_INET:
179 self.family = 1
180 if srclen is None:
181 srclen = 24
182 else:
183 raise ValueError('Bad ip family')
184
185 self.address = address
186 self.srclen = srclen
187 self.scopelen = scopelen
188
189 addrdata = dns.inet.inet_pton(af, address)
190 nbytes = int(math.ceil(srclen/8.0))
191
192 # Truncate to srclen and pad to the end of the last octet needed
193 # See RFC section 6
194 self.addrdata = addrdata[:nbytes]
195 nbits = srclen % 8
196 if nbits != 0:
197 last = struct.pack('B', ord(self.addrdata[-1:]) & (0xff << nbits))
198 self.addrdata = self.addrdata[:-1] + last
199
200 def to_text(self):
201 return "ECS {}/{} scope/{}".format(self.address, self.srclen,
202 self.scopelen)
203
204 def to_wire(self, file):
205 file.write(struct.pack('!H', self.family))
206 file.write(struct.pack('!BB', self.srclen, self.scopelen))
207 file.write(self.addrdata)
208
209 @classmethod
210 def from_wire(cls, otype, wire, cur, olen):
211 family, src, scope = struct.unpack('!HBB', wire[cur:cur+4])
212 cur += 4
213
214 addrlen = int(math.ceil(src/8.0))
215
216 if family == 1:
217 af = dns.inet.AF_INET
218 pad = 4 - addrlen
219 elif family == 2:
220 af = dns.inet.AF_INET6
221 pad = 16 - addrlen
222 else:
223 raise ValueError('unsupported family')
224
225 addr = dns.inet.inet_ntop(af, wire[cur:cur+addrlen] + b'\x00' * pad)
226 return cls(addr, src, scope)
227
228 def _cmp(self, other):
229 if self.addrdata == other.addrdata:
230 return 0
231 if self.addrdata > other.addrdata:
232 return 1
233 return -1
234
124235 _type_to_class = {
236 ECS: ECSOption
125237 }
126238
127
128239 def get_option_class(otype):
240 """Return the class for the specified option type.
241
242 The GenericOption class is used if a more specific class is not
243 known.
244 """
245
129246 cls = _type_to_class.get(otype)
130247 if cls is None:
131248 cls = GenericOption
133250
134251
135252 def option_from_wire(otype, wire, current, olen):
136 """Build an EDNS option object from wire format
137
138 @param otype: The option type
139 @type otype: int
140 @param wire: The wire-format message
141 @type wire: string
142 @param current: The offset in wire of the beginning of the rdata.
143 @type current: int
144 @param olen: The length of the wire-format option data
145 @type olen: int
146 @rtype: dns.edns.Option instance"""
253 """Build an EDNS option object from wire format.
254
255 *otype*, an ``int``, is the option type.
256
257 *wire*, a ``binary``, is the wire-format message.
258
259 *current*, an ``int``, is the offset in *wire* of the beginning
260 of the rdata.
261
262 *olen*, an ``int``, is the length of the wire-format option data
263
264 Returns an instance of a subclass of ``dns.edns.Option``.
265 """
147266
148267 cls = get_option_class(otype)
149268 return cls.from_wire(otype, wire, current, olen)
0 # Copyright (C) 2009, 2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2009-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
2325
2426
2527 class EntropyPool(object):
28
29 # This is an entropy pool for Python implementations that do not
30 # have a working SystemRandom. I'm not sure there are any, but
31 # leaving this code doesn't hurt anything as the library code
32 # is used if present.
2633
2734 def __init__(self, seed=None):
2835 self.pool_index = 0
0 from typing import Optional
1 from random import SystemRandom
2
3 system_random : Optional[SystemRandom]
4
5 def random_16() -> int:
6 pass
7
8 def between(first: int, last: int) -> int:
9 pass
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """Common DNS Exceptions."""
17 """Common DNS Exceptions.
1618
19 Dnspython modules may also define their own exceptions, which will
20 always be subclasses of ``DNSException``.
21 """
1722
1823 class DNSException(Exception):
19
2024 """Abstract base class shared by all dnspython exceptions.
2125
2226 It supports two basic modes of operation:
2327
24 a) Old/compatible mode is used if __init__ was called with
25 empty **kwargs.
26 In compatible mode all *args are passed to standard Python Exception class
27 as before and all *args are printed by standard __str__ implementation.
28 Class variable msg (or doc string if msg is None) is returned from str()
29 if *args is empty.
28 a) Old/compatible mode is used if ``__init__`` was called with
29 empty *kwargs*. In compatible mode all *args* are passed
30 to the standard Python Exception class as before and all *args* are
31 printed by the standard ``__str__`` implementation. Class variable
32 ``msg`` (or doc string if ``msg`` is ``None``) is returned from ``str()``
33 if *args* is empty.
3034
31 b) New/parametrized mode is used if __init__ was called with
32 non-empty **kwargs.
33 In the new mode *args has to be empty and all kwargs has to exactly match
34 set in class variable self.supp_kwargs. All kwargs are stored inside
35 self.kwargs and used in new __str__ implementation to construct
36 formatted message based on self.fmt string.
35 b) New/parametrized mode is used if ``__init__`` was called with
36 non-empty *kwargs*.
37 In the new mode *args* must be empty and all kwargs must match
38 those set in class variable ``supp_kwargs``. All kwargs are stored inside
39 ``self.kwargs`` and used in a new ``__str__`` implementation to construct
40 a formatted message based on the ``fmt`` class variable, a ``string``.
3741
38 In the simplest case it is enough to override supp_kwargs and fmt
39 class variables to get nice parametrized messages.
42 In the simplest case it is enough to override the ``supp_kwargs``
43 and ``fmt`` class variables to get nice parametrized messages.
4044 """
45
4146 msg = None # non-parametrized message
4247 supp_kwargs = set() # accepted parameters for _fmt_kwargs (sanity check)
4348 fmt = None # message parametrized with results from _fmt_kwargs
101106
102107
103108 class FormError(DNSException):
104
105109 """DNS message is malformed."""
106110
107111
108112 class SyntaxError(DNSException):
109
110113 """Text input is malformed."""
111114
112115
113116 class UnexpectedEnd(SyntaxError):
114
115117 """Text input ended unexpectedly."""
116118
117119
118120 class TooBig(DNSException):
119
120121 """The DNS message is too big."""
121122
122123
123124 class Timeout(DNSException):
124
125125 """The DNS operation timed out."""
126 supp_kwargs = set(['timeout'])
126 supp_kwargs = {'timeout'}
127127 fmt = "The DNS operation timed out after {timeout} seconds"
0 from typing import Set, Optional, Dict
1
2 class DNSException(Exception):
3 supp_kwargs : Set[str]
4 kwargs : Optional[Dict]
5
6 class SyntaxError(DNSException): ...
7 class FormError(DNSException): ...
8 class Timeout(DNSException): ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1618
1719 # Standard DNS flags
1820
21 #: Query Response
1922 QR = 0x8000
23 #: Authoritative Answer
2024 AA = 0x0400
25 #: Truncated Response
2126 TC = 0x0200
27 #: Recursion Desired
2228 RD = 0x0100
29 #: Recursion Available
2330 RA = 0x0080
31 #: Authentic Data
2432 AD = 0x0020
33 #: Checking Disabled
2534 CD = 0x0010
2635
2736 # EDNS flags
2837
38 #: DNSSEC answer OK
2939 DO = 0x8000
3040
3141 _by_text = {
4757 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
4858 # would cause the mappings not to be true inverses.
4959
50 _by_value = dict((y, x) for x, y in _by_text.items())
60 _by_value = {y: x for x, y in _by_text.items()}
5161
52 _edns_by_value = dict((y, x) for x, y in _edns_by_text.items())
62 _edns_by_value = {y: x for x, y in _edns_by_text.items()}
5363
5464
5565 def _order_flags(table):
8292 def from_text(text):
8393 """Convert a space-separated list of flag text values into a flags
8494 value.
85 @rtype: int"""
95
96 Returns an ``int``
97 """
8698
8799 return _from_text(text, _by_text)
88100
90102 def to_text(flags):
91103 """Convert a flags value into a space-separated list of flag text
92104 values.
93 @rtype: string"""
105
106 Returns a ``text``.
107 """
94108
95109 return _to_text(flags, _by_value, _flags_order)
96110
98112 def edns_from_text(text):
99113 """Convert a space-separated list of EDNS flag text values into a EDNS
100114 flags value.
101 @rtype: int"""
115
116 Returns an ``int``
117 """
102118
103119 return _from_text(text, _edns_by_text)
104120
106122 def edns_to_text(flags):
107123 """Convert an EDNS flags value into a space-separated list of EDNS flag
108124 text values.
109 @rtype: string"""
125
126 Returns a ``text``.
127 """
110128
111129 return _to_text(flags, _edns_by_value, _edns_flags_order)
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2012-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1618
1719 import dns
1820
19
2021 def from_text(text):
21 """Convert the text form of a range in a GENERATE statement to an
22 """Convert the text form of a range in a ``$GENERATE`` statement to an
2223 integer.
2324
24 @param text: the textual range
25 @type text: string
26 @return: The start, stop and step values.
27 @rtype: tuple
25 *text*, a ``str``, the textual range in ``$GENERATE`` form.
26
27 Returns a tuple of three ``int`` values ``(start, stop, step)``.
2828 """
29
2930 # TODO, figure out the bounds on start, stop and step.
30
3131 step = 1
3232 cur = ''
3333 state = 0
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1517 """Hashing backwards compatibility wrapper"""
1618
1719 import hashlib
20 import warnings
1821
22 warnings.warn(
23 "dns.hash module will be removed in future versions. Please use hashlib instead.",
24 DeprecationWarning)
1925
2026 hashes = {}
2127 hashes['MD5'] = hashlib.md5
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1921 import dns.ipv4
2022 import dns.ipv6
2123
24 from ._compat import maybe_ord
2225
2326 # We assume that AF_INET is always defined.
2427
3740 def inet_pton(family, text):
3841 """Convert the textual form of a network address into its binary form.
3942
40 @param family: the address family
41 @type family: int
42 @param text: the textual address
43 @type text: string
44 @raises NotImplementedError: the address family specified is not
43 *family* is an ``int``, the address family.
44
45 *text* is a ``text``, the textual address.
46
47 Raises ``NotImplementedError`` if the address family specified is not
4548 implemented.
46 @rtype: string
49
50 Returns a ``binary``.
4751 """
4852
4953 if family == AF_INET:
5761 def inet_ntop(family, address):
5862 """Convert the binary form of a network address into its textual form.
5963
60 @param family: the address family
61 @type family: int
62 @param address: the binary address
63 @type address: string
64 @raises NotImplementedError: the address family specified is not
64 *family* is an ``int``, the address family.
65
66 *address* is a ``binary``, the network address in binary form.
67
68 Raises ``NotImplementedError`` if the address family specified is not
6569 implemented.
66 @rtype: string
70
71 Returns a ``text``.
6772 """
73
6874 if family == AF_INET:
6975 return dns.ipv4.inet_ntoa(address)
7076 elif family == AF_INET6:
7682 def af_for_address(text):
7783 """Determine the address family of a textual-form network address.
7884
79 @param text: the textual address
80 @type text: string
81 @raises ValueError: the address family cannot be determined from the input.
82 @rtype: int
85 *text*, a ``text``, the textual address.
86
87 Raises ``ValueError`` if the address family cannot be determined
88 from the input.
89
90 Returns an ``int``.
8391 """
92
8493 try:
8594 dns.ipv4.inet_aton(text)
8695 return AF_INET
95104 def is_multicast(text):
96105 """Is the textual-form network address a multicast address?
97106
98 @param text: the textual address
99 @raises ValueError: the address family cannot be determined from the input.
100 @rtype: bool
107 *text*, a ``text``, the textual address.
108
109 Raises ``ValueError`` if the address family cannot be determined
110 from the input.
111
112 Returns a ``bool``.
101113 """
114
102115 try:
103 first = ord(dns.ipv4.inet_aton(text)[0])
116 first = maybe_ord(dns.ipv4.inet_aton(text)[0])
104117 return first >= 224 and first <= 239
105118 except Exception:
106119 try:
107 first = ord(dns.ipv6.inet_aton(text)[0])
120 first = maybe_ord(dns.ipv6.inet_aton(text)[0])
108121 return first == 255
109122 except Exception:
110123 raise ValueError
0 from typing import Union
1 from socket import AddressFamily
2
3 AF_INET6 : Union[int, AddressFamily]
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
2022 from ._compat import binary_type
2123
2224 def inet_ntoa(address):
23 """Convert an IPv4 address in network form to text form.
25 """Convert an IPv4 address in binary form to text form.
2426
25 @param address: The IPv4 address
26 @type address: string
27 @returns: string
27 *address*, a ``binary``, the IPv4 address in binary form.
28
29 Returns a ``text``.
2830 """
31
2932 if len(address) != 4:
3033 raise dns.exception.SyntaxError
3134 if not isinstance(address, bytearray):
3235 address = bytearray(address)
33 return (u'%u.%u.%u.%u' % (address[0], address[1],
34 address[2], address[3])).encode()
36 return ('%u.%u.%u.%u' % (address[0], address[1],
37 address[2], address[3]))
3538
3639 def inet_aton(text):
37 """Convert an IPv4 address in text form to network form.
40 """Convert an IPv4 address in text form to binary form.
3841
39 @param text: The IPv4 address
40 @type text: string
41 @returns: string
42 *text*, a ``text``, the IPv4 address in textual form.
43
44 Returns a ``binary``.
4245 """
46
4347 if not isinstance(text, binary_type):
4448 text = text.encode()
4549 parts = text.split(b'.')
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
2123 import dns.ipv4
2224 from ._compat import xrange, binary_type, maybe_decode
2325
24 _leading_zero = re.compile(b'0+([0-9a-f]+)')
26 _leading_zero = re.compile(r'0+([0-9a-f]+)')
2527
2628 def inet_ntoa(address):
27 """Convert a network format IPv6 address into text.
29 """Convert an IPv6 address in binary form to text form.
2830
29 @param address: the binary address
30 @type address: string
31 @rtype: string
32 @raises ValueError: the address isn't 16 bytes long
31 *address*, a ``binary``, the IPv6 address in binary form.
32
33 Raises ``ValueError`` if the address isn't 16 bytes long.
34 Returns a ``text``.
3335 """
3436
3537 if len(address) != 16:
3941 i = 0
4042 l = len(hex)
4143 while i < l:
42 chunk = hex[i : i + 4]
44 chunk = maybe_decode(hex[i : i + 4])
4345 # strip leading zeros. we do this with an re instead of
4446 # with lstrip() because lstrip() didn't support chars until
4547 # python 2.2.2
5658 start = -1
5759 last_was_zero = False
5860 for i in xrange(8):
59 if chunks[i] != b'0':
61 if chunks[i] != '0':
6062 if last_was_zero:
6163 end = i
6264 current_len = end - start
7678 if best_len > 1:
7779 if best_start == 0 and \
7880 (best_len == 6 or
79 best_len == 5 and chunks[5] == b'ffff'):
81 best_len == 5 and chunks[5] == 'ffff'):
8082 # We have an embedded IPv4 address
8183 if best_len == 6:
82 prefix = b'::'
84 prefix = '::'
8385 else:
84 prefix = b'::ffff:'
86 prefix = '::ffff:'
8587 hex = prefix + dns.ipv4.inet_ntoa(address[12:])
8688 else:
87 hex = b':'.join(chunks[:best_start]) + b'::' + \
88 b':'.join(chunks[best_start + best_len:])
89 hex = ':'.join(chunks[:best_start]) + '::' + \
90 ':'.join(chunks[best_start + best_len:])
8991 else:
90 hex = b':'.join(chunks)
91 return maybe_decode(hex)
92 hex = ':'.join(chunks)
93 return hex
9294
93 _v4_ending = re.compile(b'(.*):(\d+\.\d+\.\d+\.\d+)$')
94 _colon_colon_start = re.compile(b'::.*')
95 _colon_colon_end = re.compile(b'.*::$')
95 _v4_ending = re.compile(br'(.*):(\d+\.\d+\.\d+\.\d+)$')
96 _colon_colon_start = re.compile(br'::.*')
97 _colon_colon_end = re.compile(br'.*::$')
9698
9799 def inet_aton(text):
98 """Convert a text format IPv6 address into network format.
100 """Convert an IPv6 address in text form to binary form.
99101
100 @param text: the textual address
101 @type text: string
102 @rtype: string
103 @raises dns.exception.SyntaxError: the text was not properly formatted
102 *text*, a ``text``, the IPv6 address in textual form.
103
104 Returns a ``binary``.
104105 """
105106
106107 #
117118 m = _v4_ending.match(text)
118119 if not m is None:
119120 b = bytearray(dns.ipv4.inet_aton(m.group(2)))
120 text = (u"%s:%02x%02x:%02x%02x" % (m.group(1).decode(), b[0], b[1],
121 b[2], b[3])).encode()
121 text = (u"{}:{:02x}{:02x}:{:02x}{:02x}".format(m.group(1).decode(),
122 b[0], b[1], b[2],
123 b[3])).encode()
122124 #
123125 # Try to turn '::<whatever>' into ':<whatever>'; if no match try to
124126 # turn '<whatever>::' into '<whatever>:'
168170 _mapped_prefix = b'\x00' * 10 + b'\xff\xff'
169171
170172 def is_mapped(address):
173 """Is the specified address a mapped IPv4 address?
174
175 *address*, a ``binary`` is an IPv6 address in binary form.
176
177 Returns a ``bool``.
178 """
179
171180 return address.startswith(_mapped_prefix)
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
3941
4042
4143 class ShortHeader(dns.exception.FormError):
42
4344 """The DNS packet passed to from_wire() is too short."""
4445
4546
4647 class TrailingJunk(dns.exception.FormError):
47
4848 """The DNS packet passed to from_wire() has extra junk at the end of it."""
4949
5050
5151 class UnknownHeaderField(dns.exception.DNSException):
52
5352 """The header field name was not recognized when converting from text
5453 into a message."""
5554
5655
5756 class BadEDNS(dns.exception.FormError):
58
59 """OPT record occurred somewhere other than the start of
57 """An OPT record occurred somewhere other than the start of
6058 the additional data section."""
6159
6260
6361 class BadTSIG(dns.exception.FormError):
64
6562 """A TSIG record occurred somewhere other than the end of
6663 the additional data section."""
6764
6865
6966 class UnknownTSIGKey(dns.exception.DNSException):
70
7167 """A TSIG with an unknown key was received."""
7268
7369
70 #: The question section number
71 QUESTION = 0
72
73 #: The answer section number
74 ANSWER = 1
75
76 #: The authority section number
77 AUTHORITY = 2
78
79 #: The additional section number
80 ADDITIONAL = 3
81
7482 class Message(object):
75
76 """A DNS message.
77
78 @ivar id: The query id; the default is a randomly chosen id.
79 @type id: int
80 @ivar flags: The DNS flags of the message. @see: RFC 1035 for an
81 explanation of these flags.
82 @type flags: int
83 @ivar question: The question section.
84 @type question: list of dns.rrset.RRset objects
85 @ivar answer: The answer section.
86 @type answer: list of dns.rrset.RRset objects
87 @ivar authority: The authority section.
88 @type authority: list of dns.rrset.RRset objects
89 @ivar additional: The additional data section.
90 @type additional: list of dns.rrset.RRset objects
91 @ivar edns: The EDNS level to use. The default is -1, no Edns.
92 @type edns: int
93 @ivar ednsflags: The EDNS flags
94 @type ednsflags: long
95 @ivar payload: The EDNS payload size. The default is 0.
96 @type payload: int
97 @ivar options: The EDNS options
98 @type options: list of dns.edns.Option objects
99 @ivar request_payload: The associated request's EDNS payload size.
100 @type request_payload: int
101 @ivar keyring: The TSIG keyring to use. The default is None.
102 @type keyring: dict
103 @ivar keyname: The TSIG keyname to use. The default is None.
104 @type keyname: dns.name.Name object
105 @ivar keyalgorithm: The TSIG algorithm to use; defaults to
106 dns.tsig.default_algorithm. Constants for TSIG algorithms are defined
107 in dns.tsig, and the currently implemented algorithms are
108 HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
109 HMAC_SHA512.
110 @type keyalgorithm: string
111 @ivar request_mac: The TSIG MAC of the request message associated with
112 this message; used when validating TSIG signatures. @see: RFC 2845 for
113 more information on TSIG fields.
114 @type request_mac: string
115 @ivar fudge: TSIG time fudge; default is 300 seconds.
116 @type fudge: int
117 @ivar original_id: TSIG original id; defaults to the message's id
118 @type original_id: int
119 @ivar tsig_error: TSIG error code; default is 0.
120 @type tsig_error: int
121 @ivar other_data: TSIG other data.
122 @type other_data: string
123 @ivar mac: The TSIG MAC for this message.
124 @type mac: string
125 @ivar xfr: Is the message being used to contain the results of a DNS
126 zone transfer? The default is False.
127 @type xfr: bool
128 @ivar origin: The origin of the zone in messages which are used for
129 zone transfers or for DNS dynamic updates. The default is None.
130 @type origin: dns.name.Name object
131 @ivar tsig_ctx: The TSIG signature context associated with this
132 message. The default is None.
133 @type tsig_ctx: hmac.HMAC object
134 @ivar had_tsig: Did the message decoded from wire format have a TSIG
135 signature?
136 @type had_tsig: bool
137 @ivar multi: Is this message part of a multi-message sequence? The
138 default is false. This variable is used when validating TSIG signatures
139 on messages which are part of a zone transfer.
140 @type multi: bool
141 @ivar first: Is this message standalone, or the first of a multi
142 message sequence? This variable is used when validating TSIG signatures
143 on messages which are part of a zone transfer.
144 @type first: bool
145 @ivar index: An index of rrsets in the message. The index key is
146 (section, name, rdclass, rdtype, covers, deleting). Indexing can be
147 disabled by setting the index to None.
148 @type index: dict
149 """
83 """A DNS message."""
15084
15185 def __init__(self, id=None):
15286 if id is None:
166100 self.keyring = None
167101 self.keyname = None
168102 self.keyalgorithm = dns.tsig.default_algorithm
169 self.request_mac = ''
170 self.other_data = ''
103 self.request_mac = b''
104 self.other_data = b''
171105 self.tsig_error = 0
172106 self.fudge = 300
173107 self.original_id = self.id
174 self.mac = ''
108 self.mac = b''
175109 self.xfr = False
176110 self.origin = None
177111 self.tsig_ctx = None
189123 def to_text(self, origin=None, relativize=True, **kw):
190124 """Convert the message to text.
191125
192 The I{origin}, I{relativize}, and any other keyword
193 arguments are passed to the rrset to_wire() method.
194
195 @rtype: string
126 The *origin*, *relativize*, and any other keyword
127 arguments are passed to the RRset ``to_wire()`` method.
128
129 Returns a ``text``.
196130 """
197131
198132 s = StringIO()
208142 s.write(u'eflags %s\n' %
209143 dns.flags.edns_to_text(self.ednsflags))
210144 s.write(u'payload %d\n' % self.payload)
145 for opt in self.options:
146 s.write(u'option %s\n' % opt.to_text())
211147 is_update = dns.opcode.is_update(self.flags)
212148 if is_update:
213149 s.write(u';ZONE\n')
244180 def __eq__(self, other):
245181 """Two messages are equal if they have the same content in the
246182 header, question, answer, and authority sections.
247 @rtype: bool"""
183
184 Returns a ``bool``.
185 """
186
248187 if not isinstance(other, Message):
249188 return False
250189 if self.id != other.id:
272211 return True
273212
274213 def __ne__(self, other):
275 """Are two messages not equal?
276 @rtype: bool"""
277214 return not self.__eq__(other)
278215
279216 def is_response(self, other):
280 """Is other a response to self?
281 @rtype: bool"""
217 """Is this message a response to *other*?
218
219 Returns a ``bool``.
220 """
221
282222 if other.flags & dns.flags.QR == 0 or \
283223 self.id != other.id or \
284224 dns.opcode.from_flags(self.flags) != \
298238 return True
299239
300240 def section_number(self, section):
241 """Return the "section number" of the specified section for use
242 in indexing. The question section is 0, the answer section is 1,
243 the authority section is 2, and the additional section is 3.
244
245 *section* is one of the section attributes of this message.
246
247 Raises ``ValueError`` if the section isn't known.
248
249 Returns an ``int``.
250 """
251
301252 if section is self.question:
302 return 0
253 return QUESTION
303254 elif section is self.answer:
304 return 1
255 return ANSWER
305256 elif section is self.authority:
306 return 2
257 return AUTHORITY
307258 elif section is self.additional:
308 return 3
259 return ADDITIONAL
260 else:
261 raise ValueError('unknown section')
262
263 def section_from_number(self, number):
264 """Return the "section number" of the specified section for use
265 in indexing. The question section is 0, the answer section is 1,
266 the authority section is 2, and the additional section is 3.
267
268 *section* is one of the section attributes of this message.
269
270 Raises ``ValueError`` if the section isn't known.
271
272 Returns an ``int``.
273 """
274
275 if number == QUESTION:
276 return self.question
277 elif number == ANSWER:
278 return self.answer
279 elif number == AUTHORITY:
280 return self.authority
281 elif number == ADDITIONAL:
282 return self.additional
309283 else:
310284 raise ValueError('unknown section')
311285
314288 force_unique=False):
315289 """Find the RRset with the given attributes in the specified section.
316290
317 @param section: the section of the message to look in, e.g.
318 self.answer.
319 @type section: list of dns.rrset.RRset objects
320 @param name: the name of the RRset
321 @type name: dns.name.Name object
322 @param rdclass: the class of the RRset
323 @type rdclass: int
324 @param rdtype: the type of the RRset
325 @type rdtype: int
326 @param covers: the covers value of the RRset
327 @type covers: int
328 @param deleting: the deleting value of the RRset
329 @type deleting: int
330 @param create: If True, create the RRset if it is not found.
331 The created RRset is appended to I{section}.
332 @type create: bool
333 @param force_unique: If True and create is also True, create a
334 new RRset regardless of whether a matching RRset exists already.
335 @type force_unique: bool
336 @raises KeyError: the RRset was not found and create was False
337 @rtype: dns.rrset.RRset object"""
338
339 key = (self.section_number(section),
340 name, rdclass, rdtype, covers, deleting)
291 *section*, an ``int`` section number, or one of the section
292 attributes of this message. This specifies the
293 the section of the message to search. For example::
294
295 my_message.find_rrset(my_message.answer, name, rdclass, rdtype)
296 my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype)
297
298 *name*, a ``dns.name.Name``, the name of the RRset.
299
300 *rdclass*, an ``int``, the class of the RRset.
301
302 *rdtype*, an ``int``, the type of the RRset.
303
304 *covers*, an ``int`` or ``None``, the covers value of the RRset.
305 The default is ``None``.
306
307 *deleting*, an ``int`` or ``None``, the deleting value of the RRset.
308 The default is ``None``.
309
310 *create*, a ``bool``. If ``True``, create the RRset if it is not found.
311 The created RRset is appended to *section*.
312
313 *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``,
314 create a new RRset regardless of whether a matching RRset exists
315 already. The default is ``False``. This is useful when creating
316 DDNS Update messages, as order matters for them.
317
318 Raises ``KeyError`` if the RRset was not found and create was
319 ``False``.
320
321 Returns a ``dns.rrset.RRset object``.
322 """
323
324 if isinstance(section, int):
325 section_number = section
326 section = self.section_from_number(section_number)
327 else:
328 section_number = self.section_number(section)
329 key = (section_number, name, rdclass, rdtype, covers, deleting)
341330 if not force_unique:
342331 if self.index is not None:
343332 rrset = self.index.get(key)
362351
363352 If the RRset is not found, None is returned.
364353
365 @param section: the section of the message to look in, e.g.
366 self.answer.
367 @type section: list of dns.rrset.RRset objects
368 @param name: the name of the RRset
369 @type name: dns.name.Name object
370 @param rdclass: the class of the RRset
371 @type rdclass: int
372 @param rdtype: the type of the RRset
373 @type rdtype: int
374 @param covers: the covers value of the RRset
375 @type covers: int
376 @param deleting: the deleting value of the RRset
377 @type deleting: int
378 @param create: If True, create the RRset if it is not found.
379 The created RRset is appended to I{section}.
380 @type create: bool
381 @param force_unique: If True and create is also True, create a
382 new RRset regardless of whether a matching RRset exists already.
383 @type force_unique: bool
384 @rtype: dns.rrset.RRset object or None"""
354 *section*, an ``int`` section number, or one of the section
355 attributes of this message. This specifies the
356 the section of the message to search. For example::
357
358 my_message.get_rrset(my_message.answer, name, rdclass, rdtype)
359 my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype)
360
361 *name*, a ``dns.name.Name``, the name of the RRset.
362
363 *rdclass*, an ``int``, the class of the RRset.
364
365 *rdtype*, an ``int``, the type of the RRset.
366
367 *covers*, an ``int`` or ``None``, the covers value of the RRset.
368 The default is ``None``.
369
370 *deleting*, an ``int`` or ``None``, the deleting value of the RRset.
371 The default is ``None``.
372
373 *create*, a ``bool``. If ``True``, create the RRset if it is not found.
374 The created RRset is appended to *section*.
375
376 *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``,
377 create a new RRset regardless of whether a matching RRset exists
378 already. The default is ``False``. This is useful when creating
379 DDNS Update messages, as order matters for them.
380
381 Returns a ``dns.rrset.RRset object`` or ``None``.
382 """
385383
386384 try:
387385 rrset = self.find_rrset(section, name, rdclass, rdtype, covers,
394392 """Return a string containing the message in DNS compressed wire
395393 format.
396394
397 Additional keyword arguments are passed to the rrset to_wire()
395 Additional keyword arguments are passed to the RRset ``to_wire()``
398396 method.
399397
400 @param origin: The origin to be appended to any relative names.
401 @type origin: dns.name.Name object
402 @param max_size: The maximum size of the wire format output; default
403 is 0, which means 'the message's request payload, if nonzero, or
404 65536'.
405 @type max_size: int
406 @raises dns.exception.TooBig: max_size was exceeded
407 @rtype: string
398 *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended
399 to any relative names.
400
401 *max_size*, an ``int``, the maximum size of the wire format
402 output; default is 0, which means "the message's request
403 payload, if nonzero, or 65535".
404
405 Raises ``dns.exception.TooBig`` if *max_size* was exceeded.
406
407 Returns a ``binary``.
408408 """
409409
410410 if max_size == 0:
437437 return r.get_wire()
438438
439439 def use_tsig(self, keyring, keyname=None, fudge=300,
440 original_id=None, tsig_error=0, other_data='',
440 original_id=None, tsig_error=0, other_data=b'',
441441 algorithm=dns.tsig.default_algorithm):
442442 """When sending, a TSIG signature using the specified keyring
443443 and keyname should be added.
444444
445 @param keyring: The TSIG keyring to use; defaults to None.
446 @type keyring: dict
447 @param keyname: The name of the TSIG key to use; defaults to None.
448 The key must be defined in the keyring. If a keyring is specified
449 but a keyname is not, then the key used will be the first key in the
450 keyring. Note that the order of keys in a dictionary is not defined,
451 so applications should supply a keyname when a keyring is used, unless
452 they know the keyring contains only one key.
453 @type keyname: dns.name.Name or string
454 @param fudge: TSIG time fudge; default is 300 seconds.
455 @type fudge: int
456 @param original_id: TSIG original id; defaults to the message's id
457 @type original_id: int
458 @param tsig_error: TSIG error code; default is 0.
459 @type tsig_error: int
460 @param other_data: TSIG other data.
461 @type other_data: string
462 @param algorithm: The TSIG algorithm to use; defaults to
463 dns.tsig.default_algorithm
445 See the documentation of the Message class for a complete
446 description of the keyring dictionary.
447
448 *keyring*, a ``dict``, the TSIG keyring to use. If a
449 *keyring* is specified but a *keyname* is not, then the key
450 used will be the first key in the *keyring*. Note that the
451 order of keys in a dictionary is not defined, so applications
452 should supply a keyname when a keyring is used, unless they
453 know the keyring contains only one key.
454
455 *keyname*, a ``dns.name.Name`` or ``None``, the name of the TSIG key
456 to use; defaults to ``None``. The key must be defined in the keyring.
457
458 *fudge*, an ``int``, the TSIG time fudge.
459
460 *original_id*, an ``int``, the TSIG original id. If ``None``,
461 the message's id is used.
462
463 *tsig_error*, an ``int``, the TSIG error code.
464
465 *other_data*, a ``binary``, the TSIG other data.
466
467 *algorithm*, a ``dns.name.Name``, the TSIG algorithm to use.
464468 """
465469
466470 self.keyring = keyring
482486 def use_edns(self, edns=0, ednsflags=0, payload=1280, request_payload=None,
483487 options=None):
484488 """Configure EDNS behavior.
485 @param edns: The EDNS level to use. Specifying None, False, or -1
486 means 'do not use EDNS', and in this case the other parameters are
487 ignored. Specifying True is equivalent to specifying 0, i.e. 'use
488 EDNS0'.
489 @type edns: int or bool or None
490 @param ednsflags: EDNS flag values.
491 @type ednsflags: int
492 @param payload: The EDNS sender's payload field, which is the maximum
493 size of UDP datagram the sender can handle.
494 @type payload: int
495 @param request_payload: The EDNS payload size to use when sending
496 this message. If not specified, defaults to the value of payload.
497 @type request_payload: int or None
498 @param options: The EDNS options
499 @type options: None or list of dns.edns.Option objects
500 @see: RFC 2671
501 """
489
490 *edns*, an ``int``, is the EDNS level to use. Specifying
491 ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case
492 the other parameters are ignored. Specifying ``True`` is
493 equivalent to specifying 0, i.e. "use EDNS0".
494
495 *ednsflags*, an ``int``, the EDNS flag values.
496
497 *payload*, an ``int``, is the EDNS sender's payload field, which is the
498 maximum size of UDP datagram the sender can handle. I.e. how big
499 a response to this message can be.
500
501 *request_payload*, an ``int``, is the EDNS payload size to use when
502 sending this message. If not specified, defaults to the value of
503 *payload*.
504
505 *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
506 options.
507 """
508
502509 if edns is None or edns is False:
503510 edns = -1
504511 if edns is True:
524531
525532 def want_dnssec(self, wanted=True):
526533 """Enable or disable 'DNSSEC desired' flag in requests.
527 @param wanted: Is DNSSEC desired? If True, EDNS is enabled if
528 required, and then the DO bit is set. If False, the DO bit is
529 cleared if EDNS is enabled.
530 @type wanted: bool
531 """
534
535 *wanted*, a ``bool``. If ``True``, then DNSSEC data is
536 desired in the response, EDNS is enabled if required, and then
537 the DO bit is set. If ``False``, the DO bit is cleared if
538 EDNS is enabled.
539 """
540
532541 if wanted:
533542 if self.edns < 0:
534543 self.use_edns()
538547
539548 def rcode(self):
540549 """Return the rcode.
541 @rtype: int
550
551 Returns an ``int``.
542552 """
543553 return dns.rcode.from_flags(self.flags, self.ednsflags)
544554
545555 def set_rcode(self, rcode):
546556 """Set the rcode.
547 @param rcode: the rcode
548 @type rcode: int
557
558 *rcode*, an ``int``, is the rcode to set.
549559 """
550560 (value, evalue) = dns.rcode.to_flags(rcode)
551561 self.flags &= 0xFFF0
557567
558568 def opcode(self):
559569 """Return the opcode.
560 @rtype: int
570
571 Returns an ``int``.
561572 """
562573 return dns.opcode.from_flags(self.flags)
563574
564575 def set_opcode(self, opcode):
565576 """Set the opcode.
566 @param opcode: the opcode
567 @type opcode: int
577
578 *opcode*, an ``int``, is the opcode to set.
568579 """
569580 self.flags &= 0x87FF
570581 self.flags |= dns.opcode.to_flags(opcode)
574585
575586 """Wire format reader.
576587
577 @ivar wire: the wire-format message.
578 @type wire: string
579 @ivar message: The message object being built
580 @type message: dns.message.Message object
581 @ivar current: When building a message object from wire format, this
588 wire: a binary, is the wire-format message.
589 message: The message object being built
590 current: When building a message object from wire format, this
582591 variable contains the offset from the beginning of wire of the next octet
583592 to be read.
584 @type current: int
585 @ivar updating: Is the message a dynamic update?
586 @type updating: bool
587 @ivar one_rr_per_rrset: Put each RR into its own RRset?
588 @type one_rr_per_rrset: bool
589 @ivar ignore_trailing: Ignore trailing junk at end of request?
590 @type ignore_trailing: bool
591 @ivar zone_rdclass: The class of the zone in messages which are
593 updating: Is the message a dynamic update?
594 one_rr_per_rrset: Put each RR into its own RRset?
595 ignore_trailing: Ignore trailing junk at end of request?
596 zone_rdclass: The class of the zone in messages which are
592597 DNS dynamic updates.
593 @type zone_rdclass: int
594598 """
595599
596600 def __init__(self, wire, message, question_only=False,
605609 self.ignore_trailing = ignore_trailing
606610
607611 def _get_question(self, qcount):
608 """Read the next I{qcount} records from the wire data and add them to
612 """Read the next *qcount* records from the wire data and add them to
609613 the question section.
610 @param qcount: the number of questions in the message
611 @type qcount: int"""
614 """
612615
613616 if self.updating and qcount > 1:
614617 raise dns.exception.FormError
631634 def _get_section(self, section, count):
632635 """Read the next I{count} records from the wire data and add them to
633636 the specified section.
634 @param section: the section of the message to which to add records
635 @type section: list of dns.rrset.RRset objects
636 @param count: the number of records to read
637 @type count: int"""
637
638 section: the section of the message to which to add records
639 count: the number of records to read
640 """
638641
639642 if self.updating or self.one_rr_per_rrset:
640643 force_unique = True
752755 self.message.tsig_ctx.update(self.wire)
753756
754757
755 def from_wire(wire, keyring=None, request_mac='', xfr=False, origin=None,
758 def from_wire(wire, keyring=None, request_mac=b'', xfr=False, origin=None,
756759 tsig_ctx=None, multi=False, first=True,
757760 question_only=False, one_rr_per_rrset=False,
758761 ignore_trailing=False):
759762 """Convert a DNS wire format message into a message
760763 object.
761764
762 @param keyring: The keyring to use if the message is signed.
763 @type keyring: dict
764 @param request_mac: If the message is a response to a TSIG-signed request,
765 I{request_mac} should be set to the MAC of that request.
766 @type request_mac: string
767 @param xfr: Is this message part of a zone transfer?
768 @type xfr: bool
769 @param origin: If the message is part of a zone transfer, I{origin}
770 should be the origin name of the zone.
771 @type origin: dns.name.Name object
772 @param tsig_ctx: The ongoing TSIG context, used when validating zone
773 transfers.
774 @type tsig_ctx: hmac.HMAC object
775 @param multi: Is this message part of a multiple message sequence?
776 @type multi: bool
777 @param first: Is this message standalone, or the first of a multi
778 message sequence?
779 @type first: bool
780 @param question_only: Read only up to the end of the question section?
781 @type question_only: bool
782 @param one_rr_per_rrset: Put each RR into its own RRset
783 @type one_rr_per_rrset: bool
784 @param ignore_trailing: Ignore trailing junk at end of request?
785 @type ignore_trailing: bool
786 @raises ShortHeader: The message is less than 12 octets long.
787 @raises TrailingJunk: There were octets in the message past the end
788 of the proper DNS message.
789 @raises BadEDNS: An OPT record was in the wrong section, or occurred more
790 than once.
791 @raises BadTSIG: A TSIG record was not the last record of the additional
792 data section.
793 @rtype: dns.message.Message object"""
765 *keyring*, a ``dict``, the keyring to use if the message is signed.
766
767 *request_mac*, a ``binary``. If the message is a response to a
768 TSIG-signed request, *request_mac* should be set to the MAC of
769 that request.
770
771 *xfr*, a ``bool``, should be set to ``True`` if this message is part of
772 a zone transfer.
773
774 *origin*, a ``dns.name.Name`` or ``None``. If the message is part
775 of a zone transfer, *origin* should be the origin name of the
776 zone.
777
778 *tsig_ctx*, a ``hmac.HMAC`` objext, the ongoing TSIG context, used
779 when validating zone transfers.
780
781 *multi*, a ``bool``, should be set to ``True`` if this message
782 part of a multiple message sequence.
783
784 *first*, a ``bool``, should be set to ``True`` if this message is
785 stand-alone, or the first message in a multi-message sequence.
786
787 *question_only*, a ``bool``. If ``True``, read only up to
788 the end of the question section.
789
790 *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its
791 own RRset.
792
793 *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
794 junk at end of the message.
795
796 Raises ``dns.message.ShortHeader`` if the message is less than 12 octets
797 long.
798
799 Raises ``dns.messaage.TrailingJunk`` if there were octets in the message
800 past the end of the proper DNS message, and *ignore_trailing* is ``False``.
801
802 Raises ``dns.message.BadEDNS`` if an OPT record was in the
803 wrong section, or occurred more than once.
804
805 Raises ``dns.message.BadTSIG`` if a TSIG record was not the last
806 record of the additional data section.
807
808 Returns a ``dns.message.Message``.
809 """
794810
795811 m = Message(id=0)
796812 m.keyring = keyring
812828
813829 """Text format reader.
814830
815 @ivar tok: the tokenizer
816 @type tok: dns.tokenizer.Tokenizer object
817 @ivar message: The message object being built
818 @type message: dns.message.Message object
819 @ivar updating: Is the message a dynamic update?
820 @type updating: bool
821 @ivar zone_rdclass: The class of the zone in messages which are
831 tok: the tokenizer.
832 message: The message object being built.
833 updating: Is the message a dynamic update?
834 zone_rdclass: The class of the zone in messages which are
822835 DNS dynamic updates.
823 @type zone_rdclass: int
824 @ivar last_name: The most recently read name when building a message object
825 from text format.
826 @type last_name: dns.name.Name object
836 last_name: The most recently read name when building a message object.
827837 """
828838
829839 def __init__(self, text, message):
9961006 def from_text(text):
9971007 """Convert the text format message into a message object.
9981008
999 @param text: The text format message.
1000 @type text: string
1001 @raises UnknownHeaderField:
1002 @raises dns.exception.SyntaxError:
1003 @rtype: dns.message.Message object"""
1009 *text*, a ``text``, the text format message.
1010
1011 Raises ``dns.message.UnknownHeaderField`` if a header is unknown.
1012
1013 Raises ``dns.exception.SyntaxError`` if the text is badly formed.
1014
1015 Returns a ``dns.message.Message object``
1016 """
10041017
10051018 # 'text' can also be a file, but we don't publish that fact
10061019 # since it's an implementation detail. The official file
10171030 def from_file(f):
10181031 """Read the next text format message from the specified file.
10191032
1020 @param f: file or string. If I{f} is a string, it is treated
1021 as the name of a file to open.
1022 @raises UnknownHeaderField:
1023 @raises dns.exception.SyntaxError:
1024 @rtype: dns.message.Message object"""
1033 *f*, a ``file`` or ``text``. If *f* is text, it is treated as the
1034 pathname of a file to open.
1035
1036 Raises ``dns.message.UnknownHeaderField`` if a header is unknown.
1037
1038 Raises ``dns.exception.SyntaxError`` if the text is badly formed.
1039
1040 Returns a ``dns.message.Message object``
1041 """
10251042
10261043 str_type = string_types
10271044 opts = 'rU'
10511068 The query will have a randomly chosen query id, and its DNS flags
10521069 will be set to dns.flags.RD.
10531070
1054 @param qname: The query name.
1055 @type qname: dns.name.Name object or string
1056 @param rdtype: The desired rdata type.
1057 @type rdtype: int
1058 @param rdclass: The desired rdata class; the default is class IN.
1059 @type rdclass: int
1060 @param use_edns: The EDNS level to use; the default is None (no EDNS).
1071 qname, a ``dns.name.Name`` or ``text``, the query name.
1072
1073 *rdtype*, an ``int`` or ``text``, the desired rdata type.
1074
1075 *rdclass*, an ``int`` or ``text``, the desired rdata class; the default
1076 is class IN.
1077
1078 *use_edns*, an ``int``, ``bool`` or ``None``. The EDNS level to use; the
1079 default is None (no EDNS).
10611080 See the description of dns.message.Message.use_edns() for the possible
10621081 values for use_edns and their meanings.
1063 @type use_edns: int or bool or None
1064 @param want_dnssec: Should the query indicate that DNSSEC is desired?
1065 @type want_dnssec: bool
1066 @param ednsflags: EDNS flag values.
1067 @type ednsflags: int
1068 @param payload: The EDNS sender's payload field, which is the maximum
1069 size of UDP datagram the sender can handle.
1070 @type payload: int
1071 @param request_payload: The EDNS payload size to use when sending
1072 this message. If not specified, defaults to the value of payload.
1073 @type request_payload: int or None
1074 @param options: The EDNS options
1075 @type options: None or list of dns.edns.Option objects
1076 @see: RFC 2671
1077 @rtype: dns.message.Message object"""
1082
1083 *want_dnssec*, a ``bool``. If ``True``, DNSSEC data is desired.
1084
1085 *ednsflags*, an ``int``, the EDNS flag values.
1086
1087 *payload*, an ``int``, is the EDNS sender's payload field, which is the
1088 maximum size of UDP datagram the sender can handle. I.e. how big
1089 a response to this message can be.
1090
1091 *request_payload*, an ``int``, is the EDNS payload size to use when
1092 sending this message. If not specified, defaults to the value of
1093 *payload*.
1094
1095 *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
1096 options.
1097
1098 Returns a ``dns.message.Message``
1099 """
10781100
10791101 if isinstance(qname, string_types):
10801102 qname = dns.name.from_text(qname)
11231145 question section, so the query's question RRsets should not be
11241146 changed.
11251147
1126 @param query: the query to respond to
1127 @type query: dns.message.Message object
1128 @param recursion_available: should RA be set in the response?
1129 @type recursion_available: bool
1130 @param our_payload: payload size to advertise in EDNS responses; default
1131 is 8192.
1132 @type our_payload: int
1133 @param fudge: TSIG time fudge; default is 300 seconds.
1134 @type fudge: int
1135 @rtype: dns.message.Message object"""
1148 *query*, a ``dns.message.Message``, the query to respond to.
1149
1150 *recursion_available*, a ``bool``, should RA be set in the response?
1151
1152 *our_payload*, an ``int``, the payload size to advertise in EDNS
1153 responses.
1154
1155 *fudge*, an ``int``, the TSIG time fudge.
1156
1157 Returns a ``dns.message.Message`` object.
1158 """
11361159
11371160 if query.flags & dns.flags.QR:
11381161 raise dns.exception.FormError('specified query message is not a query')
11451168 if query.edns >= 0:
11461169 response.use_edns(0, 0, our_payload, query.payload)
11471170 if query.had_tsig:
1148 response.use_tsig(query.keyring, query.keyname, fudge, None, 0, '',
1171 response.use_tsig(query.keyring, query.keyname, fudge, None, 0, b'',
11491172 query.keyalgorithm)
11501173 response.request_mac = query.mac
11511174 return response
0 from typing import Optional, Dict, List, Tuple, Union
1 from . import name, rrset, tsig, rdatatype, entropy, edns, rdataclass
2 import hmac
3
4 class Message:
5 def to_wire(self, origin : Optional[name.Name]=None, max_size=0, **kw) -> bytes:
6 ...
7 def find_rrset(self, section : List[rrset.RRset], name : name.Name, rdclass : int, rdtype : int,
8 covers=rdatatype.NONE, deleting : Optional[int]=None, create=False,
9 force_unique=False) -> rrset.RRset:
10 ...
11 def __init__(self, id : Optional[int] =None) -> None:
12 self.id : int
13 self.flags = 0
14 self.question : List[rrset.RRset] = []
15 self.answer : List[rrset.RRset] = []
16 self.authority : List[rrset.RRset] = []
17 self.additional : List[rrset.RRset] = []
18 self.edns = -1
19 self.ednsflags = 0
20 self.payload = 0
21 self.options : List[edns.Option] = []
22 self.request_payload = 0
23 self.keyring = None
24 self.keyname = None
25 self.keyalgorithm = tsig.default_algorithm
26 self.request_mac = b''
27 self.other_data = b''
28 self.tsig_error = 0
29 self.fudge = 300
30 self.original_id = self.id
31 self.mac = b''
32 self.xfr = False
33 self.origin = None
34 self.tsig_ctx = None
35 self.had_tsig = False
36 self.multi = False
37 self.first = True
38 self.index : Dict[Tuple[rrset.RRset, name.Name, int, int, Union[int,str], int], rrset.RRset] = {}
39 def from_text(a : str) -> Message:
40 ...
41
42 def from_wire(wire, keyring : Optional[Dict[name.Name,bytes]] = None, request_mac = b'', xfr=False, origin=None,
43 tsig_ctx : Optional[hmac.HMAC] = None, multi=False, first=True,
44 question_only=False, one_rr_per_rrset=False,
45 ignore_trailing=False) -> Message:
46 ...
47 def make_response(query : Message, recursion_available=False, our_payload=8192,
48 fudge=300) -> Message:
49 ...
50
51 def make_query(qname : Union[name.Name,str], rdtype : Union[str,int], rdclass : Union[int,str] =rdataclass.IN, use_edns : Optional[bool] = None,
52 want_dnssec=False, ednsflags : Optional[int] = None, payload : Optional[int] = None,
53 request_payload : Optional[int] = None, options : Optional[List[edns.Option]] = None) -> Message:
54 ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
1517 """DNS Names.
16
17 @var root: The DNS root name.
18 @type root: dns.name.Name object
19 @var empty: The empty DNS name.
20 @type empty: dns.name.Name object
2118 """
2219
2320 from io import BytesIO
3734 from ._compat import long, binary_type, text_type, unichr, maybe_decode
3835
3936 try:
40 maxint = sys.maxint
37 maxint = sys.maxint # pylint: disable=sys-max-int
4138 except AttributeError:
4239 maxint = (1 << (8 * struct.calcsize("P"))) // 2 - 1
4340
41
42 # fullcompare() result values
43
44 #: The compared names have no relationship to each other.
4445 NAMERELN_NONE = 0
46 #: the first name is a superdomain of the second.
4547 NAMERELN_SUPERDOMAIN = 1
48 #: The first name is a subdomain of the second.
4649 NAMERELN_SUBDOMAIN = 2
50 #: The compared names are equal.
4751 NAMERELN_EQUAL = 3
52 #: The compared names have a common ancestor.
4853 NAMERELN_COMMONANCESTOR = 4
4954
5055
5156 class EmptyLabel(dns.exception.SyntaxError):
52
5357 """A DNS label is empty."""
5458
5559
5660 class BadEscape(dns.exception.SyntaxError):
57
5861 """An escaped code in a text format of DNS name is invalid."""
5962
6063
6164 class BadPointer(dns.exception.FormError):
62
6365 """A DNS compression pointer points forward instead of backward."""
6466
6567
6668 class BadLabelType(dns.exception.FormError):
67
6869 """The label type in DNS name wire format is unknown."""
6970
7071
7172 class NeedAbsoluteNameOrOrigin(dns.exception.DNSException):
72
7373 """An attempt was made to convert a non-absolute name to
7474 wire when there was also a non-absolute (or missing) origin."""
7575
7676
7777 class NameTooLong(dns.exception.FormError):
78
7978 """A DNS name is > 255 octets long."""
8079
8180
8281 class LabelTooLong(dns.exception.SyntaxError):
83
8482 """A DNS label is > 63 octets long."""
8583
8684
8785 class AbsoluteConcatenation(dns.exception.DNSException):
88
8986 """An attempt was made to append anything other than the
9087 empty name to an absolute DNS name."""
9188
9289
9390 class NoParent(dns.exception.DNSException):
94
9591 """An attempt was made to get the parent of the root name
9692 or the empty name."""
9793
9894 class NoIDNA2008(dns.exception.DNSException):
99
10095 """IDNA 2008 processing was requested but the idna module is not
10196 available."""
10297
10398
10499 class IDNAException(dns.exception.DNSException):
105
106100 """IDNA processing raised an exception."""
107101
108 supp_kwargs = set(['idna_exception'])
102 supp_kwargs = {'idna_exception'}
109103 fmt = "IDNA processing exception: {idna_exception}"
110104
105
111106 class IDNACodec(object):
112
113107 """Abstract base class for IDNA encoder/decoders."""
114108
115109 def __init__(self):
130124 label = maybe_decode(label)
131125 return _escapify(label, True)
132126
127
133128 class IDNA2003Codec(IDNACodec):
134
135129 """IDNA 2003 encoder/decoder."""
136130
137131 def __init__(self, strict_decode=False):
138132 """Initialize the IDNA 2003 encoder/decoder.
139 @param strict_decode: If True, then IDNA2003 checking is done when
140 decoding. This can cause failures if the name was encoded with
141 IDNA2008. The default is False.
142 @type strict_decode: bool
143 """
133
134 *strict_decode* is a ``bool``. If `True`, then IDNA2003 checking
135 is done when decoding. This can cause failures if the name
136 was encoded with IDNA2008. The default is `False`.
137 """
138
144139 super(IDNA2003Codec, self).__init__()
145140 self.strict_decode = strict_decode
146141
147142 def encode(self, label):
143 """Encode *label*."""
144
148145 if label == '':
149146 return b''
150147 try:
153150 raise LabelTooLong
154151
155152 def decode(self, label):
153 """Decode *label*."""
156154 if not self.strict_decode:
157155 return super(IDNA2003Codec, self).decode(label)
158156 if label == b'':
162160 except Exception as e:
163161 raise IDNAException(idna_exception=e)
164162
163
165164 class IDNA2008Codec(IDNACodec):
166
167 """IDNA 2008 encoder/decoder."""
165 """IDNA 2008 encoder/decoder.
166
167 *uts_46* is a ``bool``. If True, apply Unicode IDNA
168 compatibility processing as described in Unicode Technical
169 Standard #46 (http://unicode.org/reports/tr46/).
170 If False, do not apply the mapping. The default is False.
171
172 *transitional* is a ``bool``: If True, use the
173 "transitional" mode described in Unicode Technical Standard
174 #46. The default is False.
175
176 *allow_pure_ascii* is a ``bool``. If True, then a label which
177 consists of only ASCII characters is allowed. This is less
178 strict than regular IDNA 2008, but is also necessary for mixed
179 names, e.g. a name with starting with "_sip._tcp." and ending
180 in an IDN suffix which would otherwise be disallowed. The
181 default is False.
182
183 *strict_decode* is a ``bool``: If True, then IDNA2008 checking
184 is done when decoding. This can cause failures if the name
185 was encoded with IDNA2003. The default is False.
186 """
168187
169188 def __init__(self, uts_46=False, transitional=False,
170189 allow_pure_ascii=False, strict_decode=False):
171 """Initialize the IDNA 2008 encoder/decoder.
172 @param uts_46: If True, apply Unicode IDNA compatibility processing
173 as described in Unicode Technical Standard #46
174 (U{http://unicode.org/reports/tr46/}). This parameter is only
175 meaningful if IDNA 2008 is in use. If False, do not apply
176 the mapping. The default is False
177 @type uts_46: bool
178 @param transitional: If True, use the "transitional" mode described
179 in Unicode Technical Standard #46. This parameter is only
180 meaningful if IDNA 2008 is in use. The default is False.
181 @type transitional: bool
182 @param allow_pure_ascii: If True, then a label which
183 consists of only ASCII characters is allowed. This is less strict
184 than regular IDNA 2008, but is also necessary for mixed names,
185 e.g. a name with starting with "_sip._tcp." and ending in an IDN
186 suffixm which would otherwise be disallowed. The default is False
187 @type allow_pure_ascii: bool
188 @param strict_decode: If True, then IDNA2008 checking is done when
189 decoding. This can cause failures if the name was encoded with
190 IDNA2003. The default is False.
191 @type strict_decode: bool
192 """
190 """Initialize the IDNA 2008 encoder/decoder."""
193191 super(IDNA2008Codec, self).__init__()
194192 self.uts_46 = uts_46
195193 self.transitional = transitional
276274 def _validate_labels(labels):
277275 """Check for empty labels in the middle of a label sequence,
278276 labels that are too long, and for too many labels.
279 @raises NameTooLong: the name as a whole is too long
280 @raises EmptyLabel: a label is empty (i.e. the root label) and appears
281 in a position other than the end of the label sequence"""
277
278 Raises ``dns.name.NameTooLong`` if the name as a whole is too long.
279
280 Raises ``dns.name.EmptyLabel`` if a label is empty (i.e. the root
281 label) and appears in a position other than the end of the label
282 sequence
283
284 """
282285
283286 l = len(labels)
284287 total = 0
298301 raise EmptyLabel
299302
300303
301 def _ensure_bytes(label):
304 def _maybe_convert_to_binary(label):
305 """If label is ``text``, convert it to ``binary``. If it is already
306 ``binary`` just return it.
307
308 """
309
302310 if isinstance(label, binary_type):
303311 return label
304312 if isinstance(label, text_type):
310318
311319 """A DNS name.
312320
313 The dns.name.Name class represents a DNS name as a tuple of labels.
314 Instances of the class are immutable.
315
316 @ivar labels: The tuple of labels in the name. Each label is a string of
317 up to 63 octets."""
321 The dns.name.Name class represents a DNS name as a tuple of
322 labels. Each label is a `binary` in DNS wire format. Instances
323 of the class are immutable.
324 """
318325
319326 __slots__ = ['labels']
320327
321328 def __init__(self, labels):
322 """Initialize a domain name from a list of labels.
323 @param labels: the labels
324 @type labels: any iterable whose values are strings
325 """
326 labels = [_ensure_bytes(x) for x in labels]
329 """*labels* is any iterable whose values are ``text`` or ``binary``.
330 """
331
332 labels = [_maybe_convert_to_binary(x) for x in labels]
327333 super(Name, self).__setattr__('labels', tuple(labels))
328334 _validate_labels(self.labels)
329335
330336 def __setattr__(self, name, value):
337 # Names are immutable
331338 raise TypeError("object doesn't support attribute assignment")
332339
333340 def __copy__(self):
337344 return Name(copy.deepcopy(self.labels, memo))
338345
339346 def __getstate__(self):
347 # Names can be pickled
340348 return {'labels': self.labels}
341349
342350 def __setstate__(self, state):
345353
346354 def is_absolute(self):
347355 """Is the most significant label of this name the root label?
348 @rtype: bool
356
357 Returns a ``bool``.
349358 """
350359
351360 return len(self.labels) > 0 and self.labels[-1] == b''
352361
353362 def is_wild(self):
354363 """Is this name wild? (I.e. Is the least significant label '*'?)
355 @rtype: bool
364
365 Returns a ``bool``.
356366 """
357367
358368 return len(self.labels) > 0 and self.labels[0] == b'*'
359369
360370 def __hash__(self):
361371 """Return a case-insensitive hash of the name.
362 @rtype: int
372
373 Returns an ``int``.
363374 """
364375
365376 h = long(0)
369380 return int(h % maxint)
370381
371382 def fullcompare(self, other):
372 """Compare two names, returning a 3-tuple (relation, order, nlabels).
373
374 I{relation} describes the relation ship between the names,
375 and is one of: dns.name.NAMERELN_NONE,
376 dns.name.NAMERELN_SUPERDOMAIN, dns.name.NAMERELN_SUBDOMAIN,
377 dns.name.NAMERELN_EQUAL, or dns.name.NAMERELN_COMMONANCESTOR
378
379 I{order} is < 0 if self < other, > 0 if self > other, and ==
380 0 if self == other. A relative name is always less than an
383 """Compare two names, returning a 3-tuple
384 ``(relation, order, nlabels)``.
385
386 *relation* describes the relation ship between the names,
387 and is one of: ``dns.name.NAMERELN_NONE``,
388 ``dns.name.NAMERELN_SUPERDOMAIN``, ``dns.name.NAMERELN_SUBDOMAIN``,
389 ``dns.name.NAMERELN_EQUAL``, or ``dns.name.NAMERELN_COMMONANCESTOR``.
390
391 *order* is < 0 if *self* < *other*, > 0 if *self* > *other*, and ==
392 0 if *self* == *other*. A relative name is always less than an
381393 absolute name. If both names have the same relativity, then
382394 the DNSSEC order relation is used to order them.
383395
384 I{nlabels} is the number of significant labels that the two names
396 *nlabels* is the number of significant labels that the two names
385397 have in common.
398
399 Here are some examples. Names ending in "." are absolute names,
400 those not ending in "." are relative names.
401
402 ============= ============= =========== ===== =======
403 self other relation order nlabels
404 ============= ============= =========== ===== =======
405 www.example. www.example. equal 0 3
406 www.example. example. subdomain > 0 2
407 example. www.example. superdomain < 0 2
408 example1.com. example2.com. common anc. < 0 2
409 example1 example2. none < 0 0
410 example1. example2 none > 0 0
411 ============= ============= =========== ===== =======
386412 """
387413
388414 sabs = self.is_absolute()
432458 def is_subdomain(self, other):
433459 """Is self a subdomain of other?
434460
435 The notion of subdomain includes equality.
436 @rtype: bool
461 Note that the notion of subdomain includes equality, e.g.
462 "dnpython.org" is a subdomain of itself.
463
464 Returns a ``bool``.
437465 """
438466
439467 (nr, o, nl) = self.fullcompare(other)
444472 def is_superdomain(self, other):
445473 """Is self a superdomain of other?
446474
447 The notion of subdomain includes equality.
448 @rtype: bool
475 Note that the notion of superdomain includes equality, e.g.
476 "dnpython.org" is a superdomain of itself.
477
478 Returns a ``bool``.
449479 """
450480
451481 (nr, o, nl) = self.fullcompare(other)
456486 def canonicalize(self):
457487 """Return a name which is equal to the current name, but is in
458488 DNSSEC canonical form.
459 @rtype: dns.name.Name object
460489 """
461490
462491 return Name([x.lower() for x in self.labels])
504533 return self.to_text(False)
505534
506535 def to_text(self, omit_final_dot=False):
507 """Convert name to text format.
508 @param omit_final_dot: If True, don't emit the final dot (denoting the
509 root label) for absolute names. The default is False.
510 @rtype: string
536 """Convert name to DNS text format.
537
538 *omit_final_dot* is a ``bool``. If True, don't emit the final
539 dot (denoting the root label) for absolute names. The default
540 is False.
541
542 Returns a ``text``.
511543 """
512544
513545 if len(self.labels) == 0:
526558
527559 IDN ACE labels are converted to Unicode.
528560
529 @param omit_final_dot: If True, don't emit the final dot (denoting the
530 root label) for absolute names. The default is False.
531 @type omit_final_dot: bool
532 @param idna_codec: IDNA encoder/decoder. If None, the
533 IDNA_2003_Practical encoder/decoder is used. The IDNA_2003_Practical
534 decoder does not impose any policy, it just decodes punycode, so if
535 you don't want checking for compliance, you can use this decoder for
536 IDNA2008 as well.
537 @type idna_codec: dns.name.IDNA
538 @rtype: string
561 *omit_final_dot* is a ``bool``. If True, don't emit the final
562 dot (denoting the root label) for absolute names. The default
563 is False.
564 *idna_codec* specifies the IDNA encoder/decoder. If None, the
565 dns.name.IDNA_2003_Practical encoder/decoder is used.
566 The IDNA_2003_Practical decoder does
567 not impose any policy, it just decodes punycode, so if you
568 don't want checking for compliance, you can use this decoder
569 for IDNA2008 as well.
570
571 Returns a ``text``.
539572 """
540573
541574 if len(self.labels) == 0:
553586 def to_digestable(self, origin=None):
554587 """Convert name to a format suitable for digesting in hashes.
555588
556 The name is canonicalized and converted to uncompressed wire format.
557
558 @param origin: If the name is relative and origin is not None, then
559 origin will be appended to it.
560 @type origin: dns.name.Name object
561 @raises NeedAbsoluteNameOrOrigin: All names in wire format are
562 absolute. If self is a relative name, then an origin must be supplied;
563 if it is missing, then this exception is raised
564 @rtype: string
589 The name is canonicalized and converted to uncompressed wire
590 format. All names in wire format are absolute. If the name
591 is a relative name, then an origin must be supplied.
592
593 *origin* is a ``dns.name.Name`` or ``None``. If the name is
594 relative and origin is not ``None``, then origin will be appended
595 to the name.
596
597 Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is
598 relative and no origin was provided.
599
600 Returns a ``binary``.
565601 """
566602
567603 if not self.is_absolute():
578614 def to_wire(self, file=None, compress=None, origin=None):
579615 """Convert name to wire format, possibly compressing it.
580616
581 @param file: the file where the name is emitted (typically
582 a BytesIO file). If None, a string containing the wire name
583 will be returned.
584 @type file: file or None
585 @param compress: The compression table. If None (the default) names
586 will not be compressed.
587 @type compress: dict
588 @param origin: If the name is relative and origin is not None, then
589 origin will be appended to it.
590 @type origin: dns.name.Name object
591 @raises NeedAbsoluteNameOrOrigin: All names in wire format are
592 absolute. If self is a relative name, then an origin must be supplied;
593 if it is missing, then this exception is raised
617 *file* is the file where the name is emitted (typically a
618 BytesIO file). If ``None`` (the default), a ``binary``
619 containing the wire name will be returned.
620
621 *compress*, a ``dict``, is the compression table to use. If
622 ``None`` (the default), names will not be compressed.
623
624 *origin* is a ``dns.name.Name`` or ``None``. If the name is
625 relative and origin is not ``None``, then *origin* will be appended
626 to it.
627
628 Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is
629 relative and no origin was provided.
630
631 Returns a ``binary`` or ``None``.
594632 """
595633
596634 if file is None:
633671
634672 def __len__(self):
635673 """The length of the name (in labels).
636 @rtype: int
674
675 Returns an ``int``.
637676 """
638677
639678 return len(self.labels)
648687 return self.relativize(other)
649688
650689 def split(self, depth):
651 """Split a name into a prefix and suffix at depth.
652
653 @param depth: the number of labels in the suffix
654 @type depth: int
655 @raises ValueError: the depth was not >= 0 and <= the length of the
690 """Split a name into a prefix and suffix names at the specified depth.
691
692 *depth* is an ``int`` specifying the number of labels in the suffix
693
694 Raises ``ValueError`` if *depth* was not >= 0 and <= the length of the
656695 name.
657 @returns: the tuple (prefix, suffix)
658 @rtype: tuple
696
697 Returns the tuple ``(prefix, suffix)``.
659698 """
660699
661700 l = len(self.labels)
670709
671710 def concatenate(self, other):
672711 """Return a new name which is the concatenation of self and other.
673 @rtype: dns.name.Name object
674 @raises AbsoluteConcatenation: self is absolute and other is
675 not the empty name
712
713 Raises ``dns.name.AbsoluteConcatenation`` if the name is
714 absolute and *other* is not the empty name.
715
716 Returns a ``dns.name.Name``.
676717 """
677718
678719 if self.is_absolute() and len(other) > 0:
682723 return Name(labels)
683724
684725 def relativize(self, origin):
685 """If self is a subdomain of origin, return a new name which is self
686 relative to origin. Otherwise return self.
687 @rtype: dns.name.Name object
726 """If the name is a subdomain of *origin*, return a new name which is
727 the name relative to origin. Otherwise return the name.
728
729 For example, relativizing ``www.dnspython.org.`` to origin
730 ``dnspython.org.`` returns the name ``www``. Relativizing ``example.``
731 to origin ``dnspython.org.`` returns ``example.``.
732
733 Returns a ``dns.name.Name``.
688734 """
689735
690736 if origin is not None and self.is_subdomain(origin):
693739 return self
694740
695741 def derelativize(self, origin):
696 """If self is a relative name, return a new name which is the
697 concatenation of self and origin. Otherwise return self.
698 @rtype: dns.name.Name object
742 """If the name is a relative name, return a new name which is the
743 concatenation of the name and origin. Otherwise return the name.
744
745 For example, derelativizing ``www`` to origin ``dnspython.org.``
746 returns the name ``www.dnspython.org.``. Derelativizing ``example.``
747 to origin ``dnspython.org.`` returns ``example.``.
748
749 Returns a ``dns.name.Name``.
699750 """
700751
701752 if not self.is_absolute():
704755 return self
705756
706757 def choose_relativity(self, origin=None, relativize=True):
707 """Return a name with the relativity desired by the caller. If
708 origin is None, then self is returned. Otherwise, if
709 relativize is true the name is relativized, and if relativize is
710 false the name is derelativized.
711 @rtype: dns.name.Name object
758 """Return a name with the relativity desired by the caller.
759
760 If *origin* is ``None``, then the name is returned.
761 Otherwise, if *relativize* is ``True`` the name is
762 relativized, and if *relativize* is ``False`` the name is
763 derelativized.
764
765 Returns a ``dns.name.Name``.
712766 """
713767
714768 if origin:
721775
722776 def parent(self):
723777 """Return the parent of the name.
724 @rtype: dns.name.Name object
725 @raises NoParent: the name is either the root name or the empty name,
726 and thus has no parent.
727 """
778
779 For example, the parent of ``www.dnspython.org.`` is ``dnspython.org``.
780
781 Raises ``dns.name.NoParent`` if the name is either the root name or the
782 empty name, and thus has no parent.
783
784 Returns a ``dns.name.Name``.
785 """
786
728787 if self == root or self == empty:
729788 raise NoParent
730789 return Name(self.labels[1:])
731790
791 #: The root name, '.'
732792 root = Name([b''])
793
794 #: The empty name.
733795 empty = Name([])
734
735796
736797 def from_unicode(text, origin=root, idna_codec=None):
737798 """Convert unicode text into a Name object.
738799
739 Labels are encoded in IDN ACE form.
740
741 @param text: The text to convert into a name.
742 @type text: Unicode string
743 @param origin: The origin to append to non-absolute names.
744 @type origin: dns.name.Name
745 @param idna_codec: IDNA encoder/decoder. If None, the default IDNA 2003
746 encoder/decoder is used.
747 @type idna_codec: dns.name.IDNA
748 @rtype: dns.name.Name object
800 Labels are encoded in IDN ACE form according to rules specified by
801 the IDNA codec.
802
803 *text*, a ``text``, is the text to convert into a name.
804
805 *origin*, a ``dns.name.Name``, specifies the origin to
806 append to non-absolute names. The default is the root name.
807
808 *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
809 encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
810 is used.
811
812 Returns a ``dns.name.Name``.
749813 """
750814
751815 if not isinstance(text, text_type):
808872 def from_text(text, origin=root, idna_codec=None):
809873 """Convert text into a Name object.
810874
811 @param text: The text to convert into a name.
812 @type text: string
813 @param origin: The origin to append to non-absolute names.
814 @type origin: dns.name.Name
815 @param idna_codec: IDNA encoder/decoder. If None, the default IDNA 2003
816 encoder/decoder is used.
817 @type idna_codec: dns.name.IDNA
818 @rtype: dns.name.Name object
875 *text*, a ``text``, is the text to convert into a name.
876
877 *origin*, a ``dns.name.Name``, specifies the origin to
878 append to non-absolute names. The default is the root name.
879
880 *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
881 encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
882 is used.
883
884 Returns a ``dns.name.Name``.
819885 """
820886
821887 if isinstance(text, text_type):
877943
878944 def from_wire(message, current):
879945 """Convert possibly compressed wire format into a Name.
880 @param message: the entire DNS message
881 @type message: string
882 @param current: the offset of the beginning of the name from the start
883 of the message
884 @type current: int
885 @raises dns.name.BadPointer: a compression pointer did not point backwards
886 in the message
887 @raises dns.name.BadLabelType: an invalid label type was encountered.
888 @returns: a tuple consisting of the name that was read and the number
889 of bytes of the wire format message which were consumed reading it
890 @rtype: (dns.name.Name object, int) tuple
946
947 *message* is a ``binary`` containing an entire DNS message in DNS
948 wire form.
949
950 *current*, an ``int``, is the offset of the beginning of the name
951 from the start of the message
952
953 Raises ``dns.name.BadPointer`` if a compression pointer did not
954 point backwards in the message.
955
956 Raises ``dns.name.BadLabelType`` if an invalid label type was encountered.
957
958 Returns a ``(dns.name.Name, int)`` tuple consisting of the name
959 that was read and the number of bytes of the wire format message
960 which were consumed reading it.
891961 """
892962
893963 if not isinstance(message, binary_type):
0 from typing import Optional, Union, Tuple, Iterable, List
1
2 class Name:
3 def is_subdomain(self, o : Name) -> bool: ...
4 def is_superdomain(self, o : Name) -> bool: ...
5 def __init__(self, labels : Iterable[Union[bytes,str]]) -> None:
6 self.labels : List[bytes]
7 def is_absolute(self) -> bool: ...
8 def is_wild(self) -> bool: ...
9 def fullcompare(self, other) -> Tuple[int,int,int]: ...
10 def canonicalize(self) -> Name: ...
11 def __lt__(self, other : Name): ...
12 def __le__(self, other : Name): ...
13 def __ge__(self, other : Name): ...
14 def __gt__(self, other : Name): ...
15 def to_text(self, omit_final_dot=False) -> str: ...
16 def to_unicode(self, omit_final_dot=False, idna_codec=None) -> str: ...
17 def to_digestable(self, origin=None) -> bytes: ...
18 def to_wire(self, file=None, compress=None, origin=None) -> Optional[bytes]: ...
19 def __add__(self, other : Name): ...
20 def __sub__(self, other : Name): ...
21 def split(self, depth) -> List[Tuple[str,str]]: ...
22 def concatenate(self, other : Name) -> Name: ...
23 def relativize(self, origin): ...
24 def derelativize(self, origin): ...
25 def choose_relativity(self, origin : Optional[Name] = None, relativize=True): ...
26 def parent(self) -> Name: ...
27
28 class IDNACodec:
29 pass
30
31 def from_text(text, origin : Optional[Name] = Name('.'), idna_codec : Optional[IDNACodec] = None) -> Name:
32 ...
33
34 empty : Name
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 # Copyright (C) 2016 Coresec Systems AB
24 #
35 # Permission to use, copy, modify, and distribute this software and its
3032
3133
3234 class NameDict(collections.MutableMapping):
35 """A dictionary whose keys are dns.name.Name objects.
3336
34 """A dictionary whose keys are dns.name.Name objects.
35 @ivar max_depth: the maximum depth of the keys that have ever been
36 added to the dictionary.
37 @type max_depth: int
38 @ivar max_depth_items: the number of items of maximum depth
39 @type max_depth_items: int
37 In addition to being like a regular Python dictionary, this
38 dictionary can also get the deepest match for a given key.
4039 """
4140
4241 __slots__ = ["max_depth", "max_depth_items", "__store"]
4342
4443 def __init__(self, *args, **kwargs):
44 super(NameDict, self).__init__()
4545 self.__store = dict()
46 #: the maximum depth of the keys that have ever been added
4647 self.max_depth = 0
48 #: the number of items of maximum depth
4749 self.max_depth_items = 0
4850 self.update(dict(*args, **kwargs))
4951
8284 return key in self.__store
8385
8486 def get_deepest_match(self, name):
85 """Find the deepest match to I{name} in the dictionary.
87 """Find the deepest match to *fname* in the dictionary.
8688
8789 The deepest match is the longest name in the dictionary which is
88 a superdomain of I{name}.
90 a superdomain of *name*. Note that *superdomain* includes matching
91 *name* itself.
8992
90 @param name: the name
91 @type name: dns.name.Name object
92 @rtype: (key, value) tuple
93 *name*, a ``dns.name.Name``, the name to find.
94
95 Returns a ``(key, value)`` where *key* is the deepest
96 ``dns.name.Name``, and *value* is the value associated with *key*.
9397 """
9498
9599 depth = len(name)
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
2325
2426 class Node(object):
2527
26 """A DNS node.
27
28 A node is a set of rdatasets
29
30 @ivar rdatasets: the node's rdatasets
31 @type rdatasets: list of dns.rdataset.Rdataset objects"""
28 """A Node is a set of rdatasets."""
3229
3330 __slots__ = ['rdatasets']
3431
3532 def __init__(self):
36 """Initialize a DNS node.
37 """
38
33 #: the set of rdatsets, represented as a list.
3934 self.rdatasets = []
4035
4136 def to_text(self, name, **kw):
4338
4439 Each rdataset at the node is printed. Any keyword arguments
4540 to this method are passed on to the rdataset's to_text() method.
46 @param name: the owner name of the rdatasets
47 @type name: dns.name.Name object
48 @rtype: string
41
42 *name*, a ``dns.name.Name`` or ``text``, the owner name of the rdatasets.
43
44 Returns a ``text``.
4945 """
5046
5147 s = StringIO()
5955 return '<DNS node ' + str(id(self)) + '>'
6056
6157 def __eq__(self, other):
62 """Two nodes are equal if they have the same rdatasets.
63
64 @rtype: bool
65 """
6658 #
6759 # This is inefficient. Good thing we don't need to do it much.
6860 #
8880 """Find an rdataset matching the specified properties in the
8981 current node.
9082
91 @param rdclass: The class of the rdataset
92 @type rdclass: int
93 @param rdtype: The type of the rdataset
94 @type rdtype: int
95 @param covers: The covered type. Usually this value is
83 *rdclass*, an ``int``, the class of the rdataset.
84
85 *rdtype*, an ``int``, the type of the rdataset.
86
87 *covers*, an ``int``, the covered type. Usually this value is
9688 dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
9789 dns.rdatatype.RRSIG, then the covers value will be the rdata
9890 type the SIG/RRSIG covers. The library treats the SIG and RRSIG
10092 types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
10193 easier to work with than if RRSIGs covering different rdata
10294 types were aggregated into a single RRSIG rdataset.
103 @type covers: int
104 @param create: If True, create the rdataset if it is not found.
105 @type create: bool
106 @raises KeyError: An rdataset of the desired type and class does
107 not exist and I{create} is not True.
108 @rtype: dns.rdataset.Rdataset object
95
96 *create*, a ``bool``. If True, create the rdataset if it is not found.
97
98 Raises ``KeyError`` if an rdataset of the desired type and class does
99 not exist and *create* is not ``True``.
100
101 Returns a ``dns.rdataset.Rdataset``.
109102 """
110103
111104 for rds in self.rdatasets:
123116 current node.
124117
125118 None is returned if an rdataset of the specified type and
126 class does not exist and I{create} is not True.
119 class does not exist and *create* is not ``True``.
127120
128 @param rdclass: The class of the rdataset
129 @type rdclass: int
130 @param rdtype: The type of the rdataset
131 @type rdtype: int
132 @param covers: The covered type.
133 @type covers: int
134 @param create: If True, create the rdataset if it is not found.
135 @type create: bool
136 @rtype: dns.rdataset.Rdataset object or None
121 *rdclass*, an ``int``, the class of the rdataset.
122
123 *rdtype*, an ``int``, the type of the rdataset.
124
125 *covers*, an ``int``, the covered type. Usually this value is
126 dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
127 dns.rdatatype.RRSIG, then the covers value will be the rdata
128 type the SIG/RRSIG covers. The library treats the SIG and RRSIG
129 types as if they were a family of
130 types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
131 easier to work with than if RRSIGs covering different rdata
132 types were aggregated into a single RRSIG rdataset.
133
134 *create*, a ``bool``. If True, create the rdataset if it is not found.
135
136 Returns a ``dns.rdataset.Rdataset`` or ``None``.
137137 """
138138
139139 try:
148148
149149 If a matching rdataset does not exist, it is not an error.
150150
151 @param rdclass: The class of the rdataset
152 @type rdclass: int
153 @param rdtype: The type of the rdataset
154 @type rdtype: int
155 @param covers: The covered type.
156 @type covers: int
151 *rdclass*, an ``int``, the class of the rdataset.
152
153 *rdtype*, an ``int``, the type of the rdataset.
154
155 *covers*, an ``int``, the covered type.
157156 """
158157
159158 rds = self.get_rdataset(rdclass, rdtype, covers)
163162 def replace_rdataset(self, replacement):
164163 """Replace an rdataset.
165164
166 It is not an error if there is no rdataset matching I{replacement}.
165 It is not an error if there is no rdataset matching *replacement*.
167166
168 Ownership of the I{replacement} object is transferred to the node;
169 in other words, this method does not store a copy of I{replacement}
170 at the node, it stores I{replacement} itself.
167 Ownership of the *replacement* object is transferred to the node;
168 in other words, this method does not store a copy of *replacement*
169 at the node, it stores *replacement* itself.
170
171 *replacement*, a ``dns.rdataset.Rdataset``.
172
173 Raises ``ValueError`` if *replacement* is not a
174 ``dns.rdataset.Rdataset``.
171175 """
172176
173177 if not isinstance(replacement, dns.rdataset.Rdataset):
0 from typing import List, Optional, Union
1 from . import rdataset, rdatatype, name
2 class Node:
3 def __init__(self):
4 self.rdatasets : List[rdataset.Rdataset]
5 def to_text(self, name : Union[str,name.Name], **kw) -> str:
6 ...
7 def find_rdataset(self, rdclass : int, rdtype : int, covers=rdatatype.NONE,
8 create=False) -> rdataset.Rdataset:
9 ...
10 def get_rdataset(self, rdclass : int, rdtype : int, covers=rdatatype.NONE,
11 create=False) -> Optional[rdataset.Rdataset]:
12 ...
13 def delete_rdataset(self, rdclass : int, rdtype : int, covers=rdatatype.NONE):
14 ...
15 def replace_rdataset(self, replacement : rdataset.Rdataset) -> None:
16 ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1618
1719 import dns.exception
1820
21 #: Query
1922 QUERY = 0
23 #: Inverse Query (historical)
2024 IQUERY = 1
25 #: Server Status (unspecified and unimplemented anywhere)
2126 STATUS = 2
27 #: Notify
2228 NOTIFY = 4
29 #: Dynamic Update
2330 UPDATE = 5
2431
2532 _by_text = {
3441 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
3542 # would cause the mapping not to be true inverse.
3643
37 _by_value = dict((y, x) for x, y in _by_text.items())
44 _by_value = {y: x for x, y in _by_text.items()}
3845
3946
4047 class UnknownOpcode(dns.exception.DNSException):
41
4248 """An DNS opcode is unknown."""
4349
4450
4551 def from_text(text):
4652 """Convert text into an opcode.
4753
48 @param text: the textual opcode
49 @type text: string
50 @raises UnknownOpcode: the opcode is unknown
51 @rtype: int
54 *text*, a ``text``, the textual opcode
55
56 Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown.
57
58 Returns an ``int``.
5259 """
5360
5461 if text.isdigit():
6471 def from_flags(flags):
6572 """Extract an opcode from DNS message flags.
6673
67 @param flags: int
68 @rtype: int
74 *flags*, an ``int``, the DNS flags.
75
76 Returns an ``int``.
6977 """
7078
7179 return (flags & 0x7800) >> 11
7482 def to_flags(value):
7583 """Convert an opcode to a value suitable for ORing into DNS message
7684 flags.
77 @rtype: int
85
86 *value*, an ``int``, the DNS opcode value.
87
88 Returns an ``int``.
7889 """
7990
8091 return (value << 11) & 0x7800
8394 def to_text(value):
8495 """Convert an opcode to text.
8596
86 @param value: the opcdoe
87 @type value: int
88 @raises UnknownOpcode: the opcode is unknown
89 @rtype: string
97 *value*, an ``int`` the opcode value,
98
99 Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown.
100
101 Returns a ``text``.
90102 """
91103
92104 text = _by_value.get(value)
96108
97109
98110 def is_update(flags):
99 """True if the opcode in flags is UPDATE.
111 """Is the opcode in flags UPDATE?
100112
101 @param flags: DNS flags
102 @type flags: int
103 @rtype: bool
113 *flags*, an ``int``, the DNS message flags.
114
115 Returns a ``bool``.
104116 """
105117
106118 return from_flags(flags) == UPDATE
(New empty file)
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
2729 import dns.inet
2830 import dns.name
2931 import dns.message
32 import dns.rcode
3033 import dns.rdataclass
3134 import dns.rdatatype
32 from ._compat import long, string_types
33
34 if sys.version_info > (3,):
35 from ._compat import long, string_types, PY3
36
37 if PY3:
3538 select_error = OSError
3639 else:
3740 select_error = select.error
4144 socket_factory = socket.socket
4245
4346 class UnexpectedSource(dns.exception.DNSException):
44
4547 """A DNS query response came from an unexpected address or port."""
4648
4749
4850 class BadResponse(dns.exception.FormError):
49
5051 """A DNS query response does not respond to the question asked."""
52
53
54 class TransferError(dns.exception.DNSException):
55 """A zone transfer response got a non-zero rcode."""
56
57 def __init__(self, rcode):
58 message = 'Zone transfer error: %s' % dns.rcode.to_text(rcode)
59 super(TransferError, self).__init__(message)
60 self.rcode = rcode
5161
5262
5363 def _compute_expiration(timeout):
5666 else:
5767 return time.time() + timeout
5868
69 # This module can use either poll() or select() as the "polling backend".
70 #
71 # A backend function takes an fd, bools for readability, writablity, and
72 # error detection, and a timeout.
5973
6074 def _poll_for(fd, readable, writable, error, timeout):
61 """Poll polling backend.
62 @param fd: File descriptor
63 @type fd: int
64 @param readable: Whether to wait for readability
65 @type readable: bool
66 @param writable: Whether to wait for writability
67 @type writable: bool
68 @param timeout: Deadline timeout (expiration time, in seconds)
69 @type timeout: float
70 @return True on success, False on timeout
71 """
75 """Poll polling backend."""
76
7277 event_mask = 0
7378 if readable:
7479 event_mask |= select.POLLIN
8994
9095
9196 def _select_for(fd, readable, writable, error, timeout):
92 """Select polling backend.
93 @param fd: File descriptor
94 @type fd: int
95 @param readable: Whether to wait for readability
96 @type readable: bool
97 @param writable: Whether to wait for writability
98 @type writable: bool
99 @param timeout: Deadline timeout (expiration time, in seconds)
100 @type timeout: float
101 @return True on success, False on timeout
102 """
97 """Select polling backend."""
98
10399 rset, wset, xset = [], [], []
104100
105101 if readable:
118114
119115
120116 def _wait_for(fd, readable, writable, error, expiration):
117 # Use the selected polling backend to wait for any of the specified
118 # events. An "expiration" absolute time is converted into a relative
119 # timeout.
120
121121 done = False
122122 while not done:
123123 if expiration is None:
136136
137137
138138 def _set_polling_backend(fn):
139 """
140 Internal API. Do not use.
141 """
139 # Internal API. Do not use.
140
142141 global _polling_backend
143142
144143 _polling_backend = fn
164163 # Convert the first value of the tuple, which is a textual format
165164 # address into binary form, so that we are not confused by different
166165 # textual representations of the same address
167 n1 = dns.inet.inet_pton(af, a1[0])
168 n2 = dns.inet.inet_pton(af, a2[0])
166 try:
167 n1 = dns.inet.inet_pton(af, a1[0])
168 n2 = dns.inet.inet_pton(af, a2[0])
169 except dns.exception.SyntaxError:
170 return False
169171 return n1 == n2 and a1[1:] == a2[1:]
170172
171173
192194 return (af, destination, source)
193195
194196
197 def send_udp(sock, what, destination, expiration=None):
198 """Send a DNS message to the specified UDP socket.
199
200 *sock*, a ``socket``.
201
202 *what*, a ``binary`` or ``dns.message.Message``, the message to send.
203
204 *destination*, a destination tuple appropriate for the address family
205 of the socket, specifying where to send the query.
206
207 *expiration*, a ``float`` or ``None``, the absolute time at which
208 a timeout exception should be raised. If ``None``, no timeout will
209 occur.
210
211 Returns an ``(int, float)`` tuple of bytes sent and the sent time.
212 """
213
214 if isinstance(what, dns.message.Message):
215 what = what.to_wire()
216 _wait_for_writable(sock, expiration)
217 sent_time = time.time()
218 n = sock.sendto(what, destination)
219 return (n, sent_time)
220
221
222 def receive_udp(sock, destination, expiration=None,
223 ignore_unexpected=False, one_rr_per_rrset=False,
224 keyring=None, request_mac=b'', ignore_trailing=False):
225 """Read a DNS message from a UDP socket.
226
227 *sock*, a ``socket``.
228
229 *destination*, a destination tuple appropriate for the address family
230 of the socket, specifying where the associated query was sent.
231
232 *expiration*, a ``float`` or ``None``, the absolute time at which
233 a timeout exception should be raised. If ``None``, no timeout will
234 occur.
235
236 *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from
237 unexpected sources.
238
239 *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
240 RRset.
241
242 *keyring*, a ``dict``, the keyring to use for TSIG.
243
244 *request_mac*, a ``binary``, the MAC of the request (for TSIG).
245
246 *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
247 junk at end of the received message.
248
249 Raises if the message is malformed, if network errors occur, of if
250 there is a timeout.
251
252 Returns a ``dns.message.Message`` object.
253 """
254
255 wire = b''
256 while 1:
257 _wait_for_readable(sock, expiration)
258 (wire, from_address) = sock.recvfrom(65535)
259 if _addresses_equal(sock.family, from_address, destination) or \
260 (dns.inet.is_multicast(destination[0]) and
261 from_address[1:] == destination[1:]):
262 break
263 if not ignore_unexpected:
264 raise UnexpectedSource('got a response from '
265 '%s instead of %s' % (from_address,
266 destination))
267 received_time = time.time()
268 r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac,
269 one_rr_per_rrset=one_rr_per_rrset,
270 ignore_trailing=ignore_trailing)
271 return (r, received_time)
272
195273 def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
196 ignore_unexpected=False, one_rr_per_rrset=False):
274 ignore_unexpected=False, one_rr_per_rrset=False, ignore_trailing=False):
197275 """Return the response obtained after sending a query via UDP.
198276
199 @param q: the query
200 @type q: dns.message.Message
201 @param where: where to send the message
202 @type where: string containing an IPv4 or IPv6 address
203 @param timeout: The number of seconds to wait before the query times out.
204 If None, the default, wait forever.
205 @type timeout: float
206 @param port: The port to which to send the message. The default is 53.
207 @type port: int
208 @param af: the address family to use. The default is None, which
209 causes the address family to use to be inferred from the form of where.
210 If the inference attempt fails, AF_INET is used.
211 @type af: int
212 @rtype: dns.message.Message object
213 @param source: source address. The default is the wildcard address.
214 @type source: string
215 @param source_port: The port from which to send the message.
277 *q*, a ``dns.message.Message``, the query to send
278
279 *where*, a ``text`` containing an IPv4 or IPv6 address, where
280 to send the message.
281
282 *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
283 query times out. If ``None``, the default, wait forever.
284
285 *port*, an ``int``, the port send the message to. The default is 53.
286
287 *af*, an ``int``, the address family to use. The default is ``None``,
288 which causes the address family to use to be inferred from the form of
289 *where*. If the inference attempt fails, AF_INET is used. This
290 parameter is historical; you need never set it.
291
292 *source*, a ``text`` containing an IPv4 or IPv6 address, specifying
293 the source address. The default is the wildcard address.
294
295 *source_port*, an ``int``, the port from which to send the message.
216296 The default is 0.
217 @type source_port: int
218 @param ignore_unexpected: If True, ignore responses from unexpected
219 sources. The default is False.
220 @type ignore_unexpected: bool
221 @param one_rr_per_rrset: Put each RR into its own RRset
222 @type one_rr_per_rrset: bool
297
298 *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from
299 unexpected sources.
300
301 *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
302 RRset.
303
304 *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
305 junk at end of the received message.
306
307 Returns a ``dns.message.Message``.
223308 """
224309
225310 wire = q.to_wire()
226311 (af, destination, source) = _destination_and_source(af, where, port,
227312 source, source_port)
228313 s = socket_factory(af, socket.SOCK_DGRAM, 0)
229 begin_time = None
314 received_time = None
315 sent_time = None
230316 try:
231317 expiration = _compute_expiration(timeout)
232318 s.setblocking(0)
233319 if source is not None:
234320 s.bind(source)
235 _wait_for_writable(s, expiration)
236 begin_time = time.time()
237 s.sendto(wire, destination)
238 while 1:
239 _wait_for_readable(s, expiration)
240 (wire, from_address) = s.recvfrom(65535)
241 if _addresses_equal(af, from_address, destination) or \
242 (dns.inet.is_multicast(where) and
243 from_address[1:] == destination[1:]):
244 break
245 if not ignore_unexpected:
246 raise UnexpectedSource('got a response from '
247 '%s instead of %s' % (from_address,
248 destination))
321 (_, sent_time) = send_udp(s, wire, destination, expiration)
322 (r, received_time) = receive_udp(s, destination, expiration,
323 ignore_unexpected, one_rr_per_rrset,
324 q.keyring, q.mac, ignore_trailing)
249325 finally:
250 if begin_time is None:
326 if sent_time is None or received_time is None:
251327 response_time = 0
252328 else:
253 response_time = time.time() - begin_time
329 response_time = received_time - sent_time
254330 s.close()
255 r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
256 one_rr_per_rrset=one_rr_per_rrset)
257331 r.time = response_time
258332 if not q.is_response(r):
259333 raise BadResponse
289363 current += sock.send(data[current:])
290364
291365
366 def send_tcp(sock, what, expiration=None):
367 """Send a DNS message to the specified TCP socket.
368
369 *sock*, a ``socket``.
370
371 *what*, a ``binary`` or ``dns.message.Message``, the message to send.
372
373 *expiration*, a ``float`` or ``None``, the absolute time at which
374 a timeout exception should be raised. If ``None``, no timeout will
375 occur.
376
377 Returns an ``(int, float)`` tuple of bytes sent and the sent time.
378 """
379
380 if isinstance(what, dns.message.Message):
381 what = what.to_wire()
382 l = len(what)
383 # copying the wire into tcpmsg is inefficient, but lets us
384 # avoid writev() or doing a short write that would get pushed
385 # onto the net
386 tcpmsg = struct.pack("!H", l) + what
387 _wait_for_writable(sock, expiration)
388 sent_time = time.time()
389 _net_write(sock, tcpmsg, expiration)
390 return (len(tcpmsg), sent_time)
391
392 def receive_tcp(sock, expiration=None, one_rr_per_rrset=False,
393 keyring=None, request_mac=b'', ignore_trailing=False):
394 """Read a DNS message from a TCP socket.
395
396 *sock*, a ``socket``.
397
398 *expiration*, a ``float`` or ``None``, the absolute time at which
399 a timeout exception should be raised. If ``None``, no timeout will
400 occur.
401
402 *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
403 RRset.
404
405 *keyring*, a ``dict``, the keyring to use for TSIG.
406
407 *request_mac*, a ``binary``, the MAC of the request (for TSIG).
408
409 *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
410 junk at end of the received message.
411
412 Raises if the message is malformed, if network errors occur, of if
413 there is a timeout.
414
415 Returns a ``dns.message.Message`` object.
416 """
417
418 ldata = _net_read(sock, 2, expiration)
419 (l,) = struct.unpack("!H", ldata)
420 wire = _net_read(sock, l, expiration)
421 received_time = time.time()
422 r = dns.message.from_wire(wire, keyring=keyring, request_mac=request_mac,
423 one_rr_per_rrset=one_rr_per_rrset,
424 ignore_trailing=ignore_trailing)
425 return (r, received_time)
426
292427 def _connect(s, address):
293428 try:
294429 s.connect(address)
304439
305440
306441 def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
307 one_rr_per_rrset=False):
442 one_rr_per_rrset=False, ignore_trailing=False):
308443 """Return the response obtained after sending a query via TCP.
309444
310 @param q: the query
311 @type q: dns.message.Message object
312 @param where: where to send the message
313 @type where: string containing an IPv4 or IPv6 address
314 @param timeout: The number of seconds to wait before the query times out.
315 If None, the default, wait forever.
316 @type timeout: float
317 @param port: The port to which to send the message. The default is 53.
318 @type port: int
319 @param af: the address family to use. The default is None, which
320 causes the address family to use to be inferred from the form of where.
321 If the inference attempt fails, AF_INET is used.
322 @type af: int
323 @rtype: dns.message.Message object
324 @param source: source address. The default is the wildcard address.
325 @type source: string
326 @param source_port: The port from which to send the message.
445 *q*, a ``dns.message.Message``, the query to send
446
447 *where*, a ``text`` containing an IPv4 or IPv6 address, where
448 to send the message.
449
450 *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
451 query times out. If ``None``, the default, wait forever.
452
453 *port*, an ``int``, the port send the message to. The default is 53.
454
455 *af*, an ``int``, the address family to use. The default is ``None``,
456 which causes the address family to use to be inferred from the form of
457 *where*. If the inference attempt fails, AF_INET is used. This
458 parameter is historical; you need never set it.
459
460 *source*, a ``text`` containing an IPv4 or IPv6 address, specifying
461 the source address. The default is the wildcard address.
462
463 *source_port*, an ``int``, the port from which to send the message.
327464 The default is 0.
328 @type source_port: int
329 @param one_rr_per_rrset: Put each RR into its own RRset
330 @type one_rr_per_rrset: bool
465
466 *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
467 RRset.
468
469 *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
470 junk at end of the received message.
471
472 Returns a ``dns.message.Message``.
331473 """
332474
333475 wire = q.to_wire()
335477 source, source_port)
336478 s = socket_factory(af, socket.SOCK_STREAM, 0)
337479 begin_time = None
480 received_time = None
338481 try:
339482 expiration = _compute_expiration(timeout)
340483 s.setblocking(0)
342485 if source is not None:
343486 s.bind(source)
344487 _connect(s, destination)
345
346 l = len(wire)
347
348 # copying the wire into tcpmsg is inefficient, but lets us
349 # avoid writev() or doing a short write that would get pushed
350 # onto the net
351 tcpmsg = struct.pack("!H", l) + wire
352 _net_write(s, tcpmsg, expiration)
353 ldata = _net_read(s, 2, expiration)
354 (l,) = struct.unpack("!H", ldata)
355 wire = _net_read(s, l, expiration)
488 send_tcp(s, wire, expiration)
489 (r, received_time) = receive_tcp(s, expiration, one_rr_per_rrset,
490 q.keyring, q.mac, ignore_trailing)
356491 finally:
357 if begin_time is None:
492 if begin_time is None or received_time is None:
358493 response_time = 0
359494 else:
360 response_time = time.time() - begin_time
495 response_time = received_time - begin_time
361496 s.close()
362 r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
363 one_rr_per_rrset=one_rr_per_rrset)
364497 r.time = response_time
365498 if not q.is_response(r):
366499 raise BadResponse
373506 use_udp=False, keyalgorithm=dns.tsig.default_algorithm):
374507 """Return a generator for the responses to a zone transfer.
375508
376 @param where: where to send the message
377 @type where: string containing an IPv4 or IPv6 address
378 @param zone: The name of the zone to transfer
379 @type zone: dns.name.Name object or string
380 @param rdtype: The type of zone transfer. The default is
381 dns.rdatatype.AXFR.
382 @type rdtype: int or string
383 @param rdclass: The class of the zone transfer. The default is
384 dns.rdataclass.IN.
385 @type rdclass: int or string
386 @param timeout: The number of seconds to wait for each response message.
387 If None, the default, wait forever.
388 @type timeout: float
389 @param port: The port to which to send the message. The default is 53.
390 @type port: int
391 @param keyring: The TSIG keyring to use
392 @type keyring: dict
393 @param keyname: The name of the TSIG key to use
394 @type keyname: dns.name.Name object or string
395 @param relativize: If True, all names in the zone will be relativized to
396 the zone origin. It is essential that the relativize setting matches
397 the one specified to dns.zone.from_xfr().
398 @type relativize: bool
399 @param af: the address family to use. The default is None, which
400 causes the address family to use to be inferred from the form of where.
401 If the inference attempt fails, AF_INET is used.
402 @type af: int
403 @param lifetime: The total number of seconds to spend doing the transfer.
404 If None, the default, then there is no limit on the time the transfer may
405 take.
406 @type lifetime: float
407 @rtype: generator of dns.message.Message objects.
408 @param source: source address. The default is the wildcard address.
409 @type source: string
410 @param source_port: The port from which to send the message.
509 *where*. If the inference attempt fails, AF_INET is used. This
510 parameter is historical; you need never set it.
511
512 *zone*, a ``dns.name.Name`` or ``text``, the name of the zone to transfer.
513
514 *rdtype*, an ``int`` or ``text``, the type of zone transfer. The
515 default is ``dns.rdatatype.AXFR``. ``dns.rdatatype.IXFR`` can be
516 used to do an incremental transfer instead.
517
518 *rdclass*, an ``int`` or ``text``, the class of the zone transfer.
519 The default is ``dns.rdataclass.IN``.
520
521 *timeout*, a ``float``, the number of seconds to wait for each
522 response message. If None, the default, wait forever.
523
524 *port*, an ``int``, the port send the message to. The default is 53.
525
526 *keyring*, a ``dict``, the keyring to use for TSIG.
527
528 *keyname*, a ``dns.name.Name`` or ``text``, the name of the TSIG
529 key to use.
530
531 *relativize*, a ``bool``. If ``True``, all names in the zone will be
532 relativized to the zone origin. It is essential that the
533 relativize setting matches the one specified to
534 ``dns.zone.from_xfr()`` if using this generator to make a zone.
535
536 *af*, an ``int``, the address family to use. The default is ``None``,
537 which causes the address family to use to be inferred from the form of
538 *where*. If the inference attempt fails, AF_INET is used. This
539 parameter is historical; you need never set it.
540
541 *lifetime*, a ``float``, the total number of seconds to spend
542 doing the transfer. If ``None``, the default, then there is no
543 limit on the time the transfer may take.
544
545 *source*, a ``text`` containing an IPv4 or IPv6 address, specifying
546 the source address. The default is the wildcard address.
547
548 *source_port*, an ``int``, the port from which to send the message.
411549 The default is 0.
412 @type source_port: int
413 @param serial: The SOA serial number to use as the base for an IXFR diff
414 sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
415 @type serial: int
416 @param use_udp: Use UDP (only meaningful for IXFR)
417 @type use_udp: bool
418 @param keyalgorithm: The TSIG algorithm to use; defaults to
419 dns.tsig.default_algorithm
420 @type keyalgorithm: string
550
551 *serial*, an ``int``, the SOA serial number to use as the base for
552 an IXFR diff sequence (only meaningful if *rdtype* is
553 ``dns.rdatatype.IXFR``).
554
555 *use_udp*, a ``bool``. If ``True``, use UDP (only meaningful for IXFR).
556
557 *keyalgorithm*, a ``dns.name.Name`` or ``text``, the TSIG algorithm to use.
558
559 Raises on errors, and so does the generator.
560
561 Returns a generator of ``dns.message.Message`` objects.
421562 """
422563
423564 if isinstance(zone, string_types):
480621 xfr=True, origin=origin, tsig_ctx=tsig_ctx,
481622 multi=True, first=first,
482623 one_rr_per_rrset=is_ixfr)
624 rcode = r.rcode()
625 if rcode != dns.rcode.NOERROR:
626 raise TransferError(rcode)
483627 tsig_ctx = r.tsig_ctx
484628 first = False
485629 answer_index = 0
0 from typing import Optional, Union, Dict, Generator, Any
1 from . import message, tsig, rdatatype, rdataclass, name, message
2 def tcp(q : message.Message, where : str, timeout : float = None, port=53, af : Optional[int] = None, source : Optional[str] = None, source_port : int = 0,
3 one_rr_per_rrset=False) -> message.Message:
4 pass
5
6 def xfr(where : None, zone : Union[name.Name,str], rdtype=rdatatype.AXFR, rdclass=rdataclass.IN,
7 timeout : Optional[float] =None, port=53, keyring : Optional[Dict[name.Name, bytes]] =None, keyname : Union[str,name.Name]=None, relativize=True,
8 af : Optional[int] =None, lifetime : Optional[float]=None, source : Optional[str] =None, source_port=0, serial=0,
9 use_udp=False, keyalgorithm=tsig.default_algorithm) -> Generator[Any,Any,message.Message]:
10 pass
11
12 def udp(q : message.Message, where : str, timeout : Optional[float] = None, port=53, af : Optional[int] = None, source : Optional[str] = None, source_port=0,
13 ignore_unexpected=False, one_rr_per_rrset=False) -> message.Message:
14 ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1719 import dns.exception
1820 from ._compat import long
1921
20
22 #: No error
2123 NOERROR = 0
24 #: Form error
2225 FORMERR = 1
26 #: Server failure
2327 SERVFAIL = 2
28 #: Name does not exist ("Name Error" in RFC 1025 terminology).
2429 NXDOMAIN = 3
30 #: Not implemented
2531 NOTIMP = 4
32 #: Refused
2633 REFUSED = 5
34 #: Name exists.
2735 YXDOMAIN = 6
36 #: RRset exists.
2837 YXRRSET = 7
38 #: RRset does not exist.
2939 NXRRSET = 8
40 #: Not authoritative.
3041 NOTAUTH = 9
42 #: Name not in zone.
3143 NOTZONE = 10
44 #: Bad EDNS version.
3245 BADVERS = 16
3346
3447 _by_text = {
5063 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
5164 # would cause the mapping not to be a true inverse.
5265
53 _by_value = dict((y, x) for x, y in _by_text.items())
66 _by_value = {y: x for x, y in _by_text.items()}
5467
5568
5669 class UnknownRcode(dns.exception.DNSException):
57
5870 """A DNS rcode is unknown."""
5971
6072
6173 def from_text(text):
6274 """Convert text into an rcode.
6375
64 @param text: the textual rcode
65 @type text: string
66 @raises UnknownRcode: the rcode is unknown
67 @rtype: int
76 *text*, a ``text``, the textual rcode or an integer in textual form.
77
78 Raises ``dns.rcode.UnknownRcode`` if the rcode mnemonic is unknown.
79
80 Returns an ``int``.
6881 """
6982
7083 if text.isdigit():
8093 def from_flags(flags, ednsflags):
8194 """Return the rcode value encoded by flags and ednsflags.
8295
83 @param flags: the DNS flags
84 @type flags: int
85 @param ednsflags: the EDNS flags
86 @type ednsflags: int
87 @raises ValueError: rcode is < 0 or > 4095
88 @rtype: int
96 *flags*, an ``int``, the DNS flags field.
97
98 *ednsflags*, an ``int``, the EDNS flags field.
99
100 Raises ``ValueError`` if rcode is < 0 or > 4095
101
102 Returns an ``int``.
89103 """
90104
91105 value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0)
97111 def to_flags(value):
98112 """Return a (flags, ednsflags) tuple which encodes the rcode.
99113
100 @param value: the rcode
101 @type value: int
102 @raises ValueError: rcode is < 0 or > 4095
103 @rtype: (int, int) tuple
114 *value*, an ``int``, the rcode.
115
116 Raises ``ValueError`` if rcode is < 0 or > 4095.
117
118 Returns an ``(int, int)`` tuple.
104119 """
105120
106121 if value < 0 or value > 4095:
113128 def to_text(value):
114129 """Convert rcode into text.
115130
116 @param value: the rcode
117 @type value: int
118 @rtype: string
131 *value*, and ``int``, the rcode.
132
133 Raises ``ValueError`` if rcode is < 0 or > 4095.
134
135 Returns a ``text``.
119136 """
120137
138 if value < 0 or value > 4095:
139 raise ValueError('rcode must be >= 0 and <= 4095')
121140 text = _by_value.get(value)
122141 if text is None:
123142 text = str(value)
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """DNS rdata.
16
17 @var _rdata_modules: A dictionary mapping a (rdclass, rdtype) tuple to
18 the module which implements that type.
19 @type _rdata_modules: dict
20 @var _module_prefix: The prefix to use when forming modules names. The
21 default is 'dns.rdtypes'. Changing this value will break the library.
22 @type _module_prefix: string
23 @var _hex_chunk: At most this many octets that will be represented in each
24 chunk of hexstring that _hexify() produces before whitespace occurs.
25 @type _hex_chunk: int"""
17 """DNS rdata."""
2618
2719 from io import BytesIO
2820 import base64
3628 import dns.wiredata
3729 from ._compat import xrange, string_types, text_type
3830
31 try:
32 import threading as _threading
33 except ImportError:
34 import dummy_threading as _threading
35
3936 _hex_chunksize = 32
4037
4138
4239 def _hexify(data, chunksize=_hex_chunksize):
4340 """Convert a binary string into its hex encoding, broken up into chunks
44 of I{chunksize} characters separated by a space.
45
46 @param data: the binary string
47 @type data: string
48 @param chunksize: the chunk size. Default is L{dns.rdata._hex_chunksize}
49 @rtype: string
41 of chunksize characters separated by a space.
5042 """
5143
5244 line = binascii.hexlify(data)
5951
6052 def _base64ify(data, chunksize=_base64_chunksize):
6153 """Convert a binary string into its base64 encoding, broken up into chunks
62 of I{chunksize} characters separated by a space.
63
64 @param data: the binary string
65 @type data: string
66 @param chunksize: the chunk size. Default is
67 L{dns.rdata._base64_chunksize}
68 @rtype: string
54 of chunksize characters separated by a space.
6955 """
7056
7157 line = base64.b64encode(data)
7662 __escaped = bytearray(b'"\\')
7763
7864 def _escapify(qstring):
79 """Escape the characters in a quoted string which need it.
80
81 @param qstring: the string
82 @type qstring: string
83 @returns: the escaped string
84 @rtype: string
85 """
65 """Escape the characters in a quoted string which need it."""
8666
8767 if isinstance(qstring, text_type):
8868 qstring = qstring.encode()
10383 def _truncate_bitmap(what):
10484 """Determine the index of greatest byte that isn't all zeros, and
10585 return the bitmap that contains all the bytes less than that index.
106
107 @param what: a string of octets representing a bitmap.
108 @type what: string
109 @rtype: string
11086 """
11187
11288 for i in xrange(len(what) - 1, -1, -1):
11692
11793
11894 class Rdata(object):
119
120 """Base class for all DNS rdata types.
121 """
95 """Base class for all DNS rdata types."""
12296
12397 __slots__ = ['rdclass', 'rdtype']
12498
12599 def __init__(self, rdclass, rdtype):
126100 """Initialize an rdata.
127 @param rdclass: The rdata class
128 @type rdclass: int
129 @param rdtype: The rdata type
130 @type rdtype: int
101
102 *rdclass*, an ``int`` is the rdataclass of the Rdata.
103 *rdtype*, an ``int`` is the rdatatype of the Rdata.
131104 """
132105
133106 self.rdclass = rdclass
134107 self.rdtype = rdtype
135108
136109 def covers(self):
137 """DNS SIG/RRSIG rdatas apply to a specific type; this type is
110 """Return the type a Rdata covers.
111
112 DNS SIG/RRSIG rdatas apply to a specific type; this type is
138113 returned by the covers() function. If the rdata type is not
139114 SIG or RRSIG, dns.rdatatype.NONE is returned. This is useful when
140115 creating rdatasets, allowing the rdataset to contain only RRSIGs
141116 of a particular type, e.g. RRSIG(NS).
142 @rtype: int
117
118 Returns an ``int``.
143119 """
144120
145121 return dns.rdatatype.NONE
148124 """Return a 32-bit type value, the least significant 16 bits of
149125 which are the ordinary DNS type, and the upper 16 bits of which are
150126 the "covered" type, if any.
151 @rtype: int
127
128 Returns an ``int``.
152129 """
153130
154131 return self.covers() << 16 | self.rdtype
155132
156133 def to_text(self, origin=None, relativize=True, **kw):
157134 """Convert an rdata to text format.
158 @rtype: string
159 """
135
136 Returns a ``text``.
137 """
138
160139 raise NotImplementedError
161140
162141 def to_wire(self, file, compress=None, origin=None):
163142 """Convert an rdata to wire format.
164 @rtype: string
143
144 Returns a ``binary``.
165145 """
166146
167147 raise NotImplementedError
168148
169149 def to_digestable(self, origin=None):
170150 """Convert rdata to a format suitable for digesting in hashes. This
171 is also the DNSSEC canonical form."""
151 is also the DNSSEC canonical form.
152
153 Returns a ``binary``.
154 """
155
172156 f = BytesIO()
173157 self.to_wire(f, None, origin)
174158 return f.getvalue()
175159
176160 def validate(self):
177161 """Check that the current contents of the rdata's fields are
178 valid. If you change an rdata by assigning to its fields,
162 valid.
163
164 If you change an rdata by assigning to its fields,
179165 it is a good idea to call validate() when you are done making
180166 changes.
181 """
167
168 Raises various exceptions if there are problems.
169
170 Returns ``None``.
171 """
172
182173 dns.rdata.from_text(self.rdclass, self.rdtype, self.to_text())
183174
184175 def __repr__(self):
196187
197188 def _cmp(self, other):
198189 """Compare an rdata with another rdata of the same rdtype and
199 rdclass. Return < 0 if self < other in the DNSSEC ordering,
200 0 if self == other, and > 0 if self > other.
190 rdclass.
191
192 Return < 0 if self < other in the DNSSEC ordering, 0 if self
193 == other, and > 0 if self > other.
194
201195 """
202196 our = self.to_digestable(dns.name.root)
203197 their = other.to_digestable(dns.name.root)
204198 if our == their:
205199 return 0
206 if our > their:
200 elif our > their:
207201 return 1
208
209 return -1
202 else:
203 return -1
210204
211205 def __eq__(self, other):
212206 if not isinstance(other, Rdata):
252246
253247 @classmethod
254248 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
255 """Build an rdata object from text format.
256
257 @param rdclass: The rdata class
258 @type rdclass: int
259 @param rdtype: The rdata type
260 @type rdtype: int
261 @param tok: The tokenizer
262 @type tok: dns.tokenizer.Tokenizer
263 @param origin: The origin to use for relative names
264 @type origin: dns.name.Name
265 @param relativize: should names be relativized?
266 @type relativize: bool
267 @rtype: dns.rdata.Rdata instance
268 """
269
270249 raise NotImplementedError
271250
272251 @classmethod
273252 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
274 """Build an rdata object from wire format
275
276 @param rdclass: The rdata class
277 @type rdclass: int
278 @param rdtype: The rdata type
279 @type rdtype: int
280 @param wire: The wire-format message
281 @type wire: string
282 @param current: The offset in wire of the beginning of the rdata.
283 @type current: int
284 @param rdlen: The length of the wire-format rdata
285 @type rdlen: int
286 @param origin: The origin to use for relative names
287 @type origin: dns.name.Name
288 @rtype: dns.rdata.Rdata instance
289 """
290
291253 raise NotImplementedError
292254
293255 def choose_relativity(self, origin=None, relativize=True):
295257 relativization.
296258 """
297259
298 pass
299
300
301260 class GenericRdata(Rdata):
302261
303 """Generate Rdata Class
262 """Generic Rdata Class
304263
305264 This class is used for rdata types for which we have no better
306265 implementation. It implements the DNS "unknown RRs" scheme.
318277 @classmethod
319278 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
320279 token = tok.get()
321 if not token.is_identifier() or token.value != '\#':
280 if not token.is_identifier() or token.value != r'\#':
322281 raise dns.exception.SyntaxError(
323282 r'generic rdata does not start with \#')
324283 length = tok.get_int()
344303
345304 _rdata_modules = {}
346305 _module_prefix = 'dns.rdtypes'
347
306 _import_lock = _threading.Lock()
348307
349308 def get_rdata_class(rdclass, rdtype):
350309
351310 def import_module(name):
352 mod = __import__(name)
353 components = name.split('.')
354 for comp in components[1:]:
355 mod = getattr(mod, comp)
356 return mod
311 with _import_lock:
312 mod = __import__(name)
313 components = name.split('.')
314 for comp in components[1:]:
315 mod = getattr(mod, comp)
316 return mod
357317
358318 mod = _rdata_modules.get((rdclass, rdtype))
359319 rdclass_text = dns.rdataclass.to_text(rdclass)
391351 Once a class is chosen, its from_text() class method is called
392352 with the parameters to this function.
393353
394 If I{tok} is a string, then a tokenizer is created and the string
354 If *tok* is a ``text``, then a tokenizer is created and the string
395355 is used as its input.
396356
397 @param rdclass: The rdata class
398 @type rdclass: int
399 @param rdtype: The rdata type
400 @type rdtype: int
401 @param tok: The tokenizer or input text
402 @type tok: dns.tokenizer.Tokenizer or string
403 @param origin: The origin to use for relative names
404 @type origin: dns.name.Name
405 @param relativize: Should names be relativized?
406 @type relativize: bool
407 @rtype: dns.rdata.Rdata instance"""
357 *rdclass*, an ``int``, the rdataclass.
358
359 *rdtype*, an ``int``, the rdatatype.
360
361 *tok*, a ``dns.tokenizer.Tokenizer`` or a ``text``.
362
363 *origin*, a ``dns.name.Name`` (or ``None``), the
364 origin to use for relative names.
365
366 *relativize*, a ``bool``. If true, name will be relativized to
367 the specified origin.
368
369 Returns an instance of the chosen Rdata subclass.
370 """
408371
409372 if isinstance(tok, string_types):
410373 tok = dns.tokenizer.Tokenizer(tok)
438401 Once a class is chosen, its from_wire() class method is called
439402 with the parameters to this function.
440403
441 @param rdclass: The rdata class
442 @type rdclass: int
443 @param rdtype: The rdata type
444 @type rdtype: int
445 @param wire: The wire-format message
446 @type wire: string
447 @param current: The offset in wire of the beginning of the rdata.
448 @type current: int
449 @param rdlen: The length of the wire-format rdata
450 @type rdlen: int
451 @param origin: The origin to use for relative names
452 @type origin: dns.name.Name
453 @rtype: dns.rdata.Rdata instance"""
404 *rdclass*, an ``int``, the rdataclass.
405
406 *rdtype*, an ``int``, the rdatatype.
407
408 *wire*, a ``binary``, the wire-format message.
409
410 *current*, an ``int``, the offset in wire of the beginning of
411 the rdata.
412
413 *rdlen*, an ``int``, the length of the wire-format rdata
414
415 *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``,
416 then names will be relativized to this origin.
417
418 Returns an instance of the chosen Rdata subclass.
419 """
454420
455421 wire = dns.wiredata.maybe_wrap(wire)
456422 cls = get_rdata_class(rdclass, rdtype)
457423 return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin)
424
425
426 class RdatatypeExists(dns.exception.DNSException):
427 """DNS rdatatype already exists."""
428 supp_kwargs = {'rdclass', 'rdtype'}
429 fmt = "The rdata type with class {rdclass} and rdtype {rdtype} " + \
430 "already exists."
431
432
433 def register_type(implementation, rdtype, rdtype_text, is_singleton=False,
434 rdclass=dns.rdataclass.IN):
435 """Dynamically register a module to handle an rdatatype.
436
437 *implementation*, a module implementing the type in the usual dnspython
438 way.
439
440 *rdtype*, an ``int``, the rdatatype to register.
441
442 *rdtype_text*, a ``text``, the textual form of the rdatatype.
443
444 *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e.
445 RRsets of the type can have only one member.)
446
447 *rdclass*, the rdataclass of the type, or ``dns.rdataclass.ANY`` if
448 it applies to all classes.
449 """
450
451 existing_cls = get_rdata_class(rdclass, rdtype)
452 if existing_cls != GenericRdata:
453 raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype)
454 _rdata_modules[(rdclass, rdtype)] = implementation
455 dns.rdatatype.register_type(rdtype, rdtype_text, is_singleton)
0 from typing import Dict, Tuple, Any, Optional
1 from .name import Name
2 class Rdata:
3 def __init__(self):
4 self.address : str
5 def to_wire(self, file, compress : Optional[Dict[Name,int]], origin : Optional[Name]) -> bytes:
6 ...
7 @classmethod
8 def from_text(cls, rdclass : int, rdtype : int, tok, origin=None, relativize=True):
9 ...
10 _rdata_modules : Dict[Tuple[Any,Rdata],Any]
11
12 def from_text(rdclass : int, rdtype : int, tok : Optional[str], origin : Optional[Name] = None, relativize : bool = True):
13 ...
14
15 def from_wire(rdclass : int, rdtype : int, wire : bytes, current : int, rdlen : int, origin : Optional[Name] = None):
16 ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """DNS Rdata Classes.
16
17 @var _by_text: The rdata class textual name to value mapping
18 @type _by_text: dict
19 @var _by_value: The rdata class value to textual name mapping
20 @type _by_value: dict
21 @var _metaclasses: If an rdataclass is a metaclass, there will be a mapping
22 whose key is the rdatatype value and whose value is True in this dictionary.
23 @type _metaclasses: dict"""
17 """DNS Rdata Classes."""
2418
2519 import re
2620
4640 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
4741 # would cause the mapping not to be true inverse.
4842
49 _by_value = dict((y, x) for x, y in _by_text.items())
43 _by_value = {y: x for x, y in _by_text.items()}
5044
5145 # Now that we've built the inverse map, we can add class aliases to
5246 # the _by_text mapping.
6660
6761
6862 class UnknownRdataclass(dns.exception.DNSException):
69
7063 """A DNS class is unknown."""
7164
7265
7366 def from_text(text):
7467 """Convert text into a DNS rdata class value.
75 @param text: the text
76 @type text: string
77 @rtype: int
78 @raises dns.rdataclass.UnknownRdataclass: the class is unknown
79 @raises ValueError: the rdata class value is not >= 0 and <= 65535
68
69 The input text can be a defined DNS RR class mnemonic or
70 instance of the DNS generic class syntax.
71
72 For example, "IN" and "CLASS1" will both result in a value of 1.
73
74 Raises ``dns.rdatatype.UnknownRdataclass`` if the class is unknown.
75
76 Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535.
77
78 Returns an ``int``.
8079 """
8180
8281 value = _by_text.get(text.upper())
9190
9291
9392 def to_text(value):
94 """Convert a DNS rdata class to text.
95 @param value: the rdata class value
96 @type value: int
97 @rtype: string
98 @raises ValueError: the rdata class value is not >= 0 and <= 65535
93 """Convert a DNS rdata type value to text.
94
95 If the value has a known mnemonic, it will be used, otherwise the
96 DNS generic class syntax will be used.
97
98 Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535.
99
100 Returns a ``str``.
99101 """
100102
101103 if value < 0 or value > 65535:
107109
108110
109111 def is_metaclass(rdclass):
110 """True if the class is a metaclass.
111 @param rdclass: the rdata class
112 @type rdclass: int
113 @rtype: bool"""
112 """True if the specified class is a metaclass.
113
114 The currently defined metaclasses are ANY and NONE.
115
116 *rdclass* is an ``int``.
117 """
114118
115119 if rdclass in _metaclasses:
116120 return True
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
3032
3133
3234 class DifferingCovers(dns.exception.DNSException):
33
3435 """An attempt was made to add a DNS SIG/RRSIG whose covered type
3536 is not the same as that of the other rdatas in the rdataset."""
3637
3738
3839 class IncompatibleTypes(dns.exception.DNSException):
39
4040 """An attempt was made to add DNS RR data of an incompatible type."""
4141
4242
4343 class Rdataset(dns.set.Set):
4444
45 """A DNS rdataset.
46
47 @ivar rdclass: The class of the rdataset
48 @type rdclass: int
49 @ivar rdtype: The type of the rdataset
50 @type rdtype: int
51 @ivar covers: The covered type. Usually this value is
52 dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or
53 dns.rdatatype.RRSIG, then the covers value will be the rdata
54 type the SIG/RRSIG covers. The library treats the SIG and RRSIG
55 types as if they were a family of
56 types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much
57 easier to work with than if RRSIGs covering different rdata
58 types were aggregated into a single RRSIG rdataset.
59 @type covers: int
60 @ivar ttl: The DNS TTL (Time To Live) value
61 @type ttl: int
62 """
45 """A DNS rdataset."""
6346
6447 __slots__ = ['rdclass', 'rdtype', 'covers', 'ttl']
6548
66 def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
49 def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE, ttl=0):
6750 """Create a new rdataset of the specified class and type.
6851
69 @see: the description of the class instance variables for the
70 meaning of I{rdclass} and I{rdtype}"""
52 *rdclass*, an ``int``, the rdataclass.
53
54 *rdtype*, an ``int``, the rdatatype.
55
56 *covers*, an ``int``, the covered rdatatype.
57
58 *ttl*, an ``int``, the TTL.
59 """
7160
7261 super(Rdataset, self).__init__()
7362 self.rdclass = rdclass
7463 self.rdtype = rdtype
7564 self.covers = covers
76 self.ttl = 0
65 self.ttl = ttl
7766
7867 def _clone(self):
7968 obj = super(Rdataset, self)._clone()
8473 return obj
8574
8675 def update_ttl(self, ttl):
87 """Set the TTL of the rdataset to be the lesser of the set's current
76 """Perform TTL minimization.
77
78 Set the TTL of the rdataset to be the lesser of the set's current
8879 TTL or the specified TTL. If the set contains no rdatas, set the TTL
8980 to the specified TTL.
90 @param ttl: The TTL
91 @type ttl: int"""
81
82 *ttl*, an ``int``.
83 """
9284
9385 if len(self) == 0:
9486 self.ttl = ttl
9890 def add(self, rd, ttl=None):
9991 """Add the specified rdata to the rdataset.
10092
101 If the optional I{ttl} parameter is supplied, then
102 self.update_ttl(ttl) will be called prior to adding the rdata.
103
104 @param rd: The rdata
105 @type rd: dns.rdata.Rdata object
106 @param ttl: The TTL
107 @type ttl: int"""
93 If the optional *ttl* parameter is supplied, then
94 ``self.update_ttl(ttl)`` will be called prior to adding the rdata.
95
96 *rd*, a ``dns.rdata.Rdata``, the rdata
97
98 *ttl*, an ``int``, the TTL.
99
100 Raises ``dns.rdataset.IncompatibleTypes`` if the type and class
101 do not match the type and class of the rdataset.
102
103 Raises ``dns.rdataset.DifferingCovers`` if the type is a signature
104 type and the covered type does not match that of the rdataset.
105 """
108106
109107 #
110108 # If we're adding a signature, do some special handling to
138136 def update(self, other):
139137 """Add all rdatas in other to self.
140138
141 @param other: The rdataset from which to update
142 @type other: dns.rdataset.Rdataset object"""
139 *other*, a ``dns.rdataset.Rdataset``, the rdataset from which
140 to update.
141 """
143142
144143 self.update_ttl(other.ttl)
145144 super(Rdataset, self).update(other)
156155 return self.to_text()
157156
158157 def __eq__(self, other):
159 """Two rdatasets are equal if they have the same class, type, and
160 covers, and contain the same rdata.
161 @rtype: bool"""
162
163158 if not isinstance(other, Rdataset):
164159 return False
165160 if self.rdclass != other.rdclass or \
175170 override_rdclass=None, **kw):
176171 """Convert the rdataset into DNS master file format.
177172
178 @see: L{dns.name.Name.choose_relativity} for more information
179 on how I{origin} and I{relativize} determine the way names
173 See ``dns.name.Name.choose_relativity`` for more information
174 on how *origin* and *relativize* determine the way names
180175 are emitted.
181176
182177 Any additional keyword arguments are passed on to the rdata
183 to_text() method.
184
185 @param name: If name is not None, emit a RRs with I{name} as
186 the owner name.
187 @type name: dns.name.Name object
188 @param origin: The origin for relative names, or None.
189 @type origin: dns.name.Name object
190 @param relativize: True if names should names be relativized
191 @type relativize: bool"""
178 ``to_text()`` method.
179
180 *name*, a ``dns.name.Name``. If name is not ``None``, emit RRs with
181 *name* as the owner name.
182
183 *origin*, a ``dns.name.Name`` or ``None``, the origin for relative
184 names.
185
186 *relativize*, a ``bool``. If ``True``, names will be relativized
187 to *origin*.
188 """
189
192190 if name is not None:
193191 name = name.choose_relativity(origin, relativize)
194192 ntext = str(name)
207205 # some dynamic updates, so we don't need to print out the TTL
208206 # (which is meaningless anyway).
209207 #
210 s.write(u'%s%s%s %s\n' % (ntext, pad,
211 dns.rdataclass.to_text(rdclass),
212 dns.rdatatype.to_text(self.rdtype)))
208 s.write(u'{}{}{} {}\n'.format(ntext, pad,
209 dns.rdataclass.to_text(rdclass),
210 dns.rdatatype.to_text(self.rdtype)))
213211 else:
214212 for rd in self:
215213 s.write(u'%s%s%d %s %s %s\n' %
226224 override_rdclass=None, want_shuffle=True):
227225 """Convert the rdataset to wire format.
228226
229 @param name: The owner name of the RRset that will be emitted
230 @type name: dns.name.Name object
231 @param file: The file to which the wire format data will be appended
232 @type file: file
233 @param compress: The compression table to use; the default is None.
234 @type compress: dict
235 @param origin: The origin to be appended to any relative names when
236 they are emitted. The default is None.
237 @returns: the number of records emitted
238 @rtype: int
227 *name*, a ``dns.name.Name`` is the owner name to use.
228
229 *file* is the file where the name is emitted (typically a
230 BytesIO file).
231
232 *compress*, a ``dict``, is the compression table to use. If
233 ``None`` (the default), names will not be compressed.
234
235 *origin* is a ``dns.name.Name`` or ``None``. If the name is
236 relative and origin is not ``None``, then *origin* will be appended
237 to it.
238
239 *override_rdclass*, an ``int``, is used as the class instead of the
240 class of the rdataset. This is useful when rendering rdatasets
241 associated with dynamic updates.
242
243 *want_shuffle*, a ``bool``. If ``True``, then the order of the
244 Rdatas within the Rdataset will be shuffled before rendering.
245
246 Returns an ``int``, the number of records emitted.
239247 """
240248
241249 if override_rdclass is not None:
271279 return len(self)
272280
273281 def match(self, rdclass, rdtype, covers):
274 """Returns True if this rdataset matches the specified class, type,
275 and covers"""
282 """Returns ``True`` if this rdataset matches the specified class,
283 type, and covers.
284 """
276285 if self.rdclass == rdclass and \
277286 self.rdtype == rdtype and \
278287 self.covers == covers:
284293 """Create an rdataset with the specified class, type, and TTL, and with
285294 the specified list of rdatas in text format.
286295
287 @rtype: dns.rdataset.Rdataset object
296 Returns a ``dns.rdataset.Rdataset`` object.
288297 """
289298
290299 if isinstance(rdclass, string_types):
303312 """Create an rdataset with the specified class, type, and TTL, and with
304313 the specified rdatas in text format.
305314
306 @rtype: dns.rdataset.Rdataset object
315 Returns a ``dns.rdataset.Rdataset`` object.
307316 """
308317
309318 return from_text_list(rdclass, rdtype, ttl, text_rdatas)
313322 """Create an rdataset with the specified TTL, and with
314323 the specified list of rdata objects.
315324
316 @rtype: dns.rdataset.Rdataset object
325 Returns a ``dns.rdataset.Rdataset`` object.
317326 """
318327
319328 if len(rdatas) == 0:
331340 """Create an rdataset with the specified TTL, and with
332341 the specified rdata objects.
333342
334 @rtype: dns.rdataset.Rdataset object
343 Returns a ``dns.rdataset.Rdataset`` object.
335344 """
336345
337346 return from_rdata_list(ttl, rdatas)
0 from typing import Optional, Dict, List, Union
1 from io import BytesIO
2 from . import exception, name, set, rdatatype, rdata, rdataset
3
4 class DifferingCovers(exception.DNSException):
5 """An attempt was made to add a DNS SIG/RRSIG whose covered type
6 is not the same as that of the other rdatas in the rdataset."""
7
8
9 class IncompatibleTypes(exception.DNSException):
10 """An attempt was made to add DNS RR data of an incompatible type."""
11
12
13 class Rdataset(set.Set):
14 def __init__(self, rdclass, rdtype, covers=rdatatype.NONE, ttl=0):
15 self.rdclass : int = rdclass
16 self.rdtype : int = rdtype
17 self.covers : int = covers
18 self.ttl : int = ttl
19
20 def update_ttl(self, ttl : int) -> None:
21 ...
22
23 def add(self, rd : rdata.Rdata, ttl : Optional[int] =None):
24 ...
25
26 def union_update(self, other : Rdataset):
27 ...
28
29 def intersection_update(self, other : Rdataset):
30 ...
31
32 def update(self, other : Rdataset):
33 ...
34
35 def to_text(self, name : Optional[name.Name] =None, origin : Optional[name.Name] =None, relativize=True,
36 override_rdclass : Optional[int] =None, **kw) -> bytes:
37 ...
38
39 def to_wire(self, name : Optional[name.Name], file : BytesIO, compress : Optional[Dict[name.Name, int]] = None, origin : Optional[name.Name] = None,
40 override_rdclass : Optional[int] = None, want_shuffle=True) -> int:
41 ...
42
43 def match(self, rdclass : int, rdtype : int, covers : int) -> bool:
44 ...
45
46
47 def from_text_list(rdclass : Union[int,str], rdtype : Union[int,str], ttl : int, text_rdatas : str) -> rdataset.Rdataset:
48 ...
49
50 def from_text(rdclass : Union[int,str], rdtype : Union[int,str], ttl : int, *text_rdatas : str) -> rdataset.Rdataset:
51 ...
52
53 def from_rdata_list(ttl : int, rdatas : List[rdata.Rdata]) -> rdataset.Rdataset:
54 ...
55
56 def from_rdata(ttl : int, *rdatas : List[rdata.Rdata]) -> rdataset.Rdataset:
57 ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """DNS Rdata Types.
16
17 @var _by_text: The rdata type textual name to value mapping
18 @type _by_text: dict
19 @var _by_value: The rdata type value to textual name mapping
20 @type _by_value: dict
21 @var _metatypes: If an rdatatype is a metatype, there will be a mapping
22 whose key is the rdatatype value and whose value is True in this dictionary.
23 @type _metatypes: dict
24 @var _singletons: If an rdatatype is a singleton, there will be a mapping
25 whose key is the rdatatype value and whose value is True in this dictionary.
26 @type _singletons: dict"""
17 """DNS Rdata Types."""
2718
2819 import re
2920
8172 HIP = 55
8273 CDS = 59
8374 CDNSKEY = 60
75 OPENPGPKEY = 61
8476 CSYNC = 62
8577 SPF = 99
8678 UNSPEC = 103
152144 'HIP': HIP,
153145 'CDS': CDS,
154146 'CDNSKEY': CDNSKEY,
147 'OPENPGPKEY': OPENPGPKEY,
155148 'CSYNC': CSYNC,
156149 'SPF': SPF,
157150 'UNSPEC': UNSPEC,
175168 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
176169 # would cause the mapping not to be true inverse.
177170
178 _by_value = dict((y, x) for x, y in _by_text.items())
179
171 _by_value = {y: x for x, y in _by_text.items()}
180172
181173 _metatypes = {
182174 OPT: True
187179 NXT: True,
188180 DNAME: True,
189181 NSEC: True,
190 # CNAME is technically a singleton, but we allow multiple CNAMEs.
182 CNAME: True,
191183 }
192184
193185 _unknown_type_pattern = re.compile('TYPE([0-9]+)$', re.I)
194186
195187
196188 class UnknownRdatatype(dns.exception.DNSException):
197
198189 """DNS resource record type is unknown."""
199190
200191
201192 def from_text(text):
202193 """Convert text into a DNS rdata type value.
203 @param text: the text
204 @type text: string
205 @raises dns.rdatatype.UnknownRdatatype: the type is unknown
206 @raises ValueError: the rdata type value is not >= 0 and <= 65535
207 @rtype: int"""
194
195 The input text can be a defined DNS RR type mnemonic or
196 instance of the DNS generic type syntax.
197
198 For example, "NS" and "TYPE2" will both result in a value of 2.
199
200 Raises ``dns.rdatatype.UnknownRdatatype`` if the type is unknown.
201
202 Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535.
203
204 Returns an ``int``.
205 """
208206
209207 value = _by_text.get(text.upper())
210208 if value is None:
218216
219217
220218 def to_text(value):
221 """Convert a DNS rdata type to text.
222 @param value: the rdata type value
223 @type value: int
224 @raises ValueError: the rdata type value is not >= 0 and <= 65535
225 @rtype: string"""
219 """Convert a DNS rdata type value to text.
220
221 If the value has a known mnemonic, it will be used, otherwise the
222 DNS generic type syntax will be used.
223
224 Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535.
225
226 Returns a ``str``.
227 """
226228
227229 if value < 0 or value > 65535:
228230 raise ValueError("type must be between >= 0 and <= 65535")
233235
234236
235237 def is_metatype(rdtype):
236 """True if the type is a metatype.
237 @param rdtype: the type
238 @type rdtype: int
239 @rtype: bool"""
238 """True if the specified type is a metatype.
239
240 *rdtype* is an ``int``.
241
242 The currently defined metatypes are TKEY, TSIG, IXFR, AXFR, MAILA,
243 MAILB, ANY, and OPT.
244
245 Returns a ``bool``.
246 """
240247
241248 if rdtype >= TKEY and rdtype <= ANY or rdtype in _metatypes:
242249 return True
244251
245252
246253 def is_singleton(rdtype):
247 """True if the type is a singleton.
248 @param rdtype: the type
249 @type rdtype: int
250 @rtype: bool"""
254 """Is the specified type a singleton type?
255
256 Singleton types can only have a single rdata in an rdataset, or a single
257 RR in an RRset.
258
259 The currently defined singleton types are CNAME, DNAME, NSEC, NXT, and
260 SOA.
261
262 *rdtype* is an ``int``.
263
264 Returns a ``bool``.
265 """
251266
252267 if rdtype in _singletons:
253268 return True
254269 return False
270
271
272 def register_type(rdtype, rdtype_text, is_singleton=False): # pylint: disable=redefined-outer-name
273 """Dynamically register an rdatatype.
274
275 *rdtype*, an ``int``, the rdatatype to register.
276
277 *rdtype_text*, a ``text``, the textual form of the rdatatype.
278
279 *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e.
280 RRsets of the type can have only one member.)
281 """
282
283 _by_text[rdtype_text] = rdtype
284 _by_value[rdtype] = rdtype_text
285 if is_singleton:
286 _singletons[rdtype] = True
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2016 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011, 2016 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
7981 self.altitude = altitude
8082
8183 def to_text(self, origin=None, relativize=True, **kw):
82 return '%s %s %s' % (self.latitude.decode(),
84 return '{} {} {}'.format(self.latitude.decode(),
8385 self.longitude.decode(),
8486 self.altitude.decode())
8587
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
4446 self.os = os
4547
4648 def to_text(self, origin=None, relativize=True, **kw):
47 return '"%s" "%s"' % (dns.rdata._escapify(self.cpu),
48 dns.rdata._escapify(self.os))
49 return '"{}" "{}"'.format(dns.rdata._escapify(self.cpu),
50 dns.rdata._escapify(self.os))
4951
5052 @classmethod
5153 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2010, 2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
4547
4648 def to_text(self, origin=None, relativize=True, **kw):
4749 if self.subaddress:
48 return '"%s" "%s"' % (dns.rdata._escapify(self.address),
50 return '"{}" "{}"'.format(dns.rdata._escapify(self.address),
4951 dns.rdata._escapify(self.subaddress))
5052 else:
5153 return '"%s"' % dns.rdata._escapify(self.address)
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
155157 if self.size != _default_size or \
156158 self.horizontal_precision != _default_hprec or \
157159 self.vertical_precision != _default_vprec:
158 text += " %0.2fm %0.2fm %0.2fm" % (
160 text += " {:0.2f}m {:0.2f}m {:0.2f}m".format(
159161 self.size / 100.0, self.horizontal_precision / 100.0,
160162 self.vertical_precision / 100.0
161163 )
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
4951 bits.append(dns.rdatatype.to_text(window * 256 +
5052 i * 8 + j))
5153 text += (' ' + ' '.join(bits))
52 return '%s%s' % (next, text)
54 return '{}{}'.format(next, text)
5355
5456 @classmethod
5557 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
0 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2004-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
2022 import dns.exception
2123 import dns.rdata
2224 import dns.rdatatype
23 from dns._compat import xrange, text_type
25 from dns._compat import xrange, text_type, PY3
2426
25 try:
27 # pylint: disable=deprecated-string-function
28 if PY3:
29 b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV',
30 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
31 b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
32 b'0123456789ABCDEFGHIJKLMNOPQRSTUV')
33 else:
2634 b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV',
2735 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
2836 b32_normal_to_hex = string.maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
2937 '0123456789ABCDEFGHIJKLMNOPQRSTUV')
30 except AttributeError:
31 b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV',
32 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
33 b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
34 b'0123456789ABCDEFGHIJKLMNOPQRSTUV')
38 # pylint: enable=deprecated-string-function
39
3540
3641 # hash algorithm constants
3742 SHA1 = 1
129134 new_window = nrdtype // 256
130135 if new_window != window:
131136 if octets != 0:
132 windows.append((window, ''.join(bitmap[0:octets])))
137 windows.append((window, bitmap[0:octets]))
133138 bitmap = bytearray(b'\0' * 32)
134139 window = new_window
135140 offset = nrdtype % 256
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2016 Nominum, Inc.
3 #
4 # Permission to use, copy, modify, and distribute this software and its
5 # documentation for any purpose with or without fee is hereby granted,
6 # provided that the above copyright notice and this permission notice
7 # appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 import base64
18
19 import dns.exception
20 import dns.rdata
21 import dns.tokenizer
22
23 class OPENPGPKEY(dns.rdata.Rdata):
24
25 """OPENPGPKEY record
26
27 @ivar key: the key
28 @type key: bytes
29 @see: RFC 7929
30 """
31
32 def __init__(self, rdclass, rdtype, key):
33 super(OPENPGPKEY, self).__init__(rdclass, rdtype)
34 self.key = key
35
36 def to_text(self, origin=None, relativize=True, **kw):
37 return dns.rdata._base64ify(self.key)
38
39 @classmethod
40 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
41 chunks = []
42 while 1:
43 t = tok.get().unescape()
44 if t.is_eol_or_eof():
45 break
46 if not t.is_identifier():
47 raise dns.exception.SyntaxError
48 chunks.append(t.value.encode())
49 b64 = b''.join(chunks)
50 key = base64.b64decode(b64)
51 return cls(rdclass, rdtype, key)
52
53 def to_wire(self, file, compress=None, origin=None):
54 file.write(self.key)
55
56 @classmethod
57 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
58 key = wire[current: current + rdlen].unwrap()
59 return cls(rdclass, rdtype, key)
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
3840 def to_text(self, origin=None, relativize=True, **kw):
3941 mbox = self.mbox.choose_relativity(origin, relativize)
4042 txt = self.txt.choose_relativity(origin, relativize)
41 return "%s %s" % (str(mbox), str(txt))
43 return "{} {}".format(str(mbox), str(txt))
4244
4345 @classmethod
4446 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2005-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2005-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 # Copyright (C) 2015 Red Hat, Inc.
24 #
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1618
1719 __all__ = [
1820 'AFSDB',
21 'AVC',
22 'CAA',
1923 'CDNSKEY',
2024 'CDS',
2125 'CERT',
2226 'CNAME',
27 'CSYNC',
2328 'DLV',
2429 'DNAME',
2530 'DNSKEY',
3641 'NSEC',
3742 'NSEC3',
3843 'NSEC3PARAM',
39 'TLSA',
44 'OPENPGPKEY',
4045 'PTR',
4146 'RP',
4247 'RRSIG',
4449 'SOA',
4550 'SPF',
4651 'SSHFP',
52 'TLSA',
4753 'TXT',
54 'URI',
4855 'X25',
4956 ]
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
3 #
4 # Permission to use, copy, modify, and distribute this software and its
5 # documentation for any purpose with or without fee is hereby granted,
6 # provided that the above copyright notice and this permission notice
7 # appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 import dns.rdtypes.mxbase
18 import struct
19
20 class A(dns.rdtypes.mxbase.MXBase):
21
22 """A record for Chaosnet
23 @ivar domain: the domain of the address
24 @type domain: dns.name.Name object
25 @ivar address: the 16-bit address
26 @type address: int"""
27
28 __slots__ = ['domain', 'address']
29
30 def __init__(self, rdclass, rdtype, address, domain):
31 super(A, self).__init__(rdclass, rdtype, address, domain)
32 self.domain = domain
33 self.address = address
34
35 def to_text(self, origin=None, relativize=True, **kw):
36 domain = self.domain.choose_relativity(origin, relativize)
37 return '%s %o' % (domain, self.address)
38
39 @classmethod
40 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
41 domain = tok.get_name()
42 address = tok.get_uint16(base=8)
43 domain = domain.choose_relativity(origin, relativize)
44 tok.get_eol()
45 return cls(rdclass, rdtype, address, domain)
46
47 def to_wire(self, file, compress=None, origin=None):
48 self.domain.to_wire(file, compress, origin)
49 pref = struct.pack("!H", self.address)
50 file.write(pref)
51
52 def to_digestable(self, origin=None):
53 return self.domain.to_digestable(origin) + \
54 struct.pack("!H", self.address)
55
56 @classmethod
57 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
58 (domain, cused) = dns.name.from_wire(wire[: current + rdlen-2],
59 current)
60 current += cused
61 (address,) = struct.unpack('!H', wire[current: current + 2])
62 if cused+2 != rdlen:
63 raise dns.exception.FormError
64 if origin is not None:
65 domain = domain.relativize(origin)
66 return cls(rdclass, rdtype, address, domain)
67
68 def choose_relativity(self, origin=None, relativize=True):
69 self.domain = self.domain.choose_relativity(origin, relativize)
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
3 #
4 # Permission to use, copy, modify, and distribute this software and its
5 # documentation for any purpose with or without fee is hereby granted,
6 # provided that the above copyright notice and this permission notice
7 # appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 """Class CH rdata type classes."""
18
19 __all__ = [
20 'A',
21 ]
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
4749
4850 @classmethod
4951 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
50 address = dns.ipv4.inet_ntoa(wire[current: current + rdlen]).decode()
52 address = dns.ipv4.inet_ntoa(wire[current: current + rdlen])
5153 return cls(rdclass, rdtype, address)
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
17 import binascii
18 import codecs
1519 import struct
16 import binascii
1720
1821 import dns.exception
1922 import dns.inet
2023 import dns.rdata
2124 import dns.tokenizer
22 from dns._compat import xrange
25 from dns._compat import xrange, maybe_chr
2326
2427
2528 class APLItem(object):
6265 #
6366 last = 0
6467 for i in xrange(len(address) - 1, -1, -1):
65 if address[i] != chr(0):
68 if address[i] != maybe_chr(0):
6669 last = i + 1
6770 break
6871 address = address[0: last]
120123
121124 @classmethod
122125 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
126
123127 items = []
124128 while 1:
125129 if rdlen == 0:
141145 l = len(address)
142146 if header[0] == 1:
143147 if l < 4:
144 address += '\x00' * (4 - l)
148 address += b'\x00' * (4 - l)
145149 address = dns.inet.inet_ntop(dns.inet.AF_INET, address)
146150 elif header[0] == 2:
147151 if l < 16:
148 address += '\x00' * (16 - l)
152 address += b'\x00' * (16 - l)
149153 address = dns.inet.inet_ntop(dns.inet.AF_INET6, address)
150154 else:
151155 #
152156 # This isn't really right according to the RFC, but it
153157 # seems better than throwing an exception
154158 #
155 address = address.encode('hex_codec')
159 address = codecs.encode(address, 'hex_codec')
156160 current += afdlen
157161 rdlen -= afdlen
158162 item = APLItem(header[0], negation, address, header[1])
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1921 'AAAA',
2022 'APL',
2123 'DHCID',
24 'IPSECKEY',
2225 'KX',
2326 'NAPTR',
2427 'NSAP',
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1719 __all__ = [
1820 'ANY',
1921 'IN',
22 'CH',
2023 'euibase',
2124 'mxbase',
2225 'nsbase',
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
3739 # We construct the inverse mapping programmatically to ensure that we
3840 # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
3941 # would cause the mapping not to be true inverse.
40 _flag_by_value = dict((y, x) for x, y in _flag_by_text.items())
42 _flag_by_value = {y: x for x, y in _flag_by_text.items()}
4143
4244
4345 def flags_to_text_set(flags):
0 from typing import Set, Any
1
2 SEP : int
3 REVOKE : int
4 ZONE : int
5
6 def flags_to_text_set(flags : int) -> Set[str]:
7 ...
8
9 def flags_from_text_set(texts_set) -> int:
10 ...
11
12 from .. import rdata
13
14 class DNSKEYBase(rdata.Rdata):
15 def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key):
16 self.flags : int
17 self.protocol : int
18 self.key : str
19 self.algorithm : int
20
21 def to_text(self, origin : Any = None, relativize=True, **kw : Any):
22 ...
23
24 @classmethod
25 def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
26 ...
27
28 def to_wire(self, file, compress=None, origin=None):
29 ...
30
31 @classmethod
32 def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
33 ...
34
35 def flags_to_text_set(self) -> Set[str]:
36 ...
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2010, 2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2006-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1921 import dns.exception
2022 import dns.rdata
2123 import dns.tokenizer
22 from dns._compat import binary_type
24 from dns._compat import binary_type, string_types
2325
2426
2527 class TXTBase(dns.rdata.Rdata):
2628
2729 """Base class for rdata that is like a TXT record
2830
29 @ivar strings: the text strings
30 @type strings: list of string
31 @ivar strings: the strings
32 @type strings: list of binary
3133 @see: RFC 1035"""
3234
3335 __slots__ = ['strings']
3436
3537 def __init__(self, rdclass, rdtype, strings):
3638 super(TXTBase, self).__init__(rdclass, rdtype)
37 if isinstance(strings, str):
39 if isinstance(strings, binary_type) or \
40 isinstance(strings, string_types):
3841 strings = [strings]
39 self.strings = strings[:]
42 self.strings = []
43 for string in strings:
44 if isinstance(string, string_types):
45 string = string.encode()
46 self.strings.append(string)
4047
4148 def to_text(self, origin=None, relativize=True, **kw):
4249 txt = ''
4350 prefix = ''
4451 for s in self.strings:
45 txt += '%s"%s"' % (prefix, dns.rdata._escapify(s))
52 txt += '{}"{}"'.format(prefix, dns.rdata._escapify(s))
4653 prefix = ' '
4754 return txt
4855
0 from .. import rdata
1
2 class TXTBase(rdata.Rdata):
3 ...
4 class TXT(TXTBase):
5 ...
0 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2001-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
3133
3234
3335 class Renderer(object):
34
3536 """Helper class for building DNS wire-format messages.
3637
3738 Most applications can use the higher-level L{dns.message.Message}
5354 r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac)
5455 wire = r.get_wire()
5556
56 @ivar output: where rendering is written
57 @type output: BytesIO object
58 @ivar id: the message id
59 @type id: int
60 @ivar flags: the message flags
61 @type flags: int
62 @ivar max_size: the maximum size of the message
63 @type max_size: int
64 @ivar origin: the origin to use when rendering relative names
65 @type origin: dns.name.Name object
66 @ivar compress: the compression table
67 @type compress: dict
68 @ivar section: the section currently being rendered
69 @type section: int (dns.renderer.QUESTION, dns.renderer.ANSWER,
70 dns.renderer.AUTHORITY, or dns.renderer.ADDITIONAL)
71 @ivar counts: list of the number of RRs in each section
72 @type counts: int list of length 4
73 @ivar mac: the MAC of the rendered message (if TSIG was used)
74 @type mac: string
57 output, a BytesIO, where rendering is written
58
59 id: the message id
60
61 flags: the message flags
62
63 max_size: the maximum size of the message
64
65 origin: the origin to use when rendering relative names
66
67 compress: the compression table
68
69 section: an int, the section currently being rendered
70
71 counts: list of the number of RRs in each section
72
73 mac: the MAC of the rendered message (if TSIG was used)
7574 """
7675
7776 def __init__(self, id=None, flags=0, max_size=65535, origin=None):
78 """Initialize a new renderer.
79
80 @param id: the message id
81 @type id: int
82 @param flags: the DNS message flags
83 @type flags: int
84 @param max_size: the maximum message size; the default is 65535.
85 If rendering results in a message greater than I{max_size},
86 then L{dns.exception.TooBig} will be raised.
87 @type max_size: int
88 @param origin: the origin to use when rendering relative names
89 @type origin: dns.name.Name or None.
90 """
77 """Initialize a new renderer."""
9178
9279 self.output = BytesIO()
9380 if id is None:
10491 self.mac = ''
10592
10693 def _rollback(self, where):
107 """Truncate the output buffer at offset I{where}, and remove any
94 """Truncate the output buffer at offset *where*, and remove any
10895 compression table entries that pointed beyond the truncation
10996 point.
110
111 @param where: the offset
112 @type where: int
11397 """
11498
11599 self.output.seek(where)
127111 Sections must be rendered order: QUESTION, ANSWER, AUTHORITY,
128112 ADDITIONAL. Sections may be empty.
129113
130 @param section: the section
131 @type section: int
132 @raises dns.exception.FormError: an attempt was made to set
114 Raises dns.exception.FormError if an attempt was made to set
133115 a section value less than the current section.
134116 """
135117
139121 self.section = section
140122
141123 def add_question(self, qname, rdtype, rdclass=dns.rdataclass.IN):
142 """Add a question to the message.
143
144 @param qname: the question name
145 @type qname: dns.name.Name
146 @param rdtype: the question rdata type
147 @type rdtype: int
148 @param rdclass: the question rdata class
149 @type rdclass: int
150 """
124 """Add a question to the message."""
151125
152126 self._set_section(QUESTION)
153127 before = self.output.tell()
164138
165139 Any keyword arguments are passed on to the rdataset's to_wire()
166140 routine.
167
168 @param section: the section
169 @type section: int
170 @param rrset: the rrset
171 @type rrset: dns.rrset.RRset object
172141 """
173142
174143 self._set_section(section)
186155
187156 Any keyword arguments are passed on to the rdataset's to_wire()
188157 routine.
189
190 @param section: the section
191 @type section: int
192 @param name: the owner name
193 @type name: dns.name.Name object
194 @param rdataset: the rdataset
195 @type rdataset: dns.rdataset.Rdataset object
196158 """
197159
198160 self._set_section(section)
206168 self.counts[section] += n
207169
208170 def add_edns(self, edns, ednsflags, payload, options=None):
209 """Add an EDNS OPT record to the message.
210
211 @param edns: The EDNS level to use.
212 @type edns: int
213 @param ednsflags: EDNS flag values.
214 @type ednsflags: int
215 @param payload: The EDNS sender's payload field, which is the maximum
216 size of UDP datagram the sender can handle.
217 @type payload: int
218 @param options: The EDNS options list
219 @type options: list of dns.edns.Option instances
220 @see: RFC 2671
221 """
171 """Add an EDNS OPT record to the message."""
222172
223173 # make sure the EDNS version in ednsflags agrees with edns
224174 ednsflags &= long(0xFF00FFFF)
254204
255205 def add_tsig(self, keyname, secret, fudge, id, tsig_error, other_data,
256206 request_mac, algorithm=dns.tsig.default_algorithm):
257 """Add a TSIG signature to the message.
258
259 @param keyname: the TSIG key name
260 @type keyname: dns.name.Name object
261 @param secret: the secret to use
262 @type secret: string
263 @param fudge: TSIG time fudge
264 @type fudge: int
265 @param id: the message id to encode in the tsig signature
266 @type id: int
267 @param tsig_error: TSIG error code; default is 0.
268 @type tsig_error: int
269 @param other_data: TSIG other data.
270 @type other_data: string
271 @param request_mac: This message is a response to the request which
272 had the specified MAC.
273 @type request_mac: string
274 @param algorithm: the TSIG algorithm to use
275 @type algorithm: dns.name.Name object
276 """
277
278 self._set_section(ADDITIONAL)
279 before = self.output.tell()
207 """Add a TSIG signature to the message."""
208
280209 s = self.output.getvalue()
281210 (tsig_rdata, self.mac, ctx) = dns.tsig.sign(s,
282211 keyname,
288217 other_data,
289218 request_mac,
290219 algorithm=algorithm)
220 self._write_tsig(tsig_rdata, keyname)
221
222 def add_multi_tsig(self, ctx, keyname, secret, fudge, id, tsig_error,
223 other_data, request_mac,
224 algorithm=dns.tsig.default_algorithm):
225 """Add a TSIG signature to the message. Unlike add_tsig(), this can be
226 used for a series of consecutive DNS envelopes, e.g. for a zone
227 transfer over TCP [RFC2845, 4.4].
228
229 For the first message in the sequence, give ctx=None. For each
230 subsequent message, give the ctx that was returned from the
231 add_multi_tsig() call for the previous message."""
232
233 s = self.output.getvalue()
234 (tsig_rdata, self.mac, ctx) = dns.tsig.sign(s,
235 keyname,
236 secret,
237 int(time.time()),
238 fudge,
239 id,
240 tsig_error,
241 other_data,
242 request_mac,
243 ctx=ctx,
244 first=ctx is None,
245 multi=True,
246 algorithm=algorithm)
247 self._write_tsig(tsig_rdata, keyname)
248 return ctx
249
250 def _write_tsig(self, tsig_rdata, keyname):
251 self._set_section(ADDITIONAL)
252 before = self.output.tell()
253
291254 keyname.to_wire(self.output, self.compress, self.origin)
292255 self.output.write(struct.pack('!HHIH', dns.rdatatype.TSIG,
293256 dns.rdataclass.ANY, 0, 0))
294257 rdata_start = self.output.tell()
295258 self.output.write(tsig_rdata)
259
296260 after = self.output.tell()
297261 assert after - rdata_start < 65536
298262 if after >= self.max_size:
299263 self._rollback(before)
300264 raise dns.exception.TooBig
265
301266 self.output.seek(rdata_start - 2)
302267 self.output.write(struct.pack('!H', after - rdata_start))
303268 self.counts[ADDITIONAL] += 1
320285 self.output.seek(0, 2)
321286
322287 def get_wire(self):
323 """Return the wire format message.
324
325 @rtype: string
326 """
288 """Return the wire format message."""
327289
328290 return self.output.getvalue()
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """DNS stub resolver.
16
17 @var default_resolver: The default resolver object
18 @type default_resolver: dns.resolver.Resolver object"""
17 """DNS stub resolver."""
1918
2019 import socket
2120 import sys
4847 import _winreg # pylint: disable=import-error
4948
5049 class NXDOMAIN(dns.exception.DNSException):
51
5250 """The DNS query name does not exist."""
53 supp_kwargs = set(['qnames', 'responses'])
51 supp_kwargs = {'qnames', 'responses'}
5452 fmt = None # we have our own __str__ implementation
5553
5654 def _check_kwargs(self, qnames, responses=None):
7270 if len(qnames) > 1:
7371 msg = 'None of DNS query names exist'
7472 else:
75 msg = self.__doc__[:-1]
73 msg = 'The DNS query name does not exist'
7674 qnames = ', '.join(map(str, qnames))
77 return "%s: %s" % (msg, qnames)
75 return "{}: {}".format(msg, qnames)
7876
7977 def canonical_name(self):
8078 if not 'qnames' in self.kwargs:
106104 responses0[qname1] = responses1[qname1]
107105 return NXDOMAIN(qnames=qnames0, responses=responses0)
108106
107 def qnames(self):
108 """All of the names that were tried.
109
110 Returns a list of ``dns.name.Name``.
111 """
112 return self.kwargs['qnames']
113
114 def responses(self):
115 """A map from queried names to their NXDOMAIN responses.
116
117 Returns a dict mapping a ``dns.name.Name`` to a
118 ``dns.message.Message``.
119 """
120 return self.kwargs['responses']
121
122 def response(self, qname):
123 """The response for query *qname*.
124
125 Returns a ``dns.message.Message``.
126 """
127 return self.kwargs['responses'][qname]
128
109129
110130 class YXDOMAIN(dns.exception.DNSException):
111
112131 """The DNS query name is too long after DNAME substitution."""
113132
114133 # The definition of the Timeout exception has moved from here to the
119138
120139
121140 class NoAnswer(dns.exception.DNSException):
122
123141 """The DNS response does not contain an answer to the question."""
124142 fmt = 'The DNS response does not contain an answer ' + \
125143 'to the question: {query}'
126 supp_kwargs = set(['response'])
144 supp_kwargs = {'response'}
127145
128146 def _fmt_kwargs(self, **kwargs):
129147 return super(NoAnswer, self)._fmt_kwargs(
131149
132150
133151 class NoNameservers(dns.exception.DNSException):
134
135152 """All nameservers failed to answer the query.
136153
137154 errors: list of servers and respective errors
138155 The type of errors is
139 [(server ip address, any object convertible to string)].
156 [(server IP address, any object convertible to string)].
140157 Non-empty errors list will add explanatory message ()
141158 """
142159
143160 msg = "All nameservers failed to answer the query."
144161 fmt = "%s {query}: {errors}" % msg[:-1]
145 supp_kwargs = set(['request', 'errors'])
162 supp_kwargs = {'request', 'errors'}
146163
147164 def _fmt_kwargs(self, **kwargs):
148165 srv_msgs = []
149166 for err in kwargs['errors']:
150 srv_msgs.append('Server %s %s port %s answered %s' % (err[0],
167 srv_msgs.append('Server {} {} port {} answered {}'.format(err[0],
151168 'TCP' if err[1] else 'UDP', err[2], err[3]))
152169 return super(NoNameservers, self)._fmt_kwargs(
153170 query=kwargs['request'].question, errors='; '.join(srv_msgs))
154171
155172
156173 class NotAbsolute(dns.exception.DNSException):
157
158174 """An absolute domain name is required but a relative name was provided."""
159175
160176
161177 class NoRootSOA(dns.exception.DNSException):
162
163178 """There is no SOA RR at the DNS root name. This should never happen!"""
164179
165180
166181 class NoMetaqueries(dns.exception.DNSException):
167
168182 """DNS metaqueries are not allowed."""
169183
170184
171185 class Answer(object):
172
173 """DNS stub resolver answer
186 """DNS stub resolver answer.
174187
175188 Instances of this class bundle up the result of a successful DNS
176189 resolution.
177190
178191 For convenience, the answer object implements much of the sequence
179 protocol, forwarding to its rrset. E.g. "for a in answer" is
180 equivalent to "for a in answer.rrset", "answer[i]" is equivalent
181 to "answer.rrset[i]", and "answer[i:j]" is equivalent to
182 "answer.rrset[i:j]".
192 protocol, forwarding to its ``rrset`` attribute. E.g.
193 ``for a in answer`` is equivalent to ``for a in answer.rrset``.
194 ``answer[i]`` is equivalent to ``answer.rrset[i]``, and
195 ``answer[i:j]`` is equivalent to ``answer.rrset[i:j]``.
183196
184197 Note that CNAMEs or DNAMEs in the response may mean that answer
185 node's name might not be the query name.
186
187 @ivar qname: The query name
188 @type qname: dns.name.Name object
189 @ivar rdtype: The query type
190 @type rdtype: int
191 @ivar rdclass: The query class
192 @type rdclass: int
193 @ivar response: The response message
194 @type response: dns.message.Message object
195 @ivar rrset: The answer
196 @type rrset: dns.rrset.RRset object
197 @ivar expiration: The time when the answer expires
198 @type expiration: float (seconds since the epoch)
199 @ivar canonical_name: The canonical name of the query name
200 @type canonical_name: dns.name.Name object
198 RRset's name might not be the query name.
201199 """
202200
203201 def __init__(self, qname, rdtype, rdclass, response,
277275 return self.rrset and iter(self.rrset) or iter(tuple())
278276
279277 def __getitem__(self, i):
278 if self.rrset is None:
279 raise IndexError
280280 return self.rrset[i]
281281
282282 def __delitem__(self, i):
283 if self.rrset is None:
284 raise IndexError
283285 del self.rrset[i]
284286
285287
286288 class Cache(object):
287
288 """Simple DNS answer cache.
289
290 @ivar data: A dictionary of cached data
291 @type data: dict
292 @ivar cleaning_interval: The number of seconds between cleanings. The
293 default is 300 (5 minutes).
294 @type cleaning_interval: float
295 @ivar next_cleaning: The time the cache should next be cleaned (in seconds
296 since the epoch.)
297 @type next_cleaning: float
298 """
289 """Simple thread-safe DNS answer cache."""
299290
300291 def __init__(self, cleaning_interval=300.0):
301 """Initialize a DNS cache.
302
303 @param cleaning_interval: the number of seconds between periodic
304 cleanings. The default is 300.0
305 @type cleaning_interval: float.
292 """*cleaning_interval*, a ``float`` is the number of seconds between
293 periodic cleanings.
306294 """
307295
308296 self.data = {}
325313 self.next_cleaning = now + self.cleaning_interval
326314
327315 def get(self, key):
328 """Get the answer associated with I{key}. Returns None if
329 no answer is cached for the key.
330 @param key: the key
331 @type key: (dns.name.Name, int, int) tuple whose values are the
332 query name, rdtype, and rdclass.
333 @rtype: dns.resolver.Answer object or None
316 """Get the answer associated with *key*.
317
318 Returns None if no answer is cached for the key.
319
320 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the
321 query name, rdtype, and rdclass respectively.
322
323 Returns a ``dns.resolver.Answer`` or ``None``.
334324 """
335325
336326 try:
345335
346336 def put(self, key, value):
347337 """Associate key and value in the cache.
348 @param key: the key
349 @type key: (dns.name.Name, int, int) tuple whose values are the
350 query name, rdtype, and rdclass.
351 @param value: The answer being cached
352 @type value: dns.resolver.Answer object
338
339 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the
340 query name, rdtype, and rdclass respectively.
341
342 *value*, a ``dns.resolver.Answer``, the answer.
353343 """
354344
355345 try:
362352 def flush(self, key=None):
363353 """Flush the cache.
364354
365 If I{key} is specified, only that item is flushed. Otherwise
355 If *key* is not ``None``, only that item is flushed. Otherwise
366356 the entire cache is flushed.
367357
368 @param key: the key to flush
369 @type key: (dns.name.Name, int, int) tuple or None
358 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the
359 query name, rdtype, and rdclass respectively.
370360 """
371361
372362 try:
382372
383373
384374 class LRUCacheNode(object):
385
386 """LRUCache node.
387 """
375 """LRUCache node."""
388376
389377 def __init__(self, key, value):
390378 self.key = key
410398
411399
412400 class LRUCache(object):
413
414 """Bounded least-recently-used DNS answer cache.
401 """Thread-safe, bounded, least-recently-used DNS answer cache.
415402
416403 This cache is better than the simple cache (above) if you're
417404 running a web crawler or other process that does a lot of
418405 resolutions. The LRUCache has a maximum number of nodes, and when
419406 it is full, the least-recently used node is removed to make space
420407 for a new one.
421
422 @ivar data: A dictionary of cached data
423 @type data: dict
424 @ivar sentinel: sentinel node for circular doubly linked list of nodes
425 @type sentinel: LRUCacheNode object
426 @ivar max_size: The maximum number of nodes
427 @type max_size: int
428408 """
429409
430410 def __init__(self, max_size=100000):
431 """Initialize a DNS cache.
432
433 @param max_size: The maximum number of nodes to cache; the default is
434 100,000. Must be greater than 1.
435 @type max_size: int
436 """
411 """*max_size*, an ``int``, is the maximum number of nodes to cache;
412 it must be greater than 0.
413 """
414
437415 self.data = {}
438416 self.set_max_size(max_size)
439417 self.sentinel = LRUCacheNode(None, None)
445423 self.max_size = max_size
446424
447425 def get(self, key):
448 """Get the answer associated with I{key}. Returns None if
449 no answer is cached for the key.
450 @param key: the key
451 @type key: (dns.name.Name, int, int) tuple whose values are the
452 query name, rdtype, and rdclass.
453 @rtype: dns.resolver.Answer object or None
454 """
426 """Get the answer associated with *key*.
427
428 Returns None if no answer is cached for the key.
429
430 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the
431 query name, rdtype, and rdclass respectively.
432
433 Returns a ``dns.resolver.Answer`` or ``None``.
434 """
435
455436 try:
456437 self.lock.acquire()
457438 node = self.data.get(key)
470451
471452 def put(self, key, value):
472453 """Associate key and value in the cache.
473 @param key: the key
474 @type key: (dns.name.Name, int, int) tuple whose values are the
475 query name, rdtype, and rdclass.
476 @param value: The answer being cached
477 @type value: dns.resolver.Answer object
478 """
454
455 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the
456 query name, rdtype, and rdclass respectively.
457
458 *value*, a ``dns.resolver.Answer``, the answer.
459 """
460
479461 try:
480462 self.lock.acquire()
481463 node = self.data.get(key)
495477 def flush(self, key=None):
496478 """Flush the cache.
497479
498 If I{key} is specified, only that item is flushed. Otherwise
480 If *key* is not ``None``, only that item is flushed. Otherwise
499481 the entire cache is flushed.
500482
501 @param key: the key to flush
502 @type key: (dns.name.Name, int, int) tuple or None
503 """
483 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the
484 query name, rdtype, and rdclass respectively.
485 """
486
504487 try:
505488 self.lock.acquire()
506489 if key is not None:
521504
522505
523506 class Resolver(object):
524
525 """DNS stub resolver
526
527 @ivar domain: The domain of this host
528 @type domain: dns.name.Name object
529 @ivar nameservers: A list of nameservers to query. Each nameserver is
530 a string which contains the IP address of a nameserver.
531 @type nameservers: list of strings
532 @ivar search: The search list. If the query name is a relative name,
533 the resolver will construct an absolute query name by appending the search
534 names one by one to the query name.
535 @type search: list of dns.name.Name objects
536 @ivar port: The port to which to send queries. The default is 53.
537 @type port: int
538 @ivar timeout: The number of seconds to wait for a response from a
539 server, before timing out.
540 @type timeout: float
541 @ivar lifetime: The total number of seconds to spend trying to get an
542 answer to the question. If the lifetime expires, a Timeout exception
543 will occur.
544 @type lifetime: float
545 @ivar keyring: The TSIG keyring to use. The default is None.
546 @type keyring: dict
547 @ivar keyname: The TSIG keyname to use. The default is None.
548 @type keyname: dns.name.Name object
549 @ivar keyalgorithm: The TSIG key algorithm to use. The default is
550 dns.tsig.default_algorithm.
551 @type keyalgorithm: string
552 @ivar edns: The EDNS level to use. The default is -1, no Edns.
553 @type edns: int
554 @ivar ednsflags: The EDNS flags
555 @type ednsflags: int
556 @ivar payload: The EDNS payload size. The default is 0.
557 @type payload: int
558 @ivar flags: The message flags to use. The default is None (i.e. not
559 overwritten)
560 @type flags: int
561 @ivar cache: The cache to use. The default is None.
562 @type cache: dns.resolver.Cache object
563 @ivar retry_servfail: should we retry a nameserver if it says SERVFAIL?
564 The default is 'false'.
565 @type retry_servfail: bool
566 """
507 """DNS stub resolver."""
567508
568509 def __init__(self, filename='/etc/resolv.conf', configure=True):
569 """Initialize a resolver instance.
570
571 @param filename: The filename of a configuration file in
572 standard /etc/resolv.conf format. This parameter is meaningful
573 only when I{configure} is true and the platform is POSIX.
574 @type filename: string or file object
575 @param configure: If True (the default), the resolver instance
576 is configured in the normal fashion for the operating system
577 the resolver is running on. (I.e. a /etc/resolv.conf file on
578 POSIX systems and from the registry on Windows systems.)
579 @type configure: bool"""
510 """*filename*, a ``text`` or file object, specifying a file
511 in standard /etc/resolv.conf format. This parameter is meaningful
512 only when *configure* is true and the platform is POSIX.
513
514 *configure*, a ``bool``. If True (the default), the resolver
515 instance is configured in the normal fashion for the operating
516 system the resolver is running on. (I.e. by reading a
517 /etc/resolv.conf file on POSIX systems and from the registry
518 on Windows systems.)
519 """
580520
581521 self.domain = None
582522 self.nameservers = None
605545
606546 def reset(self):
607547 """Reset all resolver configuration to the defaults."""
548
608549 self.domain = \
609550 dns.name.Name(dns.name.from_text(socket.gethostname())[1:])
610551 if len(self.domain) == 0:
627568 self.rotate = False
628569
629570 def read_resolv_conf(self, f):
630 """Process f as a file in the /etc/resolv.conf format. If f is
631 a string, it is used as the name of the file to open; otherwise it
571 """Process *f* as a file in the /etc/resolv.conf format. If f is
572 a ``text``, it is used as the name of the file to open; otherwise it
632573 is treated as the file itself."""
574
633575 if isinstance(f, string_types):
634576 try:
635577 f = open(f, 'r')
683625 return split_char
684626
685627 def _config_win32_nameservers(self, nameservers):
686 """Configure a NameServer registry entry."""
687628 # we call str() on nameservers to convert it from unicode to ascii
688629 nameservers = str(nameservers)
689630 split_char = self._determine_split_char(nameservers)
693634 self.nameservers.append(ns)
694635
695636 def _config_win32_domain(self, domain):
696 """Configure a Domain registry entry."""
697637 # we call str() on domain to convert it from unicode to ascii
698638 self.domain = dns.name.from_text(str(domain))
699639
700640 def _config_win32_search(self, search):
701 """Configure a Search registry entry."""
702641 # we call str() on search to convert it from unicode to ascii
703642 search = str(search)
704643 split_char = self._determine_split_char(search)
707646 if s not in self.search:
708647 self.search.append(dns.name.from_text(s))
709648
710 def _config_win32_fromkey(self, key):
711 """Extract DNS info from a registry key."""
649 def _config_win32_fromkey(self, key, always_try_domain):
712650 try:
713651 servers, rtype = _winreg.QueryValueEx(key, 'NameServer')
714652 except WindowsError: # pylint: disable=undefined-variable
715653 servers = None
716654 if servers:
717655 self._config_win32_nameservers(servers)
656 if servers or always_try_domain:
718657 try:
719658 dom, rtype = _winreg.QueryValueEx(key, 'Domain')
720659 if dom:
743682
744683 def read_registry(self):
745684 """Extract resolver configuration from the Windows registry."""
685
746686 lm = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
747687 want_scan = False
748688 try:
758698 r'SYSTEM\CurrentControlSet'
759699 r'\Services\VxD\MSTCP')
760700 try:
761 self._config_win32_fromkey(tcp_params)
701 self._config_win32_fromkey(tcp_params, True)
762702 finally:
763703 tcp_params.Close()
764704 if want_scan:
776716 if not self._win32_is_nic_enabled(lm, guid, key):
777717 continue
778718 try:
779 self._config_win32_fromkey(key)
719 self._config_win32_fromkey(key, False)
780720 finally:
781721 key.Close()
782722 except EnvironmentError:
841781 except WindowsError: # pylint: disable=undefined-variable
842782 return False
843783
844 def _compute_timeout(self, start):
784 def _compute_timeout(self, start, lifetime=None):
785 lifetime = self.lifetime if lifetime is None else lifetime
845786 now = time.time()
846787 duration = now - start
847788 if duration < 0:
853794 # happen, e.g. under vmware with older linux kernels.
854795 # Pretend it didn't happen.
855796 now = start
856 if duration >= self.lifetime:
797 if duration >= lifetime:
857798 raise Timeout(timeout=duration)
858 return min(self.lifetime - duration, self.timeout)
799 return min(lifetime - duration, self.timeout)
859800
860801 def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
861 tcp=False, source=None, raise_on_no_answer=True, source_port=0):
802 tcp=False, source=None, raise_on_no_answer=True, source_port=0,
803 lifetime=None):
862804 """Query nameservers to find the answer to the question.
863805
864 The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
806 The *qname*, *rdtype*, and *rdclass* parameters may be objects
865807 of the appropriate type, or strings that can be converted into objects
866 of the appropriate type. E.g. For I{rdtype} the integer 2 and the
867 the string 'NS' both mean to query for records with DNS rdata type NS.
868
869 @param qname: the query name
870 @type qname: dns.name.Name object or string
871 @param rdtype: the query type
872 @type rdtype: int or string
873 @param rdclass: the query class
874 @type rdclass: int or string
875 @param tcp: use TCP to make the query (default is False).
876 @type tcp: bool
877 @param source: bind to this IP address (defaults to machine default
878 IP).
879 @type source: IP address in dotted quad notation
880 @param raise_on_no_answer: raise NoAnswer if there's no answer
881 (defaults is True).
882 @type raise_on_no_answer: bool
883 @param source_port: The port from which to send the message.
884 The default is 0.
885 @type source_port: int
886 @rtype: dns.resolver.Answer instance
887 @raises Timeout: no answers could be found in the specified lifetime
888 @raises NXDOMAIN: the query name does not exist
889 @raises YXDOMAIN: the query name is too long after DNAME substitution
890 @raises NoAnswer: the response did not contain an answer and
891 raise_on_no_answer is True.
892 @raises NoNameservers: no non-broken nameservers are available to
893 answer the question."""
808 of the appropriate type.
809
810 *qname*, a ``dns.name.Name`` or ``text``, the query name.
811
812 *rdtype*, an ``int`` or ``text``, the query type.
813
814 *rdclass*, an ``int`` or ``text``, the query class.
815
816 *tcp*, a ``bool``. If ``True``, use TCP to make the query.
817
818 *source*, a ``text`` or ``None``. If not ``None``, bind to this IP
819 address when making queries.
820
821 *raise_on_no_answer*, a ``bool``. If ``True``, raise
822 ``dns.resolver.NoAnswer`` if there's no answer to the question.
823
824 *source_port*, an ``int``, the port from which to send the message.
825
826 *lifetime*, a ``float``, how long query should run before timing out.
827
828 Raises ``dns.exception.Timeout`` if no answers could be found
829 in the specified lifetime.
830
831 Raises ``dns.resolver.NXDOMAIN`` if the query name does not exist.
832
833 Raises ``dns.resolver.YXDOMAIN`` if the query name is too long after
834 DNAME substitution.
835
836 Raises ``dns.resolver.NoAnswer`` if *raise_on_no_answer* is
837 ``True`` and the query name exists but has no RRset of the
838 desired type and class.
839
840 Raises ``dns.resolver.NoNameservers`` if no non-broken
841 nameservers are available to answer the question.
842
843 Returns a ``dns.resolver.Answer`` instance.
844 """
894845
895846 if isinstance(qname, string_types):
896847 qname = dns.name.from_text(qname, None)
945896 if len(nameservers) == 0:
946897 raise NoNameservers(request=request, errors=errors)
947898 for nameserver in nameservers[:]:
948 timeout = self._compute_timeout(start)
899 timeout = self._compute_timeout(start, lifetime)
949900 port = self.nameserver_ports.get(nameserver, self.port)
950901 try:
951902 tcp_attempt = tcp
962913 if response.flags & dns.flags.TC:
963914 # Response truncated; retry with TCP.
964915 tcp_attempt = True
965 timeout = self._compute_timeout(start)
916 timeout = self._compute_timeout(start, lifetime)
966917 response = \
967918 dns.query.tcp(request, nameserver,
968919 timeout, port,
1037988 # But we still have servers to try. Sleep a bit
1038989 # so we don't pound them!
1039990 #
1040 timeout = self._compute_timeout(start)
991 timeout = self._compute_timeout(start, lifetime)
1041992 sleep_time = min(timeout, backoff)
1042993 backoff *= 2
1043994 time.sleep(sleep_time)
10581009 algorithm=dns.tsig.default_algorithm):
10591010 """Add a TSIG signature to the query.
10601011
1061 @param keyring: The TSIG keyring to use; defaults to None.
1062 @type keyring: dict
1063 @param keyname: The name of the TSIG key to use; defaults to None.
1064 The key must be defined in the keyring. If a keyring is specified
1065 but a keyname is not, then the key used will be the first key in the
1066 keyring. Note that the order of keys in a dictionary is not defined,
1067 so applications should supply a keyname when a keyring is used, unless
1068 they know the keyring contains only one key.
1069 @param algorithm: The TSIG key algorithm to use. The default
1070 is dns.tsig.default_algorithm.
1071 @type algorithm: string"""
1012 See the documentation of the Message class for a complete
1013 description of the keyring dictionary.
1014
1015 *keyring*, a ``dict``, the TSIG keyring to use. If a
1016 *keyring* is specified but a *keyname* is not, then the key
1017 used will be the first key in the *keyring*. Note that the
1018 order of keys in a dictionary is not defined, so applications
1019 should supply a keyname when a keyring is used, unless they
1020 know the keyring contains only one key.
1021
1022 *keyname*, a ``dns.name.Name`` or ``None``, the name of the TSIG key
1023 to use; defaults to ``None``. The key must be defined in the keyring.
1024
1025 *algorithm*, a ``dns.name.Name``, the TSIG algorithm to use.
1026 """
1027
10721028 self.keyring = keyring
10731029 if keyname is None:
10741030 self.keyname = list(self.keyring.keys())[0]
10771033 self.keyalgorithm = algorithm
10781034
10791035 def use_edns(self, edns, ednsflags, payload):
1080 """Configure Edns.
1081
1082 @param edns: The EDNS level to use. The default is -1, no Edns.
1083 @type edns: int
1084 @param ednsflags: The EDNS flags
1085 @type ednsflags: int
1086 @param payload: The EDNS payload size. The default is 0.
1087 @type payload: int"""
1036 """Configure EDNS behavior.
1037
1038 *edns*, an ``int``, is the EDNS level to use. Specifying
1039 ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case
1040 the other parameters are ignored. Specifying ``True`` is
1041 equivalent to specifying 0, i.e. "use EDNS0".
1042
1043 *ednsflags*, an ``int``, the EDNS flag values.
1044
1045 *payload*, an ``int``, is the EDNS sender's payload field, which is the
1046 maximum size of UDP datagram the sender can handle. I.e. how big
1047 a response to this message can be.
1048 """
10881049
10891050 if edns is None:
10901051 edns = -1
10931054 self.payload = payload
10941055
10951056 def set_flags(self, flags):
1096 """Overrides the default flags with your own
1097
1098 @param flags: The flags to overwrite the default with
1099 @type flags: int"""
1057 """Overrides the default flags with your own.
1058
1059 *flags*, an ``int``, the message flags to use.
1060 """
1061
11001062 self.flags = flags
11011063
1064
1065 #: The default resolver.
11021066 default_resolver = None
11031067
11041068
11121076 def reset_default_resolver():
11131077 """Re-initialize default resolver.
11141078
1115 resolv.conf will be re-read immediatelly.
1079 Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX
1080 systems) will be re-read immediately.
11161081 """
1082
11171083 global default_resolver
11181084 default_resolver = Resolver()
11191085
11201086
11211087 def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
11221088 tcp=False, source=None, raise_on_no_answer=True,
1123 source_port=0):
1089 source_port=0, lifetime=None):
11241090 """Query nameservers to find the answer to the question.
11251091
11261092 This is a convenience function that uses the default resolver
11271093 object to make the query.
1128 @see: L{dns.resolver.Resolver.query} for more information on the
1129 parameters."""
1094
1095 See ``dns.resolver.Resolver.query`` for more information on the
1096 parameters.
1097 """
1098
11301099 return get_default_resolver().query(qname, rdtype, rdclass, tcp, source,
1131 raise_on_no_answer, source_port)
1100 raise_on_no_answer, source_port,
1101 lifetime)
11321102
11331103
11341104 def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
11351105 """Find the name of the zone which contains the specified name.
11361106
1137 @param name: the query name
1138 @type name: absolute dns.name.Name object or string
1139 @param rdclass: The query class
1140 @type rdclass: int
1141 @param tcp: use TCP to make the query (default is False).
1142 @type tcp: bool
1143 @param resolver: the resolver to use
1144 @type resolver: dns.resolver.Resolver object or None
1145 @rtype: dns.name.Name"""
1107 *name*, an absolute ``dns.name.Name`` or ``text``, the query name.
1108
1109 *rdclass*, an ``int``, the query class.
1110
1111 *tcp*, a ``bool``. If ``True``, use TCP to make the query.
1112
1113 *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use.
1114 If ``None``, the default resolver is used.
1115
1116 Raises ``dns.resolver.NoRootSOA`` if there is no SOA RR at the DNS
1117 root. (This is only likely to happen if you're using non-default
1118 root servers in your network and they are misconfigured.)
1119
1120 Returns a ``dns.name.Name``.
1121 """
11461122
11471123 if isinstance(name, string_types):
11481124 name = dns.name.from_text(name, dns.name.root)
12391215 v4addrs.append(rdata.address)
12401216 except dns.resolver.NXDOMAIN:
12411217 raise socket.gaierror(socket.EAI_NONAME)
1242 except:
1218 except Exception:
12431219 raise socket.gaierror(socket.EAI_SYSTEM)
12441220 port = None
12451221 try:
13781354 The resolver to use may be specified; if it's not, the default
13791355 resolver will be used.
13801356
1381 @param resolver: the resolver to use
1382 @type resolver: dns.resolver.Resolver object or None
1357 resolver, a ``dns.resolver.Resolver`` or ``None``, the resolver to use.
13831358 """
1359
13841360 if resolver is None:
13851361 resolver = get_default_resolver()
13861362 global _resolver
13941370
13951371
13961372 def restore_system_resolver():
1397 """Undo the effects of override_system_resolver().
1398 """
1373 """Undo the effects of prior override_system_resolver()."""
1374
13991375 global _resolver
14001376 _resolver = None
14011377 socket.getaddrinfo = _original_getaddrinfo
0 from typing import Union, Optional, List
1 from . import exception, rdataclass, name, rdatatype
2
3 import socket
4 _gethostbyname = socket.gethostbyname
5 class NXDOMAIN(exception.DNSException):
6 ...
7 def query(qname : str, rdtype : Union[int,str] = 0, rdclass : Union[int,str] = 0,
8 tcp=False, source=None, raise_on_no_answer=True,
9 source_port=0):
10 ...
11 class LRUCache:
12 def __init__(self, max_size=1000):
13 ...
14 def get(self, key):
15 ...
16 def put(self, key, val):
17 ...
18 class Answer:
19 def __init__(self, qname, rdtype, rdclass, response,
20 raise_on_no_answer=True):
21 ...
22 def zone_for_name(name, rdclass : int = rdataclass.IN, tcp=False, resolver : Optional[Resolver] = None):
23 ...
24
25 class Resolver:
26 def __init__(self, configure):
27 self.nameservers : List[str]
28 def query(self, qname : str, rdtype : Union[int,str] = rdatatype.A, rdclass : Union[int,str] = rdataclass.IN,
29 tcp : bool = False, source : Optional[str] = None, raise_on_no_answer=True, source_port : int = 0):
30 ...
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2006-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """DNS Reverse Map Names.
16
17 @var ipv4_reverse_domain: The DNS IPv4 reverse-map domain, in-addr.arpa.
18 @type ipv4_reverse_domain: dns.name.Name object
19 @var ipv6_reverse_domain: The DNS IPv6 reverse-map domain, ip6.arpa.
20 @type ipv6_reverse_domain: dns.name.Name object
21 """
17 """DNS Reverse Map Names."""
2218
2319 import binascii
24 import sys
2520
2621 import dns.name
2722 import dns.ipv6
2823 import dns.ipv4
24
25 from dns._compat import PY3
2926
3027 ipv4_reverse_domain = dns.name.from_text('in-addr.arpa.')
3128 ipv6_reverse_domain = dns.name.from_text('ip6.arpa.')
3431 def from_address(text):
3532 """Convert an IPv4 or IPv6 address in textual form into a Name object whose
3633 value is the reverse-map domain name of the address.
37 @param text: an IPv4 or IPv6 address in textual form (e.g. '127.0.0.1',
38 '::1')
39 @type text: str
40 @rtype: dns.name.Name object
34
35 *text*, a ``text``, is an IPv4 or IPv6 address in textual form
36 (e.g. '127.0.0.1', '::1')
37
38 Raises ``dns.exception.SyntaxError`` if the address is badly formed.
39
40 Returns a ``dns.name.Name``.
4141 """
42
4243 try:
4344 v6 = dns.ipv6.inet_aton(text)
4445 if dns.ipv6.is_mapped(v6):
45 if sys.version_info >= (3,):
46 if PY3:
4647 parts = ['%d' % byte for byte in v6[12:]]
4748 else:
4849 parts = ['%d' % ord(byte) for byte in v6[12:]]
6061
6162 def to_address(name):
6263 """Convert a reverse map domain name into textual address form.
63 @param name: an IPv4 or IPv6 address in reverse-map form.
64 @type name: dns.name.Name object
65 @rtype: str
64
65 *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name
66 form.
67
68 Raises ``dns.exception.SyntaxError`` if the name does not have a
69 reverse-map form.
70
71 Returns a ``text``.
6672 """
73
6774 if name.is_subdomain(ipv4_reverse_domain):
6875 name = name.relativize(ipv4_reverse_domain)
6976 labels = list(name.labels)
0 from . import name
1 def from_address(text : str) -> name.Name:
2 ...
3
4 def to_address(name : name.Name) -> str:
5 ...
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
6668 return self.to_text()
6769
6870 def __eq__(self, other):
69 """Two RRsets are equal if they have the same name and the same
70 rdataset
71
72 @rtype: bool"""
7371 if not isinstance(other, RRset):
7472 return False
7573 if self.name != other.name:
7775 return super(RRset, self).__eq__(other)
7876
7977 def match(self, name, rdclass, rdtype, covers, deleting=None):
80 """Returns True if this rrset matches the specified class, type,
81 covers, and deletion state."""
78 """Returns ``True`` if this rrset matches the specified class, type,
79 covers, and deletion state.
80 """
8281
8382 if not super(RRset, self).match(rdclass, rdtype, covers):
8483 return False
8988 def to_text(self, origin=None, relativize=True, **kw):
9089 """Convert the RRset into DNS master file format.
9190
92 @see: L{dns.name.Name.choose_relativity} for more information
93 on how I{origin} and I{relativize} determine the way names
91 See ``dns.name.Name.choose_relativity`` for more information
92 on how *origin* and *relativize* determine the way names
9493 are emitted.
9594
9695 Any additional keyword arguments are passed on to the rdata
97 to_text() method.
96 ``to_text()`` method.
9897
99 @param origin: The origin for relative names, or None.
100 @type origin: dns.name.Name object
101 @param relativize: True if names should names be relativized
102 @type relativize: bool"""
98 *origin*, a ``dns.name.Name`` or ``None``, the origin for relative
99 names.
100
101 *relativize*, a ``bool``. If ``True``, names will be relativized
102 to *origin*.
103 """
103104
104105 return super(RRset, self).to_text(self.name, origin, relativize,
105106 self.deleting, **kw)
106107
107108 def to_wire(self, file, compress=None, origin=None, **kw):
108 """Convert the RRset to wire format."""
109 """Convert the RRset to wire format.
110
111 All keyword arguments are passed to ``dns.rdataset.to_wire()``; see
112 that function for details.
113
114 Returns an ``int``, the number of records emitted.
115 """
109116
110117 return super(RRset, self).to_wire(self.name, file, compress, origin,
111118 self.deleting, **kw)
113120 def to_rdataset(self):
114121 """Convert an RRset into an Rdataset.
115122
116 @rtype: dns.rdataset.Rdataset object
123 Returns a ``dns.rdataset.Rdataset``.
117124 """
118125 return dns.rdataset.from_rdata_list(self.ttl, list(self))
119126
123130 """Create an RRset with the specified name, TTL, class, and type, and with
124131 the specified list of rdatas in text format.
125132
126 @rtype: dns.rrset.RRset object
133 Returns a ``dns.rrset.RRset`` object.
127134 """
128135
129136 if isinstance(name, string_types):
144151 """Create an RRset with the specified name, TTL, class, and type and with
145152 the specified rdatas in text format.
146153
147 @rtype: dns.rrset.RRset object
154 Returns a ``dns.rrset.RRset`` object.
148155 """
149156
150157 return from_text_list(name, ttl, rdclass, rdtype, text_rdatas)
154161 """Create an RRset with the specified name and TTL, and with
155162 the specified list of rdata objects.
156163
157 @rtype: dns.rrset.RRset object
164 Returns a ``dns.rrset.RRset`` object.
158165 """
159166
160167 if isinstance(name, string_types):
175182 """Create an RRset with the specified name and TTL, and with
176183 the specified rdata objects.
177184
178 @rtype: dns.rrset.RRset object
185 Returns a ``dns.rrset.RRset`` object.
179186 """
180187
181188 return from_rdata_list(name, ttl, rdatas)
0 from typing import List, Optional
1 from . import rdataset, rdatatype
2
3 class RRset(rdataset.Rdataset):
4 def __init__(self, name, rdclass : int , rdtype : int, covers=rdatatype.NONE,
5 deleting : Optional[int] =None) -> None:
6 self.name = name
7 self.deleting = deleting
8 def from_text(name : str, ttl : int, rdclass : str, rdtype : str, *text_rdatas : str):
9 ...
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 """A simple Set class."""
16
17
1817 class Set(object):
1918
2019 """A simple set class.
2120
22 Sets are not in Python until 2.3, and rdata are not immutable so
23 we cannot use sets.Set anyway. This class implements subset of
24 the 2.3 Set interface using a list as the container.
25
26 @ivar items: A list of the items which are in the set
27 @type items: list"""
21 This class was originally used to deal with sets being missing in
22 ancient versions of python, but dnspython will continue to use it
23 as these sets are based on lists and are thus indexable, and this
24 ability is widely used in dnspython applications.
25 """
2826
2927 __slots__ = ['items']
3028
3129 def __init__(self, items=None):
3230 """Initialize the set.
3331
34 @param items: the initial set of items
35 @type items: any iterable or None
32 *items*, an iterable or ``None``, the initial set of items.
3633 """
3734
3835 self.items = []
4441 return "dns.simpleset.Set(%s)" % repr(self.items)
4542
4643 def add(self, item):
47 """Add an item to the set."""
44 """Add an item to the set.
45 """
46
4847 if item not in self.items:
4948 self.items.append(item)
5049
5150 def remove(self, item):
52 """Remove an item from the set."""
51 """Remove an item from the set.
52 """
53
5354 self.items.remove(item)
5455
5556 def discard(self, item):
56 """Remove an item from the set if present."""
57 """Remove an item from the set if present.
58 """
59
5760 try:
5861 self.items.remove(item)
5962 except ValueError:
7881 return obj
7982
8083 def __copy__(self):
81 """Make a (shallow) copy of the set."""
84 """Make a (shallow) copy of the set.
85 """
86
8287 return self._clone()
8388
8489 def copy(self):
85 """Make a (shallow) copy of the set."""
90 """Make a (shallow) copy of the set.
91 """
92
8693 return self._clone()
8794
8895 def union_update(self, other):
8996 """Update the set, adding any elements from other which are not
9097 already in the set.
91 @param other: the collection of items with which to update the set
92 @type other: Set object
93 """
98 """
99
94100 if not isinstance(other, Set):
95101 raise ValueError('other must be a Set instance')
96102 if self is other:
101107 def intersection_update(self, other):
102108 """Update the set, removing any elements from other which are not
103109 in both sets.
104 @param other: the collection of items with which to update the set
105 @type other: Set object
106 """
110 """
111
107112 if not isinstance(other, Set):
108113 raise ValueError('other must be a Set instance')
109114 if self is other:
117122 def difference_update(self, other):
118123 """Update the set, removing any elements from other which are in
119124 the set.
120 @param other: the collection of items with which to update the set
121 @type other: Set object
122 """
125 """
126
123127 if not isinstance(other, Set):
124128 raise ValueError('other must be a Set instance')
125129 if self is other:
129133 self.discard(item)
130134
131135 def union(self, other):
132 """Return a new set which is the union of I{self} and I{other}.
133
134 @param other: the other set
135 @type other: Set object
136 @rtype: the same type as I{self}
136 """Return a new set which is the union of ``self`` and ``other``.
137
138 Returns the same Set type as this set.
137139 """
138140
139141 obj = self._clone()
141143 return obj
142144
143145 def intersection(self, other):
144 """Return a new set which is the intersection of I{self} and I{other}.
145
146 @param other: the other set
147 @type other: Set object
148 @rtype: the same type as I{self}
146 """Return a new set which is the intersection of ``self`` and
147 ``other``.
148
149 Returns the same Set type as this set.
149150 """
150151
151152 obj = self._clone()
153154 return obj
154155
155156 def difference(self, other):
156 """Return a new set which I{self} - I{other}, i.e. the items
157 in I{self} which are not also in I{other}.
158
159 @param other: the other set
160 @type other: Set object
161 @rtype: the same type as I{self}
157 """Return a new set which ``self`` - ``other``, i.e. the items
158 in ``self`` which are not also in ``other``.
159
160 Returns the same Set type as this set.
162161 """
163162
164163 obj = self._clone()
196195 def update(self, other):
197196 """Update the set, adding any elements from other which are not
198197 already in the set.
199 @param other: the collection of items with which to update the set
200 @type other: any iterable type"""
198
199 *other*, the collection of items with which to update the set, which
200 may be any iterable type.
201 """
202
201203 for item in other:
202204 self.add(item)
203205
232234 del self.items[i]
233235
234236 def issubset(self, other):
235 """Is I{self} a subset of I{other}?
236
237 @rtype: bool
237 """Is this set a subset of *other*?
238
239 Returns a ``bool``.
238240 """
239241
240242 if not isinstance(other, Set):
245247 return True
246248
247249 def issuperset(self, other):
248 """Is I{self} a superset of I{other}?
249
250 @rtype: bool
250 """Is this set a superset of *other*?
251
252 Returns a ``bool``.
251253 """
252254
253255 if not isinstance(other, Set):
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
4345
4446
4547 class UngetBufferFull(dns.exception.DNSException):
46
4748 """An attempt was made to unget a token when the unget buffer was full."""
4849
4950
5051 class Token(object):
51
5252 """A DNS master file format token.
5353
54 @ivar ttype: The token type
55 @type ttype: int
56 @ivar value: The token value
57 @type value: string
58 @ivar has_escape: Does the token value contain escapes?
59 @type has_escape: bool
54 ttype: The token type
55 value: The token value
56 has_escape: Does the token value contain escapes?
6057 """
6158
6259 def __init__(self, ttype, value='', has_escape=False):
63 """Initialize a token instance.
64
65 @param ttype: The token type
66 @type ttype: int
67 @param value: The token value
68 @type value: string
69 @param has_escape: Does the token value contain escapes?
70 @type has_escape: bool
71 """
60 """Initialize a token instance."""
61
7262 self.ttype = ttype
7363 self.value = value
7464 self.has_escape = has_escape
159149
160150
161151 class Tokenizer(object):
162
163152 """A DNS master file format tokenizer.
164153
165 A token is a (type, value) tuple, where I{type} is an int, and
166 I{value} is a string. The valid types are EOF, EOL, WHITESPACE,
167 IDENTIFIER, QUOTED_STRING, COMMENT, and DELIMITER.
168
169 @ivar file: The file to tokenize
170 @type file: file
171 @ivar ungotten_char: The most recently ungotten character, or None.
172 @type ungotten_char: string
173 @ivar ungotten_token: The most recently ungotten token, or None.
174 @type ungotten_token: (int, string) token tuple
175 @ivar multiline: The current multiline level. This value is increased
154 A token object is basically a (type, value) tuple. The valid
155 types are EOF, EOL, WHITESPACE, IDENTIFIER, QUOTED_STRING,
156 COMMENT, and DELIMITER.
157
158 file: The file to tokenize
159
160 ungotten_char: The most recently ungotten character, or None.
161
162 ungotten_token: The most recently ungotten token, or None.
163
164 multiline: The current multiline level. This value is increased
176165 by one every time a '(' delimiter is read, and decreased by one every time
177166 a ')' delimiter is read.
178 @type multiline: int
179 @ivar quoting: This variable is true if the tokenizer is currently
167
168 quoting: This variable is true if the tokenizer is currently
180169 reading a quoted string.
181 @type quoting: bool
182 @ivar eof: This variable is true if the tokenizer has encountered EOF.
183 @type eof: bool
184 @ivar delimiters: The current delimiter dictionary.
185 @type delimiters: dict
186 @ivar line_number: The current line number
187 @type line_number: int
188 @ivar filename: A filename that will be returned by the L{where} method.
189 @type filename: string
170
171 eof: This variable is true if the tokenizer has encountered EOF.
172
173 delimiters: The current delimiter dictionary.
174
175 line_number: The current line number
176
177 filename: A filename that will be returned by the where() method.
190178 """
191179
192180 def __init__(self, f=sys.stdin, filename=None):
193181 """Initialize a tokenizer instance.
194182
195 @param f: The file to tokenize. The default is sys.stdin.
183 f: The file to tokenize. The default is sys.stdin.
196184 This parameter may also be a string, in which case the tokenizer
197185 will take its input from the contents of the string.
198 @type f: file or string
199 @param filename: the name of the filename that the L{where} method
186
187 filename: the name of the filename that the where() method
200188 will return.
201 @type filename: string
202189 """
203190
204191 if isinstance(f, text_type):
227214
228215 def _get_char(self):
229216 """Read a character from input.
230 @rtype: string
231217 """
232218
233219 if self.ungotten_char is None:
247233 def where(self):
248234 """Return the current location in the input.
249235
250 @rtype: (string, int) tuple. The first item is the filename of
236 Returns a (string, int) tuple. The first item is the filename of
251237 the input, the second is the current line number.
252238 """
253239
260246 an error to try to unget a character when the unget buffer is not
261247 empty.
262248
263 @param c: the character to unget
264 @type c: string
265 @raises UngetBufferFull: there is already an ungotten char
249 c: the character to unget
250 raises UngetBufferFull: there is already an ungotten char
266251 """
267252
268253 if self.ungotten_char is not None:
277262
278263 If the tokenizer is in multiline mode, then newlines are whitespace.
279264
280 @rtype: int
265 Returns the number of characters skipped.
281266 """
282267
283268 skipped = 0
292277 def get(self, want_leading=False, want_comment=False):
293278 """Get the next token.
294279
295 @param want_leading: If True, return a WHITESPACE token if the
280 want_leading: If True, return a WHITESPACE token if the
296281 first character read is whitespace. The default is False.
297 @type want_leading: bool
298 @param want_comment: If True, return a COMMENT token if the
282
283 want_comment: If True, return a COMMENT token if the
299284 first token read is a comment. The default is False.
300 @type want_comment: bool
301 @rtype: Token object
302 @raises dns.exception.UnexpectedEnd: input ended prematurely
303 @raises dns.exception.SyntaxError: input was badly formed
285
286 Raises dns.exception.UnexpectedEnd: input ended prematurely
287
288 Raises dns.exception.SyntaxError: input was badly formed
289
290 Returns a Token.
304291 """
305292
306293 if self.ungotten_token is not None:
419406 an error to try to unget a token when the unget buffer is not
420407 empty.
421408
422 @param token: the token to unget
423 @type token: Token object
424 @raises UngetBufferFull: there is already an ungotten token
409 token: the token to unget
410
411 Raises UngetBufferFull: there is already an ungotten token
425412 """
426413
427414 if self.ungotten_token is not None:
430417
431418 def next(self):
432419 """Return the next item in an iteration.
433 @rtype: (int, string)
420
421 Returns a Token.
434422 """
435423
436424 token = self.get()
445433
446434 # Helpers
447435
448 def get_int(self):
436 def get_int(self, base=10):
449437 """Read the next token and interpret it as an integer.
450438
451 @raises dns.exception.SyntaxError:
452 @rtype: int
439 Raises dns.exception.SyntaxError if not an integer.
440
441 Returns an int.
453442 """
454443
455444 token = self.get().unescape()
457446 raise dns.exception.SyntaxError('expecting an identifier')
458447 if not token.value.isdigit():
459448 raise dns.exception.SyntaxError('expecting an integer')
460 return int(token.value)
449 return int(token.value, base)
461450
462451 def get_uint8(self):
463452 """Read the next token and interpret it as an 8-bit unsigned
464453 integer.
465454
466 @raises dns.exception.SyntaxError:
467 @rtype: int
455 Raises dns.exception.SyntaxError if not an 8-bit unsigned integer.
456
457 Returns an int.
468458 """
469459
470460 value = self.get_int()
473463 '%d is not an unsigned 8-bit integer' % value)
474464 return value
475465
476 def get_uint16(self):
466 def get_uint16(self, base=10):
477467 """Read the next token and interpret it as a 16-bit unsigned
478468 integer.
479469
480 @raises dns.exception.SyntaxError:
481 @rtype: int
482 """
483
484 value = self.get_int()
470 Raises dns.exception.SyntaxError if not a 16-bit unsigned integer.
471
472 Returns an int.
473 """
474
475 value = self.get_int(base=base)
485476 if value < 0 or value > 65535:
486 raise dns.exception.SyntaxError(
487 '%d is not an unsigned 16-bit integer' % value)
477 if base == 8:
478 raise dns.exception.SyntaxError(
479 '%o is not an octal unsigned 16-bit integer' % value)
480 else:
481 raise dns.exception.SyntaxError(
482 '%d is not an unsigned 16-bit integer' % value)
488483 return value
489484
490485 def get_uint32(self):
491486 """Read the next token and interpret it as a 32-bit unsigned
492487 integer.
493488
494 @raises dns.exception.SyntaxError:
495 @rtype: int
489 Raises dns.exception.SyntaxError if not a 32-bit unsigned integer.
490
491 Returns an int.
496492 """
497493
498494 token = self.get().unescape()
509505 def get_string(self, origin=None):
510506 """Read the next token and interpret it as a string.
511507
512 @raises dns.exception.SyntaxError:
513 @rtype: string
508 Raises dns.exception.SyntaxError if not a string.
509
510 Returns a string.
514511 """
515512
516513 token = self.get().unescape()
519516 return token.value
520517
521518 def get_identifier(self, origin=None):
522 """Read the next token and raise an exception if it is not an identifier.
523
524 @raises dns.exception.SyntaxError:
525 @rtype: string
519 """Read the next token, which should be an identifier.
520
521 Raises dns.exception.SyntaxError if not an identifier.
522
523 Returns a string.
526524 """
527525
528526 token = self.get().unescape()
533531 def get_name(self, origin=None):
534532 """Read the next token and interpret it as a DNS name.
535533
536 @raises dns.exception.SyntaxError:
537 @rtype: dns.name.Name object"""
534 Raises dns.exception.SyntaxError if not a name.
535
536 Returns a dns.name.Name.
537 """
538538
539539 token = self.get()
540540 if not token.is_identifier():
545545 """Read the next token and raise an exception if it isn't EOL or
546546 EOF.
547547
548 @raises dns.exception.SyntaxError:
549 @rtype: string
548 Returns a string.
550549 """
551550
552551 token = self.get()
557556 return token.value
558557
559558 def get_ttl(self):
559 """Read the next token and interpret it as a DNS TTL.
560
561 Raises dns.exception.SyntaxError or dns.ttl.BadTTL if not an
562 identifier or badly formed.
563
564 Returns an int.
565 """
566
560567 token = self.get().unescape()
561568 if not token.is_identifier():
562569 raise dns.exception.SyntaxError('expecting an identifier')
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1416
1517 """DNS TSIG support."""
1618
19 import hashlib
1720 import hmac
1821 import struct
1922
2023 import dns.exception
21 import dns.hash
2224 import dns.rdataclass
2325 import dns.name
2426 from ._compat import long, string_types, text_type
6769 HMAC_SHA512 = dns.name.from_text("hmac-sha512")
6870
6971 _hashes = {
70 HMAC_SHA224: 'SHA224',
71 HMAC_SHA256: 'SHA256',
72 HMAC_SHA384: 'SHA384',
73 HMAC_SHA512: 'SHA512',
74 HMAC_SHA1: 'SHA1',
75 HMAC_MD5: 'MD5',
72 HMAC_SHA224: hashlib.sha224,
73 HMAC_SHA256: hashlib.sha256,
74 HMAC_SHA384: hashlib.sha384,
75 HMAC_SHA512: hashlib.sha512,
76 HMAC_SHA1: hashlib.sha1,
77 HMAC_MD5: hashlib.md5,
7678 }
7779
7880 default_algorithm = HMAC_MD5
210212 algorithm = dns.name.from_text(algorithm)
211213
212214 try:
213 return (algorithm.to_digestable(), dns.hash.hashes[_hashes[algorithm]])
215 return (algorithm.to_digestable(), _hashes[algorithm])
214216 except KeyError:
215217 raise NotImplementedError("TSIG algorithm " + str(algorithm) +
216218 " is not supported")
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
0 from typing import Dict
1 from . import name
2
3 def from_text(textring : Dict[str,str]) -> Dict[name.Name,bytes]:
4 ...
5 def to_text(keyring : Dict[name.Name,bytes]) -> Dict[str, str]:
6 ...
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1921
2022
2123 class BadTTL(dns.exception.SyntaxError):
22
2324 """DNS TTL value is not well-formed."""
2425
2526
2829
2930 The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported.
3031
31 @param text: the textual TTL
32 @type text: string
33 @raises dns.ttl.BadTTL: the TTL is not well-formed
34 @rtype: int
32 *text*, a ``text``, the textual TTL.
33
34 Raises ``dns.ttl.BadTTL`` if the TTL is not well-formed.
35
36 Returns an ``int``.
3537 """
3638
3739 if text.isdigit():
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
3133 keyname=None, keyalgorithm=dns.tsig.default_algorithm):
3234 """Initialize a new DNS Update object.
3335
34 @param zone: The zone which is being updated.
35 @type zone: A dns.name.Name or string
36 @param rdclass: The class of the zone; defaults to dns.rdataclass.IN.
37 @type rdclass: An int designating the class, or a string whose value
38 is the name of a class.
39 @param keyring: The TSIG keyring to use; defaults to None.
40 @type keyring: dict
41 @param keyname: The name of the TSIG key to use; defaults to None.
42 The key must be defined in the keyring. If a keyring is specified
43 but a keyname is not, then the key used will be the first key in the
44 keyring. Note that the order of keys in a dictionary is not defined,
45 so applications should supply a keyname when a keyring is used, unless
46 they know the keyring contains only one key.
47 @type keyname: dns.name.Name or string
48 @param keyalgorithm: The TSIG algorithm to use; defaults to
49 dns.tsig.default_algorithm. Constants for TSIG algorithms are defined
50 in dns.tsig, and the currently implemented algorithms are
51 HMAC_MD5, HMAC_SHA1, HMAC_SHA224, HMAC_SHA256, HMAC_SHA384, and
52 HMAC_SHA512.
53 @type keyalgorithm: string
36 See the documentation of the Message class for a complete
37 description of the keyring dictionary.
38
39 *zone*, a ``dns.name.Name`` or ``text``, the zone which is being
40 updated.
41
42 *rdclass*, an ``int`` or ``text``, the class of the zone.
43
44 *keyring*, a ``dict``, the TSIG keyring to use. If a
45 *keyring* is specified but a *keyname* is not, then the key
46 used will be the first key in the *keyring*. Note that the
47 order of keys in a dictionary is not defined, so applications
48 should supply a keyname when a keyring is used, unless they
49 know the keyring contains only one key.
50
51 *keyname*, a ``dns.name.Name`` or ``None``, the name of the TSIG key
52 to use; defaults to ``None``. The key must be defined in the keyring.
53
54 *keyalgorithm*, a ``dns.name.Name``, the TSIG algorithm to use.
5455 """
5556 super(Update, self).__init__()
5657 self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE)
7677 rrset.add(rd, ttl)
7778
7879 def _add(self, replace, section, name, *args):
79 """Add records. The first argument is the replace mode. If
80 false, RRs are added to an existing RRset; if true, the RRset
80 """Add records.
81
82 *replace* is the replacement mode. If ``False``,
83 RRs are added to an existing RRset; if ``True``, the RRset
8184 is replaced with the specified contents. The second
8285 argument is the section to add to. The third argument
8386 is always a name. The other arguments can be:
8689
8790 - ttl, rdata...
8891
89 - ttl, rdtype, string..."""
92 - ttl, rdtype, string...
93 """
9094
9195 if isinstance(name, string_types):
9296 name = dns.name.from_text(name, None)
116120 self._add_rr(name, ttl, rd, section=section)
117121
118122 def add(self, name, *args):
119 """Add records. The first argument is always a name. The other
123 """Add records.
124
125 The first argument is always a name. The other
120126 arguments can be:
121127
122128 - rdataset...
123129
124130 - ttl, rdata...
125131
126 - ttl, rdtype, string..."""
132 - ttl, rdtype, string...
133 """
134
127135 self._add(False, self.authority, name, *args)
128136
129137 def delete(self, name, *args):
130 """Delete records. The first argument is always a name. The other
138 """Delete records.
139
140 The first argument is always a name. The other
131141 arguments can be:
132142
133 - I{nothing}
143 - *empty*
134144
135145 - rdataset...
136146
137147 - rdata...
138148
139 - rdtype, [string...]"""
149 - rdtype, [string...]
150 """
140151
141152 if isinstance(name, string_types):
142153 name = dns.name.from_text(name, None)
170181 self._add_rr(name, 0, rd, dns.rdataclass.NONE)
171182
172183 def replace(self, name, *args):
173 """Replace records. The first argument is always a name. The other
184 """Replace records.
185
186 The first argument is always a name. The other
174187 arguments can be:
175188
176189 - rdataset...
180193 - ttl, rdtype, string...
181194
182195 Note that if you want to replace the entire node, you should do
183 a delete of the name followed by one or more calls to add."""
196 a delete of the name followed by one or more calls to add.
197 """
184198
185199 self._add(True, self.authority, name, *args)
186200
187201 def present(self, name, *args):
188202 """Require that an owner name (and optionally an rdata type,
189203 or specific rdataset) exists as a prerequisite to the
190 execution of the update. The first argument is always a name.
204 execution of the update.
205
206 The first argument is always a name.
191207 The other arguments can be:
192208
193209 - rdataset...
194210
195211 - rdata...
196212
197 - rdtype, string..."""
213 - rdtype, string...
214 """
198215
199216 if isinstance(name, string_types):
200217 name = dns.name.from_text(name, None)
242259 def to_wire(self, origin=None, max_size=65535):
243260 """Return a string containing the update in DNS compressed wire
244261 format.
245 @rtype: string"""
262
263 *origin*, a ``dns.name.Name`` or ``None``, the origin to be
264 appended to any relative names. If *origin* is ``None``, then
265 the origin of the ``dns.update.Update`` message object is used
266 (i.e. the *zone* parameter passed when the Update object was
267 created).
268
269 *max_size*, an ``int``, the maximum size of the wire format
270 output; default is 0, which means "the message's request
271 payload, if nonzero, or 65535".
272
273 Returns a ``binary``.
274 """
275
246276 if origin is None:
247277 origin = self.origin
248278 return super(Update, self).to_wire(origin, max_size)
0 from typing import Optional,Dict,Union,Any
1
2 from . import message, tsig, rdataclass, name
3
4 class Update(message.Message):
5 def __init__(self, zone : Union[name.Name, str], rdclass : Union[int,str] = rdataclass.IN, keyring : Optional[Dict[name.Name,bytes]] = None,
6 keyname : Optional[name.Name] = None, keyalgorithm : Optional[name.Name] = tsig.default_algorithm) -> None:
7 self.id : int
8 def add(self, name : Union[str,name.Name], *args : Any):
9 ...
10 def delete(self, name, *args : Any):
11 ...
12 def replace(self, name : Union[str,name.Name], *args : Any):
13 ...
14 def present(self, name : Union[str,name.Name], *args : Any):
15 ...
16 def absent(self, name : Union[str,name.Name], rdtype=None):
17 """Require that an owner name (and optionally an rdata type) does
18 not exist as a prerequisite to the execution of the update."""
19 def to_wire(self, origin : Optional[name.Name] = None, max_size=65535, **kw) -> bytes:
20 ...
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1416
1517 """dnspython release version information."""
1618
19 #: MAJOR
1720 MAJOR = 1
18 MINOR = 15
21 #: MINOR
22 MINOR = 16
23 #: MICRO
1924 MICRO = 0
25 #: RELEASELEVEL
2026 RELEASELEVEL = 0x0f
27 #: SERIAL
2128 SERIAL = 0
2229
2330 if RELEASELEVEL == 0x0f:
31 #: version
2432 version = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
2533 elif RELEASELEVEL == 0x00:
2634 version = '%d.%d.%dx%d' % \
2937 version = '%d.%d.%d%x%d' % \
3038 (MAJOR, MINOR, MICRO, RELEASELEVEL, SERIAL)
3139
40 #: hexversion
3241 hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | \
3342 SERIAL
0 # Copyright (C) 2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2011,2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1416
1517 """DNS Wire Data Helper"""
1618
17 import sys
18
1919 import dns.exception
20 from ._compat import binary_type, string_types
20 from ._compat import binary_type, string_types, PY2
2121
2222 # Figure out what constant python passes for an unspecified slice bound.
2323 # It's supposed to be sys.maxint, yet on 64-bit windows sys.maxint is 2^31 - 1
3131 def __getitem__(self, key):
3232 return key.stop
3333
34 if sys.version_info < (3,):
34 if PY2:
3535 def __getslice__(self, i, j): # pylint: disable=getslice-method
3636 return self.__getitem__(slice(i, j))
3737
3939
4040
4141 class WireData(binary_type):
42 # WireData is a string with stricter slicing
42 # WireData is a binary type with stricter slicing
4343
4444 def __getitem__(self, key):
4545 try:
5050 start = key.start
5151 stop = key.stop
5252
53 if sys.version_info < (3,):
53 if PY2:
5454 if stop == _unspecified_bound:
5555 # handle the case where the right bound is unspecified
5656 stop = len(self)
7575 except IndexError:
7676 raise dns.exception.FormError
7777
78 if sys.version_info < (3,):
78 if PY2:
7979 def __getslice__(self, i, j): # pylint: disable=getslice-method
8080 return self.__getitem__(slice(i, j))
8181
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
2729 import dns.rdataclass
2830 import dns.rdatatype
2931 import dns.rdata
32 import dns.rdtypes.ANY.SOA
3033 import dns.rrset
3134 import dns.tokenizer
3235 import dns.ttl
3336 import dns.grange
34 from ._compat import string_types, text_type
35
36
37 _py3 = sys.version_info > (3,)
37 from ._compat import string_types, text_type, PY3
3838
3939
4040 class BadZone(dns.exception.DNSException):
156156 return self.nodes.__iter__()
157157
158158 def iterkeys(self):
159 if _py3:
160 return self.nodes.keys()
159 if PY3:
160 return self.nodes.keys() # pylint: disable=dict-keys-not-iterating
161161 else:
162162 return self.nodes.iterkeys() # pylint: disable=dict-iter-method
163163
164164 def keys(self):
165 return self.nodes.keys()
165 return self.nodes.keys() # pylint: disable=dict-keys-not-iterating
166166
167167 def itervalues(self):
168 if _py3:
169 return self.nodes.values()
168 if PY3:
169 return self.nodes.values() # pylint: disable=dict-values-not-iterating
170170 else:
171171 return self.nodes.itervalues() # pylint: disable=dict-iter-method
172172
173173 def values(self):
174 return self.nodes.values()
174 return self.nodes.values() # pylint: disable=dict-values-not-iterating
175175
176176 def items(self):
177 return self.nodes.items()
177 return self.nodes.items() # pylint: disable=dict-items-not-iterating
178178
179179 iteritems = items
180180
260260 exist?
261261 @type create: bool
262262 @raises KeyError: the node or rdata could not be found
263 @rtype: dns.rrset.RRset object
263 @rtype: dns.rdataset.Rdataset object
264264 """
265265
266266 name = self._validate_name(name)
295295 @param create: should the node and rdataset be created if they do not
296296 exist?
297297 @type create: bool
298 @rtype: dns.rrset.RRset object
298 @rtype: dns.rdataset.Rdataset object or None
299299 """
300300
301301 try:
450450 rdtype = dns.rdatatype.from_text(rdtype)
451451 if isinstance(covers, string_types):
452452 covers = dns.rdatatype.from_text(covers)
453 for (name, node) in self.iteritems():
453 for (name, node) in self.iteritems(): # pylint: disable=dict-iter-method
454454 for rds in node:
455455 if rdtype == dns.rdatatype.ANY or \
456456 (rds.rdtype == rdtype and rds.covers == covers):
473473 rdtype = dns.rdatatype.from_text(rdtype)
474474 if isinstance(covers, string_types):
475475 covers = dns.rdatatype.from_text(covers)
476 for (name, node) in self.iteritems():
476 for (name, node) in self.iteritems(): # pylint: disable=dict-iter-method
477477 for rds in node:
478478 if rdtype == dns.rdatatype.ANY or \
479479 (rds.rdtype == rdtype and rds.covers == covers):
524524 names = list(self.keys())
525525 names.sort()
526526 else:
527 names = self.iterkeys()
527 names = self.iterkeys() # pylint: disable=dict-iter-method
528528 for n in names:
529529 l = self[n].to_text(n, origin=self.origin,
530530 relativize=relativize)
588588
589589 @ivar tok: The tokenizer
590590 @type tok: dns.tokenizer.Tokenizer object
591 @ivar ttl: The default TTL
592 @type ttl: int
591 @ivar last_ttl: The last seen explicit TTL for an RR
592 @type last_ttl: int
593 @ivar last_ttl_known: Has last TTL been detected
594 @type last_ttl_known: bool
595 @ivar default_ttl: The default TTL from a $TTL directive or SOA RR
596 @type default_ttl: int
597 @ivar default_ttl_known: Has default TTL been detected
598 @type default_ttl_known: bool
593599 @ivar last_name: The last name read
594600 @type last_name: dns.name.Name object
595601 @ivar current_origin: The current origin
599605 @ivar zone: the zone
600606 @type zone: dns.zone.Zone object
601607 @ivar saved_state: saved reader state (used when processing $INCLUDE)
602 @type saved_state: list of (tokenizer, current_origin, last_name, file)
603 tuples.
608 @type saved_state: list of (tokenizer, current_origin, last_name, file,
609 last_ttl, last_ttl_known, default_ttl, default_ttl_known) tuples.
604610 @ivar current_file: the file object of the $INCLUDed file being parsed
605611 (None if no $INCLUDE is active).
606612 @ivar allow_include: is $INCLUDE allowed?
617623 self.tok = tok
618624 self.current_origin = origin
619625 self.relativize = relativize
620 self.ttl = 0
626 self.last_ttl = 0
627 self.last_ttl_known = False
628 self.default_ttl = 0
629 self.default_ttl_known = False
621630 self.last_name = self.current_origin
622631 self.zone = zone_factory(origin, rdclass, relativize=relativize)
623632 self.saved_state = []
658667 # TTL
659668 try:
660669 ttl = dns.ttl.from_text(token.value)
670 self.last_ttl = ttl
671 self.last_ttl_known = True
661672 token = self.tok.get()
662673 if not token.is_identifier():
663674 raise dns.exception.SyntaxError
664675 except dns.ttl.BadTTL:
665 ttl = self.ttl
676 if not (self.last_ttl_known or self.default_ttl_known):
677 raise dns.exception.SyntaxError("Missing default TTL value")
678 if self.default_ttl_known:
679 ttl = self.default_ttl
680 else:
681 ttl = self.last_ttl
666682 # Class
667683 try:
668684 rdclass = dns.rdataclass.from_text(token.value)
700716 # helpful filename:line info.
701717 (ty, va) = sys.exc_info()[:2]
702718 raise dns.exception.SyntaxError(
703 "caught exception %s: %s" % (str(ty), str(va)))
719 "caught exception {}: {}".format(str(ty), str(va)))
720
721 if not self.default_ttl_known and isinstance(rd, dns.rdtypes.ANY.SOA.SOA):
722 # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default
723 # TTL from the SOA minttl if no $TTL statement is present before the
724 # SOA is parsed.
725 self.default_ttl = rd.minimum
726 self.default_ttl_known = True
704727
705728 rd.choose_relativity(self.zone.origin, self.relativize)
706729 covers = rd.covers()
777800 # TTL
778801 try:
779802 ttl = dns.ttl.from_text(token.value)
803 self.last_ttl = ttl
804 self.last_ttl_known = True
780805 token = self.tok.get()
781806 if not token.is_identifier():
782807 raise dns.exception.SyntaxError
783808 except dns.ttl.BadTTL:
784 ttl = self.ttl
809 if not (self.last_ttl_known or self.default_ttl_known):
810 raise dns.exception.SyntaxError("Missing default TTL value")
811 if self.default_ttl_known:
812 ttl = self.default_ttl
813 else:
814 ttl = self.last_ttl
785815 # Class
786816 try:
787817 rdclass = dns.rdataclass.from_text(token.value)
883913 self.current_origin,
884914 self.last_name,
885915 self.current_file,
886 self.ttl) = self.saved_state.pop(-1)
916 self.last_ttl,
917 self.last_ttl_known,
918 self.default_ttl,
919 self.default_ttl_known) = self.saved_state.pop(-1)
887920 continue
888921 break
889922 elif token.is_eol():
897930 token = self.tok.get()
898931 if not token.is_identifier():
899932 raise dns.exception.SyntaxError("bad $TTL")
900 self.ttl = dns.ttl.from_text(token.value)
933 self.default_ttl = dns.ttl.from_text(token.value)
934 self.default_ttl_known = True
901935 self.tok.get_eol()
902936 elif c == u'$ORIGIN':
903937 self.current_origin = self.tok.get_name()
922956 self.current_origin,
923957 self.last_name,
924958 self.current_file,
925 self.ttl))
959 self.last_ttl,
960 self.last_ttl_known,
961 self.default_ttl,
962 self.default_ttl_known))
926963 self.current_file = open(filename, 'r')
927964 self.tok = dns.tokenizer.Tokenizer(self.current_file,
928965 filename)
10231060 """
10241061
10251062 str_type = string_types
1026 opts = 'rU'
1063 if PY3:
1064 opts = 'r'
1065 else:
1066 opts = 'rU'
10271067
10281068 if isinstance(f, str_type):
10291069 if filename is None:
0 from typing import Generator, Optional, Union, Tuple, Iterable, Callable, Any, Iterator, TextIO, BinaryIO, Dict
1 from . import rdata, zone, rdataclass, name, rdataclass, message, rdatatype, exception, node, rdataset, rrset, rdatatype
2
3 class BadZone(exception.DNSException): ...
4 class NoSOA(BadZone): ...
5 class NoNS(BadZone): ...
6 class UnknownOrigin(BadZone): ...
7
8 class Zone:
9 def __getitem__(self, key : str) -> node.Node:
10 ...
11 def __init__(self, origin : Union[str,name.Name], rdclass : int = rdataclass.IN, relativize : bool = True) -> None:
12 self.nodes : Dict[str,node.Node]
13 self.origin = origin
14 def values(self):
15 return self.nodes.values()
16 def iterate_rdatas(self, rdtype : Union[int,str] = rdatatype.ANY, covers : Union[int,str] = None) -> Iterable[Tuple[name.Name, int, rdata.Rdata]]:
17 ...
18 def __iter__(self) -> Iterator[str]:
19 ...
20 def get_node(self, name : Union[name.Name,str], create=False) -> Optional[node.Node]:
21 ...
22 def find_rrset(self, name : Union[str,name.Name], rdtype : Union[int,str], covers=rdatatype.NONE) -> rrset.RRset:
23 ...
24 def find_rdataset(self, name : Union[str,name.Name], rdtype : Union[str,int], covers=rdatatype.NONE,
25 create=False) -> rdataset.Rdataset:
26 ...
27 def get_rdataset(self, name : Union[str,name.Name], rdtype : Union[str,int], covers=rdatatype.NONE, create=False) -> Optional[rdataset.Rdataset]:
28 ...
29 def get_rrset(self, name : Union[str,name.Name], rdtype : Union[str,int], covers=rdatatype.NONE) -> Optional[rrset.RRset]:
30 ...
31 def replace_rdataset(self, name : Union[str,name.Name], replacement : rdataset.Rdataset) -> None:
32 ...
33 def delete_rdataset(self, name : Union[str,name.Name], rdtype : Union[str,int], covers=rdatatype.NONE) -> None:
34 ...
35 def iterate_rdatasets(self, rdtype : Union[str,int] =rdatatype.ANY,
36 covers : Union[str,int] =rdatatype.NONE):
37 ...
38 def to_file(self, f : Union[TextIO, BinaryIO, str], sorted=True, relativize=True, nl : Optional[bytes] = None):
39 ...
40 def to_text(self, sorted=True, relativize=True, nl : Optional[bytes] = None) -> bytes:
41 ...
42
43 def from_xfr(xfr : Generator[Any,Any,message.Message], zone_factory : Callable[..., zone.Zone] = zone.Zone, relativize=True, check_origin=True):
44 ...
45
46 def from_text(text : str, origin : Optional[Union[str,name.Name]] = None, rdclass : int = rdataclass.IN,
47 relativize=True, zone_factory : Callable[...,zone.Zone] = zone.Zone, filename : Optional[str] = None,
48 allow_include=False, check_origin=True) -> zone.Zone:
49 ...
50
51 def from_file(f, origin : Optional[Union[str,name.Name]] = None, rdclass=rdataclass.IN,
52 relativize=True, zone_factory : Callable[..., zone.Zone] = Zone, filename : Optional[str] = None,
53 allow_include=True, check_origin=True) -> zone.Zone:
54 ...
+0
-35
dnspython.egg-info/PKG-INFO less more
0 Metadata-Version: 1.1
1 Name: dnspython
2 Version: 1.15.0
3 Summary: DNS toolkit
4 Home-page: http://www.dnspython.org
5 Author: Bob Halley
6 Author-email: halley@dnspython.org
7 License: BSD-like
8 Download-URL: http://www.dnspython.org/kits/1.15.0/dnspython-1.15.0.tar.gz
9 Description: dnspython is a DNS toolkit for Python. It supports almost all
10 record types. It can be used for queries, zone transfers, and dynamic
11 updates. It supports TSIG authenticated messages and EDNS0.
12
13 dnspython provides both high and low level access to DNS. The high
14 level classes perform queries for data of a given name, type, and
15 class, and return an answer set. The low level classes allow
16 direct manipulation of DNS zones, messages, names, and records.
17 Platform: UNKNOWN
18 Classifier: Development Status :: 5 - Production/Stable
19 Classifier: Intended Audience :: Developers
20 Classifier: Intended Audience :: System Administrators
21 Classifier: License :: Freeware
22 Classifier: Operating System :: Microsoft :: Windows :: Windows 95/98/2000
23 Classifier: Operating System :: POSIX
24 Classifier: Programming Language :: Python
25 Classifier: Topic :: Internet :: Name Service (DNS)
26 Classifier: Topic :: Software Development :: Libraries :: Python Modules
27 Classifier: Programming Language :: Python :: 2
28 Classifier: Programming Language :: Python :: 2.6
29 Classifier: Programming Language :: Python :: 2.7
30 Classifier: Programming Language :: Python :: 3
31 Classifier: Programming Language :: Python :: 3.3
32 Classifier: Programming Language :: Python :: 3.4
33 Classifier: Programming Language :: Python :: 3.5
34 Provides: dns
+0
-138
dnspython.egg-info/SOURCES.txt less more
0 ChangeLog
1 LICENSE
2 MANIFEST.in
3 setup.py
4 dns/__init__.py
5 dns/_compat.py
6 dns/dnssec.py
7 dns/e164.py
8 dns/edns.py
9 dns/entropy.py
10 dns/exception.py
11 dns/flags.py
12 dns/grange.py
13 dns/hash.py
14 dns/inet.py
15 dns/ipv4.py
16 dns/ipv6.py
17 dns/message.py
18 dns/name.py
19 dns/namedict.py
20 dns/node.py
21 dns/opcode.py
22 dns/query.py
23 dns/rcode.py
24 dns/rdata.py
25 dns/rdataclass.py
26 dns/rdataset.py
27 dns/rdatatype.py
28 dns/renderer.py
29 dns/resolver.py
30 dns/reversename.py
31 dns/rrset.py
32 dns/set.py
33 dns/tokenizer.py
34 dns/tsig.py
35 dns/tsigkeyring.py
36 dns/ttl.py
37 dns/update.py
38 dns/version.py
39 dns/wiredata.py
40 dns/zone.py
41 dns/rdtypes/__init__.py
42 dns/rdtypes/dnskeybase.py
43 dns/rdtypes/dsbase.py
44 dns/rdtypes/euibase.py
45 dns/rdtypes/mxbase.py
46 dns/rdtypes/nsbase.py
47 dns/rdtypes/txtbase.py
48 dns/rdtypes/ANY/AFSDB.py
49 dns/rdtypes/ANY/AVC.py
50 dns/rdtypes/ANY/CAA.py
51 dns/rdtypes/ANY/CDNSKEY.py
52 dns/rdtypes/ANY/CDS.py
53 dns/rdtypes/ANY/CERT.py
54 dns/rdtypes/ANY/CNAME.py
55 dns/rdtypes/ANY/CSYNC.py
56 dns/rdtypes/ANY/DLV.py
57 dns/rdtypes/ANY/DNAME.py
58 dns/rdtypes/ANY/DNSKEY.py
59 dns/rdtypes/ANY/DS.py
60 dns/rdtypes/ANY/EUI48.py
61 dns/rdtypes/ANY/EUI64.py
62 dns/rdtypes/ANY/GPOS.py
63 dns/rdtypes/ANY/HINFO.py
64 dns/rdtypes/ANY/HIP.py
65 dns/rdtypes/ANY/ISDN.py
66 dns/rdtypes/ANY/LOC.py
67 dns/rdtypes/ANY/MX.py
68 dns/rdtypes/ANY/NS.py
69 dns/rdtypes/ANY/NSEC.py
70 dns/rdtypes/ANY/NSEC3.py
71 dns/rdtypes/ANY/NSEC3PARAM.py
72 dns/rdtypes/ANY/PTR.py
73 dns/rdtypes/ANY/RP.py
74 dns/rdtypes/ANY/RRSIG.py
75 dns/rdtypes/ANY/RT.py
76 dns/rdtypes/ANY/SOA.py
77 dns/rdtypes/ANY/SPF.py
78 dns/rdtypes/ANY/SSHFP.py
79 dns/rdtypes/ANY/TLSA.py
80 dns/rdtypes/ANY/TXT.py
81 dns/rdtypes/ANY/URI.py
82 dns/rdtypes/ANY/X25.py
83 dns/rdtypes/ANY/__init__.py
84 dns/rdtypes/IN/A.py
85 dns/rdtypes/IN/AAAA.py
86 dns/rdtypes/IN/APL.py
87 dns/rdtypes/IN/DHCID.py
88 dns/rdtypes/IN/IPSECKEY.py
89 dns/rdtypes/IN/KX.py
90 dns/rdtypes/IN/NAPTR.py
91 dns/rdtypes/IN/NSAP.py
92 dns/rdtypes/IN/NSAP_PTR.py
93 dns/rdtypes/IN/PX.py
94 dns/rdtypes/IN/SRV.py
95 dns/rdtypes/IN/WKS.py
96 dns/rdtypes/IN/__init__.py
97 dnspython.egg-info/PKG-INFO
98 dnspython.egg-info/SOURCES.txt
99 dnspython.egg-info/dependency_links.txt
100 dnspython.egg-info/top_level.txt
101 examples/ddns.py
102 examples/e164.py
103 examples/mx.py
104 examples/name.py
105 examples/reverse.py
106 examples/reverse_name.py
107 examples/xfr.py
108 examples/zonediff.py
109 tests/Makefile
110 tests/__init__.py
111 tests/example
112 tests/example1.good
113 tests/example2.good
114 tests/example3.good
115 tests/test_bugs.py
116 tests/test_dnssec.py
117 tests/test_exceptions.py
118 tests/test_flags.py
119 tests/test_generate.py
120 tests/test_grange.py
121 tests/test_message.py
122 tests/test_name.py
123 tests/test_namedict.py
124 tests/test_ntoaaton.py
125 tests/test_rdata.py
126 tests/test_rdtypeandclass.py
127 tests/test_rdtypeanydnskey.py
128 tests/test_rdtypeanyeui.py
129 tests/test_rdtypeanyloc.py
130 tests/test_resolver.py
131 tests/test_rrset.py
132 tests/test_set.py
133 tests/test_tokenizer.py
134 tests/test_update.py
135 tests/test_wiredata.py
136 tests/test_zone.py
137 tests/utest.py
+0
-1
dnspython.egg-info/dependency_links.txt less more
0
+0
-1
dnspython.egg-info/top_level.txt less more
0 dns
0 # Minimal makefile for Sphinx documentation
1 #
2
3 # You can set these variables from the command line.
4 SPHINXOPTS =
5 SPHINXBUILD = sphinx-build
6 SPHINXPROJ = dnspython
7 SOURCEDIR = .
8 BUILDDIR = _build
9
10 # Put it first so that "make" without argument is like "make help".
11 help:
12 @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13
14 .PHONY: help Makefile
15
16 # Catch-all target: route all unknown targets to Sphinx using the new
17 # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 %: Makefile
19 @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
0 .. _community:
1
2 Community
3 =========
4
5 Bugs and Feature Requests
6 -------------------------
7
8 Bugs and feature requests can be made using the github issues system at
9 `github <https://github.com/rthalley/dnspython/issues>`_.
10
11 Mailing Lists
12 -------------
13
14 | `dnspython-announce <http://groups.google.com/group/dnspython-announce>`_
15 | `dnspython-users <http://groups.google.com/group/dnspython-users>`_
16 | `dnspython-dev <http://groups.google.com/group/dnspython-dev>`_
0 #!/usr/bin/env python3
1 # -*- coding: utf-8 -*-
2 #
3 # dnspython documentation build configuration file, created by
4 # sphinx-quickstart on Fri Dec 30 05:55:44 2016.
5 #
6 # This file is execfile()d with the current directory set to its
7 # containing dir.
8 #
9 # Note that not all possible configuration values are present in this
10 # autogenerated file.
11 #
12 # All configuration values have a default; values that are commented out
13 # serve to show the default.
14
15 # If extensions (or modules to document with autodoc) are in another directory,
16 # add these directories to sys.path here. If the directory is relative to the
17 # documentation root, use os.path.abspath to make it absolute, like shown here.
18 #
19 import os
20 import sys
21 sys.path.insert(0, os.path.abspath('..'))
22
23
24 # -- General configuration ------------------------------------------------
25
26 # If your documentation needs a minimal Sphinx version, state it here.
27 #
28 # needs_sphinx = '1.0'
29
30 # Add any Sphinx extension module names here, as strings. They can be
31 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
32 # ones.
33 extensions = ['sphinx.ext.autodoc',
34 'sphinx.ext.viewcode',
35 'sphinx.ext.githubpages']
36
37 # Add any paths that contain templates here, relative to this directory.
38 templates_path = ['_templates']
39
40 # The suffix(es) of source filenames.
41 # You can specify multiple suffix as a list of string:
42 #
43 # source_suffix = ['.rst', '.md']
44 source_suffix = '.rst'
45
46 # The master toctree document.
47 master_doc = 'index'
48
49 # General information about the project.
50 project = 'dnspython'
51 copyright = '2016, Nominum, Inc.'
52 author = 'Nominum, Inc.'
53
54 # The version info for the project you're documenting, acts as replacement for
55 # |version| and |release|, also used in various other places throughout the
56 # built documents.
57 #
58 # The short X.Y version.
59 version = '1.16'
60 # The full version, including alpha/beta/rc tags.
61 release = '1.16.0'
62
63 # The language for content autogenerated by Sphinx. Refer to documentation
64 # for a list of supported languages.
65 #
66 # This is also used if you do content translation via gettext catalogs.
67 # Usually you set "language" from the command line for these cases.
68 language = None
69
70 # List of patterns, relative to source directory, that match files and
71 # directories to ignore when looking for source files.
72 # This patterns also effect to html_static_path and html_extra_path
73 exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
74
75 # The name of the Pygments (syntax highlighting) style to use.
76 pygments_style = 'sphinx'
77
78 # If true, `todo` and `todoList` produce output, else they produce nothing.
79 todo_include_todos = False
80
81 # -- Options for autodoc --------------------------------------------------
82
83 autoclass_content = 'both'
84
85 # -- Options for HTML output ----------------------------------------------
86
87 # The theme to use for HTML and HTML Help pages. See the documentation for
88 # a list of builtin themes.
89 #
90 html_theme = 'alabaster'
91
92 # Theme options are theme-specific and customize the look and feel of a theme
93 # further. For a list of options available for each theme, see the
94 # documentation.
95 #
96 # html_theme_options = {}
97
98 # Add any paths that contain custom static files (such as style sheets) here,
99 # relative to this directory. They are copied after the builtin static files,
100 # so a file named "default.css" will overwrite the builtin "default.css".
101 html_static_path = ['_static']
102
103 # -- Options for HTMLHelp output ------------------------------------------
104
105 # Output file base name for HTML help builder.
106 htmlhelp_basename = 'dnspythondoc'
107
108
109 # -- Options for LaTeX output ---------------------------------------------
110
111 latex_elements = {
112 # The paper size ('letterpaper' or 'a4paper').
113 #
114 # 'papersize': 'letterpaper',
115
116 # The font size ('10pt', '11pt' or '12pt').
117 #
118 # 'pointsize': '10pt',
119
120 # Additional stuff for the LaTeX preamble.
121 #
122 # 'preamble': '',
123
124 # Latex figure (float) alignment
125 #
126 # 'figure_align': 'htbp',
127 }
128
129 # Grouping the document tree into LaTeX files. List of tuples
130 # (source start file, target name, title,
131 # author, documentclass [howto, manual, or own class]).
132 latex_documents = [
133 (master_doc, 'dnspython.tex', 'dnspython Documentation',
134 'Nominum, Inc.', 'manual'),
135 ]
136
137
138 # -- Options for manual page output ---------------------------------------
139
140 # One entry per manual page. List of tuples
141 # (source start file, name, description, authors, manual section).
142 man_pages = [
143 (master_doc, 'dnspython', 'dnspython Documentation',
144 [author], 1)
145 ]
146
147
148 # -- Options for Texinfo output -------------------------------------------
149
150 # Grouping the document tree into Texinfo files. List of tuples
151 # (source start file, target name, title, author,
152 # dir menu entry, description, category)
153 texinfo_documents = [
154 (master_doc, 'dnspython', 'dnspython Documentation',
155 author, 'dnspython', 'One line description of project.',
156 'Miscellaneous'),
157 ]
158
159
160
0 .. module:: dns.dnssec
1 .. _dnssec:
2
3 DNSSEC
4 ======
5
6 Dnspython can do simple DNSSEC signature validation, but currently has no
7 facilities for signing. In order to use DNSSEC functions, you must have
8 ``pycryptodome`` or ``pycryptodomex`` installed. If you want to do elliptic
9 curves, you must also have ``ecdsa`` installed.
10
11 DNSSEC Algorithms
12 -----------------
13
14 .. autodata:: dns.dnssec.RSAMD5
15 .. autodata:: dns.dnssec.DH
16 .. autodata:: dns.dnssec.DSA
17 .. autodata:: dns.dnssec.ECC
18 .. autodata:: dns.dnssec.RSASHA1
19 .. autodata:: dns.dnssec.DSANSEC3SHA1
20 .. autodata:: dns.dnssec.RSASHA1NSEC3SHA1
21 .. autodata:: dns.dnssec.RSASHA256
22 .. autodata:: dns.dnssec.RSASHA512
23 .. autodata:: dns.dnssec.ECDSAP256SHA256
24 .. autodata:: dns.dnssec.ECDSAP384SHA384
25 .. autodata:: dns.dnssec.INDIRECT
26 .. autodata:: dns.dnssec.PRIVATEDNS
27 .. autodata:: dns.dnssec.PRIVATEOID
28
29 DNSSEC Functions
30 ----------------
31
32 .. autofunction:: dns.dnssec.algorithm_from_text
33 .. autofunction:: dns.dnssec.algorithm_to_text
34 .. autofunction:: dns.dnssec.key_id
35 .. autofunction:: dns.dnssec.make_ds
36 .. autofunction:: dns.dnssec.validate
37 .. autofunction:: dns.dnssec.validate_rrsig
0 .. _exceptions:
1
2 Exceptions
3 ==========
4
5 Common Exceptions
6 -----------------
7
8 .. automodule:: dns.exception
9 :members:
10
11 dns.dnssec Exceptions
12 ---------------------
13
14 .. autoexception:: dns.dnssec.UnsupportedAlgorithm
15 .. autoexception:: dns.dnssec.ValidationFailure
16
17
18 dns.message Exceptions
19 ----------------------
20
21 .. autoexception:: dns.message.BadEDNS
22 .. autoexception:: dns.message.BadTSIG
23 .. autoexception:: dns.message.ShortHeader
24 .. autoexception:: dns.message.TrailingJunk
25 .. autoexception:: dns.message.UnknownHeaderField
26 .. autoexception:: dns.message.UnknownTSIGKey
27
28 dns.name Exceptions
29 -------------------
30
31 .. autoexception:: dns.name.AbsoluteConcatenation
32 .. autoexception:: dns.name.BadEscape
33 .. autoexception:: dns.name.BadLabelType
34 .. autoexception:: dns.name.BadPointer
35 .. autoexception:: dns.name.EmptyLabel
36 .. autoexception:: dns.name.IDNAException
37 .. autoexception:: dns.name.LabelTooLong
38 .. autoexception:: dns.name.NameTooLong
39 .. autoexception:: dns.name.NeedAbsoluteNameOrOrigin
40 .. autoexception:: dns.name.NoIDNA2008
41 .. autoexception:: dns.name.NoParent
42
43 dns.opcode Exceptions
44 ---------------------
45
46 .. autoexception:: dns.opcode.UnknownOpcode
47
48 dns.query Exceptions
49 --------------------
50
51 .. autoexception:: dns.query.BadResponse
52 .. autoexception:: dns.query.UnexpectedSource
53 .. autoexception:: dns.query.TransferError
54
55
56 dns.rcode Exceptions
57 --------------------
58
59 .. autoexception:: dns.rcode.UnknownRcode
60
61 dns.rdataset Exceptions
62 -----------------------
63
64 .. autoexception:: dns.rdataset.DifferingCovers
65 .. autoexception:: dns.rdataset.IncompatibleTypes
66
67 dns.resolver Exceptions
68 -----------------------
69
70 .. autoexception:: dns.resolver.NoAnswer
71 .. autoexception:: dns.resolver.NoMetaqueries
72 .. autoexception:: dns.resolver.NoNameservers
73 .. autoexception:: dns.resolver.NoRootSOA
74 .. autoexception:: dns.resolver.NotAbsolute
75 .. autoexception:: dns.resolver.NXDOMAIN
76 .. autoexception:: dns.resolver.YXDOMAIN
77
78 dns.tokenizer Exceptions
79 ------------------------
80
81 .. autoexception:: dns.tokenizer.UngetBufferFull
82
83 dns.ttl Exceptions
84 ------------------
85
86 .. autoexception:: dns.ttl.BadTTL
0 .. dnspython documentation master file
1
2 dnspython
3 =========
4
5 Dnspython is a DNS toolkit for Python. It can be used for queries,
6 zone transfers, dynamic updates, nameserver testing, and many other
7 things.
8
9 Dnspython provides both high and low level access to the DNS. The high
10 level classes perform queries for data of a given name, type, and
11 class, and return an answer set. The low level classes allow direct
12 manipulation of DNS zones, messages, names, and records. Almost all
13 RR types are supported.
14
15 dnspython originated at Nominum where it was developed for testing DNS
16 nameservers. Nominum has generously allowed it to be open sourced
17 under a BSD-style license, and helps support its future development by
18 continuing to employ the author.
19
20 .. toctree::
21 :maxdepth: 1
22 :caption: Contents:
23
24 whatsnew
25 community
26 installation
27 manual
28 rfc
29
30 Indices and tables
31 ==================
32
33 * :ref:`genindex`
34 * :ref:`modindex`
35 * :ref:`search`
0 .. _installation:
1
2 Installation
3 ============
4
5 Requirements
6 ------------
7
8 Python 2.7, 3.4 or later.
9
10 Installation
11 ------------
12
13 Many free operating system distributions have dnspython packaged for
14 you, so you should check there first.
15
16 The next easiest option is to use ``pip``::
17
18 pip install dnspython
19
20 If ``pip`` is not available, you can download the latest zip file from
21 `PyPI <https://pypi.python.org/pypi/dnspython/>`_, unzip it.
22
23 On a UNIX-like system, you then run::
24
25 sudo python setup.py install
26
27 while on a Windows system you would run::
28
29 python setup.py install
30
31 Finally, you have the option of cloning the dnspython source from github
32 and building it::
33
34 git clone https://github.com/rthalley/dnspython.git
35
36 And then run ``setup.py`` as above.
37
38 Please be aware that the master branch of dnspython on github is under
39 active development and may not always be stable.
40
41
42 Optional Modules
43 ----------------
44
45 The following modules are optional, but recommended for full functionality.
46
47 If ``pycryptodome`` / ``pycryptodomex`` is installed, then dnspython will be
48 able to do low-level DNSSEC RSA and DSA signature validation.
49
50 If ``ecdsa`` is installed, then Elliptic Curve signature algorithms will
51 be available for low-level DNSSEC signature validation.
52
53 If ``idna`` is installed, then IDNA 2008 will be available.
0 Dnspython Manual
1 ================
2
3 .. toctree::
4 :maxdepth: 2
5 :caption: Contents:
6
7 py2vs3
8 name
9 rdata
10 message
11 dnssec
12 query
13 resolver
14 exceptions
15 utilities
0 .. _message-class:
1
2 The dns.message.Message Class
3 -----------------------------
4
5 .. autoclass:: dns.message.Message
6 :members:
7
8 .. attribute:: id
9
10 An ``int``, the query id; the default is a randomly chosen id.
11
12 .. attribute:: flags
13
14 An ``int``, the DNS flags of the message.
15
16 .. attribute:: question
17
18 The question section, a list of ``dns.rrset.RRset`` objects.
19
20 .. attribute:: answer
21
22 The answer section, a list of ``dns.rrset.RRset`` objects.
23
24 .. attribute:: authority
25
26 The authority section, a list of ``dns.rrset.RRset`` objects.
27
28 .. attribute:: additional
29
30 The additional section, a list of ``dns.rrset.RRset`` objects.
31
32 .. attribute:: edns
33
34 An ``int``, the EDNS level to use. The default is -1, no EDNS.
35
36 .. attribute:: ednsflags
37
38 An ``int``, the EDNS flags.
39
40 .. attribute:: payload
41
42 An ``int``, the EDNS payload size. The default is 0.
43
44 .. attribute:: options
45
46 The EDNS options, a list of ``dns.edns.Option`` objects. The default
47 is the empty list.
48
49 .. attribute:: request_payload
50
51 The associated request's EDNS payload size. This field is meaningful
52 in response messages, and if set to a non-zero value, will limit
53 the size of the response to the specified size. The default is 0,
54 which means "use the default limit" which is currently 65535.
55
56 .. attribute:: keyring
57
58 The TSIG keyring to use. The default is `None`. A TSIG keyring
59 is a dictionary mapping from TSIG key name, a ``dns.name.Name``, to
60 a TSIG secret, a ``binary``.
61
62 .. attribute:: keyname
63
64 The TSIG keyname to use, a ``dns.name.Name``. The default is ``None``.
65
66 .. attribute:: keyalgorithm
67
68 A ``dns.name.Name``, the TSIG algorithm to use. Defaults to
69 ``dns.tsig.default_algorithm``. Constants for TSIG algorithms are
70 defined the in ``dns.tsig`` module.
71
72 .. attribute:: request_mac
73
74 A ``binary``, the TSIG MAC of the request message associated with
75 this message; used when validating TSIG signatures.
76
77 .. attribute:: fudge
78
79 An ``int``, the TSIG time fudge. The default is 300 seconds.
80
81 .. attribute:: original_id
82
83 An ``int``, the TSIG original id; defaults to the message's id.
84
85 .. attribute:: tsig_error
86
87 An ``int``, the TSIG error code. The default is 0.
88
89 .. attribute:: other_data
90
91 A ``binary``, the TSIG "other data". The default is the empty
92 ``binary``.
93
94 .. attribute:: mac
95
96 A ``binary``, the TSIG MAC for this message.
97
98 .. attribute:: xfr
99
100 A ``bool``. This attribute is true when the message being used
101 for the results of a DNS zone transfer. The default is ``False``.
102
103 .. attribute:: origin
104
105 A ``dns.name.Name``. The origin of the zone in messages which are
106 used for zone transfers or for DNS dynamic updates. The default
107 is ``None``.
108
109 .. attribute:: tsig_ctx
110
111 An ``hmac.HMAC``, the TSIG signature context associated with this
112 message. The default is ``None``.
113
114 .. attribute:: had_tsig
115
116 A ``bool``, which is ``True`` if the message had a TSIG signature
117 when it was decoded from wire format.
118
119 .. attribute:: multi
120
121 A ``bool``, which is ``True`` if this message is part of a
122 multi-message sequence. The default is ``False``.
123 This attribute is used when validating TSIG signatures
124 on messages which are part of a zone transfer.
125
126 .. attribute:: first
127
128 A ``bool``, which is ``True`` if this message is stand-alone,
129 or the first of a multi-message sequence. The default is ``True``.
130 This variable is used when validating TSIG signatures
131 on messages which are part of a zone transfer.
132
133 .. attribute:: index
134
135 A ``dict``, an index of RRsets in the message. The index key is
136 ``(section, name, rdclass, rdtype, covers, deleting)``. The default
137 is ``{}``. Indexing improves the performance of finding RRsets.
138 Indexing can be disabled by setting the index to ``None``.
139
140 The following constants may be used to specify sections in the
141 ``find_rrset()`` and ``get_rrset()`` methods:
142
143 .. autodata:: dns.message.QUESTION
144 .. autodata:: dns.message.ANSWER
145 .. autodata:: dns.message.AUTHORITY
146 .. autodata:: dns.message.ADDITIONAL
0 .. _message-edns:
1
2 Message EDNS Options
3 --------------------
4
5 EDNS allows for larger messages and also provides an extension
6 mechanism for the protocol. EDNS *options* are typed data, and are
7 treated much like Rdata. For example, if dnsython encouters the EDNS
8 ``ECS`` option code when parsing a DNS wire format message, it
9 will create a ``dns.edns.ECSOption`` object to represent it.
10
11 .. autodata:: dns.edns.NSID
12 .. autodata:: dns.edns.DAU
13 .. autodata:: dns.edns.DHU
14 .. autodata:: dns.edns.N3U
15 .. autodata:: dns.edns.ECS
16 .. autodata:: dns.edns.EXPIRE
17 .. autodata:: dns.edns.COOKIE
18 .. autodata:: dns.edns.KEEPALIVE
19 .. autodata:: dns.edns.PADDING
20 .. autodata:: dns.edns.CHAIN
21
22 .. autoclass:: dns.edns.Option
23 :members:
24
25 .. autoclass:: dns.edns.GenericOption
26 :members:
27
28 .. autoclass:: dns.edns.ECSOption
29 :members:
30
31 .. autofunction:: dns.edns.get_option_class
32 .. autofunction:: dns.edns.option_from_wire
0 .. _message-flags:
1
2 Message Flags
3 =============
4
5 DNS message flags are used for signalling of various kinds
6 in the DNS protocol. For example, the ``QR`` flag indicates
7 that a message is a response to a prior query.
8
9 Messages flags are encoded in two locations: the DNS header
10 and the EDNS flags field.
11
12 Header Flags
13 ------------
14
15 .. autodata:: dns.flags.QR
16 .. autodata:: dns.flags.AA
17 .. autodata:: dns.flags.TC
18 .. autodata:: dns.flags.RD
19 .. autodata:: dns.flags.RA
20 .. autodata:: dns.flags.AD
21 .. autodata:: dns.flags.CD
22
23 .. autofunction:: dns.flags.from_text
24 .. autofunction:: dns.flags.to_text
25
26 EDNS Flags
27 ----------
28
29 .. autodata:: dns.flags.DO
30
31 .. autofunction:: dns.flags.edns_from_text
32 .. autofunction:: dns.flags.edns_to_text
0 .. _message-make:
1
2 Making DNS Messages
3 -------------------
4
5 .. autofunction:: dns.message.from_file
6 .. autofunction:: dns.message.from_text
7 .. autofunction:: dns.message.from_wire
8 .. autofunction:: dns.message.make_query
9 .. autofunction:: dns.message.make_response
0 .. _message-opcode:
1
2 Message Opcodes
3 ---------------
4
5 DNS Opcodes describe what kind of operation a DNS message is requesting
6 or replying to. Opcodes are embedded in the flags field in the DNS
7 header.
8
9 .. autodata:: dns.opcode.QUERY
10 .. autodata:: dns.opcode.IQUERY
11 .. autodata:: dns.opcode.STATUS
12 .. autodata:: dns.opcode.NOTIFY
13 .. autodata:: dns.opcode.UPDATE
14
15 .. autofunction:: dns.opcode.from_text
16 .. autofunction:: dns.opcode.to_text
17 .. autofunction:: dns.opcode.from_flags
18 .. autofunction:: dns.opcode.to_flags
19 .. autofunction:: dns.opcode.is_update
0 .. _message-rcode:
1
2 Message Rcodes
3 --------------
4
5 A DNS Rcode describes the result of a DNS request. If EDNS is not in
6 use, then the rcode is encoded solely in the DNS header. If EDNS is
7 in use, then the rcode is encoded using bits form both the header and
8 the EDNS OPT RR.
9
10 .. autodata:: dns.rcode.NOERROR
11 .. autodata:: dns.rcode.FORMERR
12 .. autodata:: dns.rcode.SERVFAIL
13 .. autodata:: dns.rcode.NXDOMAIN
14 .. autodata:: dns.rcode.NOTIMP
15 .. autodata:: dns.rcode.REFUSED
16 .. autodata:: dns.rcode.YXDOMAIN
17 .. autodata:: dns.rcode.YXRRSET
18 .. autodata:: dns.rcode.NXRRSET
19 .. autodata:: dns.rcode.NOTAUTH
20 .. autodata:: dns.rcode.NOTZONE
21 .. autodata:: dns.rcode.BADVERS
22
23 .. autofunction:: dns.rcode.from_text
24 .. autofunction:: dns.rcode.to_text
25 .. autofunction:: dns.rcode.from_flags
26 .. autofunction:: dns.rcode.to_flags
0 .. _message-update:
1
2 The dns.update.Update Class
3 ---------------------------
4
5 DNS Dynamic Update message have a complex encoding, so
6 dnspython provides a subclass of ``dns.message.Message``
7 specialized for creating them.
8
9 .. autoclass:: dns.update.Update
10 :members:
0 .. module:: dns.message
1 .. _message:
2
3 DNS Messages
4 ============
5
6 Objects of the dns.message.Message class represent a single DNS message,
7 as defined by `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_ and its
8 many updates and extensions.
9
10 The module provides tools for constructing and manipulating messages.
11 TSIG signatures and EDNS are also supported. Messages can be dumped to
12 a textual form, and also read from that form.
13
14 .. toctree::
15
16 message-class
17 message-make
18 message-flags
19 message-opcode
20 message-rcode
21 message-edns
22 message-update
0 .. _name-class:
1
2 The dns.name.Name Class and Predefined Names
3 --------------------------------------------
4
5 .. autoclass:: dns.name.Name
6 :members:
7
8 .. attribute:: labels
9
10 A tuple of ``binary`` in DNS wire format specifying the DNS
11 labels in the name, in order from least-signficiant label
12 (i.e. farthest from the origin) to most-significant label.
13
14 .. data:: dns.name.root
15
16 The root name, i.e. ``dns.name.Name([b''])``.
17
18 .. data:: dns.name.empty
19
20 The empty name, i.e. ``dns.name.Name([])``.
0 .. _name-codecs:
1
2 International Domain Name CODECs
3 --------------------------------
4
5 Representing non-ASCII text in the DNS is a complex and evolving
6 topic. Generally speaking, Unicode is converted into an ASCII-only,
7 case-insensitive form called "Punycode" by complex rules. There are
8 two standard specifications for this process, "IDNA 2003", which is
9 widely used, and the revised and not fully compatible standard "IDNA
10 2008". There are also varying degrees of strictness that can be applied
11 in encoding and decoding. Explaining the standards in detail is
12 out of scope for this document; Unicode Technical Standard #46
13 http://unicode.org/reports/tr46/ is a good place to start learning more.
14
15 Dnspython provides "codecs" to implement International Domain Name policy
16 according to the user's desire.
17
18 .. autoclass:: dns.name.IDNACodec
19 :members:
20 .. autoclass:: dns.name.IDNA2003Codec
21 :members:
22 .. autoclass:: dns.name.IDNA2008Codec
23 :members:
24
25 .. data:: dns.name.IDNA_2003_Practical
26
27 The "practical" codec encodes using IDNA 2003 rules and decodes
28 punycode without checking for strict IDNA 2003 compliance.
29
30 .. data:: dns.name.IDNA_2003_Strict
31
32 The "strict" codec encodes using IDNA 2003 rules and decodes
33 punycode checking for IDNA 2003 compliance.
34
35 .. data:: dns.name.IDNA_2003
36
37 A synonym for ``dns.name.IDNA_2003_Practical``.
38
39 .. data:: dns.name.IDNA_2008_Practical
40
41 The "practical" codec encodes using IDNA 2008 rules with UTS 46
42 compatibility processing, and allowing pure ASCII labels. It
43 decodes punycode without checking for strict IDNA 2008 compliance.
44
45 .. data:: dns.name.IDNA_2008_Strict
46
47 The "strict" codec encodes using IDNA 2008 rules and decodes
48 punycode checking for IDNA 2008 compliance.
49
50 .. data:: dns.name.IDNA_2008_UTS_46
51
52 The "UTS 46" codec encodes using IDNA 2008 rules with UTS 46
53 compatibility processing and decodes punycode without checking for
54 IDNA 2008 compliance.
55
56 .. data:: dns.name.IDNA_2008_Transitional
57
58 The "UTS 46" codec encodes using IDNA 2008 rules with UTS 46
59 compatibility processing in the "transitional mode" and decodes
60 punycode without checking for IDNA 2008 compliance.
61
62 .. data:: dns.name.IDNA_2008
63
64 A synonym for ``dns.name.IDNA_2008_Practical``.
0 .. _name-dict:
1
2 Name Dictionary
3 ===============
4
5 .. autoclass:: dns.namedict.NameDict
6 :members:
0 .. _name-helpers:
1
2 Name Helpers
3 ------------
4
5 Sometimes you want to look up an address in the DNS instead of a name.
6 Dnspython provides a helper functions for converting between addresses
7 and their "reverse map" form in the DNS.
8
9 For example:
10
11 ========= =========================================================================
12 Address DNS Reverse Name
13 ========= =========================================================================
14 127.0.0.1 1.0.0.127.in-addr.arpa.
15 ::1 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
16 ========= =========================================================================
17
18 |
19
20 .. autofunction:: dns.reversename.from_address
21 .. autofunction:: dns.reversename.to_address
22
23 Dnspython also provides helpers for converting E.164 numbers (i.e.
24 telephone numbers) into the names used for them in the DNS.
25
26 For example:
27
28 ================ ==================================
29 Number DNS E.164 Name
30 ================ ==================================
31 +1.650.555.1212 2.1.2.1.5.5.5.0.5.6.1.e164.arpa.
32 +44 20 7946 0123 3.2.1.0.6.4.9.7.0.2.4.4.e164.arpa.
33 ================ ==================================
34
35 |
36
37 .. autofunction:: dns.e164.from_e164
38 .. autofunction:: dns.e164.to_e164
39
40
0 .. _name-make:
1
2 Making DNS Names
3 ----------------
4
5 .. autofunction:: dns.name.from_text
6 .. autofunction:: dns.name.from_unicode
7 .. autofunction:: dns.name.from_wire
0 .. module:: dns.name
1 .. _name:
2
3 DNS Names
4 =========
5
6 Objects of the dns.name.Name class represent an immutable domain name.
7 The representation is a tuple of labels, with each lable being a ``binary``
8 object in the DNS wire format. Typically names are not created by
9 supplying the labels tuple directly, but rather by converting from DNS
10 text format or the DNS wire format.
11
12 Labels are in the same order as in the DNS textual form, e.g. the labels
13 value for ``www.dnspython.org.`` is ``(b'www', b'dnspython', b'org', b'')`` on
14 Python 3, and ``('www', 'dnspython', 'org', '')`` on Python 2.
15
16 Names may be *absolute* or *relative*. Absolute names end in the root label,
17 which is an empty ``binary``. Relative names do not end in the root label. To
18 convert a relative name to an absolute name requires specifying an *origin*.
19 Typically the origin is known by context. Dnspython provides tools to
20 relativize and derelativize names. It's a good idea not to mix relative
21 and absolute names, other than in the context of a zone. Names encoded
22 in the DNS wire protocol are always absolute. Dnspython's functions to
23 make names from text also default to an origin of the root name, and thus
24 to make a relative name using them you must specify an origin of None or
25 ``dns.name.empty``.
26
27 Names are compared and ordered according to the rules of the DNS. The
28 order is the DNSSEC canonical ordering. Relative names always sort before
29 absolute names.
30
31 Names may also be compared according to the DNS tree hierarchy with
32 the ``fullcompare()`` method. For example ```www.dnspython.org.`` is
33 a subdomain of ``dnspython.org.``. See the method description for
34 full details.
35
36 .. toctree::
37
38 name-class
39 name-make
40 name-dict
41 name-helpers
42 name-codecs
0 Python 2 vs. Python 3
1 ---------------------
2
3 Dnspython was originally written in Python 2, and for some years had a
4 separate Python 3 branch. Thanks to some excellent work by
5 contributors to the project, there is now a single source tree that
6 works for both.
7
8 The most significant user-visible differences between the two are in
9 the representations of binary data and textual data. For Python 3,
10 binary data is stored using the `bytes` type, and textual data is stored
11 using the `str` type. For Python 2, binary data is stored using the
12 `str` type, and textual data can use the `str` or `unicode` types.
13 Because there is a single source tree, the documentation will refer to
14 `binary` and `text` when describing the types of binary data or
15 textual data, respectively.
16
17
0 .. module:: dns.query
1 .. _query:
2
3 DNS Query Support
4 =================
5
6 The ``dns.query`` module is for sending messages to DNS servers, and
7 processing their responses. If you want "stub resolver" behavior, then
8 you should use the higher level ``dns.resolver`` module; see :ref:`resolver`.
9
10 For UDP and TCP, the module provides a single "do everything" query
11 function, and also provides the send and receive halves of this function
12 individually for situations where more sophisticated I/O handling is in
13 being used by the application.
14
15 UDP
16 ---
17
18 .. autofunction:: dns.query.udp
19 .. autofunction:: dns.query.send_udp
20 .. autofunction:: dns.query.receive_udp
21
22 TCP
23 ---
24
25 .. autofunction:: dns.query.tcp
26 .. autofunction:: dns.query.send_tcp
27 .. autofunction:: dns.query.receive_tcp
28
29 Zone Transfers
30 --------------
31
32 .. autofunction:: dns.query.xfr
0 .. _rdata-class:
1
2 DNS Rdata Base Class
3 ====================
4
5 All Rdata objects are instances of some subclass of ``dns.rdata.Rdata``.
6 The Rdata factory functions described in :ref:`rdata-make` will create
7 objects which are instances of the most appropriate subclass. For example,
8 a AAAA record will be an instance of the ``dns.rdtypes.IN.AAAA`` class,
9 but a record of TYPE12345, which we don't know anything specific about,
10 will be an instance of ``dns.rdata.GenericRdata``.
11
12 .. autoclass:: dns.rdata.Rdata
13 :members:
0 .. _rdata-make:
1
2 Making DNS Rdata
3 ----------------
4
5 .. autofunction:: dns.rdata.from_text
6 .. autofunction:: dns.rdata.from_wire
0 .. _rdata-set-classes:
1
2 Rdataset, RRset and Node Classes
3 ================================
4
5 An ``Rdataset`` is a set of ``Rdata`` objects which all have the same
6 rdatatype, rdataclass, and covered type. ``Rdatasets`` also have a
7 ``ttl`` (DNS time-to-live) field. Rdatasets support the normal Python
8 set API, but are also ordered.
9
10 An ``RRset`` is a subclass of ``Rdataset`` that also has an owner
11 name, i.e. a ``dns.name.Name`` that says where in the DNS tree this
12 set is located.
13
14 A ``Node`` is a set of ``Rdataset`` objects, the Rdatasets being
15 interpreted as at the same place (i.e. same owner name) int the DNS
16 tree. Nodes are primarily used in ``Zone`` objects.
17
18 .. autoclass:: dns.rdataset.Rdataset
19 :members:
20
21 .. autoclass:: dns.rrset.RRset
22 :members:
23
24 .. autoclass:: dns.node.Node
25 :members:
0 .. _rdata-make:
1
2 Making DNS Rdatasets and RRsets
3 ===============================
4
5 .. autofunction:: dns.rdataset.from_text
6 .. autofunction:: dns.rdataset.from_text_list
7 .. autofunction:: dns.rdataset.from_rdata
8 .. autofunction:: dns.rdataset.from_rdata_list
9 .. autofunction:: dns.rrset.from_text
10 .. autofunction:: dns.rrset.from_text_list
11 .. autofunction:: dns.rrset.from_rdata
12 .. autofunction:: dns.rrset.from_rdata_list
0 .. _rdata-subclasses:
1
2 Rdata Subclass Reference
3 ========================
4
5 XXXRTH This is just a placeholder for proper documentation of all
6 the subclasses, which will basically just be documenting the attributes
7 of the subclass, as well as any method specific to the subclass.
8
9 .. autoclass:: dns.rdata.GenericRdata
10 :members:
11
12 .. automodule:: dns.rdtypes.dnskeybase
13 :members:
14
15 .. automodule:: dns.rdtypes.dsbase
16 :members:
17
18 .. automodule:: dns.rdtypes.euibase
19 :members:
20
21 .. automodule:: dns.rdtypes.mxbase
22 :members:
23
24 .. automodule:: dns.rdtypes.nsbase
25 :members:
26
27 .. automodule:: dns.rdtypes.txtbase
28 :members:
29
30 .. automodule:: dns.rdtypes.ANY.AFSDB
31 :members:
32
33 .. automodule:: dns.rdtypes.ANY.AVC
34 :members:
35
36 .. automodule:: dns.rdtypes.ANY.CAA
37 :members:
38
39 .. automodule:: dns.rdtypes.ANY.CDNSKEY
40 :members:
41
42 .. automodule:: dns.rdtypes.ANY.CDS
43 :members:
44
45 .. automodule:: dns.rdtypes.ANY.CERT
46 :members:
47
48 .. automodule:: dns.rdtypes.ANY.CNAME
49 :members:
50
51 .. automodule:: dns.rdtypes.ANY.CSYNC
52 :members:
53
54 .. automodule:: dns.rdtypes.ANY.DLV
55 :members:
56
57 .. automodule:: dns.rdtypes.ANY.DNAME
58 :members:
59
60 .. automodule:: dns.rdtypes.ANY.DNSKEY
61 :members:
62
63 .. automodule:: dns.rdtypes.ANY.DS
64 :members:
65
66 .. automodule:: dns.rdtypes.ANY.EUI48
67 :members:
68
69 .. automodule:: dns.rdtypes.ANY.EUI64
70 :members:
71
72 .. automodule:: dns.rdtypes.ANY.GPOS
73 :members:
74
75 .. automodule:: dns.rdtypes.ANY.HINFO
76 :members:
77
78 .. automodule:: dns.rdtypes.ANY.HIP
79 :members:
80
81 .. automodule:: dns.rdtypes.ANY.ISDN
82 :members:
83
84 .. automodule:: dns.rdtypes.ANY.LOC
85 :members:
86
87 .. automodule:: dns.rdtypes.ANY.MX
88 :members:
89
90 .. automodule:: dns.rdtypes.ANY.NS
91 :members:
92
93 .. automodule:: dns.rdtypes.ANY.NSEC
94 :members:
95
96 .. automodule:: dns.rdtypes.ANY.NSEC3
97 :members:
98
99 .. automodule:: dns.rdtypes.ANY.NSEC3PARAM
100 :members:
101
102 .. automodule:: dns.rdtypes.ANY.OPENPGPKEY
103 :members:
104
105 .. automodule:: dns.rdtypes.ANY.PTR
106 :members:
107
108 .. automodule:: dns.rdtypes.ANY.RP
109 :members:
110
111 .. automodule:: dns.rdtypes.ANY.RRSIG
112 :members:
113
114 .. automodule:: dns.rdtypes.ANY.RT
115 :members:
116
117 .. automodule:: dns.rdtypes.ANY.SOA
118 :members:
119
120 .. automodule:: dns.rdtypes.ANY.SPF
121 :members:
122
123 .. automodule:: dns.rdtypes.ANY.SSHFP
124 :members:
125
126 .. automodule:: dns.rdtypes.ANY.TLSA
127 :members:
128
129 .. automodule:: dns.rdtypes.ANY.TXT
130 :members:
131
132 .. automodule:: dns.rdtypes.ANY.URI
133 :members:
134
135 .. automodule:: dns.rdtypes.ANY.X25
136 :members:
137
138 .. automodule:: dns.rdtypes.IN.A
139 :members:
140
141 .. automodule:: dns.rdtypes.IN.AAAA
142 :members:
143
144 .. automodule:: dns.rdtypes.IN.APL
145 :members:
146
147 .. automodule:: dns.rdtypes.IN.DHCID
148 :members:
149
150 .. automodule:: dns.rdtypes.IN.IPSECKEY
151 :members:
152
153 .. automodule:: dns.rdtypes.IN.KX
154 :members:
155
156 .. automodule:: dns.rdtypes.IN.NAPTR
157 :members:
158
159 .. automodule:: dns.rdtypes.IN.NSAP
160 :members:
161
162 .. automodule:: dns.rdtypes.IN.NSAP_PTR
163 :members:
164
165 .. automodule:: dns.rdtypes.IN.PX
166 :members:
167
168 .. automodule:: dns.rdtypes.IN.SRV
169 :members:
170
171 .. automodule:: dns.rdtypes.IN.WKS
172 :members:
173
0 .. _rdata-types:
1
2 Rdata classes and types
3 -----------------------
4
5 Sets of typed data can be associated with a given name. A single typed
6 datum is called an *rdata*. The type of an rdata is specified by its
7 *rdataclass* and *rdatatype*. The class is almost always `IN`, the Internet
8 class, and may often be omitted in the dnspython APIs.
9
10 The ``dns.rdataclass`` module provides constants for each defined
11 rdata class, as well as some helpful functions. The ``dns.rdatatype``
12 module does the same for rdata types. Examples of the constants are::
13
14 dns.rdataclass.IN
15 dns.rdatatype.AAAA
16
17 .. automodule:: dns.rdataclass
18 :members:
19
20 .. automodule:: dns.rdatatype
21 :members:
22
23 .. toctree::
24 rdataclass-list
25 rdatatype-list
0 .. _rdata:
1
2 DNS Rdata
3 =========
4
5 .. toctree::
6
7 rdata-types
8 rdata-class
9 rdata-make
10 rdata-subclasses
11 rdata-set-classes
12 rdata-set-make
0 Rdataclasses
1 ============
2
3 .. py:data:: dns.rdataclass.ANY
4 :annotation: = 255
5 .. py:data:: dns.rdataclass.CH
6 :annotation: = 3
7 .. py:data:: dns.rdataclass.CHAOS
8 :annotation: = 3
9 .. py:data:: dns.rdataclass.HESIOD
10 :annotation: = 4
11 .. py:data:: dns.rdataclass.HS
12 :annotation: = 4
13 .. py:data:: dns.rdataclass.IN
14 :annotation: = 1
15 .. py:data:: dns.rdataclass.INTERNET
16 :annotation: = 1
17 .. py:data:: dns.rdataclass.NONE
18 :annotation: = 254
19 .. py:data:: dns.rdataclass.RESERVED0
20 :annotation: = 0
0 Rdatatypes
1 ==========
2
3 .. py:data:: dns.rdatatype.A
4 :annotation: = 1
5 .. py:data:: dns.rdatatype.A6
6 :annotation: = 38
7 .. py:data:: dns.rdatatype.AAAA
8 :annotation: = 28
9 .. py:data:: dns.rdatatype.AFSDB
10 :annotation: = 18
11 .. py:data:: dns.rdatatype.ANY
12 :annotation: = 255
13 .. py:data:: dns.rdatatype.APL
14 :annotation: = 42
15 .. py:data:: dns.rdatatype.AVC
16 :annotation: = 258
17 .. py:data:: dns.rdatatype.AXFR
18 :annotation: = 252
19 .. py:data:: dns.rdatatype.CAA
20 :annotation: = 257
21 .. py:data:: dns.rdatatype.CDNSKEY
22 :annotation: = 60
23 .. py:data:: dns.rdatatype.CDS
24 :annotation: = 59
25 .. py:data:: dns.rdatatype.CERT
26 :annotation: = 37
27 .. py:data:: dns.rdatatype.CNAME
28 :annotation: = 5
29 .. py:data:: dns.rdatatype.CSYNC
30 :annotation: = 62
31 .. py:data:: dns.rdatatype.DHCID
32 :annotation: = 49
33 .. py:data:: dns.rdatatype.DLV
34 :annotation: = 32769
35 .. py:data:: dns.rdatatype.DNAME
36 :annotation: = 39
37 .. py:data:: dns.rdatatype.DNSKEY
38 :annotation: = 48
39 .. py:data:: dns.rdatatype.DS
40 :annotation: = 43
41 .. py:data:: dns.rdatatype.EUI48
42 :annotation: = 108
43 .. py:data:: dns.rdatatype.EUI64
44 :annotation: = 109
45 .. py:data:: dns.rdatatype.GPOS
46 :annotation: = 27
47 .. py:data:: dns.rdatatype.HINFO
48 :annotation: = 13
49 .. py:data:: dns.rdatatype.HIP
50 :annotation: = 55
51 .. py:data:: dns.rdatatype.IPSECKEY
52 :annotation: = 45
53 .. py:data:: dns.rdatatype.ISDN
54 :annotation: = 20
55 .. py:data:: dns.rdatatype.IXFR
56 :annotation: = 251
57 .. py:data:: dns.rdatatype.KEY
58 :annotation: = 25
59 .. py:data:: dns.rdatatype.KX
60 :annotation: = 36
61 .. py:data:: dns.rdatatype.LOC
62 :annotation: = 29
63 .. py:data:: dns.rdatatype.MAILA
64 :annotation: = 254
65 .. py:data:: dns.rdatatype.MAILB
66 :annotation: = 253
67 .. py:data:: dns.rdatatype.MB
68 :annotation: = 7
69 .. py:data:: dns.rdatatype.MD
70 :annotation: = 3
71 .. py:data:: dns.rdatatype.MF
72 :annotation: = 4
73 .. py:data:: dns.rdatatype.MG
74 :annotation: = 8
75 .. py:data:: dns.rdatatype.MINFO
76 :annotation: = 14
77 .. py:data:: dns.rdatatype.MR
78 :annotation: = 9
79 .. py:data:: dns.rdatatype.MX
80 :annotation: = 15
81 .. py:data:: dns.rdatatype.NAPTR
82 :annotation: = 35
83 .. py:data:: dns.rdatatype.NONE
84 :annotation: = 0
85 .. py:data:: dns.rdatatype.NS
86 :annotation: = 2
87 .. py:data:: dns.rdatatype.NSAP
88 :annotation: = 22
89 .. py:data:: dns.rdatatype.NSAP-PTR
90 :annotation: = 23
91 .. py:data:: dns.rdatatype.NSEC
92 :annotation: = 47
93 .. py:data:: dns.rdatatype.NSEC3
94 :annotation: = 50
95 .. py:data:: dns.rdatatype.NSEC3PARAM
96 :annotation: = 51
97 .. py:data:: dns.rdatatype.NULL
98 :annotation: = 10
99 .. py:data:: dns.rdatatype.NXT
100 :annotation: = 30
101 .. py:data:: dns.rdatatype.OPT
102 :annotation: = 41
103 .. py:data:: dns.rdatatype.PTR
104 :annotation: = 12
105 .. py:data:: dns.rdatatype.PX
106 :annotation: = 26
107 .. py:data:: dns.rdatatype.RP
108 :annotation: = 17
109 .. py:data:: dns.rdatatype.RRSIG
110 :annotation: = 46
111 .. py:data:: dns.rdatatype.RT
112 :annotation: = 21
113 .. py:data:: dns.rdatatype.SIG
114 :annotation: = 24
115 .. py:data:: dns.rdatatype.SOA
116 :annotation: = 6
117 .. py:data:: dns.rdatatype.SPF
118 :annotation: = 99
119 .. py:data:: dns.rdatatype.SRV
120 :annotation: = 33
121 .. py:data:: dns.rdatatype.SSHFP
122 :annotation: = 44
123 .. py:data:: dns.rdatatype.TA
124 :annotation: = 32768
125 .. py:data:: dns.rdatatype.TKEY
126 :annotation: = 249
127 .. py:data:: dns.rdatatype.TLSA
128 :annotation: = 52
129 .. py:data:: dns.rdatatype.TSIG
130 :annotation: = 250
131 .. py:data:: dns.rdatatype.TXT
132 :annotation: = 16
133 .. py:data:: dns.rdatatype.UNSPEC
134 :annotation: = 103
135 .. py:data:: dns.rdatatype.URI
136 :annotation: = 256
137 .. py:data:: dns.rdatatype.WKS
138 :annotation: = 11
139 .. py:data:: dns.rdatatype.X25
140 :annotation: = 19
0 .. _resolver-caching:
1
2 Resolver Caching Classes
3 ========================
4
5 This is a placeholder.
6
7 .. autoclass:: dns.resolver.Cache
8 :members:
9
10 .. autoclass:: dns.resolver.LRUCache
11 :members:
12
0 .. _resolver-class:
1
2 The dns.resolver.Resolver and dns.resolver.Answer Classes
3 ---------------------------------------------------------
4
5 .. autoclass:: dns.resolver.Resolver
6 :members:
7
8 .. attribute:: domain
9
10 A ``dns.name.Name``, the domain of this host.
11
12 .. attribute:: nameservers
13
14 A ``list`` of ``text``, each item containing an IPv4 or IPv6 address.
15
16 .. attribute:: search
17
18 A ``list`` of dns.name.Name objects. If the query name is a
19 relative name, the resolver will construct absolute query names
20 to try by appending values from the search list.
21
22 .. attribute:: port
23
24 An ``int``, the default DNS port to send to if not overriden by
25 *nameserver_ports*. The default value is 53.
26
27 .. attribute:: nameserver_ports
28
29 A ``dict`` mapping an IPv4 or IPv6 address ``text`` to an ``int``.
30 This specifies the port to use when sending to a nameserver. If
31 a port is not defined for an address, the value of the *port*
32 attribute will be used.
33
34 .. attribute:: timeout
35
36 A ``float``, the number of seconds to wait for a response from
37 a server.
38
39 .. attribute:: lifetime
40
41 A ``float``, the number of seconds to spend trying to get an
42 answer to the question. If the lifetime expires a
43 ``dns.exception.Timeout`` exception will be raised.
44
45 .. attribute:: cache:
46
47 An object implementing the caching protocol, e.g. a
48 ``dns.resolver.Cache`` or a ``dns.resolver.LRUCache``. The default
49 is ``None``, in which case there is no local caching.
50
51 .. attribute:: retry_servfail
52
53 A ``bool``. Should we retry a nameserver if it says ``SERVFAIL``?
54 The default is ``False``.
55
56 .. attribute:: keyring
57
58 A ``dict``, the TSIG keyring to use. If a *keyring* is
59 specified but a *keyname* is not, then the key used will be
60 the first key in the *keyring*. Note that the order of keys
61 in a dictionary is not defined, so applications should supply
62 a keyname when a keyring is used, unless they know the keyring
63 contains only one key.
64
65 .. attribute:: keyname
66
67 A ``dns.name.Name`` or ``None``, the name of the TSIG key to
68 use; defaults to ``None``. The key must be defined in the
69 keyring.
70
71 .. attribute:: keyalgorithm
72
73 A ``dns.name.Name`` or ``text``, the TSIG algorithm to use.
74 *edns*, an ``int``, is the EDNS level to use. Specifying
75 ``None``, ``False``, or ``-1`` means "do not use EDNS", and in
76 this case the other parameters are ignored. Specifying
77 ``True`` is equivalent to specifying 0, i.e. "use EDNS0".
78
79 .. attribute:: ednsflags
80
81 An ``int``, the EDNS flag values.
82
83 .. attribute:: payload
84
85 An ``int``, is the EDNS sender's payload field, which is the
86 maximum size of UDP datagram the sender can handle. I.e. how big
87 a response to this message can be.
88
89 .. attribute:: flags
90
91 An ``int`` or ``None``, the message flags to use. If ``None``,
92 then the default flags as set by the ``dns.message.Message``
93 constructor will be used.
94
95
96 .. autoclass:: dns.resolver.Answer
97 :members:
98
99 .. attribute:: qname
100
101 A ``dns.name.Name``, the query name.
102
103 .. attribute:: rdclass
104
105 An ``int``, the query class.
106
107 .. attribute:: rdtype
108
109 An ``int``, the query type.
110
111 .. attribute:: response
112
113 A ``dns.message.Message``, the response message.
114
115 .. attribute:: rrset
116
117 A ``dns.rrset.RRset`` or ``None``, the answer RRset.
118
119 .. attribute:: expiration
120
121 A ``float``, the time when the answer expires.
122
123 .. attribute:: canonical_name
124
125 A ``dns.name.Name``, the canonical name of the query name,
126 i.e. the owner name of the answer RRset after any CNAME and DNAME
127 chaining.
0 .. _resolver-functions:
1
2 Resolver Functions and The Default Resolver
3 ===========================================
4
5 .. autofunction:: dns.resolver.query
6 .. autofunction:: dns.resolver.zone_for_name
7 .. autodata:: dns.resolver.default_resolver
8 .. autofunction:: dns.resolver.get_default_resolver
9 .. autofunction:: dns.resolver.reset_default_resolver
0 .. _resolver-override:
1
2 Overriding the System Resolver
3 ------------------------------
4
5 Sometimes it can be useful to make all of Python use dnspython's resolver
6 rather than the default functionality in the ``socket`` module. Dnspython
7 can redefine the entires in the socket module to point at its own code, and
8 it can also restore them back to the regular Python defaults.
9
10 .. autofunction:: dns.resolver.override_system_resolver
11 .. autofunction:: dns.resolver.restore_system_resolver
0 .. module:: dns.resolver
1 .. _resolver:
2
3 Stub Resolver
4 =============
5
6 This is a placeholder.
7
8 .. toctree::
9
10 resolver-class
11 resolver-functions
12 resolver-caching
13 resolver-override
0 .. _rfc:
1
2 DNS RFC Reference
3 =================
4
5 The DNS is defined by a large number of RFCs, many of which have been
6 extensively updated or obsoleted. This chapter aims to provide a
7 roadmap and reference for this confusing space. The chapter does not
8 aim to be encyclopedically complete, however, as the key information
9 would then be lost in the noise. The curious are encouraged to click
10 on the "Updated by" links on the IETF pages to see the finer points, or
11 the "Obsoletes" links to go spelunking into the history of the DNS.
12
13 DNSSEC gets its own section instead of being included in the "Core"
14 list because there are many DNSSEC related RFCs and it's helpful to group
15 them together. It's not a statement that DNSSEC isn't part of the "Core"
16 of the DNS.
17
18 The IANA `DNS Parameters <http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml>`_ registry is the offical reference site for all DNS
19 constants.
20
21
22 Core RFCs
23 ---------
24
25 `RFC 1034 <https://tools.ietf.org/html/rfc1034>`_
26 Introduction to the DNS and description of basic behavior.
27
28 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
29 The core DNS wire protocol and master file format.
30
31 `RFC 1995 <https://tools.ietf.org/html/rfc1995>`_
32 Incremental zone transfer (IXFR).
33
34 `RFC 1996 <https://tools.ietf.org/html/rfc1996>`_
35 The NOTIFY protocol.
36
37 `RFC 2181 <https://tools.ietf.org/html/rfc2181>`_
38 Clarifications to the specification.
39
40 `RFC 2308 <https://tools.ietf.org/html/rfc2308>`_
41 Negative Caching.
42
43 `RFC 2845 <https://tools.ietf.org/html/rfc2845>`_
44 Transaction Sigatures (TSIG)
45
46 `RFC 3007 <https://tools.ietf.org/html/rfc3007>`_
47 Dynamic Updates
48
49 `RFC 3645 <https://tools.ietf.org/html/rfc3645>`_
50 GSS-TSIG.
51
52 Note that dnspython does not currently have GSS-TSIG support.
53 GSS-TSIG is most frequently used when updating Microsoft
54 Active-Directory-based DNS servers.
55
56 `RFC 5936 <https://tools.ietf.org/html/rfc5936>`_
57 Zone transfers (AXFR).
58
59 `RFC 6891 <https://tools.ietf.org/html/rfc6891>`_
60 EDNS (version 0)
61
62 `RFC 8020 <https://tools.ietf.org/html/rfc8020>`_
63 Clarification on the meaning of NXDOMAIN.
64
65 DNSSEC RFCs
66 -----------
67
68 `RFC 4033 <https://tools.ietf.org/html/rfc4033>`_
69 Introduction and requirements.
70
71 `RFC 4034 <https://tools.ietf.org/html/rfc4034>`_
72 Resource records.
73
74 `RFC 4035 <https://tools.ietf.org/html/rfc4035>`_
75 Protocol.
76
77 `RFC 4470 <https://tools.ietf.org/html/rfc4470>`_
78 Minimally covering NSEC records and On-line Signing.
79
80 `RFC 6840 <https://tools.ietf.org/html/rfc6840>`_
81 Clarifications and implementation Notes.
82
83 Misc RFCs
84 ---------
85
86 `RFC 1101 <https://tools.ietf.org/html/rfc1101>`_
87 Reverse mapping name form for IPv4.
88
89 `RFC 1982 <https://tools.ietf.org/html/rfc1982>`_
90 Serial number arithmetic.
91
92 `RFC 4343 <https://tools.ietf.org/html/rfc4343>`_
93 Case-sensitivity clarification.
94
95 RFCs for RR types
96 -----------------
97
98 There are many more RR types than are listed here; if a type is not
99 listed it means it is obsolete, deprecated, or rare "in the wild".
100 Some newer types that are currently rare are listed because they may
101 well be more heavily used in the not-to-distant future.
102 See the
103 IANA `DNS Parameters <http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml>`_ registry for a complete list.
104
105 A
106 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
107 AAAA
108 `RFC 3596 <https://tools.ietf.org/html/rfc3596>`_
109 CDS
110 `RFC 7344 <https://tools.ietf.org/html/rfc7344>`_
111 CDNSKEY
112 `RFC 7344 <https://tools.ietf.org/html/rfc7344>`_
113 CNAME
114 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
115 CSYNC
116 `RFC 7477 <https://tools.ietf.org/html/rfc7477>`_
117 DNAME
118 `RFC 6672 <https://tools.ietf.org/html/rfc6672>`_
119 DNSKEY
120 `RFC 4034 <https://tools.ietf.org/html/rfc4034>`_
121 DS
122 `RFC 4034 <https://tools.ietf.org/html/rfc4034>`_
123 LOC
124 `RFC 1876 <https://tools.ietf.org/html/rfc1876>`_
125 MX
126 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
127 NAPTR
128 `RFC 3403 <https://tools.ietf.org/html/rfc3403>`_
129 NS
130 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
131 NSEC
132 `RFC 4034 <https://tools.ietf.org/html/rfc4034>`_
133 NSEC3
134 `RFC 5155 <https://tools.ietf.org/html/rfc5155>`_
135 NSEC3PARAM
136 `RFC 5155 <https://tools.ietf.org/html/rfc5155>`_
137 OPENPGPKEY
138 `RFC 7929 <https://tools.ietf.org/html/rfc7929>`_
139 PTR
140 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
141 RRSIG
142 `RFC 4034 <https://tools.ietf.org/html/rfc4034>`_
143 SOA
144 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
145 SPF
146 `RFC 7208 <https://tools.ietf.org/html/rfc7208>`_
147 SRV
148 `RFC 2782 <https://tools.ietf.org/html/rfc2782>`_
149 TLSA
150 `RFC 6698 <https://tools.ietf.org/html/rfc6698>`_
151 TXT
152 `RFC 1035 <https://tools.ietf.org/html/rfc1035>`_
0 #!/usr/bin/env python3
1
2 import importlib
3 import sys
4
5 name = sys.argv[1]
6 title = sys.argv[2]
7
8 print(title)
9 print('=' * len(title))
10 print()
11
12 module = importlib.import_module(name)
13 for t in sorted(module._by_text.keys()):
14 print('.. py:data:: {}.{}'.format(name, t))
15 print(' :annotation: = {}'.format(module._by_text[t]))
0 .. _utilities:
1
2 Miscellaneous Utilities
3 -----------------------
4
5 .. automodule:: dns.inet
6 :members:
7
8 .. automodule:: dns.ipv4
9 :members:
10
11 .. automodule:: dns.ipv6
12 :members:
13
14 .. autofunction:: dns.ttl.from_text
15
16 .. automodule:: dns.set
17 :members:
18
19 .. automodule:: dns.version
20 :members:
0 .. _whatsnew:
1
2 What's New in dnspython 1.16.0
3 ==============================
4
5 New Features
6 ------------
7
8 Bug Fixes
9 ---------
10
0 #!/usr/bin/env python
1
2 # Two ways of querying a specific nameserver.
3
4 from __future__ import print_function
5
6 import dns.message
7 import dns.rdataclass
8 import dns.rdatatype
9 import dns.query
10
11 # This way is just like nslookup/dig:
12
13 qname = dns.name.from_text('amazon.com')
14 q = dns.message.make_query(qname, dns.rdatatype.NS)
15 print('The query is:')
16 print(q)
17 print('')
18 r = dns.query.udp(q, '8.8.8.8')
19 print('The response is:')
20 print(r)
21 print('')
22 print('The nameservers are:')
23 ns_rrset = r.find_rrset(r.answer, qname, dns.rdataclass.IN, dns.rdatatype.NS)
24 for rr in ns_rrset:
25 print(rr.target)
26 print('')
27 print('')
28
29 # A higher-level way
30
31 import dns.resolver
32
33 resolver = dns.resolver.Resolver(configure=False)
34 resolver.nameservers = ['8.8.8.8']
35 answer = resolver.query('amazon.com', 'NS')
36 print('The nameservers are:')
37 for rr in answer:
38 print(rr.target)
0 #!/usr/bin/env python3
1
2 # This is just a toy, real code would check that the received message
3 # really was a NOTIFY, and otherwise handle errors.
4
5 from __future__ import print_function
6
7 import socket
8
9 import dns.flags
10 import dns.message
11 import dns.rdataclass
12 import dns.rdatatype
13 import dns.name
14
15 from typing import cast
16
17 address = '127.0.0.1'
18 port = 53535
19
20 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
21 s.bind((address, port))
22 while True:
23 (wire, address) = s.recvfrom(512)
24 notify = dns.message.from_wire(wire)
25 soa = notify.find_rrset(notify.answer, notify.question[0].name,
26 dns.rdataclass.IN, dns.rdatatype.SOA)
27
28 # Do something with the SOA RR here
29 print('The serial number for', soa.name, 'is', soa[0].serial)
30
31 response = dns.message.make_response(notify) # type: dns.message.Message
32 response.flags |= dns.flags.AA
33 wire = response.to_wire(cast(dns.name.Name, response))
34 s.sendto(wire, address)
2121 import dns.ipv4
2222 import os.path
2323 import sys
24 from typing import Dict, List # pylint: disable=unused-import
2425
25 reverse_map = {}
26 reverse_map = {} # type: Dict[str, List[str]]
2627
2728 for filename in sys.argv[1:]:
2829 zone = dns.zone.from_file(filename, os.path.basename(filename),
2930 relativize=False)
3031 for (name, ttl, rdata) in zone.iterate_rdatas('A'):
32 print(type(rdata))
3133 try:
3234 reverse_map[rdata.address].append(name.to_text())
3335 except KeyError:
3436 reverse_map[rdata.address] = [name.to_text()]
3537
36 keys = reverse_map.keys()
37 keys.sort(key=dns.ipv4.inet_aton)
38 for k in keys:
38 for k in sorted(reverse_map.keys(), key=dns.ipv4.inet_aton):
3939 v = reverse_map[k]
4040 v.sort()
4141 print(k, v)
99 master_answer = dns.resolver.query(soa_answer[0].mname, 'A')
1010
1111 z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, 'dnspython.org'))
12 names = z.nodes.keys()
13 names.sort()
14 for n in names:
12 for n in sorted(z.nodes.keys()):
1513 print(z[n].to_text(n))
2121 """See diff_zones.__doc__ for more information"""
2222
2323 from __future__ import print_function
24 from typing import cast, Union, Any # pylint: disable=unused-import
2425
2526 __all__ = ['diff_zones', 'format_changes_plain', 'format_changes_html']
2627
2728 try:
2829 import dns.zone
30 import dns.node
2931 except ImportError:
3032 raise SystemExit("Please install dnspython")
3133
3234
33 def diff_zones(zone1, zone2, ignore_ttl=False, ignore_soa=False):
35 def diff_zones(zone1, # type: dns.zone.Zone
36 zone2, # type: dns.zone.Zone
37 ignore_ttl=False,
38 ignore_soa=False
39 ): # type: (...) -> list
3440 """diff_zones(zone1, zone2, ignore_ttl=False, ignore_soa=False) -> changes
3541 Compares two dns.zone.Zone objects and returns a list of all changes
3642 in the format (name, oldnode, newnode).
4652
4753 changes = []
4854 for name in zone1:
49 name = str(name)
50 n1 = zone1.get_node(name)
51 n2 = zone2.get_node(name)
55 namestr = str(name)
56 n1 = cast(dns.node.Node, zone1.get_node(namestr))
57 n2 = cast(dns.node.Node, zone2.get_node(namestr))
5258 if not n2:
5359 changes.append((str(name), n1, n2))
5460 elif _nodes_differ(n1, n2, ignore_ttl, ignore_soa):
5561 changes.append((str(name), n1, n2))
5662
5763 for name in zone2:
58 n1 = zone1.get_node(name)
59 if not n1:
60 n2 = zone2.get_node(name)
61 changes.append((str(name), n1, n2))
64 n3 = cast(dns.node.Node, zone1.get_node(name))
65 if not n3:
66 n4 = cast(dns.node.Node, zone2.get_node(name))
67 changes.append((str(name), n3, n4))
6268 return changes
6369
64 def _nodes_differ(n1, n2, ignore_ttl, ignore_soa):
70 def _nodes_differ(n1, # type: dns.node.Node
71 n2, # type: dns.node.Node
72 ignore_ttl, # type: bool
73 ignore_soa # type: bool
74 ): # type: (...) -> bool
6575 if ignore_soa or not ignore_ttl:
6676 # Compare datasets directly
6777 for r in n1.rdatasets:
7787 continue
7888 if r not in n1.rdatasets:
7989 return True
90 assert False
8091 else:
8192 return n1 != n2
8293
83 def format_changes_plain(oldf, newf, changes, ignore_ttl=False):
94 def format_changes_plain(oldf, # type: str
95 newf, # type: str
96 changes, # type: list
97 ignore_ttl=False
98 ): # type: (...) -> str
8499 """format_changes(oldfile, newfile, changes, ignore_ttl=False) -> str
85100 Given 2 filenames and a list of changes from diff_zones, produce diff-like
86101 output. If ignore_ttl is True, TTL-only changes are not displayed"""
87102
88 ret = "--- %s\n+++ %s\n" % (oldf, newf)
103 ret = "--- {}\n+++ {}\n".format(oldf, newf)
89104 for name, old, new in changes:
90105 ret += "@ %s\n" % name
91106 if not old:
109124 ret += "+ %s\n" % str(r).replace('\n', '\n+ ')
110125 return ret
111126
112 def format_changes_html(oldf, newf, changes, ignore_ttl=False):
127 def format_changes_html(oldf, # type: str
128 newf, # type: str
129 changes, # type: list
130 ignore_ttl=False
131 ): # type: (...) -> str
113132 """format_changes(oldfile, newfile, changes, ignore_ttl=False) -> str
114133 Given 2 filenames and a list of changes from diff_zones, produce nice html
115134 output. If ignore_ttl is True, TTL-only changes are not displayed"""
160179
161180
162181 # Make this module usable as a script too.
163 def main():
182 def main(): # type: () -> None
164183 import argparse
165184 import subprocess
166185 import sys
189208 opts, args = p.parse_args()
190209 opts.use_vc = opts.use_git or opts.use_bzr or opts.use_rcs
191210
192 def _open(what, err):
211 def _open(what, err): # type: (Union[list,str], str) -> Any
193212 if isinstance(what, list):
194213 # Must be a list, open subprocess
195214 try:
224243 else:
225244 if len(args) == 3:
226245 filename, oldr, newr = args
227 oldn = "%s:%s" % (oldr, filename)
228 newn = "%s:%s" % (newr, filename)
246 oldn = "{}:{}".format(oldr, filename)
247 newn = "{}:{}".format(newr, filename)
229248 else:
230249 filename, oldr = args
231250 newr = None
232 oldn = "%s:%s" % (oldr, filename)
251 oldn = "{}:{}".format(oldr, filename)
233252 newn = filename
234253
235254 old, new = None, None
236255 oldz, newz = None, None
237256 if opts.use_bzr:
238257 old = _open(["bzr", "cat", "-r" + oldr, filename],
239 "Unable to retrieve revision %s of %s" % (oldr, filename))
240 if newr != None:
258 "Unable to retrieve revision {} of {}".format(oldr, filename))
259 if newr is not None:
241260 new = _open(["bzr", "cat", "-r" + newr, filename],
242 "Unable to retrieve revision %s of %s" % (newr, filename))
261 "Unable to retrieve revision {} of {}".format(newr, filename))
243262 elif opts.use_git:
244263 old = _open(["git", "show", oldn],
245 "Unable to retrieve revision %s of %s" % (oldr, filename))
246 if newr != None:
264 "Unable to retrieve revision {} of {}".format(oldr, filename))
265 if newr is not None:
247266 new = _open(["git", "show", newn],
248 "Unable to retrieve revision %s of %s" % (newr, filename))
267 "Unable to retrieve revision {} of {}".format(newr, filename))
249268 elif opts.use_rcs:
250269 old = _open(["co", "-q", "-p", "-r" + oldr, filename],
251 "Unable to retrieve revision %s of %s" % (oldr, filename))
252 if newr != None:
270 "Unable to retrieve revision {} of {}".format(oldr, filename))
271 if newr is not None:
253272 new = _open(["co", "-q", "-p", "-r" + newr, filename],
254 "Unable to retrieve revision %s of %s" % (newr, filename))
273 "Unable to retrieve revision {} of {}".format(newr, filename))
255274 if not opts.use_vc:
256275 old = _open(oldn, "Unable to open %s" % oldn)
257276 if not opts.use_vc or newr is None:
264283 try:
265284 oldz = dns.zone.from_file(old, origin='.', check_origin=False)
266285 except dns.exception.DNSException:
267 sys.stderr.write("Incorrect zonefile: %s\n", old)
286 sys.stderr.write("Incorrect zonefile: %s\n" % old)
268287 if opts.tracebacks:
269288 traceback.print_exc()
270289 try:
0 [MASTER]
1 # Pickle collected data for later comparisons.
2 persistent=no
3
4 # Use multiple processes to speed up Pylint, auto-detect number of cores.
5 jobs=0
6
7 [MESSAGES CONTROL]
8
9 enable=
10 all,
11 python3
12
13 # It's worth looking at len-as-condition for optimization, but it's disabled
14 # here as it is not a correctness thing. Similarly eq-without-hash is
15 # probably worth improving.
16
17 disable=
18 R,
19 I,
20 anomalous-backslash-in-string,
21 arguments-differ,
22 assigning-non-slot,
23 bad-builtin,
24 bad-continuation,
25 broad-except,
26 deprecated-method,
27 fixme,
28 global-statement,
29 invalid-name,
30 missing-docstring,
31 no-absolute-import,
32 no-member,
33 protected-access,
34 redefined-builtin,
35 too-many-lines,
36 unused-argument,
37 unused-variable,
38 wrong-import-order,
39 wrong-import-position,
40 len-as-condition,
41 eq-without-hash,
42 next-method-defined,
43
44 [REPORTS]
45
46 # Set the output format. Available formats are text, parseable, colorized, msvs
47 # (visual studio) and html. You can also give a reporter class, eg
48 # mypackage.mymodule.MyReporterClass.
49 output-format=colorized
50
51 # Tells whether to display a full report or only the messages
52 reports=no
53
54 # Template used to display messages. This is a python new-style format string
55 # used to format the message information. See doc for all details
56 msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg})'
0 [egg_info]
1 tag_build =
2 tag_date = 0
3 tag_svn_revision = 0
0 [bdist_wheel]
1 universal = 1
42
3 [metadata]
4 license_file = LICENSE
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 #!/usr/bin/env python
13 #
24 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
1719 import sys
1820 from setuptools import setup
1921
20 version = '1.15.0'
22 version = '1.16.0'
23
24 try:
25 sys.argv.remove("--cython-compile")
26 except ValueError:
27 compile_cython = False
28 else:
29 compile_cython = True
30 from Cython.Build import cythonize
31 ext_modules = cythonize(['dns/*.py', 'dns/rdtypes/*.py', 'dns/rdtypes/*/*.py'])
2132
2233 kwargs = {
2334 'name' : 'dnspython',
3647 'author_email' : 'halley@dnspython.org',
3748 'license' : 'BSD-like',
3849 'url' : 'http://www.dnspython.org',
39 'packages' : ['dns', 'dns.rdtypes', 'dns.rdtypes.IN', 'dns.rdtypes.ANY'],
50 'packages' : ['dns', 'dns.rdtypes', 'dns.rdtypes.IN', 'dns.rdtypes.ANY', 'dns.rdtypes.CH'],
51 'package_data' : {'dns': ['py.typed']},
4052 'download_url' : \
41 'http://www.dnspython.org/kits/%s/dnspython-%s.tar.gz' % (version, version),
53 'http://www.dnspython.org/kits/{}/dnspython-{}.tar.gz'.format(version, version),
4254 'classifiers' : [
4355 "Development Status :: 5 - Production/Stable",
4456 "Intended Audience :: Developers",
5062 "Topic :: Internet :: Name Service (DNS)",
5163 "Topic :: Software Development :: Libraries :: Python Modules",
5264 "Programming Language :: Python :: 2",
53 "Programming Language :: Python :: 2.6",
5465 "Programming Language :: Python :: 2.7",
5566 "Programming Language :: Python :: 3",
56 "Programming Language :: Python :: 3.3",
5767 "Programming Language :: Python :: 3.4",
5868 "Programming Language :: Python :: 3.5",
69 "Programming Language :: Python :: 3.6",
70 "Programming Language :: Python :: 3.7",
5971 ],
72 'python_requires': '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
6073 'test_suite': 'tests',
6174 'provides': ['dns'],
75 'extras_require': {
76 'IDNA': ['idna>=2.1'],
77 'DNSSEC': ['pycryptodome', 'ecdsa>=0.13'],
78 },
79 'ext_modules': ext_modules if compile_cython else None,
80 'zip_safe': False if compile_cython else None,
6281 }
6382
6483 setup(**kwargs)
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
194194 caa04 CAA 0 issue "ca.example.net; account=230123"
195195 caa05 CAA 0 issue "ca.example.net; policy=ev"
196196 caa06 CAA 128 tbs "Unknown"
197 openpgpkey OPENPGPKEY (
198 mQENBEteQDsBCADYnatn9+5t43AdJlVk9dZC2RM0idPQcmrrKcjeAWDnISqoJzkv
199 Q8ifX6mefquTBsDZC279uXShyTffYzQtvP2r9ewkK7zmSv52Ar563TSULAMwiLpe
200 0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3
201 ldx2Jz//kuru4YqROLBYyB8D6V2jNUFOdaP6j5C5prh9dxfYFp2O/xFeAKLWlWuH
202 9o96INUoIhgdEyj9PHPT3c821NMZu8tCvsZgUB+QPbHA/QYGa+aollcdGkJpVxXo
203 Hhbu6aMx/B+pXg55WM5pqOxmoVjyViHIUYfPABEBAAG0IUJvYiBIYWxsZXkgPGhh
204 bGxleUBkbnNweXRob24ub3JnPokBPgQTAQIAKAUCS15AOwIbAwUJA8JnAAYLCQgH
205 AwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d
206 24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7ZqRXAcOATNteQmpzqexx+BRKDWU8ZgYx1
207 2J4GZmC06jABr2JDWxgvbMX9qjkUUgDGZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKT
208 B9yNJ8v/WERlFdGaUveEUiFU8g75xp1Hj9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE6
209 7EQdFGgqQFynR53md7cmVhAGopKLwMkpCtToKUlxxlfnDfpKZhhXThmhA0PsUQUk
210 JptfGwYwH3O2N3KzfUw3wXRvLa3hona3TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1
211 kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUD
212 u4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUxpoI+A7WWk9ThfjbynoZxRD820Kbqidqx
213 BSgtFF36SRWzmX8DZfKKAskT9ZGU1odeSKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE
214 6Xd65JO6ufhad+ELhgFt95vRwTiFvVrBRjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu
215 0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5V
216 UqRR25ubXLuzx9PaHYiC5GiQIU45pWAd0IWcTI/MJQARAQABiQElBBgBAgAPBQJL
217 XkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12HRsIAKrB9E++9X9W6VTXBfdkShCFv0yk
218 ZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkMDMdGVe6bn4A3oIAbf0Tjykq1AetZLVPs
219 Hl/QosTbSQluis/PEvJkTQXHaKHB3bFhwA90c/3HNhrLGugt9AmcfLf9LAynXDgN
220 LV5eYdPYqfKE+27qjEBARf6PYh/8WQ8CPKS8DILFbwCZbRxUogyrZf/7AiHAGdJi
221 8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQRaHBhD4pHU1S/IRSlx9/3Ytww32PYD9A
222 yO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg0qzwVBNGb84v/ex2MouwtAYScwc=
223 )
197224 csync0 CSYNC 12345 0 A MX RRSIG NSEC TYPE1234
198225 avc01 AVC "app-name:WOLFGANG|app-class:OAM|business=yes"
8888 nsec03 3600 IN NSEC . NSEC TYPE65535
8989 nsec301 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
9090 nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
91 openpgpkey 3600 IN OPENPGPKEY mQENBEteQDsBCADYnatn9+5t43AdJlVk 9dZC2RM0idPQcmrrKcjeAWDnISqoJzkv Q8ifX6mefquTBsDZC279uXShyTffYzQt vP2r9ewkK7zmSv52Ar563TSULAMwiLpe 0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+ AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3 ldx2Jz//kuru4YqROLBYyB8D6V2jNUFO daP6j5C5prh9dxfYFp2O/xFeAKLWlWuH 9o96INUoIhgdEyj9PHPT3c821NMZu8tC vsZgUB+QPbHA/QYGa+aollcdGkJpVxXo Hhbu6aMx/B+pXg55WM5pqOxmoVjyViHI UYfPABEBAAG0IUJvYiBIYWxsZXkgPGhh bGxleUBkbnNweXRob24ub3JnPokBPgQT AQIAKAUCS15AOwIbAwUJA8JnAAYLCQgH AwIGFQgCCQoLBBYCAwECHgECF4AACgkQ 6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d 24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7Z qRXAcOATNteQmpzqexx+BRKDWU8ZgYx1 2J4GZmC06jABr2JDWxgvbMX9qjkUUgDG ZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKT B9yNJ8v/WERlFdGaUveEUiFU8g75xp1H j9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE6 7EQdFGgqQFynR53md7cmVhAGopKLwMkp CtToKUlxxlfnDfpKZhhXThmhA0PsUQUk JptfGwYwH3O2N3KzfUw3wXRvLa3hona3 TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1 kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1 SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUD u4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUx poI+A7WWk9ThfjbynoZxRD820Kbqidqx BSgtFF36SRWzmX8DZfKKAskT9ZGU1ode SKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE 6Xd65JO6ufhad+ELhgFt95vRwTiFvVrB RjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu 0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E 7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5V UqRR25ubXLuzx9PaHYiC5GiQIU45pWAd 0IWcTI/MJQARAQABiQElBBgBAgAPBQJL XkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12 HRsIAKrB9E++9X9W6VTXBfdkShCFv0yk ZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkM DMdGVe6bn4A3oIAbf0Tjykq1AetZLVPs Hl/QosTbSQluis/PEvJkTQXHaKHB3bFh wA90c/3HNhrLGugt9AmcfLf9LAynXDgN LV5eYdPYqfKE+27qjEBARf6PYh/8WQ8C PKS8DILFbwCZbRxUogyrZf/7AiHAGdJi 8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQ RaHBhD4pHU1S/IRSlx9/3Ytww32PYD9A yO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg 0qzwVBNGb84v/ex2MouwtAYScwc=
9192 ptr01 3600 IN PTR @
9293 px01 3600 IN PX 65535 foo. bar.
9394 px02 3600 IN PX 65535 . .
8888 nsec03.example. 3600 IN NSEC . NSEC TYPE65535
8989 nsec301.example. 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
9090 nsec302.example. 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
91 openpgpkey.example. 3600 IN OPENPGPKEY mQENBEteQDsBCADYnatn9+5t43AdJlVk 9dZC2RM0idPQcmrrKcjeAWDnISqoJzkv Q8ifX6mefquTBsDZC279uXShyTffYzQt vP2r9ewkK7zmSv52Ar563TSULAMwiLpe 0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+ AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3 ldx2Jz//kuru4YqROLBYyB8D6V2jNUFO daP6j5C5prh9dxfYFp2O/xFeAKLWlWuH 9o96INUoIhgdEyj9PHPT3c821NMZu8tC vsZgUB+QPbHA/QYGa+aollcdGkJpVxXo Hhbu6aMx/B+pXg55WM5pqOxmoVjyViHI UYfPABEBAAG0IUJvYiBIYWxsZXkgPGhh bGxleUBkbnNweXRob24ub3JnPokBPgQT AQIAKAUCS15AOwIbAwUJA8JnAAYLCQgH AwIGFQgCCQoLBBYCAwECHgECF4AACgkQ 6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d 24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7Z qRXAcOATNteQmpzqexx+BRKDWU8ZgYx1 2J4GZmC06jABr2JDWxgvbMX9qjkUUgDG ZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKT B9yNJ8v/WERlFdGaUveEUiFU8g75xp1H j9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE6 7EQdFGgqQFynR53md7cmVhAGopKLwMkp CtToKUlxxlfnDfpKZhhXThmhA0PsUQUk JptfGwYwH3O2N3KzfUw3wXRvLa3hona3 TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1 kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1 SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUD u4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUx poI+A7WWk9ThfjbynoZxRD820Kbqidqx BSgtFF36SRWzmX8DZfKKAskT9ZGU1ode SKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE 6Xd65JO6ufhad+ELhgFt95vRwTiFvVrB RjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu 0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E 7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5V UqRR25ubXLuzx9PaHYiC5GiQIU45pWAd 0IWcTI/MJQARAQABiQElBBgBAgAPBQJL XkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12 HRsIAKrB9E++9X9W6VTXBfdkShCFv0yk ZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkM DMdGVe6bn4A3oIAbf0Tjykq1AetZLVPs Hl/QosTbSQluis/PEvJkTQXHaKHB3bFh wA90c/3HNhrLGugt9AmcfLf9LAynXDgN LV5eYdPYqfKE+27qjEBARf6PYh/8WQ8C PKS8DILFbwCZbRxUogyrZf/7AiHAGdJi 8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQ RaHBhD4pHU1S/IRSlx9/3Ytww32PYD9A yO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg 0qzwVBNGb84v/ex2MouwtAYScwc=
9192 ptr01.example. 3600 IN PTR example.
9293 px01.example. 3600 IN PX 65535 foo. bar.
9394 px02.example. 3600 IN PX 65535 . .
8888 nsec03 3600 IN NSEC . NSEC TYPE65535
8989 nsec301 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
9090 nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM
91 openpgpkey 3600 IN OPENPGPKEY mQENBEteQDsBCADYnatn9+5t43AdJlVk 9dZC2RM0idPQcmrrKcjeAWDnISqoJzkv Q8ifX6mefquTBsDZC279uXShyTffYzQt vP2r9ewkK7zmSv52Ar563TSULAMwiLpe 0gGQE0ex20mX5ggtYn6czdbEtcKpW0t+ AfDqRk5YcpgqfZKXapKQ+A3CwWJKP9i3 ldx2Jz//kuru4YqROLBYyB8D6V2jNUFO daP6j5C5prh9dxfYFp2O/xFeAKLWlWuH 9o96INUoIhgdEyj9PHPT3c821NMZu8tC vsZgUB+QPbHA/QYGa+aollcdGkJpVxXo Hhbu6aMx/B+pXg55WM5pqOxmoVjyViHI UYfPABEBAAG0IUJvYiBIYWxsZXkgPGhh bGxleUBkbnNweXRob24ub3JnPokBPgQT AQIAKAUCS15AOwIbAwUJA8JnAAYLCQgH AwIGFQgCCQoLBBYCAwECHgECF4AACgkQ 6o6Gb8yUnXaflQgAhlhIqZGncRw3LV3d 24JmPD+UEcEGiVh2b/Ic/1TMec46Ts7Z qRXAcOATNteQmpzqexx+BRKDWU8ZgYx1 2J4GZmC06jABr2JDWxgvbMX9qjkUUgDG ZZgAS/B2x5AmKgy2ZnCUlaKfePcKmtKT B9yNJ8v/WERlFdGaUveEUiFU8g75xp1H j9Wp9sXCg9yeG1K2RwQ3RQd5tLudhyE6 7EQdFGgqQFynR53md7cmVhAGopKLwMkp CtToKUlxxlfnDfpKZhhXThmhA0PsUQUk JptfGwYwH3O2N3KzfUw3wXRvLa3hona3 TlHk3kfg7Qyd7oP4AZGbJKp97YHnfqo1 kp8rObkBDQRLXkA7AQgA0ePG7g5GgZ/1 SdtGZlJJiE2X15vTUc3KGfmx/kI5NaUD u4fXb+XK+yFy9I/X+UJ46JSkyhj6QvUx poI+A7WWk9ThfjbynoZxRD820Kbqidqx BSgtFF36SRWzmX8DZfKKAskT9ZGU1ode SKDXLCJF7qAbZVRTuFRiDFGwtoVIICeE 6Xd65JO6ufhad+ELhgFt95vRwTiFvVrB RjwF7ZgN/nOXfYncxZ/2mpFqfwsnB2eu 0A2XZBm8IngsSmr/Wrz1RQ7+SNMqt77E 7CKwBX7UIAZgyoJxIRxWirJoOt1rIm5V UqRR25ubXLuzx9PaHYiC5GiQIU45pWAd 0IWcTI/MJQARAQABiQElBBgBAgAPBQJL XkA7AhsMBQkDwmcAAAoJEOqOhm/MlJ12 HRsIAKrB9E++9X9W6VTXBfdkShCFv0yk ZVn2eVs6tkqzoub9s4f+Z5ylWw+a5nkM DMdGVe6bn4A3oIAbf0Tjykq1AetZLVPs Hl/QosTbSQluis/PEvJkTQXHaKHB3bFh wA90c/3HNhrLGugt9AmcfLf9LAynXDgN LV5eYdPYqfKE+27qjEBARf6PYh/8WQ8C PKS8DILFbwCZbRxUogyrZf/7AiHAGdJi 8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQ RaHBhD4pHU1S/IRSlx9/3Ytww32PYD9A yO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg 0qzwVBNGb84v/ex2MouwtAYScwc=
9192 ptr01 3600 IN PTR @
9293 px01 3600 IN PX 65535 foo. bar.
9394 px02 3600 IN PX 65535 . .
0 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2006-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
1517 from io import BytesIO
16 try:
17 import unittest2 as unittest
18 except ImportError:
19 import unittest
18 import unittest
19
20 import binascii
2021
2122 import dns.rdata
2223 import dns.rdataclass
2324 import dns.rdatatype
25 import dns.rdtypes.ANY.TXT
2426 import dns.ttl
2527
2628 class BugsTestCase(unittest.TestCase):
6769 wire, 0, rdlen)
6870 self.failUnless(rdata == rdata2)
6971
72 def test_trailing_zero_APL(self):
73 in4 = "!1:127.0.0.0/1"
74 rd4 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, in4)
75 out4 = rd4.to_digestable(dns.name.from_text("test"))
76 text4 = binascii.hexlify(out4).decode('ascii')
77 self.failUnless(text4 == '000101817f')
78 in6 = "!2:::1000/1"
79 rd6 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, in6)
80 out6 = rd6.to_digestable(dns.name.from_text("test"))
81 text6 = binascii.hexlify(out6).decode('ascii')
82 self.failUnless(text6 == '0002018f000000000000000000000000000010')
83
84 def test_TXT_conversions(self):
85 t1 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
86 [b'foo'])
87 t2 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
88 b'foo')
89 t3 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
90 'foo')
91 t4 = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT,
92 ['foo'])
93 self.failUnless(t1 == t2)
94 self.failUnless(t1 == t2)
95 self.failUnless(t1 == t4)
96
7097 if __name__ == '__main__':
7198 unittest.main()
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1416
1517 from __future__ import print_function
1618
17 try:
18 import unittest2 as unittest
19 except ImportError:
20 import unittest
21
22 try:
23 import Crypto.Util.number # pylint: disable=unused-import
24 import_ok = True
25 except ImportError:
26 import_ok = False
19 import unittest
2720
2821 import dns.dnssec
2922 import dns.name
155148 abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG',
156149 "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI")
157150
158 @unittest.skipUnless(import_ok, "skipping DNSSEC tests because pycrypto is not"
159 " installed")
151
152
153 @unittest.skipUnless(dns.dnssec._have_pycrypto,
154 "Pycryptodome cannot be imported")
160155 class DNSSECValidatorTestCase(unittest.TestCase):
161156
162 @unittest.skipUnless(dns.dnssec._have_pycrypto,
163 "PyCrypto cannot be imported")
164 def testAbsoluteRSAGood(self):
157 def testAbsoluteRSAGood(self): # type: () -> None
165158 dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when)
166159
167 @unittest.skipUnless(dns.dnssec._have_pycrypto,
168 "PyCrypto cannot be imported")
169 def testDuplicateKeytag(self):
160 def testDuplicateKeytag(self): # type: () -> None
170161 dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when)
171162
172 @unittest.skipUnless(dns.dnssec._have_pycrypto,
173 "PyCrypto cannot be imported")
174 def testAbsoluteRSABad(self):
175 def bad():
163 def testAbsoluteRSABad(self): # type: () -> None
164 def bad(): # type: () -> None
176165 dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None,
177166 when)
178167 self.failUnlessRaises(dns.dnssec.ValidationFailure, bad)
179168
180 @unittest.skipUnless(dns.dnssec._have_pycrypto,
181 "PyCrypto cannot be imported")
182 def testRelativeRSAGood(self):
169 def testRelativeRSAGood(self): # type: () -> None
183170 dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys,
184171 abs_dnspython_org, when)
185172
186 @unittest.skipUnless(dns.dnssec._have_pycrypto,
187 "PyCrypto cannot be imported")
188 def testRelativeRSABad(self):
189 def bad():
173 def testRelativeRSABad(self): # type: () -> None
174 def bad(): # type: () -> None
190175 dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys,
191176 abs_dnspython_org, when)
192177 self.failUnlessRaises(dns.dnssec.ValidationFailure, bad)
193178
194 def testMakeSHA256DS(self):
179 def testMakeSHA256DS(self): # type: () -> None
195180 ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, 'SHA256')
196181 self.failUnless(ds == good_ds)
197182
198 @unittest.skipUnless(dns.dnssec._have_pycrypto,
199 "PyCrypto cannot be imported")
200 def testAbsoluteDSAGood(self):
183 def testAbsoluteDSAGood(self): # type: () -> None
201184 dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None,
202185 when2)
203186
204 @unittest.skipUnless(dns.dnssec._have_pycrypto,
205 "PyCrypto cannot be imported")
206 def testAbsoluteDSABad(self):
207 def bad():
187 def testAbsoluteDSABad(self): # type: () -> None
188 def bad(): # type: () -> None
208189 dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig,
209190 abs_dsa_keys, None, when2)
210191 self.failUnlessRaises(dns.dnssec.ValidationFailure, bad)
211192
212 def testMakeExampleSHA1DS(self):
193 def testMakeExampleSHA1DS(self): # type: () -> None
213194 ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA1')
214195 self.failUnless(ds == example_ds_sha1)
215196
216 def testMakeExampleSHA256DS(self):
197 def testMakeExampleSHA256DS(self): # type: () -> None
217198 ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256')
218199 self.failUnless(ds == example_ds_sha256)
219200
220201 @unittest.skipUnless(dns.dnssec._have_ecdsa,
221202 "python ECDSA cannot be imported")
222 def testAbsoluteECDSA256Good(self):
203 def testAbsoluteECDSA256Good(self): # type: () -> None
223204 dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig,
224205 abs_ecdsa256_keys, None, when3)
225206
226207 @unittest.skipUnless(dns.dnssec._have_ecdsa,
227208 "python ECDSA cannot be imported")
228 def testAbsoluteECDSA256Bad(self):
229 def bad():
209 def testAbsoluteECDSA256Bad(self): # type: () -> None
210 def bad(): # type: () -> None
230211 dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig,
231212 abs_ecdsa256_keys, None, when3)
232213 self.failUnlessRaises(dns.dnssec.ValidationFailure, bad)
233214
234215 @unittest.skipUnless(dns.dnssec._have_ecdsa,
235216 "python ECDSA cannot be imported")
236 def testAbsoluteECDSA384Good(self):
217 def testAbsoluteECDSA384Good(self): # type: () -> None
237218 dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig,
238219 abs_ecdsa384_keys, None, when4)
239220
240221 @unittest.skipUnless(dns.dnssec._have_ecdsa,
241222 "python ECDSA cannot be imported")
242 def testAbsoluteECDSA384Bad(self):
243 def bad():
223 def testAbsoluteECDSA384Bad(self): # type: () -> None
224 def bad(): # type: () -> None
244225 dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig,
245226 abs_ecdsa384_keys, None, when4)
246227 self.failUnlessRaises(dns.dnssec.ValidationFailure, bad)
0 # -*- coding: utf-8
1 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
2
3 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
4 #
5 # Permission to use, copy, modify, and distribute this software and its
6 # documentation for any purpose with or without fee is hereby granted,
7 # provided that the above copyright notice and this permission notice
8 # appear in all copies.
9 #
10 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
11 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
13 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 from __future__ import print_function
19
20 import unittest
21
22 from io import BytesIO
23
24 import dns.edns
25
26 class OptionTestCase(unittest.TestCase):
27 def testGenericOption(self):
28 opt = dns.edns.GenericOption(3, b'data')
29 io = BytesIO()
30 opt.to_wire(io)
31 data = io.getvalue()
32 self.assertEqual(data, b'data')
33
34 def testECSOption_prefix_length(self):
35 opt = dns.edns.ECSOption('1.2.255.33', 20)
36 io = BytesIO()
37 opt.to_wire(io)
38 data = io.getvalue()
39 self.assertEqual(data, b'\x00\x01\x14\x00\x01\x02\xf0')
40
41 def testECSOption_from_wire(self):
42 opt = dns.edns.option_from_wire(8, b'\x00\x01\x14\x00\x01\x02\xf0',
43 0, 7)
44 self.assertEqual(opt.otype, dns.edns.ECS)
45 self.assertEqual(opt.address, '1.2.240.0')
46 self.assertEqual(opt.srclen, 20)
47 self.assertEqual(opt.scopelen, 0)
48
49 def testECSOption(self):
50 opt = dns.edns.ECSOption('1.2.3.4', 24)
51 io = BytesIO()
52 opt.to_wire(io)
53 data = io.getvalue()
54 self.assertEqual(data, b'\x00\x01\x18\x00\x01\x02\x03')
55
56 def testECSOption_v6(self):
57 opt = dns.edns.ECSOption('2001:4b98::1')
58 io = BytesIO()
59 opt.to_wire(io)
60 data = io.getvalue()
61 self.assertEqual(data, b'\x00\x02\x38\x00\x20\x01\x4b\x98\x00\x00\x00')
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 from dns.exception import DNSException
2120
2221
2322 class FormatedError(DNSException):
2423 fmt = "Custom format: {parameter}"
25 supp_kwargs = set(['parameter'])
24 supp_kwargs = {'parameter'}
2625
2726
2827 class ExceptionTestCase(unittest.TestCase):
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.flags
2120 import dns.rcode
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1517 import sys
1618 sys.path.insert(0, '../') # Force the local project to be *the* dns
1719
18 try:
19 import unittest2 as unittest
20 except ImportError:
21 import unittest
20 import unittest
2221
2322 import dns.exception
2423 import dns.rdata
139138
140139 class GenerateTestCase(unittest.TestCase):
141140
142 def testFromText(self):
143 def bad():
141 def testFromText(self): # type: () -> None
142 def bad(): # type: () -> None
144143 dns.zone.from_text(example_text, 'example.', relativize=True)
145144 self.failUnlessRaises(dns.zone.NoSOA, bad)
146145
147 def testFromText1(self):
148 def bad():
146 def testFromText1(self): # type: () -> None
147 def bad(): # type: () -> None
149148 dns.zone.from_text(example_text1, 'example.', relativize=True)
150149 self.failUnlessRaises(dns.zone.NoSOA, bad)
151150
152 def testIterateAllRdatas2(self):
151 def testIterateAllRdatas2(self): # type: () -> None
153152 z = dns.zone.from_text(example_text2, 'example.', relativize=True)
154153 l = list(z.iterate_rdatas())
155154 l.sort(key=_rdata_sort)
193192 exl.sort(key=_rdata_sort)
194193 self.failUnless(l == exl)
195194
196 def testIterateAllRdatas3(self):
195 def testIterateAllRdatas3(self): # type: () -> None
197196 z = dns.zone.from_text(example_text3, 'example.', relativize=True)
198197 l = list(z.iterate_rdatas())
199198 l.sort(key=_rdata_sort)
232231 '10.0.0.8'))]
233232 exl.sort(key=_rdata_sort)
234233 self.failUnless(l == exl)
235 def testGenerate1(self):
234 def testGenerate1(self): # type: () -> None
236235 z = dns.zone.from_text(example_text4, 'example.', relativize=True)
237236 l = list(z.iterate_rdatas())
238237 l.sort(key=_rdata_sort)
278277 exl.sort(key=_rdata_sort)
279278 self.assertEqual(l, exl)
280279
281 def testGenerate2(self):
280 def testGenerate2(self): # type: () -> None
282281 z = dns.zone.from_text(example_text5, 'example.', relativize=True)
283282 l = list(z.iterate_rdatas())
284283 l.sort(key=_rdata_sort)
321320 exl.sort(key=_rdata_sort)
322321 self.failUnless(l == exl)
323322
324 def testGenerate3(self):
323 def testGenerate3(self): # type: () -> None
325324 z = dns.zone.from_text(example_text6, 'example.', relativize=True)
326325 l = list(z.iterate_rdatas())
327326 l.sort(key=_rdata_sort)
364363 exl.sort(key=_rdata_sort)
365364 self.failUnless(l == exl)
366365
367 def testGenerate4(self):
366 def testGenerate4(self): # type: () -> None
368367 z = dns.zone.from_text(example_text7, 'example.', relativize=True)
369368 l = list(z.iterate_rdatas())
370369 l.sort(key=_rdata_sort)
407406 exl.sort(key=_rdata_sort)
408407 self.failUnless(l == exl)
409408
410 def testGenerate6(self):
409 def testGenerate6(self): # type: () -> None
411410 z = dns.zone.from_text(example_text9, 'example.', relativize=True)
412411 l = list(z.iterate_rdatas())
413412 l.sort(key=_rdata_sort)
457456 exl.sort(key=_rdata_sort)
458457 self.failUnless(l == exl)
459458
460 def testGenerate7(self):
459 def testGenerate7(self): # type: () -> None
461460 z = dns.zone.from_text(example_text10, 'example.', relativize=True)
462461 l = list(z.iterate_rdatas())
463462 l.sort(key=_rdata_sort)
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1517 import sys
1618 sys.path.insert(0, '../')
1719
18 try:
19 import unittest2 as unittest
20 except ImportError:
21 import unittest
20 import unittest
2221
2322 import dns
2423 import dns.exception
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918 import binascii
2019
2120 import dns.exception
2221 import dns.flags
2322 import dns.message
23 import dns.name
24 import dns.rdataclass
25 import dns.rdatatype
2426 from dns._compat import xrange
2527
2628 query_text = """id 1234
198200 m = dns.message.make_query('foo', 'A', options=[])
199201 self.failUnless(m.edns == 0)
200202
203 def test_FindRRset(self):
204 a = dns.message.from_text(answer_text)
205 n = dns.name.from_text('dnspython.org.')
206 rrs1 = a.find_rrset(a.answer, n, dns.rdataclass.IN, dns.rdatatype.SOA)
207 rrs2 = a.find_rrset(dns.message.ANSWER, n, dns.rdataclass.IN,
208 dns.rdatatype.SOA)
209 self.failUnless(rrs1 == rrs2)
210
201211 if __name__ == '__main__':
202212 unittest.main()
00 # -*- coding: utf-8
1 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
1 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
2
3 # Copyright (C) 2003-2017 Nominum, Inc.
24 #
35 # Permission to use, copy, modify, and distribute this software and its
46 # documentation for any purpose with or without fee is hereby granted,
1517
1618 from __future__ import print_function
1719
18 try:
19 import unittest2 as unittest
20 except ImportError:
21 import unittest
20 from typing import Dict # pylint: disable=unused-import
21 import unittest
2222
2323 from io import BytesIO
2424
2626 import dns.reversename
2727 import dns.e164
2828
29 # pylint: disable=line-too-long
29 # pylint: disable=line-too-long,unsupported-assignment-operation
3030
3131
3232 class NameTestCase(unittest.TestCase):
379379 def testToWire1(self):
380380 n = dns.name.from_text('FOO.bar')
381381 f = BytesIO()
382 compress = {}
382 compress = {} # type: Dict[dns.name.Name,int]
383383 n.to_wire(f, compress)
384384 self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00')
385385
386386 def testToWire2(self):
387387 n = dns.name.from_text('FOO.bar')
388388 f = BytesIO()
389 compress = {}
389 compress = {} # type: Dict[dns.name.Name,int]
390390 n.to_wire(f, compress)
391391 n.to_wire(f, compress)
392392 self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\xc0\x00')
395395 n1 = dns.name.from_text('FOO.bar')
396396 n2 = dns.name.from_text('foo.bar')
397397 f = BytesIO()
398 compress = {}
398 compress = {} # type: Dict[dns.name.Name,int]
399399 n1.to_wire(f, compress)
400400 n2.to_wire(f, compress)
401401 self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\xc0\x00')
404404 n1 = dns.name.from_text('FOO.bar')
405405 n2 = dns.name.from_text('a.foo.bar')
406406 f = BytesIO()
407 compress = {}
407 compress = {} # type: Dict[dns.name.Name,int]
408408 n1.to_wire(f, compress)
409409 n2.to_wire(f, compress)
410410 self.assertEqual(f.getvalue(), b'\x03FOO\x03bar\x00\x01\x61\xc0\x00')
413413 n1 = dns.name.from_text('FOO.bar')
414414 n2 = dns.name.from_text('a.foo.bar')
415415 f = BytesIO()
416 compress = {}
416 compress = {} # type: Dict[dns.name.Name,int]
417417 n1.to_wire(f, compress)
418418 n2.to_wire(f, None)
419419 self.assertEqual(f.getvalue(),
428428 def bad():
429429 n = dns.name.from_text('FOO.bar', None)
430430 f = BytesIO()
431 compress = {}
431 compress = {} # type: Dict[dns.name.Name,int]
432432 n.to_wire(f, compress)
433433 self.failUnlessRaises(dns.name.NeedAbsoluteNameOrOrigin, bad)
434434
763763
764764 def testForwardIPv4(self):
765765 n = dns.name.from_text('1.0.0.127.in-addr.arpa.')
766 e = b'127.0.0.1'
766 e = '127.0.0.1'
767767 text = dns.reversename.to_address(n)
768768 self.assertEqual(text, e)
769769
781781
782782 def testEnumToE164(self):
783783 n = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.')
784 e = b'+16505551212'
784 e = '+16505551212'
785785 text = dns.e164.to_e164(n)
786786 self.assertEqual(text, e)
787787
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.name
2120 import dns.namedict
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2006-2017 Nominum, Inc.
3 #
4 # Permission to use, copy, modify, and distribute this software and its
5 # documentation for any purpose with or without fee is hereby granted,
6 # provided that the above copyright notice and this permission notice
7 # appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 import unittest
18
19 import dns.rdata
20 import dns.rdataclass
21 import dns.rdatatype
22 import dns.rdtypes.ANY.TXT
23 import dns.ttl
24
25 class NSEC3TestCase(unittest.TestCase):
26 def test_NSEC3_bitmap(self):
27 rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3,
28 u"1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715 A CAA TYPE65534")
29 bitmap = bytearray(b'\0' * 32)
30 bitmap[31] = bitmap[31] | 2
31 self.assertEqual(rdata.windows, [(0, bytearray(b'@')),
32 (1, bytearray(b'@')), # CAA = 257
33 (255, bitmap)
34 ])
35
36 if __name__ == '__main__':
37 unittest.main()
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1416
1517 from __future__ import print_function
1618
17 try:
18 import unittest2 as unittest
19 except ImportError:
20 import unittest
19 import unittest
2120 import binascii
2221
2322 import dns.exception
2423 import dns.ipv4
2524 import dns.ipv6
25 import dns.inet
2626
2727 # for convenience
2828 aton4 = dns.ipv4.inet_aton
169169 self.failUnlessRaises(ValueError, bad)
170170
171171 def test_good_v4_aton(self):
172 pairs = [(b'1.2.3.4', b'\x01\x02\x03\x04'),
173 (b'255.255.255.255', b'\xff\xff\xff\xff'),
174 (b'0.0.0.0', b'\x00\x00\x00\x00')]
172 pairs = [('1.2.3.4', b'\x01\x02\x03\x04'),
173 ('255.255.255.255', b'\xff\xff\xff\xff'),
174 ('0.0.0.0', b'\x00\x00\x00\x00')]
175175 for (t, b) in pairs:
176176 b1 = aton4(t)
177177 t1 = ntoa4(b1)
213213 self.failUnless(dns.ipv6.is_mapped(aton6(t2)))
214214 self.failIf(dns.ipv6.is_mapped(aton6(t3)))
215215
216 def test_is_multicast(self):
217 t1 = '223.0.0.1'
218 t2 = '240.0.0.1'
219 t3 = '224.0.0.1'
220 t4 = '239.0.0.1'
221 t5 = 'fe00::1'
222 t6 = 'ff00::1'
223 self.failIf(dns.inet.is_multicast(t1))
224 self.failIf(dns.inet.is_multicast(t2))
225 self.failUnless(dns.inet.is_multicast(t3))
226 self.failUnless(dns.inet.is_multicast(t4))
227 self.failIf(dns.inet.is_multicast(t5))
228 self.failUnless(dns.inet.is_multicast(t6))
229
216230 if __name__ == '__main__':
217231 unittest.main()
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.rdata
2120 import dns.rdataclass
2221 import dns.rdatatype
22
23 import tests.ttxt_module
2324
2425 class RdataTestCase(unittest.TestCase):
2526
3132 rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, u"1.2.3.4")
3233 self.failUnless(rdata.address == "1.2.3.4")
3334
35 def test_module_registration(self):
36 TTXT = 64001
37 dns.rdata.register_type(tests.ttxt_module, TTXT, 'TTXT')
38 rdata = dns.rdata.from_text(dns.rdataclass.IN, TTXT, 'hello world')
39 self.failUnless(rdata.strings == [b'hello', b'world'])
40 self.failUnless(dns.rdatatype.to_text(TTXT) == 'TTXT')
41 self.failUnless(dns.rdatatype.from_text('TTXT') == TTXT)
42
43 def test_module_reregistration(self):
44 def bad():
45 TTXTTWO = dns.rdatatype.TXT
46 dns.rdata.register_type(tests.ttxt_module, TTXTTWO, 'TTXTTWO')
47 self.failUnlessRaises(dns.rdata.RdatatypeExists, bad)
48
3449 if __name__ == '__main__':
3550 unittest.main()
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.rdataclass
2120 import dns.rdatatype
1313 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1414 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515
16 try:
17 import unittest2 as unittest
18 except ImportError:
19 import unittest
16 import unittest
2017
2118 import dns.rrset
2219 import dns.rdtypes.ANY.DNSKEY
2320
21 from typing import Set # pylint: disable=unused-import
2422
2523 class RdtypeAnyDnskeyTestCase(unittest.TestCase):
2624
27 def testFlagsEmpty(self):
25 def testFlagsEmpty(self): # type: () -> None
2826 '''Test DNSKEY flag to/from text conversion for zero flag/empty set.'''
29 good_s = set()
27 good_s = set() #type: Set[str]
3028 good_f = 0
3129 from_flags = dns.rdtypes.ANY.DNSKEY.flags_to_text_set(good_f)
3230 self.failUnless(from_flags == good_s,
33 '"%s" != "%s"' % (from_flags, good_s))
31 '"{}" != "{}"'.format(from_flags, good_s))
3432 from_set = dns.rdtypes.ANY.DNSKEY.flags_from_text_set(good_s)
3533 self.failUnless(from_set == good_f,
36 '"0x%x" != "0x%x"' % (from_set, good_f))
34 '"0x{:x}" != "0x{:x}"'.format(from_set, good_f))
3735
38 def testFlagsAll(self):
36 def testFlagsAll(self): # type: () -> None
3937 '''Test that all defined flags are recognized.'''
40 good_s = set(['SEP', 'REVOKE', 'ZONE'])
38 good_s = {'SEP', 'REVOKE', 'ZONE'}
4139 good_f = 0x181
4240 from_flags = dns.rdtypes.ANY.DNSKEY.flags_to_text_set(good_f)
4341 self.failUnless(from_flags == good_s,
44 '"%s" != "%s"' % (from_flags, good_s))
42 '"{}" != "{}"'.format(from_flags, good_s))
4543 from_text = dns.rdtypes.ANY.DNSKEY.flags_from_text_set(good_s)
4644 self.failUnless(from_text == good_f,
47 '"0x%x" != "0x%x"' % (from_text, good_f))
45 '"0x{:x}" != "0x{:x}"'.format(from_text, good_f))
4846
49 def testFlagsUnknownToText(self):
47 def testFlagsUnknownToText(self): # type: () -> None
5048 '''Test that undefined flags are returned in hexadecimal notation.'''
51 unk_s = set(['0x8000'])
49 unk_s = {'0x8000'}
5250 flags_s = dns.rdtypes.ANY.DNSKEY.flags_to_text_set(0x8000)
53 self.failUnless(flags_s == unk_s, '"%s" != "%s"' % (flags_s, unk_s))
51 self.failUnless(flags_s == unk_s, '"{}" != "{}"'.format(flags_s, unk_s))
5452
55 def testFlagsUnknownToFlags(self):
53 def testFlagsUnknownToFlags(self): # type: () -> None
5654 '''Test that conversion from undefined mnemonic raises error.'''
5755 self.failUnlessRaises(NotImplementedError,
5856 dns.rdtypes.ANY.DNSKEY.flags_from_text_set,
5957 (['0x8000']))
6058
61 def testFlagsRRToText(self):
59 def testFlagsRRToText(self): # type: () -> None
6260 '''Test that RR method returns correct flags.'''
6361 rr = dns.rrset.from_text('foo', 300, 'IN', 'DNSKEY', '257 3 8 KEY=')[0]
64 rr_s = set(['ZONE', 'SEP'])
62 rr_s = {'ZONE', 'SEP'}
6563 flags_s = rr.flags_to_text_set()
66 self.failUnless(flags_s == rr_s, '"%s" != "%s"' % (flags_s, rr_s))
64 self.failUnless(flags_s == rr_s, '"{}" != "{}"'.format(flags_s, rr_s))
6765
6866
6967 if __name__ == '__main__':
1313 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1414 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515
16 try:
17 import unittest2 as unittest
18 except ImportError:
19 import unittest
16 import unittest
2017 from io import BytesIO
2118
2219 import dns.rrset
1313 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1414 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1515
16 try:
17 import unittest2 as unittest
18 except ImportError:
19 import unittest
16 import unittest
2017
2118 import dns.rrset
2219 import dns.rdtypes.ANY.LOC
3027 r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc',
3128 '49 11 42.400 N 16 36 29.600 E 227.64m '
3229 '1.00m 10000.00m 10.00m')
33 self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2))
30 self.failUnless(r1 == r2, '"{}" != "{}"'.format(r1, r2))
3431
3532 def testEqual2(self):
3633 '''Test default values for size, horizontal and vertical precision.'''
4138 (16, 36, 29, 600, 1),
4239 22764.0, # centimeters
4340 100.0, 1000000.00, 1000.0) # centimeters
44 self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2))
41 self.failUnless(r1 == r2, '"{}" != "{}"'.format(r1, r2))
4542
4643 def testEqual3(self):
4744 '''Test size, horizontal and vertical precision parsers: 100 cm == 1 m.
5350 r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc',
5451 '49 11 42.400 N 16 36 29.600 E 227.64m '
5552 '2.00m 10.00m 2.00m')[0]
56 self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2))
53 self.failUnless(r1 == r2, '"{}" != "{}"'.format(r1, r2))
5754
5855 def testEqual4(self):
5956 '''Test size, horizontal and vertical precision parsers without unit.
6663 r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc',
6764 '49 11 42.400 N 16 36 29.600 E 227.64 '
6865 '2 10 2')[0] # meters without explicit unit
69 self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2))
66 self.failUnless(r1 == r2, '"{}" != "{}"'.format(r1, r2))
7067
7168 if __name__ == '__main__':
7269 unittest.main()
0 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
2 # Copyright (C) 2003-2017 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
35 # documentation for any purpose with or without fee is hereby granted,
1719 import sys
1820 import socket
1921 import time
20 try:
21 import unittest2 as unittest
22 except ImportError:
23 import unittest
22 import unittest
2423
2524 import dns.message
2625 import dns.name
2726 import dns.rdataclass
2827 import dns.rdatatype
2928 import dns.resolver
30 from dns._compat import xrange
29 from dns._compat import xrange, PY3
3130
3231 # Some tests require the internet to be available to run, so let's
3332 # skip those if it's not there.
132131 time.sleep(2)
133132 self.failUnless(cache.get((name, dns.rdatatype.A, dns.rdataclass.IN))
134133 is None)
134
135 def testIndexErrorOnEmptyRRsetAccess(self):
136 def bad():
137 message = dns.message.from_text(message_text)
138 name = dns.name.from_text('example.')
139 answer = dns.resolver.Answer(name, dns.rdatatype.MX,
140 dns.rdataclass.IN, message,
141 False)
142 return answer[0]
143 self.failUnlessRaises(IndexError, bad)
144
145 def testIndexErrorOnEmptyRRsetDelete(self):
146 def bad():
147 message = dns.message.from_text(message_text)
148 name = dns.name.from_text('example.')
149 answer = dns.resolver.Answer(name, dns.rdatatype.MX,
150 dns.rdataclass.IN, message,
151 False)
152 del answer[0]
153 self.failUnlessRaises(IndexError, bad)
135154
136155 @unittest.skipIf(not _network_available, "Internet not reachable")
137156 def testZoneForName1(self):
259278 def test_nxdomain_compatible(self):
260279 n1 = dns.name.Name(('a', 'b', ''))
261280 n2 = dns.name.Name(('a', 'b', 's', ''))
262 py3 = (sys.version_info[0] > 2)
263281
264282 try:
265283 raise dns.resolver.NXDOMAIN
266284 except dns.exception.DNSException as e:
267 if not py3:
285 if not PY3:
286 # pylint: disable=exception-message-attribute
268287 self.assertTrue((e.message == e.__doc__))
269288 self.assertTrue((e.args == (e.__doc__,)))
270289 self.assertTrue(('kwargs' in dir(e)))
275294 try:
276295 raise dns.resolver.NXDOMAIN("errmsg")
277296 except dns.exception.DNSException as e:
278 if not py3:
297 if not PY3:
298 # pylint: disable=exception-message-attribute
279299 self.assertTrue((e.message == "errmsg"))
280300 self.assertTrue((e.args == ("errmsg",)))
281301 self.assertTrue(('kwargs' in dir(e)))
286306 try:
287307 raise dns.resolver.NXDOMAIN("errmsg", -1)
288308 except dns.exception.DNSException as e:
289 if not py3:
309 if not PY3:
310 # pylint: disable=exception-message-attribute
290311 self.assertTrue((e.message == ""))
291312 self.assertTrue((e.args == ("errmsg", -1)))
292313 self.assertTrue(('kwargs' in dir(e)))
313334 raise dns.resolver.NXDOMAIN(qnames=[n1])
314335 except dns.exception.DNSException as e:
315336 MSG = "The DNS query name does not exist: a.b."
316 if not py3:
337 if not PY3:
338 # pylint: disable=exception-message-attribute
317339 self.assertTrue((e.message == MSG), e.message)
318340 self.assertTrue((e.args == (MSG,)), repr(e.args))
319341 self.assertTrue(('kwargs' in dir(e)))
325347
326348 try:
327349 raise dns.resolver.NXDOMAIN(qnames=[n2, n1])
328 except Exception as e:
350 except dns.resolver.NXDOMAIN as e:
329351 e0 = dns.resolver.NXDOMAIN("errmsg")
330352 e = e0 + e
331353 MSG = "None of DNS query names exist: a.b.s., a.b."
332 if not py3:
354 if not PY3:
355 # pylint: disable=exception-message-attribute
333356 self.assertTrue((e.message == MSG), e.message)
334357 self.assertTrue((e.args == (MSG,)), repr(e.args))
335358 self.assertTrue(('kwargs' in dir(e)))
346369
347370 try:
348371 raise dns.resolver.NXDOMAIN(qnames=[n1], responses={n1: 'r1.1'})
349 except Exception as e:
372 except dns.resolver.NXDOMAIN as e:
350373 MSG = "The DNS query name does not exist: a.b."
351 if not py3:
374 if not PY3:
375 # pylint: disable=exception-message-attribute
352376 self.assertTrue((e.message == MSG), e.message)
353377 self.assertTrue((e.args == (MSG,)), repr(e.args))
354378 self.assertTrue(('kwargs' in dir(e)))
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.rrset
2120
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.set
2120
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918
2019 import dns.exception
2120 import dns.tokenizer
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1214 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1315 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1416
15 try:
16 import unittest2 as unittest
17 except ImportError:
18 import unittest
17 import unittest
1918 import binascii
2019
2120 import dns.update
6261
6362 class UpdateTestCase(unittest.TestCase):
6463
65 def test_to_wire1(self):
64 def test_to_wire1(self): # type: () -> None
6665 update = dns.update.Update('example')
6766 update.id = 1
6867 update.present('foo')
7776 update.delete('blaz2')
7877 self.failUnless(update.to_wire() == goodwire)
7978
80 def test_to_wire2(self):
79 def test_to_wire2(self): # type: () -> None
8180 update = dns.update.Update('example')
8281 update.id = 1
8382 update.present('foo')
9291 update.delete('blaz2')
9392 self.failUnless(update.to_wire() == goodwire)
9493
95 def test_to_wire3(self):
94 def test_to_wire3(self): # type: () -> None
9695 update = dns.update.Update('example')
9796 update.id = 1
9897 update.present('foo')
107106 update.delete('blaz2')
108107 self.failUnless(update.to_wire() == goodwire)
109108
110 def test_from_text1(self):
109 def test_from_text1(self): # type: () -> None
111110 update = dns.message.from_text(update_text)
112111 w = update.to_wire(origin=dns.name.from_text('example'),
113112 want_shuffle=False)
55 # provided that the above copyright notice and this permission notice
66 # appear in all copies.
77
8 try:
9 import unittest2 as unittest
10 except ImportError:
11 import unittest
8 import unittest
129
1310 from dns.exception import FormError
1411 from dns.wiredata import WireData
0 # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
1
02 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
13 #
24 # Permission to use, copy, modify, and distribute this software and its
1517 from io import BytesIO, StringIO
1618 import filecmp
1719 import os
18 try:
19 import unittest2 as unittest
20 except ImportError:
21 import unittest
20 import unittest
21 from typing import cast
2222
2323 import dns.exception
2424 import dns.rdata
25 import dns.rdataset
2526 import dns.rdataclass
2627 import dns.rdatatype
2728 import dns.rrset
2829 import dns.zone
30 import dns.node
2931
3032 def here(filename):
3133 return os.path.join(os.path.dirname(__file__), filename)
7577 ns2 1w1D1h1m1S a 10.0.0.2
7678 """
7779
80 # No $TTL so default TTL for RRs should be inherited from SOA minimum TTL (
81 # not from the last explicit RR TTL).
82 ttl_from_soa_text = """$ORIGIN example.
83 @ 1h soa foo bar 1 2 3 4 5
84 @ 1h ns ns1
85 @ 1h ns ns2
86 ns1 1w1D1h1m1S a 10.0.0.2
87 ns2 a 10.0.0.1
88 """
89
90 # No $TTL and no SOA, so default TTL for RRs should be inherited from last
91 # explicit RR TTL.
92 ttl_from_last_text = """$ORIGIN example.
93 @ 1h ns ns1
94 @ 1h ns ns2
95 ns1 a 10.0.0.1
96 ns2 1w1D1h1m1S a 10.0.0.2
97 """
98
99 # No $TTL and no SOA should raise SyntaxError as no TTL can be determined.
100 no_ttl_text = """$ORIGIN example.
101 @ ns ns1
102 @ ns ns2
103 ns1 a 10.0.0.1
104 ns2 a 10.0.0.2
105 """
106
78107 no_soa_text = """$TTL 1h
79108 $ORIGIN example.
80109 @ ns ns1
107136
108137 class ZoneTestCase(unittest.TestCase):
109138
110 def testFromFile1(self):
139 def testFromFile1(self): # type: () -> None
111140 z = dns.zone.from_file(here('example'), 'example')
112141 ok = False
113142 try:
119148 os.unlink(here('example1.out'))
120149 self.failUnless(ok)
121150
122 def testFromFile2(self):
151 def testFromFile2(self): # type: () -> None
123152 z = dns.zone.from_file(here('example'), 'example', relativize=False)
124153 ok = False
125154 try:
131160 os.unlink(here('example2.out'))
132161 self.failUnless(ok)
133162
134 def testToFileTextualStream(self):
163 def testToFileTextualStream(self): # type: () -> None
135164 z = dns.zone.from_text(example_text, 'example.', relativize=True)
136165 f = StringIO()
137166 z.to_file(f)
139168 f.close()
140169 self.assertEqual(out, example_text_output)
141170
142 def testToFileBinaryStream(self):
171 def testToFileBinaryStream(self): # type: () -> None
143172 z = dns.zone.from_text(example_text, 'example.', relativize=True)
144173 f = BytesIO()
145174 z.to_file(f)
147176 f.close()
148177 self.assertEqual(out, example_text_output.encode())
149178
150 def testToFileTextual(self):
179 def testToFileTextual(self): # type: () -> None
151180 z = dns.zone.from_file(here('example'), 'example')
152181 try:
153182 f = open(here('example3-textual.out'), 'w')
160189 os.unlink(here('example3-textual.out'))
161190 self.failUnless(ok)
162191
163 def testToFileBinary(self):
192 def testToFileBinary(self): # type: () -> None
164193 z = dns.zone.from_file(here('example'), 'example')
165194 try:
166195 f = open(here('example3-binary.out'), 'wb')
173202 os.unlink(here('example3-binary.out'))
174203 self.failUnless(ok)
175204
176 def testToFileFilename(self):
205 def testToFileFilename(self): # type: () -> None
177206 z = dns.zone.from_file(here('example'), 'example')
178207 try:
179 z.to_file('example3-filename.out')
208 z.to_file(here('example3-filename.out'))
180209 ok = filecmp.cmp(here('example3-filename.out'),
181210 here('example3.good'))
182211 finally:
184213 os.unlink(here('example3-filename.out'))
185214 self.failUnless(ok)
186215
187 def testToText(self):
216 def testToText(self): # type: () -> None
188217 z = dns.zone.from_file(here('example'), 'example')
189218 ok = False
190219 try:
199228 os.unlink(here('example3.out'))
200229 self.failUnless(ok)
201230
202 def testFromText(self):
231 def testFromText(self): # type: () -> None
203232 z = dns.zone.from_text(example_text, 'example.', relativize=True)
204233 f = StringIO()
205234 names = list(z.nodes.keys())
209238 f.write(u'\n')
210239 self.assertEqual(f.getvalue(), example_text_output)
211240
212 def testTorture1(self):
241 def testTorture1(self): # type: () -> None
213242 #
214243 # Read a zone containing all our supported RR types, and
215244 # for each RR in the zone, convert the rdata into wire format
230259 origin=o)
231260 self.failUnless(rd == rd2)
232261
233 def testEqual(self):
262 def testEqual(self): # type: () -> None
234263 z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
235264 z2 = dns.zone.from_text(example_text_output, 'example.',
236265 relativize=True)
237266 self.failUnless(z1 == z2)
238267
239 def testNotEqual1(self):
268 def testNotEqual1(self): # type: () -> None
240269 z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
241270 z2 = dns.zone.from_text(something_quite_similar, 'example.',
242271 relativize=True)
243272 self.failUnless(z1 != z2)
244273
245 def testNotEqual2(self):
274 def testNotEqual2(self): # type: () -> None
246275 z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
247276 z2 = dns.zone.from_text(something_different, 'example.',
248277 relativize=True)
249278 self.failUnless(z1 != z2)
250279
251 def testNotEqual3(self):
280 def testNotEqual3(self): # type: () -> None
252281 z1 = dns.zone.from_text(example_text, 'example.', relativize=True)
253282 z2 = dns.zone.from_text(something_different, 'example2.',
254283 relativize=True)
255284 self.failUnless(z1 != z2)
256285
257 def testFindRdataset1(self):
286 def testFindRdataset1(self): # type: () -> None
258287 z = dns.zone.from_text(example_text, 'example.', relativize=True)
259288 rds = z.find_rdataset('@', 'soa')
260289 exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
261290 self.failUnless(rds == exrds)
262291
263 def testFindRdataset2(self):
264 def bad():
292 def testFindRdataset2(self): # type: () -> None
293 def bad(): # type: () -> None
265294 z = dns.zone.from_text(example_text, 'example.', relativize=True)
266295 z.find_rdataset('@', 'loc')
267296 self.failUnlessRaises(KeyError, bad)
268297
269 def testFindRRset1(self):
298 def testFindRRset1(self): # type: () -> None
270299 z = dns.zone.from_text(example_text, 'example.', relativize=True)
271300 rrs = z.find_rrset('@', 'soa')
272301 exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5')
273302 self.failUnless(rrs == exrrs)
274303
275 def testFindRRset2(self):
276 def bad():
304 def testFindRRset2(self): # type: () -> None
305 def bad(): # type: () -> None
277306 z = dns.zone.from_text(example_text, 'example.', relativize=True)
278307 z.find_rrset('@', 'loc')
279308 self.failUnlessRaises(KeyError, bad)
280309
281 def testGetRdataset1(self):
310 def testGetRdataset1(self): # type: () -> None
282311 z = dns.zone.from_text(example_text, 'example.', relativize=True)
283312 rds = z.get_rdataset('@', 'soa')
284313 exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
285314 self.failUnless(rds == exrds)
286315
287 def testGetRdataset2(self):
316 def testGetRdataset2(self): # type: () -> None
288317 z = dns.zone.from_text(example_text, 'example.', relativize=True)
289318 rds = z.get_rdataset('@', 'loc')
290319 self.failUnless(rds is None)
291320
292 def testGetRRset1(self):
321 def testGetRRset1(self): # type: () -> None
293322 z = dns.zone.from_text(example_text, 'example.', relativize=True)
294323 rrs = z.get_rrset('@', 'soa')
295324 exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5')
296325 self.failUnless(rrs == exrrs)
297326
298 def testGetRRset2(self):
327 def testGetRRset2(self): # type: () -> None
299328 z = dns.zone.from_text(example_text, 'example.', relativize=True)
300329 rrs = z.get_rrset('@', 'loc')
301330 self.failUnless(rrs is None)
302331
303 def testReplaceRdataset1(self):
332 def testReplaceRdataset1(self): # type: () -> None
304333 z = dns.zone.from_text(example_text, 'example.', relativize=True)
305334 rdataset = dns.rdataset.from_text('in', 'ns', 300, 'ns3', 'ns4')
306335 z.replace_rdataset('@', rdataset)
307336 rds = z.get_rdataset('@', 'ns')
308337 self.failUnless(rds is rdataset)
309338
310 def testReplaceRdataset2(self):
339 def testReplaceRdataset2(self): # type: () -> None
311340 z = dns.zone.from_text(example_text, 'example.', relativize=True)
312341 rdataset = dns.rdataset.from_text('in', 'txt', 300, '"foo"')
313342 z.replace_rdataset('@', rdataset)
314343 rds = z.get_rdataset('@', 'txt')
315344 self.failUnless(rds is rdataset)
316345
317 def testDeleteRdataset1(self):
346 def testDeleteRdataset1(self): # type: () -> None
318347 z = dns.zone.from_text(example_text, 'example.', relativize=True)
319348 z.delete_rdataset('@', 'ns')
320349 rds = z.get_rdataset('@', 'ns')
321350 self.failUnless(rds is None)
322351
323 def testDeleteRdataset2(self):
352 def testDeleteRdataset2(self): # type: () -> None
324353 z = dns.zone.from_text(example_text, 'example.', relativize=True)
325354 z.delete_rdataset('ns1', 'a')
326355 node = z.get_node('ns1')
327356 self.failUnless(node is None)
328357
329 def testNodeFindRdataset1(self):
358 def testNodeFindRdataset1(self): # type: () -> None
330359 z = dns.zone.from_text(example_text, 'example.', relativize=True)
331360 node = z['@']
332361 rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
333362 exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
334363 self.failUnless(rds == exrds)
335364
336 def testNodeFindRdataset2(self):
337 def bad():
365 def testNodeFindRdataset2(self): # type: () -> None
366 def bad(): # type: () -> None
338367 z = dns.zone.from_text(example_text, 'example.', relativize=True)
339368 node = z['@']
340369 node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
341370 self.failUnlessRaises(KeyError, bad)
342371
343 def testNodeGetRdataset1(self):
372 def testNodeGetRdataset1(self): # type: () -> None
344373 z = dns.zone.from_text(example_text, 'example.', relativize=True)
345374 node = z['@']
346375 rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
347376 exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5')
348377 self.failUnless(rds == exrds)
349378
350 def testNodeGetRdataset2(self):
379 def testNodeGetRdataset2(self): # type: () -> None
351380 z = dns.zone.from_text(example_text, 'example.', relativize=True)
352381 node = z['@']
353382 rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
354383 self.failUnless(rds is None)
355384
356 def testNodeDeleteRdataset1(self):
385 def testNodeDeleteRdataset1(self): # type: () -> None
357386 z = dns.zone.from_text(example_text, 'example.', relativize=True)
358387 node = z['@']
359388 node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
360389 rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
361390 self.failUnless(rds is None)
362391
363 def testNodeDeleteRdataset2(self):
392 def testNodeDeleteRdataset2(self): # type: () -> None
364393 z = dns.zone.from_text(example_text, 'example.', relativize=True)
365394 node = z['@']
366395 node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
367396 rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC)
368397 self.failUnless(rds is None)
369398
370 def testIterateRdatasets(self):
399 def testIterateRdatasets(self): # type: () -> None
371400 z = dns.zone.from_text(example_text, 'example.', relativize=True)
372401 ns = [n for n, r in z.iterate_rdatasets('A')]
373402 ns.sort()
374403 self.failUnless(ns == [dns.name.from_text('ns1', None),
375404 dns.name.from_text('ns2', None)])
376405
377 def testIterateAllRdatasets(self):
406 def testIterateAllRdatasets(self): # type: () -> None
378407 z = dns.zone.from_text(example_text, 'example.', relativize=True)
379408 ns = [n for n, r in z.iterate_rdatasets()]
380409 ns.sort()
384413 dns.name.from_text('ns1', None),
385414 dns.name.from_text('ns2', None)])
386415
387 def testIterateRdatas(self):
416 def testIterateRdatas(self): # type: () -> None
388417 z = dns.zone.from_text(example_text, 'example.', relativize=True)
389418 l = list(z.iterate_rdatas('A'))
390419 l.sort()
398427 '10.0.0.2'))]
399428 self.failUnless(l == exl)
400429
401 def testIterateAllRdatas(self):
430 def testIterateAllRdatas(self): # type: () -> None
402431 z = dns.zone.from_text(example_text, 'example.', relativize=True)
403432 l = list(z.iterate_rdatas())
404433 l.sort(key=_rdata_sort)
429458 exl.sort(key=_rdata_sort)
430459 self.failUnless(l == exl)
431460
432 def testTTLs(self):
461 def testTTLs(self): # type: () -> None
433462 z = dns.zone.from_text(ttl_example_text, 'example.', relativize=True)
434 n = z['@']
435 rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA)
463 n = z['@'] # type: dns.node.Node
464 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA))
436465 self.failUnless(rds.ttl == 3600)
437466 n = z['ns1']
438 rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
467 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
439468 self.failUnless(rds.ttl == 86401)
440469 n = z['ns2']
441 rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
470 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
442471 self.failUnless(rds.ttl == 694861)
443472
444 def testNoSOA(self):
445 def bad():
473 def testTTLFromSOA(self): # type: () -> None
474 z = dns.zone.from_text(ttl_from_soa_text, 'example.', relativize=True)
475 n = z['@']
476 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA))
477 self.failUnless(rds.ttl == 3600)
478 soa_rd = rds[0]
479 n = z['ns1']
480 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
481 self.failUnless(rds.ttl == 694861)
482 n = z['ns2']
483 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
484 self.failUnless(rds.ttl == soa_rd.minimum)
485
486 def testTTLFromLast(self): # type: () -> None
487 z = dns.zone.from_text(ttl_from_last_text, 'example.', check_origin=False)
488 n = z['@']
489 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.NS))
490 self.failUnless(rds.ttl == 3600)
491 n = z['ns1']
492 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
493 self.failUnless(rds.ttl == 3600)
494 n = z['ns2']
495 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
496 self.failUnless(rds.ttl == 694861)
497
498 def testNoTTL(self): # type: () -> None
499 def bad(): # type: () -> None
500 dns.zone.from_text(no_ttl_text, 'example.', check_origin=False)
501 self.failUnlessRaises(dns.exception.SyntaxError, bad)
502
503 def testNoSOA(self): # type: () -> None
504 def bad(): # type: () -> None
446505 dns.zone.from_text(no_soa_text, 'example.', relativize=True)
447506 self.failUnlessRaises(dns.zone.NoSOA, bad)
448507
449 def testNoNS(self):
450 def bad():
508 def testNoNS(self): # type: () -> None
509 def bad(): # type: () -> None
451510 dns.zone.from_text(no_ns_text, 'example.', relativize=True)
452511 self.failUnlessRaises(dns.zone.NoNS, bad)
453512
454 def testInclude(self):
513 def testInclude(self): # type: () -> None
455514 z1 = dns.zone.from_text(include_text, 'example.', relativize=True,
456515 allow_include=True)
457516 z2 = dns.zone.from_file(here('example'), 'example.', relativize=True)
458517 self.failUnless(z1 == z2)
459518
460 def testBadDirective(self):
461 def bad():
519 def testBadDirective(self): # type: () -> None
520 def bad(): # type: () -> None
462521 dns.zone.from_text(bad_directive_text, 'example.', relativize=True)
463522 self.failUnlessRaises(dns.exception.SyntaxError, bad)
464523
465 def testFirstRRStartsWithWhitespace(self):
524 def testFirstRRStartsWithWhitespace(self): # type: () -> None
466525 # no name is specified, so default to the initial origin
467 # no ttl is specified, so default to the initial TTL of 0
468 z = dns.zone.from_text(' IN A 10.0.0.1', origin='example.',
526 z = dns.zone.from_text(' 300 IN A 10.0.0.1', origin='example.',
469527 check_origin=False)
470528 n = z['@']
471 rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A)
472 self.failUnless(rds.ttl == 0)
473
474 def testZoneOrigin(self):
529 rds = cast(dns.rdataset.Rdataset, n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A))
530 self.failUnless(rds.ttl == 300)
531
532 def testZoneOrigin(self): # type: () -> None
475533 z = dns.zone.Zone('example.')
476534 self.failUnless(z.origin == dns.name.from_text('example.'))
477 def bad1():
535 def bad1(): # type: () -> None
478536 o = dns.name.from_text('example', None)
479537 dns.zone.Zone(o)
480538 self.failUnlessRaises(ValueError, bad1)
481 def bad2():
482 dns.zone.Zone(1.0)
539 def bad2(): # type: () -> None
540 dns.zone.Zone(cast(str, 1.0))
483541 self.failUnlessRaises(ValueError, bad2)
484542
485 def testZoneOriginNone(self):
486 dns.zone.Zone(None)
543 def testZoneOriginNone(self): # type: () -> None
544 dns.zone.Zone(cast(str, None))
487545
488546 if __name__ == '__main__':
489547 unittest.main()
0 import dns.rdtypes.txtbase
1
2 class TTXT(dns.rdtypes.txtbase.TXTBase):
3 """Test TXT-like record"""
00 import os.path
11 import sys
2 try:
3 import unittest2 as unittest
4 except ImportError:
5 import unittest
2 import unittest
63
74 if __name__ == '__main__':
85 sys.path.insert(0, os.path.realpath('..'))
9 suites = unittest.defaultTestLoader.discover('.')
6 if len(sys.argv) > 1:
7 pattern = sys.argv[1]
8 else:
9 pattern = 'test*.py'
10 suites = unittest.defaultTestLoader.discover('.', pattern)
1011 if not unittest.TextTestRunner(verbosity=2).run(suites).wasSuccessful():
1112 sys.exit(1)
0 [tox]
1 envlist =
2 py27,
3 py34,
4 py35,
5 py36,
6 py37,
7 flake8,
8 pylint,
9 mypy,
10 coverage
11
12 [testenv]
13
14 commands=
15 python setup.py test
16
17 deps=
18
19 [testenv:py27]
20 deps =
21 typing
22
23
24 [testenv:flake8]
25 commands =
26 pip install flake8
27 flake8 dns
28
29 [testenv:pylint]
30 commands =
31 pip install pylint
32 pylint dns
33
34 [testenv:mypy]
35 commands =
36 pip install mypy
37 mypy examples tests
38
39 [testenv:coverage]
40 basepython = python2
41
42 deps =
43 coverage
44
45 commands =
46 python setup.py install
47 coverage run --rcfile=.coverage.ini setup.py test
48 coverage report
49
50 [pep8]
51 show-pep8 = True
52 show-source = True
53