diff --git a/bin/tests/convert-trs-to-junit.py b/bin/tests/convert-trs-to-junit.py index c94c0377ac..85b37dd629 100755 --- a/bin/tests/convert-trs-to-junit.py +++ b/bin/tests/convert-trs-to-junit.py @@ -76,9 +76,7 @@ def walk_trss(source_dir): # try to find dir/file path for a clickable link try: - t["rel_file_path"] = find_test_relative_path( - source_dir, test_name - ) + t["rel_file_path"] = find_test_relative_path(source_dir, test_name) except KeyError: pass # no existing path found diff --git a/bin/tests/system/addzone/tests_rndc_deadlock.py b/bin/tests/system/addzone/tests_rndc_deadlock.py index ec6ad1526b..bd21d62a90 100755 --- a/bin/tests/system/addzone/tests_rndc_deadlock.py +++ b/bin/tests/system/addzone/tests_rndc_deadlock.py @@ -16,61 +16,63 @@ import time def run_rndc(server, rndc_command): - ''' + """ Send the specified 'rndc_command' to 'server' with a timeout of 10 seconds - ''' - rndc = os.getenv('RNDC') - port = os.getenv('CONTROLPORT') + """ + rndc = os.getenv("RNDC") + port = os.getenv("CONTROLPORT") - cmdline = [rndc, '-c', '../common/rndc.conf', '-p', port, '-s', server] + cmdline = [rndc, "-c", "../common/rndc.conf", "-p", port, "-s", server] cmdline.extend(rndc_command) subprocess.check_output(cmdline, stderr=subprocess.STDOUT, timeout=10) def rndc_loop(test_state, domain): - ''' + """ Run "rndc addzone", "rndc modzone", and "rndc delzone" in a tight loop until the test is considered finished, ignoring errors - ''' + """ rndc_commands = [ - ['addzone', domain, - '{ type primary; file "example.db"; };'], - ['modzone', domain, - '{ type primary; file "example.db"; allow-transfer { any; }; };'], - ['delzone', domain], + ["addzone", domain, '{ type primary; file "example.db"; };'], + [ + "modzone", + domain, + '{ type primary; file "example.db"; allow-transfer { any; }; };', + ], + ["delzone", domain], ] - while not test_state['finished']: + while not test_state["finished"]: for command in rndc_commands: try: - run_rndc('10.53.0.3', command) + run_rndc("10.53.0.3", command) except subprocess.SubprocessError: pass def check_if_server_is_responsive(): - ''' + """ Check if server status can be successfully retrieved using "rndc status" - ''' + """ try: - run_rndc('10.53.0.3', ['status']) + run_rndc("10.53.0.3", ["status"]) return True except subprocess.SubprocessError: return False def test_rndc_deadlock(): - ''' + """ Test whether running "rndc addzone", "rndc modzone", and "rndc delzone" commands concurrently does not trigger a deadlock - ''' - test_state = {'finished': False} + """ + test_state = {"finished": False} # Create 4 worker threads running "rndc" commands in a loop. with concurrent.futures.ThreadPoolExecutor() as executor: for i in range(1, 5): - domain = 'example%d' % i + domain = "example%d" % i executor.submit(rndc_loop, test_state, domain) # Run "rndc status" 10 times, with 1-second pauses between attempts. @@ -84,7 +86,7 @@ def test_rndc_deadlock(): time.sleep(1) # Signal worker threads that the test is finished. - test_state['finished'] = True + test_state["finished"] = True # Check whether all "rndc status" commands succeeded. assert server_is_responsive diff --git a/bin/tests/system/chain/ans4/ans.py b/bin/tests/system/chain/ans4/ans.py index a5dad70edc..4d17705ef1 100755 --- a/bin/tests/system/chain/ans4/ans.py +++ b/bin/tests/system/chain/ans4/ans.py @@ -69,18 +69,22 @@ from dns.name import * ############################################################################ actions = [] rrs = [] + + def ctl_channel(msg): global actions, rrs msg = msg.splitlines().pop(0) - print ('received control message: %s' % msg) + print("received control message: %s" % msg) - msg = msg.split(b'|') + msg = msg.split(b"|") if len(msg) == 0: return - actions = [x.strip() for x in msg[0].split(b',')] - n = functools.reduce(lambda n, act: (n + (2 if act == b'dname' else 1)), [0] + actions) + actions = [x.strip() for x in msg[0].split(b",")] + n = functools.reduce( + lambda n, act: (n + (2 if act == b"dname" else 1)), [0] + actions + ) if len(msg) == 1: rrs = [] @@ -89,29 +93,30 @@ def ctl_channel(msg): rrs.append((i, b)) return - rlist = [x.strip() for x in msg[1].split(b',')] + rlist = [x.strip() for x in msg[1].split(b",")] rrs = [] for item in rlist: - if item[0] == b's'[0]: + if item[0] == b"s"[0]: i = int(item[1:].strip()) - 1 if i > n: - print ('invalid index %d' + (i + 1)) + print("invalid index %d" + (i + 1)) continue rrs.append((int(item[1:]) - 1, True)) else: i = int(item) - 1 if i > n: - print ('invalid index %d' % (i + 1)) + print("invalid index %d" % (i + 1)) continue rrs.append((i, False)) + ############################################################################ # Respond to a DNS query. ############################################################################ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() - labels = qname.lower().split('.') + labels = qname.lower().split(".") wantsigs = True if m.ednsflags & dns.flags.DO else False # get qtype @@ -124,27 +129,27 @@ def create_response(msg): # - sld is 'example' # - tld is 'com.' name = labels.pop(0) - domain = '.'.join(labels) + domain = ".".join(labels) sld = labels.pop(0) - tld = '.'.join(labels) + tld = ".".join(labels) - print ('query: ' + qname + '/' + typename) - print ('domain: ' + domain) + print("query: " + qname + "/" + typename) + print("domain: " + domain) # default answers, depending on QTYPE. # currently only A, AAAA, TXT and NS are supported. ttl = 86400 - additionalA = '10.53.0.4' - additionalAAAA = 'fd92:7065:b8e:ffff::4' - if typename == 'A': - final = '10.53.0.4' - elif typename == 'AAAA': - final = 'fd92:7065:b8e:ffff::4' - elif typename == 'TXT': - final = 'Some\ text\ here' - elif typename == 'NS': + additionalA = "10.53.0.4" + additionalAAAA = "fd92:7065:b8e:ffff::4" + if typename == "A": + final = "10.53.0.4" + elif typename == "AAAA": + final = "fd92:7065:b8e:ffff::4" + elif typename == "TXT": + final = "Some\ text\ here" + elif typename == "NS": domain = qname - final = ('ns1.%s' % domain) + final = "ns1.%s" % domain else: final = None @@ -153,9 +158,9 @@ def create_response(msg): delta = timedelta(30) t1 = t - delta t2 = t + delta - inception=t1.strftime('%Y%m%d000000') - expiry=t2.strftime('%Y%m%d000000') - sigdata='OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso=' + inception = t1.strftime("%Y%m%d000000") + expiry = t2.strftime("%Y%m%d000000") + sigdata = "OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso=" # construct answer set. answers = [] @@ -165,71 +170,97 @@ def create_response(msg): i = 0 for action in actions: - if name != 'test': + if name != "test": continue - if action == b'xname': - owner = curname + '.' + curdom - newname = 'cname%d' % i + if action == b"xname": + owner = curname + "." + curdom + newname = "cname%d" % i i += 1 - newdom = 'domain%d.%s' % (i, tld) + newdom = "domain%d.%s" % (i, tld) i += 1 - target = newname + '.' + newdom - print ('add external CNAME %s to %s' % (owner, target)) + target = newname + "." + newdom + print("add external CNAME %s to %s" % (owner, target)) answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) - rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add external RRISG(CNAME) %s to %s' % (owner, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add external RRISG(CNAME) %s to %s" % (owner, target)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) curname = newname curdom = newdom continue - if action == b'cname': - owner = curname + '.' + curdom - newname = 'cname%d' % i - target = newname + '.' + curdom + if action == b"cname": + owner = curname + "." + curdom + newname = "cname%d" % i + target = newname + "." + curdom i += 1 - print ('add CNAME %s to %s' % (owner, target)) + print("add CNAME %s to %s" % (owner, target)) answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) - rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add RRSIG(CNAME) %s to %s' % (owner, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add RRSIG(CNAME) %s to %s" % (owner, target)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) curname = newname continue - if action == b'dname': + if action == b"dname": owner = curdom - newdom = 'domain%d.%s' % (i, tld) + newdom = "domain%d.%s" % (i, tld) i += 1 - print ('add DNAME %s to %s' % (owner, newdom)) + print("add DNAME %s to %s" % (owner, newdom)) answers.append(dns.rrset.from_text(owner, ttl, IN, DNAME, newdom)) - rrsig = 'DNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add RRSIG(DNAME) %s to %s' % (owner, newdom)) + rrsig = "DNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add RRSIG(DNAME) %s to %s" % (owner, newdom)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) - owner = curname + '.' + curdom - target = curname + '.' + newdom - print ('add synthesized CNAME %s to %s' % (owner, target)) + owner = curname + "." + curdom + target = curname + "." + newdom + print("add synthesized CNAME %s to %s" % (owner, target)) answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) - rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add synthesized RRSIG(CNAME) %s to %s' % (owner, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add synthesized RRSIG(CNAME) %s to %s" % (owner, target)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) curdom = newdom continue # now add the final answer - owner = curname + '.' + curdom + owner = curname + "." + curdom answers.append(dns.rrset.from_text(owner, ttl, IN, rrtype, final)) - rrsig = '%s 5 3 %d %s %s 12345 %s %s' % \ - (typename, ttl, expiry, inception, domain, sigdata) + rrsig = "%s 5 3 %d %s %s 12345 %s %s" % ( + typename, + ttl, + expiry, + inception, + domain, + sigdata, + ) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) # prepare the response and convert to wire format r = dns.message.make_response(m) - if name != 'test': + if name != "test": r.answer.append(answers[-1]) if wantsigs: r.answer.append(sigs[-1]) @@ -242,24 +273,29 @@ def create_response(msg): else: r.answer.append(answers[i]) - if typename != 'NS': - r.authority.append(dns.rrset.from_text(domain, ttl, IN, "NS", - ("ns1.%s" % domain))) - r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400, - IN, A, additionalA)) - r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400, - IN, AAAA, additionalAAAA)) + if typename != "NS": + r.authority.append( + dns.rrset.from_text(domain, ttl, IN, "NS", ("ns1.%s" % domain)) + ) + r.additional.append( + dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, A, additionalA) + ) + r.additional.append( + dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, AAAA, additionalAAAA) + ) r.flags |= dns.flags.AA r.use_edns() return r.to_wire() + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -270,11 +306,15 @@ def sigterm(signum, frame): ip4 = "10.53.0.4" ip6 = "fd92:7065:b8e:ffff::4" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 -try: ctrlport=int(os.environ['EXTRAPORT1']) -except: ctrlport=5300 +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -296,18 +336,18 @@ ctrl_socket.listen(5) signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Control channel on %s port %d" % (ip4, ctrlport)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Control channel on %s port %d" % (ip4, ctrlport)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket, ctrl_socket] @@ -328,7 +368,7 @@ while running: if s == ctrl_socket: # Handle control channel input conn, addr = s.accept() - print ("Control channel connected") + print("Control channel connected") while True: msg = conn.recv(65535) if not msg: @@ -336,8 +376,7 @@ while running: ctl_channel(msg) conn.close() if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6)) + print("Query received on %s" % (ip4 if s == query4_socket else ip6)) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/checkds/tests-checkds.py b/bin/tests/system/checkds/tests-checkds.py index 68b197c73e..56777fb3af 100755 --- a/bin/tests/system/checkds/tests-checkds.py +++ b/bin/tests/system/checkds/tests-checkds.py @@ -19,7 +19,7 @@ import time import pytest -pytest.importorskip('dns', minversion='2.0.0') +pytest.importorskip("dns", minversion="2.0.0") import dns.exception import dns.message import dns.name @@ -55,18 +55,22 @@ def has_signed_apex_nsec(zone, response): def do_query(server, qname, qtype, tcp=False): - query = dns.message.make_query(qname, qtype, use_edns=True, - want_dnssec=True) + query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) try: if tcp: - response = dns.query.tcp(query, server.nameservers[0], timeout=3, - port=server.port) + response = dns.query.tcp( + query, server.nameservers[0], timeout=3, port=server.port + ) else: - response = dns.query.udp(query, server.nameservers[0], timeout=3, - port=server.port) + response = dns.query.udp( + query, server.nameservers[0], timeout=3, port=server.port + ) except dns.exception.Timeout: - print("error: query timeout for query {} {} to {}".format( - qname, qtype, server.nameservers[0])) + print( + "error: query timeout for query {} {} to {}".format( + qname, qtype, server.nameservers[0] + ) + ) return None return response @@ -77,10 +81,10 @@ def verify_zone(zone, transfer): assert verify is not None filename = "{}out".format(zone) - with open(filename, 'w', encoding='utf-8') as file: + with open(filename, "w", encoding="utf-8") as file: for rr in transfer.answer: file.write(rr.to_text()) - file.write('\n') + file.write("\n") # dnssec-verify command with default arguments. verify_cmd = [verify, "-z", "-o", zone, filename] @@ -108,30 +112,39 @@ def read_statefile(server, zone): if response.rcode() == dns.rcode.NOERROR: # fetch key id from response. for rr in response.answer: - if rr.match(dns.name.from_text(zone), dns.rdataclass.IN, - dns.rdatatype.DS, dns.rdatatype.NONE): + if rr.match( + dns.name.from_text(zone), + dns.rdataclass.IN, + dns.rdatatype.DS, + dns.rdatatype.NONE, + ): if count == 0: keyid = list(dict(rr.items).items())[0][0].key_tag count += 1 if count != 1: - print("error: expected a single DS in response for {} from {}," - "got {}".format(zone, addr, count)) + print( + "error: expected a single DS in response for {} from {}," + "got {}".format(zone, addr, count) + ) return {} else: - print("error: {} response for {} DNSKEY from {}".format( - dns.rcode.to_text(response.rcode()), zone, addr)) + print( + "error: {} response for {} DNSKEY from {}".format( + dns.rcode.to_text(response.rcode()), zone, addr + ) + ) return {} filename = "ns9/K{}+013+{:05d}.state".format(zone, keyid) print("read state file {}".format(filename)) try: - with open(filename, 'r', encoding='utf-8') as file: + with open(filename, "r", encoding="utf-8") as file: for line in file: - if line.startswith(';'): + if line.startswith(";"): continue - key, val = line.strip().split(':', 1) + key, val = line.strip().split(":", 1) state[key.strip()] = val.strip() except FileNotFoundError: @@ -147,14 +160,17 @@ def zone_check(server, zone): # wait until zone is fully signed. signed = False for _ in range(10): - response = do_query(server, zone, 'NSEC') + response = do_query(server, zone, "NSEC") if not isinstance(response, dns.message.Message): print("error: no response for {} NSEC from {}".format(zone, addr)) elif response.rcode() == dns.rcode.NOERROR: signed = has_signed_apex_nsec(zone, response) else: - print("error: {} response for {} NSEC from {}".format( - dns.rcode.to_text(response.rcode()), zone, addr)) + print( + "error: {} response for {} NSEC from {}".format( + dns.rcode.to_text(response.rcode()), zone, addr + ) + ) if signed: break @@ -165,14 +181,17 @@ def zone_check(server, zone): # check if zone if DNSSEC valid. verified = False - transfer = do_query(server, zone, 'AXFR', tcp=True) + transfer = do_query(server, zone, "AXFR", tcp=True) if not isinstance(transfer, dns.message.Message): print("error: no response for {} AXFR from {}".format(zone, addr)) elif transfer.rcode() == dns.rcode.NOERROR: verified = verify_zone(zone, transfer) else: - print("error: {} response for {} AXFR from {}".format( - dns.rcode.to_text(transfer.rcode()), zone, addr)) + print( + "error: {} response for {} AXFR from {}".format( + dns.rcode.to_text(transfer.rcode()), zone, addr + ) + ) assert verified @@ -182,7 +201,7 @@ def keystate_check(server, zone, key): deny = False search = key - if key.startswith('!'): + if key.startswith("!"): deny = True search = key[1:] @@ -213,7 +232,7 @@ def wait_for_log(filename, log): print("read log file {}".format(filename)) try: - with open(filename, 'r', encoding='utf-8') as file: + with open(filename, "r", encoding="utf-8") as file: s = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) if s.find(bytes(log, "ascii")) != -1: found = True @@ -241,67 +260,89 @@ def test_checkds_dspublished(named_port): # DS correctly published in parent. zone_check(server, "dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") + wait_for_log( + "ns9/named.run", + "zone dspublished.checkds/IN (signed): checkds: " "DS response from 10.53.0.2", + ) keystate_check(parent, "dspublished.checkds.", "DSPublish") # DS correctly published in parent (reference to parental-agent). zone_check(server, "reference.checkds.") - wait_for_log("ns9/named.run", - "zone reference.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") + wait_for_log( + "ns9/named.run", + "zone reference.checkds/IN (signed): checkds: " "DS response from 10.53.0.2", + ) keystate_check(parent, "reference.checkds.", "DSPublish") # DS not published in parent. zone_check(server, "missing-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone missing-dspublished.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") + wait_for_log( + "ns9/named.run", + "zone missing-dspublished.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) keystate_check(parent, "missing-dspublished.checkds.", "!DSPublish") # Badly configured parent. zone_check(server, "bad-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone bad-dspublished.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad-dspublished.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad-dspublished.checkds.", "!DSPublish") # TBD: DS published in parent, but bogus signature. # DS correctly published in all parents. zone_check(server, "multiple-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone multiple-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone multiple-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.4") + wait_for_log( + "ns9/named.run", + "zone multiple-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone multiple-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) keystate_check(parent, "multiple-dspublished.checkds.", "DSPublish") # DS published in only one of multiple parents. zone_check(server, "incomplete-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone incomplete-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone incomplete-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.4") - wait_for_log("ns9/named.run", - "zone incomplete-dspublished.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) keystate_check(parent, "incomplete-dspublished.checkds.", "!DSPublish") # One of the parents is badly configured. - wait_for_log("ns9/named.run", - "zone bad2-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone bad2-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.4") - wait_for_log("ns9/named.run", - "zone bad2-dspublished.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad2-dspublished.checkds.", "!DSPublish") # TBD: DS published in all parents, but one has bogus signature. @@ -323,60 +364,82 @@ def test_checkds_dswithdrawn(named_port): # DS correctly published in single parent. zone_check(server, "dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") + wait_for_log( + "ns9/named.run", + "zone dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) keystate_check(parent, "dswithdrawn.checkds.", "DSRemoved") # DS not withdrawn from parent. zone_check(server, "missing-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone missing-dswithdrawn.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") + wait_for_log( + "ns9/named.run", + "zone missing-dswithdrawn.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) keystate_check(parent, "missing-dswithdrawn.checkds.", "!DSRemoved") # Badly configured parent. zone_check(server, "bad-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone bad-dswithdrawn.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad-dswithdrawn.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad-dswithdrawn.checkds.", "!DSRemoved") # TBD: DS published in parent, but bogus signature. # DS correctly withdrawn from all parents. zone_check(server, "multiple-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") - wait_for_log("ns9/named.run", - "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.7") + wait_for_log( + "ns9/named.run", + "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) keystate_check(parent, "multiple-dswithdrawn.checkds.", "DSRemoved") # DS withdrawn from only one of multiple parents. zone_check(server, "incomplete-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") - wait_for_log("ns9/named.run", - "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.7") + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) keystate_check(parent, "incomplete-dswithdrawn.checkds.", "!DSRemoved") # One of the parents is badly configured. - wait_for_log("ns9/named.run", - "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") - wait_for_log("ns9/named.run", - "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.7") - wait_for_log("ns9/named.run", - "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad2-dswithdrawn.checkds.", "!DSRemoved") # TBD: DS withdrawn from all parents, but one has bogus signature. diff --git a/bin/tests/system/conftest.py b/bin/tests/system/conftest.py index 2fd05add7d..8abf963926 100644 --- a/bin/tests/system/conftest.py +++ b/bin/tests/system/conftest.py @@ -16,16 +16,16 @@ import os import pytest -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def named_port(): - return int(os.environ.get('PORT', default=5300)) + return int(os.environ.get("PORT", default=5300)) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def named_tlsport(): - return int(os.environ.get('TLSPORT', default=8853)) + return int(os.environ.get("TLSPORT", default=8853)) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def control_port(): - return int(os.environ.get('CONTROLPORT', default=9953)) + return int(os.environ.get("CONTROLPORT", default=9953)) diff --git a/bin/tests/system/cookie/ans9/ans.py b/bin/tests/system/cookie/ans9/ans.py index abc6d36ee2..550909466a 100644 --- a/bin/tests/system/cookie/ans9/ans.py +++ b/bin/tests/system/cookie/ans9/ans.py @@ -40,20 +40,17 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + # DNS 2.0 keyring specifies the algorithm try: - keyring = dns.tsigkeyring.from_text({ "foo" : { - "hmac-sha256", - "aaaaaaaaaaaa" - } , - "fake" : { - "hmac-sha256", - "aaaaaaaaaaaa" - } - }) + keyring = dns.tsigkeyring.from_text( + { + "foo": {"hmac-sha256", "aaaaaaaaaaaa"}, + "fake": {"hmac-sha256", "aaaaaaaaaaaa"}, + } + ) except: - keyring = dns.tsigkeyring.from_text({ "foo" : "aaaaaaaaaaaa", - "fake" : "aaaaaaaaaaaa" }) + keyring = dns.tsigkeyring.from_text({"foo": "aaaaaaaaaaaa", "fake": "aaaaaaaaaaaa"}) dopass2 = False @@ -81,7 +78,7 @@ def create_response(msg, tcp, first, ns10): m = dns.message.from_wire(msg, keyring=keyring) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") rrtype = m.question[0].rdtype typename = dns.rdatatype.to_text(rrtype) @@ -113,27 +110,31 @@ def create_response(msg, tcp, first, ns10): # Add a server cookie to the response if labels[0] != "nocookie": for o in m.options: - if o.otype == 10: # Use 10 instead of COOKIE - if first and labels[0] == "withtsig" and not tcp: - r.use_tsig(keyring = keyring, - keyname = dns.name.from_text("fake"), - algorithm = HMAC_SHA256) - elif labels[0] != "tcponly" or tcp: - cookie = o - if len(o.data) == 8: - cookie.data = o.data + o.data - else: - cookie.data = o.data - r.use_edns(options=[cookie]) + if o.otype == 10: # Use 10 instead of COOKIE + if first and labels[0] == "withtsig" and not tcp: + r.use_tsig( + keyring=keyring, + keyname=dns.name.from_text("fake"), + algorithm=HMAC_SHA256, + ) + elif labels[0] != "tcponly" or tcp: + cookie = o + if len(o.data) == 8: + cookie.data = o.data + o.data + else: + cookie.data = o.data + r.use_edns(options=[cookie]) r.flags |= dns.flags.AA return r + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -146,8 +147,10 @@ ip4_addr2 = "10.53.0.10" ip6_addr1 = "fd92:7065:b8e:ffff::9" ip6_addr2 = "fd92:7065:b8e:ffff::10" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_udp1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_udp1.bind((ip4_addr1, port)) @@ -195,24 +198,32 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Using DNS version %s" % dns.version.version) -print ("Listening on %s port %d" % (ip4_addr1, port)) -print ("Listening on %s port %d" % (ip4_addr2, port)) +print("Using DNS version %s" % dns.version.version) +print("Listening on %s port %d" % (ip4_addr1, port)) +print("Listening on %s port %d" % (ip4_addr2, port)) if havev6: - print ("Listening on %s port %d" % (ip6_addr1, port)) - print ("Listening on %s port %d" % (ip6_addr2, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6_addr1, port)) + print("Listening on %s port %d" % (ip6_addr2, port)) +print("Ctrl-c to quit") if havev6: - input = [query4_udp1, query6_udp1, query4_tcp1, query6_tcp1, - query4_udp2, query6_udp2, query4_tcp2, query6_tcp2] + input = [ + query4_udp1, + query6_udp1, + query4_tcp1, + query6_tcp1, + query4_udp2, + query6_udp2, + query4_tcp2, + query6_tcp2, + ] else: input = [query4_udp1, query4_tcp1, query4_udp2, query4_tcp2] @@ -228,14 +239,19 @@ while running: for s in inputready: ns10 = False - if s == query4_udp1 or s == query6_udp1 or \ - s == query4_udp2 or s == query6_udp2: + if s == query4_udp1 or s == query6_udp1 or s == query4_udp2 or s == query6_udp2: if s == query4_udp1 or s == query6_udp1: - print ("UDP Query received on %s" % - (ip4_addr1 if s == query4_udp1 else ip6_addr1), end=" ") + print( + "UDP Query received on %s" + % (ip4_addr1 if s == query4_udp1 else ip6_addr1), + end=" ", + ) if s == query4_udp2 or s == query6_udp2: - print ("UDP Query received on %s" % - (ip4_addr2 if s == query4_udp2 else ip6_addr2), end=" ") + print( + "UDP Query received on %s" + % (ip4_addr2 if s == query4_udp2 else ip6_addr2), + end=" ", + ) ns10 = True # Handle incoming queries msg = s.recvfrom(65535) @@ -244,31 +260,36 @@ while running: print(dns.rcode.to_text(rsp.rcode())) s.sendto(rsp.to_wire(), msg[1]) if dopass2: - print ("Sending second UDP response without TSIG", end=" ") + print("Sending second UDP response without TSIG", end=" ") rsp = create_response(msg[0], False, False, ns10) s.sendto(rsp.to_wire(), msg[1]) print(dns.rcode.to_text(rsp.rcode())) - if s == query4_tcp1 or s == query6_tcp1 or \ - s == query4_tcp2 or s == query6_tcp2: + if s == query4_tcp1 or s == query6_tcp1 or s == query4_tcp2 or s == query6_tcp2: try: (cs, _) = s.accept() if s == query4_tcp1 or s == query6_tcp1: - print ("TCP Query received on %s" % - (ip4_addr1 if s == query4_tcp1 else ip6_addr1), end=" ") + print( + "TCP Query received on %s" + % (ip4_addr1 if s == query4_tcp1 else ip6_addr1), + end=" ", + ) if s == query4_tcp2 or s == query6_tcp2: - print ("TCP Query received on %s" % - (ip4_addr2 if s == query4_tcp2 else ip6_addr2), end=" ") + print( + "TCP Query received on %s" + % (ip4_addr2 if s == query4_tcp2 else ip6_addr2), + end=" ", + ) ns10 = True # get TCP message length buf = cs.recv(2) - length = struct.unpack('>H', buf[:2])[0] + length = struct.unpack(">H", buf[:2])[0] # grep DNS message msg = cs.recv(length) rsp = create_response(msg, True, True, ns10) print(dns.rcode.to_text(rsp.rcode())) wire = rsp.to_wire() - cs.send(struct.pack('>H', len(wire))) + cs.send(struct.pack(">H", len(wire))) cs.send(wire) cs.close() except s.timeout: diff --git a/bin/tests/system/digdelv/ans8/ans.py b/bin/tests/system/digdelv/ans8/ans.py index 333b2f6044..3e18edc1cc 100644 --- a/bin/tests/system/digdelv/ans8/ans.py +++ b/bin/tests/system/digdelv/ans8/ans.py @@ -21,14 +21,15 @@ import dns, dns.message from dns.rcode import * modes = [ - b"silent", # Do not respond - b"close", # UDP: same as silent; TCP: also close the connection - b"servfail", # Always respond with SERVFAIL - b"unstable", # Constantly switch between "silent" and "servfail" + b"silent", # Do not respond + b"close", # UDP: same as silent; TCP: also close the connection + b"servfail", # Always respond with SERVFAIL + b"unstable", # Constantly switch between "silent" and "servfail" ] mode = modes[0] n = 0 + def ctrl_channel(msg): global modes, mode, n @@ -40,6 +41,7 @@ def ctrl_channel(msg): n = 0 print("New mode: %s" % str(mode)) + def create_servfail(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() @@ -54,19 +56,25 @@ def create_servfail(msg): r.set_rcode(SERVFAIL) return r + def sigterm(signum, frame): print("Shutting down now...") os.remove("ans.pid") running = False sys.exit(0) + ip4 = "10.53.0.8" -try: port=int(os.environ["PORT"]) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 -try: ctrlport=int(os.environ['EXTRAPORT1']) -except: ctrlport=5300 +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 query4_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_udp.bind((ip4, port)) @@ -85,14 +93,14 @@ signal.signal(signal.SIGTERM, sigterm) f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) -print ("Listening on %s port %d" % (ip4, ctrlport)) -print ("Ctrl-c to quit") +print("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, ctrlport)) +print("Ctrl-c to quit") input = [query4_udp, query4_tcp, ctrl4_tcp] @@ -113,7 +121,11 @@ while running: n = n + 1 print("UDP query received on %s" % ip4, end=" ") msg = s.recvfrom(65535) - if mode == b"silent" or mode == b"close" or (mode == b"unstable" and n % 2 == 1): + if ( + mode == b"silent" + or mode == b"close" + or (mode == b"unstable" and n % 2 == 1) + ): # Do not respond. print("NO RESPONSE (%s)" % str(mode)) continue @@ -125,7 +137,7 @@ while running: else: print("NO RESPONSE (can not create a response)") else: - raise(Exception("unsupported mode: %s" % mode)) + raise (Exception("unsupported mode: %s" % mode)) elif s == query4_tcp: n = n + 1 print("TCP query received on %s" % ip4, end=" ") @@ -151,7 +163,7 @@ while running: print("NO RESPONSE (can not read the message length)") conn.close() continue - length = struct.unpack('>H', msg[:2])[0] + length = struct.unpack(">H", msg[:2])[0] msg = conn.recv(length) if len(msg) != length: print("NO RESPONSE (can not read the message)") @@ -161,12 +173,12 @@ while running: if rsp: print(dns.rcode.to_text(rsp.rcode())) wire = rsp.to_wire() - conn.send(struct.pack('>H', len(wire))) + conn.send(struct.pack(">H", len(wire))) conn.send(wire) else: print("NO RESPONSE (can not create a response)") else: - raise(Exception("unsupported mode: %s" % mode)) + raise (Exception("unsupported mode: %s" % mode)) except socket.error as e: print("NO RESPONSE (error: %s)" % str(e)) if conn: diff --git a/bin/tests/system/dispatch/ans3/ans.py b/bin/tests/system/dispatch/ans3/ans.py index b57d73c005..4e4ebacb0b 100644 --- a/bin/tests/system/dispatch/ans3/ans.py +++ b/bin/tests/system/dispatch/ans3/ans.py @@ -32,7 +32,7 @@ def port(): def udp_listen(port): udp = socket.socket(type=socket.SOCK_DGRAM) - udp.bind(('10.53.0.3', port)) + udp.bind(("10.53.0.3", port)) return udp @@ -40,7 +40,7 @@ def udp_listen(port): def tcp_listen(port): tcp = socket.socket(type=socket.SOCK_STREAM) tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - tcp.bind(('10.53.0.3', port)) + tcp.bind(("10.53.0.3", port)) tcp.listen(100) return tcp @@ -62,12 +62,12 @@ def tcp_once(tcp): def sigterm(signum, frame): - os.remove('ans.pid') + os.remove("ans.pid") sys.exit(0) def write_pid(): - with open('ans.pid', 'w') as f: + with open("ans.pid", "w") as f: pid = os.getpid() f.write("{}".format(pid)) diff --git a/bin/tests/system/dispatch/tests-connreset.py b/bin/tests/system/dispatch/tests-connreset.py index 61758ffe6d..f74bfd719a 100644 --- a/bin/tests/system/dispatch/tests-connreset.py +++ b/bin/tests/system/dispatch/tests-connreset.py @@ -20,7 +20,8 @@ import dns.rcode def test_connreset(named_port): - msg = dns.message.make_query("sub.example.", "A", want_dnssec=True, - use_edns=0, payload=1232) + msg = dns.message.make_query( + "sub.example.", "A", want_dnssec=True, use_edns=0, payload=1232 + ) ans = dns.query.udp(msg, "10.53.0.2", timeout=10, port=named_port) assert ans.rcode() == dns.rcode.SERVFAIL diff --git a/bin/tests/system/dnssec/ans10/ans.py b/bin/tests/system/dnssec/ans10/ans.py index c738978503..c2f60e68e5 100644 --- a/bin/tests/system/dnssec/ans10/ans.py +++ b/bin/tests/system/dnssec/ans10/ans.py @@ -30,6 +30,7 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + ############################################################################ # Respond to a DNS query. # SOA gets a unsigned response. @@ -54,10 +55,16 @@ def create_response(msg): now = datetime.today() expire = now + timedelta(days=30) inception = now - timedelta(days=1) - rrsig = "A 13 2 60 " + expire.strftime("%Y%m%d%H%M%S") + " " + \ - inception.strftime("%Y%m%d%H%M%S") + " 12345 " + qname + \ - " gB+eISXAhSPZU2i/II0W9ZUhC2SCIrb94mlNvP5092WAeXxqN/vG43/1nmDl" + \ - "y2Qs7y5VCjSMOGn85bnaMoAc7w==" + rrsig = ( + "A 13 2 60 " + + expire.strftime("%Y%m%d%H%M%S") + + " " + + inception.strftime("%Y%m%d%H%M%S") + + " 12345 " + + qname + + " gB+eISXAhSPZU2i/II0W9ZUhC2SCIrb94mlNvP5092WAeXxqN/vG43/1nmDl" + + "y2Qs7y5VCjSMOGn85bnaMoAc7w==" + ) r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) r.answer.append(dns.rrset.from_text(qname, 1, IN, RRSIG, rrsig)) elif rrtype == NS: @@ -69,12 +76,14 @@ def create_response(msg): r.flags |= dns.flags.AA return r + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -85,8 +94,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.10" ip6 = "fd92:7065:b8e:ffff::10" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -102,17 +113,17 @@ except: havev6 = False signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -131,8 +142,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py index 43cd227996..ab7e3c9ada 100644 --- a/bin/tests/system/dnstap/ydump.py +++ b/bin/tests/system/dnstap/ydump.py @@ -22,7 +22,7 @@ import pprint DNSTAP_READ = sys.argv[1] DATAFILE = sys.argv[2] -ARGS = [DNSTAP_READ, '-y', DATAFILE] +ARGS = [DNSTAP_READ, "-y", DATAFILE] with subprocess.Popen(ARGS, stdout=subprocess.PIPE) as f: for y in yaml.load_all(f.stdout, Loader=yaml.SafeLoader): diff --git a/bin/tests/system/doth/conftest.py b/bin/tests/system/doth/conftest.py index 01c2071468..94392ccc0d 100644 --- a/bin/tests/system/doth/conftest.py +++ b/bin/tests/system/doth/conftest.py @@ -20,15 +20,18 @@ import pytest @pytest.fixture def gnutls_cli_executable(): # Ensure gnutls-cli is available. - executable = shutil.which('gnutls-cli') + executable = shutil.which("gnutls-cli") if not executable: - pytest.skip('gnutls-cli not found in PATH') + pytest.skip("gnutls-cli not found in PATH") # Ensure gnutls-cli supports the --logfile command-line option. - output = subprocess.run([executable, '--logfile=/dev/null'], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - check=False).stdout - if b'illegal option' in output: - pytest.skip('gnutls-cli does not support the --logfile option') + output = subprocess.run( + [executable, "--logfile=/dev/null"], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=False, + ).stdout + if b"illegal option" in output: + pytest.skip("gnutls-cli does not support the --logfile option") return executable diff --git a/bin/tests/system/doth/get_openssl_version.py b/bin/tests/system/doth/get_openssl_version.py index 0aea9afa36..f1d6f4bf00 100755 --- a/bin/tests/system/doth/get_openssl_version.py +++ b/bin/tests/system/doth/get_openssl_version.py @@ -12,5 +12,6 @@ # information regarding copyright ownership. import ssl + version = ssl.OPENSSL_VERSION_INFO print(version[0], version[1], version[2]) diff --git a/bin/tests/system/doth/stress_http_quota.py b/bin/tests/system/doth/stress_http_quota.py index c3586b2485..12e29c858e 100755 --- a/bin/tests/system/doth/stress_http_quota.py +++ b/bin/tests/system/doth/stress_http_quota.py @@ -36,7 +36,7 @@ if rlimit_nofile[0] < 1024: # Introduce some random delay def jitter(): - time.sleep((500 + random.randint(0, 250))/1000000.0) + time.sleep((500 + random.randint(0, 250)) / 1000000.0) # A set of simple procedures to get the test's configuration options @@ -77,8 +77,9 @@ class TCPConnector: tries = CONNECT_TRIES while tries > 0: try: - sock = socket.create_connection(address=(self.host, self.port), - timeout=None) + sock = socket.create_connection( + address=(self.host, self.port), timeout=None + ) self.connections.append(sock) break except ConnectionResetError: @@ -137,9 +138,10 @@ class SubDIG: def run(self): # pylint: disable=consider-using-with - with open(os.devnull, 'w', encoding='utf-8') as devnull: - self.sub_process = subprocess.Popen(self.get_command(), shell=True, - stdout=devnull) + with open(os.devnull, "w", encoding="utf-8") as devnull: + self.sub_process = subprocess.Popen( + self.get_command(), shell=True, stdout=devnull + ) def wait(self, timeout=None): res = None @@ -158,13 +160,11 @@ class SubDIG: # A simple wrapper class which allows running multiple dig instances # and examining their statuses in one logical operation. class MultiDIG: - def __init__(self, numdigs, http_secure=None, - extra_args=None): + def __init__(self, numdigs, http_secure=None, extra_args=None): assert int(numdigs) > 0 digs = [] for _ in range(1, int(numdigs) + 1): - digs.append(SubDIG(http_secure=http_secure, - extra_args=extra_args)) + digs.append(SubDIG(http_secure=http_secure, extra_args=extra_args)) self.digs = digs assert len(self.digs) == int(numdigs) @@ -179,12 +179,11 @@ class MultiDIG: # status. Returns true or false. def wait_for_result(self, result): return reduce( - lambda a, b: ((a == result or a is True) and b == result), - self.wait()) + lambda a, b: ((a == result or a is True) and b == result), self.wait() + ) def alive(self): - return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), - self.digs)) + return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), self.digs)) def completed(self): total = 0 @@ -203,8 +202,7 @@ def run_test(http_secure=True): assert subdig.wait() == 0, "DIG was expected to succeed" # Let's create a lot of TCP connections to the server stress the # HTTP quota - connector = TCPConnector(get_http_host(), - get_http_port(http_secure=http_secure)) + connector = TCPConnector(get_http_host(), get_http_port(http_secure=http_secure)) # Let's make queries until the quota kicks in subdig = SubDIG(http_secure=http_secure, extra_args=query_args) subdig.run() @@ -218,25 +216,28 @@ def run_test(http_secure=True): # At this point quota has kicked in. Additionally, let's create a # bunch of dig processes all trying to make a query against the # server with exceeded quota - multidig = MultiDIG(MULTIDIG_INSTANCES, http_secure=http_secure, - extra_args=query_args) + multidig = MultiDIG( + MULTIDIG_INSTANCES, http_secure=http_secure, extra_args=query_args + ) multidig.run() # Wait for the dig instance to complete. Not a single instance has # a chance to complete successfully because of the exceeded quota - assert subdig.wait(timeout=5) is None,\ - "The single DIG instance has stopped prematurely" + assert ( + subdig.wait(timeout=5) is None + ), "The single DIG instance has stopped prematurely" assert subdig.alive(), "The single DIG instance is expected to be alive" - assert multidig.alive(), \ - ("The DIG instances from the set are all expected to " - "be alive, but {} of them have completed")\ - .format(multidig.completed()) + assert multidig.alive(), ( + "The DIG instances from the set are all expected to " + "be alive, but {} of them have completed" + ).format(multidig.completed()) # Let's close opened connections (in random order) to let all dig # processes to complete connector.disconnect_all() # Wait for all processes to complete successfully assert subdig.wait() == 0, "Single DIG instance failed" - assert multidig.wait_for_result(0) is True,\ - "One or more of DIG instances returned unexpected results" + assert ( + multidig.wait_for_result(0) is True + ), "One or more of DIG instances returned unexpected results" def main(): diff --git a/bin/tests/system/doth/tests_gnutls.py b/bin/tests/system/doth/tests_gnutls.py index ea86a961b2..5ddb708fd2 100644 --- a/bin/tests/system/doth/tests_gnutls.py +++ b/bin/tests/system/doth/tests_gnutls.py @@ -18,7 +18,7 @@ import time import pytest -pytest.importorskip('dns') +pytest.importorskip("dns") import dns.exception import dns.message import dns.name @@ -28,18 +28,28 @@ import dns.rdatatype def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): # Prepare the example/SOA query which will be sent over TLS. - query = dns.message.make_query('example.', dns.rdatatype.SOA) + query = dns.message.make_query("example.", dns.rdatatype.SOA) query_wire = query.to_wire() - query_with_length = struct.pack('>H', len(query_wire)) + query_wire + query_with_length = struct.pack(">H", len(query_wire)) + query_wire # Run gnutls-cli. - gnutls_cli_args = [gnutls_cli_executable, '--no-ca-verification', '-V', - '--no-ocsp', '--alpn=dot', '--logfile=gnutls-cli.log', - '--port=%d' % named_tlsport, '10.53.0.1'] - with open('gnutls-cli.err', 'wb') as gnutls_cli_stderr, \ - subprocess.Popen(gnutls_cli_args, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=gnutls_cli_stderr, - bufsize=0) as gnutls_cli: + gnutls_cli_args = [ + gnutls_cli_executable, + "--no-ca-verification", + "-V", + "--no-ocsp", + "--alpn=dot", + "--logfile=gnutls-cli.log", + "--port=%d" % named_tlsport, + "10.53.0.1", + ] + with open("gnutls-cli.err", "wb") as gnutls_cli_stderr, subprocess.Popen( + gnutls_cli_args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=gnutls_cli_stderr, + bufsize=0, + ) as gnutls_cli: # Send the example/SOA query to the standard input of gnutls-cli. Do # not close standard input yet because that causes gnutls-cli to close # the TLS connection immediately, preventing the response from being @@ -56,8 +66,8 @@ def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): selector = selectors.DefaultSelector() selector.register(gnutls_cli.stdout, selectors.EVENT_READ) deadline = time.time() + 10 - gnutls_cli_output = b'' - response = b'' + gnutls_cli_output = b"" + response = b"" while not response and not gnutls_cli.poll(): if not selector.select(timeout=deadline - time.time()): break @@ -80,16 +90,19 @@ def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): gnutls_cli.kill() # Store the response received for diagnostic purposes. - with open('gnutls-cli.out.bin', 'wb') as response_bin: + with open("gnutls-cli.out.bin", "wb") as response_bin: response_bin.write(gnutls_cli_output) if response: - with open('gnutls-cli.out.txt', 'w', encoding='utf-8') as response_txt: + with open("gnutls-cli.out.txt", "w", encoding="utf-8") as response_txt: response_txt.write(response.to_text()) # Check whether a response was received and whether it is sane. assert response assert query.id == response.id assert len(response.answer) == 1 - assert response.answer[0].match(dns.name.from_text('example.'), - dns.rdataclass.IN, dns.rdatatype.SOA, - dns.rdatatype.NONE) + assert response.answer[0].match( + dns.name.from_text("example."), + dns.rdataclass.IN, + dns.rdatatype.SOA, + dns.rdatatype.NONE, + ) diff --git a/bin/tests/system/forward/ans11/ans.py b/bin/tests/system/forward/ans11/ans.py index ae636d46be..95993813f8 100644 --- a/bin/tests/system/forward/ans11/ans.py +++ b/bin/tests/system/forward/ans11/ans.py @@ -31,11 +31,13 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + # Create a UDP listener -def udp_listen(ip, port, is_ipv6 = False): +def udp_listen(ip, port, is_ipv6=False): try: - udp = socket.socket(socket.AF_INET6 if is_ipv6 else socket.AF_INET, - socket.SOCK_DGRAM) + udp = socket.socket( + socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_DGRAM + ) try: udp.bind((ip, port)) except: @@ -49,11 +51,13 @@ def udp_listen(ip, port, is_ipv6 = False): return udp + # Create a TCP listener -def tcp_listen(ip, port, is_ipv6 = False): +def tcp_listen(ip, port, is_ipv6=False): try: - tcp = socket.socket(socket.AF_INET6 if is_ipv6 else socket.AF_INET, - socket.SOCK_STREAM) + tcp = socket.socket( + socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_STREAM + ) try: tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcp.bind((ip, port)) @@ -69,10 +73,13 @@ def tcp_listen(ip, port, is_ipv6 = False): return tcp + ############################################################################ # Control channel - send "1" or "0" to enable or disable the "silent" mode. ############################################################################ silent = False + + def ctrl_channel(msg): global silent @@ -83,14 +90,15 @@ def ctrl_channel(msg): return if silent: - if msg == b'0': + if msg == b"0": silent = False print("Silent mode was disabled") else: - if msg == b'1': + if msg == b"1": silent = True print("Silent mode was enabled") + ############################################################################ # Respond to a DNS query. ############################################################################ @@ -107,8 +115,8 @@ def create_response(msg): r = dns.message.make_response(m) r.set_rcode(NOERROR) if rrtype == A: - tld=qname.split('.')[-2] + '.' - ns="local." + tld + tld = qname.split(".")[-2] + "." + ns = "local." + tld r.answer.append(dns.rrset.from_text(qname, 300, IN, A, "10.53.0.11")) r.answer.append(dns.rrset.from_text(tld, 300, IN, NS, "local." + tld)) r.additional.append(dns.rrset.from_text(ns, 300, IN, A, "10.53.0.11")) @@ -121,12 +129,14 @@ def create_response(msg): r.flags |= dns.flags.AA return r + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -137,11 +147,15 @@ def sigterm(signum, frame): ip4 = "10.53.0.11" ip6 = "fd92:7065:b8e:ffff::11" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 -try: ctrlport=int(os.environ['EXTRAPORT1']) -except: ctrlport=5300 +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 ctrl4_tcp = tcp_listen(ip4, ctrlport) query4_udp = udp_listen(ip4, port) @@ -153,19 +167,19 @@ havev6 = query6_udp is not None and query6_tcp is not None signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, ctrlport)) -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, ctrlport)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) + print("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") +print("Ctrl-c to quit") if havev6: input = [ctrl4_tcp, query4_udp, query6_udp, query4_tcp, query6_tcp] @@ -200,8 +214,9 @@ while running: if conn: conn.close() elif s == query4_tcp or s == query6_tcp: - print("TCP query received on %s" % - (ip4 if s == query4_tcp else ip6), end=" ") + print( + "TCP query received on %s" % (ip4 if s == query4_tcp else ip6), end=" " + ) conn = None try: # Handle incoming queries @@ -213,7 +228,7 @@ while running: print("NO RESPONSE (can not read the message length)") conn.close() continue - length = struct.unpack('>H', msg[:2])[0] + length = struct.unpack(">H", msg[:2])[0] msg = conn.recv(length) if len(msg) != length: print("NO RESPONSE (can not read the message)") @@ -223,7 +238,7 @@ while running: if rsp: print(dns.rcode.to_text(rsp.rcode())) wire = rsp.to_wire() - conn.send(struct.pack('>H', len(wire))) + conn.send(struct.pack(">H", len(wire))) conn.send(wire) else: print("NO RESPONSE (can not create a response)") @@ -237,8 +252,9 @@ while running: if conn: conn.close() elif s == query4_udp or s == query6_udp: - print("UDP query received on %s" % - (ip4 if s == query4_udp else ip6), end=" ") + print( + "UDP query received on %s" % (ip4 if s == query4_udp else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) if not silent: diff --git a/bin/tests/system/inline/tests_signed_zone_files.py b/bin/tests/system/inline/tests_signed_zone_files.py index 12ac675db5..06806eeb7d 100755 --- a/bin/tests/system/inline/tests_signed_zone_files.py +++ b/bin/tests/system/inline/tests_signed_zone_files.py @@ -14,29 +14,29 @@ import struct class RawFormatHeader(dict): - ''' + """ A dictionary of raw-format header fields read from a zone file. - ''' + """ fields = [ - 'format', - 'version', - 'dumptime', - 'flags', - 'sourceserial', - 'lastxfrin', + "format", + "version", + "dumptime", + "flags", + "sourceserial", + "lastxfrin", ] def __init__(self, file_name): - header = struct.Struct('>IIIIII') - with open(file_name, 'rb') as data: + header = struct.Struct(">IIIIII") + with open(file_name, "rb") as data: header_data = data.read(header.size) super().__init__(zip(self.fields, header.unpack_from(header_data))) def test_unsigned_serial_number(): - ''' + """ Check whether all signed zone files in the "ns8" subdirectory contain the serial number of the unsigned version of the zone in the raw-format header. The test assumes that all "*.signed" files in the "ns8" subdirectory are in @@ -51,18 +51,18 @@ def test_unsigned_serial_number(): - example[0-9][0-9].com.db.signed files are initially signed by dnssec-signzone while the others - by named. - ''' + """ zones_with_unsigned_serial_missing = [] - for signed_zone in sorted(glob.glob('ns8/*.signed')): + for signed_zone in sorted(glob.glob("ns8/*.signed")): raw_header = RawFormatHeader(signed_zone) # Ensure the unsigned serial number is placed where it is expected. - assert raw_header['format'] == 2 - assert raw_header['version'] == 1 + assert raw_header["format"] == 2 + assert raw_header["version"] == 1 # Check whether the header flags indicate that the unsigned serial # number is set and that the latter is indeed set. - if raw_header['flags'] & 0x02 == 0 or raw_header['sourceserial'] == 0: + if raw_header["flags"] & 0x02 == 0 or raw_header["sourceserial"] == 0: zones_with_unsigned_serial_missing.append(signed_zone) assert not zones_with_unsigned_serial_missing diff --git a/bin/tests/system/pipelined/ans5/ans.py b/bin/tests/system/pipelined/ans5/ans.py index 0a64033ecb..bac5ed35d8 100644 --- a/bin/tests/system/pipelined/ans5/ans.py +++ b/bin/tests/system/pipelined/ans5/ans.py @@ -47,25 +47,28 @@ import struct DELAY = 0.5 THREADS = [] + def log(msg): - print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg) + print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg) def sigterm(*_): - log('SIGTERM received, shutting down') + log("SIGTERM received, shutting down") for thread in THREADS: thread.close() thread.join() - os.remove('ans.pid') + os.remove("ans.pid") sys.exit(0) + class TCPDelayer(threading.Thread): - """ For a given TCP connection conn we open a connection to (ip, port), - and then we delay each incoming packet by DELAY by putting it in a - queue. - In the pipelined test TCP should not be used, but it's here for - completnes. + """For a given TCP connection conn we open a connection to (ip, port), + and then we delay each incoming packet by DELAY by putting it in a + queue. + In the pipelined test TCP should not be used, but it's here for + completnes. """ + def __init__(self, conn, ip, port): threading.Thread.__init__(self) self.conn = conn @@ -81,13 +84,15 @@ class TCPDelayer(threading.Thread): while self.running: curr_timeout = 0.5 try: - curr_timeout = self.queue[0][0]-time.time() + curr_timeout = self.queue[0][0] - time.time() except StopIteration: pass if curr_timeout > 0: if curr_timeout == 0: curr_timeout = 0.5 - rfds, _, _ = select.select([self.conn, self.cconn], [], [], curr_timeout) + rfds, _, _ = select.select( + [self.conn, self.cconn], [], [], curr_timeout + ) if self.conn in rfds: data = self.conn.recv(65535) if not data: @@ -99,17 +104,19 @@ class TCPDelayer(threading.Thread): return self.conn.send(data) try: - while self.queue[0][0]-time.time() < 0: + while self.queue[0][0] - time.time() < 0: _, data = self.queue.pop(0) self.cconn.send(data) except StopIteration: pass + class UDPDelayer(threading.Thread): - """ Every incoming UDP packet is put in a queue for DELAY time, then - it's sent to (ip, port). We remember the query id to send the - response we get to a proper source, responses are not delayed. + """Every incoming UDP packet is put in a queue for DELAY time, then + it's sent to (ip, port). We remember the query id to send the + response we get to a proper source, responses are not delayed. """ + def __init__(self, usock, ip, port): threading.Thread.__init__(self) self.sock = usock @@ -126,50 +133,56 @@ class UDPDelayer(threading.Thread): while self.running: curr_timeout = 0.5 if self.queue: - curr_timeout = self.queue[0][0]-time.time() + curr_timeout = self.queue[0][0] - time.time() if curr_timeout >= 0: if curr_timeout == 0: curr_timeout = 0.5 - rfds, _, _ = select.select([self.sock, self.csock], [], [], curr_timeout) + rfds, _, _ = select.select( + [self.sock, self.csock], [], [], curr_timeout + ) if self.sock in rfds: data, addr = self.sock.recvfrom(65535) if not data: return self.queue.append((time.time() + DELAY, data)) - qid = struct.unpack('>H', data[:2])[0] - log('Received a query from %s, queryid %d' % (str(addr), qid)) + qid = struct.unpack(">H", data[:2])[0] + log("Received a query from %s, queryid %d" % (str(addr), qid)) self.qid_mapping[qid] = addr if self.csock in rfds: data, addr = self.csock.recvfrom(65535) if not data: return - qid = struct.unpack('>H', data[:2])[0] + qid = struct.unpack(">H", data[:2])[0] dst = self.qid_mapping.get(qid) if dst is not None: self.sock.sendto(data, dst) - log('Received a response from %s, queryid %d, sending to %s' % (str(addr), qid, str(dst))) - while self.queue and self.queue[0][0]-time.time() < 0: + log( + "Received a response from %s, queryid %d, sending to %s" + % (str(addr), qid, str(dst)) + ) + while self.queue and self.queue[0][0] - time.time() < 0: _, data = self.queue.pop(0) - qid = struct.unpack('>H', data[:2])[0] - log('Sending a query to %s, queryid %d' % (str(self.dst), qid)) + qid = struct.unpack(">H", data[:2])[0] + log("Sending a query to %s, queryid %d" % (str(self.dst), qid)) self.csock.sendto(data, self.dst) + def main(): signal.signal(signal.SIGTERM, sigterm) signal.signal(signal.SIGINT, sigterm) - with open('ans.pid', 'w') as pidfile: + with open("ans.pid", "w") as pidfile: print(os.getpid(), file=pidfile) - listenip = '10.53.0.5' - serverip = '10.53.0.2' + listenip = "10.53.0.5" + serverip = "10.53.0.2" try: - port = int(os.environ['PORT']) + port = int(os.environ["PORT"]) except KeyError: port = 5300 - log('Listening on %s:%d' % (listenip, port)) + log("Listening on %s:%d" % (listenip, port)) usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -187,12 +200,13 @@ def main(): while True: try: (clientsock, _) = sock.accept() - log('Accepted connection from %s' % clientsock) + log("Accepted connection from %s" % clientsock) thread = TCPDelayer(clientsock, serverip, port) thread.start() THREADS.append(thread) except socket.timeout: pass -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/bin/tests/system/pytest_custom_markers.py b/bin/tests/system/pytest_custom_markers.py index 256fb7db8d..55b02f6c58 100644 --- a/bin/tests/system/pytest_custom_markers.py +++ b/bin/tests/system/pytest_custom_markers.py @@ -16,5 +16,6 @@ import os import pytest -long_test = pytest.mark.skipif(not os.environ.get('CI_ENABLE_ALL_TESTS'), - reason='CI_ENABLE_ALL_TESTS not set') +long_test = pytest.mark.skipif( + not os.environ.get("CI_ENABLE_ALL_TESTS"), reason="CI_ENABLE_ALL_TESTS not set" +) diff --git a/bin/tests/system/qmin/ans2/ans.py b/bin/tests/system/qmin/ans2/ans.py index 583b388768..1994ff35db 100755 --- a/bin/tests/system/qmin/ans2/ans.py +++ b/bin/tests/system/qmin/ans2/ans.py @@ -31,9 +31,11 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + def endswith(domain, labels): return domain.endswith("." + labels) or domain == labels + ############################################################################ # Respond to a DNS query. # For good. it serves: @@ -65,7 +67,7 @@ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") # get qtype rrtype = m.question[0].rdtype @@ -88,22 +90,61 @@ def create_response(msg): # Direct query - give direct answer if endswith(lqname, "8.2.6.0.1.0.0.2.ip6.arpa."): # Delegate to ns3 - r.authority.append(dns.rrset.from_text("8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns3.good.")) - r.additional.append(dns.rrset.from_text("ns3.good.", 60, IN, A, "10.53.0.3")) - elif lqname == "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa." and rrtype == PTR: + r.authority.append( + dns.rrset.from_text( + "8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns3.good." + ) + ) + r.additional.append( + dns.rrset.from_text("ns3.good.", 60, IN, A, "10.53.0.3") + ) + elif ( + lqname + == "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa." + and rrtype == PTR + ): # Direct query - give direct answer - r.answer.append(dns.rrset.from_text("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", 1, IN, PTR, "nee.com.")) + r.answer.append( + dns.rrset.from_text( + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", + 1, + IN, + PTR, + "nee.com.", + ) + ) r.flags |= dns.flags.AA elif lqname == "1.0.0.2.ip6.arpa." and rrtype == NS: # NS query at the apex - r.answer.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, NS, "ns2.good.")) + r.answer.append( + dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, NS, "ns2.good.") + ) r.flags |= dns.flags.AA - elif endswith("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", lqname): + elif endswith( + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", + lqname, + ): # NODATA answer - r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "1.0.0.2.ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "1.0.0.2.ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) r.set_rcode(NXDOMAIN) return r elif endswith(lqname, "ip6.arpa."): @@ -113,35 +154,71 @@ def create_response(msg): r.flags |= dns.flags.AA elif endswith("1.0.0.2.ip6.arpa.", lqname): # NODATA answer - r.authority.append(dns.rrset.from_text("ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) r.set_rcode(NXDOMAIN) return r elif endswith(lqname, "stale."): if endswith(lqname, "a.b.stale."): # Delegate to ns.a.b.stale. - r.authority.append(dns.rrset.from_text("a.b.stale.", 2, IN, NS, "ns.a.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.a.b.stale.", 2, IN, A, "10.53.0.3")) + r.authority.append( + dns.rrset.from_text("a.b.stale.", 2, IN, NS, "ns.a.b.stale.") + ) + r.additional.append( + dns.rrset.from_text("ns.a.b.stale.", 2, IN, A, "10.53.0.3") + ) elif endswith(lqname, "b.stale."): # Delegate to ns.b.stale. - r.authority.append(dns.rrset.from_text("b.stale.", 2, IN, NS, "ns.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.4")) + r.authority.append( + dns.rrset.from_text("b.stale.", 2, IN, NS, "ns.b.stale.") + ) + r.additional.append( + dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.4") + ) elif lqname == "stale." and rrtype == NS: # NS query at the apex. r.answer.append(dns.rrset.from_text("stale.", 2, IN, NS, "ns2.stale.")) r.flags |= dns.flags.AA elif lqname == "stale." and rrtype == SOA: # SOA query at the apex. - r.answer.append(dns.rrset.from_text("stale.", 2, IN, SOA, "ns2.stale. hostmaster.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + "stale.", 2, IN, SOA, "ns2.stale. hostmaster.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA elif lqname == "stale.": # NODATA answer - r.authority.append(dns.rrset.from_text("stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + "stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5" + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + "stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5" + ) + ) r.set_rcode(NXDOMAIN) return r elif endswith(lqname, "bad."): @@ -168,43 +245,72 @@ def create_response(msg): # Good/bad/ugly differs only in how we treat non-empty terminals if endswith(lqname, "zoop.boing."): - r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix)) - elif lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z." and rrtype == A: + r.authority.append( + dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix) + ) + elif ( + lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z." + and rrtype == A + ): r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2")) r.flags |= dns.flags.AA elif lqname == "" and rrtype == NS: r.answer.append(dns.rrset.from_text(suffix, 30, IN, NS, "ns2." + suffix)) r.flags |= dns.flags.AA elif lqname == "ns2." and rrtype == A: - r.answer.append(dns.rrset.from_text("ns2."+suffix, 30, IN, A, "10.53.0.2")) + r.answer.append(dns.rrset.from_text("ns2." + suffix, 30, IN, A, "10.53.0.2")) r.flags |= dns.flags.AA elif lqname == "ns2." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("ns2."+suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::2")) + r.answer.append( + dns.rrset.from_text("ns2." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::2") + ) r.flags |= dns.flags.AA elif lqname == "ns3." and rrtype == A: - r.answer.append(dns.rrset.from_text("ns3."+suffix, 30, IN, A, "10.53.0.3")) + r.answer.append(dns.rrset.from_text("ns3." + suffix, 30, IN, A, "10.53.0.3")) r.flags |= dns.flags.AA elif lqname == "ns3." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("ns3."+suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::3")) + r.answer.append( + dns.rrset.from_text("ns3." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::3") + ) r.flags |= dns.flags.AA elif lqname == "ns4." and rrtype == A: - r.answer.append(dns.rrset.from_text("ns4."+suffix, 30, IN, A, "10.53.0.4")) + r.answer.append(dns.rrset.from_text("ns4." + suffix, 30, IN, A, "10.53.0.4")) r.flags |= dns.flags.AA elif lqname == "ns4." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("ns4."+suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::4")) + r.answer.append( + dns.rrset.from_text("ns4." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::4") + ) r.flags |= dns.flags.AA elif lqname == "a.bit.longer.ns.name." and rrtype == A: - r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, A, "10.53.0.4")) + r.answer.append( + dns.rrset.from_text("a.bit.longer.ns.name." + suffix, 1, IN, A, "10.53.0.4") + ) r.flags |= dns.flags.AA elif lqname == "a.bit.longer.ns.name." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4")) + r.answer.append( + dns.rrset.from_text( + "a.bit.longer.ns.name." + suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4" + ) + ) r.flags |= dns.flags.AA else: - r.authority.append(dns.rrset.from_text(suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) - if bad or not \ - (endswith("icky.icky.icky.ptang.zoop.boing.", lqname) or \ - endswith("many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.", lqname) or \ - endswith("a.bit.longer.ns.name.", lqname)): + r.authority.append( + dns.rrset.from_text( + suffix, + 1, + IN, + SOA, + "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) + if bad or not ( + endswith("icky.icky.icky.ptang.zoop.boing.", lqname) + or endswith( + "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.", + lqname, + ) + or endswith("a.bit.longer.ns.name.", lqname) + ): r.set_rcode(NXDOMAIN) if ugly: r.set_rcode(FORMERR) @@ -214,11 +320,12 @@ def create_response(msg): def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -229,8 +336,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.2" ip6 = "fd92:7065:b8e:ffff::2" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -248,17 +357,17 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -277,8 +386,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/qmin/ans3/ans.py b/bin/tests/system/qmin/ans3/ans.py index 7416e6f18f..b2883a1b7d 100755 --- a/bin/tests/system/qmin/ans3/ans.py +++ b/bin/tests/system/qmin/ans3/ans.py @@ -31,9 +31,11 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + def endswith(domain, labels): return domain.endswith("." + labels) or domain == labels + ############################################################################ # Respond to a DNS query. # For good. it serves: @@ -54,7 +56,7 @@ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") # get qtype rrtype = m.question[0].rdtype @@ -101,17 +103,31 @@ def create_response(msg): elif rrtype == NS: # NS a.b. r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")) + r.additional.append( + dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3") + ) r.flags |= dns.flags.AA elif rrtype == SOA: # SOA a.b. - r.answer.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA else: # NODATA. - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) else: - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) r.set_rcode(NXDOMAIN) # NXDOMAIN. return r @@ -121,21 +137,51 @@ def create_response(msg): # Good/bad differs only in how we treat non-empty terminals if lqname == "zoop.boing." and rrtype == NS: - r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3."+suffix)) + r.answer.append( + dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3." + suffix) + ) r.flags |= dns.flags.AA elif endswith(lqname, "icky.ptang.zoop.boing."): - r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix)) + r.authority.append( + dns.rrset.from_text( + "icky.ptang.zoop.boing." + suffix, + 1, + IN, + NS, + "a.bit.longer.ns.name." + suffix, + ) + ) elif endswith("icky.ptang.zoop.boing.", lqname): - r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "zoop.boing." + suffix, + 1, + IN, + SOA, + "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) if bad: r.set_rcode(NXDOMAIN) if ugly: r.set_rcode(FORMERR) elif endswith(lqname, "zoop.boing."): - r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "zoop.boing." + suffix, + 1, + IN, + SOA, + "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) r.set_rcode(NXDOMAIN) elif ip6req: - r.authority.append(dns.rrset.from_text("1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns4.good.")) + r.authority.append( + dns.rrset.from_text( + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns4.good." + ) + ) r.additional.append(dns.rrset.from_text("ns4.good.", 60, IN, A, "10.53.0.4")) else: r.set_rcode(REFUSED) @@ -146,11 +192,12 @@ def create_response(msg): def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -161,8 +208,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.3" ip6 = "fd92:7065:b8e:ffff::3" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -180,17 +229,17 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -209,8 +258,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/qmin/ans4/ans.py b/bin/tests/system/qmin/ans4/ans.py index 2c672c8e71..a4cc13c656 100755 --- a/bin/tests/system/qmin/ans4/ans.py +++ b/bin/tests/system/qmin/ans4/ans.py @@ -31,9 +31,11 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + def endswith(domain, labels): return domain.endswith("." + labels) or domain == labels + ############################################################################ # Respond to a DNS query. # For good. it serves: @@ -55,7 +57,7 @@ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") # get qtype rrtype = m.question[0].rdtype @@ -102,30 +104,54 @@ def create_response(msg): elif rrtype == NS: # NS a.b. r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")) + r.additional.append( + dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3") + ) r.flags |= dns.flags.AA elif rrtype == SOA: # SOA a.b. - r.answer.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA else: # NODATA. - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) elif lqname == "b.stale.": if rrtype == NS: # NS b. r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.b.stale.", 1, IN, A, "10.53.0.4")) + r.additional.append( + dns.rrset.from_text("ns.b.stale.", 1, IN, A, "10.53.0.4") + ) r.flags |= dns.flags.AA elif rrtype == SOA: # SOA b. - r.answer.append(dns.rrset.from_text(lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA else: # NODATA. - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5" + ) + ) else: - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5" + ) + ) r.set_rcode(NXDOMAIN) # NXDOMAIN. return r @@ -141,24 +167,67 @@ def create_response(msg): r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2")) r.flags |= dns.flags.AA elif lqname == "icky.ptang.zoop.boing." and rrtype == NS: - r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name."+suffix)) + r.answer.append( + dns.rrset.from_text( + lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix + ) + ) r.flags |= dns.flags.AA elif endswith(lqname, "icky.ptang.zoop.boing."): - r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "icky.ptang.zoop.boing." + suffix, + 1, + IN, + SOA, + "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) if bad or not endswith("more.icky.icky.icky.ptang.zoop.boing.", lqname): r.set_rcode(NXDOMAIN) if ugly: r.set_rcode(FORMERR) elif ip6req: r.flags |= dns.flags.AA - if lqname == "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa." and rrtype == TXT: - r.answer.append(dns.rrset.from_text("test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 1, IN, TXT, "long_ip6_name")) - elif endswith("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", lqname): - #NODATA answer - r.authority.append(dns.rrset.from_text("1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, SOA, "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16")) + if ( + lqname + == "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa." + and rrtype == TXT + ): + r.answer.append( + dns.rrset.from_text( + "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + 1, + IN, + TXT, + "long_ip6_name", + ) + ) + elif endswith( + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + lqname, + ): + # NODATA answer + r.authority.append( + dns.rrset.from_text( + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + 60, + IN, + SOA, + "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16", + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, SOA, "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16")) + r.authority.append( + dns.rrset.from_text( + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + 60, + IN, + SOA, + "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16", + ) + ) r.set_rcode(NXDOMAIN) else: r.set_rcode(REFUSED) @@ -169,11 +238,12 @@ def create_response(msg): def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -184,8 +254,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.4" ip6 = "fd92:7065:b8e:ffff::4" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -203,17 +275,17 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -232,8 +304,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py b/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py index 4785babfba..326284739e 100755 --- a/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py +++ b/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py @@ -15,24 +15,24 @@ import os import pytest -pytest.importorskip('dns') +pytest.importorskip("dns") import dns.resolver def test_rpz_passthru_logging(named_port): resolver = dns.resolver.Resolver() - resolver.nameservers = ['10.53.0.1'] + resolver.nameservers = ["10.53.0.1"] resolver.port = named_port # Should generate a log entry into rpz_passthru.txt - ans = resolver.query('allowed.', 'A') + ans = resolver.query("allowed.", "A") for rd in ans: assert rd.address == "10.53.0.2" # baddomain.com isn't allowed (CNAME .), should return NXDOMAIN # Should generate a log entry into rpz.txt with pytest.raises(dns.resolver.NXDOMAIN): - resolver.query('baddomain.', 'A') + resolver.query("baddomain.", "A") rpz_passthru_logfile = os.path.join("ns1", "rpz_passthru.txt") rpz_logfile = os.path.join("ns1", "rpz.txt") @@ -40,11 +40,11 @@ def test_rpz_passthru_logging(named_port): assert os.path.isfile(rpz_passthru_logfile) assert os.path.isfile(rpz_logfile) - with open(rpz_passthru_logfile, encoding='utf-8') as log_file: + with open(rpz_passthru_logfile, encoding="utf-8") as log_file: line = log_file.read() assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" in line - with open(rpz_logfile, encoding='utf-8') as log_file: + with open(rpz_logfile, encoding="utf-8") as log_file: line = log_file.read() assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" not in line assert "rpz QNAME NXDOMAIN rewrite baddomain/A/IN" in line diff --git a/bin/tests/system/shutdown/tests-shutdown.py b/bin/tests/system/shutdown/tests-shutdown.py index b8de379d66..e8fc69e170 100755 --- a/bin/tests/system/shutdown/tests-shutdown.py +++ b/bin/tests/system/shutdown/tests-shutdown.py @@ -21,47 +21,47 @@ import time import pytest -pytest.importorskip('dns') +pytest.importorskip("dns") import dns.exception import dns.resolver def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries): """Creates a number of A queries to run in parallel - in order simulate a slightly more realistic test scenario. + in order simulate a slightly more realistic test scenario. - The main idea of this function is to create and send a bunch - of A queries to a target named instance and during this process - a request for shutting down named will be issued. + The main idea of this function is to create and send a bunch + of A queries to a target named instance and during this process + a request for shutting down named will be issued. - In the process of shutting down named, a couple control connections - are created (by launching rndc) to ensure that the crash was fixed. + In the process of shutting down named, a couple control connections + are created (by launching rndc) to ensure that the crash was fixed. - if kill_method=="rndc" named will be asked to shutdown by - means of rndc stop. - if kill_method=="sigterm" named will be killed by SIGTERM on - POSIX systems or by TerminateProcess() on Windows systems. + if kill_method=="rndc" named will be asked to shutdown by + means of rndc stop. + if kill_method=="sigterm" named will be killed by SIGTERM on + POSIX systems or by TerminateProcess() on Windows systems. - :param named_proc: named process instance - :type named_proc: subprocess.Popen + :param named_proc: named process instance + :type named_proc: subprocess.Popen - :param resolver: target resolver - :type resolver: dns.resolver.Resolver + :param resolver: target resolver + :type resolver: dns.resolver.Resolver - :param rndc_cmd: rndc command with default arguments - :type rndc_cmd: list of strings, e.g. ["rndc", "-p", "23750"] + :param rndc_cmd: rndc command with default arguments + :type rndc_cmd: list of strings, e.g. ["rndc", "-p", "23750"] - :kill_method: "rndc" or "sigterm" - :type kill_method: str + :kill_method: "rndc" or "sigterm" + :type kill_method: str - :param n_workers: Number of worker threads to create - :type n_workers: int + :param n_workers: Number of worker threads to create + :type n_workers: int - :param n_queries: Total number of queries to send - :type n_queries: int + :param n_queries: Total number of queries to send + :type n_queries: int """ -# pylint: disable-msg=too-many-arguments -# pylint: disable-msg=too-many-locals + # pylint: disable-msg=too-many-arguments + # pylint: disable-msg=too-many-locals # helper function, args must be a list or tuple with arguments to rndc. def launch_rndc(args): @@ -91,21 +91,22 @@ def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries): else: tag = "bad" length = random.randint(4, 10) - relname = "".join(letters[ - random.randrange(len(letters))] for i in range(length)) + relname = "".join( + letters[random.randrange(len(letters))] for i in range(length) + ) qname = relname + ".test" - futures[executor.submit(resolver.query, qname, 'A')] = tag + futures[executor.submit(resolver.query, qname, "A")] = tag elif shutdown: # We attempt to stop named in the middle shutdown = False if kill_method == "rndc": - futures[executor.submit(launch_rndc, ['stop'])] = 'stop' + futures[executor.submit(launch_rndc, ["stop"])] = "stop" else: - futures[executor.submit(named_proc.terminate)] = 'kill' + futures[executor.submit(named_proc.terminate)] = "kill" else: # We attempt to send couple rndc commands while named is # being shutdown - futures[executor.submit(launch_rndc, ['status'])] = 'status' + futures[executor.submit(launch_rndc, ["status"])] = "status" ret_code = -1 for future in as_completed(futures): @@ -120,9 +121,11 @@ def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries): if futures[future] == "stop": ret_code = result - except (dns.resolver.NXDOMAIN, - dns.resolver.NoNameservers, - dns.exception.Timeout): + except ( + dns.resolver.NXDOMAIN, + dns.resolver.NoNameservers, + dns.exception.Timeout, + ): pass if kill_method == "rndc": @@ -148,12 +151,11 @@ def test_named_shutdown(named_port, control_port): assert os.path.isfile(rndc_cfg) # rndc command with default arguments. - rndc_cmd = [rndc, "-c", rndc_cfg, "-p", str(control_port), - "-s", "10.53.0.3"] + rndc_cmd = [rndc, "-c", rndc_cfg, "-p", str(control_port), "-s", "10.53.0.3"] # We create a resolver instance that will be used to send queries. resolver = dns.resolver.Resolver() - resolver.nameservers = ['10.53.0.3'] + resolver.nameservers = ["10.53.0.3"] resolver.port = named_port # We test named shutting down using two methods: @@ -168,13 +170,14 @@ def test_named_shutdown(named_port, control_port): # wait for named to finish loading for _ in range(10): try: - resolver.query('version.bind', 'TXT', 'CH') + resolver.query("version.bind", "TXT", "CH") break except (dns.resolver.NoNameservers, dns.exception.Timeout): time.sleep(1) - do_work(named_proc, resolver, rndc_cmd, - kill_method, n_workers=12, n_queries=16) + do_work( + named_proc, resolver, rndc_cmd, kill_method, n_workers=12, n_queries=16 + ) # Wait named to exit for a maximum of MAX_TIMEOUT seconds. MAX_TIMEOUT = 10 diff --git a/bin/tests/system/statschannel/generic.py b/bin/tests/system/statschannel/generic.py index e4cf82cec5..6688ff6db0 100644 --- a/bin/tests/system/statschannel/generic.py +++ b/bin/tests/system/statschannel/generic.py @@ -14,7 +14,7 @@ import os # ISO datetime format without msec -fmt = '%Y-%m-%dT%H:%M:%SZ' +fmt = "%Y-%m-%dT%H:%M:%SZ" # The constants were taken from BIND 9 source code (lib/dns/zone.c) max_refresh = timedelta(seconds=2419200) # 4 weeks @@ -71,9 +71,9 @@ def zone_mtime(zonedir, name): def test_zone_timers_primary(fetch_zones, load_timers, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] - zonedir = kwargs['zonedir'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] + zonedir = kwargs["zonedir"] zones = fetch_zones(statsip, statsport) @@ -85,9 +85,9 @@ def test_zone_timers_primary(fetch_zones, load_timers, **kwargs): def test_zone_timers_secondary(fetch_zones, load_timers, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] - zonedir = kwargs['zonedir'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] + zonedir = kwargs["zonedir"] zones = fetch_zones(statsip, statsport) @@ -99,12 +99,12 @@ def test_zone_timers_secondary(fetch_zones, load_timers, **kwargs): def test_zone_with_many_keys(fetch_zones, load_zone, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] zones = fetch_zones(statsip, statsport) for zone in zones: name = load_zone(zone) - if name == 'manykeys': + if name == "manykeys": check_manykeys(name) diff --git a/bin/tests/system/statschannel/generic_dnspython.py b/bin/tests/system/statschannel/generic_dnspython.py index 88dabbca08..37e6e89f14 100644 --- a/bin/tests/system/statschannel/generic_dnspython.py +++ b/bin/tests/system/statschannel/generic_dnspython.py @@ -20,8 +20,9 @@ TIMEOUT = 10 def create_msg(qname, qtype): - msg = dns.message.make_query(qname, qtype, want_dnssec=True, - use_edns=0, payload=4096) + msg = dns.message.make_query( + qname, qtype, want_dnssec=True, use_edns=0, payload=4096 + ) return msg @@ -43,15 +44,16 @@ def tcp_query(ip, port, msg): def create_expected(data): - expected = {"dns-tcp-requests-sizes-received-ipv4": defaultdict(int), - "dns-tcp-responses-sizes-sent-ipv4": defaultdict(int), - "dns-tcp-requests-sizes-received-ipv6": defaultdict(int), - "dns-tcp-responses-sizes-sent-ipv6": defaultdict(int), - "dns-udp-requests-sizes-received-ipv4": defaultdict(int), - "dns-udp-requests-sizes-received-ipv6": defaultdict(int), - "dns-udp-responses-sizes-sent-ipv4": defaultdict(int), - "dns-udp-responses-sizes-sent-ipv6": defaultdict(int), - } + expected = { + "dns-tcp-requests-sizes-received-ipv4": defaultdict(int), + "dns-tcp-responses-sizes-sent-ipv4": defaultdict(int), + "dns-tcp-requests-sizes-received-ipv6": defaultdict(int), + "dns-tcp-responses-sizes-sent-ipv6": defaultdict(int), + "dns-udp-requests-sizes-received-ipv4": defaultdict(int), + "dns-udp-requests-sizes-received-ipv6": defaultdict(int), + "dns-udp-responses-sizes-sent-ipv4": defaultdict(int), + "dns-udp-responses-sizes-sent-ipv6": defaultdict(int), + } for k, v in data.items(): for kk, vv in v.items(): @@ -89,9 +91,9 @@ def check_traffic(data, expected): def test_traffic(fetch_traffic, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] - port = kwargs['port'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] + port = kwargs["port"] data = fetch_traffic(statsip, statsport) exp = create_expected(data) diff --git a/bin/tests/system/statschannel/tests-json.py b/bin/tests/system/statschannel/tests-json.py index 373f98d30b..d94a32f7da 100755 --- a/bin/tests/system/statschannel/tests-json.py +++ b/bin/tests/system/statschannel/tests-json.py @@ -19,16 +19,18 @@ import pytest import generic -pytestmark = pytest.mark.skipif(not os.environ.get('HAVEJSONSTATS'), - reason='json-c support disabled in the build') -requests = pytest.importorskip('requests') +pytestmark = pytest.mark.skipif( + not os.environ.get("HAVEJSONSTATS"), reason="json-c support disabled in the build" +) +requests = pytest.importorskip("requests") # JSON helper functions def fetch_zones_json(statsip, statsport): - r = requests.get("http://{}:{}/json/v1/zones".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/json/v1/zones".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 data = r.json() @@ -37,8 +39,9 @@ def fetch_zones_json(statsip, statsport): def fetch_traffic_json(statsip, statsport): - r = requests.get("http://{}:{}/json/v1/traffic".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/json/v1/traffic".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 data = r.json() @@ -48,52 +51,61 @@ def fetch_traffic_json(statsip, statsport): def load_timers_json(zone, primary=True): - name = zone['name'] + name = zone["name"] # Check if the primary zone timer exists - assert 'loaded' in zone - loaded = datetime.strptime(zone['loaded'], generic.fmt) + assert "loaded" in zone + loaded = datetime.strptime(zone["loaded"], generic.fmt) if primary: # Check if the secondary zone timers does not exist - assert 'expires' not in zone - assert 'refresh' not in zone + assert "expires" not in zone + assert "refresh" not in zone expires = None refresh = None else: - assert 'expires' in zone - assert 'refresh' in zone - expires = datetime.strptime(zone['expires'], generic.fmt) - refresh = datetime.strptime(zone['refresh'], generic.fmt) + assert "expires" in zone + assert "refresh" in zone + expires = datetime.strptime(zone["expires"], generic.fmt) + refresh = datetime.strptime(zone["refresh"], generic.fmt) return (name, loaded, expires, refresh) def load_zone_json(zone): - name = zone['name'] + name = zone["name"] return name def test_zone_timers_primary_json(statsport): - generic.test_zone_timers_primary(fetch_zones_json, load_timers_json, - statsip="10.53.0.1", statsport=statsport, - zonedir="ns1") + generic.test_zone_timers_primary( + fetch_zones_json, + load_timers_json, + statsip="10.53.0.1", + statsport=statsport, + zonedir="ns1", + ) def test_zone_timers_secondary_json(statsport): - generic.test_zone_timers_secondary(fetch_zones_json, load_timers_json, - statsip="10.53.0.3", statsport=statsport, - zonedir="ns3") + generic.test_zone_timers_secondary( + fetch_zones_json, + load_timers_json, + statsip="10.53.0.3", + statsport=statsport, + zonedir="ns3", + ) def test_zone_with_many_keys_json(statsport): - generic.test_zone_with_many_keys(fetch_zones_json, load_zone_json, - statsip="10.53.0.2", statsport=statsport) + generic.test_zone_with_many_keys( + fetch_zones_json, load_zone_json, statsip="10.53.0.2", statsport=statsport + ) def test_traffic_json(named_port, statsport): - generic_dnspython = pytest.importorskip('generic_dnspython') - generic_dnspython.test_traffic(fetch_traffic_json, - statsip="10.53.0.2", statsport=statsport, - port=named_port) + generic_dnspython = pytest.importorskip("generic_dnspython") + generic_dnspython.test_traffic( + fetch_traffic_json, statsip="10.53.0.2", statsport=statsport, port=named_port + ) diff --git a/bin/tests/system/statschannel/tests-xml.py b/bin/tests/system/statschannel/tests-xml.py index 73b6e909f3..423754916a 100755 --- a/bin/tests/system/statschannel/tests-xml.py +++ b/bin/tests/system/statschannel/tests-xml.py @@ -20,41 +20,43 @@ import pytest import generic -pytestmark = pytest.mark.skipif(not os.environ.get('HAVEXMLSTATS'), - reason='libxml2 support disabled in the build') -requests = pytest.importorskip('requests') +pytestmark = pytest.mark.skipif( + not os.environ.get("HAVEXMLSTATS"), reason="libxml2 support disabled in the build" +) +requests = pytest.importorskip("requests") # XML helper functions def fetch_zones_xml(statsip, statsport): - r = requests.get("http://{}:{}/xml/v3/zones".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/xml/v3/zones".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 root = ET.fromstring(r.text) default_view = None - for view in root.find('views').iter('view'): - if view.attrib['name'] == "_default": + for view in root.find("views").iter("view"): + if view.attrib["name"] == "_default": default_view = view break assert default_view is not None - return default_view.find('zones').findall('zone') + return default_view.find("zones").findall("zone") def fetch_traffic_xml(statsip, statsport): - def load_counters(data): out = {} for counter in data.findall("counter"): - out[counter.attrib['name']] = int(counter.text) + out[counter.attrib["name"]] = int(counter.text) return out - r = requests.get("http://{}:{}/xml/v3/traffic".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/xml/v3/traffic".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 root = ET.fromstring(r.text) @@ -64,7 +66,7 @@ def fetch_traffic_xml(statsip, statsport): for proto in ["udp", "tcp"]: proto_root = root.find("traffic").find(ip).find(proto) for counters in proto_root.findall("counters"): - if counters.attrib['type'] == "request-size": + if counters.attrib["type"] == "request-size": key = "dns-{}-requests-sizes-received-{}".format(proto, ip) else: key = "dns-{}-responses-sizes-sent-{}".format(proto, ip) @@ -77,14 +79,14 @@ def fetch_traffic_xml(statsip, statsport): def load_timers_xml(zone, primary=True): - name = zone.attrib['name'] + name = zone.attrib["name"] - loaded_el = zone.find('loaded') + loaded_el = zone.find("loaded") assert loaded_el is not None loaded = datetime.strptime(loaded_el.text, generic.fmt) - expires_el = zone.find('expires') - refresh_el = zone.find('refresh') + expires_el = zone.find("expires") + refresh_el = zone.find("refresh") if primary: assert expires_el is None assert refresh_el is None @@ -100,30 +102,39 @@ def load_timers_xml(zone, primary=True): def load_zone_xml(zone): - name = zone.attrib['name'] + name = zone.attrib["name"] return name def test_zone_timers_primary_xml(statsport): - generic.test_zone_timers_primary(fetch_zones_xml, load_timers_xml, - statsip="10.53.0.1", statsport=statsport, - zonedir="ns1") + generic.test_zone_timers_primary( + fetch_zones_xml, + load_timers_xml, + statsip="10.53.0.1", + statsport=statsport, + zonedir="ns1", + ) def test_zone_timers_secondary_xml(statsport): - generic.test_zone_timers_secondary(fetch_zones_xml, load_timers_xml, - statsip="10.53.0.3", statsport=statsport, - zonedir="ns3") + generic.test_zone_timers_secondary( + fetch_zones_xml, + load_timers_xml, + statsip="10.53.0.3", + statsport=statsport, + zonedir="ns3", + ) def test_zone_with_many_keys_xml(statsport): - generic.test_zone_with_many_keys(fetch_zones_xml, load_zone_xml, - statsip="10.53.0.2", statsport=statsport) + generic.test_zone_with_many_keys( + fetch_zones_xml, load_zone_xml, statsip="10.53.0.2", statsport=statsport + ) def test_traffic_xml(named_port, statsport): - generic_dnspython = pytest.importorskip('generic_dnspython') - generic_dnspython.test_traffic(fetch_traffic_xml, - statsip="10.53.0.2", statsport=statsport, - port=named_port) + generic_dnspython = pytest.importorskip("generic_dnspython") + generic_dnspython.test_traffic( + fetch_traffic_xml, statsip="10.53.0.2", statsport=statsport, port=named_port + ) diff --git a/bin/tests/system/tcp/ans6/ans.py b/bin/tests/system/tcp/ans6/ans.py index 5cc98538fb..4595ddcd07 100644 --- a/bin/tests/system/tcp/ans6/ans.py +++ b/bin/tests/system/tcp/ans6/ans.py @@ -42,10 +42,11 @@ import time # Timeout for establishing all connections requested by a single 'open' command. OPEN_TIMEOUT = 2 -VERSION_QUERY = b'\x00\x1e\xaf\xb8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03' +VERSION_QUERY = b"\x00\x1e\xaf\xb8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03" + def log(msg): - print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg) + print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg) def open_connections(active_conns, count, host, port): @@ -58,14 +59,14 @@ def open_connections(active_conns, count, host, port): except socket.error: family = socket.AF_INET6 - log('Opening %d connections...' % count) + log("Opening %d connections..." % count) for _ in range(count): sock = socket.socket(family, socket.SOCK_STREAM) sock.setblocking(0) err = sock.connect_ex((host, port)) if err not in (0, errno.EINPROGRESS): - log('%s on connect for socket %s' % (errno.errorcode[err], sock)) + log("%s on connect for socket %s" % (errno.errorcode[err], sock)) errors.append(sock) else: queued.append(sock) @@ -81,35 +82,35 @@ def open_connections(active_conns, count, host, port): queued.remove(sock) err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) if err: - log('%s for socket %s' % (errno.errorcode[err], sock)) + log("%s for socket %s" % (errno.errorcode[err], sock)) errors.append(sock) else: sock.send(VERSION_QUERY) active_conns.append(sock) if errors: - log('result=FAIL: %d connection(s) failed' % len(errors)) + log("result=FAIL: %d connection(s) failed" % len(errors)) elif queued: - log('result=FAIL: Timed out, aborting %d pending connections' % len(queued)) + log("result=FAIL: Timed out, aborting %d pending connections" % len(queued)) for sock in queued: sock.close() else: - log('result=OK: Successfully opened %d connections' % count) + log("result=OK: Successfully opened %d connections" % count) def close_connections(active_conns, count): - log('Closing %s connections...' % "all" if count == 0 else str(count)) + log("Closing %s connections..." % "all" if count == 0 else str(count)) if count == 0: count = len(active_conns) for _ in range(count): sock = active_conns.pop(0) sock.close() - log('result=OK: Successfully closed %d connections' % count) + log("result=OK: Successfully closed %d connections" % count) def sigterm(*_): - log('SIGTERM received, shutting down') - os.remove('ans.pid') + log("SIGTERM received, shutting down") + os.remove("ans.pid") sys.exit(0) @@ -118,16 +119,16 @@ def main(): signal.signal(signal.SIGTERM, sigterm) - with open('ans.pid', 'w') as pidfile: + with open("ans.pid", "w") as pidfile: print(os.getpid(), file=pidfile) - listenip = '10.53.0.6' + listenip = "10.53.0.6" try: - port = int(os.environ['CONTROLPORT']) + port = int(os.environ["CONTROLPORT"]) except KeyError: port = 5309 - log('Listening on %s:%d' % (listenip, port)) + log("Listening on %s:%d" % (listenip, port)) ctlsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ctlsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -136,21 +137,21 @@ def main(): while True: (clientsock, _) = ctlsock.accept() - log('Accepted control connection from %s' % clientsock) - cmdline = clientsock.recv(512).decode('ascii').strip() + log("Accepted control connection from %s" % clientsock) + cmdline = clientsock.recv(512).decode("ascii").strip() if cmdline: - log('Received command: %s' % cmdline) + log("Received command: %s" % cmdline) cmd = cmdline.split() - if cmd[0] == 'open': + if cmd[0] == "open": count, host, port = cmd[1:] open_connections(active_conns, int(count), host, int(port)) - elif cmd[0] == 'close': - (count, ) = cmd[1:] + elif cmd[0] == "close": + (count,) = cmd[1:] close_connections(active_conns, int(count)) else: - log('result=FAIL: Unknown command') + log("result=FAIL: Unknown command") clientsock.close() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/bin/tests/system/tcp/tests-tcp.py b/bin/tests/system/tcp/tests-tcp.py index e641ad9103..b38e1de688 100644 --- a/bin/tests/system/tcp/tests-tcp.py +++ b/bin/tests/system/tcp/tests-tcp.py @@ -19,7 +19,7 @@ import time import pytest -pytest.importorskip('dns', minversion='2.0.0') +pytest.importorskip("dns", minversion="2.0.0") import dns.message import dns.query @@ -54,8 +54,8 @@ def test_tcp_garbage(named_port): # Send DNS message shorter than DNS message header (12), # this should cause the connection to be terminated - sock.send(struct.pack('!H', 11)) - sock.send(struct.pack('!s', b'0123456789a')) + sock.send(struct.pack("!H", 11)) + sock.send(struct.pack("!s", b"0123456789a")) with pytest.raises(EOFError): try: @@ -96,8 +96,7 @@ def test_close_wait(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) (response, rtime) = dns.query.receive_tcp(sock, timeout()) - msg = dns.message.make_query("a.example.", "A", use_edns=0, - payload=1232) + msg = dns.message.make_query("a.example.", "A", use_edns=0, payload=1232) (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Shutdown the socket, but ignore the other side closing the socket diff --git a/bin/tests/system/timeouts/tests-tcp.py b/bin/tests/system/timeouts/tests-tcp.py index 74d7cb695f..994a9d746c 100644 --- a/bin/tests/system/timeouts/tests-tcp.py +++ b/bin/tests/system/timeouts/tests-tcp.py @@ -18,7 +18,7 @@ import time import pytest -pytest.importorskip('dns', minversion='2.0.0') +pytest.importorskip("dns", minversion="2.0.0") import dns.edns import dns.message import dns.name @@ -33,8 +33,9 @@ TIMEOUT = 10 def create_msg(qname, qtype): - msg = dns.message.make_query(qname, qtype, want_dnssec=True, - use_edns=0, payload=4096) + msg = dns.message.make_query( + qname, qtype, want_dnssec=True, use_edns=0, payload=4096 + ) return msg @@ -94,7 +95,7 @@ def test_keepalive_timeout(named_port): # Keepalive is 7 seconds, so the third message should succeed. # msg = create_msg("example.", "A") - kopt = dns.edns.GenericOption(11, b'\x00') + kopt = dns.edns.GenericOption(11, b"\x00") msg.use_edns(edns=True, payload=4096, options=[kopt]) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: @@ -163,18 +164,22 @@ def test_long_axfr(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Receive the initial DNS message with SOA - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) assert soa is not None # Pull DNS message from wire until the second SOA is received while True: - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) if soa is not None: break assert soa is not None @@ -216,10 +221,12 @@ def test_max_transfer_idle_out(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Receive the initial DNS message with SOA - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) assert soa is not None time.sleep(61) # max-transfer-idle-out is 1 minute @@ -227,11 +234,12 @@ def test_max_transfer_idle_out(named_port): with pytest.raises(ConnectionResetError): # Process queued TCP messages while True: - (response, rtime) = \ - dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) if soa is not None: break assert soa is None @@ -247,21 +255,24 @@ def test_max_transfer_time_out(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Receive the initial DNS message with SOA - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) assert soa is not None # The loop should timeout at the 5 minutes (max-transfer-time-out) with pytest.raises(EOFError): while True: time.sleep(1) - (response, rtime) = \ - dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) if soa is not None: break assert soa is None diff --git a/bin/tests/system/wildcard/tests-wildcard.py b/bin/tests/system/wildcard/tests-wildcard.py index f4134225e1..66166f2a9e 100755 --- a/bin/tests/system/wildcard/tests-wildcard.py +++ b/bin/tests/system/wildcard/tests-wildcard.py @@ -45,19 +45,21 @@ from hypothesis.strategies import binary, integers # labels of a zone with * A 192.0.2.1 wildcard -WILDCARD_ZONE = ('allwild', 'test', '') +WILDCARD_ZONE = ("allwild", "test", "") WILDCARD_RDTYPE = dns.rdatatype.A -WILDCARD_RDATA = '192.0.2.1' -IPADDR = '10.53.0.1' +WILDCARD_RDATA = "192.0.2.1" +IPADDR = "10.53.0.1" TIMEOUT = 5 # seconds, just a sanity check # Helpers def is_nonexpanding_rdtype(rdtype): """skip meta types to avoid weird rcodes caused by AXFR etc.; RFC 6895""" - return not(rdtype == WILDCARD_RDTYPE - or dns.rdatatype.is_metatype(rdtype) # known metatypes: OPT ... - or 128 <= rdtype <= 255) # unknown meta types + return not ( + rdtype == WILDCARD_RDTYPE + or dns.rdatatype.is_metatype(rdtype) # known metatypes: OPT ... + or 128 <= rdtype <= 255 + ) # unknown meta types def tcp_query(where, port, qname, qtype): @@ -67,15 +69,16 @@ def tcp_query(where, port, qname, qtype): def query(where, port, label, rdtype): - labels = (label, ) + WILDCARD_ZONE + labels = (label,) + WILDCARD_ZONE qname = dns.name.Name(labels) return tcp_query(where, port, qname, rdtype) # Tests -@given(label=binary(min_size=1, max_size=63), - rdtype=integers(min_value=0, max_value=65535).filter( - is_nonexpanding_rdtype)) +@given( + label=binary(min_size=1, max_size=63), + rdtype=integers(min_value=0, max_value=65535).filter(is_nonexpanding_rdtype), +) def test_wildcard_rdtype_mismatch(label, rdtype, named_port): """any label non-matching rdtype must result in to NODATA""" check_answer_nodata(*query(IPADDR, named_port, label, rdtype)) @@ -97,10 +100,13 @@ def check_answer_noerror(querymsg, answer): assert querymsg.is_response(answer), str(answer) assert answer.rcode() == dns.rcode.NOERROR, str(answer) assert len(querymsg.question) == 1, str(answer) - expected_answer = [dns.rrset.from_text( - querymsg.question[0].name, - 300, # TTL, ignored by dnspython comparison - dns.rdataclass.IN, - WILDCARD_RDTYPE, - WILDCARD_RDATA)] + expected_answer = [ + dns.rrset.from_text( + querymsg.question[0].name, + 300, # TTL, ignored by dnspython comparison + dns.rdataclass.IN, + WILDCARD_RDTYPE, + WILDCARD_RDATA, + ) + ] assert answer.answer == expected_answer, str(answer) diff --git a/dangerfile.py b/dangerfile.py index 5a7b564758..2f139f79aa 100644 --- a/dangerfile.py +++ b/dangerfile.py @@ -15,24 +15,30 @@ import re # Helper functions and variables + def added_lines(target_branch, paths): import subprocess - subprocess.check_output(['/usr/bin/git', 'fetch', '--depth', '1', 'origin', - target_branch]) - diff = subprocess.check_output(['/usr/bin/git', 'diff', 'FETCH_HEAD..', - '--'] + paths) + + subprocess.check_output( + ["/usr/bin/git", "fetch", "--depth", "1", "origin", target_branch] + ) + diff = subprocess.check_output( + ["/usr/bin/git", "diff", "FETCH_HEAD..", "--"] + paths + ) added_lines = [] for line in diff.splitlines(): - if line.startswith(b'+') and not line.startswith(b'+++'): + if line.startswith(b"+") and not line.startswith(b"+++"): added_lines.append(line) return added_lines -def lines_containing(lines, string): - return [l for l in lines if bytes(string, 'utf-8') in l] -changes_issue_or_mr_id_regex = re.compile(br'\[(GL [#!]|RT #)[0-9]+\]') -relnotes_issue_or_mr_id_regex = re.compile(br':gl:`[#!][0-9]+`') -release_notes_regex = re.compile(r'doc/(arm|notes)/notes-.*\.(rst|xml)') +def lines_containing(lines, string): + return [l for l in lines if bytes(string, "utf-8") in l] + + +changes_issue_or_mr_id_regex = re.compile(rb"\[(GL [#!]|RT #)[0-9]+\]") +relnotes_issue_or_mr_id_regex = re.compile(rb":gl:`[#!][0-9]+`") +release_notes_regex = re.compile(r"doc/(arm|notes)/notes-.*\.(rst|xml)") modified_files = danger.git.modified_files mr_labels = danger.gitlab.mr.labels @@ -75,33 +81,39 @@ fixup_error_logged = False for commit in danger.git.commits: message_lines = commit.message.splitlines() subject = message_lines[0] - if (not fixup_error_logged and - (subject.startswith('fixup!') or - subject.startswith('Apply suggestion'))): - fail('Fixup commits are still present in this merge request. ' - 'Please squash them before merging.') - fixup_error_logged = True - if len(subject) > 72 and not subject.startswith('Merge branch '): - warn( - f'Subject line for commit {commit.sha} is too long: ' - f'```{subject}``` ({len(subject)} > 72 characters).' + if not fixup_error_logged and ( + subject.startswith("fixup!") or subject.startswith("Apply suggestion") + ): + fail( + "Fixup commits are still present in this merge request. " + "Please squash them before merging." ) - if subject[-1] == '.': - fail(f'Trailing dot found in the subject of commit {commit.sha}.') + fixup_error_logged = True + if len(subject) > 72 and not subject.startswith("Merge branch "): + warn( + f"Subject line for commit {commit.sha} is too long: " + f"```{subject}``` ({len(subject)} > 72 characters)." + ) + if subject[-1] == ".": + fail(f"Trailing dot found in the subject of commit {commit.sha}.") if len(message_lines) > 1 and message_lines[1]: - fail(f'No empty line after subject for commit {commit.sha}.') - if (len(message_lines) < 3 and - 'fixup! ' not in subject and - ' CHANGES ' not in subject and - ' release note' not in subject): - warn(f'Please write a log message for commit {commit.sha}.') + fail(f"No empty line after subject for commit {commit.sha}.") + if ( + len(message_lines) < 3 + and "fixup! " not in subject + and " CHANGES " not in subject + and " release note" not in subject + ): + warn(f"Please write a log message for commit {commit.sha}.") for line in message_lines[2:]: - if (len(line) > 72 and - not line.startswith(' ') and - not re.match(r'\[[0-9]+\]', line)): + if ( + len(line) > 72 + and not line.startswith(" ") + and not re.match(r"\[[0-9]+\]", line) + ): warn( - f'Line too long in log message for commit {commit.sha}: ' - f'```{line}``` ({len(line)} > 72 characters).' + f"Line too long in log message for commit {commit.sha}: " + f"```{line}``` ({len(line)} > 72 characters)." ) ############################################################################### @@ -111,7 +123,7 @@ for commit in danger.git.commits: # FAIL if the merge request is not assigned to any milestone. if not danger.gitlab.mr.milestone: - fail('Please assign this merge request to a milestone.') + fail("Please assign this merge request to a milestone.") ############################################################################### # VERSION LABELS @@ -129,15 +141,19 @@ if not danger.gitlab.mr.milestone: # request is not a backport, version labels are used for indicating # backporting preferences.) -backport_label_set = 'Backport' in mr_labels -version_labels = [l for l in mr_labels if l.startswith('v9.')] +backport_label_set = "Backport" in mr_labels +version_labels = [l for l in mr_labels if l.startswith("v9.")] if backport_label_set and len(version_labels) != 1: - fail('The *Backport* label is set for this merge request. ' - 'Please also set exactly one version label (*v9.x*).') + fail( + "The *Backport* label is set for this merge request. " + "Please also set exactly one version label (*v9.x*)." + ) if not backport_label_set and not version_labels: - fail('If this merge request is a backport, set the *Backport* label and ' - 'a single version label (*v9.x*) indicating the target branch. ' - 'If not, set version labels for all targeted backport branches.') + fail( + "If this merge request is a backport, set the *Backport* label and " + "a single version label (*v9.x*) indicating the target branch. " + "If not, set version labels for all targeted backport branches." + ) ############################################################################### # OTHER LABELS @@ -151,12 +167,16 @@ if not backport_label_set and not version_labels: # remind developers about the need to set the latter on merge requests which # passed review.) -if 'Review' not in mr_labels: - warn('This merge request does not have the *Review* label set. ' - 'Please set it if you would like the merge request to be reviewed.') -elif 'LGTM (Merge OK)' not in mr_labels: - warn('This merge request is currently in review. ' - 'It should not be merged until it is marked with the *LGTM* label.') +if "Review" not in mr_labels: + warn( + "This merge request does not have the *Review* label set. " + "Please set it if you would like the merge request to be reviewed." + ) +elif "LGTM (Merge OK)" not in mr_labels: + warn( + "This merge request is currently in review. " + "It should not be merged until it is marked with the *LGTM* label." + ) ############################################################################### # 'CHANGES' FILE @@ -178,25 +198,31 @@ elif 'LGTM (Merge OK)' not in mr_labels: # * The merge request adds a new CHANGES entry that is not a placeholder and # does not contain any GitLab/RT issue/MR identifiers. -changes_modified = 'CHANGES' in modified_files -no_changes_label_set = 'No CHANGES' in mr_labels +changes_modified = "CHANGES" in modified_files +no_changes_label_set = "No CHANGES" in mr_labels if not changes_modified and not no_changes_label_set: - fail('This merge request does not modify `CHANGES`. ' - 'Add a `CHANGES` entry or set the *No CHANGES* label.') + fail( + "This merge request does not modify `CHANGES`. " + "Add a `CHANGES` entry or set the *No CHANGES* label." + ) if changes_modified and no_changes_label_set: - fail('This merge request modifies `CHANGES`. ' - 'Revert `CHANGES` modifications or unset the *No Changes* label.') + fail( + "This merge request modifies `CHANGES`. " + "Revert `CHANGES` modifications or unset the *No Changes* label." + ) -changes_added_lines = added_lines(target_branch, ['CHANGES']) -placeholders_added = lines_containing(changes_added_lines, '[placeholder]') +changes_added_lines = added_lines(target_branch, ["CHANGES"]) +placeholders_added = lines_containing(changes_added_lines, "[placeholder]") identifiers_found = filter(changes_issue_or_mr_id_regex.search, changes_added_lines) if changes_added_lines: if placeholders_added: - if target_branch != 'main': - fail('This MR adds at least one placeholder entry to `CHANGES`. ' - 'It should be targeting the `main` branch.') + if target_branch != "main": + fail( + "This MR adds at least one placeholder entry to `CHANGES`. " + "It should be targeting the `main` branch." + ) elif not any(identifiers_found): - fail('No valid issue/MR identifiers found in added `CHANGES` entries.') + fail("No valid issue/MR identifiers found in added `CHANGES` entries.") ############################################################################### # RELEASE NOTES @@ -221,25 +247,31 @@ if changes_added_lines: # identifiers are found in the lines added to the release notes by this # MR. -release_notes_regex = re.compile(r'doc/(arm|notes)/notes-.*\.(rst|xml)') +release_notes_regex = re.compile(r"doc/(arm|notes)/notes-.*\.(rst|xml)") release_notes_changed = list(filter(release_notes_regex.match, modified_files)) -release_notes_label_set = 'Release Notes' in mr_labels +release_notes_label_set = "Release Notes" in mr_labels if not release_notes_changed: if release_notes_label_set: - fail('This merge request has the *Release Notes* label set. ' - 'Add a release note or unset the *Release Notes* label.') - elif 'Customer' in mr_labels: - warn('This merge request has the *Customer* label set. ' - 'Add a release note unless the changes introduced are trivial.') + fail( + "This merge request has the *Release Notes* label set. " + "Add a release note or unset the *Release Notes* label." + ) + elif "Customer" in mr_labels: + warn( + "This merge request has the *Customer* label set. " + "Add a release note unless the changes introduced are trivial." + ) if release_notes_changed and not release_notes_label_set: - fail('This merge request modifies release notes. ' - 'Revert release note modifications or set the *Release Notes* label.') + fail( + "This merge request modifies release notes. " + "Revert release note modifications or set the *Release Notes* label." + ) if release_notes_changed: notes_added_lines = added_lines(target_branch, release_notes_changed) identifiers_found = filter(relnotes_issue_or_mr_id_regex.search, notes_added_lines) if notes_added_lines and not any(identifiers_found): - warn('No valid issue/MR identifiers found in added release notes.') + warn("No valid issue/MR identifiers found in added release notes.") else: notes_added_lines = [] @@ -251,13 +283,17 @@ else: # identifier is missing from either the added CHANGES entry or the added # release note. -if lines_containing(changes_added_lines, '[security]'): - if not lines_containing(changes_added_lines, '(CVE-20'): - fail('This merge request fixes a security issue. ' - 'Please add a CHANGES entry which includes a CVE identifier.') - if not lines_containing(notes_added_lines, 'CVE-20'): - fail('This merge request fixes a security issue. ' - 'Please add a release note which includes a CVE identifier.') +if lines_containing(changes_added_lines, "[security]"): + if not lines_containing(changes_added_lines, "(CVE-20"): + fail( + "This merge request fixes a security issue. " + "Please add a CHANGES entry which includes a CVE identifier." + ) + if not lines_containing(notes_added_lines, "CVE-20"): + fail( + "This merge request fixes a security issue. " + "Please add a release note which includes a CVE identifier." + ) ############################################################################### # PAIRWISE TESTING @@ -266,13 +302,16 @@ if lines_containing(changes_added_lines, '[security]'): # FAIL if the merge request adds any new ./configure switch without an # associated annotation used for pairwise testing. -configure_added_lines = added_lines(target_branch, ['configure.ac']) -switches_added = (lines_containing(configure_added_lines, 'AC_ARG_ENABLE') + - lines_containing(configure_added_lines, 'AC_ARG_WITH')) -annotations_added = lines_containing(configure_added_lines, '# [pairwise: ') +configure_added_lines = added_lines(target_branch, ["configure.ac"]) +switches_added = lines_containing( + configure_added_lines, "AC_ARG_ENABLE" +) + lines_containing(configure_added_lines, "AC_ARG_WITH") +annotations_added = lines_containing(configure_added_lines, "# [pairwise: ") if len(switches_added) > len(annotations_added): - fail('This merge request adds at least one new `./configure` switch that ' - 'is not annotated for pairwise testing purposes.') + fail( + "This merge request adds at least one new `./configure` switch that " + "is not annotated for pairwise testing purposes." + ) ############################################################################### # USER-VISIBLE LOG LEVELS @@ -281,16 +320,18 @@ if len(switches_added) > len(annotations_added): # WARN if the merge request adds new user-visible log messages (INFO or above) user_visible_log_levels = [ - 'ISC_LOG_INFO', - 'ISC_LOG_NOTICE', - 'ISC_LOG_WARNING', - 'ISC_LOG_ERROR', - 'ISC_LOG_CRITICAL', + "ISC_LOG_INFO", + "ISC_LOG_NOTICE", + "ISC_LOG_WARNING", + "ISC_LOG_ERROR", + "ISC_LOG_CRITICAL", ] -source_added_lines = added_lines(target_branch, ['*.[ch]']) +source_added_lines = added_lines(target_branch, ["*.[ch]"]) for log_level in user_visible_log_levels: - if (lines_containing(source_added_lines, log_level)): - warn('This merge request adds new user-visible log messages with ' - 'level INFO or above. Please double-check log levels and make ' - 'sure none of the messages added is a leftover debug message.') + if lines_containing(source_added_lines, log_level): + warn( + "This merge request adds new user-visible log messages with " + "level INFO or above. Please double-check log levels and make " + "sure none of the messages added is a leftover debug message." + ) break diff --git a/doc/arm/conf.py b/doc/arm/conf.py index 403b6cf529..84061baae2 100644 --- a/doc/arm/conf.py +++ b/doc/arm/conf.py @@ -28,17 +28,18 @@ try: except ImportError: # pylint: disable=too-few-public-methods class ReferenceRole(roles.GenericRole): - ''' + """ The ReferenceRole class (used as a base class by GitLabRefRole below) is only defined in Sphinx >= 2.0.0. For older Sphinx versions, this stub version of the ReferenceRole class is used instead. - ''' + """ + def __init__(self): - super().__init__('', nodes.strong) + super().__init__("", nodes.strong) -GITLAB_BASE_URL = 'https://gitlab.isc.org/isc-projects/bind9/-/' +GITLAB_BASE_URL = "https://gitlab.isc.org/isc-projects/bind9/-/" # Custom Sphinx role enabling automatic hyperlinking to GitLab issues/MRs. @@ -48,25 +49,26 @@ class GitLabRefRole(ReferenceRole): super().__init__() def run(self) -> Tuple[List[Node], List[system_message]]: - gl_identifier = '[GL %s]' % self.target + gl_identifier = "[GL %s]" % self.target - target_id = 'index-%s' % self.env.new_serialno('index') - entries = [('single', 'GitLab; ' + gl_identifier, target_id, '', None)] + target_id = "index-%s" % self.env.new_serialno("index") + entries = [("single", "GitLab; " + gl_identifier, target_id, "", None)] index = addnodes.index(entries=entries) - target = nodes.target('', '', ids=[target_id]) + target = nodes.target("", "", ids=[target_id]) self.inliner.document.note_explicit_target(target) try: refuri = self.build_uri() - reference = nodes.reference('', '', internal=False, refuri=refuri, - classes=['gl']) + reference = nodes.reference( + "", "", internal=False, refuri=refuri, classes=["gl"] + ) if self.has_explicit_title: reference += nodes.strong(self.title, self.title) else: reference += nodes.strong(gl_identifier, gl_identifier) except ValueError: - error_text = 'invalid GitLab identifier %s' % self.target + error_text = "invalid GitLab identifier %s" % self.target msg = self.inliner.reporter.error(error_text, line=self.lineno) prb = self.inliner.problematic(self.rawtext, self.rawtext, msg) return [prb], [msg] @@ -74,16 +76,17 @@ class GitLabRefRole(ReferenceRole): return [index, target, reference], [] def build_uri(self): - if self.target[0] == '#': - return self.base_url + 'issues/%d' % int(self.target[1:]) - if self.target[0] == '!': - return self.base_url + 'merge_requests/%d' % int(self.target[1:]) + if self.target[0] == "#": + return self.base_url + "issues/%d" % int(self.target[1:]) + if self.target[0] == "!": + return self.base_url + "merge_requests/%d" % int(self.target[1:]) raise ValueError def setup(app): - roles.register_local_role('gl', GitLabRefRole(GITLAB_BASE_URL)) - app.add_crossref_type('iscman', 'iscman', 'pair: %s; manual page') + roles.register_local_role("gl", GitLabRefRole(GITLAB_BASE_URL)) + app.add_crossref_type("iscman", "iscman", "pair: %s; manual page") + # # Configuration file for the Sphinx documentation builder. @@ -105,23 +108,25 @@ def setup(app): # -- Project information ----------------------------------------------------- -project = 'BIND 9' +project = "BIND 9" # pylint: disable=redefined-builtin -copyright = '2022, Internet Systems Consortium' -author = 'Internet Systems Consortium' +copyright = "2022, Internet Systems Consortium" +author = "Internet Systems Consortium" m4_vars = {} -with open('../../configure.ac', encoding='utf-8') as configure_ac: +with open("../../configure.ac", encoding="utf-8") as configure_ac: for line in configure_ac: - match = re.match(r'm4_define\(\[(?Pbind_VERSION_[A-Z]+)\], (?P[^)]*)\)dnl', line) + match = re.match( + r"m4_define\(\[(?Pbind_VERSION_[A-Z]+)\], (?P[^)]*)\)dnl", line + ) if match: - m4_vars[match.group('key')] = match.group('val') + m4_vars[match.group("key")] = match.group("val") -version = '%s.%s.%s%s' % ( - m4_vars['bind_VERSION_MAJOR'], - m4_vars['bind_VERSION_MINOR'], - m4_vars['bind_VERSION_PATCH'], - m4_vars['bind_VERSION_EXTRA'], +version = "%s.%s.%s%s" % ( + m4_vars["bind_VERSION_MAJOR"], + m4_vars["bind_VERSION_MINOR"], + m4_vars["bind_VERSION_PATCH"], + m4_vars["bind_VERSION_EXTRA"], ) release = version @@ -133,43 +138,42 @@ release = version extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [ - '_build', - 'Thumbs.db', - '.DS_Store', - '*.inc.rst' - ] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "*.inc.rst"] # The master toctree document. -master_doc = 'index' +master_doc = "index" # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' -html_static_path = ['_static'] -html_css_files = [ - 'custom.css' -] +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] +html_css_files = ["custom.css"] # -- Options for EPUB output ------------------------------------------------- -epub_basename = 'Bv9ARM' +epub_basename = "Bv9ARM" # -- Options for LaTeX output ------------------------------------------------ -latex_engine = 'xelatex' +latex_engine = "xelatex" # pylint disable=line-too-long latex_documents = [ - (master_doc, 'Bv9ARM.tex', 'BIND 9 Administrator Reference Manual', author, 'manual'), - ] + ( + master_doc, + "Bv9ARM.tex", + "BIND 9 Administrator Reference Manual", + author, + "manual", + ), +] latex_logo = "isc-logo.pdf" diff --git a/doc/man/conf.py b/doc/man/conf.py index e4d4cdad63..f805e03bff 100644 --- a/doc/man/conf.py +++ b/doc/man/conf.py @@ -32,13 +32,14 @@ # -- Project information ----------------------------------------------------- -project = 'BIND 9' +project = "BIND 9" # pylint: disable=wrong-import-position import datetime + year = datetime.datetime.now().year # pylint: disable=redefined-builtin copyright = "%d, Internet Systems Consortium" % year -author = 'Internet Systems Consortium' +author = "Internet Systems Consortium" # -- General configuration --------------------------------------------------- @@ -52,56 +53,146 @@ man_make_section_directory = False extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['../arm/_templates'] +templates_path = ["../arm/_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [ - '_build', - 'Thumbs.db', - '.DS_Store', - ] + "_build", + "Thumbs.db", + ".DS_Store", +] # The master toctree document. -master_doc = 'index' +master_doc = "index" # pylint: disable=line-too-long man_pages = [ - ('arpaname', 'arpaname', 'translate IP addresses to the corresponding ARPA names', author, 1), - ('ddns-confgen', 'ddns-confgen', 'ddns key generation tool', author, 8), - ('delv', 'delv', 'DNS lookup and validation utility', author, 1), - ('dig', 'dig', 'DNS lookup utility', author, 1), - ('dnssec-cds', 'dnssec-cds', 'change DS records for a child zone based on CDS/CDNSKEY', author, 1), - ('dnssec-dsfromkey', 'dnssec-dsfromkey', 'DNSSEC DS RR generation tool', author, 1), - ('dnssec-importkey', 'dnssec-importkey', 'import DNSKEY records from external systems so they can be managed', author, 1), - ('dnssec-keyfromlabel', 'dnssec-keyfromlabel', 'DNSSEC key generation tool', author, 1), - ('dnssec-keygen', 'dnssec-keygen', 'DNSSEC key generation tool', author, 1), - ('dnssec-revoke', 'dnssec-revoke', 'set the REVOKED bit on a DNSSEC key', author, 1), - ('dnssec-settime', 'dnssec-settime', 'set the key timing metadata for a DNSSEC key', author, 1), - ('dnssec-signzone', 'dnssec-signzone', 'DNSSEC zone signing tool', author, 1), - ('dnssec-verify', 'dnssec-verify', 'DNSSEC zone verification tool', author, 1), - ('dnstap-read', 'dnstap-read', 'print dnstap data in human-readable form', author, 1), - ('filter-aaaa', 'filter-aaaa', 'filter AAAA in DNS responses when A is present', author, 8), - ('filter-a', 'filter-a', 'filter A in DNS responses when AAAA is present', author, 8), - ('host', 'host', 'DNS lookup utility', author, 1), - ('mdig', 'mdig', 'DNS pipelined lookup utility', author, 1), - ('named-checkconf', 'named-checkconf', 'named configuration file syntax checking tool', author, 1), - ('named-checkzone', 'named-checkzone', 'zone file validity checking or converting tool', author, 1), - ('named-compilezone', 'named-compilezone', 'zone file validity checking or converting tool', author, 1), - ('named-journalprint', 'named-journalprint', 'print zone journal in human-readable form', author, 1), - ('named-nzd2nzf', 'named-nzd2nzf', 'convert an NZD database to NZF text format', author, 1), - ('named-rrchecker', 'named-rrchecker', 'syntax checker for individual DNS resource records', author, 1), - ('named.conf', 'named.conf', 'configuration file for **named**', author, 5), - ('named', 'named', 'Internet domain name server', author, 8), - ('nsec3hash', 'nsec3hash', 'generate NSEC3 hash', author, 1), - ('nslookup', 'nslookup', 'query Internet name servers interactively', author, 1), - ('nsupdate', 'nsupdate', 'dynamic DNS update utility', author, 1), - ('rndc-confgen', 'rndc-confgen', 'rndc key generation tool', author, 8), - ('rndc.conf', 'rndc.conf', 'rndc configuration file', author, 5), - ('rndc', 'rndc', 'name server control utility', author, 8), - ('tsig-keygen', 'tsig-keygen', 'TSIG key generation tool', author, 8), - ] + ( + "arpaname", + "arpaname", + "translate IP addresses to the corresponding ARPA names", + author, + 1, + ), + ("ddns-confgen", "ddns-confgen", "ddns key generation tool", author, 8), + ("delv", "delv", "DNS lookup and validation utility", author, 1), + ("dig", "dig", "DNS lookup utility", author, 1), + ( + "dnssec-cds", + "dnssec-cds", + "change DS records for a child zone based on CDS/CDNSKEY", + author, + 1, + ), + ("dnssec-dsfromkey", "dnssec-dsfromkey", "DNSSEC DS RR generation tool", author, 1), + ( + "dnssec-importkey", + "dnssec-importkey", + "import DNSKEY records from external systems so they can be managed", + author, + 1, + ), + ( + "dnssec-keyfromlabel", + "dnssec-keyfromlabel", + "DNSSEC key generation tool", + author, + 1, + ), + ("dnssec-keygen", "dnssec-keygen", "DNSSEC key generation tool", author, 1), + ( + "dnssec-revoke", + "dnssec-revoke", + "set the REVOKED bit on a DNSSEC key", + author, + 1, + ), + ( + "dnssec-settime", + "dnssec-settime", + "set the key timing metadata for a DNSSEC key", + author, + 1, + ), + ("dnssec-signzone", "dnssec-signzone", "DNSSEC zone signing tool", author, 1), + ("dnssec-verify", "dnssec-verify", "DNSSEC zone verification tool", author, 1), + ( + "dnstap-read", + "dnstap-read", + "print dnstap data in human-readable form", + author, + 1, + ), + ( + "filter-aaaa", + "filter-aaaa", + "filter AAAA in DNS responses when A is present", + author, + 8, + ), + ( + "filter-a", + "filter-a", + "filter A in DNS responses when AAAA is present", + author, + 8, + ), + ("host", "host", "DNS lookup utility", author, 1), + ("mdig", "mdig", "DNS pipelined lookup utility", author, 1), + ( + "named-checkconf", + "named-checkconf", + "named configuration file syntax checking tool", + author, + 1, + ), + ( + "named-checkzone", + "named-checkzone", + "zone file validity checking or converting tool", + author, + 1, + ), + ( + "named-compilezone", + "named-compilezone", + "zone file validity checking or converting tool", + author, + 1, + ), + ( + "named-journalprint", + "named-journalprint", + "print zone journal in human-readable form", + author, + 1, + ), + ( + "named-nzd2nzf", + "named-nzd2nzf", + "convert an NZD database to NZF text format", + author, + 1, + ), + ( + "named-rrchecker", + "named-rrchecker", + "syntax checker for individual DNS resource records", + author, + 1, + ), + ("named.conf", "named.conf", "configuration file for **named**", author, 5), + ("named", "named", "Internet domain name server", author, 8), + ("nsec3hash", "nsec3hash", "generate NSEC3 hash", author, 1), + ("nslookup", "nslookup", "query Internet name servers interactively", author, 1), + ("nsupdate", "nsupdate", "dynamic DNS update utility", author, 1), + ("rndc-confgen", "rndc-confgen", "rndc key generation tool", author, 8), + ("rndc.conf", "rndc.conf", "rndc configuration file", author, 5), + ("rndc", "rndc", "name server control utility", author, 8), + ("tsig-keygen", "tsig-keygen", "TSIG key generation tool", author, 8), +] # # The rst_epilog will be completely overwritten from the Makefile, @@ -117,5 +208,6 @@ rst_epilog = """ .. |session_key| replace:: ``@runstatedir@/session.key`` """ + def setup(app): - app.add_crossref_type('iscman', 'iscman', 'pair: %s; manual page') + app.add_crossref_type("iscman", "iscman", "pair: %s; manual page") diff --git a/util/parse_tsan.py b/util/parse_tsan.py index ad4f55026c..393712a038 100755 --- a/util/parse_tsan.py +++ b/util/parse_tsan.py @@ -76,20 +76,20 @@ PATH = re.compile(TOP + "/") S = State() -with open(sys.argv[1], "r", encoding='utf-8') as f: +with open(sys.argv[1], "r", encoding="utf-8") as f: for line in f.readlines(): if line == "==================\n": if not S.inside: S.inside = True else: - DNAME = sha256(S.last_line.encode('utf-8')).hexdigest() + DNAME = sha256(S.last_line.encode("utf-8")).hexdigest() DNAME = os.path.join(OUT, DNAME) if not os.path.isdir(DNAME): os.mkdir(DNAME) - FNAME = sha256(S.block.encode('utf-8')).hexdigest() + ".txt" + FNAME = sha256(S.block.encode("utf-8")).hexdigest() + ".txt" FNAME = os.path.join(DNAME, FNAME) if not os.path.isfile(FNAME): - with open(FNAME, "w", encoding='utf-8') as w: + with open(FNAME, "w", encoding="utf-8") as w: w.write(S.block) S.reset() else: