gethost.c revision 193149
1135446Strhodes/*
2193149Sdougb * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 2000, 2001  Internet Software Consortium.
4135446Strhodes *
5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18193149Sdougb/* $Id: gethost.c,v 1.34 2007/06/19 23:47:22 tbox Exp $ */
19135446Strhodes
20170222Sdougb/*! \file */
21170222Sdougb
22170222Sdougb/**
23170222Sdougb *    These functions provide hostname-to-address and address-to-hostname
24170222Sdougb *    lookups by means of the lightweight resolver. They are similar to the
25170222Sdougb *    standard gethostent(3) functions provided by most operating systems.
26170222Sdougb *    They use a struct hostent which is usually defined in <namedb.h>.
27170222Sdougb *
28170222Sdougb * \code
29170222Sdougb * struct  hostent {
30170222Sdougb *         char    *h_name;        // official name of host
31170222Sdougb * 	   char    **h_aliases;    // alias list
32170222Sdougb *         int     h_addrtype;     // host address type
33170222Sdougb *         int     h_length;       // length of address
34170222Sdougb *         char    **h_addr_list;  // list of addresses from name server
35170222Sdougb * };
36170222Sdougb * #define h_addr  h_addr_list[0]  // address, for backward compatibility
37170222Sdougb * \endcode
38170222Sdougb *
39170222Sdougb *    The members of this structure are:
40170222Sdougb *
41170222Sdougb * \li   h_name:
42170222Sdougb *           The official (canonical) name of the host.
43170222Sdougb *
44170222Sdougb * \li   h_aliases:
45170222Sdougb *           A NULL-terminated array of alternate names (nicknames) for the
46170222Sdougb *           host.
47170222Sdougb *
48170222Sdougb * \li   h_addrtype:
49170222Sdougb *           The type of address being returned -- PF_INET or PF_INET6.
50170222Sdougb *
51170222Sdougb * \li   h_length:
52170222Sdougb *           The length of the address in bytes.
53170222Sdougb *
54170222Sdougb * \li   h_addr_list:
55170222Sdougb *           A NULL terminated array of network addresses for the host. Host
56170222Sdougb *           addresses are returned in network byte order.
57170222Sdougb *
58170222Sdougb *    For backward compatibility with very old software, h_addr is the first
59170222Sdougb *    address in h_addr_list.
60170222Sdougb *
61170222Sdougb *    lwres_gethostent(), lwres_sethostent(), lwres_endhostent(),
62170222Sdougb *    lwres_gethostent_r(), lwres_sethostent_r() and lwres_endhostent_r()
63170222Sdougb *    provide iteration over the known host entries on systems that provide
64170222Sdougb *    such functionality through facilities like /etc/hosts or NIS. The
65170222Sdougb *    lightweight resolver does not currently implement these functions; it
66170222Sdougb *    only provides them as stub functions that always return failure.
67170222Sdougb *
68170222Sdougb *    lwres_gethostbyname() and lwres_gethostbyname2() look up the hostname
69170222Sdougb *    name. lwres_gethostbyname() always looks for an IPv4 address while
70170222Sdougb *    lwres_gethostbyname2() looks for an address of protocol family af:
71170222Sdougb *    either PF_INET or PF_INET6 -- IPv4 or IPV6 addresses respectively.
72170222Sdougb *    Successful calls of the functions return a struct hostent for the name
73170222Sdougb *    that was looked up. NULL is returned if the lookups by
74170222Sdougb *    lwres_gethostbyname() or lwres_gethostbyname2() fail.
75170222Sdougb *
76170222Sdougb *    Reverse lookups of addresses are performed by lwres_gethostbyaddr().
77170222Sdougb *    addr is an address of length len bytes and protocol family type --
78170222Sdougb *    PF_INET or PF_INET6. lwres_gethostbyname_r() is a thread-safe function
79170222Sdougb *    for forward lookups. If an error occurs, an error code is returned in
80170222Sdougb *    *error. resbuf is a pointer to a struct hostent which is initialised
81170222Sdougb *    by a successful call to lwres_gethostbyname_r() . buf is a buffer of
82170222Sdougb *    length len bytes which is used to store the h_name, h_aliases, and
83170222Sdougb *    h_addr_list elements of the struct hostent returned in resbuf.
84170222Sdougb *    Successful calls to lwres_gethostbyname_r() return resbuf, which is a
85170222Sdougb *    pointer to the struct hostent it created.
86170222Sdougb *
87170222Sdougb *    lwres_gethostbyaddr_r() is a thread-safe function that performs a
88170222Sdougb *    reverse lookup of address addr which is len bytes long and is of
89170222Sdougb *    protocol family type -- PF_INET or PF_INET6. If an error occurs, the
90170222Sdougb *    error code is returned in *error. The other function parameters are
91170222Sdougb *    identical to those in lwres_gethostbyname_r(). resbuf is a pointer to
92170222Sdougb *    a struct hostent which is initialised by a successful call to
93170222Sdougb *    lwres_gethostbyaddr_r(). buf is a buffer of length len bytes which is
94170222Sdougb *    used to store the h_name, h_aliases, and h_addr_list elements of the
95170222Sdougb *    struct hostent returned in resbuf. Successful calls to
96170222Sdougb *    lwres_gethostbyaddr_r() return resbuf, which is a pointer to the
97170222Sdougb *    struct hostent it created.
98170222Sdougb *
99170222Sdougb * \section gethost_return Return Values
100170222Sdougb *
101170222Sdougb *    The functions lwres_gethostbyname(), lwres_gethostbyname2(),
102170222Sdougb *    lwres_gethostbyaddr(), and lwres_gethostent() return NULL to indicate
103170222Sdougb *    an error. In this case the global variable lwres_h_errno will contain
104170222Sdougb *    one of the following error codes defined in \link netdb.h <lwres/netdb.h>:\endlink
105170222Sdougb *
106170222Sdougb * \li #HOST_NOT_FOUND:
107170222Sdougb *           The host or address was not found.
108170222Sdougb *
109170222Sdougb * \li #TRY_AGAIN:
110170222Sdougb *           A recoverable error occurred, e.g., a timeout. Retrying the
111170222Sdougb *           lookup may succeed.
112170222Sdougb *
113170222Sdougb * \li #NO_RECOVERY:
114170222Sdougb *           A non-recoverable error occurred.
115170222Sdougb *
116170222Sdougb * \li #NO_DATA:
117170222Sdougb *           The name exists, but has no address information associated with
118170222Sdougb *           it (or vice versa in the case of a reverse lookup). The code
119170222Sdougb *           NO_ADDRESS is accepted as a synonym for NO_DATA for backwards
120170222Sdougb *           compatibility.
121170222Sdougb *
122170222Sdougb *    lwres_hstrerror() translates these error codes to suitable error
123170222Sdougb *    messages.
124170222Sdougb *
125170222Sdougb *    lwres_gethostent() and lwres_gethostent_r() always return NULL.
126170222Sdougb *
127170222Sdougb *    Successful calls to lwres_gethostbyname_r() and
128170222Sdougb *    lwres_gethostbyaddr_r() return resbuf, a pointer to the struct hostent
129170222Sdougb *    that was initialised by these functions. They return NULL if the
130170222Sdougb *    lookups fail or if buf was too small to hold the list of addresses and
131170222Sdougb *    names referenced by the h_name, h_aliases, and h_addr_list elements of
132170222Sdougb *    the struct hostent. If buf was too small, both lwres_gethostbyname_r()
133170222Sdougb *    and lwres_gethostbyaddr_r() set the global variable errno to ERANGE.
134170222Sdougb *
135170222Sdougb * \section gethost_see See Also
136170222Sdougb *
137170222Sdougb *    gethostent(), \link getipnode.c getipnode\endlink, lwres_hstrerror()
138170222Sdougb *
139170222Sdougb * \section gethost_bugs Bugs
140170222Sdougb *
141170222Sdougb *    lwres_gethostbyname(), lwres_gethostbyname2(), lwres_gethostbyaddr()
142170222Sdougb *    and lwres_endhostent() are not thread safe; they return pointers to
143170222Sdougb *    static data and provide error codes through a global variable.
144170222Sdougb *    Thread-safe versions for name and address lookup are provided by
145170222Sdougb *    lwres_gethostbyname_r(), and lwres_gethostbyaddr_r() respectively.
146170222Sdougb *
147170222Sdougb *    The resolver daemon does not currently support any non-DNS name
148170222Sdougb *    services such as /etc/hosts or NIS, consequently the above functions
149170222Sdougb *    don't, either.
150170222Sdougb */
151170222Sdougb
152135446Strhodes#include <config.h>
153135446Strhodes
154135446Strhodes#include <errno.h>
155135446Strhodes#include <string.h>
156135446Strhodes
157135446Strhodes#include <lwres/net.h>
158135446Strhodes#include <lwres/netdb.h>
159135446Strhodes
160135446Strhodes#include "assert_p.h"
161135446Strhodes
162135446Strhodes#define LWRES_ALIGNBYTES (sizeof(char *) - 1)
163135446Strhodes#define LWRES_ALIGN(p) \
164135446Strhodes	(((unsigned long)(p) + LWRES_ALIGNBYTES) &~ LWRES_ALIGNBYTES)
165135446Strhodes
166135446Strhodesstatic struct hostent *he = NULL;
167135446Strhodesstatic int copytobuf(struct hostent *, struct hostent *, char *, int);
168135446Strhodes
169170222Sdougb/*% Always looks for an IPv4 address. */
170135446Strhodesstruct hostent *
171135446Strhodeslwres_gethostbyname(const char *name) {
172135446Strhodes
173135446Strhodes	if (he != NULL)
174135446Strhodes		lwres_freehostent(he);
175135446Strhodes
176135446Strhodes	he = lwres_getipnodebyname(name, AF_INET, 0, &lwres_h_errno);
177135446Strhodes	return (he);
178135446Strhodes}
179135446Strhodes
180170222Sdougb/*% Looks for either an IPv4 or IPv6 address. */
181135446Strhodesstruct hostent *
182135446Strhodeslwres_gethostbyname2(const char *name, int af) {
183135446Strhodes	if (he != NULL)
184135446Strhodes		lwres_freehostent(he);
185135446Strhodes
186135446Strhodes	he = lwres_getipnodebyname(name, af, 0, &lwres_h_errno);
187135446Strhodes	return (he);
188135446Strhodes}
189135446Strhodes
190170222Sdougb/*% Reverse lookup of addresses. */
191135446Strhodesstruct hostent *
192135446Strhodeslwres_gethostbyaddr(const char *addr, int len, int type) {
193135446Strhodes
194135446Strhodes	if (he != NULL)
195135446Strhodes		lwres_freehostent(he);
196135446Strhodes
197135446Strhodes	he = lwres_getipnodebyaddr(addr, len, type, &lwres_h_errno);
198135446Strhodes	return (he);
199135446Strhodes}
200135446Strhodes
201170222Sdougb/*% Stub function.  Always returns failure. */
202135446Strhodesstruct hostent *
203135446Strhodeslwres_gethostent(void) {
204135446Strhodes	if (he != NULL)
205135446Strhodes		lwres_freehostent(he);
206135446Strhodes
207135446Strhodes	return (NULL);
208135446Strhodes}
209135446Strhodes
210170222Sdougb/*% Stub function.  Always returns failure. */
211135446Strhodesvoid
212135446Strhodeslwres_sethostent(int stayopen) {
213135446Strhodes	/*
214135446Strhodes	 * Empty.
215135446Strhodes	 */
216135446Strhodes	UNUSED(stayopen);
217135446Strhodes}
218135446Strhodes
219170222Sdougb/*% Stub function.  Always returns failure. */
220135446Strhodesvoid
221135446Strhodeslwres_endhostent(void) {
222135446Strhodes	/*
223135446Strhodes	 * Empty.
224135446Strhodes	 */
225135446Strhodes}
226135446Strhodes
227170222Sdougb/*% Thread-safe function for forward lookups. */
228135446Strhodesstruct hostent *
229135446Strhodeslwres_gethostbyname_r(const char *name, struct hostent *resbuf,
230135446Strhodes		char *buf, int buflen, int *error)
231135446Strhodes{
232135446Strhodes	struct hostent *he;
233135446Strhodes	int res;
234135446Strhodes
235135446Strhodes	he = lwres_getipnodebyname(name, AF_INET, 0, error);
236135446Strhodes	if (he == NULL)
237135446Strhodes		return (NULL);
238135446Strhodes	res = copytobuf(he, resbuf, buf, buflen);
239135446Strhodes	lwres_freehostent(he);
240135446Strhodes	if (res != 0) {
241135446Strhodes		errno = ERANGE;
242135446Strhodes		return (NULL);
243135446Strhodes	}
244135446Strhodes	return (resbuf);
245135446Strhodes}
246135446Strhodes
247170222Sdougb/*% Thread-safe reverse lookup. */
248135446Strhodesstruct hostent  *
249135446Strhodeslwres_gethostbyaddr_r(const char *addr, int len, int type,
250135446Strhodes		      struct hostent *resbuf, char *buf, int buflen,
251135446Strhodes		      int *error)
252135446Strhodes{
253135446Strhodes	struct hostent *he;
254135446Strhodes	int res;
255135446Strhodes
256135446Strhodes	he = lwres_getipnodebyaddr(addr, len, type, error);
257135446Strhodes	if (he == NULL)
258135446Strhodes		return (NULL);
259135446Strhodes	res = copytobuf(he, resbuf, buf, buflen);
260135446Strhodes	lwres_freehostent(he);
261135446Strhodes	if (res != 0) {
262135446Strhodes		errno = ERANGE;
263135446Strhodes		return (NULL);
264135446Strhodes	}
265135446Strhodes	return (resbuf);
266135446Strhodes}
267135446Strhodes
268170222Sdougb/*% Stub function.  Always returns failure. */
269135446Strhodesstruct hostent  *
270135446Strhodeslwres_gethostent_r(struct hostent *resbuf, char *buf, int buflen, int *error) {
271135446Strhodes	UNUSED(resbuf);
272135446Strhodes	UNUSED(buf);
273135446Strhodes	UNUSED(buflen);
274135446Strhodes	*error = 0;
275135446Strhodes	return (NULL);
276135446Strhodes}
277135446Strhodes
278170222Sdougb/*% Stub function.  Always returns failure. */
279135446Strhodesvoid
280135446Strhodeslwres_sethostent_r(int stayopen) {
281135446Strhodes	/*
282135446Strhodes	 * Empty.
283135446Strhodes	 */
284135446Strhodes	UNUSED(stayopen);
285135446Strhodes}
286135446Strhodes
287170222Sdougb/*% Stub function.  Always returns failure. */
288135446Strhodesvoid
289135446Strhodeslwres_endhostent_r(void) {
290135446Strhodes	/*
291135446Strhodes	 * Empty.
292135446Strhodes	 */
293135446Strhodes}
294135446Strhodes
295135446Strhodesstatic int
296135446Strhodescopytobuf(struct hostent *he, struct hostent *hptr, char *buf, int buflen) {
297135446Strhodes        char *cp;
298135446Strhodes        char **ptr;
299135446Strhodes        int i, n;
300135446Strhodes        int nptr, len;
301135446Strhodes
302135446Strhodes        /*
303135446Strhodes	 * Find out the amount of space required to store the answer.
304135446Strhodes	 */
305135446Strhodes        nptr = 2; /* NULL ptrs */
306135446Strhodes        len = (char *)LWRES_ALIGN(buf) - buf;
307135446Strhodes        for (i = 0; he->h_addr_list[i]; i++, nptr++) {
308135446Strhodes                len += he->h_length;
309135446Strhodes        }
310135446Strhodes        for (i = 0; he->h_aliases[i]; i++, nptr++) {
311135446Strhodes                len += strlen(he->h_aliases[i]) + 1;
312135446Strhodes        }
313135446Strhodes        len += strlen(he->h_name) + 1;
314135446Strhodes        len += nptr * sizeof(char*);
315135446Strhodes
316135446Strhodes        if (len > buflen) {
317135446Strhodes                return (-1);
318135446Strhodes        }
319135446Strhodes
320135446Strhodes        /*
321135446Strhodes	 * Copy address size and type.
322135446Strhodes	 */
323135446Strhodes        hptr->h_addrtype = he->h_addrtype;
324135446Strhodes        n = hptr->h_length = he->h_length;
325135446Strhodes
326135446Strhodes        ptr = (char **)LWRES_ALIGN(buf);
327135446Strhodes        cp = (char *)LWRES_ALIGN(buf) + nptr * sizeof(char *);
328135446Strhodes
329135446Strhodes        /*
330135446Strhodes	 * Copy address list.
331135446Strhodes	 */
332135446Strhodes        hptr->h_addr_list = ptr;
333135446Strhodes        for (i = 0; he->h_addr_list[i]; i++, ptr++) {
334135446Strhodes                memcpy(cp, he->h_addr_list[i], n);
335135446Strhodes                hptr->h_addr_list[i] = cp;
336135446Strhodes                cp += n;
337135446Strhodes        }
338135446Strhodes        hptr->h_addr_list[i] = NULL;
339135446Strhodes        ptr++;
340135446Strhodes
341135446Strhodes        /*
342135446Strhodes	 * Copy official name.
343135446Strhodes	 */
344135446Strhodes        n = strlen(he->h_name) + 1;
345135446Strhodes        strcpy(cp, he->h_name);
346135446Strhodes        hptr->h_name = cp;
347135446Strhodes        cp += n;
348135446Strhodes
349135446Strhodes        /*
350135446Strhodes	 * Copy aliases.
351135446Strhodes	 */
352135446Strhodes        hptr->h_aliases = ptr;
353135446Strhodes        for (i = 0; he->h_aliases[i]; i++) {
354135446Strhodes                n = strlen(he->h_aliases[i]) + 1;
355135446Strhodes                strcpy(cp, he->h_aliases[i]);
356135446Strhodes                hptr->h_aliases[i] = cp;
357135446Strhodes                cp += n;
358135446Strhodes        }
359135446Strhodes        hptr->h_aliases[i] = NULL;
360135446Strhodes
361135446Strhodes        return (0);
362135446Strhodes}
363