]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - lib/libc/net/gethostbynis.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / lib / libc / net / gethostbynis.c
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         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         bcopy((char *)result, (char *)&ypbuf, resultlen);
90         ypbuf[resultlen] = '\0';
91         free(result);
92         result = (char *)&ypbuf;
93
94         if ((cp = strchr(result, '\n')))
95                 *cp = '\0';
96
97         cp = strpbrk(result, " \t");
98         *cp++ = '\0';
99         he->h_addr_list = hed->h_addr_ptrs;
100         he->h_addr = (char *)hed->host_addr;
101         switch (af) {
102         case AF_INET:
103                 addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
104                 if (addrok != 1)
105                         break;
106                 if (statp->options & RES_USE_INET6) {
107                         _map_v4v6_address((char *)hed->host_addr,
108                             (char *)hed->host_addr);
109                         af = AF_INET6;
110                         size = NS_IN6ADDRSZ;
111                 }
112                 break;
113         case AF_INET6:
114                 addrok = inet_pton(af, result, hed->host_addr);
115                 break;
116         }
117         if (addrok != 1) {
118                 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
119                 return (-1);
120         }
121         he->h_addr_list[1] = NULL;
122         he->h_length = size;
123         he->h_addrtype = af;
124         while (*cp == ' ' || *cp == '\t')
125                 cp++;
126         bp = hed->hostbuf;
127         ep = hed->hostbuf + sizeof hed->hostbuf;
128         he->h_name = bp;
129         q = he->h_aliases = hed->host_aliases;
130         p = strpbrk(cp, " \t");
131         if (p != NULL)
132                 *p++ = '\0';
133         size = strlen(cp) + 1;
134         if (ep - bp < size) {
135                 RES_SET_H_ERRNO(statp, NO_RECOVERY);
136                 return (-1);
137         }
138         strlcpy(bp, cp, ep - bp);
139         bp += size;
140         cp = p;
141         while (cp && *cp) {
142                 if (*cp == ' ' || *cp == '\t') {
143                         cp++;
144                         continue;
145                 }
146                 if (q >= &hed->host_aliases[_MAXALIASES - 1])
147                         break;
148                 p = strpbrk(cp, " \t");
149                 if (p != NULL)
150                         *p++ = '\0';
151                 size = strlen(cp) + 1;
152                 if (ep - bp < size)
153                         break;
154                 strlcpy(bp, cp, ep - bp);
155                 *q++ = bp;
156                 bp += size;
157                 cp = p;
158         }
159         *q = NULL;
160         return (0);
161 }
162
163 static int
164 _gethostbynisname_r(const char *name, int af, struct hostent *he,
165     struct hostent_data *hed)
166 {
167         char *map;
168
169         switch (af) {
170         case AF_INET:
171                 map = "hosts.byname";
172                 break;
173         default:
174                 map = "ipnodes.byname";
175                 break;
176         }
177         return (_gethostbynis(name, map, af, he, hed));
178 }
179
180 static int
181 _gethostbynisaddr_r(const void *addr, socklen_t len, int af,
182     struct hostent *he, struct hostent_data *hed)
183 {
184         char *map;
185         char numaddr[46];
186
187         switch (af) {
188         case AF_INET:
189                 map = "hosts.byaddr";
190                 break;
191         default:
192                 map = "ipnodes.byaddr";
193                 break;
194         }
195         if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
196                 return (-1);
197         return (_gethostbynis(numaddr, map, af, he, hed));
198 }
199 #endif /* YP */
200
201 int
202 _nis_gethostbyname(void *rval, void *cb_data, va_list ap)
203 {
204 #ifdef YP
205         const char *name;
206         int af;
207         char *buffer;
208         size_t buflen;
209         int *errnop, *h_errnop;
210         struct hostent *hptr, he;
211         struct hostent_data *hed;
212         res_state statp;
213
214         name = va_arg(ap, const char *);
215         af = va_arg(ap, int);
216         hptr = va_arg(ap, struct hostent *);
217         buffer = va_arg(ap, char *);
218         buflen = va_arg(ap, size_t);
219         errnop = va_arg(ap, int *);
220         h_errnop = va_arg(ap, int *);
221
222         *((struct hostent **)rval) = NULL;
223
224         statp = __res_state();
225         if ((hed = __hostent_data_init()) == NULL) {
226                 RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
227                 *h_errnop = statp->res_h_errno;
228                 return (NS_NOTFOUND);
229         }
230
231         if (_gethostbynisname_r(name, af, &he, hed) != 0) {
232                 *h_errnop = statp->res_h_errno;
233                 return (NS_NOTFOUND);
234         }
235         if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
236                 *errnop = errno;
237                 RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
238                 *h_errnop = statp->res_h_errno;
239                 return (NS_RETURN);
240         }
241         *((struct hostent **)rval) = hptr;
242         return (NS_SUCCESS);
243 #else
244         *((struct hostent **)rval) = NULL;
245         return (NS_UNAVAIL);
246 #endif
247 }
248
249 int
250 _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
251 {
252 #ifdef YP
253         const void *addr;
254         socklen_t len;
255         int af;
256         char *buffer;
257         size_t buflen;
258         int *errnop, *h_errnop;
259         struct hostent *hptr, he;
260         struct hostent_data *hed;
261         res_state statp;
262
263         addr = va_arg(ap, const void *);
264         len = va_arg(ap, socklen_t);
265         af = va_arg(ap, int);
266         hptr = va_arg(ap, struct hostent *);
267         buffer = va_arg(ap, char *);
268         buflen = va_arg(ap, size_t);
269         errnop = va_arg(ap, int *);
270         h_errnop = va_arg(ap, int *);
271
272         *((struct hostent **)rval) = NULL;
273
274         statp = __res_state();
275         if ((hed = __hostent_data_init()) == NULL) {
276                 RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
277                 *h_errnop = statp->res_h_errno;
278                 return (NS_NOTFOUND);
279         }
280
281         if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
282                 *h_errnop = statp->res_h_errno;
283                 return (NS_NOTFOUND);
284         }
285         if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
286                 *errnop = errno;
287                 RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
288                 *h_errnop = statp->res_h_errno;
289                 return (NS_RETURN);
290         }
291         *((struct hostent **)rval) = hptr;
292         return (NS_SUCCESS);
293 #else
294         *((struct hostent **)rval) = NULL;
295         return (NS_UNAVAIL);
296 #endif
297 }