printresults.py 3.75 KB
Newer Older
Petr Špaček's avatar
Petr Špaček committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#!/usr/bin/python3
"""
print list of new "dead" domains + their NSes
i.e. list of domains which will break after 2019 EDNS Flag Day
"""

import argparse
import logging
import pickle
import sys
from typing import Dict, Set

import dns.name

from evalzone import EDNSResult

def print_domain(mode: str, result: EDNSResult, domain: dns.name.Name,
    nsset: Set[dns.name.Name], reason) \
    -> None:
    if not nsset:
        print(mode, result, domain, ';', reason)
    else:
        for nsname in nsset:
            print(mode, result, domain, nsname, ';', reason)

def new_domains(permissive, strict,
    args, domain2ns: Dict[dns.name.Name, dns.name.Name]) -> None:
    logging.info('computing domains with NS which are going to stop working')
    edns_broken_domains = set(strict[EDNSResult.dead].keys()) \
            - set(permissive[EDNSResult.dead].keys())
    for domain in edns_broken_domains:
        nsset = args.ns and domain2ns[domain]
        print_domain('strict', EDNSResult.dead, domain, nsset, strict[EDNSResult.dead][domain])

def print_all(permissive, strict, args, domain2ns) -> None:
    if not args.mode:
        modes = {'permissive': permissive,
                 'strict': strict}
    else:
        modes = {args.mode: locals()[args.mode]}

    if not args.result:
        args.result = EDNSResult
    else:
        # workaround for non-functional argparse choices=Enum
        args.result = (getattr(EDNSResult, args.result), )

    for modename, modedata in modes.items():
        for result in args.result:
            for domain, reason in modedata[result].items():
                nsset = args.ns and domain2ns[domain]
                print_domain(modename, result, domain, nsset, reason)

def main():
    """
    compute stats and print them to stdout
    """
    parser = argparse.ArgumentParser(description='''
print test result for each domain in format:
<mode> <result> <domain name> [ns name] ; commentary
''')
    subparsers = parser.add_subparsers(dest='cmd')

    allcmd = subparsers.add_parser('all', help='list results for all domains (see list --help)')
    allcmd.add_argument('mode', nargs='?', choices=['permissive', 'strict'],
                         help='limit listing to specified mode')
    # workaround for non-functional argparse choices=Enum
    allcmd.add_argument('result', nargs='?', choices=EDNSResult.__members__,
                         help='limit listing to specified result category')
    allcmd.add_argument('--ns', action='store_true', default=False,
                         help='print NS for each domain')
    allcmd.set_defaults(func=print_all)

    newcmd = subparsers.add_parser('new',
        help='list only domains which will die after 2019 DNS flag day')
    newcmd.add_argument('--ns', action='store_true', default=False,
                        help='print NS for each domain')
    newcmd.set_defaults(func=new_domains)
    args = parser.parse_args()
    # parser.add_subparsers() call is missing required= option in Python 3.6
    if not args.cmd:
        sys.exit('subcommand required, see --help for usage')


    # this can be optimized but it is probably not worth the effort
    logging.info('loading permissive mode results')
    with open('results_permissive.pickle', 'rb') as pickle_bin:
        permissive = pickle.load(pickle_bin)
    logging.info('loading strict mode results')
    with open('results_strict.pickle', 'rb') as pickle_bin:
        strict = pickle.load(pickle_bin)

    if args.ns:
        logging.info('loading NS sets')
        with open('domain2nsset.pickle', 'rb') as pickle_bin:
            domain2ns = pickle.load(pickle_bin)
    else:
        domain2ns = None

    args.func(permissive, strict, args, domain2ns)

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(message)s')
    main()