#!/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()