1156956Sume/*- 2156956Sume * Copyright (c) 2006 The FreeBSD Project. All rights reserved. 3156956Sume * 4156956Sume * Redistribution and use in source and binary forms, with or without 5156956Sume * modification, are permitted provided that the following conditions 6156956Sume * are met: 7156956Sume * 1. Redistributions of source code must retain the above copyright 8156956Sume * notice, this list of conditions and the following disclaimer. 9156956Sume * 2. Redistributions in binary form must reproduce the above copyright 10156956Sume * notice, this list of conditions and the following disclaimer in the 11156956Sume * documentation and/or other materials provided with the distribution. 12156956Sume * 13156956Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14156956Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15156956Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16156956Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17156956Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18156956Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19156956Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20156956Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21156956Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22156956Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23156956Sume * SUCH DAMAGE. 24156956Sume * 25156956Sume * $FreeBSD: releng/10.3/lib/libc/resolv/res_state.c 292462 2015-12-19 02:41:31Z vangyzen $ 26156956Sume */ 27156956Sume 28156956Sume#include <sys/types.h> 29292462Svangyzen#include <sys/stat.h> 30292462Svangyzen#include <sys/time.h> 31156956Sume#include <netinet/in.h> 32156956Sume#include <arpa/nameser.h> 33156956Sume#include <resolv.h> 34156956Sume#include <stdlib.h> 35156956Sume 36156956Sume#include "namespace.h" 37156956Sume#include "reentrant.h" 38156956Sume#include "un-namespace.h" 39156956Sume 40292462Svangyzen#include "res_private.h" 41292462Svangyzen 42156956Sume#undef _res 43156956Sume 44156956Sumestruct __res_state _res; 45156956Sume 46156956Sumestatic thread_key_t res_key; 47156956Sumestatic once_t res_init_once = ONCE_INITIALIZER; 48156956Sumestatic int res_thr_keycreated = 0; 49156956Sume 50156956Sumestatic void 51156956Sumefree_res(void *ptr) 52156956Sume{ 53156956Sume res_state statp = ptr; 54156956Sume 55157594Sume if (statp->_u._ext.ext != NULL) 56156956Sume res_ndestroy(statp); 57156956Sume free(statp); 58156956Sume} 59156956Sume 60156956Sumestatic void 61156956Sumeres_keycreate(void) 62156956Sume{ 63156956Sume res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0; 64156956Sume} 65156956Sume 66292462Svangyzenstatic res_state 67292462Svangyzenres_check_reload(res_state statp) 68292462Svangyzen{ 69292462Svangyzen struct timespec now; 70292462Svangyzen struct stat sb; 71292462Svangyzen struct __res_state_ext *ext; 72292462Svangyzen 73292462Svangyzen if ((statp->options & RES_INIT) == 0) { 74292462Svangyzen return (statp); 75292462Svangyzen } 76292462Svangyzen 77292462Svangyzen ext = statp->_u._ext.ext; 78292462Svangyzen if (ext == NULL || ext->reload_period == 0) { 79292462Svangyzen return (statp); 80292462Svangyzen } 81292462Svangyzen 82292462Svangyzen if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) != 0 || 83292462Svangyzen (now.tv_sec - ext->conf_stat) < ext->reload_period) { 84292462Svangyzen return (statp); 85292462Svangyzen } 86292462Svangyzen 87292462Svangyzen ext->conf_stat = now.tv_sec; 88292462Svangyzen if (stat(_PATH_RESCONF, &sb) == 0 && 89292462Svangyzen (sb.st_mtim.tv_sec != ext->conf_mtim.tv_sec || 90292462Svangyzen sb.st_mtim.tv_nsec != ext->conf_mtim.tv_nsec)) { 91292462Svangyzen statp->options &= ~RES_INIT; 92292462Svangyzen } 93292462Svangyzen 94292462Svangyzen return (statp); 95292462Svangyzen} 96292462Svangyzen 97156956Sumeres_state 98156956Sume__res_state(void) 99156956Sume{ 100156956Sume res_state statp; 101156956Sume 102156956Sume if (thr_main() != 0) 103292462Svangyzen return res_check_reload(&_res); 104156956Sume 105156956Sume if (thr_once(&res_init_once, res_keycreate) != 0 || 106156956Sume !res_thr_keycreated) 107156956Sume return (&_res); 108156956Sume 109156956Sume statp = thr_getspecific(res_key); 110156956Sume if (statp != NULL) 111292462Svangyzen return res_check_reload(statp); 112156956Sume statp = calloc(1, sizeof(*statp)); 113156956Sume if (statp == NULL) 114156956Sume return (&_res); 115156956Sume#ifdef __BIND_RES_TEXT 116156956Sume statp->options = RES_TIMEOUT; /* Motorola, et al. */ 117156956Sume#endif 118156956Sume if (thr_setspecific(res_key, statp) == 0) 119156956Sume return (statp); 120156956Sume free(statp); 121156956Sume return (&_res); 122156956Sume} 123