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/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;
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 == (char *)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 ypbuf = alloca(resultlen + 2);
89 bcopy(result, ypbuf, resultlen);
90 ypbuf[resultlen] = '\0';
91 free(result);
92 result = 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
_gethostbynisname_r(const char * name,int af,struct hostent * he,struct hostent_data * hed)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
_gethostbynisaddr_r(const void * addr,socklen_t len,int af,struct hostent * he,struct hostent_data * hed)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
_nis_gethostbyname(void * rval,void * cb_data,va_list ap)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
_nis_gethostbyaddr(void * rval,void * cb_data,va_list ap)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 }
298