Created
March 13, 2017 16:02
-
-
Save dhke/442a2eebe34cc152247da588920b1385 to your computer and use it in GitHub Desktop.
little script to test getaddrinfo resolver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python | |
from __future__ import print_function | |
import argparse | |
import socket | |
import six | |
def parse_args(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument( | |
'-6', '--ipv6', dest='ipv6', default=None, action='store_true', help='enable IPv6-only lookups (default=both)', | |
) | |
parser.add_argument( | |
'--no-ipv6', dest='ipv6', action='store_false', help='disable IPv6 lookups', | |
) | |
parser.add_argument( | |
'-4', '--ipv4', dest='ipv4', default=None, action='store_true', help='enable IPv4-only lookups (default=both)', | |
) | |
parser.add_argument( | |
'--no-ipv4', dest='ipv4', action='store_false', help='disable IPv4 lookups', | |
) | |
parser.add_argument( | |
'-s', '--socktype', dest='socktype', nargs=1, type=six.text_type, help='socket type (stream, dgram, ...)', | |
) | |
parser.add_argument( | |
'-p', '--proto', '--protocol', nargs=1, dest='proto', type=six.text_type, help='protocol (udp, tcp, ...)', | |
) | |
parser.add_argument('host', type=str, help='hostname to resolve') | |
parser.add_argument('port', nargs='?', type=str, help='port to resolve') | |
args = parser.parse_args() | |
return args | |
def resolve_socktype(socktype_arg): | |
sock = getattr(socket, 'SOCK_' + proto.upper(), None) | |
if not sock: | |
raise AttributeError('Unknown socket type: {}'.format(socktype_arg)) | |
return sock | |
def print_sockaddr(sockaddr, numeric=False): | |
print("ip_addr= {}".format(sockaddr[0])) | |
if numeric: | |
print("port= {}".format(sockaddr[1])) | |
else: | |
try: | |
serv = socket.getservbyport(sockaddr[1]) | |
print("serv= {} ({})".format(serv, sockaddr[1])) | |
except socket.error: | |
print("port= {}".format(sockaddr[1])) | |
if len(sockaddr) > 2: | |
print("scope= {}".format(sockaddr[2])) | |
def get_family_by_id(family): | |
for key in socket.__all__: | |
if key.startswith('AF_') and getattr(socket, key) == family: | |
return key | |
return family | |
def get_socktype_by_id(socktype): | |
for key in socket.__all__: | |
if key.startswith('SOCK_') and getattr(socket, key) == socktype: | |
return key | |
return socktype | |
def print_addr(addr, numeric=False): | |
family, socktype, proto, canonname, sockaddr = addr | |
if numeric: | |
print("family= {}".format(family)) | |
print("socktype= {}".format(socktype)) | |
else: | |
print("family= {} ({})".format(get_family_by_id(family), family)) | |
print("socktype= {} ({})".format(get_socktype_by_id(socktype), socktype)) | |
if canonname: | |
print("canonname= {}".format(canonname)) | |
print_sockaddr(sockaddr) | |
def print_addrs(addrs): | |
for i, addr in enumerate(addrs): | |
if i: | |
print('') | |
print_addr(addr) | |
def main(): | |
args = parse_args() | |
ipv4 = getattr(args, 'ipv4', None) | |
ipv6 = getattr(args, 'ipv6', None) | |
host = args.host | |
port = args.port | |
# defaults are a little weird: | |
# - when nothing is specified, you get v4 and v6 | |
# - when one of either ipv4 or ipv6 is specified, you only get addresses of that type | |
# - when both are specified, you get addresses of both types | |
# POLA violation: | |
# - when you disable both v4 and v6, you (again) get all addresses | |
# | |
# Command line switches are evaluated in order, so --ipv6 --no-ipv6 gives you ipv4 addreses only. | |
if (ipv4 or ipv4 is None) and not ipv6: | |
family = socket.AF_INET | |
elif (ipv6 or ipv6 is None) and not ipv4: | |
family = socket.AF_INET6 | |
else: | |
family = socket.AF_UNSPEC | |
if getattr(args, 'socktype', None): | |
socktype = resolve_socktype(args.socktype[0]) | |
else: | |
socktype = 0 | |
if getattr(args, 'proto', None): | |
proto = socket.getprotobyname(args.proto[0]) | |
else: | |
proto = 0 | |
addrs = socket.getaddrinfo(host, port, family, socktype, proto) | |
print_addrs(addrs) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment