1 /* $NetBSD: irs_data.c,v 1.1.1.1 2009/04/12 15:33:42 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) 21 static 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 51 extern int h_errno; 52 #endif 53 54 extern struct __res_state _res; 55 56 #ifdef DO_PTHREADS 57 static pthread_key_t key; 58 static int once = 0; 59 #else 60 static struct net_data *net_data; 61 #endif 62 63 void 64 irs_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 72 void 73 net_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 124 struct net_data * 125 net_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 164 struct net_data * 165 net_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 198 void 199 net_data_minimize(struct net_data *net_data) { 200 res_nclose(net_data->res); 201 } 202 203 #ifdef _REENTRANT 204 struct __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 215 struct __res_state * 216 __res_state(void) { 217 return (&_res); 218 } 219 #endif 220 #endif 221 222 int * 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 235 void 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