Using socket.getaddrinfo to look up IP addresses
As sort of promised in the last entry, here's
the Python code to look up IPv4 and IPv6 addresses for a host, using
getaddrinfo(). As usual, this is condensed for WanderingThoughts
and omits a modicum of error checking.
import socket
def gethostips(host, type=None):
ips = set()
if type:
types = (type,)
else:
types = (socket.AF_INET,
socket.AF_INET6)
for t in types:
try:
res = socket.getaddrinfo(host, None,
t, socket.SOCK_STREAM)
except socket.error:
continue
nips = set([x[4][0] for x in res])
ips.update(nips)
return list(ips)
Passed just the hostname, it returns both IPv4 and IPv6 addresses;
passed an optional type argument, it returns just addresses of that
type. If there's nothing available, you get an empty list. Addresses are
returned in some arbitrary order that mixes IPv4 and IPv6 addresses;
I'm going to call this a feature, although in real code I might be
tempted to change it so that all IPv4 addresses are returned either
first or last.
(Besides, if you care about pretty-printing things you want to have some
kind of sorting function that puts IP addresses in ascending order.)
This isn't what you want for making connections; instead, this is the
kind of utility function that you need when verifying the hostnames of
IP addresses, when some of the IP addresses
you're dealing with are now IPv6 addresses because you've started to
IPv6-enable your programs. This intended use is one reason why it
returns an empty list if getaddrinfo() returns nothing instead of
raising an exception.
(Note that a really good IPv6 hostname lookup function is more
complicated than the IPv4 version; done properly, it should convert
IPv4 compatible and IPv4 mapped addresses
into IPv4 addresses and do an IPv4 hostname lookup for them.)