libresolv with getaddrinfo
Joshua Rogers
glibc@internot.info
Sat Mar 14 11:32:00 GMT 2015
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:
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/resolv/res_data.c?rev=1.14&content-type=text/x-cvsweb-markup&only_with_tag=MAIN
> /*
> * 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 (!_nres.id)
> _nres.id = res_nrandomid(&_nres);
>
> rv = __res_vinit(&_nres, 1);
And __res_vinit:
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/resolv/res_init.c?rev=1.30&content-type=text/x-cvsweb-markup&only_with_tag=HEAD
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 http://codepad.org/55rsDQjZ), 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) {
> RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
> 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.
Thanks,
--
-- Joshua Rogers <https://internot.info/>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://sourceware.org/pipermail/libc-help/attachments/20150314/e41b75a1/attachment.sig>
More information about the Libc-help
mailing list