xref: /freebsd/lib/libc/net/gethostbyht.c (revision 3d11b6c8f01e1fca5936a11d6996448467851a94)
1 /*-
2  * Copyright (c) 1985, 1988, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  * -
33  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34  *
35  * Permission to use, copy, modify, and distribute this software for any
36  * purpose with or without fee is hereby granted, provided that the above
37  * copyright notice and this permission notice appear in all copies, and that
38  * the name of Digital Equipment Corporation not be used in advertising or
39  * publicity pertaining to distribution of the document or software without
40  * specific, written prior permission.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
45  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49  * SOFTWARE.
50  * -
51  * --Copyright--
52  */
53 
54 #if defined(LIBC_SCCS) && !defined(lint)
55 static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
56 #endif /* LIBC_SCCS and not lint */
57 #include <sys/cdefs.h>
58 __FBSDID("$FreeBSD$");
59 
60 #include <sys/param.h>
61 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #include <netdb.h>
65 #include <stdio.h>
66 #include <ctype.h>
67 #include <string.h>
68 #include <stdarg.h>
69 #include <nsswitch.h>
70 #include <arpa/nameser.h>	/* XXX */
71 #include <resolv.h>		/* XXX */
72 #include "netdb_private.h"
73 
74 void
75 _sethosthtent(int f, struct hostent_data *hed)
76 {
77 	if (!hed->hostf)
78 		hed->hostf = fopen(_PATH_HOSTS, "r");
79 	else
80 		rewind(hed->hostf);
81 	hed->stayopen = f;
82 }
83 
84 void
85 _endhosthtent(struct hostent_data *hed)
86 {
87 	if (hed->hostf && !hed->stayopen) {
88 		(void) fclose(hed->hostf);
89 		hed->hostf = NULL;
90 	}
91 }
92 
93 static int
94 gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped)
95 {
96 	char *p, *bp, *ep;
97 	char *cp, **q;
98 	int af, len;
99 	char hostbuf[BUFSIZ + 1];
100 
101 	if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) {
102 		RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
103 		return -1;
104 	}
105  again:
106 	if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
107 		RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
108 		return -1;
109 	}
110 	if (*p == '#')
111 		goto again;
112 	cp = strpbrk(p, "#\n");
113 	if (cp != NULL)
114 		*cp = '\0';
115 	if (!(cp = strpbrk(p, " \t")))
116 		goto again;
117 	*cp++ = '\0';
118 	if (inet_pton(AF_INET6, p, hed->host_addr) > 0) {
119 		af = AF_INET6;
120 		len = IN6ADDRSZ;
121 	} else if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
122 		if (mapped) {
123 			_map_v4v6_address((char *)hed->host_addr,
124 			    (char *)hed->host_addr);
125 			af = AF_INET6;
126 			len = IN6ADDRSZ;
127 		} else {
128 			af = AF_INET;
129 			len = INADDRSZ;
130 		}
131 	} else {
132 		goto again;
133 	}
134 	hed->h_addr_ptrs[0] = (char *)hed->host_addr;
135 	hed->h_addr_ptrs[1] = NULL;
136 	he->h_addr_list = hed->h_addr_ptrs;
137 	he->h_length = len;
138 	he->h_addrtype = af;
139 	while (*cp == ' ' || *cp == '\t')
140 		cp++;
141 	bp = hed->hostbuf;
142 	ep = hed->hostbuf + sizeof hed->hostbuf;
143 	he->h_name = bp;
144 	q = he->h_aliases = hed->host_aliases;
145 	if ((p = strpbrk(cp, " \t")) != NULL)
146 		*p++ = '\0';
147 	len = strlen(cp) + 1;
148 	if (ep - bp < len) {
149 		RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
150 		return -1;
151 	}
152 	strlcpy(bp, cp, ep - bp);
153 	bp += len;
154 	cp = p;
155 	while (cp && *cp) {
156 		if (*cp == ' ' || *cp == '\t') {
157 			cp++;
158 			continue;
159 		}
160 		if (q >= &hed->host_aliases[_MAXALIASES - 1])
161 			break;
162 		if ((p = strpbrk(cp, " \t")) != NULL)
163 			*p++ = '\0';
164 		len = strlen(cp) + 1;
165 		if (ep - bp < len)
166 			break;
167 		strlcpy(bp, cp, ep - bp);
168 		*q++ = bp;
169 		bp += len;
170 		cp = p;
171 	}
172 	*q = NULL;
173 	RES_SET_H_ERRNO(hed->res, NETDB_SUCCESS);
174 	return 0;
175 }
176 
177 int
178 gethostent_r(struct hostent *he, struct hostent_data *hed)
179 {
180 	hed->res = __res_state();
181 	if ((hed->res->options & RES_INIT) == 0 && res_ninit(hed->res) == -1) {
182 		RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
183 		return -1;
184 	}
185 	return gethostent_p(he, hed, hed->res->options & RES_USE_INET6);
186 }
187 
188 struct hostent *
189 gethostent(void)
190 {
191 	struct hostdata *hd;
192 
193 	if ((hd = __hostdata_init()) == NULL)
194 		return NULL;
195 	if (gethostent_r(&hd->host, &hd->data) != 0)
196 		return NULL;
197 	return &hd->host;
198 }
199 
200 int
201 _ht_gethostbyname(void *rval, void *cb_data, va_list ap)
202 {
203 	const char *name;
204 	int af;
205 	struct hostent *he;
206 	struct hostent_data *hed;
207 	char **cp;
208 	int error;
209 
210 	name = va_arg(ap, const char *);
211 	af = va_arg(ap, int);
212 	he = va_arg(ap, struct hostent *);
213 	hed = va_arg(ap, struct hostent_data *);
214 
215 	sethostent_r(0, hed);
216 	while ((error = gethostent_p(he, hed, 0)) == 0) {
217 		if (he->h_addrtype != af)
218 			continue;
219 		if (he->h_addrtype == AF_INET &&
220 		    hed->res->options & RES_USE_INET6) {
221 			_map_v4v6_address(he->h_addr, he->h_addr);
222 			he->h_length = IN6ADDRSZ;
223 			he->h_addrtype = AF_INET6;
224 		}
225 		if (strcasecmp(he->h_name, name) == 0)
226 			break;
227 		for (cp = he->h_aliases; *cp != 0; cp++)
228 			if (strcasecmp(*cp, name) == 0)
229 				goto found;
230 	}
231 found:
232 	endhostent_r(hed);
233 
234 	return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
235 }
236 
237 int
238 _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
239 {
240 	const char *addr;
241 	int len, af;
242 	struct hostent *he;
243 	struct hostent_data *hed;
244 	int error;
245 
246 	addr = va_arg(ap, const char *);
247 	len = va_arg(ap, int);
248 	af = va_arg(ap, int);
249 	he = va_arg(ap, struct hostent *);
250 	hed = va_arg(ap, struct hostent_data *);
251 
252 	sethostent_r(0, hed);
253 	while ((error = gethostent_p(he, hed, 0)) == 0)
254 		if (he->h_addrtype == af && !bcmp(he->h_addr, addr, len)) {
255 			if (he->h_addrtype == AF_INET &&
256 			    hed->res->options & RES_USE_INET6) {
257 				_map_v4v6_address(he->h_addr, he->h_addr);
258 				he->h_length = IN6ADDRSZ;
259 				he->h_addrtype = AF_INET6;
260 			}
261 			break;
262 		}
263 	endhostent_r(hed);
264 
265 	return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
266 }
267