11.3 gethostbyname
Function
Host computers are normally known by
human-readable names. All the examples that we have shown so far in
this book have intentionally used IP addresses instead of names, so
we know exactly what goes into the socket address structures for
functions such as connect and sendto, and what is
returned by functions such as accept and
recvfrom. But, most applications should deal with names,
not addresses. This is especially true as we move to IPv6, since
IPv6 addresses (hex strings) are much longer than IPv4
dotted-decimal numbers. (The example AAAA record and
ip6.arpa PTR record in the previous section should make
this obvious.)
The most basic function that looks up a hostname
is gethostbyname. If successful, it returns a pointer to a
hostent structure that contains all the IPv4 addresses for
the host. However, it is limited in that it can only return IPv4
addresses. See Section 11.6 for a
function that handles both IPv4 and IPv6 addresses. The POSIX
specification cautions that gethostbyname may be withdrawn
in a future version of the spec.
It is unlikely that gethostbyname
implementations will actually disappear until the whole Internet is
using IPv6, which will be far in the future. However, withdrawing
the function from the POSIX specification is a way to assert that
it should not be used in new code. We encourage the use of
getaddrinfo (Section 11.6) in
new programs.
#include <netdb.h>
|
struct hostent *gethostbyname (const char
*hostname);
|
Returns: non-null pointer if OK,NULL on
error with h_errno set
|
The non-null pointer returned by this function
points to the following hostent structure:
struct hostent {
char *h_name; /* official (canonical) name of host */
char **h_aliases; /* pointer to array of pointers to alias names */
int h_addrtype; /* host address type: AF_INET */
int h_length; /* length of address: 4 */
char **h_addr_list; /* ptr to array of ptrs with IPv4 addrs */
};
In terms of the DNS, gethostbyname
performs a query for an A record. This function can return only
IPv4 addresses.
Figure
11.2 shows the arrangement of the hostent structure
and the information that it points to assuming the hostname that is
looked up has two alias names and three IPv4 addresses. Of these
fields, the official hostname and all the aliases are
null-terminated C strings.
The returned h_name is called the
canonical name of the host. For
example, given the CNAME records shown in the previous section, the
canonical name of the host ftp.unpbook.com would be
linux.unpbook.com. Also, if we call gethostbyname
from the host aix with an unqualified hostname, say
solaris, the FQDN (solaris.unpbook.com) is
returned as the canonical name.
Some versions of gethostbyname allow
the hostname argument to be a
dotted-decimal string. That is, a call of the form
hptr = gethostbyname ("192.168.42.2");
will work. This code was added because the
Rlogin client accepts only a hostname, calling
gethostbyname, and will not accept a dotted-decimal string
[Vixie 1996]. The POSIX specification permits, but does not
require, this behavior, so a portable application cannot depend on
it.
gethostbyname differs from the other
socket functions that we have described in that it does not set
errno when an error occurs. Instead, it sets the global
integer h_errno to one of the following constants defined
by including <netdb.h>:
The NO_DATA error means the specified
name is valid, but it does not have an A record. An example of this
is a hostname with only an MX record.
Most modern resolvers provide the function
hstrerror, which takes an h_errno value as its
only argument and returns a const char * pointer to a
description of the error. We show some examples of the strings
returned by this function in the next example.
Example
Figure
11.3 shows a simple program that calls gethostbyname
for any number of command-line arguments and prints all the
returned information.
Figure 11.3
Call gethostbyname and print returned information.
names/hostent.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 char *ptr, **pptr;
6 char str [INET_ADDRSTRLEN];
7 struct hostent *hptr;
8 while (--argc > 0) {
9 ptr = *++argv;
10 if ( (hptr = gethostbyname (ptr) ) == NULL) {
11 err_msg ("gethostbyname error for host: %s: %s",
12 ptr, hstrerror (h_errno) );
13 continue;
14 }
15 printf ("official hostname: %s\n", hptr->h_name);
16 for (pptr = hptr->h_aliases; *pptr ! = NULL; pptr++)
17 printf ("\talias: %s\n", *pptr);
18 switch (hptr->h_addrtype) {
19 case AF_INET:
20 pptr = hptr->h_addr_list;
21 for ( ; *pptr != NULL; pptr++)
22 printf ("\taddress: %s\n",
23 Inet_ntop (hptr->h_addrtype, *pptr, str, sizeof (str)));
24 break;
25 default:
26 err_ret ("unknown address type");
27 break;
28 }
29 }
30 exit(0);
31 }
8鈥?4
gethostbyname is called for each command-line
argument.
15鈥?7
The official hostname is output followed by a list of alias
names.
18鈥?4
pptr points to the array of pointers to the individual
addresses. For each address, we call inet_ntop and print
the returned string.
We first execute the program with the name of
our host aix, which has just one IPv4 address.
freebsd % hostent aix
official hostname: aix.unpbook.com
address: 192.168.42.2
Notice that the official hostname is the FQDN.
Also notice that even though this host has an IPv6 address, only
the IPv4 address is returned.
Next is a Web server with multiple IPv4
addresses.
freebsd % hostent cnn.com
official hostname: cnn.com
address: 64.236.16.20
address: 64.236.16.52
address: 64.236.16.84
address: 64.236.16.116
address: 64.236.24.4
address: 64.236.24.12
address: 64.236.24.20
address: 64.236.24.28
Next is a name that we showed in Section
11.2 as having a CNAME record.
freebsd % hostent www
official hostname: linux. unpbook. com
alias: www.unpbook.com
address: 206.168.112.219
As expected, the official hostname differs from
our command-line argument.
To see the error strings returned by the
hstrerror function, we first specify a non-existent
hostname, and then a name that has only an MX record.
freebsd % hostent nosuchname.invalid
gethostbyname error for host: nosuchname.invalid: Unknown host
freebsd % hostent uunet.uu.net
gethostbyname error for host: uunet.uu.net: No address associated with name
|