diff options
Diffstat (limited to 'libc/dns/resolv/res_data.cpp')
-rw-r--r-- | libc/dns/resolv/res_data.cpp | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/libc/dns/resolv/res_data.cpp b/libc/dns/resolv/res_data.cpp new file mode 100644 index 000000000..22d9f7b16 --- /dev/null +++ b/libc/dns/resolv/res_data.cpp @@ -0,0 +1,157 @@ +/* $NetBSD: res_data.c,v 1.8 2004/06/09 18:07:03 christos Exp $ */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "resolv_private.h" + +#include <pthread.h> + +extern "C" int res_ourserver_p(const res_state, const struct sockaddr*); +extern "C" int __res_vinit(res_state, int); + +class GlobalStateAccessor { + public: + GlobalStateAccessor() { + pthread_mutex_lock(&mutex); + if (!initialized) { + init(); + initialized = true; + } + } + + ~GlobalStateAccessor() { + pthread_mutex_unlock(&mutex); + } + + __res_state* get() { + return &state; + } + + int init(); + + private: + static __res_state state; + static bool initialized; + static pthread_mutex_t mutex; +}; +__res_state GlobalStateAccessor::state; +bool GlobalStateAccessor::initialized = false; +pthread_mutex_t GlobalStateAccessor::mutex = PTHREAD_MUTEX_INITIALIZER; + +int GlobalStateAccessor::init() { + // These three fields used to be statically initialized. This made + // it hard to use this code in a shared library. It is necessary, + // now that we're doing dynamic initialization here, that we preserve + // the old semantics: if an application modifies one of these three + // fields of _res before res_init() is called, res_init() will not + // alter them. Of course, if an application is setting them to + // _zero_ before calling res_init(), hoping to override what used + // to be the static default, we can't detect it and unexpected results + // will follow. Zero for any of these fields would make no sense, + // so one can safely assume that the applications were already getting + // unexpected results. + // g_nres.options is tricky since some apps were known to diddle the bits + // before res_init() was first called. We can't replicate that semantic + // with dynamic initialization (they may have turned bits off that are + // set in RES_DEFAULT). Our solution is to declare such applications + // "broken". They could fool us by setting RES_INIT but none do (yet). + if (!state.retrans) state.retrans = RES_TIMEOUT; + if (!state.retry) state.retry = 4; + if (!(state.options & RES_INIT)) state.options = RES_DEFAULT; + + // This one used to initialize implicitly to zero, so unless the app + // has set it to something in particular, we can randomize it now. + if (!state.id) state.id = res_randomid(); + + return __res_vinit(&state, 1); +} + +int res_init(void) { + GlobalStateAccessor gsa; + return gsa.init(); +} + +void p_query(const u_char* msg) { + fp_query(msg, stdout); +} + +void fp_query(const u_char* msg, FILE* file) { + fp_nquery(msg, PACKETSZ, file); +} + +void fp_nquery(const u_char* msg, int len, FILE* file) { + GlobalStateAccessor gsa; + res_pquery(gsa.get(), msg, len, file); +} + +int +res_mkquery(int op, const char* dname, int klass, int type, const u_char* data, + int datalen, const u_char* newrr_in, u_char* buf, int buflen) { + GlobalStateAccessor gsa; + return res_nmkquery(gsa.get(), op, dname, klass, type, data, datalen, newrr_in, buf, buflen); +} + +int res_query(const char* name, int klass, int type, u_char* answer, int anslen) { + GlobalStateAccessor gsa; + return res_nquery(gsa.get(), name, klass, type, answer, anslen); +} + +void res_send_setqhook(res_send_qhook hook) { + GlobalStateAccessor gsa; + gsa.get()->qhook = hook; +} + +void res_send_setrhook(res_send_rhook hook) { + GlobalStateAccessor gsa; + gsa.get()->rhook = hook; +} + +int res_isourserver(const struct sockaddr_in* inp) { + GlobalStateAccessor gsa; + return res_ourserver_p(gsa.get(), reinterpret_cast<const sockaddr*>(inp)); +} + +int res_send(const u_char* buf, int buflen, u_char* ans, int anssiz) { + GlobalStateAccessor gsa; + return res_nsend(gsa.get(), buf, buflen, ans, anssiz); +} + +void res_close(void) { + GlobalStateAccessor gsa; + res_nclose(gsa.get()); +} + +int res_search(const char* name, int klass, int type, u_char* answer, int anslen) { + GlobalStateAccessor gsa; + return res_nsearch(gsa.get(), name, klass, type, answer, anslen); +} + +int res_querydomain(const char* name, const char* domain, int klass, int type, u_char* answer, + int anslen) { + GlobalStateAccessor gsa; + return res_nquerydomain(gsa.get(), name, domain, klass, type, answer, anslen); +} + +int res_opt(int a, u_char* b, int c, int d) { + GlobalStateAccessor gsa; + return res_nopt(gsa.get(), a, b, c, d); +} + +const char* hostalias(const char* name) { + return NULL; +} |