/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2006 The FreeBSD Project. All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <sys/types.h>28#include <sys/stat.h>29#include <sys/time.h>30#include <netinet/in.h>31#include <arpa/nameser.h>32#include <resolv.h>33#include <stdlib.h>3435#include "namespace.h"36#include "reentrant.h"37#include "un-namespace.h"3839#include "res_private.h"4041#undef _res4243struct __res_state _res;4445static thread_key_t res_key;46static once_t res_init_once = ONCE_INITIALIZER;47static int res_thr_keycreated = 0;4849static void50free_res(void *ptr)51{52res_state statp = ptr;5354if (statp->_u._ext.ext != NULL)55res_ndestroy(statp);56free(statp);57}5859static void60res_keycreate(void)61{62res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0;63}6465static res_state66res_check_reload(res_state statp)67{68struct timespec now;69struct stat sb;70struct __res_state_ext *ext;7172if ((statp->options & RES_INIT) == 0) {73return (statp);74}7576ext = statp->_u._ext.ext;77if (ext == NULL || ext->reload_period == 0) {78return (statp);79}8081if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) != 0 ||82(now.tv_sec - ext->conf_stat) < ext->reload_period) {83return (statp);84}8586ext->conf_stat = now.tv_sec;87if (stat(_PATH_RESCONF, &sb) == 0 &&88(sb.st_mtim.tv_sec != ext->conf_mtim.tv_sec ||89sb.st_mtim.tv_nsec != ext->conf_mtim.tv_nsec)) {90statp->options &= ~RES_INIT;91}9293return (statp);94}9596res_state97__res_state(void)98{99res_state statp;100101if (thr_main() != 0)102return res_check_reload(&_res);103104if (thr_once(&res_init_once, res_keycreate) != 0 ||105!res_thr_keycreated)106return (&_res);107108statp = thr_getspecific(res_key);109if (statp != NULL)110return res_check_reload(statp);111statp = calloc(1, sizeof(*statp));112if (statp == NULL)113return (&_res);114#ifdef __BIND_RES_TEXT115statp->options = RES_TIMEOUT; /* Motorola, et al. */116#endif117if (thr_setspecific(res_key, statp) == 0)118return (statp);119free(statp);120return (&_res);121}122123124