res_state.c revision 289315
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: head/lib/libc/resolv/res_state.c 289315 2015-10-14 14:26:44Z vangyzen $ 26156956Sume */ 27156956Sume 28156956Sume#include <sys/types.h> 29289315Svangyzen#include <sys/stat.h> 30289315Svangyzen#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 40156956Sume#undef _res 41156956Sume 42156956Sumestruct __res_state _res; 43156956Sume 44156956Sumestatic thread_key_t res_key; 45156956Sumestatic once_t res_init_once = ONCE_INITIALIZER; 46156956Sumestatic int res_thr_keycreated = 0; 47156956Sume 48156956Sumestatic void 49156956Sumefree_res(void *ptr) 50156956Sume{ 51156956Sume res_state statp = ptr; 52156956Sume 53157594Sume if (statp->_u._ext.ext != NULL) 54156956Sume res_ndestroy(statp); 55156956Sume free(statp); 56156956Sume} 57156956Sume 58156956Sumestatic void 59156956Sumeres_keycreate(void) 60156956Sume{ 61156956Sume res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0; 62156956Sume} 63156956Sume 64289315Svangyzenstatic res_state 65289315Svangyzenres_check_reload(res_state statp) 66289315Svangyzen{ 67289315Svangyzen struct timespec now; 68289315Svangyzen struct stat sb; 69289315Svangyzen 70289315Svangyzen if ((statp->options & RES_INIT) == 0 || statp->reload_period == 0) { 71289315Svangyzen return (statp); 72289315Svangyzen } 73289315Svangyzen 74289315Svangyzen if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) != 0 || 75289315Svangyzen (now.tv_sec - statp->conf_stat) < statp->reload_period) { 76289315Svangyzen return (statp); 77289315Svangyzen } 78289315Svangyzen 79289315Svangyzen statp->conf_stat = now.tv_sec; 80289315Svangyzen if (stat(_PATH_RESCONF, &sb) == 0 && 81289315Svangyzen (sb.st_mtim.tv_sec != statp->conf_mtim.tv_sec || 82289315Svangyzen sb.st_mtim.tv_nsec != statp->conf_mtim.tv_nsec)) { 83289315Svangyzen statp->options &= ~RES_INIT; 84289315Svangyzen } 85289315Svangyzen 86289315Svangyzen return (statp); 87289315Svangyzen} 88289315Svangyzen 89156956Sumeres_state 90156956Sume__res_state(void) 91156956Sume{ 92156956Sume res_state statp; 93156956Sume 94156956Sume if (thr_main() != 0) 95289315Svangyzen return res_check_reload(&_res); 96156956Sume 97156956Sume if (thr_once(&res_init_once, res_keycreate) != 0 || 98156956Sume !res_thr_keycreated) 99156956Sume return (&_res); 100156956Sume 101156956Sume statp = thr_getspecific(res_key); 102156956Sume if (statp != NULL) 103289315Svangyzen return res_check_reload(statp); 104156956Sume statp = calloc(1, sizeof(*statp)); 105156956Sume if (statp == NULL) 106156956Sume return (&_res); 107156956Sume#ifdef __BIND_RES_TEXT 108156956Sume statp->options = RES_TIMEOUT; /* Motorola, et al. */ 109156956Sume#endif 110156956Sume if (thr_setspecific(res_key, statp) == 0) 111156956Sume return (statp); 112156956Sume free(statp); 113156956Sume return (&_res); 114156956Sume} 115