gethostbynis.c revision 351694
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: stable/11/lib/libc/net/gethostbynis.c 351694 2019-09-02 10:20:57Z kib $");
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
51static 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;
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	ypbuf = alloca(resultlen + 2);
90	bcopy(result, ypbuf, resultlen);
91	ypbuf[resultlen] = '\0';
92	free(result);
93	result = ypbuf;
94
95	if ((cp = strchr(result, '\n')))
96		*cp = '\0';
97
98	cp = strpbrk(result, " \t");
99	*cp++ = '\0';
100	he->h_addr_list = hed->h_addr_ptrs;
101	he->h_addr = (char *)hed->host_addr;
102	switch (af) {
103	case AF_INET:
104		addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
105		if (addrok != 1)
106			break;
107		if (statp->options & RES_USE_INET6) {
108			_map_v4v6_address((char *)hed->host_addr,
109			    (char *)hed->host_addr);
110			af = AF_INET6;
111			size = NS_IN6ADDRSZ;
112		}
113		break;
114	case AF_INET6:
115		addrok = inet_pton(af, result, hed->host_addr);
116		break;
117	}
118	if (addrok != 1) {
119		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
120		return (-1);
121	}
122	he->h_addr_list[1] = NULL;
123	he->h_length = size;
124	he->h_addrtype = af;
125	while (*cp == ' ' || *cp == '\t')
126		cp++;
127	bp = hed->hostbuf;
128	ep = hed->hostbuf + sizeof hed->hostbuf;
129	he->h_name = bp;
130	q = he->h_aliases = hed->host_aliases;
131	p = strpbrk(cp, " \t");
132	if (p != NULL)
133		*p++ = '\0';
134	size = strlen(cp) + 1;
135	if (ep - bp < size) {
136		RES_SET_H_ERRNO(statp, NO_RECOVERY);
137		return (-1);
138	}
139	strlcpy(bp, cp, ep - bp);
140	bp += size;
141	cp = p;
142	while (cp && *cp) {
143		if (*cp == ' ' || *cp == '\t') {
144			cp++;
145			continue;
146		}
147		if (q >= &hed->host_aliases[_MAXALIASES - 1])
148			break;
149		p = strpbrk(cp, " \t");
150		if (p != NULL)
151			*p++ = '\0';
152		size = strlen(cp) + 1;
153		if (ep - bp < size)
154			break;
155		strlcpy(bp, cp, ep - bp);
156		*q++ = bp;
157		bp += size;
158		cp = p;
159	}
160	*q = NULL;
161	return (0);
162}
163
164static int
165_gethostbynisname_r(const char *name, int af, struct hostent *he,
166    struct hostent_data *hed)
167{
168	char *map;
169
170	switch (af) {
171	case AF_INET:
172		map = "hosts.byname";
173		break;
174	default:
175		map = "ipnodes.byname";
176		break;
177	}
178	return (_gethostbynis(name, map, af, he, hed));
179}
180
181static int
182_gethostbynisaddr_r(const void *addr, socklen_t len, int af,
183    struct hostent *he, struct hostent_data *hed)
184{
185	char *map;
186	char numaddr[46];
187
188	switch (af) {
189	case AF_INET:
190		map = "hosts.byaddr";
191		break;
192	default:
193		map = "ipnodes.byaddr";
194		break;
195	}
196	if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
197		return (-1);
198	return (_gethostbynis(numaddr, map, af, he, hed));
199}
200#endif /* YP */
201
202int
203_nis_gethostbyname(void *rval, void *cb_data, va_list ap)
204{
205#ifdef YP
206	const char *name;
207	int af;
208	char *buffer;
209	size_t buflen;
210	int *errnop, *h_errnop;
211	struct hostent *hptr, he;
212	struct hostent_data *hed;
213	res_state statp;
214
215	name = va_arg(ap, const char *);
216	af = va_arg(ap, int);
217	hptr = va_arg(ap, struct hostent *);
218	buffer = va_arg(ap, char *);
219	buflen = va_arg(ap, size_t);
220	errnop = va_arg(ap, int *);
221	h_errnop = va_arg(ap, int *);
222
223	*((struct hostent **)rval) = NULL;
224
225	statp = __res_state();
226	if ((hed = __hostent_data_init()) == NULL) {
227		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
228		*h_errnop = statp->res_h_errno;
229		return (NS_NOTFOUND);
230	}
231
232	if (_gethostbynisname_r(name, af, &he, hed) != 0) {
233		*h_errnop = statp->res_h_errno;
234		return (NS_NOTFOUND);
235	}
236	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
237		*errnop = errno;
238		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
239		*h_errnop = statp->res_h_errno;
240		return (NS_RETURN);
241	}
242	*((struct hostent **)rval) = hptr;
243	return (NS_SUCCESS);
244#else
245	*((struct hostent **)rval) = NULL;
246	return (NS_UNAVAIL);
247#endif
248}
249
250int
251_nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
252{
253#ifdef YP
254	const void *addr;
255	socklen_t len;
256	int af;
257	char *buffer;
258	size_t buflen;
259	int *errnop, *h_errnop;
260	struct hostent *hptr, he;
261	struct hostent_data *hed;
262	res_state statp;
263
264	addr = va_arg(ap, const void *);
265	len = va_arg(ap, socklen_t);
266	af = va_arg(ap, int);
267	hptr = va_arg(ap, struct hostent *);
268	buffer = va_arg(ap, char *);
269	buflen = va_arg(ap, size_t);
270	errnop = va_arg(ap, int *);
271	h_errnop = va_arg(ap, int *);
272
273	*((struct hostent **)rval) = NULL;
274
275	statp = __res_state();
276	if ((hed = __hostent_data_init()) == NULL) {
277		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
278		*h_errnop = statp->res_h_errno;
279		return (NS_NOTFOUND);
280	}
281
282	if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
283		*h_errnop = statp->res_h_errno;
284		return (NS_NOTFOUND);
285	}
286	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
287		*errnop = errno;
288		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
289		*h_errnop = statp->res_h_errno;
290		return (NS_RETURN);
291	}
292	*((struct hostent **)rval) = hptr;
293	return (NS_SUCCESS);
294#else
295	*((struct hostent **)rval) = NULL;
296	return (NS_UNAVAIL);
297#endif
298}
299