#!/usr/bin/env python # # This file is a part of DNSViz, a tool suite for DNS/DNSSEC monitoring, # analysis, and visualization. # Created by Casey Deccio (casey@deccio.net) # # Copyright 2015-2016 VeriSign, Inc. # # Copyright 2016-2021 Casey Deccio # # DNSViz is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # DNSViz is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with DNSViz. If not, see . # from __future__ import unicode_literals import getopt import importlib import logging import os import sys CMD_DIR1 = 'dnsviz' CMD_DIR2 = 'commands' logging.basicConfig(level=logging.WARNING, format='%(message)s') logger = logging.getLogger() def check_deps(): # check dnspython dependency try: import dns.name except ImportError: sys.stderr.write('Error: dnspython does not appear to be installed\n') sys.exit(1) def usage(err=None): if err is not None: err += '\n\n' else: err = '' sys.stderr.write('''%sUsage: dnsviz [options] [args] Options: -p - Add path to the python path. Commands: probe - Issue diagnostic DNS queries. grok - Assess diagnostic DNS queries. graph - Graph the assessment of diagnostic DNS queries. print - Process diagnostic DNS queries to textual output. query - Assess a DNS query. help [] - Show usage for a command. ''' % (err)) def main(): check_deps() try: opts, args = getopt.getopt(sys.argv[1:], 'p:') except getopt.GetoptError as e: usage(str(e) + '\n') sys.exit(1) opts = dict(opts) if len(args) < 1: usage() sys.exit(0) if args[0] == 'help': if len(args) < 2: usage() sys.exit(0) command = args[1] else: command = args[0] if '-p' in opts: sys.path.insert(0, opts['-p']) # first try importing just the commands module to make sure # dnsviz is properly reachable with the current path importlib.import_module('%s.%s' % (CMD_DIR1, CMD_DIR2)) # now try importing the module for the actual command try: mod = importlib.import_module('%s.%s.%s' % (CMD_DIR1, CMD_DIR2, command)) except ImportError: # See if the filename corresponding to the module we were trying to # import was found in the stack. If so, then the error is with # importing something from inside that file. Otherwise, it was that we # couldn't find the file corresponding to the command, so it was thus # an illegitmate command. exc_frame = sys.exc_info()[2] frame1 = exc_frame.tb_next.tb_next found_file = False while frame1 is not None: filename = frame1.tb_frame.f_code.co_filename cmd_dir2, filename = os.path.split(filename) if filename.endswith('.py'): filename = filename[:-3] cmd_dir1, cmd_dir2 = os.path.split(cmd_dir2) cmd_dir0, cmd_dir1 = os.path.split(cmd_dir1) if cmd_dir1 == CMD_DIR1 and \ cmd_dir2 == CMD_DIR2 and \ filename == command: found_file = True break frame1 = frame1.tb_next if found_file: raise else: sys.stderr.write('Invalid command: %s\n' % command) sys.exit(1) if args[0] == 'help': helper = mod.build_helper(logger, sys.argv[0], command) helper.parser.print_help() else: mod.main(args) if __name__ == "__main__": main()