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