Index: tools/telemetry/third_party/webpagereplay/third_party/dns/query.py |
diff --git a/tools/telemetry/third_party/webpagereplay/third_party/dns/query.py b/tools/telemetry/third_party/webpagereplay/third_party/dns/query.py |
deleted file mode 100644 |
index c023b140aff67d1d0748c87718849ebc7076d7e5..0000000000000000000000000000000000000000 |
--- a/tools/telemetry/third_party/webpagereplay/third_party/dns/query.py |
+++ /dev/null |
@@ -1,428 +0,0 @@ |
-# Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc. |
-# |
-# Permission to use, copy, modify, and distribute this software and its |
-# documentation for any purpose with or without fee is hereby granted, |
-# provided that the above copyright notice and this permission notice |
-# appear in all copies. |
-# |
-# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES |
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR |
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
- |
-"""Talk to a DNS server.""" |
- |
-from __future__ import generators |
- |
-import errno |
-import select |
-import socket |
-import struct |
-import sys |
-import time |
- |
-import dns.exception |
-import dns.inet |
-import dns.name |
-import dns.message |
-import dns.rdataclass |
-import dns.rdatatype |
- |
-class UnexpectedSource(dns.exception.DNSException): |
- """Raised if a query response comes from an unexpected address or port.""" |
- pass |
- |
-class BadResponse(dns.exception.FormError): |
- """Raised if a query response does not respond to the question asked.""" |
- pass |
- |
-def _compute_expiration(timeout): |
- if timeout is None: |
- return None |
- else: |
- return time.time() + timeout |
- |
-def _wait_for(ir, iw, ix, expiration): |
- done = False |
- while not done: |
- if expiration is None: |
- timeout = None |
- else: |
- timeout = expiration - time.time() |
- if timeout <= 0.0: |
- raise dns.exception.Timeout |
- try: |
- if timeout is None: |
- (r, w, x) = select.select(ir, iw, ix) |
- else: |
- (r, w, x) = select.select(ir, iw, ix, timeout) |
- except select.error, e: |
- if e.args[0] != errno.EINTR: |
- raise e |
- done = True |
- if len(r) == 0 and len(w) == 0 and len(x) == 0: |
- raise dns.exception.Timeout |
- |
-def _wait_for_readable(s, expiration): |
- _wait_for([s], [], [s], expiration) |
- |
-def _wait_for_writable(s, expiration): |
- _wait_for([], [s], [s], expiration) |
- |
-def _addresses_equal(af, a1, a2): |
- # Convert the first value of the tuple, which is a textual format |
- # address into binary form, so that we are not confused by different |
- # textual representations of the same address |
- n1 = dns.inet.inet_pton(af, a1[0]) |
- n2 = dns.inet.inet_pton(af, a2[0]) |
- return n1 == n2 and a1[1:] == a2[1:] |
- |
-def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0, |
- ignore_unexpected=False, one_rr_per_rrset=False): |
- """Return the response obtained after sending a query via UDP. |
- |
- @param q: the query |
- @type q: dns.message.Message |
- @param where: where to send the message |
- @type where: string containing an IPv4 or IPv6 address |
- @param timeout: The number of seconds to wait before the query times out. |
- If None, the default, wait forever. |
- @type timeout: float |
- @param port: The port to which to send the message. The default is 53. |
- @type port: int |
- @param af: the address family to use. The default is None, which |
- causes the address family to use to be inferred from the form of of where. |
- If the inference attempt fails, AF_INET is used. |
- @type af: int |
- @rtype: dns.message.Message object |
- @param source: source address. The default is the IPv4 wildcard address. |
- @type source: string |
- @param source_port: The port from which to send the message. |
- The default is 0. |
- @type source_port: int |
- @param ignore_unexpected: If True, ignore responses from unexpected |
- sources. The default is False. |
- @type ignore_unexpected: bool |
- @param one_rr_per_rrset: Put each RR into its own RRset |
- @type one_rr_per_rrset: bool |
- """ |
- |
- wire = q.to_wire() |
- if af is None: |
- try: |
- af = dns.inet.af_for_address(where) |
- except: |
- af = dns.inet.AF_INET |
- if af == dns.inet.AF_INET: |
- destination = (where, port) |
- if source is not None: |
- source = (source, source_port) |
- elif af == dns.inet.AF_INET6: |
- destination = (where, port, 0, 0) |
- if source is not None: |
- source = (source, source_port, 0, 0) |
- s = socket.socket(af, socket.SOCK_DGRAM, 0) |
- try: |
- expiration = _compute_expiration(timeout) |
- s.setblocking(0) |
- if source is not None: |
- s.bind(source) |
- _wait_for_writable(s, expiration) |
- s.sendto(wire, destination) |
- while 1: |
- _wait_for_readable(s, expiration) |
- (wire, from_address) = s.recvfrom(65535) |
- if _addresses_equal(af, from_address, destination) or \ |
- (dns.inet.is_multicast(where) and \ |
- from_address[1:] == destination[1:]): |
- break |
- if not ignore_unexpected: |
- raise UnexpectedSource('got a response from ' |
- '%s instead of %s' % (from_address, |
- destination)) |
- finally: |
- s.close() |
- r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac, |
- one_rr_per_rrset=one_rr_per_rrset) |
- if not q.is_response(r): |
- raise BadResponse |
- return r |
- |
-def _net_read(sock, count, expiration): |
- """Read the specified number of bytes from sock. Keep trying until we |
- either get the desired amount, or we hit EOF. |
- A Timeout exception will be raised if the operation is not completed |
- by the expiration time. |
- """ |
- s = '' |
- while count > 0: |
- _wait_for_readable(sock, expiration) |
- n = sock.recv(count) |
- if n == '': |
- raise EOFError |
- count = count - len(n) |
- s = s + n |
- return s |
- |
-def _net_write(sock, data, expiration): |
- """Write the specified data to the socket. |
- A Timeout exception will be raised if the operation is not completed |
- by the expiration time. |
- """ |
- current = 0 |
- l = len(data) |
- while current < l: |
- _wait_for_writable(sock, expiration) |
- current += sock.send(data[current:]) |
- |
-def _connect(s, address): |
- try: |
- s.connect(address) |
- except socket.error: |
- (ty, v) = sys.exc_info()[:2] |
- if v[0] != errno.EINPROGRESS and \ |
- v[0] != errno.EWOULDBLOCK and \ |
- v[0] != errno.EALREADY: |
- raise v |
- |
-def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0, |
- one_rr_per_rrset=False): |
- """Return the response obtained after sending a query via TCP. |
- |
- @param q: the query |
- @type q: dns.message.Message object |
- @param where: where to send the message |
- @type where: string containing an IPv4 or IPv6 address |
- @param timeout: The number of seconds to wait before the query times out. |
- If None, the default, wait forever. |
- @type timeout: float |
- @param port: The port to which to send the message. The default is 53. |
- @type port: int |
- @param af: the address family to use. The default is None, which |
- causes the address family to use to be inferred from the form of of where. |
- If the inference attempt fails, AF_INET is used. |
- @type af: int |
- @rtype: dns.message.Message object |
- @param source: source address. The default is the IPv4 wildcard address. |
- @type source: string |
- @param source_port: The port from which to send the message. |
- The default is 0. |
- @type source_port: int |
- @param one_rr_per_rrset: Put each RR into its own RRset |
- @type one_rr_per_rrset: bool |
- """ |
- |
- wire = q.to_wire() |
- if af is None: |
- try: |
- af = dns.inet.af_for_address(where) |
- except: |
- af = dns.inet.AF_INET |
- if af == dns.inet.AF_INET: |
- destination = (where, port) |
- if source is not None: |
- source = (source, source_port) |
- elif af == dns.inet.AF_INET6: |
- destination = (where, port, 0, 0) |
- if source is not None: |
- source = (source, source_port, 0, 0) |
- s = socket.socket(af, socket.SOCK_STREAM, 0) |
- try: |
- expiration = _compute_expiration(timeout) |
- s.setblocking(0) |
- if source is not None: |
- s.bind(source) |
- _connect(s, destination) |
- |
- l = len(wire) |
- |
- # copying the wire into tcpmsg is inefficient, but lets us |
- # avoid writev() or doing a short write that would get pushed |
- # onto the net |
- tcpmsg = struct.pack("!H", l) + wire |
- _net_write(s, tcpmsg, expiration) |
- ldata = _net_read(s, 2, expiration) |
- (l,) = struct.unpack("!H", ldata) |
- wire = _net_read(s, l, expiration) |
- finally: |
- s.close() |
- r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac, |
- one_rr_per_rrset=one_rr_per_rrset) |
- if not q.is_response(r): |
- raise BadResponse |
- return r |
- |
-def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN, |
- timeout=None, port=53, keyring=None, keyname=None, relativize=True, |
- af=None, lifetime=None, source=None, source_port=0, serial=0, |
- use_udp=False, keyalgorithm=dns.tsig.default_algorithm): |
- """Return a generator for the responses to a zone transfer. |
- |
- @param where: where to send the message |
- @type where: string containing an IPv4 or IPv6 address |
- @param zone: The name of the zone to transfer |
- @type zone: dns.name.Name object or string |
- @param rdtype: The type of zone transfer. The default is |
- dns.rdatatype.AXFR. |
- @type rdtype: int or string |
- @param rdclass: The class of the zone transfer. The default is |
- dns.rdatatype.IN. |
- @type rdclass: int or string |
- @param timeout: The number of seconds to wait for each response message. |
- If None, the default, wait forever. |
- @type timeout: float |
- @param port: The port to which to send the message. The default is 53. |
- @type port: int |
- @param keyring: The TSIG keyring to use |
- @type keyring: dict |
- @param keyname: The name of the TSIG key to use |
- @type keyname: dns.name.Name object or string |
- @param relativize: If True, all names in the zone will be relativized to |
- the zone origin. It is essential that the relativize setting matches |
- the one specified to dns.zone.from_xfr(). |
- @type relativize: bool |
- @param af: the address family to use. The default is None, which |
- causes the address family to use to be inferred from the form of of where. |
- If the inference attempt fails, AF_INET is used. |
- @type af: int |
- @param lifetime: The total number of seconds to spend doing the transfer. |
- If None, the default, then there is no limit on the time the transfer may |
- take. |
- @type lifetime: float |
- @rtype: generator of dns.message.Message objects. |
- @param source: source address. The default is the IPv4 wildcard address. |
- @type source: string |
- @param source_port: The port from which to send the message. |
- The default is 0. |
- @type source_port: int |
- @param serial: The SOA serial number to use as the base for an IXFR diff |
- sequence (only meaningful if rdtype == dns.rdatatype.IXFR). |
- @type serial: int |
- @param use_udp: Use UDP (only meaningful for IXFR) |
- @type use_udp: bool |
- @param keyalgorithm: The TSIG algorithm to use; defaults to |
- dns.tsig.default_algorithm |
- @type keyalgorithm: string |
- """ |
- |
- if isinstance(zone, (str, unicode)): |
- zone = dns.name.from_text(zone) |
- if isinstance(rdtype, str): |
- rdtype = dns.rdatatype.from_text(rdtype) |
- q = dns.message.make_query(zone, rdtype, rdclass) |
- if rdtype == dns.rdatatype.IXFR: |
- rrset = dns.rrset.from_text(zone, 0, 'IN', 'SOA', |
- '. . %u 0 0 0 0' % serial) |
- q.authority.append(rrset) |
- if not keyring is None: |
- q.use_tsig(keyring, keyname, algorithm=keyalgorithm) |
- wire = q.to_wire() |
- if af is None: |
- try: |
- af = dns.inet.af_for_address(where) |
- except: |
- af = dns.inet.AF_INET |
- if af == dns.inet.AF_INET: |
- destination = (where, port) |
- if source is not None: |
- source = (source, source_port) |
- elif af == dns.inet.AF_INET6: |
- destination = (where, port, 0, 0) |
- if source is not None: |
- source = (source, source_port, 0, 0) |
- if use_udp: |
- if rdtype != dns.rdatatype.IXFR: |
- raise ValueError('cannot do a UDP AXFR') |
- s = socket.socket(af, socket.SOCK_DGRAM, 0) |
- else: |
- s = socket.socket(af, socket.SOCK_STREAM, 0) |
- s.setblocking(0) |
- if source is not None: |
- s.bind(source) |
- expiration = _compute_expiration(lifetime) |
- _connect(s, destination) |
- l = len(wire) |
- if use_udp: |
- _wait_for_writable(s, expiration) |
- s.send(wire) |
- else: |
- tcpmsg = struct.pack("!H", l) + wire |
- _net_write(s, tcpmsg, expiration) |
- done = False |
- soa_rrset = None |
- soa_count = 0 |
- if relativize: |
- origin = zone |
- oname = dns.name.empty |
- else: |
- origin = None |
- oname = zone |
- tsig_ctx = None |
- first = True |
- while not done: |
- mexpiration = _compute_expiration(timeout) |
- if mexpiration is None or mexpiration > expiration: |
- mexpiration = expiration |
- if use_udp: |
- _wait_for_readable(s, expiration) |
- (wire, from_address) = s.recvfrom(65535) |
- else: |
- ldata = _net_read(s, 2, mexpiration) |
- (l,) = struct.unpack("!H", ldata) |
- wire = _net_read(s, l, mexpiration) |
- r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac, |
- xfr=True, origin=origin, tsig_ctx=tsig_ctx, |
- multi=True, first=first, |
- one_rr_per_rrset=(rdtype==dns.rdatatype.IXFR)) |
- tsig_ctx = r.tsig_ctx |
- first = False |
- answer_index = 0 |
- delete_mode = False |
- expecting_SOA = False |
- if soa_rrset is None: |
- if not r.answer or r.answer[0].name != oname: |
- raise dns.exception.FormError |
- rrset = r.answer[0] |
- if rrset.rdtype != dns.rdatatype.SOA: |
- raise dns.exception.FormError("first RRset is not an SOA") |
- answer_index = 1 |
- soa_rrset = rrset.copy() |
- if rdtype == dns.rdatatype.IXFR: |
- if soa_rrset[0].serial == serial: |
- # |
- # We're already up-to-date. |
- # |
- done = True |
- else: |
- expecting_SOA = True |
- # |
- # Process SOAs in the answer section (other than the initial |
- # SOA in the first message). |
- # |
- for rrset in r.answer[answer_index:]: |
- if done: |
- raise dns.exception.FormError("answers after final SOA") |
- if rrset.rdtype == dns.rdatatype.SOA and rrset.name == oname: |
- if expecting_SOA: |
- if rrset[0].serial != serial: |
- raise dns.exception.FormError("IXFR base serial mismatch") |
- expecting_SOA = False |
- elif rdtype == dns.rdatatype.IXFR: |
- delete_mode = not delete_mode |
- if rrset == soa_rrset and not delete_mode: |
- done = True |
- elif expecting_SOA: |
- # |
- # We made an IXFR request and are expecting another |
- # SOA RR, but saw something else, so this must be an |
- # AXFR response. |
- # |
- rdtype = dns.rdatatype.AXFR |
- expecting_SOA = False |
- if done and q.keyring and not r.had_tsig: |
- raise dns.exception.FormError("missing TSIG") |
- yield r |
- s.close() |