13070Spst/*-
23070Spst * Copyright (c) 1994, Garrett Wollman
33070Spst *
43070Spst * Redistribution and use in source and binary forms, with or without
53070Spst * modification, are permitted provided that the following conditions
63070Spst * are met:
73070Spst * 1. Redistributions of source code must retain the above copyright
83070Spst *    notice, this list of conditions and the following disclaimer.
93070Spst * 2. Redistributions in binary form must reproduce the above copyright
103070Spst *    notice, this list of conditions and the following disclaimer in the
113070Spst *    documentation and/or other materials provided with the distribution.
123070Spst *
133070Spst * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
143070Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
153070Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
163070Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
173070Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
183070Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
193070Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
203070Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
213070Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
223070Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
233070Spst * SUCH DAMAGE.
243070Spst */
253070Spst
2692986Sobrien#include <sys/cdefs.h>
2792986Sobrien__FBSDID("$FreeBSD$");
283070Spst
293070Spst#include <sys/param.h>
303070Spst#include <sys/socket.h>
313070Spst#include <netinet/in.h>
323070Spst#include <arpa/inet.h>
3343171Sgallatin#include <arpa/nameser.h>
343070Spst#include <netdb.h>
353070Spst#include <stdio.h>
3617141Sjkh#include <stdlib.h>
373070Spst#include <ctype.h>
383070Spst#include <errno.h>
393070Spst#include <string.h>
4065532Snectar#include <stdarg.h>
4165532Snectar#include <nsswitch.h>
42145721Sume#include <resolv.h>		/* XXX */
4314639Swpaul#ifdef YP
4414639Swpaul#include <rpc/rpc.h>
4514639Swpaul#include <rpcsvc/yp_prot.h>
4614639Swpaul#include <rpcsvc/ypclnt.h>
4714639Swpaul#endif
48145633Sume#include "netdb_private.h"
493070Spst
503070Spst#ifdef YP
51145633Sumestatic int
52145633Sume_gethostbynis(const char *name, char *map, int af, struct hostent *he,
53145728Sume    struct hostent_data *hed)
543070Spst{
55145633Sume	char *p, *bp, *ep;
5692889Sobrien	char *cp, **q;
573070Spst	char *result;
58145550Sume	int resultlen, size, addrok = 0;
59145633Sume	char ypbuf[YPMAXRECORD + 2];
60157779Sume	res_state statp;
613070Spst
62157779Sume	statp = __res_state();
6317903Speter	switch(af) {
6417903Speter	case AF_INET:
6543171Sgallatin		size = NS_INADDRSZ;
6617903Speter		break;
6717903Speter	case AF_INET6:
6843171Sgallatin		size = NS_IN6ADDRSZ;
69145550Sume		break;
70145550Sume	default:
7117903Speter		errno = EAFNOSUPPORT;
72157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
73157779Sume		return (-1);
7417903Speter	}
7517903Speter
76145633Sume	if (hed->yp_domain == (char *)NULL)
77145633Sume		if (yp_get_default_domain (&hed->yp_domain)) {
78157779Sume			RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
79157779Sume			return (-1);
8065702Snectar		}
813070Spst
82145633Sume	if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
83145633Sume	    &resultlen)) {
84157779Sume		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
85157779Sume		return (-1);
8665702Snectar	}
873070Spst
8814639Swpaul	/* avoid potential memory leak */
8914639Swpaul	bcopy((char *)result, (char *)&ypbuf, resultlen);
9020900Swpaul	ypbuf[resultlen] = '\0';
9114639Swpaul	free(result);
9214639Swpaul	result = (char *)&ypbuf;
9314639Swpaul
94229403Sed	if ((cp = strchr(result, '\n')))
953070Spst		*cp = '\0';
963070Spst
973070Spst	cp = strpbrk(result, " \t");
983070Spst	*cp++ = '\0';
99145633Sume	he->h_addr_list = hed->h_addr_ptrs;
100145633Sume	he->h_addr = (char *)hed->host_addr;
101145550Sume	switch (af) {
102145550Sume	case AF_INET:
103145633Sume		addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
104145721Sume		if (addrok != 1)
105145721Sume			break;
106157779Sume		if (statp->options & RES_USE_INET6) {
107145721Sume			_map_v4v6_address((char *)hed->host_addr,
108145721Sume			    (char *)hed->host_addr);
109145721Sume			af = AF_INET6;
110145721Sume			size = NS_IN6ADDRSZ;
111145721Sume		}
112145550Sume		break;
113145550Sume	case AF_INET6:
114145633Sume		addrok = inet_pton(af, result, hed->host_addr);
115145550Sume		break;
116145550Sume	}
117145550Sume	if (addrok != 1) {
118157779Sume		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
119157779Sume		return (-1);
120145550Sume	}
121145633Sume	he->h_addr_list[1] = NULL;
122145633Sume	he->h_length = size;
123145633Sume	he->h_addrtype = af;
1243070Spst	while (*cp == ' ' || *cp == '\t')
1253070Spst		cp++;
126145633Sume	bp = hed->hostbuf;
127145633Sume	ep = hed->hostbuf + sizeof hed->hostbuf;
128145633Sume	he->h_name = bp;
129145633Sume	q = he->h_aliases = hed->host_aliases;
130145633Sume	p = strpbrk(cp, " \t");
131145633Sume	if (p != NULL)
132145633Sume		*p++ = '\0';
133145633Sume	size = strlen(cp) + 1;
134145633Sume	if (ep - bp < size) {
135157779Sume		RES_SET_H_ERRNO(statp, NO_RECOVERY);
136157779Sume		return (-1);
137145633Sume	}
138145633Sume	strlcpy(bp, cp, ep - bp);
139145633Sume	bp += size;
140145633Sume	cp = p;
1413070Spst	while (cp && *cp) {
1423070Spst		if (*cp == ' ' || *cp == '\t') {
1433070Spst			cp++;
1443070Spst			continue;
1453070Spst		}
146145633Sume		if (q >= &hed->host_aliases[_MAXALIASES - 1])
147145633Sume			break;
148145633Sume		p = strpbrk(cp, " \t");
149145633Sume		if (p != NULL)
150145633Sume			*p++ = '\0';
151145633Sume		size = strlen(cp) + 1;
152145633Sume		if (ep - bp < size)
153145633Sume			break;
154145633Sume		strlcpy(bp, cp, ep - bp);
155145633Sume		*q++ = bp;
156145633Sume		bp += size;
157145633Sume		cp = p;
1583070Spst	}
1593070Spst	*q = NULL;
160157779Sume	return (0);
16165532Snectar}
162145550Sume
163145633Sumestatic int
164145633Sume_gethostbynisname_r(const char *name, int af, struct hostent *he,
165145633Sume    struct hostent_data *hed)
166145550Sume{
167145550Sume	char *map;
168145550Sume
169145550Sume	switch (af) {
170145550Sume	case AF_INET:
171145550Sume		map = "hosts.byname";
172145550Sume		break;
173145550Sume	default:
174145550Sume		map = "ipnodes.byname";
175145550Sume		break;
176145550Sume	}
177157779Sume	return (_gethostbynis(name, map, af, he, hed));
178145550Sume}
179145550Sume
180145633Sumestatic int
181158477Sume_gethostbynisaddr_r(const void *addr, socklen_t len, int af,
182158477Sume    struct hostent *he, struct hostent_data *hed)
183145550Sume{
184145550Sume	char *map;
185145677Sume	char numaddr[46];
186145550Sume
187145550Sume	switch (af) {
188145550Sume	case AF_INET:
189145550Sume		map = "hosts.byaddr";
190145550Sume		break;
191145550Sume	default:
192145550Sume		map = "ipnodes.byaddr";
193145550Sume		break;
194145550Sume	}
195145677Sume	if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
196157779Sume		return (-1);
197157779Sume	return (_gethostbynis(numaddr, map, af, he, hed));
198145550Sume}
19965532Snectar#endif /* YP */
20065532Snectar
20165532Snectarint
20265532Snectar_nis_gethostbyname(void *rval, void *cb_data, va_list ap)
20365532Snectar{
20465532Snectar#ifdef YP
20517903Speter	const char *name;
20617903Speter	int af;
207157779Sume	char *buffer;
208157779Sume	size_t buflen;
209157779Sume	int *errnop, *h_errnop;
210157779Sume	struct hostent *hptr, he;
211145633Sume	struct hostent_data *hed;
212157779Sume	res_state statp;
21365532Snectar
21465532Snectar	name = va_arg(ap, const char *);
21565532Snectar	af = va_arg(ap, int);
216157779Sume	hptr = va_arg(ap, struct hostent *);
217157779Sume	buffer = va_arg(ap, char *);
218157779Sume	buflen = va_arg(ap, size_t);
219157779Sume	errnop = va_arg(ap, int *);
220157779Sume	h_errnop = va_arg(ap, int *);
22165532Snectar
222157779Sume	*((struct hostent **)rval) = NULL;
223157779Sume
224157779Sume	statp = __res_state();
225157779Sume	if ((hed = __hostent_data_init()) == NULL) {
226157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
227157779Sume		*h_errnop = statp->res_h_errno;
228157779Sume		return (NS_NOTFOUND);
229157779Sume	}
230157779Sume
231157779Sume	if (_gethostbynisname_r(name, af, &he, hed) != 0) {
232157779Sume		*h_errnop = statp->res_h_errno;
233157779Sume		return (NS_NOTFOUND);
234157779Sume	}
235157779Sume	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
236211276Sume		*errnop = errno;
237211276Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
238157779Sume		*h_errnop = statp->res_h_errno;
239211276Sume		return (NS_RETURN);
240157779Sume	}
241157779Sume	*((struct hostent **)rval) = hptr;
242157779Sume	return (NS_SUCCESS);
24365532Snectar#else
244157779Sume	*((struct hostent **)rval) = NULL;
245157779Sume	return (NS_UNAVAIL);
24665532Snectar#endif
2473070Spst}
2483070Spst
24965532Snectarint
25065532Snectar_nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
25165532Snectar{
25265532Snectar#ifdef YP
253158477Sume	const void *addr;
254158477Sume	socklen_t len;
25517903Speter	int af;
256157779Sume	char *buffer;
257157779Sume	size_t buflen;
258157779Sume	int *errnop, *h_errnop;
259157779Sume	struct hostent *hptr, he;
260145633Sume	struct hostent_data *hed;
261157779Sume	res_state statp;
26265532Snectar
263158477Sume	addr = va_arg(ap, const void *);
264158477Sume	len = va_arg(ap, socklen_t);
26565532Snectar	af = va_arg(ap, int);
266157779Sume	hptr = va_arg(ap, struct hostent *);
267157779Sume	buffer = va_arg(ap, char *);
268157779Sume	buflen = va_arg(ap, size_t);
269157779Sume	errnop = va_arg(ap, int *);
270157779Sume	h_errnop = va_arg(ap, int *);
271145550Sume
272157779Sume	*((struct hostent **)rval) = NULL;
273157779Sume
274157779Sume	statp = __res_state();
275157779Sume	if ((hed = __hostent_data_init()) == NULL) {
276157779Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
277157779Sume		*h_errnop = statp->res_h_errno;
278157779Sume		return (NS_NOTFOUND);
279157779Sume	}
280157779Sume
281157779Sume	if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
282157779Sume		*h_errnop = statp->res_h_errno;
283157779Sume		return (NS_NOTFOUND);
284157779Sume	}
285157779Sume	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
286211276Sume		*errnop = errno;
287211276Sume		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
288157779Sume		*h_errnop = statp->res_h_errno;
289211276Sume		return (NS_RETURN);
290157779Sume	}
291157779Sume	*((struct hostent **)rval) = hptr;
292157779Sume	return (NS_SUCCESS);
29365532Snectar#else
294157779Sume	*((struct hostent **)rval) = NULL;
295157779Sume	return (NS_UNAVAIL);
29665532Snectar#endif
2973070Spst}
298