xref: /netbsd-src/distrib/utils/libhack/gethost.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
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 
76 int h_errno;
77 FILE *_h_file;
78 static struct hostent h_ent;
79 static char h_buf[4096];
80 
81 static struct hostent *
82 getby(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 
98 struct hostent *
99 gethostbyname_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 
111 struct hostent *
112 gethostbyname(const char *name)
113 {
114 	return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
115 }
116 
117 struct hostent *
118 gethostbyaddr_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 
129 struct hostent *
130 gethostbyaddr(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 
136 struct hostent *
137 gethostent_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;
228 nospc:
229 	errno = ENOSPC;
230 	*he = NETDB_INTERNAL;
231 	return NULL;
232 }
233