1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/socket.h> 33 #include <netinet/in.h> 34 #include <arpa/inet.h> 35 #include <arpa/nameser.h> 36 #include <netdb.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <ctype.h> 40 #include <errno.h> 41 #include <string.h> 42 #include <stdarg.h> 43 #include <nsswitch.h> 44 #include <resolv.h> /* XXX */ 45 #ifdef YP 46 #include <rpc/rpc.h> 47 #include <rpcsvc/yp_prot.h> 48 #include <rpcsvc/ypclnt.h> 49 #endif 50 #include "netdb_private.h" 51 52 #ifdef YP 53 static int 54 _gethostbynis(const char *name, char *map, int af, struct hostent *he, 55 struct hostent_data *hed) 56 { 57 char *p, *bp, *ep; 58 char *cp, **q; 59 char *result; 60 int resultlen, size, addrok = 0; 61 char ypbuf[YPMAXRECORD + 2]; 62 res_state statp; 63 64 statp = __res_state(); 65 switch(af) { 66 case AF_INET: 67 size = NS_INADDRSZ; 68 break; 69 case AF_INET6: 70 size = NS_IN6ADDRSZ; 71 break; 72 default: 73 errno = EAFNOSUPPORT; 74 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 75 return (-1); 76 } 77 78 if (hed->yp_domain == (char *)NULL) 79 if (yp_get_default_domain (&hed->yp_domain)) { 80 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 81 return (-1); 82 } 83 84 if (yp_match(hed->yp_domain, map, name, strlen(name), &result, 85 &resultlen)) { 86 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 87 return (-1); 88 } 89 90 /* avoid potential memory leak */ 91 bcopy((char *)result, (char *)&ypbuf, resultlen); 92 ypbuf[resultlen] = '\0'; 93 free(result); 94 result = (char *)&ypbuf; 95 96 if ((cp = strchr(result, '\n'))) 97 *cp = '\0'; 98 99 cp = strpbrk(result, " \t"); 100 *cp++ = '\0'; 101 he->h_addr_list = hed->h_addr_ptrs; 102 he->h_addr = (char *)hed->host_addr; 103 switch (af) { 104 case AF_INET: 105 addrok = inet_aton(result, (struct in_addr *)hed->host_addr); 106 if (addrok != 1) 107 break; 108 if (statp->options & RES_USE_INET6) { 109 _map_v4v6_address((char *)hed->host_addr, 110 (char *)hed->host_addr); 111 af = AF_INET6; 112 size = NS_IN6ADDRSZ; 113 } 114 break; 115 case AF_INET6: 116 addrok = inet_pton(af, result, hed->host_addr); 117 break; 118 } 119 if (addrok != 1) { 120 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 121 return (-1); 122 } 123 he->h_addr_list[1] = NULL; 124 he->h_length = size; 125 he->h_addrtype = af; 126 while (*cp == ' ' || *cp == '\t') 127 cp++; 128 bp = hed->hostbuf; 129 ep = hed->hostbuf + sizeof hed->hostbuf; 130 he->h_name = bp; 131 q = he->h_aliases = hed->host_aliases; 132 p = strpbrk(cp, " \t"); 133 if (p != NULL) 134 *p++ = '\0'; 135 size = strlen(cp) + 1; 136 if (ep - bp < size) { 137 RES_SET_H_ERRNO(statp, NO_RECOVERY); 138 return (-1); 139 } 140 strlcpy(bp, cp, ep - bp); 141 bp += size; 142 cp = p; 143 while (cp && *cp) { 144 if (*cp == ' ' || *cp == '\t') { 145 cp++; 146 continue; 147 } 148 if (q >= &hed->host_aliases[_MAXALIASES - 1]) 149 break; 150 p = strpbrk(cp, " \t"); 151 if (p != NULL) 152 *p++ = '\0'; 153 size = strlen(cp) + 1; 154 if (ep - bp < size) 155 break; 156 strlcpy(bp, cp, ep - bp); 157 *q++ = bp; 158 bp += size; 159 cp = p; 160 } 161 *q = NULL; 162 return (0); 163 } 164 165 static int 166 _gethostbynisname_r(const char *name, int af, struct hostent *he, 167 struct hostent_data *hed) 168 { 169 char *map; 170 171 switch (af) { 172 case AF_INET: 173 map = "hosts.byname"; 174 break; 175 default: 176 map = "ipnodes.byname"; 177 break; 178 } 179 return (_gethostbynis(name, map, af, he, hed)); 180 } 181 182 static int 183 _gethostbynisaddr_r(const void *addr, socklen_t len, int af, 184 struct hostent *he, struct hostent_data *hed) 185 { 186 char *map; 187 char numaddr[46]; 188 189 switch (af) { 190 case AF_INET: 191 map = "hosts.byaddr"; 192 break; 193 default: 194 map = "ipnodes.byaddr"; 195 break; 196 } 197 if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) 198 return (-1); 199 return (_gethostbynis(numaddr, map, af, he, hed)); 200 } 201 #endif /* YP */ 202 203 int 204 _nis_gethostbyname(void *rval, void *cb_data, va_list ap) 205 { 206 #ifdef YP 207 const char *name; 208 int af; 209 char *buffer; 210 size_t buflen; 211 int *errnop, *h_errnop; 212 struct hostent *hptr, he; 213 struct hostent_data *hed; 214 res_state statp; 215 216 name = va_arg(ap, const char *); 217 af = va_arg(ap, int); 218 hptr = va_arg(ap, struct hostent *); 219 buffer = va_arg(ap, char *); 220 buflen = va_arg(ap, size_t); 221 errnop = va_arg(ap, int *); 222 h_errnop = va_arg(ap, int *); 223 224 *((struct hostent **)rval) = NULL; 225 226 statp = __res_state(); 227 if ((hed = __hostent_data_init()) == NULL) { 228 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 229 *h_errnop = statp->res_h_errno; 230 return (NS_NOTFOUND); 231 } 232 233 if (_gethostbynisname_r(name, af, &he, hed) != 0) { 234 *h_errnop = statp->res_h_errno; 235 return (NS_NOTFOUND); 236 } 237 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 238 *errnop = errno; 239 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 240 *h_errnop = statp->res_h_errno; 241 return (NS_RETURN); 242 } 243 *((struct hostent **)rval) = hptr; 244 return (NS_SUCCESS); 245 #else 246 *((struct hostent **)rval) = NULL; 247 return (NS_UNAVAIL); 248 #endif 249 } 250 251 int 252 _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap) 253 { 254 #ifdef YP 255 const void *addr; 256 socklen_t len; 257 int af; 258 char *buffer; 259 size_t buflen; 260 int *errnop, *h_errnop; 261 struct hostent *hptr, he; 262 struct hostent_data *hed; 263 res_state statp; 264 265 addr = va_arg(ap, const void *); 266 len = va_arg(ap, socklen_t); 267 af = va_arg(ap, int); 268 hptr = va_arg(ap, struct hostent *); 269 buffer = va_arg(ap, char *); 270 buflen = va_arg(ap, size_t); 271 errnop = va_arg(ap, int *); 272 h_errnop = va_arg(ap, int *); 273 274 *((struct hostent **)rval) = NULL; 275 276 statp = __res_state(); 277 if ((hed = __hostent_data_init()) == NULL) { 278 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 279 *h_errnop = statp->res_h_errno; 280 return (NS_NOTFOUND); 281 } 282 283 if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) { 284 *h_errnop = statp->res_h_errno; 285 return (NS_NOTFOUND); 286 } 287 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 288 *errnop = errno; 289 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 290 *h_errnop = statp->res_h_errno; 291 return (NS_RETURN); 292 } 293 *((struct hostent **)rval) = hptr; 294 return (NS_SUCCESS); 295 #else 296 *((struct hostent **)rval) = NULL; 297 return (NS_UNAVAIL); 298 #endif 299 } 300