resolv: Remove support for RES_USE_INET6 and the inet6 option

This functionality was deprecated in glibc 2.25.

This commit only includes the core changes to remove the
functionality.  It does not remove the RES_USE_INET6 handling in the
individual NSS service modules and the res_use_inet6 function.
These changes will happen in future commits.
This commit is contained in:
Florian Weimer 2019-04-08 10:40:31 +02:00
parent 94e358f6d4
commit 3f8b44be0a
15 changed files with 61 additions and 680 deletions

View File

@ -1,3 +1,40 @@
2019-04-08 Florian Weimer <fweimer@redhat.com>
resolv: Remove support for RES_USE_INET6 and the inet6 option.
* nscd/aicache.c (addhstaiX): Do not disable RES_USE_INET6.
* nscd/nscd_gehst_r.c (__nscd_gethostbyname_r): Always use
GETHOSTBYNAME.
* resolv/Makefile (tests): Remove tst-res_use_inet6.
(tests-internal): Update justification for tst-resolv-res_init,
tst-resolv-res_init-thread.
(tst-res_use_inet6): Remove target.
(CFLAGS-tst-res_use_inet6.c): Do not set variable.
* resolv/res_debug.c (p_option): Remove "inet6" support.
* resolv/res_init.c (res_setoptions): Likewise.
* resolv/res_use_inet6.h: Remove file.
* resolv/resolv-internal.h (DEPRECATED_RES_USE_INET6): Remove
definition.
(res_use_inet6): Always return false.
* resolv/resolv.h (RES_USE_INET6): Remove definition.
* resolv/resolv_context.h: Adjust file comment.
(struct resolv_context): Update comment on __next field.
(__resolv_context_put): Update comment.
* resolv/tst-res_use_inet6.c: Remove file.
* resolv/tst-resolv-res_init-skeleton.c (print_resp): Remove
"inet6" support.
(test_cases): Adjust test case.
* resolv/tst-resolv-threads.c (byname_inet6) Remove function.
(thread_byname2_af_inet6): Use old byname_inet6 code.
(thread_byname_inet6, thread_byname2_af_inet6): Remove functions.
(gai): Remove do_inet6 argument.
(thread_gai_inet, thread_gai_inet6, thread_gai_unspec): Adjust.
(thread_gai_inet_inet6, thread_gai_inet6_inet6)
(thread_gai_unspec_inet6): Remove functions.
(do_test): Adjust thread_funcs.
* sysdeps/posix/getaddrinfo.c (gethosts): Do not restore
RES_USE_INET6 flag.
(gaih_inet): Do not disable RES_USE_INET6 flag.
2019-04-05 Anton Youdkevitch <anton.youdkevitch@bell-sw.com> 2019-04-05 Anton Youdkevitch <anton.youdkevitch@bell-sw.com>
* sysdeps/aarch64/multiarch/memcpy_thunderx2.S: Cleanup branching * sysdeps/aarch64/multiarch/memcpy_thunderx2.S: Cleanup branching

3
NEWS
View File

@ -35,6 +35,9 @@ Deprecated and removed features, and other changes affecting compatibility:
* The obsolete and never-implemented XSI STREAMS header files <stropts.h> * The obsolete and never-implemented XSI STREAMS header files <stropts.h>
and <sys/stropts.h> have been removed. and <sys/stropts.h> have been removed.
* Support for the "inet6" option in /etc/resolv.conf and the RES_USE_INET6
resolver flag (deprecated in glibc 2.25) have been removed.
Changes to build and runtime requirements: Changes to build and runtime requirements:
* GCC 6.2 or later is required to build the GNU C Library. * GCC 6.2 or later is required to build the GNU C Library.

View File

@ -27,7 +27,6 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <resolv/resolv-internal.h> #include <resolv/resolv-internal.h>
#include <resolv/resolv_context.h> #include <resolv/resolv_context.h>
#include <resolv/res_use_inet6.h>
#include <scratch_buffer.h> #include <scratch_buffer.h>
#include "dbg_log.h" #include "dbg_log.h"
@ -100,12 +99,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
no_more = 0; no_more = 0;
nip = hosts_database; nip = hosts_database;
/* Initialize configurations. If we are looking for both IPv4 and /* Initialize configurations. */
IPv6 address we don't want the lookup functions to automatically
promote IPv4 addresses to IPv6 addresses. Therefore, use the
_no_inet6 variant. */
struct resolv_context *ctx = __resolv_context_get (); struct resolv_context *ctx = __resolv_context_get ();
bool enable_inet6 = __resolv_context_disable_inet6 (ctx);
if (ctx == NULL) if (ctx == NULL)
no_more = 1; no_more = 1;
@ -513,7 +508,6 @@ next_nip:
} }
out: out:
__resolv_context_enable_inet6 (ctx, enable_inet6);
__resolv_context_put (ctx); __resolv_context_put (ctx);
if (dataset != NULL && !alloca_used) if (dataset != NULL && !alloca_used)

View File

