13070Spst/*- 23070Spst * Copyright (c) 1985, 1988, 1993 33070Spst * The Regents of the University of California. All rights reserved. 43070Spst * 53070Spst * Redistribution and use in source and binary forms, with or without 63070Spst * modification, are permitted provided that the following conditions 73070Spst * are met: 83070Spst * 1. Redistributions of source code must retain the above copyright 93070Spst * notice, this list of conditions and the following disclaimer. 103070Spst * 2. Redistributions in binary form must reproduce the above copyright 113070Spst * notice, this list of conditions and the following disclaimer in the 123070Spst * documentation and/or other materials provided with the distribution. 133070Spst * 4. Neither the name of the University nor the names of its contributors 143070Spst * may be used to endorse or promote products derived from this software 153070Spst * without specific prior written permission. 163070Spst * 173070Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 183070Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 193070Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 203070Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 213070Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 223070Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 233070Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 243070Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 253070Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 263070Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 273070Spst * SUCH DAMAGE. 283070Spst * - 293070Spst * Portions Copyright (c) 1993 by Digital Equipment Corporation. 308870Srgrimes * 313070Spst * Permission to use, copy, modify, and distribute this software for any 323070Spst * purpose with or without fee is hereby granted, provided that the above 333070Spst * copyright notice and this permission notice appear in all copies, and that 343070Spst * the name of Digital Equipment Corporation not be used in advertising or 353070Spst * publicity pertaining to distribution of the document or software without 363070Spst * specific, written prior permission. 378870Srgrimes * 383070Spst * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 393070Spst * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 403070Spst * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 413070Spst * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 423070Spst * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 433070Spst * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 443070Spst * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 453070Spst * SOFTWARE. 463070Spst * - 473070Spst * --Copyright-- 483070Spst */ 493070Spst 503070Spst#if defined(LIBC_SCCS) && !defined(lint) 513070Spststatic char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 523070Spst#endif /* LIBC_SCCS and not lint */ 5392986Sobrien#include <sys/cdefs.h> 5492986Sobrien__FBSDID("$FreeBSD$"); 553070Spst 563070Spst#include <sys/param.h> 573070Spst#include <sys/socket.h> 583070Spst#include <netinet/in.h> 593070Spst#include <arpa/inet.h> 603070Spst#include <netdb.h> 613070Spst#include <stdio.h> 623070Spst#include <ctype.h> 63211276Sume#include <errno.h> 643070Spst#include <string.h> 6565532Snectar#include <stdarg.h> 6665532Snectar#include <nsswitch.h> 6717903Speter#include <arpa/nameser.h> /* XXX */ 6817903Speter#include <resolv.h> /* XXX */ 69145602Sume#include "netdb_private.h" 703070Spst 713070Spstvoid 72145633Sume_sethosthtent(int f, struct hostent_data *hed) 733070Spst{ 74145633Sume if (!hed->hostf) 75145633Sume hed->hostf = fopen(_PATH_HOSTS, "r"); 763070Spst else 77145633Sume rewind(hed->hostf); 78145633Sume hed->stayopen = f; 793070Spst} 803070Spst 813070Spstvoid 82145633Sume_endhosthtent(struct hostent_data *hed) 833070Spst{ 84145633Sume if (hed->hostf && !hed->stayopen) { 85145633Sume (void) fclose(hed->hostf); 86145633Sume hed->hostf = NULL; 873070Spst } 883070Spst} 893070Spst 90145715Sumestatic int 91157779Sumegethostent_p(struct hostent *he, struct hostent_data *hed, int mapped, 92157779Sume res_state statp) 933070Spst{ 94145633Sume char *p, *bp, *ep; 9592889Sobrien char *cp, **q; 9617903Speter int af, len; 97145633Sume char hostbuf[BUFSIZ + 1]; 983070Spst 99145633Sume if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) { 100157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 101157779Sume return (-1); 10213408Speter } 10317903Speter again: 104145633Sume if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) { 105157779Sume RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 106157779Sume return (-1); 10713408Speter } 1083070Spst if (*p == '#') 1093070Spst goto again; 110139612Ssobomax cp = strpbrk(p, "#\n"); 111139612Ssobomax if (cp != NULL) 112139612Ssobomax *cp = '\0'; 11313408Speter if (!(cp = strpbrk(p, " \t"))) 1143070Spst goto again; 1153070Spst *cp++ = '\0'; 116145633Sume if (inet_pton(AF_INET6, p, hed->host_addr) > 0) { 11717903Speter af = AF_INET6; 11817903Speter len = IN6ADDRSZ; 119145633Sume } else if (inet_pton(AF_INET, p, hed->host_addr) > 0) { 120145715Sume if (mapped) { 121145633Sume _map_v4v6_address((char *)hed->host_addr, 122145633Sume (char *)hed->host_addr); 12317903Speter af = AF_INET6; 12417903Speter len = IN6ADDRSZ; 12517903Speter } else { 12617903Speter af = AF_INET; 12717903Speter len = INADDRSZ; 12817903Speter } 12917903Speter } else { 13013408Speter goto again; 13117903Speter } 132145633Sume hed->h_addr_ptrs[0] = (char *)hed->host_addr; 133145633Sume hed->h_addr_ptrs[1] = NULL; 134145633Sume he->h_addr_list = hed->h_addr_ptrs; 135145633Sume he->h_length = len; 136145633Sume he->h_addrtype = af; 1373070Spst while (*cp == ' ' || *cp == '\t') 1383070Spst cp++; 139145633Sume bp = hed->hostbuf; 140145633Sume ep = hed->hostbuf + sizeof hed->hostbuf; 141145633Sume he->h_name = bp; 142145633Sume q = he->h_aliases = hed->host_aliases; 143145633Sume if ((p = strpbrk(cp, " \t")) != NULL) 144145633Sume *p++ = '\0'; 145145633Sume len = strlen(cp) + 1; 146145633Sume if (ep - bp < len) { 147157779Sume RES_SET_H_ERRNO(statp, NO_RECOVERY); 148157779Sume return (-1); 149145633Sume } 150145633Sume strlcpy(bp, cp, ep - bp); 151145633Sume bp += len; 152145633Sume cp = p; 1533070Spst while (cp && *cp) { 1543070Spst if (*cp == ' ' || *cp == '\t') { 1553070Spst cp++; 1563070Spst continue; 1573070Spst } 158145633Sume if (q >= &hed->host_aliases[_MAXALIASES - 1]) 159145633Sume break; 160145633Sume if ((p = strpbrk(cp, " \t")) != NULL) 161145633Sume *p++ = '\0'; 162145633Sume len = strlen(cp) + 1; 163145633Sume if (ep - bp < len) 164145633Sume break; 165145633Sume strlcpy(bp, cp, ep - bp); 166145633Sume *q++ = bp; 167145633Sume bp += len; 168145633Sume cp = p; 1693070Spst } 1703070Spst *q = NULL; 171157779Sume RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 172157779Sume return (0); 1733070Spst} 1743070Spst 175145715Sumeint 176157779Sumegethostent_r(struct hostent *hptr, char *buffer, size_t buflen, 177157779Sume struct hostent **result, int *h_errnop) 178145715Sume{ 179157779Sume struct hostent_data *hed; 180157779Sume struct hostent he; 181157779Sume res_state statp; 182157779Sume 183157779Sume statp = __res_state(); 184157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 185157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 186157779Sume *h_errnop = statp->res_h_errno; 187157779Sume return (-1); 188156960Sume } 189157779Sume if ((hed = __hostent_data_init()) == NULL) { 190157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 191157779Sume *h_errnop = statp->res_h_errno; 192157779Sume return (-1); 193157779Sume } 194157779Sume if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0) 195157779Sume return (-1); 196211276Sume if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 197211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 198211276Sume *h_errnop = statp->res_h_errno; 199211276Sume return ((errno != 0) ? errno : -1); 200211276Sume } 201157779Sume *result = hptr; 202157779Sume return (0); 203145715Sume} 204145715Sume 205145633Sumestruct hostent * 206145633Sumegethostent(void) 207145633Sume{ 208145633Sume struct hostdata *hd; 209157779Sume struct hostent *rval; 210157779Sume int ret_h_errno; 211145633Sume 212145633Sume if ((hd = __hostdata_init()) == NULL) 213157779Sume return (NULL); 214157779Sume if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval, 215157779Sume &ret_h_errno) != 0) 216157779Sume return (NULL); 217157779Sume return (rval); 218145633Sume} 219145633Sume 22065532Snectarint 221145715Sume_ht_gethostbyname(void *rval, void *cb_data, va_list ap) 22265532Snectar{ 22317922Speter const char *name; 22417903Speter int af; 225157779Sume char *buffer; 226157779Sume size_t buflen; 227157779Sume int *errnop, *h_errnop; 228157779Sume struct hostent *hptr, he; 229145633Sume struct hostent_data *hed; 23092889Sobrien char **cp; 231157779Sume res_state statp; 232145633Sume int error; 23365532Snectar 23465532Snectar name = va_arg(ap, const char *); 23565532Snectar af = va_arg(ap, int); 236157779Sume hptr = va_arg(ap, struct hostent *); 237157779Sume buffer = va_arg(ap, char *); 238157779Sume buflen = va_arg(ap, size_t); 239157779Sume errnop = va_arg(ap, int *); 240157779Sume h_errnop = va_arg(ap, int *); 241145633Sume 242157779Sume *((struct hostent **)rval) = NULL; 243157779Sume 244157779Sume statp = __res_state(); 245157779Sume if ((hed = __hostent_data_init()) == NULL) { 246157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 247157779Sume *h_errnop = statp->res_h_errno; 248157779Sume return (NS_NOTFOUND); 249157779Sume } 250157779Sume 251157779Sume _sethosthtent(0, hed); 252157779Sume while ((error = gethostent_p(&he, hed, 0, statp)) == 0) { 253157779Sume if (he.h_addrtype != af) 25417903Speter continue; 255157779Sume if (he.h_addrtype == AF_INET && 256157779Sume statp->options & RES_USE_INET6) { 257157779Sume _map_v4v6_address(he.h_addr, he.h_addr); 258157779Sume he.h_length = IN6ADDRSZ; 259157779Sume he.h_addrtype = AF_INET6; 260145715Sume } 261157779Sume if (strcasecmp(he.h_name, name) == 0) 2623070Spst break; 263157779Sume for (cp = he.h_aliases; *cp != 0; cp++) 2643070Spst if (strcasecmp(*cp, name) == 0) 2653070Spst goto found; 2663070Spst } 2673070Spstfound: 268157779Sume _endhosthtent(hed); 269145633Sume 270157779Sume if (error != 0) { 271157779Sume *h_errnop = statp->res_h_errno; 272157779Sume return (NS_NOTFOUND); 273157779Sume } 274157779Sume if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 275211276Sume *errnop = errno; 276211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 277157779Sume *h_errnop = statp->res_h_errno; 278211276Sume return (NS_RETURN); 279157779Sume } 280157779Sume *((struct hostent **)rval) = hptr; 281157779Sume return (NS_SUCCESS); 2823070Spst} 2833070Spst 284145715Sumeint 28565532Snectar_ht_gethostbyaddr(void *rval, void *cb_data, va_list ap) 28665532Snectar{ 287158477Sume const void *addr; 288158477Sume socklen_t len; 289158477Sume int af; 290157779Sume char *buffer; 291157779Sume size_t buflen; 292157779Sume int *errnop, *h_errnop; 293157779Sume struct hostent *hptr, he; 294145633Sume struct hostent_data *hed; 295157779Sume res_state statp; 296145633Sume int error; 2973070Spst 298158477Sume addr = va_arg(ap, const void *); 299158477Sume len = va_arg(ap, socklen_t); 30065532Snectar af = va_arg(ap, int); 301157779Sume hptr = va_arg(ap, struct hostent *); 302157779Sume buffer = va_arg(ap, char *); 303157779Sume buflen = va_arg(ap, size_t); 304157779Sume errnop = va_arg(ap, int *); 305157779Sume h_errnop = va_arg(ap, int *); 30665532Snectar 307157779Sume *((struct hostent **)rval) = NULL; 308157779Sume 309157779Sume statp = __res_state(); 310157779Sume if ((hed = __hostent_data_init()) == NULL) { 311157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 312157779Sume *h_errnop = statp->res_h_errno; 313157779Sume return (NS_NOTFOUND); 314157779Sume } 315157779Sume 316157779Sume _sethosthtent(0, hed); 317157779Sume while ((error = gethostent_p(&he, hed, 0, statp)) == 0) 318157779Sume if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) { 319157779Sume if (he.h_addrtype == AF_INET && 320157779Sume statp->options & RES_USE_INET6) { 321157779Sume _map_v4v6_address(he.h_addr, he.h_addr); 322157779Sume he.h_length = IN6ADDRSZ; 323157779Sume he.h_addrtype = AF_INET6; 324145728Sume } 3253070Spst break; 326145728Sume } 327157779Sume _endhosthtent(hed); 32865532Snectar 329157779Sume if (error != 0) 330157779Sume return (NS_NOTFOUND); 331157779Sume if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 332211276Sume *errnop = errno; 333211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 334157779Sume *h_errnop = statp->res_h_errno; 335211276Sume return (NS_RETURN); 336157779Sume } 337157779Sume *((struct hostent **)rval) = hptr; 338157779Sume return (NS_SUCCESS); 3393070Spst} 340