1*65d37cedSriastradh /* $NetBSD: res_state.c,v 1.8 2024/12/15 11:34:14 riastradh Exp $ */ 29b99e159Schristos 39b99e159Schristos /*- 49b99e159Schristos * Copyright (c) 2004 The NetBSD Foundation, Inc. 59b99e159Schristos * All rights reserved. 69b99e159Schristos * 79b99e159Schristos * This code is derived from software contributed to The NetBSD Foundation 89b99e159Schristos * by Christos Zoulas. 99b99e159Schristos * 109b99e159Schristos * Redistribution and use in source and binary forms, with or without 119b99e159Schristos * modification, are permitted provided that the following conditions 129b99e159Schristos * are met: 139b99e159Schristos * 1. Redistributions of source code must retain the above copyright 149b99e159Schristos * notice, this list of conditions and the following disclaimer. 159b99e159Schristos * 2. Redistributions in binary form must reproduce the above copyright 169b99e159Schristos * notice, this list of conditions and the following disclaimer in the 179b99e159Schristos * documentation and/or other materials provided with the distribution. 189b99e159Schristos * 199b99e159Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 209b99e159Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 219b99e159Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 229b99e159Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 239b99e159Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 249b99e159Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 259b99e159Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 269b99e159Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 279b99e159Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 289b99e159Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 299b99e159Schristos * POSSIBILITY OF SUCH DAMAGE. 309b99e159Schristos */ 319b99e159Schristos 329b99e159Schristos #include <sys/cdefs.h> 339b99e159Schristos #if defined(LIBC_SCCS) && !defined(lint) 34*65d37cedSriastradh __RCSID("$NetBSD: res_state.c,v 1.8 2024/12/15 11:34:14 riastradh Exp $"); 359b99e159Schristos #endif 369b99e159Schristos 377adb4107Sriastradh /* Need to use libc-private names for atomic operations. */ 387adb4107Sriastradh #include "../../common/lib/libc/atomic/atomic_op_namespace.h" 397adb4107Sriastradh 409b99e159Schristos #include <sys/types.h> 419b99e159Schristos #include <sys/queue.h> 429b99e159Schristos #include <arpa/inet.h> 439b99e159Schristos #include <arpa/nameser.h> 449b99e159Schristos #include <stdlib.h> 459b99e159Schristos #include <unistd.h> 469b99e159Schristos #include <resolv.h> 47556949a6Schristos #include <netdb.h> 489b99e159Schristos 499b99e159Schristos #include "pthread.h" 509b99e159Schristos #include "pthread_int.h" 519b99e159Schristos 5293b9ee23Schristos static SLIST_HEAD(, _res_st) res_list = LIST_HEAD_INITIALIZER(&res_list); 539b99e159Schristos 5493b9ee23Schristos struct _res_st { 5593b9ee23Schristos /* __res_put_state() assumes st_res is the first member. */ 569b99e159Schristos struct __res_state st_res; 5793b9ee23Schristos 5893b9ee23Schristos SLIST_ENTRY(_res_st) st_list; 599b99e159Schristos }; 609b99e159Schristos 619b99e159Schristos static pthread_mutex_t res_mtx = PTHREAD_MUTEX_INITIALIZER; 629b99e159Schristos 637168861fSchristos res_state __res_state(void); 649b99e159Schristos res_state __res_get_state(void); 659b99e159Schristos void __res_put_state(res_state); 669b99e159Schristos 679b99e159Schristos #ifdef RES_STATE_DEBUG 689b99e159Schristos static void 699b99e159Schristos res_state_debug(const char *msg, void *p) 709b99e159Schristos { 719b99e159Schristos char buf[512]; 7215e9cec1Sad pthread_t self = pthread__self(); 739b99e159Schristos int len = snprintf(buf, sizeof(buf), "%p: %s %p\n", self, msg, p); 749b99e159Schristos 759b99e159Schristos (void)write(STDOUT_FILENO, buf, (size_t)len); 769b99e159Schristos } 779b99e159Schristos #else 789b99e159Schristos #define res_state_debug(a, b) 799b99e159Schristos #endif 809b99e159Schristos 819b99e159Schristos 829b99e159Schristos res_state 839b99e159Schristos __res_get_state(void) 849b99e159Schristos { 859b99e159Schristos res_state res; 8693b9ee23Schristos struct _res_st *st; 879b99e159Schristos pthread_mutex_lock(&res_mtx); 8893b9ee23Schristos st = SLIST_FIRST(&res_list); 899b99e159Schristos if (st != NULL) { 9093b9ee23Schristos SLIST_REMOVE_HEAD(&res_list, st_list); 91556949a6Schristos pthread_mutex_unlock(&res_mtx); 9293b9ee23Schristos res = &st->st_res; 9393b9ee23Schristos res_state_debug("checkout from list", st); 9493b9ee23Schristos } else { 9593b9ee23Schristos pthread_mutex_unlock(&res_mtx); 96*65d37cedSriastradh st = calloc(1, sizeof(*st)); 9793b9ee23Schristos if (st == NULL) { 98556949a6Schristos h_errno = NETDB_INTERNAL; 99556949a6Schristos return NULL; 100556949a6Schristos } 10193b9ee23Schristos res = &st->st_res; 102556949a6Schristos res->options = 0; 1039b99e159Schristos res_state_debug("alloc new", res); 1049b99e159Schristos } 10593b9ee23Schristos if ((res->options & RES_INIT) == 0) { 10693b9ee23Schristos if (res_ninit(res) == -1) { 107556949a6Schristos h_errno = NETDB_INTERNAL; 10893b9ee23Schristos free(st); 109556949a6Schristos return NULL; 110556949a6Schristos } 11193b9ee23Schristos } 1129b99e159Schristos return res; 1139b99e159Schristos } 1149b99e159Schristos 1159b99e159Schristos void 1169b99e159Schristos /*ARGSUSED*/ 1179b99e159Schristos __res_put_state(res_state res) 1189b99e159Schristos { 11993b9ee23Schristos struct _res_st *st = (struct _res_st *)(void *)res; 12093b9ee23Schristos 1219b99e159Schristos res_state_debug("free", res); 12293b9ee23Schristos pthread_mutex_lock(&res_mtx); 12393b9ee23Schristos SLIST_INSERT_HEAD(&res_list, st, st_list); 1249b99e159Schristos pthread_mutex_unlock(&res_mtx); 1259b99e159Schristos } 1267168861fSchristos 1277168861fSchristos /* 1287168861fSchristos * This is aliased via a macro to _res; don't allow multi-threaded programs 1297168861fSchristos * to use it. 1307168861fSchristos */ 1317168861fSchristos res_state 1327168861fSchristos __res_state(void) 1337168861fSchristos { 1347168861fSchristos static const char res[] = "_res is not supported for multi-threaded" 1357168861fSchristos " programs.\n"; 1367168861fSchristos (void)write(STDERR_FILENO, res, sizeof(res) - 1); 1377168861fSchristos abort(); 1387168861fSchristos return NULL; 1397168861fSchristos } 140