1/* $NetBSD: gethost.c,v 1.11 2013/08/27 09:53:33 christos Exp $ */ 2 3/*- 4 * Copyright (c) 1985, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * - 31 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 32 * 33 * Permission to use, copy, modify, and distribute this software for any 34 * purpose with or without fee is hereby granted, provided that the above 35 * copyright notice and this permission notice appear in all copies, and that 36 * the name of Digital Equipment Corporation not be used in advertising or 37 * publicity pertaining to distribution of the document or software without 38 * specific, written prior permission. 39 * 40 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 41 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 42 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 43 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47 * SOFTWARE. 48 * - 49 * --Copyright-- 50 */ 51 52/* Provide just /etc/hosts lookup support */ 53 54#include <sys/cdefs.h> 55 56#ifdef __weak_alias 57#define gethostbyaddr _gethostbyaddr 58#define gethostbyname _gethostbyname 59#endif 60 61#include <netdb.h> 62#include <string.h> 63#include <nsswitch.h> 64#include <errno.h> 65#include <arpa/nameser.h> 66#include <arpa/inet.h> 67#include <sys/socket.h> 68 69#include "hostent.h" 70 71#ifdef __weak_alias 72__weak_alias(gethostbyaddr,_gethostbyaddr); 73__weak_alias(gethostbyname,_gethostbyname); 74#endif 75 76int h_errno; 77FILE *_h_file; 78static struct hostent h_ent; 79static char h_buf[4096]; 80 81static struct hostent * 82getby(int (*f)(void *, void *, va_list), struct getnamaddr *info, ...) 83{ 84 va_list ap; 85 int e; 86 87 va_start(ap, info); 88 e = (*f)(info, NULL, ap); 89 va_end(ap); 90 switch (e) { 91 case NS_SUCCESS: 92 return info->hp; 93 default: 94 return NULL; 95 } 96} 97 98struct hostent * 99gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t bufsiz, 100 int *he) 101{ 102 struct getnamaddr info; 103 info.hp = hp; 104 info.buf = buf; 105 info.buflen = bufsiz; 106 info.he = he; 107 return getby(_hf_gethtbyname, &info, name, 0, AF_INET); 108} 109 110 111struct hostent * 112gethostbyname(const char *name) 113{ 114 return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno); 115} 116 117struct hostent * 118gethostbyaddr_r(const void *addr, socklen_t len, int type, struct hostent *hp, 119 char *buf, size_t bufsiz, int *he) 120{ 121 struct getnamaddr info; 122 info.hp = hp; 123 info.buf = buf; 124 info.buflen = bufsiz; 125 info.he = he; 126 return getby(_hf_gethtbyaddr, &info, addr, len, type); 127} 128 129struct hostent * 130gethostbyaddr(const void *addr, socklen_t len, int type) 131{ 132 return gethostbyaddr_r(addr, len, type, &h_ent, h_buf, sizeof(h_buf), 133 &h_errno); 134} 135 136struct hostent * 137gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he) 138{ 139 char *p, *name; 140 char *cp, **q; 141 int af, len; 142 size_t llen, anum; 143 char *aliases[MAXALIASES]; 144 struct in6_addr host_addr; 145 146 if (hf == NULL) { 147 *he = NETDB_INTERNAL; 148 errno = EINVAL; 149 return NULL; 150 } 151 again: 152 if ((p = fgetln(hf, &llen)) == NULL) { 153 *he = HOST_NOT_FOUND; 154 return NULL; 155 } 156 if (llen < 1) 157 goto again; 158 if (*p == '#') 159 goto again; 160 p[llen] = '\0'; 161 if (!(cp = strpbrk(p, "#\n"))) 162 goto again; 163 *cp = '\0'; 164 if (!(cp = strpbrk(p, " \t"))) 165 goto again; 166 *cp++ = '\0'; 167 if (inet_pton(AF_INET6, p, &host_addr) > 0) { 168 af = AF_INET6; 169 len = NS_IN6ADDRSZ; 170 } else if (inet_pton(AF_INET, p, &host_addr) > 0) { 171#if 0 172 res_state res = __res_get_state(); 173 if (res == NULL) 174 return NULL; 175 if (res->options & RES_USE_INET6) { 176 map_v4v6_address(buf, buf); 177 af = AF_INET6; 178 len = NS_IN6ADDRSZ; 179 } else { 180#endif 181 af = AF_INET; 182 len = NS_INADDRSZ; 183#if 0 184 } 185 __res_put_state(res); 186#endif 187 } else { 188 goto again; 189 } 190 /* if this is not something we're looking for, skip it. */ 191 if (hent->h_addrtype != 0 && hent->h_addrtype != af) 192 goto again; 193 if (hent->h_length != 0 && hent->h_length != len) 194 goto again; 195 196 while (*cp == ' ' || *cp == '\t') 197 cp++; 198 if ((cp = strpbrk(name = cp, " \t")) != NULL) 199 *cp++ = '\0'; 200 q = aliases; 201 while (cp && *cp) { 202 if (*cp == ' ' || *cp == '\t') { 203 cp++; 204 continue; 205 } 206 if (q >= &aliases[__arraycount(aliases)]) 207 goto nospc; 208 *q++ = cp; 209 if ((cp = strpbrk(cp, " \t")) != NULL) 210 *cp++ = '\0'; 211 } 212 hent->h_length = len; 213 hent->h_addrtype = af; 214 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen); 215 anum = (size_t)(q - aliases); 216 HENT_ARRAY(hent->h_aliases, anum, buf, buflen); 217 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, 218 buflen); 219 hent->h_addr_list[1] = NULL; 220 221 HENT_SCOPY(hent->h_name, name, buf, buflen); 222 for (size_t i = 0; i < anum; i++) 223 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen); 224 hent->h_aliases[anum] = NULL; 225 226 *he = NETDB_SUCCESS; 227 return hent; 228nospc: 229 errno = ENOSPC; 230 *he = NETDB_INTERNAL; 231 return NULL; 232} 233