1/*	$NetBSD: gethost.c,v 1.12 2013/12/21 20:10:02 christos Exp $	*/
2
3/*-
4 * Copyright (c) 1985, 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 * -
31 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
32 *
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies, and that
36 * the name of Digital Equipment Corporation not be used in advertising or
37 * publicity pertaining to distribution of the document or software without
38 * specific, written prior permission.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
43 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 * SOFTWARE.
48 * -
49 * --Copyright--
50 */
51
52/* Provide just /etc/hosts lookup support */
53
54#include <sys/cdefs.h>
55
56#ifdef __weak_alias
57#define gethostbyaddr		_gethostbyaddr
58#define gethostbyname		_gethostbyname
59#endif
60
61#include <netdb.h>
62#include <string.h>
63#include <nsswitch.h>
64#include <errno.h>
65#include <arpa/nameser.h>
66#include <arpa/inet.h>
67#include <sys/socket.h>
68
69#include "hostent.h"
70
71#ifdef __weak_alias
72__weak_alias(gethostbyaddr,_gethostbyaddr);
73__weak_alias(gethostbyname,_gethostbyname);
74#endif
75
76int h_errno;
77FILE *_h_file;
78static struct hostent h_ent;
79static char h_buf[4096];
80
81static struct hostent *
82getby(int (*f)(void *, void *, va_list), struct getnamaddr *info, ...)
83{
84        va_list ap;
85        int e;
86
87        va_start(ap, info);
88        e = (*f)(info, NULL, ap);
89        va_end(ap);
90        switch (e) {
91        case NS_SUCCESS:
92                return info->hp;
93        default:
94		return NULL;
95        }
96}
97
98struct hostent *
99gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t bufsiz,
100    int *he)
101{
102	struct getnamaddr info;
103	info.hp = hp;
104	info.buf = buf;
105	info.buflen = bufsiz;
106	info.he = he;
107	return getby(_hf_gethtbyname, &info, name, 0, AF_INET);
108}
109
110
111struct hostent *
112gethostbyname(const char *name)
113{
114	return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
115}
116
117struct hostent *
118gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *hp,
119    char *buf, size_t bufsiz, int *he)
120{
121	struct getnamaddr info;
122	info.hp = hp;
123	info.buf = buf;
124	info.buflen = bufsiz;
125	info.he = he;
126	return getby(_hf_gethtbyaddr, &info, addr, len, type);
127}
128
129struct hostent *
130gethostbyaddr(const void *addr, socklen_t len, int type)
131{
132	return gethostbyaddr_r(addr, len, type, &h_ent, h_buf, sizeof(h_buf),
133	    &h_errno);
134}
135
136struct hostent *
137gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
138{
139	char *p, *name;
140	char *cp, **q;
141	int af, len;
142	size_t llen, anum;
143	char *aliases[MAXALIASES];
144	struct in6_addr host_addr;
145
146	if (hf == NULL) {
147		*he = NETDB_INTERNAL;
148		errno = EINVAL;
149		return NULL;
150	}
151 again:
152	if ((p = fgetln(hf, &llen)) == NULL) {
153		*he = HOST_NOT_FOUND;
154		return NULL;
155	}
156	if (llen < 1)
157		goto again;
158	if (*p == '#')
159		goto again;
160	p[llen] = '\0';
161	if (!(cp = strpbrk(p, "#\n")))
162		goto again;
163	*cp = '\0';
164	if (!(cp = strpbrk(p, " \t")))
165		goto again;
166	*cp++ = '\0';
167	if (inet_pton(AF_INET6, p, &host_addr) > 0) {
168		af = AF_INET6;
169		len = NS_IN6ADDRSZ;
170	} else if (inet_pton(AF_INET, p, &host_addr) > 0) {
171#if 0
172		res_state res = __res_get_state();
173		if (res == NULL)
174			return NULL;
175		if (res->options & RES_USE_INET6) {
176			map_v4v6_address(buf, buf);
177			af = AF_INET6;
178			len = NS_IN6ADDRSZ;
179		} else {
180#endif
181			af = AF_INET;
182			len = NS_INADDRSZ;
183#if 0
184		}
185		__res_put_state(res);
186#endif
187	} else {
188		goto again;
189	}
190	/* if this is not something we're looking for, skip it. */
191	if (hent->h_addrtype != 0 && hent->h_addrtype != af)
192		goto again;
193	if (hent->h_length != 0 && hent->h_length != len)
194		goto again;
195
196	while (*cp == ' ' || *cp == '\t')
197		cp++;
198	if ((cp = strpbrk(name = cp, " \t")) != NULL)
199		*cp++ = '\0';
200	q = aliases;
201	while (cp && *cp) {
202		if (*cp == ' ' || *cp == '\t') {
203			cp++;
204			continue;
205		}
206		if (q >= &aliases[__arraycount(aliases)])
207			goto nospc;
208		*q++ = cp;
209		if ((cp = strpbrk(cp, " \t")) != NULL)
210			*cp++ = '\0';
211	}
212	hent->h_length = len;
213	hent->h_addrtype = af;
214	HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
215	anum = (size_t)(q - aliases);
216	HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
217	HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
218	    buflen);
219	hent->h_addr_list[1] = NULL;
220
221	HENT_SCOPY(hent->h_name, name, buf, buflen);
222	for (size_t i = 0; i < anum; i++)
223		HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
224	hent->h_aliases[anum] = NULL;
225
226	*he = NETDB_SUCCESS;
227	return hent;
228nospc:
229	errno = ENOSPC;
230	*he = NETDB_INTERNAL;
231	return NULL;
232}
233