xref: /netbsd-src/lib/libc/net/sethostent.c (revision 058a8681342def63dd3d9a3b0618134b0a5591ce)
1*058a8681Skre /*	$NetBSD: sethostent.c,v 1.21 2023/12/07 22:33:49 kre Exp $	*/
2efba316dSchristos 
3efba316dSchristos /*
4efba316dSchristos  * Copyright (c) 1985, 1993
5efba316dSchristos  *	The Regents of the University of California.  All rights reserved.
6efba316dSchristos  *
7efba316dSchristos  * Redistribution and use in source and binary forms, with or without
8efba316dSchristos  * modification, are permitted provided that the following conditions
9efba316dSchristos  * are met:
10efba316dSchristos  * 1. Redistributions of source code must retain the above copyright
11efba316dSchristos  *    notice, this list of conditions and the following disclaimer.
12efba316dSchristos  * 2. Redistributions in binary form must reproduce the above copyright
13efba316dSchristos  *    notice, this list of conditions and the following disclaimer in the
14efba316dSchristos  *    documentation and/or other materials provided with the distribution.
15efba316dSchristos  * 3. Neither the name of the University nor the names of its contributors
16efba316dSchristos  *    may be used to endorse or promote products derived from this software
17efba316dSchristos  *    without specific prior written permission.
18efba316dSchristos  *
19efba316dSchristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20efba316dSchristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21efba316dSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22efba316dSchristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23efba316dSchristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24efba316dSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25efba316dSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26efba316dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27efba316dSchristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28efba316dSchristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29efba316dSchristos  * SUCH DAMAGE.
30efba316dSchristos  */
31efba316dSchristos 
32efba316dSchristos #include <sys/cdefs.h>
33efba316dSchristos #if defined(LIBC_SCCS) && !defined(lint)
34efba316dSchristos #if 0
35efba316dSchristos static char sccsid[] = "@(#)sethostent.c	8.1 (Berkeley) 6/4/93";
36efba316dSchristos static char rcsid[] = "Id: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp ";
37efba316dSchristos #else
38*058a8681Skre __RCSID("$NetBSD: sethostent.c,v 1.21 2023/12/07 22:33:49 kre Exp $");
39efba316dSchristos #endif
40efba316dSchristos #endif /* LIBC_SCCS and not lint */
41efba316dSchristos 
42efba316dSchristos #include "namespace.h"
43efba316dSchristos #include <sys/param.h>
44efba316dSchristos #include <netinet/in.h>
45efba316dSchristos #include <arpa/nameser.h>
464d322dedSchristos #include <arpa/inet.h>
474d322dedSchristos #include <assert.h>
484d322dedSchristos #include <string.h>
494d322dedSchristos #include <nsswitch.h>
50efba316dSchristos #include <netdb.h>
51efba316dSchristos #include <resolv.h>
524d322dedSchristos #include <errno.h>
534d322dedSchristos #include <stdlib.h>
54efba316dSchristos 
5502dd2447Schristos #include "hostent.h"
5602dd2447Schristos 
57efba316dSchristos #ifdef __weak_alias
58efba316dSchristos __weak_alias(sethostent,_sethostent)
59efba316dSchristos __weak_alias(endhostent,_endhostent)
60efba316dSchristos #endif
61efba316dSchristos 
62efba316dSchristos #ifndef _REENTRANT
63504f8671Smatt void	res_close(void);
64efba316dSchristos #endif
65efba316dSchristos 
664d322dedSchristos static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *);
674d322dedSchristos 
68efba316dSchristos void
69efba316dSchristos /*ARGSUSED*/
sethostent(int stayopen)70504f8671Smatt sethostent(int stayopen)
71efba316dSchristos {
72efba316dSchristos #ifndef _REENTRANT
73efba316dSchristos 	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
74efba316dSchristos 		return;
75efba316dSchristos 	if (stayopen)
76efba316dSchristos 		_res.options |= RES_STAYOPEN | RES_USEVC;
77efba316dSchristos #endif
7802dd2447Schristos 	sethostent_r(&_h_file);
79efba316dSchristos }
80efba316dSchristos 
81efba316dSchristos void
endhostent(void)82504f8671Smatt endhostent(void)
83efba316dSchristos {
84efba316dSchristos #ifndef _REENTRANT
85efba316dSchristos 	_res.options &= ~(RES_STAYOPEN | RES_USEVC);
86efba316dSchristos 	res_close();
87efba316dSchristos #endif
8802dd2447Schristos 	endhostent_r(&_h_file);
89efba316dSchristos }
904d322dedSchristos static const char *_h_hosts = _PATH_HOSTS;
914d322dedSchristos 
924d322dedSchristos void
_hf_sethostsfile(const char * f)934d322dedSchristos _hf_sethostsfile(const char *f) {
944d322dedSchristos 	_h_hosts = f;
954d322dedSchristos }
964d322dedSchristos 
974d322dedSchristos void
sethostent_r(FILE ** hf)984d322dedSchristos sethostent_r(FILE **hf)
994d322dedSchristos {
1004d322dedSchristos 	if (!*hf)
1014d322dedSchristos 		*hf = fopen(_h_hosts, "re");
1024d322dedSchristos 	else
1034d322dedSchristos 		rewind(*hf);
1044d322dedSchristos }
1054d322dedSchristos 
1064d322dedSchristos void
endhostent_r(FILE ** hf)1074d322dedSchristos endhostent_r(FILE **hf)
1084d322dedSchristos {
1094d322dedSchristos 	if (*hf) {
1104d322dedSchristos 		(void)fclose(*hf);
1114d322dedSchristos 		*hf = NULL;
1124d322dedSchristos 	}
1134d322dedSchristos }
1144d322dedSchristos 
1154d322dedSchristos /*ARGSUSED*/
1164d322dedSchristos int
_hf_gethtbyname(void * rv,void * cb_data,va_list ap)1174d322dedSchristos _hf_gethtbyname(void *rv, void *cb_data, va_list ap)
1184d322dedSchristos {
1194d322dedSchristos 	struct hostent *hp;
1204d322dedSchristos 	const char *name;
1214d322dedSchristos 	int af;
1224d322dedSchristos 	struct getnamaddr *info = rv;
1234d322dedSchristos 
1244d322dedSchristos 	_DIAGASSERT(rv != NULL);
1254d322dedSchristos 
1264d322dedSchristos 	name = va_arg(ap, char *);
1274d322dedSchristos 	/* NOSTRICT skip string len */(void)va_arg(ap, int);
1284d322dedSchristos 	af = va_arg(ap, int);
1294d322dedSchristos 
1304d322dedSchristos #if 0
1314d322dedSchristos 	{
1324d322dedSchristos 		res_state res = __res_get_state();
1334d322dedSchristos 		if (res == NULL)
1344d322dedSchristos 			return NS_NOTFOUND;
1354d322dedSchristos 		if (res->options & RES_USE_INET6)
1364d322dedSchristos 			hp = _hf_gethtbyname2(name, AF_INET6, info);
1374d322dedSchristos 		else
1384d322dedSchristos 			hp = NULL;
1394d322dedSchristos 		if (hp == NULL)
1404d322dedSchristos 			hp = _hf_gethtbyname2(name, AF_INET, info);
1414d322dedSchristos 		__res_put_state(res);
1424d322dedSchristos 	}
1434d322dedSchristos #else
1444d322dedSchristos 	hp = _hf_gethtbyname2(name, af, info);
1454d322dedSchristos #endif
1464d322dedSchristos 	if (hp == NULL) {
1474d322dedSchristos 		*info->he = HOST_NOT_FOUND;
1484d322dedSchristos 		return NS_NOTFOUND;
1494d322dedSchristos 	}
1504d322dedSchristos 	return NS_SUCCESS;
1514d322dedSchristos }
1524d322dedSchristos 
1534d322dedSchristos struct hostent *
_hf_gethtbyname2(const char * name,int af,struct getnamaddr * info)1544d322dedSchristos _hf_gethtbyname2(const char *name, int af, struct getnamaddr *info)
1554d322dedSchristos {
1564d322dedSchristos 	struct hostent *hp, hent;
1574d322dedSchristos 	char *buf, *ptr;
1584d322dedSchristos 	size_t len, anum, num, i;
1594d322dedSchristos 	FILE *hf;
1604d322dedSchristos 	char *aliases[MAXALIASES];
1614d322dedSchristos 	char *addr_ptrs[MAXADDRS];
1624d322dedSchristos 
1634d322dedSchristos 	_DIAGASSERT(name != NULL);
1644d322dedSchristos 
1654d322dedSchristos 	hf = NULL;
1664d322dedSchristos 	sethostent_r(&hf);
1674d322dedSchristos 	if (hf == NULL) {
1684d322dedSchristos 		errno = EINVAL;
1694d322dedSchristos 		*info->he = NETDB_INTERNAL;
1704d322dedSchristos 		return NULL;
1714d322dedSchristos 	}
1724d322dedSchristos 
1734d322dedSchristos 	if ((ptr = buf = malloc(len = info->buflen)) == NULL) {
174*058a8681Skre 		endhostent_r(&hf);
1754d322dedSchristos 		*info->he = NETDB_INTERNAL;
1764d322dedSchristos 		return NULL;
1774d322dedSchristos 	}
1784d322dedSchristos 
1794d322dedSchristos 	anum = 0;		/* XXX: gcc */
1804d322dedSchristos 	hent.h_name = NULL;	/* XXX: gcc */
1814d322dedSchristos 	hent.h_addrtype = 0;	/* XXX: gcc */
1824d322dedSchristos 	hent.h_length = 0;	/* XXX: gcc */
1834d322dedSchristos 
1844d322dedSchristos 	for (num = 0; num < MAXADDRS;) {
1854d322dedSchristos 		info->hp->h_addrtype = af;
1864d322dedSchristos 		info->hp->h_length = 0;
1874d322dedSchristos 
1884d322dedSchristos 		hp = gethostent_r(hf, info->hp, info->buf, info->buflen,
1894d322dedSchristos 		    info->he);
1904d322dedSchristos 		if (hp == NULL)
1914d322dedSchristos 			break;
1924d322dedSchristos 
1934d322dedSchristos 		if (strcasecmp(hp->h_name, name) != 0) {
1944d322dedSchristos 			char **cp;
1954d322dedSchristos 			for (cp = hp->h_aliases; *cp != NULL; cp++)
1964d322dedSchristos 				if (strcasecmp(*cp, name) == 0)
1974d322dedSchristos 					break;
1984d322dedSchristos 			if (*cp == NULL) continue;
1994d322dedSchristos 		}
2004d322dedSchristos 
2014d322dedSchristos 		if (num == 0) {
2024d322dedSchristos 			hent.h_addrtype = af = hp->h_addrtype;
2034d322dedSchristos 			hent.h_length = hp->h_length;
2044d322dedSchristos 
2054d322dedSchristos 			HENT_SCOPY(hent.h_name, hp->h_name, ptr, len);
2064d322dedSchristos 			for (anum = 0; hp->h_aliases[anum]; anum++) {
2074d322dedSchristos 				if (anum >= __arraycount(aliases))
2084d322dedSchristos 					goto nospc;
2094d322dedSchristos 				HENT_SCOPY(aliases[anum], hp->h_aliases[anum],
2104d322dedSchristos 				    ptr, len);
2114d322dedSchristos 			}
2124d322dedSchristos 			ptr = (void *)ALIGN(ptr);
2134d322dedSchristos 			if ((size_t)(ptr - buf) >= info->buflen)
2144d322dedSchristos 				goto nospc;
2154d322dedSchristos 		}
2164d322dedSchristos 
2174d322dedSchristos 		if (num >= __arraycount(addr_ptrs))
2184d322dedSchristos 			goto nospc;
2194d322dedSchristos 		HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr,
2204d322dedSchristos 		    len);
2214d322dedSchristos 		num++;
2224d322dedSchristos 	}
2234d322dedSchristos 	endhostent_r(&hf);
2244d322dedSchristos 
2254d322dedSchristos 	if (num == 0) {
2264d322dedSchristos 		*info->he = HOST_NOT_FOUND;
227e2ecf243Schristos 		free(buf);
2284d322dedSchristos 		return NULL;
2294d322dedSchristos 	}
2304d322dedSchristos 
2314d322dedSchristos 	hp = info->hp;
2324d322dedSchristos 	ptr = info->buf;
2334d322dedSchristos 	len = info->buflen;
2344d322dedSchristos 
2354d322dedSchristos 	hp->h_addrtype = hent.h_addrtype;
2364d322dedSchristos 	hp->h_length = hent.h_length;
2374d322dedSchristos 
2384d322dedSchristos 	HENT_ARRAY(hp->h_aliases, anum, ptr, len);
2394d322dedSchristos 	HENT_ARRAY(hp->h_addr_list, num, ptr, len);
2404d322dedSchristos 
2414d322dedSchristos 	for (i = 0; i < num; i++)
2424d322dedSchristos 		HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr,
2434d322dedSchristos 		    len);
2444d322dedSchristos 	hp->h_addr_list[num] = NULL;
2454d322dedSchristos 
2464d322dedSchristos 	HENT_SCOPY(hp->h_name, hent.h_name, ptr, len);
2474d322dedSchristos 
2484d322dedSchristos 	for (i = 0; i < anum; i++)
2494d322dedSchristos 		HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
2504d322dedSchristos 	hp->h_aliases[anum] = NULL;
2514d322dedSchristos 
252e2ecf243Schristos 	free(buf);
2534d322dedSchristos 	return hp;
2544d322dedSchristos nospc:
255*058a8681Skre 	endhostent_r(&hf);
2564d322dedSchristos 	*info->he = NETDB_INTERNAL;
257e2ecf243Schristos 	free(buf);
2584d322dedSchristos 	errno = ENOSPC;
2594d322dedSchristos 	return NULL;
2604d322dedSchristos }
2614d322dedSchristos 
2624d322dedSchristos /*ARGSUSED*/
2634d322dedSchristos int
_hf_gethtbyaddr(void * rv,void * cb_data,va_list ap)2644d322dedSchristos _hf_gethtbyaddr(void *rv, void *cb_data, va_list ap)
2654d322dedSchristos {
2664d322dedSchristos 	struct hostent *hp;
2674d322dedSchristos 	const unsigned char *addr;
2684d322dedSchristos 	struct getnamaddr *info = rv;
2694d322dedSchristos 	FILE *hf;
2704d322dedSchristos 
2714d322dedSchristos 	_DIAGASSERT(rv != NULL);
2724d322dedSchristos 
2734d322dedSchristos 	addr = va_arg(ap, unsigned char *);
2744d322dedSchristos 	info->hp->h_length = va_arg(ap, int);
2754d322dedSchristos 	info->hp->h_addrtype = va_arg(ap, int);
2764d322dedSchristos 
2774d322dedSchristos 	hf = NULL;
2784d322dedSchristos 	sethostent_r(&hf);
2794d322dedSchristos 	if (hf == NULL) {
2804d322dedSchristos 		*info->he = NETDB_INTERNAL;
2814d322dedSchristos 		return NS_UNAVAIL;
2824d322dedSchristos 	}
2834d322dedSchristos 	while ((hp = gethostent_r(hf, info->hp, info->buf, info->buflen,
2844d322dedSchristos 	    info->he)) != NULL)
2854d322dedSchristos 		if (!memcmp(hp->h_addr_list[0], addr, (size_t)hp->h_length))
2864d322dedSchristos 			break;
2874d322dedSchristos 	endhostent_r(&hf);
2884d322dedSchristos 
2894d322dedSchristos 	if (hp == NULL) {
2904d322dedSchristos 		*info->he = HOST_NOT_FOUND;
2914d322dedSchristos 		return NS_NOTFOUND;
2924d322dedSchristos 	}
2934d322dedSchristos 	return NS_SUCCESS;
2944d322dedSchristos }
295