diff --git a/check_ping_multiaddr.py b/check_ping_multiaddr.py index e533c12f078d4ef362616f3b0d11710ede810949..ca7460315d99d884801403663a8e0d4cc9e26cd4 100755 --- a/check_ping_multiaddr.py +++ b/check_ping_multiaddr.py @@ -56,6 +56,9 @@ class Options(optparse.OptionParser): help=("Check all addresses each hostname resolves to." " By default, only the first address for each host is" " checked.")) + self.add_option( + '-d', '--debug', action='count', default=0, + help=("Increase debug level [default: %default].")) def get_version(self): progname = self.get_prog_name() @@ -88,11 +91,70 @@ def fail(status, fmt, *args): raise ProgramFailure(status=status, msg=msg) +def chatter(level, fmt, *args, **kwargs): + if level <= OPTIONS.debug: + msg = fmt % (kwargs or args) + sys.stderr.write("#" + " " * level + msg + "\n") + + +def eai_errno_to_symbol(errno): + for symbol in dir(socket): + if symbol.startswith('EAI_') and getattr(socket, symbol) == errno: + return symbol + return + + + +def collect_addresses(hosts, all_addresses, do_v4, do_v6): + if do_v4 and do_v6: + ipfamily = socket.AF_UNSPEC ; ipversion = None + elif do_v4: + ipfamily = socket.AF_INET ; ipversion = 4 + elif do_v6: + ipfamily = socket.AF_INET6 ; ipversion = 6 + else: + raise ValueError("Neither IPv4 nor IPv6 selected") + + lookupflags = 0 + lookupflags |= getattr(socket, 'AI_IDN', 0) + + addresses = { 4: set(), 6: set() } + for host in hosts: + # Try it as a numerical IP address first + try: + addr = ipaddr.IPAddress(host, ipversion) + except ValueError: + pass + else: + addresses[addr.version].add(addr) + continue + + # And if that failed, try resolving the name + try: + ipres = socket.getaddrinfo(host, None, ipfamily, 0, 0, lookupflags) + except socket.gaierror as e: + fail(os.EX_NOHOST, "%s, %s", e.strerror, host) + for ai in ipres: + ipfam = ai[0] ; ip = ai[4][0] + addr = ipaddr.IPAddress(ip) + addresses[addr.version].add(addr) + if not all_addresses: + break + + return addresses + + def main(argv): global OPTIONS OPTIONS, arg_addresses = Options().parse_args(argv[1:]) + addresses = collect_addresses( + arg_addresses, OPTIONS.all_addresses, OPTIONS.ipv4, OPTIONS.ipv6) + + for ipver,addrs in addresses.items(): + chatter(2, "IPv%d addresses: %s", ipver, " ".join(map(str, addrs))) + ping_statuses = { 'UNKNOWN': [ 'check_ping_multiaddr not yet implemented' ], }