13070Spst/*-
23070Spst * Copyright (c) 1985, 1988, 1993
33070Spst *	The Regents of the University of California.  All rights reserved.
43070Spst *
53070Spst * Redistribution and use in source and binary forms, with or without
63070Spst * modification, are permitted provided that the following conditions
73070Spst * are met:
83070Spst * 1. Redistributions of source code must retain the above copyright
93070Spst *    notice, this list of conditions and the following disclaimer.
103070Spst * 2. Redistributions in binary form must reproduce the above copyright
113070Spst *    notice, this list of conditions and the following disclaimer in the
123070Spst *    documentation and/or other materials provided with the distribution.
133070Spst * 4. Neither the name of the University nor the names of its contributors
143070Spst *    may be used to endorse or promote products derived from this software
153070Spst *    without specific prior written permission.
163070Spst *
173070Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
183070Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
193070Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
203070Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
213070Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
223070Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
233070Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
243070Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
253070Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
263070Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
273070Spst * SUCH DAMAGE.
283070Spst * -
293070Spst * Portions Copyright (c) 1993 by Digital Equipment Corporation.
308870Srgrimes *
313070Spst * Permission to use, copy, modify, and distribute this software for any
323070Spst * purpose with or without fee is hereby granted, provided that the above
333070Spst * copyright notice and this permission notice appear in all copies, and that
343070Spst * the name of Digital Equipment Corporation not be used in advertising or
353070Spst * publicity pertaining to distribution of the document or software without
363070Spst * specific, written prior permission.
378870Srgrimes *
383070Spst * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
393070Spst * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
403070Spst * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
413070Spst * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
423070Spst * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
433070Spst * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
443070Spst * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
453070Spst * SOFTWARE.
463070Spst * -
473070Spst * --Copyright--
483070Spst */
493070Spst
503070Spst#if defined(LIBC_SCCS) && !defined(lint)
513070Spststatic char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
523070Spst#endif /* LIBC_SCCS and not lint */
5392986Sobrien#include <sys/cdefs.h>
5492986Sobrien__FBSDID("$FreeBSD$");
553070Spst
563070Spst#include <sys/param.h>
573070Spst#include <sys/socket.h>
583070Spst#include <netinet/in.h>
593070Spst#include <arpa/inet.h>
603070Spst#include <netdb.h>
613070Spst#include <stdio.h>
623070Spst#include <ctype.h>
63211276Sume#include <errno.h>
643070Spst#include <string.h>
6565532Snectar#include <stdarg.h>
6665532Snectar#include <nsswitch.h>
6717903Speter#include <arpa/nameser.h>	/* XXX */
6817903Speter#include <resolv.h>		/* XXX */
69145602Sume#include "netdb_private.h"
703070Spst
713070Spstvoid
72145633Sume_sethosthtent(int f, struct hostent_data *hed)
733070Spst{
74145633Sume	if (!hed->hostf)
75145633Sume		hed->hostf = fopen(_PATH_HOSTS, "r");
763070Spst	else
77145633Sume		rewind(hed->hostf);
78145633Sume	hed->stayopen = f;
793070Spst}
803070Spst
813070Spstvoid
82145633Sume_endhosthtent(struct hostent_data *hed)
833070Spst{
84145633Sume	if (hed->hostf && !hed->stayopen) {
85145633Sume		(void) fclose(hed->hostf);
86145633Sume		hed->hostf = NULL;
873070Spst	}
883070Spst}
893070Spst
90145715Sumestatic int
91157779Sumegethostent_p(struct hostent *he, struct hostent_data *hed, int mapped,
92157779Sume    res_state statp)
933070Spst{
94145633Sume	char *p, *bp, *ep;
9592889Sobrien	char *cp, **q;
9617903Speter	int af, len;
97145633Sume	char hostbuf[BUFSIZ + 1];
983070Spst
99145633Sume	if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) {
100157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
101157779Sume		return (-1);
10213408Speter	}
10317903Speter again:
104145633Sume	if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
105157779Sume		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
106157779Sume		return (-1);
10713408Speter	}
1083070Spst	if (*p == '#')
1093070Spst		goto again;
110139612Ssobomax	cp = strpbrk(p, "#\n");
111139612Ssobomax	if (cp != NULL)
112139612Ssobomax		*cp = '\0';
11313408Speter	if (!(cp = strpbrk(p, " \t")))
1143070Spst		goto again;
1153070Spst	*cp++ = '\0';
116145633Sume	if (inet_pton(AF_INET6, p, hed->host_addr) > 0) {
11717903Speter		af = AF_INET6;
11817903Speter		len = IN6ADDRSZ;
119145633Sume	} else if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
120145715Sume		if (mapped) {
121145633Sume			_map_v4v6_address((char *)hed->host_addr,
122145633Sume			    (char *)hed->host_addr);
12317903Speter			af = AF_INET6;
12417903Speter			len = IN6ADDRSZ;
12517903Speter		} else {
12617903Speter			af = AF_INET;
12717903Speter			len = INADDRSZ;
12817903Speter		}
12917903Speter	} else {
13013408Speter		goto again;
13117903Speter	}
132145633Sume	hed->h_addr_ptrs[0] = (char *)hed->host_addr;
133145633Sume	hed->h_addr_ptrs[1] = NULL;
134145633Sume	he->h_addr_list = hed->h_addr_ptrs;
135145633Sume	he->h_length = len;
136145633Sume	he->h_addrtype = af;
1373070Spst	while (*cp == ' ' || *cp == '\t')
1383070Spst		cp++;
139145633Sume	bp = hed->hostbuf;
140145633Sume	ep = hed->hostbuf + sizeof hed->hostbuf;
141145633Sume	he->h_name = bp;
142145633Sume	q = he->h_aliases = hed->host_aliases;
143145633Sume	if ((p = strpbrk(cp, " \t")) != NULL)
144145633Sume		*p++ = '\0';
145145633Sume	len = strlen(cp) + 1;
146145633Sume	if (ep - bp < len) {
147157779Sume		RES_SET_H_ERRNO(statp, NO_RECOVERY);
148157779Sume		return (-1);
149145633Sume	}
150145633Sume	strlcpy(bp, cp, ep - bp);
151145633Sume	bp += len;
152145633Sume	cp = p;
1533070Spst	while (cp && *cp) {
1543070Spst		if (*cp == ' ' || *cp == '\t') {
1553070Spst			cp++;
1563070Spst			continue;
1573070Spst		}
158145633Sume		if (q >= &hed->host_aliases[_MAXALIASES - 1])
159145633Sume			break;
160145633Sume		if ((p = strpbrk(cp, " \t")) != NULL)
161145633Sume			*p++ = '\0';
162145633Sume		len = strlen(cp) + 1;
163145633Sume		if (ep - bp < len)
164145633Sume			break;
165145633Sume		strlcpy(bp, cp, ep - bp);
166145633Sume		*q++ = bp;
167145633Sume		bp += len;
168145633Sume		cp = p;
1693070Spst	}
1703070Spst	*q = NULL;
171157779Sume	RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
172157779Sume	return (0);
1733070Spst}
1743070Spst
175145715Sumeint
176157779Sumegethostent_r(struct hostent *hptr, char *buffer, size_t buflen,
177157779Sume    struct hostent **result, int *h_errnop)
178145715Sume{
179157779Sume	struct hostent_data *hed;
180157779Sume	struct hostent he;
181157779Sume	res_state statp;
182157779Sume
183157779Sume	statp = __res_state();
184157779Sume	if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
185157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
186157779Sume		*h_errnop = statp->res_h_errno;
187157779Sume		return (-1);
188156960Sume	}
189157779Sume	if ((hed = __hostent_data_init()) == NULL) {
190157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
191157779Sume		*h_errnop = statp->res_h_errno;
192157779Sume		return (-1);
193157779Sume	}
194157779Sume	if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0)
195157779Sume		return (-1);
196211276Sume	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
197211276Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
198211276Sume		*h_errnop = statp->res_h_errno;
199211276Sume		return ((errno != 0) ? errno : -1);
200211276Sume	}
201157779Sume	*result = hptr;
202157779Sume	return (0);
203145715Sume}
204145715Sume
205145633Sumestruct hostent *
206145633Sumegethostent(void)
207145633Sume{
208145633Sume	struct hostdata *hd;
209157779Sume	struct hostent *rval;
210157779Sume	int ret_h_errno;
211145633Sume
212145633Sume	if ((hd = __hostdata_init()) == NULL)
213157779Sume		return (NULL);
214157779Sume	if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval,
215157779Sume	    &ret_h_errno) != 0)
216157779Sume		return (NULL);
217157779Sume	return (rval);
218145633Sume}
219145633Sume
22065532Snectarint
221145715Sume_ht_gethostbyname(void *rval, void *cb_data, va_list ap)
22265532Snectar{
22317922Speter	const char *name;
22417903Speter	int af;
225157779Sume	char *buffer;
226157779Sume	size_t buflen;
227157779Sume	int *errnop, *h_errnop;
228157779Sume	struct hostent *hptr, he;
229145633Sume	struct hostent_data *hed;
23092889Sobrien	char **cp;
231157779Sume	res_state statp;
232145633Sume	int error;
23365532Snectar
23465532Snectar	name = va_arg(ap, const char *);
23565532Snectar	af = va_arg(ap, int);
236157779Sume	hptr = va_arg(ap, struct hostent *);
237157779Sume	buffer = va_arg(ap, char *);
238157779Sume	buflen = va_arg(ap, size_t);
239157779Sume	errnop = va_arg(ap, int *);
240157779Sume	h_errnop = va_arg(ap, int *);
241145633Sume
242157779Sume	*((struct hostent **)rval) = NULL;
243157779Sume
244157779Sume	statp = __res_state();
245157779Sume	if ((hed = __hostent_data_init()) == NULL) {
246157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
247157779Sume		*h_errnop = statp->res_h_errno;
248157779Sume		return (NS_NOTFOUND);
249157779Sume	}
250157779Sume
251157779Sume	_sethosthtent(0, hed);
252157779Sume	while ((error = gethostent_p(&he, hed, 0, statp)) == 0) {
253157779Sume		if (he.h_addrtype != af)
25417903Speter			continue;
255157779Sume		if (he.h_addrtype == AF_INET &&
256157779Sume		    statp->options & RES_USE_INET6) {
257157779Sume			_map_v4v6_address(he.h_addr, he.h_addr);
258157779Sume			he.h_length = IN6ADDRSZ;
259157779Sume			he.h_addrtype = AF_INET6;
260145715Sume		}
261157779Sume		if (strcasecmp(he.h_name, name) == 0)
2623070Spst			break;
263157779Sume		for (cp = he.h_aliases; *cp != 0; cp++)
2643070Spst			if (strcasecmp(*cp, name) == 0)
2653070Spst				goto found;
2663070Spst	}
2673070Spstfound:
268157779Sume	_endhosthtent(hed);
269145633Sume
270157779Sume	if (error != 0) {
271157779Sume		*h_errnop = statp->res_h_errno;
272157779Sume		return (NS_NOTFOUND);
273157779Sume	}
274157779Sume	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
275211276Sume		*errnop = errno;
276211276Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
277157779Sume		*h_errnop = statp->res_h_errno;
278211276Sume		return (NS_RETURN);
279157779Sume	}
280157779Sume	*((struct hostent **)rval) = hptr;
281157779Sume	return (NS_SUCCESS);
2823070Spst}
2833070Spst
284145715Sumeint
28565532Snectar_ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
28665532Snectar{
287158477Sume	const void *addr;
288158477Sume	socklen_t len;
289158477Sume	int af;
290157779Sume	char *buffer;
291157779Sume	size_t buflen;
292157779Sume	int *errnop, *h_errnop;
293157779Sume	struct hostent *hptr, he;
294145633Sume	struct hostent_data *hed;
295157779Sume	res_state statp;
296145633Sume	int error;
2973070Spst
298158477Sume	addr = va_arg(ap, const void *);
299158477Sume	len = va_arg(ap, socklen_t);
30065532Snectar	af = va_arg(ap, int);
301157779Sume	hptr = va_arg(ap, struct hostent *);
302157779Sume	buffer = va_arg(ap, char *);
303157779Sume	buflen = va_arg(ap, size_t);
304157779Sume	errnop = va_arg(ap, int *);
305157779Sume	h_errnop = va_arg(ap, int *);
30665532Snectar
307157779Sume	*((struct hostent **)rval) = NULL;
308157779Sume
309157779Sume	statp = __res_state();
310157779Sume	if ((hed = __hostent_data_init()) == NULL) {
311157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
312157779Sume		*h_errnop = statp->res_h_errno;
313157779Sume		return (NS_NOTFOUND);
314157779Sume	}
315157779Sume
316157779Sume	_sethosthtent(0, hed);
317157779Sume	while ((error = gethostent_p(&he, hed, 0, statp)) == 0)
318157779Sume		if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) {
319157779Sume			if (he.h_addrtype == AF_INET &&
320157779Sume			    statp->options & RES_USE_INET6) {
321157779Sume				_map_v4v6_address(he.h_addr, he.h_addr);
322157779Sume				he.h_length = IN6ADDRSZ;
323157779Sume				he.h_addrtype = AF_INET6;
324145728Sume			}
3253070Spst			break;
326145728Sume		}
327157779Sume	_endhosthtent(hed);
32865532Snectar
329157779Sume	if (error != 0)
330157779Sume		return (NS_NOTFOUND);
331157779Sume	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
332211276Sume		*errnop = errno;
333211276Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
334157779Sume		*h_errnop = statp->res_h_errno;
335211276Sume		return (NS_RETURN);
336157779Sume	}
337157779Sume	*((struct hostent **)rval) = hptr;
338157779Sume	return (NS_SUCCESS);
3393070Spst}
340