1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Talk to a DNS server."""
17
18 from __future__ import generators
19
20 import errno
21 import select
22 import socket
23 import struct
24 import sys
25 import time
26
27 import dns.exception
28 import dns.inet
29 import dns.name
30 import dns.message
31 import dns.rdataclass
32 import dns.rdatatype
33
35 """Raised if a query response comes from an unexpected address or port."""
36 pass
37
39 """Raised if a query response does not respond to the question asked."""
40 pass
41
43 if timeout is None:
44 return None
45 else:
46 return time.time() + timeout
47
48 -def _poll_for(fd, readable, writable, error, timeout):
49 """Poll polling backend.
50 @param fd: File descriptor
51 @type fd: int
52 @param readable: Whether to wait for readability
53 @type readable: bool
54 @param writable: Whether to wait for writability
55 @type writable: bool
56 @param timeout: Deadline timeout (expiration time, in seconds)
57 @type timeout: float
58 @return True on success, False on timeout
59 """
60 event_mask = 0
61 if readable:
62 event_mask |= select.POLLIN
63 if writable:
64 event_mask |= select.POLLOUT
65 if error:
66 event_mask |= select.POLLERR
67
68 pollable = select.poll()
69 pollable.register(fd, event_mask)
70
71 if timeout:
72 event_list = pollable.poll(int(timeout * 1000))
73 else:
74 event_list = pollable.poll()
75
76 return bool(event_list)
77
78 -def _select_for(fd, readable, writable, error, timeout):
79 """Select polling backend.
80 @param fd: File descriptor
81 @type fd: int
82 @param readable: Whether to wait for readability
83 @type readable: bool
84 @param writable: Whether to wait for writability
85 @type writable: bool
86 @param timeout: Deadline timeout (expiration time, in seconds)
87 @type timeout: float
88 @return True on success, False on timeout
89 """
90 rset, wset, xset = [], [], []
91
92 if readable:
93 rset = [fd]
94 if writable:
95 wset = [fd]
96 if error:
97 xset = [fd]
98
99 if timeout is None:
100 (rcount, wcount, xcount) = select.select(rset, wset, xset)
101 else:
102 (rcount, wcount, xcount) = select.select(rset, wset, xset, timeout)
103
104 return bool((rcount or wcount or xcount))
105
106 -def _wait_for(fd, readable, writable, error, expiration):
107 done = False
108 while not done:
109 if expiration is None:
110 timeout = None
111 else:
112 timeout = expiration - time.time()
113 if timeout <= 0.0:
114 raise dns.exception.Timeout
115 try:
116 if not _polling_backend(fd, readable, writable, error, timeout):
117 raise dns.exception.Timeout
118 except select.error as e:
119 if e.errno != errno.EINTR:
120 raise e
121 done = True
122
124 """
125 Internal API. Do not use.
126 """
127 global _polling_backend
128
129 _polling_backend = fn
130
131 if hasattr(select, 'poll'):
132
133
134
135 _polling_backend = _poll_for
136 else:
137 _polling_backend = _select_for
138
140 _wait_for(s, True, False, True, expiration)
141
143 _wait_for(s, False, True, True, expiration)
144
152
154
155
156 if af is None:
157 try:
158 af = dns.inet.af_for_address(where)
159 except:
160 af = dns.inet.AF_INET
161 if af == dns.inet.AF_INET:
162 destination = (where, port)
163 if source is not None or source_port != 0:
164 if source is None:
165 source = '0.0.0.0'
166 source = (source, source_port)
167 elif af == dns.inet.AF_INET6:
168 destination = (where, port, 0, 0)
169 if source is not None or source_port != 0:
170 if source is None:
171 source = '::'
172 source = (source, source_port, 0, 0)
173 return (af, destination, source)
174
175 -def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
176 ignore_unexpected=False, one_rr_per_rrset=False):
177 """Return the response obtained after sending a query via UDP.
178
179 @param q: the query
180 @type q: dns.message.Message
181 @param where: where to send the message
182 @type where: string containing an IPv4 or IPv6 address
183 @param timeout: The number of seconds to wait before the query times out.
184 If None, the default, wait forever.
185 @type timeout: float
186 @param port: The port to which to send the message. The default is 53.
187 @type port: int
188 @param af: the address family to use. The default is None, which
189 causes the address family to use to be inferred from the form of of where.
190 If the inference attempt fails, AF_INET is used.
191 @type af: int
192 @rtype: dns.message.Message object
193 @param source: source address. The default is the wildcard address.
194 @type source: string
195 @param source_port: The port from which to send the message.
196 The default is 0.
197 @type source_port: int
198 @param ignore_unexpected: If True, ignore responses from unexpected
199 sources. The default is False.
200 @type ignore_unexpected: bool
201 @param one_rr_per_rrset: Put each RR into its own RRset
202 @type one_rr_per_rrset: bool
203 """
204
205 wire = q.to_wire()
206 (af, destination, source) = _destination_and_source(af, where, port, source,
207 source_port)
208 s = socket.socket(af, socket.SOCK_DGRAM, 0)
209 try:
210 expiration = _compute_expiration(timeout)
211 s.setblocking(0)
212 if source is not None:
213 s.bind(source)
214 _wait_for_writable(s, expiration)
215 s.sendto(wire, destination)
216 while 1:
217 _wait_for_readable(s, expiration)
218 (wire, from_address) = s.recvfrom(65535)
219 if _addresses_equal(af, from_address, destination) or \
220 (dns.inet.is_multicast(where) and \
221 from_address[1:] == destination[1:]):
222 break
223 if not ignore_unexpected:
224 raise UnexpectedSource('got a response from '
225 '%s instead of %s' % (from_address,
226 destination))
227 finally:
228 s.close()
229 r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
230 one_rr_per_rrset=one_rr_per_rrset)
231 if not q.is_response(r):
232 raise BadResponse
233 return r
234
236 """Read the specified number of bytes from sock. Keep trying until we
237 either get the desired amount, or we hit EOF.
238 A Timeout exception will be raised if the operation is not completed
239 by the expiration time.
240 """
241 s = b''
242 while count > 0:
243 _wait_for_readable(sock, expiration)
244 n = sock.recv(count)
245 if n == b'':
246 raise EOFError
247 count = count - len(n)
248 s = s + n
249 return s
250
252 """Write the specified data to the socket.
253 A Timeout exception will be raised if the operation is not completed
254 by the expiration time.
255 """
256 current = 0
257 l = len(data)
258 while current < l:
259 _wait_for_writable(sock, expiration)
260 current += sock.send(data[current:])
261
263 try:
264 s.connect(address)
265 except socket.error:
266 (ty, v) = sys.exc_info()[:2]
267 if v.errno != errno.EINPROGRESS and \
268 v.errno != errno.EWOULDBLOCK and \
269 v.errno != errno.EALREADY:
270 raise v
271
272 -def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
273 one_rr_per_rrset=False):
274 """Return the response obtained after sending a query via TCP.
275
276 @param q: the query
277 @type q: dns.message.Message object
278 @param where: where to send the message
279 @type where: string containing an IPv4 or IPv6 address
280 @param timeout: The number of seconds to wait before the query times out.
281 If None, the default, wait forever.
282 @type timeout: float
283 @param port: The port to which to send the message. The default is 53.
284 @type port: int
285 @param af: the address family to use. The default is None, which
286 causes the address family to use to be inferred from the form of of where.
287 If the inference attempt fails, AF_INET is used.
288 @type af: int
289 @rtype: dns.message.Message object
290 @param source: source address. The default is the wildcard address.
291 @type source: string
292 @param source_port: The port from which to send the message.
293 The default is 0.
294 @type source_port: int
295 @param one_rr_per_rrset: Put each RR into its own RRset
296 @type one_rr_per_rrset: bool
297 """
298
299 wire = q.to_wire()
300 (af, destination, source) = _destination_and_source(af, where, port, source,
301 source_port)
302 s = socket.socket(af, socket.SOCK_STREAM, 0)
303 try:
304 expiration = _compute_expiration(timeout)
305 s.setblocking(0)
306 if source is not None:
307 s.bind(source)
308 _connect(s, destination)
309
310 l = len(wire)
311
312
313
314
315 tcpmsg = struct.pack("!H", l) + wire
316 _net_write(s, tcpmsg, expiration)
317 ldata = _net_read(s, 2, expiration)
318 (l,) = struct.unpack("!H", ldata)
319 wire = _net_read(s, l, expiration)
320 finally:
321 s.close()
322 r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
323 one_rr_per_rrset=one_rr_per_rrset)
324 if not q.is_response(r):
325 raise BadResponse
326 return r
327
328 -def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
329 timeout=None, port=53, keyring=None, keyname=None, relativize=True,
330 af=None, lifetime=None, source=None, source_port=0, serial=0,
331 use_udp=False, keyalgorithm=dns.tsig.default_algorithm):
332 """Return a generator for the responses to a zone transfer.
333
334 @param where: where to send the message
335 @type where: string containing an IPv4 or IPv6 address
336 @param zone: The name of the zone to transfer
337 @type zone: dns.name.Name object or string
338 @param rdtype: The type of zone transfer. The default is
339 dns.rdatatype.AXFR.
340 @type rdtype: int or string
341 @param rdclass: The class of the zone transfer. The default is
342 dns.rdatatype.IN.
343 @type rdclass: int or string
344 @param timeout: The number of seconds to wait for each response message.
345 If None, the default, wait forever.
346 @type timeout: float
347 @param port: The port to which to send the message. The default is 53.
348 @type port: int
349 @param keyring: The TSIG keyring to use
350 @type keyring: dict
351 @param keyname: The name of the TSIG key to use
352 @type keyname: dns.name.Name object or string
353 @param relativize: If True, all names in the zone will be relativized to
354 the zone origin. It is essential that the relativize setting matches
355 the one specified to dns.zone.from_xfr().
356 @type relativize: bool
357 @param af: the address family to use. The default is None, which
358 causes the address family to use to be inferred from the form of of where.
359 If the inference attempt fails, AF_INET is used.
360 @type af: int
361 @param lifetime: The total number of seconds to spend doing the transfer.
362 If None, the default, then there is no limit on the time the transfer may
363 take.
364 @type lifetime: float
365 @rtype: generator of dns.message.Message objects.
366 @param source: source address. The default is the wildcard address.
367 @type source: string
368 @param source_port: The port from which to send the message.
369 The default is 0.
370 @type source_port: int
371 @param serial: The SOA serial number to use as the base for an IXFR diff
372 sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
373 @type serial: int
374 @param use_udp: Use UDP (only meaningful for IXFR)
375 @type use_udp: bool
376 @param keyalgorithm: The TSIG algorithm to use; defaults to
377 dns.tsig.default_algorithm
378 @type keyalgorithm: string
379 """
380
381 if isinstance(zone, str):
382 zone = dns.name.from_text(zone)
383 if isinstance(rdtype, str):
384 rdtype = dns.rdatatype.from_text(rdtype)
385 q = dns.message.make_query(zone, rdtype, rdclass)
386 if rdtype == dns.rdatatype.IXFR:
387 rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA',
388 '. . %u 0 0 0 0' % serial)
389 q.authority.append(rrset)
390 if not keyring is None:
391 q.use_tsig(keyring, keyname, algorithm=keyalgorithm)
392 wire = q.to_wire()
393 (af, destination, source) = _destination_and_source(af, where, port, source,
394 source_port)
395 if use_udp:
396 if rdtype != dns.rdatatype.IXFR:
397 raise ValueError('cannot do a UDP AXFR')
398 s = socket.socket(af, socket.SOCK_DGRAM, 0)
399 else:
400 s = socket.socket(af, socket.SOCK_STREAM, 0)
401 s.setblocking(0)
402 if source is not None:
403 s.bind(source)
404 expiration = _compute_expiration(lifetime)
405 _connect(s, destination)
406 l = len(wire)
407 if use_udp:
408 _wait_for_writable(s, expiration)
409 s.send(wire)
410 else:
411 tcpmsg = struct.pack("!H", l) + wire
412 _net_write(s, tcpmsg, expiration)
413 done = False
414 soa_rrset = None
415 soa_count = 0
416 if relativize:
417 origin = zone
418 oname = dns.name.empty
419 else:
420 origin = None
421 oname = zone
422 tsig_ctx = None
423 first = True
424 while not done:
425 mexpiration = _compute_expiration(timeout)
426 if mexpiration is None or mexpiration > expiration:
427 mexpiration = expiration
428 if use_udp:
429 _wait_for_readable(s, expiration)
430 (wire, from_address) = s.recvfrom(65535)
431 else:
432 ldata = _net_read(s, 2, mexpiration)
433 (l,) = struct.unpack("!H", ldata)
434 wire = _net_read(s, l, mexpiration)
435 r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
436 xfr=True, origin=origin, tsig_ctx=tsig_ctx,
437 multi=True, first=first,
438 one_rr_per_rrset=(rdtype==dns.rdatatype.IXFR))
439 tsig_ctx = r.tsig_ctx
440 first = False
441 answer_index = 0
442 delete_mode = False
443 expecting_SOA = False
444 if soa_rrset is None:
445 if not r.answer or r.answer[0].name != oname:
446 raise dns.exception.FormError
447 rrset = r.answer[0]
448 if rrset.rdtype != dns.rdatatype.SOA:
449 raise dns.exception.FormError("first RRset is not an SOA")
450 answer_index = 1
451 soa_rrset = rrset.copy()
452 if rdtype == dns.rdatatype.IXFR:
453 if soa_rrset[0].serial == serial:
454
455
456
457 done = True
458 else:
459 expecting_SOA = True
460
461
462
463
464 for rrset in r.answer[answer_index:]:
465 if done:
466 raise dns.exception.FormError("answers after final SOA")
467 if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname:
468 if expecting_SOA:
469 if rrset[0].serial != serial:
470 raise dns.exception.FormError("IXFR base serial mismatch")
471 expecting_SOA = False
472 elif rdtype == dns.rdatatype.IXFR:
473 delete_mode = not delete_mode
474 if rrset == soa_rrset and not delete_mode:
475 done = True
476 elif expecting_SOA:
477
478
479
480
481
482 rdtype = dns.rdatatype.AXFR
483 expecting_SOA = False
484 if done and q.keyring and not r.had_tsig:
485 raise dns.exception.FormError("missing TSIG")
486 yield r
487 s.close()
488