However, res_init() neglects to set things that the ubuntu-specific eglibc requires for it to be a valid struct, such as the last modified time of /etc/resolv.conf -- "last_mtime".
Thus, the first call to res_query() resets the _res struct, effectively making any changes before it and after the original res_init(), useless.
On the first run of __res_maybe_init()[thus, effectively, res_query), it will always call __res_vinit(), because res_init() does not set the 'last_mtime'. -- That's because the last_mtime is an Ubuntu-specific feature, likely added for security reasons.
even shorter tl;dr:
'last_mtime' is an ubuntu-specific feature added to eglibc's resolv library, which is only set inside the __res_maybe_init() function.
When calling res_init(), it does not set 'last_mtime', as that uses __res_vinit(), not __res_maybe_init().
When calling res_query() for the first time, all the changes made to the _res struct are wiped, with the exception of int retrans, int retry, u_long options. This is because res_query uses __res_maybe_init(), which will reset _res if 'last_mtime' has not been set(or is old)
A quick fix is to replace __res_vinit()'s usage within the res_query() function with __res_maybe_init(), which takes the exact same parameters.
tl;dr:
res_init() does not correctly initialize the _res struct.
The code:
res_init();
} else {
}
outputs "RES_INIT set." correctly, and that bit is set. res_init() does all of its setting through res_init.c, https:/ /sourceware. org/git/ ?p=glibc. git;a=blob; f=resolv/ res_init. c;h=66561ffac2f fc039707676ed8b 4bf36ee50ee889; hb=HEAD# l151
That's all fine and dandy. -- (The actual resetting happens through the function __res_vinit())
However, res_init() neglects to set things that the ubuntu-specific eglibc requires for it to be a valid struct, such as the last modified time of /etc/resolv.conf -- "last_mtime".
Thus, the first call to res_query() resets the _res struct, effectively making any changes before it and after the original res_init(), useless.
As we can see in res_data.c, https:/ /sourceware. org/git/ ?p=glibc. git;a=blob; f=resolv/ res_data. c;h=81c9ae5bfd7 ef71ebb986b5c95 72c1859684ba39; hb=HEAD# l185 , res_query() calls __res_maybe_init (), which decides whether we need to re-call res_init() or not.
In the comments for that __res_maybe_init() function:
/* Initialize resp if RES_INIT is not yet set or if res_init in some other
thread requested re-initializing. */
On the first run of __res_maybe_ init()[ thus, effectively, res_query), it will always call __res_vinit(), because res_init() does not set the 'last_mtime'. -- That's because the last_mtime is an Ubuntu-specific feature, likely added for security reasons.
>>>>>> if ((ret == 0) && (last_mtime != statbuf.st_mtime)) { <<<<<<<
last_ mtime = statbuf.st_mtime;
atomicinc (__res_initstamp);
__libc_ lock_unlock (lock); u._ext. initstamp) {
if (resp->nscount > 0)
__res_ iclose (resp, true);
return __res_vinit (resp, 1);
}
if (__res_initstamp != resp->_
}
even shorter tl;dr:
'last_mtime' is an ubuntu-specific feature added to eglibc's resolv library, which is only set inside the __res_maybe_init() function.
When calling res_init(), it does not set 'last_mtime', as that uses __res_vinit(), not __res_maybe_init().
When calling res_query() for the first time, all the changes made to the _res struct are wiped, with the exception of int retrans, int retry, u_long options. This is because res_query uses __res_maybe_init(), which will reset _res if 'last_mtime' has not been set(or is old)
A quick fix is to replace __res_vinit()'s usage within the res_query() function with __res_maybe_init(), which takes the exact same parameters.