xref: /dragonfly/lib/libc/net/gethostbynis.c (revision cf515c3a6f3a8964ad592e524442bc628f8ed63b)
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