/* Initialize resp if RES_INIT is not yet set or if res_init in some other thread requested re-initializing. */ int __res_maybe_init (res_state resp, int preinit) { static time_t last_mtime; struct stat statbuf; int ret; if (resp->options & RES_INIT) { ret = stat (_PATH_RESCONF, &statbuf); __libc_lock_lock (lock); if ((ret == 0) && (last_mtime != statbuf.st_mtime)) { last_mtime = statbuf.st_mtime; atomicinc (__res_initstamp); } __libc_lock_unlock (lock); if (__res_initstamp != resp->_u._ext.initstamp) { if (resp->nscount > 0) __res_iclose (resp, true); return __res_vinit (resp, 1); } return 0; } else if (preinit) { if (!resp->retrans) resp->retrans = RES_TIMEOUT; if (!resp->retry) resp->retry = 4; resp->options = RES_DEFAULT; if (!resp->id) resp->id = res_randomid (); return __res_vinit (resp, 1); } else return __res_ninit (resp); }
/* Initialize *RESP if RES_INIT is not yet set in RESP->options, or if res_init in some other thread requested re-initializing. */ static __attribute__ ((warn_unused_result)) bool maybe_init (struct resolv_context *ctx, bool preinit) { struct __res_state *resp = ctx->resp; if (resp->options & RES_INIT) { if (resp->options & RES_NORELOAD) /* Configuration reloading was explicitly disabled. */ return true; /* If there is no associated resolv_conf object despite the initialization, something modified *ctx->resp. Do not override those changes. */ if (ctx->conf != NULL && replicated_configuration_matches (ctx)) { struct resolv_conf *current = __resolv_conf_get_current (); if (current == NULL) return false; /* Check if the configuration changed. */ if (current != ctx->conf) { /* This call will detach the extended resolver state. */ if (resp->nscount > 0) __res_iclose (resp, true); /* Reattach the current configuration. */ if (__resolv_conf_attach (ctx->resp, current)) { __resolv_conf_put (ctx->conf); /* ctx takes ownership, so we do not release current. */ ctx->conf = current; } } else /* No change. Drop the reference count for current. */ __resolv_conf_put (current); } return true; } assert (ctx->conf == NULL); if (preinit) { if (!resp->retrans) resp->retrans = RES_TIMEOUT; if (!resp->retry) resp->retry = RES_DFLRETRY; resp->options = RES_DEFAULT; if (!resp->id) resp->id = res_randomid (); } if (__res_vinit (resp, preinit) < 0) return false; ctx->conf = __resolv_conf_get (ctx->resp); return true; }
/* This function belongs to libresolv, which is why it is not included in res-close.c. */ void __res_close (void) { /* Some programs call res_close before res_init. Since _res._vcsock isn't explicitly initialized, these means that we could call close (0), which might lead to some security problems. Therefore we check if res_init was called before by looking at the RES_INIT bit in _res.options. If it hasn't been set we bail out early. */ if ((_res.options & RES_INIT) == 0) return; /* We don't free the name server addresses because we never did it and it would be done implicitly on shutdown. */ __res_iclose (&_res, false); }
int res_init(void) { extern int __res_vinit(res_state, int); /* * 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. * * _res.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 (!_res.retrans) _res.retrans = RES_TIMEOUT; if (!_res.retry) _res.retry = 4; if (!(_res.options & RES_INIT)) _res.options = RES_DEFAULT; else if (_res.nscount > 0) __res_iclose (&_res, true); /* Close any VC sockets. */ /* * 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 (!_res.id) _res.id = res_randomid(); atomicinclock (lock); /* Request all threads to re-initialize their resolver states, resolv.conf might have changed. */ atomicinc (__res_initstamp); atomicincunlock (lock); return (__res_vinit(&_res, 1)); }
/* Initialize resp if RES_INIT is not yet set or if res_init in some other thread requested re-initializing. */ int __res_maybe_init (res_state resp, int preinit) { if (resp->options & RES_INIT) { if (__res_initstamp != resp->_u._ext.initstamp) { if (resp->nscount > 0) __res_iclose (resp, true); return __res_vinit (resp, 1); } return 0; } else if (preinit) { if (!resp->retrans) resp->retrans = RES_TIMEOUT; if (!resp->retry) resp->retry = 4; resp->options = RES_DEFAULT; if (!resp->id) resp->id = res_randomid (); return __res_vinit (resp, 1); } else return __res_ninit (resp); }