]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/net/gethostbynis.c
zfs: merge openzfs/zfs@4647353c8
[FreeBSD/FreeBSD.git] / lib / libc / net / gethostbynis.c
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 }