@ -40,11 +40,7 @@ __nscd_gethostbyname_r (const char *name, struct hostent *resultbuf,
char *buffer, size_t buflen, struct hostent **result, char *buffer, size_t buflen, struct hostent **result,
int *h_errnop) int *h_errnop)
{ {
request_type reqtype; return nscd_gethst_r (name, strlen (name) + 1, GETHOSTBYNAME, resultbuf,
reqtype = res_use_inet6 () ? GETHOSTBYNAMEv6 : GETHOSTBYNAME;
return nscd_gethst_r (name, strlen (name) + 1, reqtype, resultbuf,
buffer, buflen, result, h_errnop); buffer, buflen, result, h_errnop);
} }

View File

@ -52,7 +52,6 @@ tests += \
tst-ns_name_pton \ tst-ns_name_pton \
tst-res_hconf_reorder \ tst-res_hconf_reorder \
tst-res_hnok \ tst-res_hnok \
tst-res_use_inet6 \
tst-resolv-basic \ tst-resolv-basic \
tst-resolv-binary \ tst-resolv-binary \
tst-resolv-edns \ tst-resolv-edns \
@ -70,13 +69,10 @@ tests += \
tst-resolv-ai_idn-nolibidn2 \ tst-resolv-ai_idn-nolibidn2 \
tst-resolv-canonname \ tst-resolv-canonname \
# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>. # Needs resolv_context.
tests-internal += \ tests-internal += \
tst-resolv-res_init \ tst-resolv-res_init \
tst-resolv-res_init-thread \ tst-resolv-res_init-thread \
# Needs resolv_context.
tests-internal += \
tst-resolv-res_ninit \ tst-resolv-res_ninit \
tst-resolv-threads \ tst-resolv-threads \
@ -175,7 +171,6 @@ $(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out
$(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-ai_idn: \ $(objpfx)tst-resolv-ai_idn: \
$(libdl) $(objpfx)libresolv.so $(shared-thread-library) $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-ai_idn-latin1: \ $(objpfx)tst-resolv-ai_idn-latin1: \
@ -211,7 +206,3 @@ $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so
$(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so $(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so
$(objpfx)tst-res_hnok: $(objpfx)libresolv.so $(objpfx)tst-res_hnok: $(objpfx)libresolv.so
$(objpfx)tst-p_secstodate: $(objpfx)libresolv.so $(objpfx)tst-p_secstodate: $(objpfx)libresolv.so
# This test case uses the deprecated RES_USE_INET6 resolver option.
CFLAGS-tst-res_use_inet6.c += -Wno-error

View File

@ -607,7 +607,6 @@ p_option(u_long option) {
case RES_INSECURE1: return "insecure1"; case RES_INSECURE1: return "insecure1";
case RES_INSECURE2: return "insecure2"; case RES_INSECURE2: return "insecure2";
case RES_NOALIASES: return "noaliases"; case RES_NOALIASES: return "noaliases";
case DEPRECATED_RES_USE_INET6: return "inet6";
case RES_ROTATE: return "rotate"; case RES_ROTATE: return "rotate";
case RES_USE_EDNS0: return "edns0"; case RES_USE_EDNS0: return "edns0";
case RES_SNGLKUP: return "single-request"; case RES_SNGLKUP: return "single-request";

View File

@ -672,7 +672,6 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
unsigned long int flag; unsigned long int flag;
} options[] = { } options[] = {
#define STRnLEN(str) str, sizeof (str) - 1 #define STRnLEN(str) str, sizeof (str) - 1
{ STRnLEN ("inet6"), 0, DEPRECATED_RES_USE_INET6 },
{ STRnLEN ("rotate"), 0, RES_ROTATE }, { STRnLEN ("rotate"), 0, RES_ROTATE },
{ STRnLEN ("edns0"), 0, RES_USE_EDNS0 }, { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
{ STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP }, { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },

View File

@ -1,49 +0,0 @@
/* Support functions for handling RES_USE_INET6 in getaddrinfo/nscd.
Copyright (C) 2017-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _RES_USE_INET6_H
#define _RES_USE_INET6_H
#include <resolv/resolv_context.h>
#include <resolv/resolv-internal.h>
/* Ensure that RES_USE_INET6 is disabled in *CTX. Return true if
__resolv_context_enable_inet6 below should enable RES_USE_INET6
again. */
static inline bool
__resolv_context_disable_inet6 (struct resolv_context *ctx)
{
if (ctx != NULL && ctx->resp->options & DEPRECATED_RES_USE_INET6)
{
ctx->resp->options &= ~DEPRECATED_RES_USE_INET6;
return true;
}
else
return false;
}
/* If ENABLE, re-enable RES_USE_INET6 in *CTX. To be paired with
__resolv_context_disable_inet6. */
static inline void
__resolv_context_enable_inet6 (struct resolv_context *ctx, bool enable)
{
if (ctx != NULL && enable)
ctx->resp->options |= DEPRECATED_RES_USE_INET6;
}
#endif

View File

@ -27,15 +27,12 @@
#define RES_F_CONN 0x00000002 /* Socket is connected. */ #define RES_F_CONN 0x00000002 /* Socket is connected. */
#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */ #define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */
/* Legacy function. This needs to be removed once all NSS modules
/* Internal version of RES_USE_INET6 which does not trigger a have been adjusted. */
deprecation warning. */
#define DEPRECATED_RES_USE_INET6 0x00002000
static inline bool static inline bool
res_use_inet6 (void) res_use_inet6 (void)
{ {
return _res.options & DEPRECATED_RES_USE_INET6; return false;
} }
enum enum

View File

@ -118,8 +118,6 @@ struct res_sym {
#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ #define RES_INSECURE1 0x00000400 /* type 1 security disabled */
#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_INSECURE2 0x00000800 /* type 2 security disabled */
#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ #define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */
#define RES_USE_INET6 \
__glibc_macro_warning ("RES_USE_INET6 is deprecated") 0x00002000
#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ #define RES_ROTATE 0x00004000 /* rotate ns list after each query */
#define RES_NOCHECKNAME \ #define RES_NOCHECKNAME \
__glibc_macro_warning ("RES_NOCHECKNAME is deprecated") 0x00008000 __glibc_macro_warning ("RES_NOCHECKNAME is deprecated") 0x00008000

View File

@ -26,9 +26,7 @@
allocating a new context. This prevents unexpected reloading of allocating a new context. This prevents unexpected reloading of
the resolver configuration. Care is taken to keep the context in the resolver configuration. Care is taken to keep the context in
sync with the thread-local _res object. (This does not happen with sync with the thread-local _res object. (This does not happen with
__resolv_context_get_override, and __resolv_context_get_no_inet6 may __resolv_context_get_override.)
also interpose another context object if RES_USE_INET6 needs to be
disabled.)
In contrast to struct __res_state, struct resolv_context is not In contrast to struct __res_state, struct resolv_context is not
affected by ABI compatibility concerns. affected by ABI compatibility concerns.
@ -62,8 +60,8 @@ struct resolv_context
size_t __refcount; /* Count of reusages by the get functions. */ size_t __refcount; /* Count of reusages by the get functions. */
bool __from_res; /* True if created from _res. */ bool __from_res; /* True if created from _res. */
/* If RES_USE_INET6 was disabled at this level, this field points to /* Single-linked list of resolver contexts. Used for memory
the previous context. */ deallocation on thread cancellation. */
struct resolv_context *__next; struct resolv_context *__next;
}; };
@ -75,8 +73,7 @@ struct resolv_context *__resolv_context_get (void)
libc_hidden_proto (__resolv_context_get) libc_hidden_proto (__resolv_context_get)
/* Deallocate the temporary resolver context. Converse of /* Deallocate the temporary resolver context. Converse of
__resolv_context_get. Restore the RES_USE_INET6 flag if necessary. __resolv_context_get. Do nothing if CTX is NULL. */
Do nothing if CTX is NULL. */
void __resolv_context_put (struct resolv_context *ctx); void __resolv_context_put (struct resolv_context *ctx);
libc_hidden_proto (__resolv_context_put) libc_hidden_proto (__resolv_context_put)

View File

@ -1,509 +0,0 @@
/* Basic functionality tests for inet6 option processing.
Copyright (C) 2016-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <ctype.h>
#include <netdb.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/check_nss.h>
#include <support/resolv_test.h>
#include <support/support.h>
#include <support/xthread.h>
/* Handle IPv4 reverse lookup responses. Product a PTR record
A-B-C-D.v4.example. */
static void
response_ptr_v4 (const struct resolv_response_context *ctx,
struct resolv_response_builder *b,
const char *qname, uint16_t qclass, uint16_t qtype)
{
int bytes[4];
int offset = -1;
TEST_VERIFY (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa%n",
bytes + 0, bytes + 1, bytes + 2, bytes + 3,
&offset) == 4);
TEST_VERIFY (offset == strlen (qname));
resolv_response_init (b, (struct resolv_response_flags) {});
resolv_response_add_question (b, qname, qclass, qtype);
resolv_response_section (b, ns_s_an);
resolv_response_open_record (b, qname, qclass, T_PTR, 0);
char *name = xasprintf ("%d-%d-%d-%d.v4.example",
bytes[3], bytes[2], bytes[1], bytes[0]);
resolv_response_add_name (b, name);
free (name);
resolv_response_close_record (b);
}
/* Handle IPv6 reverse lookup responses. Produce a PTR record
<32 hex digits>.v6.example. */
static void
response_ptr_v6 (const struct resolv_response_context *ctx,
struct resolv_response_builder *b,
const char *qname, uint16_t qclass, uint16_t qtype)
{
TEST_VERIFY_EXIT (strlen (qname) > 64);
char bytes[33];
for (int i = 0; i < 64; ++i)
if ((i % 2) == 0)
{
TEST_VERIFY (isxdigit ((unsigned char) qname[i]));
bytes[31 - i / 2] = qname[i];
}
else
TEST_VERIFY_EXIT (qname[i] == '.');
bytes[32] = '\0';
resolv_response_init (b, (struct resolv_response_flags) {});
resolv_response_add_question (b, qname, qclass, qtype);
resolv_response_section (b, ns_s_an);
resolv_response_open_record (b, qname, qclass, T_PTR, 0);
char *name = xasprintf ("%s.v6.example", bytes);
resolv_response_add_name (b, name);
free (name);
resolv_response_close_record (b);
}
/* Produce a response based on QNAME: Certain characters in the first
label of QNAME trigger the inclusion of resource records:
'a' A record (IPv4 address)
'q' AAAA record (quad A record, IPv6 address)
'p' PTR record
'm' record type must match QTYPE (no additional records)
'6' stop flag processing if QTYPE == AAAA
For 'a' and 'q', QTYPE is ignored for record type selection if 'm'
is not specified.
in-addr.arpa and ip6.arpa queries are handled separately in
response_ptr_v4 and response_ptr_v6. */
static void
response (const struct resolv_response_context *ctx,
struct resolv_response_builder *b,
const char *qname, uint16_t qclass, uint16_t qtype)
{
if (strstr (qname, ".in-addr.arpa") != NULL)
return response_ptr_v4 (ctx, b, qname, qclass, qtype);
else if (strstr (qname, ".ip6.arpa") != NULL)
return response_ptr_v6 (ctx, b, qname, qclass, qtype);
bool include_a = false;
bool include_aaaa = false;
bool include_match = false;
bool include_ptr = false;
for (const char *p = qname; *p != '.' && *p != '\0'; ++p)
{
if (*p == 'a')
include_a = true;
else if (*p == 'q')
include_aaaa = true;
else if (*p == 'm')
include_match = true;
else if (*p == 'p')
include_ptr = true;
else if (*p == '6' && qtype == T_AAAA)
break;
}
if (include_match)
{
if (qtype == T_A)
include_aaaa = false;
else if (qtype == T_AAAA)
include_a = false;
}
resolv_response_init (b, (struct resolv_response_flags) {});
resolv_response_add_question (b, qname, qclass, qtype);
resolv_response_section (b, ns_s_an);
if (include_a)
{
char ipv4[4] = {192, 0, 2, 17};
resolv_response_open_record (b, qname, qclass, T_A, 0);
resolv_response_add_data (b, &ipv4, sizeof (ipv4));
resolv_response_close_record (b);
}
if (include_aaaa)
{
char ipv6[16]
= {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
resolv_response_open_record (b, qname, qclass, T_AAAA, 0);
resolv_response_add_data (b, &ipv6, sizeof (ipv6));
resolv_response_close_record (b);
}
if (include_ptr)
{
resolv_response_open_record (b, qname, qclass, T_PTR, 0);
resolv_response_add_name (b, "ptr-target.example");
resolv_response_close_record (b);
}
}
/* Test that getaddrinfo is not influenced by RES_USE_INET6. */
static void
test_gai (void)
{
{
struct addrinfo hints =
{
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
};
struct addrinfo *ai;
int ret = getaddrinfo ("qam.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_UNSPEC qam.example", ai, ret,
"address: STREAM/TCP 192.0.2.17 80\n"
"address: STREAM/TCP 2001:db8::1 80\n");
if (ret == 0)
freeaddrinfo (ai);
ret = getaddrinfo ("am.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_UNSPEC am.example", ai, ret,
"address: STREAM/TCP 192.0.2.17 80\n");
if (ret == 0)
freeaddrinfo (ai);
ret = getaddrinfo ("qa.example", "80", &hints, &ai);
/* Combined A/AAAA responses currently result in address
duplication. */
check_addrinfo ("getaddrinfo AF_UNSPEC qa.example", ai, ret,
"address: STREAM/TCP 192.0.2.17 80\n"
"address: STREAM/TCP 192.0.2.17 80\n"
"address: STREAM/TCP 2001:db8::1 80\n"
"address: STREAM/TCP 2001:db8::1 80\n");
if (ret == 0)
freeaddrinfo (ai);
}
{
struct addrinfo hints =
{
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
};
struct addrinfo *ai;
int ret = getaddrinfo ("qam.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_INET qam.example", ai, ret,
"address: STREAM/TCP 192.0.2.17 80\n");
if (ret == 0)
freeaddrinfo (ai);
ret = getaddrinfo ("am.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_INET am.example", ai, ret,
"address: STREAM/TCP 192.0.2.17 80\n");
if (ret == 0)
freeaddrinfo (ai);
ret = getaddrinfo ("qa.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_INET qa.example", ai, ret,
"address: STREAM/TCP 192.0.2.17 80\n");
if (ret == 0)
freeaddrinfo (ai);
}
{
struct addrinfo hints =
{
.ai_family = AF_INET6,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
};
struct addrinfo *ai;
int ret = getaddrinfo ("qa.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo (AF_INET6)", ai, ret,
"address: STREAM/TCP 2001:db8::1 80\n");
if (ret == 0)
freeaddrinfo (ai);
ret = getaddrinfo ("am.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_INET6 am.example", ai, ret,
"error: No address associated with hostname\n");
if (ret == 0)
freeaddrinfo (ai);
ret = getaddrinfo ("qam.example", "80", &hints, &ai);
check_addrinfo ("getaddrinfo AF_INET6 qam.example", ai, ret,
"address: STREAM/TCP 2001:db8::1 80\n");
if (ret == 0)
freeaddrinfo (ai);
}
}
/* Test gethostbyaddr and getnameinfo. The results are independent of
RES_USE_INET6. */
static void
test_reverse (void)
{
{
char ipv4[4] = { 192, 0, 2, 17 };
check_hostent ("gethostbyaddr AF_INET",
gethostbyaddr (ipv4, sizeof (ipv4), AF_INET),
"name: 192-0-2-17.v4.example\n"
"address: 192.0.2.17\n");
}
{
char ipv6[16]
= {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
check_hostent ("gethostbyaddr AF_INET",
gethostbyaddr (ipv6, sizeof (ipv6), AF_INET6),
"name: 20010db8000000000000000000000001.v6.example\n"
"address: 2001:db8::1\n");
}
{
struct sockaddr_in addr =
{
.sin_family = AF_INET,
.sin_addr = { .s_addr = htonl (0xc0000211) },
.sin_port = htons (80)
};
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int ret = getnameinfo ((struct sockaddr *) &addr, sizeof (addr),
host, sizeof (host), service, sizeof (service),
NI_NUMERICSERV);
TEST_VERIFY (ret == 0);
TEST_VERIFY (strcmp (host, "192-0-2-17.v4.example") == 0);
TEST_VERIFY (strcmp (service, "80") == 0);
}
{
char ipv6[16]
= {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
struct sockaddr_in6 addr =
{
.sin6_family = AF_INET6,
.sin6_port = htons (80),
};
TEST_VERIFY (sizeof (ipv6) == sizeof (addr.sin6_addr));
memcpy (&addr.sin6_addr, ipv6, sizeof (addr.sin6_addr));
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int ret = getnameinfo ((struct sockaddr *) &addr, sizeof (addr),
host, sizeof (host), service, sizeof (service),
NI_NUMERICSERV);
TEST_VERIFY (ret == 0);
TEST_VERIFY
(strcmp (host, "20010db8000000000000000000000001.v6.example") == 0);
TEST_VERIFY (strcmp (service, "80") == 0);
}
}
/* Test that gethostbyname2 is mostly not influenced by
RES_USE_INET6. */
static void
test_get2_any (void)
{
check_hostent ("gethostbyname2 AF_INET am.example",
gethostbyname2 ("am.example", AF_INET),
"name: am.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname2 AF_INET a.example",
gethostbyname2 ("a.example", AF_INET),
"name: a.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname2 AF_INET qm.example",
gethostbyname2 ("qm.example", AF_INET),
"error: NO_ADDRESS\n");
check_hostent ("gethostbyname2 AF_INET q.example",
gethostbyname2 ("q.example", AF_INET),
"error: NO_RECOVERY\n");
check_hostent ("gethostbyname2 AF_INET qam.example",
gethostbyname2 ("qam.example", AF_INET),
"name: qam.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname2 AF_INET qa.example",
gethostbyname2 ("qa.example", AF_INET),
"name: qa.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname2 AF_INET6 qm.example",
gethostbyname2 ("qm.example", AF_INET6),
"name: qm.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname2 AF_INET6 q.example",
gethostbyname2 ("q.example", AF_INET6),
"name: q.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname2 AF_INET6 qam.example",
gethostbyname2 ("qam.example", AF_INET6),
"name: qam.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname2 AF_INET6 qa.example",
gethostbyname2 ("qa.example", AF_INET6),
"name: qa.example\n"
"address: 2001:db8::1\n");
/* Additional AF_INET6 tests depend on RES_USE_INET6; see below. */
test_reverse ();
}
/* gethostbyname2 tests with RES_USE_INET6 disabled. */
static void
test_get2_no_inet6 (void)
{
test_get2_any ();
check_hostent ("gethostbyname2 AF_INET6 am.example",
gethostbyname2 ("am.example", AF_INET6),
"error: NO_ADDRESS\n");
check_hostent ("gethostbyname2 AF_INET6 a.example",
gethostbyname2 ("a.example", AF_INET6),
"error: NO_RECOVERY\n");
}
/* gethostbyname2 tests with RES_USE_INET6 enabled. */
static void
test_get2_inet6 (void)
{
test_get2_any ();
check_hostent ("gethostbyname2 AF_INET6 am.example",
gethostbyname2 ("am.example", AF_INET6),
"name: am.example\n"
"address: ::ffff:192.0.2.17\n");
check_hostent ("gethostbyname2 AF_INET6 a.example",
gethostbyname2 ("a.example", AF_INET6),
"error: NO_RECOVERY\n");
}
/* Collection of tests which assume no RES_USE_INET6 flag. */
static void
test_no_inet6 (void)
{
check_hostent ("gethostbyname (\"a.example\")",
gethostbyname ("a.example"),
"name: a.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname (\"qa.example\")",
gethostbyname ("qa.example"),
"name: qa.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname (\"am.example\")",
gethostbyname ("am.example"),
"name: am.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname (\"amp.example\")",
gethostbyname ("amp.example"),
"name: amp.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname (\"qam.example\")",
gethostbyname ("qam.example"),
"name: qam.example\n"
"address: 192.0.2.17\n");
check_hostent ("gethostbyname (\"q.example\")",
gethostbyname ("q.example"),
"error: NO_RECOVERY\n");
check_hostent ("gethostbyname (\"qm.example\")",
gethostbyname ("qm.example"),
"error: NO_ADDRESS\n");
test_get2_no_inet6 ();
test_get2_no_inet6 ();
test_gai ();
test_get2_no_inet6 ();
test_get2_no_inet6 ();
}
static void *
threadfunc (void *ignored)
{
struct resolv_test *obj = resolv_test_start
((struct resolv_redirect_config)
{
.response_callback = response
});
TEST_VERIFY ((_res.options & RES_USE_INET6) == 0);
test_no_inet6 ();
_res.options |= RES_USE_INET6;
check_hostent ("gethostbyname (\"a.inet6.example\")",
gethostbyname ("a.inet6.example"),
"error: NO_RECOVERY\n");
check_hostent ("gethostbyname (\"am.inet6.example\")",
gethostbyname ("am.inet6.example"),
"name: am.inet6.example\n"
"address: ::ffff:192.0.2.17\n");
check_hostent ("gethostbyname (\"qa.inet6.example\")",
gethostbyname ("qa.inet6.example"),
"name: qa.inet6.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname (\"qam.inet6.example\")",
gethostbyname ("qam.inet6.example"),
"name: qam.inet6.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname (\"q.inet6.example\")",
gethostbyname ("q.inet6.example"),
"name: q.inet6.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname (\"qm.inet6.example\")",
gethostbyname ("qm.inet6.example"),
"name: qm.inet6.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname (\"amp.inet6.example\")",
gethostbyname ("amp.inet6.example"),
"error: NO_RECOVERY\n");
check_hostent ("gethostbyname (\"qmp.inet6.example\")",
gethostbyname ("qmp.inet6.example"),
"name: qmp.inet6.example\n"
"address: 2001:db8::1\n");
check_hostent ("gethostbyname (\"ap.inet6.example\")",
gethostbyname ("ap.inet6.example"),
"error: NO_RECOVERY\n");
check_hostent ("gethostbyname (\"6ap.inet6.example\")",
gethostbyname ("6ap.inet6.example"),
"name: 6ap.inet6.example\n"
"address: ::ffff:192.0.2.17\n");
check_hostent ("gethostbyname (\"am6p.inet6.example\")",
gethostbyname ("am6p.inet6.example"),
"name: am6p.inet6.example\n"
"address: ::ffff:192.0.2.17\n");
check_hostent ("gethostbyname (\"qp.inet6.example\")",
gethostbyname ("qp.inet6.example"),
"name: qp.inet6.example\n"
"address: 2001:db8::1\n");
test_get2_inet6 ();
test_get2_inet6 ();
test_gai ();
test_get2_inet6 ();
test_get2_inet6 ();
TEST_VERIFY (_res.options & RES_USE_INET6);
_res.options &= ~RES_USE_INET6;
test_no_inet6 ();
resolv_test_end (obj);
return NULL;
}
static int
do_test (void)
{
resolv_test_init ();
/* Attempt to run on a non-main thread first. */
{
pthread_t thr = xpthread_create (NULL, threadfunc, NULL);
xpthread_join (thr);
}
/* Try the main thread next. */
threadfunc (NULL);
return 0;
}
#include <support/test-driver.c>

View File

@ -24,7 +24,6 @@
#include <errno.h> #include <errno.h>
#include <gnu/lib-names.h> #include <gnu/lib-names.h>
#include <netdb.h> #include <netdb.h>
#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */
#include <resolv/resolv_context.h> #include <resolv/resolv_context.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -120,7 +119,6 @@ print_resp (FILE *fp, res_state resp)
if (resp->retry != RES_DFLRETRY) if (resp->retry != RES_DFLRETRY)
fprintf (fp, " attempts:%d", resp->retry); fprintf (fp, " attempts:%d", resp->retry);
print_option_flag (fp, &options, RES_USEVC, "use-vc"); print_option_flag (fp, &options, RES_USEVC, "use-vc");
print_option_flag (fp, &options, DEPRECATED_RES_USE_INET6, "inet6");
print_option_flag (fp, &options, RES_ROTATE, "rotate"); print_option_flag (fp, &options, RES_ROTATE, "rotate");
print_option_flag (fp, &options, RES_USE_EDNS0, "edns0"); print_option_flag (fp, &options, RES_USE_EDNS0, "edns0");
print_option_flag (fp, &options, RES_SNGLKUP, print_option_flag (fp, &options, RES_SNGLKUP,
@ -560,7 +558,7 @@ struct test_case test_cases[] =
"nameserver 192.0.2.1\n" "nameserver 192.0.2.1\n"
"nameserver ::1\n" "nameserver ::1\n"
"nameserver 192.0.2.2\n", "nameserver 192.0.2.2\n",
.expected = "options ndots:3 timeout:19 attempts:5 inet6 edns0\n" .expected = "options ndots:3 timeout:19 attempts:5 edns0\n"
"search corp.example.com example.com\n" "search corp.example.com example.com\n"
"; search[0]: corp.example.com\n" "; search[0]: corp.example.com\n"
"; search[1]: example.com\n" "; search[1]: example.com\n"

View File

@ -276,19 +276,12 @@ thread_byname2 (void *closure)
return byname (true); return byname (true);
} }
/* Call gethostbyname_r with RES_USE_INET6 (if do_2 is false), or /* Test gethostbyname2_r with AF_INET6. */
gethostbyname_r with AF_INET6 (if do_2 is true). */
static void * static void *
byname_inet6 (bool do_2) thread_byname2_af_inet6 (void *closure)
{ {
int this_thread = get_thread_number (); int this_thread = get_thread_number ();
xpthread_barrier_wait (&barrier); xpthread_barrier_wait (&barrier);
if (!do_2)
{
res_init ();
_res.options |= DEPRECATED_RES_USE_INET6;
TEST_VERIFY (strcmp (_res.defdname, "example.com") == 0);
}
for (int i = 0; i < queries_per_thread; ++i) for (int i = 0; i < queries_per_thread; ++i)
{ {
char qname[100]; char qname[100];
@ -298,46 +291,19 @@ byname_inet6 (bool do_2)
char buf[1000]; char buf[1000];
struct hostent *e = NULL; struct hostent *e = NULL;
int herrno; int herrno;
int ret; int ret = gethostbyname2_r (qname, AF_INET6, &storage, buf, sizeof (buf),
if (do_2) &e, &herrno);
ret = gethostbyname2_r (qname, AF_INET6, &storage, buf, sizeof (buf), check_hostent (__func__, "gethostbyname2_r", qname, ret, e, AF_INET6, i);
&e, &herrno);
else
ret = gethostbyname_r (qname, &storage, buf, sizeof (buf),
&e, &herrno);
check_hostent (__func__,
do_2 ? "gethostbyname2_r" : "gethostbyname_r",
qname, ret, e, AF_INET6, i);
} }
return NULL; return NULL;
} }
/* Test gethostbyname_r with AF_INET6. */
static void *
thread_byname_inet6 (void *closure)
{
return byname_inet6 (false);
}
/* Test gethostbyname2_r with AF_INET6. */
static void *
thread_byname2_af_inet6 (void *closure)
{
return byname_inet6 (true);
}
/* Run getaddrinfo tests for FAMILY. */ /* Run getaddrinfo tests for FAMILY. */
static void * static void *
gai (int family, bool do_inet6) gai (int family)
{ {
int this_thread = get_thread_number (); int this_thread = get_thread_number ();
xpthread_barrier_wait (&barrier); xpthread_barrier_wait (&barrier);
if (do_inet6)
{
res_init ();
_res.options |= DEPRECATED_RES_USE_INET6;
check_have_conf ();
}
for (int i = 0; i < queries_per_thread; ++i) for (int i = 0; i < queries_per_thread; ++i)
{ {
char qname[100]; char qname[100];
@ -362,42 +328,21 @@ gai (int family, bool do_inet6)
static void * static void *
thread_gai_inet (void *closure) thread_gai_inet (void *closure)
{ {
return gai (AF_INET, false); return gai (AF_INET);
} }
/* Test getaddrinfo with AF_INET6. */ /* Test getaddrinfo with AF_INET6. */
static void * static void *
thread_gai_inet6 (void *closure) thread_gai_inet6 (void *closure)
{ {
return gai (AF_INET6, false); return gai (AF_INET6);
} }
/* Test getaddrinfo with AF_UNSPEC. */ /* Test getaddrinfo with AF_UNSPEC. */
static void * static void *
thread_gai_unspec (void *closure) thread_gai_unspec (void *closure)
{ {
return gai (AF_UNSPEC, false); return gai (AF_UNSPEC);
}
/* Test getaddrinfo with AF_INET. */
static void *
thread_gai_inet_inet6 (void *closure)
{
return gai (AF_INET, true);
}
/* Test getaddrinfo with AF_INET6. */
static void *
thread_gai_inet6_inet6 (void *closure)
{
return gai (AF_INET6, true);
}
/* Test getaddrinfo with AF_UNSPEC. */
static void *
thread_gai_unspec_inet6 (void *closure)
{
return gai (AF_UNSPEC, true);
} }
/* Description of the chroot environment used to run the tests. */ /* Description of the chroot environment used to run the tests. */
@ -451,7 +396,7 @@ do_test (void)
.server_address_overrides = server_addresses, .server_address_overrides = server_addresses,
}); });
enum { thread_count = 10 }; enum { thread_count = 6 };
xpthread_barrier_init (&barrier, NULL, thread_count + 1); xpthread_barrier_init (&barrier, NULL, thread_count + 1);
pthread_t threads[thread_count]; pthread_t threads[thread_count];
typedef void *(*thread_func) (void *); typedef void *(*thread_func) (void *);
@ -459,14 +404,10 @@ do_test (void)
{ {
thread_byname, thread_byname,
thread_byname2, thread_byname2,
thread_byname_inet6,
thread_byname2_af_inet6, thread_byname2_af_inet6,
thread_gai_inet, thread_gai_inet,
thread_gai_inet6, thread_gai_inet6,
thread_gai_unspec, thread_gai_unspec,
thread_gai_inet_inet6,
thread_gai_inet6_inet6,
thread_gai_unspec_inet6,
}; };
for (int i = 0; i < thread_count; ++i) for (int i = 0; i < thread_count; ++i)
threads[i] = xpthread_create (NULL, thread_funcs[i], NULL); threads[i] = xpthread_create (NULL, thread_funcs[i], NULL);

View File

@ -61,7 +61,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <nss.h> #include <nss.h>
#include <resolv/resolv-internal.h> #include <resolv/resolv-internal.h>
#include <resolv/resolv_context.h> #include <resolv/resolv_context.h>
#include <resolv/res_use_inet6.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdio_ext.h> #include <stdio_ext.h>
@ -255,7 +254,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
break; \ break; \
if (!scratch_buffer_grow (tmpbuf)) \ if (!scratch_buffer_grow (tmpbuf)) \
{ \ { \
__resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
__resolv_context_put (res_ctx); \ __resolv_context_put (res_ctx); \
result = -EAI_MEMORY; \ result = -EAI_MEMORY; \
goto free_and_return; \ goto free_and_return; \
@ -266,7 +264,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
{ \ { \
if (h_errno == NETDB_INTERNAL) \ if (h_errno == NETDB_INTERNAL) \
{ \ { \
__resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
__resolv_context_put (res_ctx); \ __resolv_context_put (res_ctx); \
result = -EAI_SYSTEM; \ result = -EAI_SYSTEM; \
goto free_and_return; \ goto free_and_return; \
@ -280,7 +277,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
{ \ { \
if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \ if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \
{ \ { \
__resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
__resolv_context_put (res_ctx); \ __resolv_context_put (res_ctx); \
result = -EAI_SYSTEM; \ result = -EAI_SYSTEM; \
goto free_and_return; \ goto free_and_return; \
@ -558,7 +554,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
enum nss_status status = NSS_STATUS_UNAVAIL; enum nss_status status = NSS_STATUS_UNAVAIL;
int no_more; int no_more;
struct resolv_context *res_ctx = NULL; struct resolv_context *res_ctx = NULL;
bool res_enable_inet6 = false;
/* If we do not have to look for IPv6 addresses or the canonical /* If we do not have to look for IPv6 addresses or the canonical
name, use the simple, old functions, which do not support name, use the simple, old functions, which do not support
@ -749,7 +744,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
addresses to IPv6 addresses, so we use the no_inet6 addresses to IPv6 addresses, so we use the no_inet6
function variant. */ function variant. */
res_ctx = __resolv_context_get (); res_ctx = __resolv_context_get ();
res_enable_inet6 = __resolv_context_disable_inet6 (res_ctx);
if (res_ctx == NULL) if (res_ctx == NULL)
no_more = 1; no_more = 1;
@ -785,8 +779,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (!scratch_buffer_grow (tmpbuf)) if (!scratch_buffer_grow (tmpbuf))
{ {
__resolv_context_enable_inet6
(res_ctx, res_enable_inet6);
__resolv_context_put (res_ctx); __resolv_context_put (res_ctx);
result = -EAI_MEMORY; result = -EAI_MEMORY;
goto free_and_return; goto free_and_return;
@ -886,8 +878,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
canonbuf = getcanonname (nip, at, name); canonbuf = getcanonname (nip, at, name);
if (canonbuf == NULL) if (canonbuf == NULL)
{ {
__resolv_context_enable_inet6
(res_ctx, res_enable_inet6);
__resolv_context_put (res_ctx); __resolv_context_put (res_ctx);
result = -EAI_MEMORY; result = -EAI_MEMORY;
goto free_and_return; goto free_and_return;
@ -932,7 +922,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
nip = nip->next; nip = nip->next;
} }
__resolv_context_enable_inet6 (res_ctx, res_enable_inet6);
__resolv_context_put (res_ctx); __resolv_context_put (res_ctx);
/* If we have a failure which sets errno, report it using /* If we have a failure which sets errno, report it using