1/* $NetBSD: irs_data.c,v 1.1.1.2 2012/09/09 16:07:57 christos Exp $ */ 2 3/* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1996,1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#if !defined(LINT) && !defined(CODECENTER) 21static const char rcsid[] = "Id: irs_data.c,v 1.12 2007/08/27 03:32:26 marka Exp "; 22#endif 23 24#include "port_before.h" 25 26#ifndef __BIND_NOSTATIC 27 28#include <sys/types.h> 29 30#include <netinet/in.h> 31#include <arpa/nameser.h> 32 33#include <resolv.h> 34#include <stdio.h> 35#include <string.h> 36#include <isc/memcluster.h> 37 38#ifdef DO_PTHREADS 39#include <pthread.h> 40#endif 41 42#include <irs.h> 43#include <stdlib.h> 44 45#include "port_after.h" 46 47#include "irs_data.h" 48#undef _res 49#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) 50#undef h_errno 51extern int h_errno; 52#endif 53 54extern struct __res_state _res; 55 56#ifdef DO_PTHREADS 57static pthread_key_t key; 58static int once = 0; 59#else 60static struct net_data *net_data; 61#endif 62 63void 64irs_destroy(void) { 65#ifndef DO_PTHREADS 66 if (net_data != NULL) 67 net_data_destroy(net_data); 68 net_data = NULL; 69#endif 70} 71 72void 73net_data_destroy(void *p) { 74 struct net_data *net_data = p; 75 76 res_ndestroy(net_data->res); 77 if (net_data->gr != NULL) { 78 (*net_data->gr->close)(net_data->gr); 79 net_data->gr = NULL; 80 } 81 if (net_data->pw != NULL) { 82 (*net_data->pw->close)(net_data->pw); 83 net_data->pw = NULL; 84 } 85 if (net_data->sv != NULL) { 86 (*net_data->sv->close)(net_data->sv); 87 net_data->sv = NULL; 88 } 89 if (net_data->pr != NULL) { 90 (*net_data->pr->close)(net_data->pr); 91 net_data->pr = NULL; 92 } 93 if (net_data->ho != NULL) { 94 (*net_data->ho->close)(net_data->ho); 95 net_data->ho = NULL; 96 } 97 if (net_data->nw != NULL) { 98 (*net_data->nw->close)(net_data->nw); 99 net_data->nw = NULL; 100 } 101 if (net_data->ng != NULL) { 102 (*net_data->ng->close)(net_data->ng); 103 net_data->ng = NULL; 104 } 105 if (net_data->ho_data != NULL) { 106 free(net_data->ho_data); 107 net_data->ho_data = NULL; 108 } 109 if (net_data->nw_data != NULL) { 110 free(net_data->nw_data); 111 net_data->nw_data = NULL; 112 } 113 114 (*net_data->irs->close)(net_data->irs); 115 memput(net_data, sizeof *net_data); 116} 117 118/*% 119 * applications that need a specific config file other than 120 * _PATH_IRS_CONF should call net_data_init directly rather than letting 121 * the various wrapper functions make the first call. - brister 122 */ 123 124struct net_data * 125net_data_init(const char *conf_file) { 126#ifdef DO_PTHREADS 127#ifndef LIBBIND_MUTEX_INITIALIZER 128#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 129#endif 130 static pthread_mutex_t keylock = LIBBIND_MUTEX_INITIALIZER; 131 struct net_data *net_data; 132 133 if (!once) { 134 if (pthread_mutex_lock(&keylock) != 0) 135 return (NULL); 136 if (!once) { 137 if (pthread_key_create(&key, net_data_destroy) != 0) { 138 (void)pthread_mutex_unlock(&keylock); 139 return (NULL); 140 } 141 once = 1; 142 } 143 if (pthread_mutex_unlock(&keylock) != 0) 144 return (NULL); 145 } 146 net_data = pthread_getspecific(key); 147#endif 148 149 if (net_data == NULL) { 150 net_data = net_data_create(conf_file); 151 if (net_data == NULL) 152 return (NULL); 153#ifdef DO_PTHREADS 154 if (pthread_setspecific(key, net_data) != 0) { 155 net_data_destroy(net_data); 156 return (NULL); 157 } 158#endif 159 } 160 161 return (net_data); 162} 163 164struct net_data * 165net_data_create(const char *conf_file) { 166 struct net_data *net_data; 167 168 net_data = memget(sizeof (struct net_data)); 169 if (net_data == NULL) 170 return (NULL); 171 memset(net_data, 0, sizeof (struct net_data)); 172 173 if ((net_data->irs = irs_gen_acc("", conf_file)) == NULL) { 174 memput(net_data, sizeof (struct net_data)); 175 return (NULL); 176 } 177#ifndef DO_PTHREADS 178 (*net_data->irs->res_set)(net_data->irs, &_res, NULL); 179#endif 180 181 net_data->res = (*net_data->irs->res_get)(net_data->irs); 182 if (net_data->res == NULL) { 183 (*net_data->irs->close)(net_data->irs); 184 memput(net_data, sizeof (struct net_data)); 185 return (NULL); 186 } 187 188 if ((net_data->res->options & RES_INIT) == 0U && 189 res_ninit(net_data->res) == -1) { 190 (*net_data->irs->close)(net_data->irs); 191 memput(net_data, sizeof (struct net_data)); 192 return (NULL); 193 } 194 195 return (net_data); 196} 197 198void 199net_data_minimize(struct net_data *net_data) { 200 res_nclose(net_data->res); 201} 202 203#ifdef _REENTRANT 204struct __res_state * 205__res_state(void) { 206 /* NULL param here means use the default config file. */ 207 struct net_data *net_data = net_data_init(NULL); 208 if (net_data && net_data->res) 209 return (net_data->res); 210 211 return (&_res); 212} 213#else 214#ifdef __linux 215struct __res_state * 216__res_state(void) { 217 return (&_res); 218} 219#endif 220#endif 221 222int * 223__h_errno(void) { 224 /* NULL param here means use the default config file. */ 225 struct net_data *net_data = net_data_init(NULL); 226 if (net_data && net_data->res) 227 return (&net_data->res->res_h_errno); 228#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) 229 return(&_res.res_h_errno); 230#else 231 return (&h_errno); 232#endif 233} 234 235void 236__h_errno_set(struct __res_state *res, int err) { 237 238 239#if (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) 240 res->res_h_errno = err; 241#else 242 h_errno = res->res_h_errno = err; 243#endif 244} 245 246#endif /*__BIND_NOSTATIC*/ 247 248/*! \file */ 249