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 57 #ifdef __HAIKU__ 58 #include <libutil.h> 59 #include <FindDirectory.h> 60 #endif 61 62 #ifdef __weak_alias 63 __weak_alias(sethostent,_sethostent) 64 __weak_alias(endhostent,_endhostent) 65 #endif 66 67 #ifndef _REENTRANT 68 void res_close(void); 69 #endif 70 71 static struct hostent *_hf_gethtbyname2(const char *, int, struct getnamaddr *); 72 73 void 74 /*ARGSUSED*/ 75 sethostent(int stayopen) 76 { 77 #ifndef _REENTRANT 78 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 79 return; 80 if (stayopen) 81 _res.options |= RES_STAYOPEN | RES_USEVC; 82 #endif 83 sethostent_r(&_h_file); 84 } 85 86 void 87 endhostent(void) 88 { 89 #ifndef _REENTRANT 90 _res.options &= ~(RES_STAYOPEN | RES_USEVC); 91 res_close(); 92 #endif 93 endhostent_r(&_h_file); 94 } 95 96 void 97 sethostent_r(FILE **hf) 98 { 99 if (!*hf) { 100 #ifdef __HAIKU__ 101 char buffer[256]; 102 find_directory(B_SYSTEM_SETTINGS_DIRECTORY, 0, false, 103 buffer, sizeof(buffer)); 104 strlcat(buffer, "/network/hosts", sizeof(buffer)); 105 *hf = fopen(buffer, "re"); 106 #else 107 *hf = fopen(_h_hosts, "re"); 108 #endif 109 } else 110 rewind(*hf); 111 } 112 113 void 114 endhostent_r(FILE **hf) 115 { 116 if (*hf) { 117 (void)fclose(*hf); 118 *hf = NULL; 119 } 120 } 121 122 /*ARGSUSED*/ 123 int 124 _hf_gethtbyname(void *rv, void *cb_data, va_list ap) 125 { 126 struct hostent *hp; 127 const char *name; 128 int af; 129 struct getnamaddr *info = rv; 130 131 _DIAGASSERT(rv != NULL); 132 133 name = va_arg(ap, char *); 134 /* NOSTRICT skip string len */(void)va_arg(ap, int); 135 af = va_arg(ap, int); 136 137 #if 0 138 { 139 res_state res = __res_get_state(); 140 if (res == NULL) 141 return NS_NOTFOUND; 142 if (res->options & RES_USE_INET6) 143 hp = _hf_gethtbyname2(name, AF_INET6, info); 144 else 145 hp = NULL; 146 if (hp == NULL) 147 hp = _hf_gethtbyname2(name, AF_INET, info); 148 __res_put_state(res); 149 } 150 #else 151 hp = _hf_gethtbyname2(name, af, info); 152 #endif 153 if (hp == NULL) { 154 *info->he = HOST_NOT_FOUND; 155 return NS_NOTFOUND; 156 } 157 return NS_SUCCESS; 158 } 159 160 struct hostent * 161 _hf_gethtbyname2(const char *name, int af, struct getnamaddr *info) 162 { 163 struct hostent *hp, hent; 164 char *buf, *ptr; 165 size_t len, anum, num, i; 166 FILE *hf; 167 char *aliases[MAXALIASES]; 168 char *addr_ptrs[MAXADDRS]; 169 170 _DIAGASSERT(name != NULL); 171 172 hf = NULL; 173 sethostent_r(&hf); 174 if (hf == NULL) { 175 errno = EINVAL; 176 *info->he = NETDB_INTERNAL; 177 return NULL; 178 } 179 180 if ((ptr = buf = malloc(len = info->buflen)) == NULL) { 181 *info->he = NETDB_INTERNAL; 182 return NULL; 183 } 184 185 anum = 0; /* XXX: gcc */ 186 hent.h_name = NULL; /* XXX: gcc */ 187 hent.h_addrtype = 0; /* XXX: gcc */ 188 hent.h_length = 0; /* XXX: gcc */ 189 190 for (num = 0; num < MAXADDRS;) { 191 info->hp->h_addrtype = af; 192 info->hp->h_length = 0; 193 194 hp = gethostent_r(hf, info->hp, info->buf, info->buflen, 195 info->he); 196 if (hp == NULL) 197 break; 198 199 if (strcasecmp(hp->h_name, name) != 0) { 200 char **cp; 201 for (cp = hp->h_aliases; *cp != NULL; cp++) 202 if (strcasecmp(*cp, name) == 0) 203 break; 204 if (*cp == NULL) continue; 205 } 206 207 if (num == 0) { 208 hent.h_addrtype = af = hp->h_addrtype; 209 hent.h_length = hp->h_length; 210 211 HENT_SCOPY(hent.h_name, hp->h_name, ptr, len); 212 for (anum = 0; hp->h_aliases[anum]; anum++) { 213 if (anum >= __arraycount(aliases)) 214 goto nospc; 215 HENT_SCOPY(aliases[anum], hp->h_aliases[anum], 216 ptr, len); 217 } 218 ptr = (void *)ALIGN(ptr); 219 if ((size_t)(ptr - buf) >= info->buflen) 220 goto nospc; 221 } 222 223 if (num >= __arraycount(addr_ptrs)) 224 goto nospc; 225 HENT_COPY(addr_ptrs[num], hp->h_addr_list[0], hp->h_length, ptr, 226 len); 227 num++; 228 } 229 endhostent_r(&hf); 230 231 if (num == 0) { 232 *info->he = HOST_NOT_FOUND; 233 free(buf); 234 return NULL; 235 } 236 237 hp = info->hp; 238 ptr = info->buf; 239 len = info->buflen; 240 241 hp->h_addrtype = hent.h_addrtype; 242 hp->h_length = hent.h_length; 243 244 HENT_ARRAY(hp->h_aliases, anum, ptr, len); 245 HENT_ARRAY(hp->h_addr_list, num, ptr, len); 246 247 for (i = 0; i < num; i++) 248 HENT_COPY(hp->h_addr_list[i], addr_ptrs[i], hp->h_length, ptr, 249 len); 250 hp->h_addr_list[num] = NULL; 251 252 HENT_SCOPY(hp->h_name, hent.h_name, ptr, len); 253 254 for (i = 0; i < anum; i++) 255 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len); 256 hp->h_aliases[anum] = NULL; 257 258 free(buf); 259 return hp; 260 nospc: 261 *info->he = NETDB_INTERNAL; 262 free(buf); 263 errno = ENOSPC; 264 return NULL; 265 } 266 267 /*ARGSUSED*/ 268 int 269 _hf_gethtbyaddr(void *rv, void *cb_data, va_list ap) 270 { 271 struct hostent *hp; 272 const unsigned char *addr; 273 struct getnamaddr *info = rv; 274 FILE *hf; 275 276 _DIAGASSERT(rv != NULL); 277 278 addr = va_arg(ap, unsigned char *); 279 info->hp->h_length = va_arg(ap, int); 280 info->hp->h_addrtype = va_arg(ap, int); 281 282 hf = NULL; 283 sethostent_r(&hf); 284 if (hf == NULL) { 285 *info->he = NETDB_INTERNAL; 286 return NS_UNAVAIL; 287 } 288 while ((hp = gethostent_r(hf, info->hp, info->buf, info->buflen, 289 info->he)) != NULL) 290 if (!memcmp(hp->h_addr_list[0], addr, (size_t)hp->h_length)) 291 break; 292 endhostent_r(&hf); 293 294 if (hp == NULL) { 295 *info->he = HOST_NOT_FOUND; 296 return NS_NOTFOUND; 297 } 298 return NS_SUCCESS; 299 } 300