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