Merge branch 'vendor/DHCPCD'
[dragonfly.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  * $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
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
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
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 *
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 *
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
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
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 }