1 /*- 2 * Copyright (c) 1985, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * - 29 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 30 * 31 * Permission to use, copy, modify, and distribute this software for any 32 * purpose with or without fee is hereby granted, provided that the above 33 * copyright notice and this permission notice appear in all copies, and that 34 * the name of Digital Equipment Corporation not be used in advertising or 35 * publicity pertaining to distribution of the document or software without 36 * specific, written prior permission. 37 * 38 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 39 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 40 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 41 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 42 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 43 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 44 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 45 * SOFTWARE. 46 * - 47 * --Copyright-- 48 */ 49 50 #if defined(LIBC_SCCS) && !defined(lint) 51 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 52 #endif /* LIBC_SCCS and not lint */ 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 #include <sys/param.h> 57 #include <sys/socket.h> 58 #include <netinet/in.h> 59 #include <arpa/inet.h> 60 #include <netdb.h> 61 #include <stdio.h> 62 #include <ctype.h> 63 #include <errno.h> 64 #include <string.h> 65 #include <stdarg.h> 66 #include <nsswitch.h> 67 #include <arpa/nameser.h> /* XXX */ 68 #include <resolv.h> /* XXX */ 69 #include "netdb_private.h" 70 71 void 72 _sethosthtent(int f, struct hostent_data *hed) 73 { 74 if (!hed->hostf) 75 hed->hostf = fopen(_PATH_HOSTS, "r"); 76 else 77 rewind(hed->hostf); 78 hed->stayopen = f; 79 } 80 81 void 82 _endhosthtent(struct hostent_data *hed) 83 { 84 if (hed->hostf && !hed->stayopen) { 85 (void) fclose(hed->hostf); 86 hed->hostf = NULL; 87 } 88 } 89 90 static int 91 gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped, 92 res_state statp) 93 { 94 char *p, *bp, *ep; 95 char *cp, **q; 96 int af, len; 97 char hostbuf[BUFSIZ + 1]; 98 99 if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) { 100 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 101 return (-1); 102 } 103 again: 104 if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) { 105 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 106 return (-1); 107 } 108 if (*p == '#') 109 goto again; 110 cp = strpbrk(p, "#\n"); 111 if (cp != NULL) 112 *cp = '\0'; 113 if (!(cp = strpbrk(p, " \t"))) 114 goto again; 115 *cp++ = '\0'; 116 if (inet_pton(AF_INET6, p, hed->host_addr) > 0) { 117 af = AF_INET6; 118 len = IN6ADDRSZ; 119 } else if (inet_pton(AF_INET, p, hed->host_addr) > 0) { 120 if (mapped) { 121 _map_v4v6_address((char *)hed->host_addr, 122 (char *)hed->host_addr); 123 af = AF_INET6; 124 len = IN6ADDRSZ; 125 } else { 126 af = AF_INET; 127 len = INADDRSZ; 128 } 129 } else { 130 goto again; 131 } 132 hed->h_addr_ptrs[0] = (char *)hed->host_addr; 133 hed->h_addr_ptrs[1] = NULL; 134 he->h_addr_list = hed->h_addr_ptrs; 135 he->h_length = len; 136 he->h_addrtype = af; 137 while (*cp == ' ' || *cp == '\t') 138 cp++; 139 bp = hed->hostbuf; 140 ep = hed->hostbuf + sizeof hed->hostbuf; 141 he->h_name = bp; 142 q = he->h_aliases = hed->host_aliases; 143 if ((p = strpbrk(cp, " \t")) != NULL) 144 *p++ = '\0'; 145 len = strlen(cp) + 1; 146 if (ep - bp < len) { 147 RES_SET_H_ERRNO(statp, NO_RECOVERY); 148 return (-1); 149 } 150 strlcpy(bp, cp, ep - bp); 151 bp += len; 152 cp = p; 153 while (cp && *cp) { 154 if (*cp == ' ' || *cp == '\t') { 155 cp++; 156 continue; 157 } 158 if (q >= &hed->host_aliases[_MAXALIASES - 1]) 159 break; 160 if ((p = strpbrk(cp, " \t")) != NULL) 161 *p++ = '\0'; 162 len = strlen(cp) + 1; 163 if (ep - bp < len) 164 break; 165 strlcpy(bp, cp, ep - bp); 166 *q++ = bp; 167 bp += len; 168 cp = p; 169 } 170 *q = NULL; 171 RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 172 return (0); 173 } 174 175 int 176 gethostent_r(struct hostent *hptr, char *buffer, size_t buflen, 177 struct hostent **result, int *h_errnop) 178 { 179 struct hostent_data *hed; 180 struct hostent he; 181 res_state statp; 182 183 statp = __res_state(); 184 if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 185 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 186 *h_errnop = statp->res_h_errno; 187 return (-1); 188 } 189 if ((hed = __hostent_data_init()) == NULL) { 190 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 191 *h_errnop = statp->res_h_errno; 192 return (-1); 193 } 194 if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0) 195 return (-1); 196 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 197 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 198 *h_errnop = statp->res_h_errno; 199 return ((errno != 0) ? errno : -1); 200 } 201 *result = hptr; 202 return (0); 203 } 204 205 struct hostent * 206 gethostent(void) 207 { 208 struct hostdata *hd; 209 struct hostent *rval; 210 int ret_h_errno; 211 212 if ((hd = __hostdata_init()) == NULL) 213 return (NULL); 214 if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval, 215 &ret_h_errno) != 0) 216 return (NULL); 217 return (rval); 218 } 219 220 int 221 _ht_gethostbyname(void *rval, void *cb_data, va_list ap) 222 { 223 const char *name; 224 int af; 225 char *buffer; 226 size_t buflen; 227 int *errnop, *h_errnop; 228 struct hostent *hptr, he; 229 struct hostent_data *hed; 230 char **cp; 231 res_state statp; 232 int error; 233 234 name = va_arg(ap, const char *); 235 af = va_arg(ap, int); 236 hptr = va_arg(ap, struct hostent *); 237 buffer = va_arg(ap, char *); 238 buflen = va_arg(ap, size_t); 239 errnop = va_arg(ap, int *); 240 h_errnop = va_arg(ap, int *); 241 242 *((struct hostent **)rval) = NULL; 243 244 statp = __res_state(); 245 if ((hed = __hostent_data_init()) == NULL) { 246 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 247 *h_errnop = statp->res_h_errno; 248 return (NS_NOTFOUND); 249 } 250 251 _sethosthtent(0, hed); 252 while ((error = gethostent_p(&he, hed, 0, statp)) == 0) { 253 if (he.h_addrtype != af) 254 continue; 255 if (he.h_addrtype == AF_INET && 256 statp->options & RES_USE_INET6) { 257 _map_v4v6_address(he.h_addr, he.h_addr); 258 he.h_length = IN6ADDRSZ; 259 he.h_addrtype = AF_INET6; 260 } 261 if (strcasecmp(he.h_name, name) == 0) 262 break; 263 for (cp = he.h_aliases; *cp != 0; cp++) 264 if (strcasecmp(*cp, name) == 0) 265 goto found; 266 } 267 found: 268 _endhosthtent(hed); 269 270 if (error != 0) { 271 *h_errnop = statp->res_h_errno; 272 return (NS_NOTFOUND); 273 } 274 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 275 *errnop = errno; 276 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 277 *h_errnop = statp->res_h_errno; 278 return (NS_RETURN); 279 } 280 *((struct hostent **)rval) = hptr; 281 return (NS_SUCCESS); 282 } 283 284 int 285 _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap) 286 { 287 const void *addr; 288 socklen_t len; 289 int af; 290 char *buffer; 291 size_t buflen; 292 int *errnop, *h_errnop; 293 struct hostent *hptr, he; 294 struct hostent_data *hed; 295 res_state statp; 296 int error; 297 298 addr = va_arg(ap, const void *); 299 len = va_arg(ap, socklen_t); 300 af = va_arg(ap, int); 301 hptr = va_arg(ap, struct hostent *); 302 buffer = va_arg(ap, char *); 303 buflen = va_arg(ap, size_t); 304 errnop = va_arg(ap, int *); 305 h_errnop = va_arg(ap, int *); 306 307 *((struct hostent **)rval) = NULL; 308 309 statp = __res_state(); 310 if ((hed = __hostent_data_init()) == NULL) { 311 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 312 *h_errnop = statp->res_h_errno; 313 return (NS_NOTFOUND); 314 } 315 316 _sethosthtent(0, hed); 317 while ((error = gethostent_p(&he, hed, 0, statp)) == 0) 318 if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) { 319 if (he.h_addrtype == AF_INET && 320 statp->options & RES_USE_INET6) { 321 _map_v4v6_address(he.h_addr, he.h_addr); 322 he.h_length = IN6ADDRSZ; 323 he.h_addrtype = AF_INET6; 324 } 325 break; 326 } 327 _endhosthtent(hed); 328 329 if (error != 0) 330 return (NS_NOTFOUND); 331 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 332 *errnop = errno; 333 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 334 *h_errnop = statp->res_h_errno; 335 return (NS_RETURN); 336 } 337 *((struct hostent **)rval) = hptr; 338 return (NS_SUCCESS); 339 } 340