xref: /freebsd/lib/libc/net/gethostbynis.c (revision 3d11b6c8f01e1fca5936a11d6996448467851a94)
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$");
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
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[YPMAXRECORD + 2];
60 
61 	switch(af) {
62 	case AF_INET:
63 		size = NS_INADDRSZ;
64 		break;
65 	case AF_INET6:
66 		size = NS_IN6ADDRSZ;
67 		break;
68 	default:
69 		errno = EAFNOSUPPORT;
70 		RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
71 		return -1;
72 	}
73 
74 	if (hed->yp_domain == (char *)NULL)
75 		if (yp_get_default_domain (&hed->yp_domain)) {
76 			RES_SET_H_ERRNO(hed->res, NETDB_INTERNAL);
77 			return -1;
78 		}
79 
80 	if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
81 	    &resultlen)) {
82 		RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
83 		return -1;
84 	}
85 
86 	/* avoid potential memory leak */
87 	bcopy((char *)result, (char *)&ypbuf, resultlen);
88 	ypbuf[resultlen] = '\0';
89 	free(result);
90 	result = (char *)&ypbuf;
91 
92 	if ((cp = index(result, '\n')))
93 		*cp = '\0';
94 
95 	cp = strpbrk(result, " \t");
96 	*cp++ = '\0';
97 	he->h_addr_list = hed->h_addr_ptrs;
98 	he->h_addr = (char *)hed->host_addr;
99 	switch (af) {
100 	case AF_INET:
101 		addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
102 		if (addrok != 1)
103 			break;
104 		if (hed->res->options & RES_USE_INET6) {
105 			_map_v4v6_address((char *)hed->host_addr,
106 			    (char *)hed->host_addr);
107 			af = AF_INET6;
108 			size = NS_IN6ADDRSZ;
109 		}
110 		break;
111 	case AF_INET6:
112 		addrok = inet_pton(af, result, hed->host_addr);
113 		break;
114 	}
115 	if (addrok != 1) {
116 		RES_SET_H_ERRNO(hed->res, HOST_NOT_FOUND);
117 		return -1;
118 	}
119 	he->h_addr_list[1] = NULL;
120 	he->h_length = size;
121 	he->h_addrtype = af;
122 	while (*cp == ' ' || *cp == '\t')
123 		cp++;
124 	bp = hed->hostbuf;
125 	ep = hed->hostbuf + sizeof hed->hostbuf;
126 	he->h_name = bp;
127 	q = he->h_aliases = hed->host_aliases;
128 	p = strpbrk(cp, " \t");
129 	if (p != NULL)
130 		*p++ = '\0';
131 	size = strlen(cp) + 1;
132 	if (ep - bp < size) {
133 		RES_SET_H_ERRNO(hed->res, NO_RECOVERY);
134 		return -1;
135 	}
136 	strlcpy(bp, cp, ep - bp);
137 	bp += size;
138 	cp = p;
139 	while (cp && *cp) {
140 		if (*cp == ' ' || *cp == '\t') {
141 			cp++;
142 			continue;
143 		}
144 		if (q >= &hed->host_aliases[_MAXALIASES - 1])
145 			break;
146 		p = strpbrk(cp, " \t");
147 		if (p != NULL)
148 			*p++ = '\0';
149 		size = strlen(cp) + 1;
150 		if (ep - bp < size)
151 			break;
152 		strlcpy(bp, cp, ep - bp);
153 		*q++ = bp;
154 		bp += size;
155 		cp = p;
156 	}
157 	*q = NULL;
158 	return 0;
159 }
160 
161 static int
162 _gethostbynisname_r(const char *name, int af, struct hostent *he,
163     struct hostent_data *hed)
164 {
165 	char *map;
166 
167 	switch (af) {
168 	case AF_INET:
169 		map = "hosts.byname";
170 		break;
171 	default:
172 		map = "ipnodes.byname";
173 		break;
174 	}
175 	return _gethostbynis(name, map, af, he, hed);
176 }
177 
178 static int
179 _gethostbynisaddr_r(const char *addr, int len, int af, struct hostent *he,
180     struct hostent_data *hed)
181 {
182 	char *map;
183 	char numaddr[46];
184 
185 	switch (af) {
186 	case AF_INET:
187 		map = "hosts.byaddr";
188 		break;
189 	default:
190 		map = "ipnodes.byaddr";
191 		break;
192 	}
193 	if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
194 		return -1;
195 	return _gethostbynis(numaddr, map, af, he, hed);
196 }
197 #endif /* YP */
198 
199 /* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */
200 struct hostent *
201 _gethostbynisname(const char *name, int af)
202 {
203 #ifdef YP
204 	struct hostdata *hd;
205 	u_long oresopt;
206 	int error;
207 	res_state statp;
208 
209 	statp = __res_state();
210 	if ((hd = __hostdata_init()) == NULL) {
211 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
212 		return NULL;
213 	}
214 	hd->data.res = statp;
215 	oresopt = statp->options;
216 	statp->options &= ~RES_USE_INET6;
217 	error = _gethostbynisname_r(name, af, &hd->host, &hd->data);
218 	statp->options = oresopt;
219 	return (error == 0) ? &hd->host : NULL;
220 #else
221 	return NULL;
222 #endif
223 }
224 
225 struct hostent *
226 _gethostbynisaddr(const char *addr, int len, int af)
227 {
228 #ifdef YP
229 	struct hostdata *hd;
230 	u_long oresopt;
231 	int error;
232 	res_state statp;
233 
234 	statp = __res_state();
235 	if ((hd = __hostdata_init()) == NULL) {
236 		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
237 		return NULL;
238 	}
239 	hd->data.res = statp;
240 	oresopt = statp->options;
241 	statp->options &= ~RES_USE_INET6;
242 	error = _gethostbynisaddr_r(addr, len, af, &hd->host, &hd->data);
243 	statp->options = oresopt;
244 	return (error == 0) ? &hd->host : NULL;
245 #else
246 	return NULL;
247 #endif
248 }
249 
250 int
251 _nis_gethostbyname(void *rval, void *cb_data, va_list ap)
252 {
253 #ifdef YP
254 	const char *name;
255 	int af;
256 	struct hostent *he;
257 	struct hostent_data *hed;
258 	int error;
259 
260 	name = va_arg(ap, const char *);
261 	af = va_arg(ap, int);
262 	he = va_arg(ap, struct hostent *);
263 	hed = va_arg(ap, struct hostent_data *);
264 
265 	error = _gethostbynisname_r(name, af, he, hed);
266 	return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
267 #else
268 	return NS_UNAVAIL;
269 #endif
270 }
271 
272 int
273 _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
274 {
275 #ifdef YP
276 	const char *addr;
277 	int len;
278 	int af;
279 	struct hostent *he;
280 	struct hostent_data *hed;
281 	int error;
282 
283 	addr = va_arg(ap, const char *);
284 	len = va_arg(ap, int);
285 	af = va_arg(ap, int);
286 	he = va_arg(ap, struct hostent *);
287 	hed = va_arg(ap, struct hostent_data *);
288 
289 	error = _gethostbynisaddr_r(addr, len, af, he, hed);
290 	return (error == 0) ? NS_SUCCESS : NS_NOTFOUND;
291 #else
292 	return NS_UNAVAIL;
293 #endif
294 }
295