Recipe 18.1 Simple DNS Lookups

18.1.1 Problem

You
want to find the IP address of a host or turn an IP address into a
name. Network servers do this to authenticate their clients, and
clients do it when the user gives them a hostname. But Perl's socket
library requires an IP address. Furthermore, many servers produce log
files containing IP addresses, but hostnames are more useful to
analysis software and humans.

18.1.2 Solution

If you have a name like www.perl.com, use
gethostbyname if you want all
addresses:

18.1.3 Discussion

This process is complicated because the functions are mere wrappers
for C system calls, so you have to convert IP addresses from ASCII
strings ("208.146.240.1") into C structures. The
standard Socket module provides inet_aton to
convert from ASCII to the packed numeric format and
inet_ntoa to convert back:

The gethostbyname function takes a string
containing the hostname (or IP address). In scalar context, it
returns the remote IP address suitable for passing to
inet_ntoa (or undef on error).
In list context, it returns a list of at least five elements (or an
empty list on error). The returned list is:

Index

Meaning

0

Official name of host

1

Aliases (space-separated string)

2

Address type (normally AF_INET)

3

Length of address structure (irrelevant)

4,5, ...

Address structures

A hostname may have more than one address, as often seen for busy web
sites where many machines serve identical web pages to share the
load. In such situations, the DNS server that provides addresses
rotates them to balance the load. If you need to pick an IP address
to connect to, just select the first. But if it doesn't work, try the
rest as well.

If you're using hostnames to permit or deny access to a service, be
careful. Anyone can set their DNS server to identify their machine as
www.whitehouse.gov,
www.yahoo.com, or
this.is.not.funny. You can't know whether the
machine really has the name it claims to have until you use
gethostbyname and check that the original address
is in the address list for the name.

It turns out that even with this algorithm, you can't be absolutely
sure of the name due to a variety of mechanisms that can circumvent
this technique. Even the IP address from which packets appear to be
coming can be spoofed, so you should never rely on the network layer
for authentication. Always do authentication yourself (with passwords
or cryptographic challenges) when it matters, because the IPv4
network was not designed to provide security.

More information is kept about a host than just addresses and
aliases. To access this information, use the Net::DNS module from
CPAN. For instance, Example 18-1 shows how to
retrieve the MX (mail exchange) records for an arbitrary
host.

The inet_aton function takes a string containing a
hostname or IP address, as does gethostbyname, but
it returns only the first IP address for the host. To find them all,
you'll need to add more code. The Net::hostent module provides
by-name access for that; Example 18-2 shows an
example of its use.

18.1.4 See Also

The gethostbyname and
gethostbyaddr functions in Chapter 29 of
Programming Perl and in
perlfunc(1); the documentation for the Net::DNS
module from CPAN; the documentation for the standard Socket and
Net::hostent modules