xref: /dragonfly/lib/libc/net/gethostbynis.c (revision cf515c3a)
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  * $FreeBSD: src/lib/libc/net/gethostbynis.c,v 1.28 2006/05/12 15:37:23 ume Exp $
26  */
27 
28 #include <sys/param.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <arpa/nameser.h>
33 #include <netdb.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <nsswitch.h>
41 #include <resolv.h>		/* XXX */
42 #ifdef YP
43 #include <rpc/rpc.h>
44 #include <rpcsvc/yp_prot.h>
45 #include <rpcsvc/ypclnt.h>
46 #endif
47 #include "netdb_private.h"
48 
49 #ifdef YP
50 static int
_gethostbynis(const char * name,char * map,int af,struct hostent * he,struct hostent_data * hed)51 _gethostbynis(const char *name, char *map, int af, struct hostent *he,
52 	      struct hostent_data *hed)
53 {
54 	char *p, *bp, *ep;
55 	char *cp, **q;
56 	char *result;
57 	int resultlen, size, addrok = 0;
58 	char ypbuf[YPMAXRECORD + 2];
59 	res_state statp;
60 
61 	statp = __res_state();
62 	switch(af) {
63 	case AF_INET:
64 		size = NS_INADDRSZ;
65 		break;
66 	case AF_INET6:
67 		size = NS_IN6ADDRSZ;
68 		break;
69 	default:
70 		errno = EAFNOSUPPORT;
71 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
72 		return (-1);
73 	}
74 
75 	if (hed->yp_domain == NULL)
76 		if (yp_get_default_domain (&hed->yp_domain)) {
77 			RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
78 			return (-1);
79 		}
80 
81 	if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
82 	    &resultlen)) {
83 		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
84 		return (-1);
85 	}
86 
87 	/* avoid potential memory leak */
88 	bcopy((char *)result, (char *)&ypbuf, resultlen);
89 	ypbuf[resultlen] = '\0';
90 	free(result);
91 	result = (char *)&ypbuf;
92 
93 	if ((cp = index(result, '\n')))
94 		*cp = '\0';
95 
96 	cp = strpbrk(result, " \t");
97 	*cp++ = '\0';
98 	he->h_addr_list = hed->h_addr_ptrs;
99 	he->h_addr = (char *)hed->host_addr;
100 	switch (af) {
101 	case AF_INET:
102 		addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
103 		if (addrok != 1)
104 			break;
105 		if (statp->options & RES_USE_INET6) {
106 			_map_v4v6_address((char *)hed->host_addr,
107 			    (char *)hed->host_addr);
108 			af = AF_INET6;
109 			size = NS_IN6ADDRSZ;
110 		}
111 		break;
112 	case AF_INET6:
113 		addrok = inet_pton(af, result, hed->host_addr);
114 		break;
115 	}
116 	if (addrok != 1) {
117 		RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
118 		return (-1);
119 	}
120 	he->h_addr_list[1] = NULL;
121 	he->h_length = size;
122 	he->h_addrtype = af;
123 	while (*cp == ' ' || *cp == '\t')
124 		cp++;
125 	bp = hed->hostbuf;
126 	ep = hed->hostbuf + sizeof hed->hostbuf;
127 	he->h_name = bp;
128 	q = he->h_aliases = hed->host_aliases;
129 	p = strpbrk(cp, " \t");
130 	if (p != NULL)
131 		*p++ = '\0';
132 	size = strlen(cp) + 1;
133 	if (ep - bp < size) {
134 		RES_SET_H_ERRNO(statp, NO_RECOVERY);
135 		return (-1);
136 	}
137 	strlcpy(bp, cp, ep - bp);
138 	bp += size;
139 	cp = p;
140 	while (cp && *cp) {
141 		if (*cp == ' ' || *cp == '\t') {
142 			cp++;
143 			continue;
144 		}
145 		if (q >= &hed->host_aliases[_MAXALIASES - 1])
146 			break;
147 		p = strpbrk(cp, " \t");
148 		if (p != NULL)
149 			*p++ = '\0';
150 		size = strlen(cp) + 1;
151 		if (ep - bp < size)
152 			break;
153 		strlcpy(bp, cp, ep - bp);
154 		*q++ = bp;
155 		bp += size;
156 		cp = p;
157 	}
158 	*q = NULL;
159 	return (0);
160 }
161 
162 static int
_gethostbynisname_r(const char * name,int af,struct hostent * he,struct hostent_data * hed)163 _gethostbynisname_r(const char *name, int af, struct hostent *he,
164 		    struct hostent_data *hed)
165 {
166 	char *map;
167 
168 	switch (af) {
169 	case AF_INET:
170 		map = "hosts.byname";
171 		break;
172 	default:
173 		map = "ipnodes.byname";
174 		break;
175 	}
176 	return (_gethostbynis(name, map, af, he, hed));
177 }
178 
179 static int
_gethostbynisaddr_r(const void * addr,socklen_t len __unused,int af,struct hostent * he,struct hostent_data * hed)180 _gethostbynisaddr_r(const void *addr, socklen_t len __unused, int af,
181 		    struct hostent *he, struct hostent_data *hed)
182 {
183 	char *map;
184 	char numaddr[46];
185 
186 	switch (af) {
187 	case AF_INET:
188 		map = "hosts.byaddr";
189 		break;
190 	default:
191 		map = "ipnodes.byaddr";
192 		break;
193 	}
194 	if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
195 		return (-1);
196 	return (_gethostbynis(numaddr, map, af, he, hed));
197 }
198 #endif /* YP */
199 
200 /* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */
201 struct hostent *
_gethostbynisname(const char * name,int af)202 _gethostbynisname(const char *name, int af)
203 {
204 #ifdef YP
205 	struct hostent *he;
206 	struct hostent_data *hed;
207 	u_long oresopt;
208 	int error;
209 	res_state statp;
210 
211 	statp = __res_state();
212 	if ((he = __hostent_init()) == NULL ||
213 	    (hed = __hostent_data_init()) == NULL) {
214 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
215 		return (NULL);
216 	}
217 
218 	oresopt = statp->options;
219 	statp->options &= ~RES_USE_INET6;
220 	error = _gethostbynisname_r(name, af, he, hed);
221 	statp->options = oresopt;
222 	return (error == 0) ? he : NULL;
223 #else
224 	return (NULL);
225 #endif
226 }
227 
228 struct hostent *
_gethostbynisaddr(const void * addr,socklen_t len,int af)229 _gethostbynisaddr(const void *addr, socklen_t len, int af)
230 {
231 #ifdef YP
232 	struct hostent *he;
233 	struct hostent_data *hed;
234 	u_long oresopt;
235 	int error;
236 	res_state statp;
237 
238 	statp = __res_state();
239 	if ((he = __hostent_init()) == NULL ||
240 	    (hed = __hostent_data_init()) == NULL) {
241 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
242 		return (NULL);
243 	}
244 
245 	oresopt = statp->options;
246 	statp->options &= ~RES_USE_INET6;
247 	error = _gethostbynisaddr_r(addr, len, af, he, hed);
248 	statp->options = oresopt;
249 	return (error == 0) ? he : NULL;
250 #else
251 	return (NULL);
252 #endif
253 }
254 
255 int
_nis_gethostbyname(void * rval,void * cb_data __unused,va_list ap)256 _nis_gethostbyname(void *rval, void *cb_data __unused, va_list ap)
257 {
258 #ifdef YP
259 	const char *name;
260 	int af;
261 	char *buffer;
262 	size_t buflen;
263 	int *errnop __unused;
264 	int *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 		*h_errnop = statp->res_h_errno;
292 		return (NS_NOTFOUND);
293 	}
294 	*((struct hostent **)rval) = hptr;
295 	return (NS_SUCCESS);
296 #else
297 	*((struct hostent **)rval) = NULL;
298 	return (NS_UNAVAIL);
299 #endif
300 }
301 
302 int
_nis_gethostbyaddr(void * rval,void * cb_data __unused,va_list ap)303 _nis_gethostbyaddr(void *rval, void *cb_data __unused, va_list ap)
304 {
305 #ifdef YP
306 	const void *addr;
307 	socklen_t len;
308 	int af;
309 	char *buffer;
310 	size_t buflen;
311 	int *errnop __unused;
312 	int *h_errnop;
313 	struct hostent *hptr, he;
314 	struct hostent_data *hed;
315 	res_state statp;
316 
317 	addr = va_arg(ap, const void *);
318 	len = va_arg(ap, socklen_t);
319 	af = va_arg(ap, int);
320 	hptr = va_arg(ap, struct hostent *);
321 	buffer = va_arg(ap, char *);
322 	buflen = va_arg(ap, size_t);
323 	errnop = va_arg(ap, int *);
324 	h_errnop = va_arg(ap, int *);
325 
326 	*((struct hostent **)rval) = NULL;
327 
328 	statp = __res_state();
329 	if ((hed = __hostent_data_init()) == NULL) {
330 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
331 		*h_errnop = statp->res_h_errno;
332 		return (NS_NOTFOUND);
333 	}
334 
335 	if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
336 		*h_errnop = statp->res_h_errno;
337 		return (NS_NOTFOUND);
338 	}
339 	if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
340 		*h_errnop = statp->res_h_errno;
341 		return (NS_NOTFOUND);
342 	}
343 	*((struct hostent **)rval) = hptr;
344 	return (NS_SUCCESS);
345 #else
346 	*((struct hostent **)rval) = NULL;
347 	return (NS_UNAVAIL);
348 #endif
349 }
350