xref: /freebsd/lib/libc/net/gethostbynis.c (revision 63f537551380d2dab29fa402ad1269feae17e594)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
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 #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;
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 
164 static 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 
181 static 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 
202 int
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 
250 int
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