This is the mail archive of the mailing list for the glibc project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: libresolv with getaddrinfo

On 14/03/15 21:29, Joshua Rogers wrote:
> I confirmed (as you can see in the code in the gdb output), that nscount
> is reset on the run by gethostbyname, but options is not.

I can see why this is the case:

> 	/*
> 	 * 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.
> 	 *
> 	 * _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 (!_nres.retrans)
> 		_nres.retrans = RES_TIMEOUT;
> 	if (!_nres.retry)
> 		_nres.retry = 4;
> 	if (!(_nres.options & RES_INIT))
> 		_nres.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 (!
> = res_nrandomid(&_nres);
> 	rv = __res_vinit(&_nres, 1);
And __res_vinit:
does not edit those 3 settings if the second parameter, 'preinit' is 1.

> 	if (!preinit) {
> 		statp->retrans = RES_TIMEOUT;
> 		statp->retry = RES_DFLRETRY;
> 		statp->options = RES_DEFAULT;
> 	}

It does, however, edit the ns stuff:
e.g.:     statp->nscount = 0;

This shows up why on res_init(); the nscount is reset -- expected behaviour.

This does not explain why the first call to an _actual_(non-init)
function overwrites everything, and then FURTHER writes do _not_ get
overwritten by the calls.

gethostbyname.c uses _res_init():
    struct res_data *data = _res_init();

But as explained, the second call to gethostbyname does not overwrite
the ns stuff.

Using res_query directly(as per, does this:

> int
> res_query(const char *name,	/*!< domain name  */
> 	  int class, int type,	/*!< class and type of query  */
> 	  u_char *answer,	/*!< buffer to put answer  */
> 	  int anslen)		/*!< size of answer buffer  */
> {
> 	if ((_nres.options & RES_INIT) == 0U && res_init() == -1) {
> 		return (-1);
> 	}
> 	return (res_nquery(&_nres, name, class, type, answer, anslen));
> }

In the if() condition, if RES_INIT is set, should never reach the
res_init(), so it will not be overwritten.

I noticed something. In the file that res_query is defined
in(res_data.c), everything uses "_nres".

May THIS be why the first run is not working? It's not setting nres?

I don't think I can dive any deeper into the code to work this out.


-- Joshua Rogers <>

Attachment: signature.asc
Description: OpenPGP digital signature

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]