xref: /freebsd/lib/libc/net/gethostbyht.c (revision 40ca152d152be86531280469b1e70a99f8b29d1b)
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 		h_errno = NETDB_INTERNAL;
103 		return -1;
104 	}
105  again:
106 	if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
107 		h_errno = 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 		h_errno = 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 	h_errno = NETDB_SUCCESS;
174 	return 0;
175 }
176 
177 int
178 gethostent_r(struct hostent *he, struct hostent_data *hed)
179 {
180 	return gethostent_p(he, hed, _res.options & RES_USE_INET6);
181 }
182 
183 struct hostent *
184 gethostent(void)
185 {
186 	struct hostdata *hd;
187 
188 	if ((hd = __hostdata_init()) == NULL)
189 		return NULL;
190 	if (gethostent_r(&hd->host, &hd->data) != 0)
191 		return NULL;
192 	return &hd->host;
193 }
194 
195 int
196 _ht_gethostbyname(void *rval, void *cb_data, va_list ap)
197 {
198 	const char *name;
199 	int af;
200 	struct hostent *he;
201 	struct hostent_data *hed;
202 	char **cp;
203 	int error;
204 
205 	name = va_arg(ap, const char *);
206 	af = va_arg(ap, int);
207 	he = va_arg(ap, struct hostent *);
208 	hed = va_arg(ap, struct hostent_data *);
209 
210 	sethostent_r(0, hed);
211 	while ((error = gethostent_p(he, hed, 0)) == 0) {
212 		if (he->h_addrtype != af)
213 			continue;
214 		if (he->h_addrtype == AF_INET &&
215 		    _res.options & RES_USE_INET6) {
216 			_map_v4v6_address(he->h_addr, he->h_addr);
217 			he->h_length = IN6ADDRSZ;
218 			he->h_addrtype = AF_INET6;
219 		}
220 		if (strcasecmp(he->h_name, name) == 0)
221 			break;
222 		for (cp = he->h_aliases; *cp != 0; cp++)
223 			if (strcasecmp(*cp, name) == 0)
224 				goto found;
225 	}
226 found:
227 	endhostent_r(hed);
228 
229 	return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
230 }
231 
232 int
233 _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
234 {
235 	const char *addr;
236 	int len, af;
237 	struct hostent *he;
238 	struct hostent_data *hed;
239 	int error;
240 
241 	addr = va_arg(ap, const char *);
242 	len = va_arg(ap, int);
243 	af = va_arg(ap, int);
244 	he = va_arg(ap, struct hostent *);
245 	hed = va_arg(ap, struct hostent_data *);
246 
247 	sethostent_r(0, hed);
248 	while ((error = gethostent_r(he, hed)) == 0)
249 		if (he->h_addrtype == af && !bcmp(he->h_addr, addr, len))
250 			break;
251 	endhostent_r(hed);
252 
253 	return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
254 }
255