xref: /freebsd/lib/libc/net/gethostbynis.c (revision 38f0b757fd84d17d0fc24739a7cda160c4516d81)
1 /*-
2  * Copyright (c) 1994, Garrett Wollman
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <arpa/nameser.h>
34 #include <netdb.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <nsswitch.h>
42 #include <resolv.h>		/* XXX */
43 #ifdef YP
44 #include <rpc/rpc.h>
45 #include <rpcsvc/yp_prot.h>
46 #include <rpcsvc/ypclnt.h>
47 #endif
48 #include "netdb_private.h"
49 
50 #ifdef YP
51 static int
52 _gethostbynis(const char *name, char *map, int af, struct hostent *he,
53     struct hostent_data *hed)
54 {
55 	char *p, *bp, *ep;
56 	char *cp, **q;
57 	char *result;
58 	int resultlen, size, addrok = 0;
59 	char ypbuf[YPMAXRECORD + 2];
60 	res_state statp;
61 
62 	statp = __res_state();
63 	switch(af) {
64 	case AF_INET:
65 		size = NS_INADDRSZ;
66 		break;
67 	case AF_INET6:
68 		size = NS_IN6ADDRSZ;
69 		break;
70 	default:
71 		errno = EAFNOSUPPORT;
72 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
73 		return (-1);
74 	}
75 
76 	if (hed->yp_domain == (char *)NULL)
77 		if (yp_get_default_domain (&hed->yp_domain)) {
78 			RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
79 			return (-1);
80 		}
81 
82 	if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
83 	    &resultlen)) {
84 		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
85 		return (-1);
86 	}
87 
88 	/* avoid potential memory leak */
89 	bcopy((char *)result, (char *)&ypbuf, resultlen);
90 	ypbuf[resultlen] = '\0';
91 	free(result);
92 	result = (char *)&ypbuf;
93 
94 	if ((cp = strchr(result, '\n')))
95 		*cp = '\0';
96 
97 	cp = strpbrk(result, " \t");
98 	*cp++ = '\0';
99 	he->h_addr_list = hed->h_addr_ptrs;
100 	he->h_addr = (char *)hed->host_addr;
101 	switch (af) {
102 	case AF_INET:
103 		addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
104 		if (addrok != 1)
105 			break;
106 		if (statp->options & RES_USE_INET6) {
107 			_map_v4v6_address((char *)hed->host_addr,
108 			    (char *)hed->host_addr);
109 			af = AF_INET6;
110 			size = NS_IN6ADDRSZ;
111 		}
112 		break;
113 	case AF_INET6:
114 		addrok = inet_pton(af, result, hed->host_addr);
115 		break;
116 	}
117 	if (addrok != 1) {
118 		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
119 		return (-1);
120 	}
121 	he->h_addr_list[1] = NULL;
122 	he->h_length = size;
123 	he->h_addrtype = af;
124 	while (*cp == ' ' || *cp == '\t')
125 		cp++;
126 	bp = hed->hostbuf;
127 	ep = hed->hostbuf + sizeof hed->hostbuf;
128 	he->h_name = bp;
129 	q = he->h_aliases = hed->host_aliases;
130 	p = strpbrk(cp, " \t");
131 	if (p != NULL)
132 		*p++ = '\0';
133 	size = strlen(cp) + 1;
134 	if (ep - bp < size) {
135 		RES_SET_H_ERRNO(statp, NO_RECOVERY);
136 		return (-1);
137 	}
138 	strlcpy(bp, cp, ep - bp);
139 	bp += size;
140 	cp = p;
141 	while (cp && *cp) {
142 		if (*cp == ' ' || *cp == '\t') {
143 			cp++;
144 			continue;
145 		}
146 		if (q >= &hed->host_aliases[_MAXALIASES - 1])
147 			break;
148 		p = strpbrk(cp, " \t");
149 		if (p != NULL)
150 			*p++ = '\0';
151 		size = strlen(cp) + 1;
152 		if (ep - bp < size)
153 			break;
154 		strlcpy(bp, cp, ep - bp);
155 		*q++ = bp;
156 		bp += size;
157 		cp = p;
158 	}
159 	*q = NULL;
160 	return (0);
161 }
162 
163 static int
164 _gethostbynisname_r(const char *name, int af, struct hostent *he,
165     struct hostent_data *hed)
166 {
167 	char *map;
168 
169 	switch (af) {
170 	case AF_INET:
171 		map = "hosts.byname";
172 		break;
173 	default:
174 		map = "ipnodes.byname";
175 		break;
176 	}
177 	return (_gethostbynis(name, map, af, he, hed));
178 }
179 
180 static int
181 _gethostbynisaddr_r(const void *addr, socklen_t len, int af,
182     struct hostent *he, struct hostent_data *hed)
183 {
184 	char *map;
185 	char numaddr[46];
186 
187 	switch (af) {
188 	case AF_INET:
189 		map = "hosts.byaddr";
190 		break;
191 	default:
192 		map = "ipnodes.byaddr";
193 		break;
194 	}
195 	if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
196 		return (-1);
197 	return (_gethostbynis(numaddr, map, af, he, hed));
198 }
199 #endif /* YP */
200 
201 /* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */
202 struct hostent *
203 _gethostbynisname(const char *name, int af)
204 {
205 #ifdef YP
206 	struct hostent *he;
207 	struct hostent_data *hed;
208 	u_long oresopt;
209 	int error;
210 	res_state statp;
211 
212 	statp = __res_state();
213 	if ((he = __hostent_init()) == NULL ||
214 	    (hed = __hostent_data_init()) == NULL) {
215 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
216 		return (NULL);
217 	}
218 
219 	oresopt = statp->options;
220 	statp->options &= ~RES_USE_INET6;
221 	error = _gethostbynisname_r(name, af, he, hed);
222 	statp->options = oresopt;
223 	return (error == 0) ? he : NULL;
224 #else
225 	return (NULL);
226 #endif
227 }
228 
229 struct hostent *
230 _gethostbynisaddr(const void *addr, socklen_t len, int af)
231 {
232 #ifdef YP
233 	struct hostent *he;
234 	struct hostent_data *hed;
235 	u_long oresopt;
236 	int error;
237 	res_state statp;
238 
239 	statp = __res_state();
240 	if ((he = __hostent_init()) == NULL ||
241 	    (hed = __hostent_data_init()) == NULL) {
242 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
243 		return (NULL);
244 	}
245 
246 	oresopt = statp->options;
247 	statp->options &= ~RES_USE_INET6;
248 	error = _gethostbynisaddr_r(addr, len, af, he, hed);
249 	statp->options = oresopt;
250 	return (error == 0) ? he : NULL;
251 #else
252 	return (NULL);
253 #endif
254 }
255 
256 int
257 _nis_gethostbyname(void *rval, void *cb_data, va_list ap)
258 {
259 #ifdef YP
260 	const char *name;
261 	int af;
262 	char *buffer;
263 	size_t buflen;
264 	int *errnop, *h_errnop;
265 	struct hostent *hptr, he;
266 	struct hostent_data *hed;
267 	res_state statp;
268 
269 	name = va_arg(ap, const char *);
270 	af = va_arg(ap, int);
271 	hptr = va_arg(ap, struct hostent *);
272 	buffer = va_arg(ap, char *);
273 	buflen = va_arg(ap, size_t);
274 	errnop = va_arg(ap, int *);
275 	h_errnop = va_arg(ap, int *);
276 
277 	*((struct hostent **)rval) = NULL;
278 
279 	statp = __res_state();
280 	if ((hed = __hostent_data_init()) == NULL) {
281 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
282 		*h_errnop = statp->res_h_errno;
283 		return (NS_NOTFOUND);
284 	}
285 
286 	if (_gethostbynisname_r(name, af, &he, hed) != 0) {
287 		*h_errnop = statp->res_h_errno;
288 		return (NS_NOTFOUND);
289 	}
290 	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
291 		*errnop = errno;
292 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
293 		*h_errnop = statp->res_h_errno;
294 		return (NS_RETURN);
295 	}
296 	*((struct hostent **)rval) = hptr;
297 	return (NS_SUCCESS);
298 #else
299 	*((struct hostent **)rval) = NULL;
300 	return (NS_UNAVAIL);
301 #endif
302 }
303 
304 int
305 _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
306 {
307 #ifdef YP
308 	const void *addr;
309 	socklen_t len;
310 	int af;
311 	char *buffer;
312 	size_t buflen;
313 	int *errnop, *h_errnop;
314 	struct hostent *hptr, he;
315 	struct hostent_data *hed;
316 	res_state statp;
317 
318 	addr = va_arg(ap, const void *);
319 	len = va_arg(ap, socklen_t);
320 	af = va_arg(ap, int);
321 	hptr = va_arg(ap, struct hostent *);
322 	buffer = va_arg(ap, char *);
323 	buflen = va_arg(ap, size_t);
324 	errnop = va_arg(ap, int *);
325 	h_errnop = va_arg(ap, int *);
326 
327 	*((struct hostent **)rval) = NULL;
328 
329 	statp = __res_state();
330 	if ((hed = __hostent_data_init()) == NULL) {
331 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
332 		*h_errnop = statp->res_h_errno;
333 		return (NS_NOTFOUND);
334 	}
335 
336 	if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
337 		*h_errnop = statp->res_h_errno;
338 		return (NS_NOTFOUND);
339 	}
340 	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
341 		*errnop = errno;
342 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
343 		*h_errnop = statp->res_h_errno;
344 		return (NS_RETURN);
345 	}
346 	*((struct hostent **)rval) = hptr;
347 	return (NS_SUCCESS);
348 #else
349 	*((struct hostent **)rval) = NULL;
350 	return (NS_UNAVAIL);
351 #endif
352 }
353