1 | """Usage: python3 check_test_ips.py IP|HOSTNAME [...] |
---|
2 | |
---|
3 | Check if the given IPs, or IPs associated with given hostnames, are |
---|
4 | routable. Under the assumption that those IPs are local a positive |
---|
5 | result means they should be usable for tests. |
---|
6 | |
---|
7 | The script prints the first two (in order of arguments) usable |
---|
8 | addresses to sys.stdout. IPv6 addresses in the output are enclosed in |
---|
9 | square brackets. |
---|
10 | |
---|
11 | """ |
---|
12 | import socket |
---|
13 | import sys |
---|
14 | |
---|
15 | |
---|
16 | def try_connect(sockaddr): |
---|
17 | """Try to connect a UDP socket to the given address. "Connecting" a |
---|
18 | UDP socket means only setting the default destination for packets, |
---|
19 | so nothing is actually sent. Return True if the socket.connect() |
---|
20 | call was successful, False otherwise. |
---|
21 | |
---|
22 | For loopback this effectively tests if the address is really |
---|
23 | configured, to detect e.g. situations where a system may have "::1 |
---|
24 | localhost" in /etc/hosts, but actually has IPv6 disabled. |
---|
25 | |
---|
26 | """ |
---|
27 | af, socktype, proto, canonname, sa = sockaddr |
---|
28 | try: |
---|
29 | s = socket.socket(af, socktype, proto) |
---|
30 | s.connect(sa) |
---|
31 | except: |
---|
32 | return False |
---|
33 | finally: |
---|
34 | s.close() |
---|
35 | return True |
---|
36 | |
---|
37 | |
---|
38 | if __name__ == "__main__": |
---|
39 | import argparse |
---|
40 | parser = argparse.ArgumentParser( |
---|
41 | description='Check if IPs/hostnames are routable') |
---|
42 | parser.add_argument('hosts', metavar='HOST', nargs='+', |
---|
43 | help='the hostnames/IPs to check') |
---|
44 | parser.add_argument('--quiet', '-q', action='store_true', |
---|
45 | help='disable debug output') |
---|
46 | args = parser.parse_args() |
---|
47 | |
---|
48 | test_ips = [] |
---|
49 | for name in args.hosts: |
---|
50 | addrs = list(map(lambda t: t[-1][0], |
---|
51 | filter(try_connect, |
---|
52 | socket.getaddrinfo(name, 12345, |
---|
53 | proto=socket.IPPROTO_UDP)))) |
---|
54 | if not args.quiet: |
---|
55 | print(f'{name}: {addrs}', file=sys.stderr) |
---|
56 | test_ips += addrs |
---|
57 | |
---|
58 | print(' '.join(f'[{i}]' if ':' in i else i for i in test_ips[:2])) |
---|