1 /* $NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1985, 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 32 #include <sys/cdefs.h> 33 #if defined(LIBC_SCCS) && !defined(lint) 34 #if 0 35 static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93"; 36 static char rcsid[] = "Id: sethostent.c,v 8.5 1996/09/28 06:51:07 vixie Exp "; 37 #else 38 __RCSID("$NetBSD: sethostent.c,v 1.20 2014/03/17 13:24:23 christos Exp $"); 39 #endif 40 #endif /* LIBC_SCCS and not lint */ 41 42 #include "namespace.h" 43 #include <sys/param.h> 44 #include <netinet/in.h> 45 #include <arpa/nameser.h> 46 #include <arpa/inet.h> 47 #include <assert.h> 48 #include <string.h> 49 #include <nsswitch.h> 50 #include <netdb.h> 51 #include <resolv.h> 52 #include <errno.h> 53 #include <stdlib.h> 54 55 #include "hostent.h" 56 #include "resolv_private.h" 57 58 #define ALIGNBYTES (sizeof(uintptr_t) - 1) 59 #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES) 60 61 #ifndef _REENTRANT 62 void res_close(void); 63 #endif 64 65 static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *); 66 67 static const char *_h_hosts = _PATH_HOSTS; 68 69 void 70 sethostent_r(FILE **hf) 71 { 72 if (!*hf) 73 *hf = fopen(_h_hosts, "re"); 74 else 75 rewind(*hf); 76 } 77 78 void 79 endhostent_r(FILE **hf) 80 { 81 if (*hf) { 82 (void)fclose(*hf); 83 *hf = NULL; 84 } 85 } 86 87 /*ARGSUSED*/ 88 int 89 _hf_gethtbyname(void *rv, void *cb_data, va_list ap) 90 { 91 struct hostent *hp; 92 const char *name; 93 int af; 94 struct getnamaddr *info = rv; 95 96 _DIAGASSERT(rv != NULL); 97 98 name = va_arg(ap, char *); 99 /* NOSTRICT skip string len */(void)va_arg(ap, int); 100 af = va_arg(ap, int); 101 102 #if 0 103 { 104 res_state res = __res_get_state(); 105 if (res == NULL) 106 return NS_NOTFOUND; 107 if (res->options & RES_USE_INET6) 108 hp = _hf_gethtbyname2(name, AF_INET6, info); 109 else 110 hp = NULL; 111 if (hp == NULL) 112 hp = _hf_gethtbyname2(name, AF_INET, info); 113 __res_put_state(res); 114 } 115 #else 116 hp = _hf_gethtbyname2(name, af, info); 117 #endif 118 if (hp == NULL) { 119 if (*info->he == NETDB_INTERNAL && errno == ENOSPC) { 120 return NS_UNAVAIL; 121 } 122 return NS_NOTFOUND; 123 } 124 return NS_SUCCESS; 125 } 126 127 static struct hostent * 128 _hf_gethtbyname2(const char *name, int af, struct getnamaddr *info) 129 { 130 struct hostent *hp, hent; 131 char *buf, *ptr; 132 size_t len, anum, num, i; 133 FILE *hf; 134 char *aliases[MAXALIASES]; 135 char *addr_ptrs[MAXADDRS]; 136 137 _DIAGASSERT(name != NULL); 138 139 hf = NULL; 140 sethostent_r(&hf); 141 if (hf == NULL) { 142 errno = EINVAL; 143 *info->he = NETDB_INTERNAL; 144 return NULL; 145 } 146 147 if ((ptr = buf = malloc(len = info->buflen)) == NULL) { 148 endhostent_r(&hf); 149 *info->he = NETDB_INTERNAL; 150 return NULL; 151 } 152 153 anum = 0; /* XXX: gcc */ 154 hent.h_name = NULL; /* XXX: gcc */ 155 hent.h_addrtype = 0; /* XXX: gcc */ 156 hent.h_length = 0; /* XXX: gcc */ 157 158 for (num = 0; num < MAXADDRS;) { 159 info->hp->h_addrtype = af; 160 info->hp->h_length = 0; 161 162 hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, 163 info->he); 164 if (hp == NULL) { 165 if (*info->he == NETDB_INTERNAL && errno == ENOSPC) { 166 goto nospc; 167 } 168 break; 169 } 170 171 if (strcasecmp(hp->h_name, name) != 0) { 172 char **cp; 173 for (cp = hp->h_aliases; *cp != NULL; cp++) 174 if (strcasecmp(*cp, name) == 0) 175 break; 176 if (*cp == NULL) continue; 177 } 178 179 if (num == 0) { 180 hent.h_addrtype = af = hp->h_addrtype; 181 hent.h_length = hp->h_length; 182 183 HENT_SCOPY(hent.h_name, hp->h_name, ptr, len); 184 for (anum = 0; hp->h_aliases[anum]; anum++) { 185 if (anum >= MAXALIASES) 186 goto nospc; 187 HENT_SCOPY(aliases[anum], hp->h_aliases[anum], 188 ptr, len); 189 } 190 ptr = (void *)ALIGN(ptr); 191 if ((size_t)(ptr - buf) >= info->buflen) 192 goto nospc; 193 } 194 195 if (num >= MAXADDRS) 196 goto nospc; 197 HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr, 198 len); 199 num++; 200 } 201 endhostent_r(&hf); 202 203 if (num == 0) { 204 *info->he = HOST_NOT_FOUND; 205 free(buf); 206 return NULL; 207 } 208 209 hp = info->hp; 210 ptr = info->buf; 211 len = info->buflen; 212 213 hp->h_addrtype = hent.h_addrtype; 214 hp->h_length = hent.h_length; 215 216 HENT_ARRAY(hp->h_aliases, anum, ptr, len); 217 HENT_ARRAY(hp->h_addr_list, num, ptr, len); 218 219 for (i = 0; i < num; i++) 220 HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr, 221 len); 222 hp->h_addr_list[num] = NULL; 223 224 HENT_SCOPY(hp->h_name, hent.h_name, ptr, len); 225 226 for (i = 0; i < anum; i++) 227 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); 228 hp->h_aliases[anum] = NULL; 229 230 free(buf); 231 return hp; 232 nospc: 233 endhostent_r(&hf); 234 *info->he = NETDB_INTERNAL; 235 free(buf); 236 errno = ENOSPC; 237 return NULL; 238 } 239 240 /*ARGSUSED*/ 241 int 242 _hf_gethtbyaddr(void *rv, void *cb_data, va_list ap) 243 { 244 struct hostent *hp; 245 const unsigned char *addr; 246 struct getnamaddr *info = rv; 247 FILE *hf; 248 249 _DIAGASSERT(rv != NULL); 250 251 addr = va_arg(ap, unsigned char *); 252 info->hp->h_length = va_arg(ap, int); 253 info->hp->h_addrtype = va_arg(ap, int); 254 255 hf = NULL; 256 sethostent_r(&hf); 257 if (hf == NULL) { 258 *info->he = NETDB_INTERNAL; 259 return NS_UNAVAIL; 260 } 261 while ((hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen, 262 info->he)) != NULL) 263 if (!memcmp(hp->h_addr_list[0], addr, (size_t)hp->h_length)) 264 break; 265 endhostent_r(&hf); 266 267 if (hp == NULL) { 268 if (errno == ENOSPC) { 269 return NS_UNAVAIL; 270 } 271 *info->he = HOST_NOT_FOUND; 272 return NS_NOTFOUND; 273 } 274 return NS_SUCCESS; 275 } 276