[3/4] resolv: fix issues when using IPv6 name servers only
Commit Message
statp->nscount contains the number of servers in the statp->nsaddr_list
array, which only contains IPv4 name servers.
When resolv.conf only contains IPv6 name servers, statp->nscount equals
to 0, which causes the existing code to add a 127.0.0.1 entry. Change
that by checking nservall, contains the number of IPv4 + IPv6 servers
instead.
The same way __libc_res_nsend exits almost immediately when
statp->nscount considering that no name servers are available, while
IPv6 name servers are actually available. Change that by checking
(statp->nscount + EXT(statp).nscount6) instead.
Finally in send_dg, the seconds variable is wrongly computed in case of
IPv6 only name servers. Use (statp->nscount + EXT(statp).nscount6)
instead of statp->nscount.
2014-06-13 Aurelien Jarno <aurelien@aurel32.net>
* resolv/res_init.c (__res_vinit): Check for both IPv4 and IPv6
name servers before adding a localhost name server entry.
* resolv/res_send.c (__libc_res_nsend): Check for both IPv4 and
IPv6 name servers before ignoring the request.
(send_dg): Check for both IPv4 and IPv6 name servers to compute
time for the total operation.
Comments
On Fri, Jun 13, 2014 at 05:32:12PM +0200, Aurelien Jarno wrote:
> statp->nscount contains the number of servers in the statp->nsaddr_list
> array, which only contains IPv4 name servers.
>
> When resolv.conf only contains IPv6 name servers, statp->nscount equals
> to 0, which causes the existing code to add a 127.0.0.1 entry. Change
> that by checking nservall, contains the number of IPv4 + IPv6 servers
> instead.
>
> The same way __libc_res_nsend exits almost immediately when
> statp->nscount considering that no name servers are available, while
> IPv6 name servers are actually available. Change that by checking
> (statp->nscount + EXT(statp).nscount6) instead.
>
> Finally in send_dg, the seconds variable is wrongly computed in case of
> IPv6 only name servers. Use (statp->nscount + EXT(statp).nscount6)
> instead of statp->nscount.
>
> 2014-06-13 Aurelien Jarno <aurelien@aurel32.net>
>
> * resolv/res_init.c (__res_vinit): Check for both IPv4 and IPv6
> name servers before adding a localhost name server entry.
> * resolv/res_send.c (__libc_res_nsend): Check for both IPv4 and
> IPv6 name servers before ignoring the request.
> (send_dg): Check for both IPv4 and IPv6 name servers to compute
> time for the total operation.
You may also have to fix this bit to also account for ipv6
nameservers:
...
static void __attribute__ ((section ("__libc_thread_freeres_fn")))
res_thread_freeres (void)
{
if (_res.nscount == 0)
/* Never called res_ninit. */
return;
...
Likewise for any other checks in the resolver that may be using only
nscount.
Siddhesh
>
> diff --git a/resolv/res_init.c b/resolv/res_init.c
> index 37004ab..95564af 100644
> --- a/resolv/res_init.c
> +++ b/resolv/res_init.c
> @@ -427,7 +427,7 @@ __res_vinit(res_state statp, int preinit) {
> #endif
> (void) fclose(fp);
> }
> - if (__builtin_expect(statp->nscount == 0, 0)) {
> + if (__builtin_expect(nservall == 0, 0)) {
> statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
> statp->nsaddr.sin_family = AF_INET;
> statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
> diff --git a/resolv/res_send.c b/resolv/res_send.c
> index af42b8a..82242bd 100644
> --- a/resolv/res_send.c
> +++ b/resolv/res_send.c
> @@ -347,7 +347,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
> {
> int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
>
> - if (statp->nscount == 0) {
> + if ((statp->nscount + EXT(statp).nscount6) == 0) {
> __set_errno (ESRCH);
> return (-1);
> }
> @@ -1013,7 +1013,7 @@ send_dg(res_state statp,
> */
> int seconds = (statp->retrans << ns);
> if (ns > 0)
> - seconds /= statp->nscount;
> + seconds /= (statp->nscount + EXT(statp).nscount6);
> if (seconds <= 0)
> seconds = 1;
> bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
> --
> 2.0.0
>
@@ -427,7 +427,7 @@ __res_vinit(res_state statp, int preinit) {
#endif
(void) fclose(fp);
}
- if (__builtin_expect(statp->nscount == 0, 0)) {
+ if (__builtin_expect(nservall == 0, 0)) {
statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
statp->nsaddr.sin_family = AF_INET;
statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
@@ -347,7 +347,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
{
int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
- if (statp->nscount == 0) {
+ if ((statp->nscount + EXT(statp).nscount6) == 0) {
__set_errno (ESRCH);
return (-1);
}
@@ -1013,7 +1013,7 @@ send_dg(res_state statp,
*/
int seconds = (statp->retrans << ns);
if (ns > 0)
- seconds /= statp->nscount;
+ seconds /= (statp->nscount + EXT(statp).nscount6);
if (seconds <= 0)
seconds = 1;
bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;