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 } 299