Compare commits
26 Commits
Author | SHA1 | Date |
---|---|---|
Florian Weimer | ab210104fb | |
Florian Weimer | bdd2e8da08 | |
Florian Weimer | 6b34bf502d | |
Florian Weimer | bd8a4ead36 | |
Florian Weimer | 8597553f96 | |
Florian Weimer | a13e3a1e46 | |
Florian Weimer | 3262c2cba5 | |
Florian Weimer | cd836dbd43 | |
Florian Weimer | 0f76f1d26a | |
Florian Weimer | 95f1260cfd | |
Florian Weimer | e2343bce79 | |
Florian Weimer | b17de1d824 | |
Florian Weimer | d9fc484e2b | |
Florian Weimer | 59c40130ab | |
Florian Weimer | 387c3212c7 | |
Florian Weimer | e68f1ebb7b | |
Florian Weimer | d771af991f | |
Florian Weimer | 67abe960c0 | |
Florian Weimer | be8d2dcb53 | |
Florian Weimer | 4cd15aea67 | |
Florian Weimer | 77cd17d274 | |
Florian Weimer | 2d4666e460 | |
Florian Weimer | 669790c2cf | |
Florian Weimer | a2f7bb7876 | |
Arjun Shankar | 190fd58e63 | |
Florian Weimer | e43c7ab809 |
|
@ -0,0 +1,29 @@
|
|||
commit d54bb9b1d3fd25779fba2c403003c5097ba9af73
|
||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||||
Date: Mon Jun 26 09:55:41 2017 -0300
|
||||
|
||||
Prevent an implicit int promotion in malloc/tst-alloc_buffer.c
|
||||
|
||||
According to ISO C11, section 6.5.3.3 "Unary arithmetic operators", the
|
||||
result of the ~ operator is the bitwise complement of its (promoted)
|
||||
operand.
|
||||
This can lead to a comparison of a char with another integer type.
|
||||
|
||||
Tested on powerpc, powerpc64 and powerpc64le.
|
||||
|
||||
* malloc/tst-alloc_buffer.c (test_misaligned): Cast to char
|
||||
before comparing with another char.
|
||||
|
||||
diff --git a/malloc/tst-alloc_buffer.c b/malloc/tst-alloc_buffer.c
|
||||
index 1c143999c70180f7..9b2bd2046a12c0f2 100644
|
||||
--- a/malloc/tst-alloc_buffer.c
|
||||
+++ b/malloc/tst-alloc_buffer.c
|
||||
@@ -429,7 +429,7 @@ test_misaligned (char pad)
|
||||
}
|
||||
|
||||
/* Verify that padding was not overwritten. */
|
||||
- TEST_VERIFY (backing[0] == ~pad);
|
||||
+ TEST_VERIFY (backing[0] == (char) ~pad);
|
||||
TEST_VERIFY (backing[SIZE + 1] == pad);
|
||||
free (backing);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
Add <bits/types/res_state.h> to simplify backports.
|
||||
|
||||
Introduced upstream as part of this commit:
|
||||
|
||||
commit 500b3a499fff61157db464a99f459c772d7eb6c0
|
||||
Author: Zack Weinberg <zackw@panix.com>
|
||||
Date: Wed Mar 22 09:55:25 2017 -0400
|
||||
|
||||
Remove __need_list_t and __need_res_state.
|
||||
|
||||
diff --git a/include/bits/types/res_state.h b/include/bits/types/res_state.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..172103878d28a7ee
|
||||
--- /dev/null
|
||||
+++ b/include/bits/types/res_state.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <resolv.h>
|
|
@ -21,10 +21,11 @@
|
|||
# elf/rtld.c | 4 ----
|
||||
# 4 files changed, 7 insertions(+), 10 deletions(-)
|
||||
#
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/dl-init.c glibc-2.20-205-ga39208b.mod/elf/dl-init.c
|
||||
--- glibc-2.20-205-ga39208b/elf/dl-init.c 2014-11-21 16:08:32.744913590 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/dl-init.c 2014-11-21 16:09:42.485708197 -0500
|
||||
@@ -119,8 +119,6 @@
|
||||
Index: b/elf/dl-init.c
|
||||
===================================================================
|
||||
--- a/elf/dl-init.c
|
||||
+++ b/elf/dl-init.c
|
||||
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
|
||||
while (i-- > 0)
|
||||
call_init (main_map->l_initfini[i], argc, argv, env);
|
||||
|
||||
|
@ -33,10 +34,11 @@ diff -urN glibc-2.20-205-ga39208b/elf/dl-init.c glibc-2.20-205-ga39208b.mod/elf/
|
|||
_dl_starting_up = 0;
|
||||
-#endif
|
||||
}
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/dl-support.c glibc-2.20-205-ga39208b.mod/elf/dl-support.c
|
||||
--- glibc-2.20-205-ga39208b/elf/dl-support.c 2014-11-19 14:35:03.000000000 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/dl-support.c 2014-11-21 16:09:54.829671843 -0500
|
||||
@@ -118,10 +118,8 @@
|
||||
Index: b/elf/dl-support.c
|
||||
===================================================================
|
||||
--- a/elf/dl-support.c
|
||||
+++ b/elf/dl-support.c
|
||||
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
|
||||
.r_nlist = 1,
|
||||
};
|
||||
|
||||
|
@ -47,18 +49,19 @@ diff -urN glibc-2.20-205-ga39208b/elf/dl-support.c glibc-2.20-205-ga39208b.mod/e
|
|||
|
||||
/* Random data provided by the kernel. */
|
||||
void *_dl_random;
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/rtld.c glibc-2.20-205-ga39208b.mod/elf/rtld.c
|
||||
--- glibc-2.20-205-ga39208b/elf/rtld.c 2014-11-21 16:08:32.745913587 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/rtld.c 2014-11-21 16:09:05.614816785 -0500
|
||||
@@ -107,7 +107,6 @@
|
||||
struct audit_list *next;
|
||||
} *audit_list;
|
||||
Index: b/elf/rtld.c
|
||||
===================================================================
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
|
||||
return iter->previous->name;
|
||||
}
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
must not be initialized to nonzero, because the unused dynamic
|
||||
@@ -117,7 +116,6 @@
|
||||
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
|
||||
never be called. */
|
||||
int _dl_starting_up = 0;
|
||||
rtld_hidden_def (_dl_starting_up)
|
||||
|
@ -66,7 +69,7 @@ diff -urN glibc-2.20-205-ga39208b/elf/rtld.c glibc-2.20-205-ga39208b.mod/elf/rtl
|
|||
|
||||
/* This is the structure which defines all variables global to ld.so
|
||||
(except those which cannot be added for some reason). */
|
||||
@@ -776,10 +774,8 @@
|
||||
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Process the environment variable which control the behaviour. */
|
||||
process_envvars (&mode);
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
Builds with gcc 7.0 fail with:
|
||||
|
||||
../test-skeleton.c: In function ‘legacy_test_function’:
|
||||
cc1: error: assuming signed overflow does not occur when \
|
||||
assuming that (X - c) <= X is always true [-Werror=strict-overflow]
|
||||
|
||||
Ignoring this warning until the test or compiler is adjusted.
|
||||
Disabled with -Wno-strict-overflow. Attempted -Wstrict-overflow=1,
|
||||
but it still results in the same warning.
|
||||
|
||||
Index: glibc-2.24-661-g5653ab1/string/Makefile
|
||||
===================================================================
|
||||
--- glibc-2.24-661-g5653ab1.orig/string/Makefile
|
||||
+++ glibc-2.24-661-g5653ab1/string/Makefile
|
||||
@@ -71,7 +71,9 @@ include ../Rules
|
||||
CFLAGS-inl-tester.c = -fno-builtin
|
||||
CFLAGS-noinl-tester.c = -fno-builtin
|
||||
CFLAGS-tst-strlen.c = -fno-builtin
|
||||
-CFLAGS-stratcliff.c = -fno-builtin
|
||||
+# Added '-Wno-strict-overflow' for gcc 7.0 until the test or compiler
|
||||
+# is adjusted.
|
||||
+CFLAGS-stratcliff.c = -fno-builtin -Wno-strict-overflow
|
||||
CFLAGS-test-ffs.c = -fno-builtin
|
||||
CFLAGS-tst-inlcall.c = -fno-builtin
|
||||
CFLAGS-tst-xbzero-opt.c = -O3
|
||||
Index: glibc-2.24-661-g5653ab1/wcsmbs/Makefile
|
||||
===================================================================
|
||||
--- glibc-2.24-661-g5653ab1.orig/wcsmbs/Makefile
|
||||
+++ glibc-2.24-661-g5653ab1/wcsmbs/Makefile
|
||||
@@ -102,3 +102,7 @@ CPPFLAGS += $(libio-mtsafe)
|
||||
CPPFLAGS-wcstold_l.c = -I../stdlib
|
||||
|
||||
$(objpfx)tst-wcstod-nan-locale: $(libm)
|
||||
+
|
||||
+# Added '-Wno-strict-overflow' for gcc 7.0 until the test or compiler
|
||||
+# is adjusted.
|
||||
+CFLAGS-wcsatcliff.c = -Wno-strict-overflow
|
|
@ -0,0 +1,17 @@
|
|||
Add <libc-diag.h> to simplify backports.
|
||||
|
||||
Added upstream as part of this commit:
|
||||
|
||||
commit e15f7de60c26bb75fe1923b17c5f0461164d1a41
|
||||
Author: Zack Weinberg <zackw@panix.com>
|
||||
Date: Sun Nov 20 20:46:30 2016 -0500
|
||||
|
||||
Split DIAG_* macros to new header libc-diag.h.
|
||||
|
||||
diff --git a/include/libc-diag.h b/include/libc-diag.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..5876a41e8e5fcc15
|
||||
--- /dev/null
|
||||
+++ b/include/libc-diag.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <libc-internal.h>
|
|
@ -0,0 +1,70 @@
|
|||
commit 1e9522c61c7a544d59db32cb7fbbd42e6793d848
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Oct 5 18:14:27 2017 +0200
|
||||
|
||||
nscd: Eliminate compilation time dependency in the build output
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/nscd/nscd_stat.c b/nscd/nscd_stat.c
|
||||
index feb1c98ac31edcb8..b1bc81bd6d7d7fd1 100644
|
||||
--- a/nscd/nscd_stat.c
|
||||
+++ b/nscd/nscd_stat.c
|
||||
@@ -35,9 +35,23 @@
|
||||
# include <selinux/avc.h>
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
+/* We use this to make sure the receiver is the same. The lower 16
|
||||
+ bits are reserved for flags indicating compilation variants. This
|
||||
+ version needs to be updated if the definition of struct statdata
|
||||
+ changes. */
|
||||
+#define STATDATA_VERSION 0x01020000U
|
||||
|
||||
-/* We use this to make sure the receiver is the same. */
|
||||
-static const char compilation[21] = __DATE__ " " __TIME__;
|
||||
+#ifdef HAVE_SELINUX
|
||||
+# define STATDATA_VERSION_SELINUX_FLAG 0x0001U
|
||||
+#else
|
||||
+# define STATDATA_VERSION_SELINUX_FLAG 0x0000U
|
||||
+#endif
|
||||
+
|
||||
+/* All flags affecting the struct statdata layout. */
|
||||
+#define STATDATA_VERSION_FLAGS STATDATA_VERSION_SELINUX_FLAG
|
||||
+
|
||||
+/* The full version number for struct statdata. */
|
||||
+#define STATDATA_VERSION_FULL (STATDATA_VERSION | STATDATA_VERSION_FLAGS)
|
||||
|
||||
/* Statistic data for one database. */
|
||||
struct dbstat
|
||||
@@ -68,10 +82,11 @@ struct dbstat
|
||||
uintmax_t addfailed;
|
||||
};
|
||||
|
||||
-/* Record for transmitting statistics. */
|
||||
+/* Record for transmitting statistics. If this definition changes,
|
||||
+ update STATDATA_VERSION above. */
|
||||
struct statdata
|
||||
{
|
||||
- char version[sizeof (compilation)];
|
||||
+ unsigned int version; /* Must be STATDATA_VERSION_FULL. */
|
||||
int debug_level;
|
||||
time_t runtime;
|
||||
unsigned long int client_queued;
|
||||
@@ -96,7 +111,7 @@ send_stats (int fd, struct database_dyn dbs[lastdb])
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
|
||||
- memcpy (data.version, compilation, sizeof (compilation));
|
||||
+ data.version = STATDATA_VERSION_FULL;
|
||||
data.debug_level = debug_level;
|
||||
data.runtime = time (NULL) - start_time;
|
||||
data.client_queued = client_queued;
|
||||
@@ -196,7 +211,7 @@ receive_print_stats (void)
|
||||
|
||||
/* Read as much data as we expect. */
|
||||
if (TEMP_FAILURE_RETRY (read (fd, &data, sizeof (data))) != sizeof (data)
|
||||
- || (memcmp (data.version, compilation, sizeof (compilation)) != 0
|
||||
+ || (data.version != STATDATA_VERSION_FULL
|
||||
/* Yes, this is an assignment! */
|
||||
&& (errno = EINVAL)))
|
||||
{
|
|
@ -0,0 +1,448 @@
|
|||
commit 64d1e08ea822bf47cb2796ad0f727136227f983c
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Mon Oct 2 14:30:46 2017 +0200
|
||||
|
||||
Move nss_compat from nis to nss subdir and install it unconditionally
|
||||
|
||||
This has been tested that local lookup still works with and
|
||||
without an installed libnss_nis, and that NIS lookup works when
|
||||
libnss_nis is available.
|
||||
|
||||
diff --git a/nis/Makefile b/nis/Makefile
|
||||
index d6be9e27fd8e90bc..81a51b6d7fc7cf55 100644
|
||||
--- a/nis/Makefile
|
||||
+++ b/nis/Makefile
|
||||
@@ -34,7 +34,7 @@ databases = proto service hosts network grp pwd rpc ethers \
|
||||
spwd netgrp alias publickey
|
||||
|
||||
# Specify rules for the nss_* modules.
|
||||
-services := nis nisplus compat
|
||||
+services := nis nisplus
|
||||
|
||||
extra-libs = libnsl $(services:%=libnss_%)
|
||||
# These libraries will be built in the `others' pass rather than
|
||||
@@ -57,9 +57,6 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
|
||||
nis_findserv nis_callback nis_clone_dir nis_clone_obj\
|
||||
nis_clone_res nss-default
|
||||
|
||||
-libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups)
|
||||
-libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
-
|
||||
libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \
|
||||
nss-nis
|
||||
libnss_nis-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
@@ -71,7 +68,6 @@ libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
include ../Rules
|
||||
|
||||
|
||||
-$(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version)
|
||||
$(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \
|
||||
$(common-objpfx)nss/libnss_files.so
|
||||
$(objpfx)libnss_nisplus.so: $(objpfx)libnsl.so$(libnsl.so-version)
|
||||
diff --git a/nis/Versions b/nis/Versions
|
||||
index ef9a5124174ec0e8..90d3d9dfaa3d853b 100644
|
||||
--- a/nis/Versions
|
||||
+++ b/nis/Versions
|
||||
@@ -63,17 +63,6 @@ libnsl {
|
||||
}
|
||||
}
|
||||
|
||||
-libnss_compat {
|
||||
- GLIBC_PRIVATE {
|
||||
- _nss_compat_endgrent; _nss_compat_endpwent; _nss_compat_endspent;
|
||||
- _nss_compat_getgrent_r; _nss_compat_getgrgid_r; _nss_compat_getgrnam_r;
|
||||
- _nss_compat_getpwent_r; _nss_compat_getpwnam_r; _nss_compat_getpwuid_r;
|
||||
- _nss_compat_getspent_r; _nss_compat_getspnam_r;
|
||||
- _nss_compat_setgrent; _nss_compat_setpwent; _nss_compat_setspent;
|
||||
- _nss_compat_initgroups_dyn;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
libnss_nis {
|
||||
GLIBC_PRIVATE {
|
||||
_nss_nis_endaliasent; _nss_nis_endetherent; _nss_nis_endgrent;
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index de6c47a1dbab9879..f0a6e4877fac6bf7 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -61,7 +61,7 @@ tests += tst-cancel-getpwuid_r
|
||||
endif
|
||||
|
||||
# Specify rules for the nss_* modules. We have some services.
|
||||
-services := files db
|
||||
+services := files db compat
|
||||
|
||||
extra-libs = $(services:%=libnss_%)
|
||||
# These libraries will be built in the `others' pass rather than
|
||||
@@ -84,11 +84,15 @@ libnss_db-routines := $(libnss_db-dbs) db-open db-init hash-string
|
||||
generated += $(filter-out db-alias.c db-netgrp.c, \
|
||||
$(addsuffix .c,$(libnss_db-dbs)))
|
||||
|
||||
+libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) \
|
||||
+ nisdomain
|
||||
+
|
||||
install-others += $(inst_vardbdir)/Makefile
|
||||
|
||||
# Build static module into libc if requested
|
||||
libnss_files-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
libnss_db-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
+libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
ifeq ($(build-static-nss),yes)
|
||||
routines += $(libnss_files-routines)
|
||||
static-only-routines += $(libnss_files-routines)
|
||||
diff --git a/nss/Versions b/nss/Versions
|
||||
index f8ababccc74d1dd2..14c2571468169e4d 100644
|
||||
--- a/nss/Versions
|
||||
+++ b/nss/Versions
|
||||
@@ -160,3 +160,14 @@ libnss_db {
|
||||
_nss_db_init;
|
||||
}
|
||||
}
|
||||
+
|
||||
+libnss_compat {
|
||||
+ GLIBC_PRIVATE {
|
||||
+ _nss_compat_endgrent; _nss_compat_endpwent; _nss_compat_endspent;
|
||||
+ _nss_compat_getgrent_r; _nss_compat_getgrgid_r; _nss_compat_getgrnam_r;
|
||||
+ _nss_compat_getpwent_r; _nss_compat_getpwnam_r; _nss_compat_getpwuid_r;
|
||||
+ _nss_compat_getspent_r; _nss_compat_getspnam_r;
|
||||
+ _nss_compat_setgrent; _nss_compat_setpwent; _nss_compat_setspent;
|
||||
+ _nss_compat_initgroups_dyn;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/nis/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c
|
||||
similarity index 97%
|
||||
rename from nis/nss_compat/compat-grp.c
|
||||
rename to nss/nss_compat/compat-grp.c
|
||||
index e830a2f0a2a1f169..fecbd35f270a7943 100644
|
||||
--- a/nis/nss_compat/compat-grp.c
|
||||
+++ b/nss/nss_compat/compat-grp.c
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <nsswitch.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <string.h>
|
||||
-#include <rpc/types.h>
|
||||
#include <libc-lock.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
@@ -58,14 +57,14 @@ struct blacklist_t
|
||||
|
||||
struct ent_t
|
||||
{
|
||||
- bool_t files;
|
||||
+ bool files;
|
||||
enum nss_status setent_status;
|
||||
FILE *stream;
|
||||
struct blacklist_t blacklist;
|
||||
};
|
||||
typedef struct ent_t ent_t;
|
||||
|
||||
-static ent_t ext_ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
|
||||
+static ent_t ext_ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
|
||||
|
||||
/* Protect global state against multiple changers. */
|
||||
__libc_lock_define_initialized (static, lock)
|
||||
@@ -85,7 +84,7 @@ int __compat_have_cloexec;
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
static void blacklist_store_name (const char *, ent_t *);
|
||||
-static int in_blacklist (const char *, int, ent_t *);
|
||||
+static bool in_blacklist (const char *, int, ent_t *);
|
||||
|
||||
/* Initialize the NSS interface/functions. The calling function must
|
||||
hold the lock. */
|
||||
@@ -107,7 +106,7 @@ internal_setgrent (ent_t *ent, int stayopen, int needent)
|
||||
{
|
||||
enum nss_status status = NSS_STATUS_SUCCESS;
|
||||
|
||||
- ent->files = TRUE;
|
||||
+ ent->files = true;
|
||||
|
||||
if (ent->blacklist.data != NULL)
|
||||
{
|
||||
@@ -369,7 +368,7 @@ getgrent_next_file (struct group *result, ent_t *ent,
|
||||
/* +:... */
|
||||
if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
|
||||
{
|
||||
- ent->files = FALSE;
|
||||
+ ent->files = false;
|
||||
|
||||
return getgrent_next_nss (result, ent, buffer, buflen, errnop);
|
||||
}
|
||||
@@ -514,7 +513,7 @@ enum nss_status
|
||||
_nss_compat_getgrnam_r (const char *name, struct group *grp,
|
||||
char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
- ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
|
||||
+ ent_t ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
|
||||
enum nss_status result;
|
||||
|
||||
if (name[0] == '-' || name[0] == '+')
|
||||
@@ -646,7 +645,7 @@ enum nss_status
|
||||
_nss_compat_getgrgid_r (gid_t gid, struct group *grp,
|
||||
char *buffer, size_t buflen, int *errnop)
|
||||
{
|
||||
- ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
|
||||
+ ent_t ent = { true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
|
||||
enum nss_status result;
|
||||
|
||||
__libc_lock_lock (lock);
|
||||
@@ -713,15 +712,15 @@ blacklist_store_name (const char *name, ent_t *ent)
|
||||
return;
|
||||
}
|
||||
|
||||
-/* returns TRUE if ent->blacklist contains name, else FALSE */
|
||||
-static bool_t
|
||||
+/* Return whether ent->blacklist contains name. */
|
||||
+static bool
|
||||
in_blacklist (const char *name, int namelen, ent_t *ent)
|
||||
{
|
||||
char buf[namelen + 3];
|
||||
char *cp;
|
||||
|
||||
if (ent->blacklist.data == NULL)
|
||||
- return FALSE;
|
||||
+ return false;
|
||||
|
||||
buf[0] = '|';
|
||||
cp = stpcpy (&buf[1], name);
|
||||
diff --git a/nis/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c
|
||||
similarity index 98%
|
||||
rename from nis/nss_compat/compat-initgroups.c
|
||||
rename to nss/nss_compat/compat-initgroups.c
|
||||
index cc3db7889ba289db..a603a33e13dec134 100644
|
||||
--- a/nis/nss_compat/compat-initgroups.c
|
||||
+++ b/nss/nss_compat/compat-initgroups.c
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <stdio_ext.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
-#include <rpc/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <nsswitch.h>
|
||||
#include <libc-lock.h>
|
||||
@@ -93,7 +92,7 @@ extern int __compat_have_cloexec;
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
static void blacklist_store_name (const char *, ent_t *);
|
||||
-static int in_blacklist (const char *, int, ent_t *);
|
||||
+static bool in_blacklist (const char *, int, ent_t *);
|
||||
|
||||
/* Initialize the NSS interface/functions. The calling function must
|
||||
hold the lock. */
|
||||
@@ -602,15 +601,15 @@ blacklist_store_name (const char *name, ent_t *ent)
|
||||
return;
|
||||
}
|
||||
|
||||
-/* returns TRUE if ent->blacklist contains name, else FALSE */
|
||||
-static bool_t
|
||||
+/* Return whether ent->blacklist contains name. */
|
||||
+static bool
|
||||
in_blacklist (const char *name, int namelen, ent_t *ent)
|
||||
{
|
||||
char buf[namelen + 3];
|
||||
char *cp;
|
||||
|
||||
if (ent->blacklist.data == NULL)
|
||||
- return FALSE;
|
||||
+ return false;
|
||||
|
||||
buf[0] = '|';
|
||||
cp = stpcpy (&buf[1], name);
|
||||
diff --git a/nis/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c
|
||||
similarity index 99%
|
||||
rename from nis/nss_compat/compat-pwd.c
|
||||
rename to nss/nss_compat/compat-pwd.c
|
||||
index 28ae7fba84db8617..577af3a0fd8b50c3 100644
|
||||
--- a/nis/nss_compat/compat-pwd.c
|
||||
+++ b/nss/nss_compat/compat-pwd.c
|
||||
@@ -25,12 +25,11 @@
|
||||
#include <pwd.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <string.h>
|
||||
-#include <rpc/types.h>
|
||||
-#include <rpcsvc/ypclnt.h>
|
||||
#include <libc-lock.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
#include "netgroup.h"
|
||||
+#include "nisdomain.h"
|
||||
|
||||
static service_user *ni;
|
||||
static enum nss_status (*nss_setpwent) (int stayopen);
|
||||
@@ -95,7 +94,7 @@ extern int __compat_have_cloexec;
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
static void blacklist_store_name (const char *, ent_t *);
|
||||
-static int in_blacklist (const char *, int, ent_t *);
|
||||
+static bool in_blacklist (const char *, int, ent_t *);
|
||||
|
||||
/* Initialize the NSS interface/functions. The calling function must
|
||||
hold the lock. */
|
||||
@@ -394,7 +393,7 @@ getpwent_next_nss_netgr (const char *name, struct passwd *result, ent_t *ent,
|
||||
if (domain != NULL)
|
||||
{
|
||||
if (curdomain == NULL
|
||||
- && yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
|
||||
+ && __nss_get_default_domain (&curdomain) != 0)
|
||||
{
|
||||
__internal_endnetgrent (&ent->netgrdata);
|
||||
ent->netgroup = false;
|
||||
@@ -1162,15 +1161,15 @@ blacklist_store_name (const char *name, ent_t *ent)
|
||||
return;
|
||||
}
|
||||
|
||||
-/* Returns TRUE if ent->blacklist contains name, else FALSE. */
|
||||
-static bool_t
|
||||
+/* Returns whether ent->blacklist contains name. */
|
||||
+static bool
|
||||
in_blacklist (const char *name, int namelen, ent_t *ent)
|
||||
{
|
||||
char buf[namelen + 3];
|
||||
char *cp;
|
||||
|
||||
if (ent->blacklist.data == NULL)
|
||||
- return FALSE;
|
||||
+ return false;
|
||||
|
||||
buf[0] = '|';
|
||||
cp = stpcpy (&buf[1], name);
|
||||
diff --git a/nis/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c
|
||||
similarity index 98%
|
||||
rename from nis/nss_compat/compat-spwd.c
|
||||
rename to nss/nss_compat/compat-spwd.c
|
||||
index 550444cd800743bb..b96328a7dcb82953 100644
|
||||
--- a/nis/nss_compat/compat-spwd.c
|
||||
+++ b/nss/nss_compat/compat-spwd.c
|
||||
@@ -25,12 +25,11 @@
|
||||
#include <shadow.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <string.h>
|
||||
-#include <rpc/types.h>
|
||||
-#include <rpcsvc/ypclnt.h>
|
||||
#include <libc-lock.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
#include "netgroup.h"
|
||||
+#include "nisdomain.h"
|
||||
|
||||
static service_user *ni;
|
||||
static enum nss_status (*nss_setspent) (int stayopen);
|
||||
@@ -92,7 +91,7 @@ extern int __compat_have_cloexec;
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
static void blacklist_store_name (const char *, ent_t *);
|
||||
-static int in_blacklist (const char *, int, ent_t *);
|
||||
+static bool in_blacklist (const char *, int, ent_t *);
|
||||
|
||||
/* Initialize the NSS interface/functions. The calling function must
|
||||
hold the lock. */
|
||||
@@ -354,7 +353,7 @@ getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent,
|
||||
if (domain != NULL)
|
||||
{
|
||||
if (curdomain == NULL
|
||||
- && yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
|
||||
+ && __nss_get_default_domain (&curdomain) != 0)
|
||||
{
|
||||
__internal_endnetgrent (&ent->netgrdata);
|
||||
ent->netgroup = false;
|
||||
@@ -888,8 +887,8 @@ blacklist_store_name (const char *name, ent_t *ent)
|
||||
}
|
||||
|
||||
|
||||
-/* Returns TRUE if ent->blacklist contains name, else FALSE. */
|
||||
-static bool_t
|
||||
+/* Returns whether ent->blacklist contains name. */
|
||||
+static bool
|
||||
in_blacklist (const char *name, int namelen, ent_t *ent)
|
||||
{
|
||||
char buf[namelen + 3];
|
||||
diff --git a/nss/nss_compat/nisdomain.c b/nss/nss_compat/nisdomain.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..220ae27234705855
|
||||
--- /dev/null
|
||||
+++ b/nss/nss_compat/nisdomain.c
|
||||
@@ -0,0 +1,58 @@
|
||||
+/* Copyright (C) 2017 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 <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <errno.h>
|
||||
+#include <unistd.h>
|
||||
+#include <libc-lock.h>
|
||||
+#include "nisdomain.h"
|
||||
+
|
||||
+#define MAXDOMAINNAMELEN 1024
|
||||
+
|
||||
+static char domainname[MAXDOMAINNAMELEN];
|
||||
+
|
||||
+__libc_lock_define_initialized (static, domainname_lock)
|
||||
+
|
||||
+int
|
||||
+__nss_get_default_domain (char **outdomain)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ *outdomain = NULL;
|
||||
+
|
||||
+ __libc_lock_lock (domainname_lock);
|
||||
+
|
||||
+ if (domainname[0] != '\0')
|
||||
+ {
|
||||
+ if (getdomainname (domainname, MAXDOMAINNAMELEN) < 0)
|
||||
+ result = errno;
|
||||
+ else if (strcmp (domainname, "(none)") == 0)
|
||||
+ {
|
||||
+ /* If domainname is not set, some systems will return "(none)" */
|
||||
+ domainname[0] = '\0';
|
||||
+ result = ENOENT;
|
||||
+ }
|
||||
+ else
|
||||
+ *outdomain = domainname;
|
||||
+ }
|
||||
+ else
|
||||
+ *outdomain = domainname;
|
||||
+
|
||||
+ __libc_lock_unlock (domainname_lock);
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
diff --git a/nss/nss_compat/nisdomain.h b/nss/nss_compat/nisdomain.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..314f3f7c069835af
|
||||
--- /dev/null
|
||||
+++ b/nss/nss_compat/nisdomain.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* Copyright (C) 2017 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/>. */
|
||||
+
|
||||
+/* Set OUTDOMAIN to a pointer to the current NIS domain name, or NULL if
|
||||
+ not set. Return zero on success, an error number on failure. */
|
||||
+extern int __nss_get_default_domain (char **outdomain);
|
|
@ -0,0 +1,271 @@
|
|||
commit 5a79f97554af6f2eb0a654f844b3d1f56937064d
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Mon Sep 4 17:00:03 2017 -0300
|
||||
|
||||
posix: Fix getpwnam_r usage (BZ #1062)
|
||||
|
||||
This patch fixes longstanding misuse of errno after getpwnam_r,
|
||||
which returns an error number rather than setting errno. This is
|
||||
sync with gnulib commit 5db9301.
|
||||
|
||||
Checked on x86_64-linux-gnu and on a build using build-many-glibcs.py
|
||||
for all major architectures.
|
||||
|
||||
[BZ #1062]
|
||||
* posix/glob.c (glob): Port recent patches to platforms
|
||||
lacking getpwnam_r.
|
||||
(glob): Fix longstanding misuse of errno after getpwnam_r, which
|
||||
returns an error number rather than setting errno.
|
||||
|
||||
diff --git a/posix/glob.c b/posix/glob.c
|
||||
index c761c0861ddb49ea..70434745f57f8ff5 100644
|
||||
--- a/posix/glob.c
|
||||
+++ b/posix/glob.c
|
||||
@@ -15,10 +15,6 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#ifndef _LIBC
|
||||
-# include <config.h>
|
||||
-#endif
|
||||
-
|
||||
#include <glob.h>
|
||||
|
||||
#include <errno.h>
|
||||
@@ -39,10 +35,6 @@
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
-#ifndef __set_errno
|
||||
-# define __set_errno(val) errno = (val)
|
||||
-#endif
|
||||
-
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -78,12 +70,8 @@
|
||||
|
||||
#include <flexmember.h>
|
||||
#include <glob_internal.h>
|
||||
+#include <scratch_buffer.h>
|
||||
|
||||
-#ifdef _SC_GETPW_R_SIZE_MAX
|
||||
-# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
|
||||
-#else
|
||||
-# define GETPW_R_SIZE_MAX() (-1)
|
||||
-#endif
|
||||
#ifdef _SC_LOGIN_NAME_MAX
|
||||
# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX)
|
||||
#else
|
||||
@@ -651,97 +639,36 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
|
||||
if (success)
|
||||
{
|
||||
struct passwd *p;
|
||||
- char *malloc_pwtmpbuf = NULL;
|
||||
- char *pwtmpbuf;
|
||||
+ struct scratch_buffer pwtmpbuf;
|
||||
+ scratch_buffer_init (&pwtmpbuf);
|
||||
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
||||
- long int pwbuflenmax = GETPW_R_SIZE_MAX ();
|
||||
- size_t pwbuflen = pwbuflenmax;
|
||||
struct passwd pwbuf;
|
||||
- int save = errno;
|
||||
|
||||
-# ifndef _LIBC
|
||||
- if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
|
||||
- /* 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.
|
||||
- Try a moderate value. */
|
||||
- pwbuflen = 1024;
|
||||
-# endif
|
||||
- if (glob_use_alloca (alloca_used, pwbuflen))
|
||||
- pwtmpbuf = alloca_account (pwbuflen, alloca_used);
|
||||
- else
|
||||
+ while (getpwnam_r (name, &pwbuf,
|
||||
+ pwtmpbuf.data, pwtmpbuf.length, &p)
|
||||
+ == ERANGE)
|
||||
{
|
||||
- pwtmpbuf = malloc (pwbuflen);
|
||||
- if (pwtmpbuf == NULL)
|
||||
+ if (!scratch_buffer_grow (&pwtmpbuf))
|
||||
{
|
||||
- if (__glibc_unlikely (malloc_name))
|
||||
- free (name);
|
||||
retval = GLOB_NOSPACE;
|
||||
goto out;
|
||||
}
|
||||
- malloc_pwtmpbuf = pwtmpbuf;
|
||||
- }
|
||||
-
|
||||
- while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
|
||||
- != 0)
|
||||
- {
|
||||
- size_t newlen;
|
||||
- bool v;
|
||||
- if (errno != ERANGE)
|
||||
- {
|
||||
- p = NULL;
|
||||
- break;
|
||||
- }
|
||||
- v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
|
||||
- if (!v && malloc_pwtmpbuf == NULL
|
||||
- && glob_use_alloca (alloca_used, newlen))
|
||||
- pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
|
||||
- newlen, alloca_used);
|
||||
- else
|
||||
- {
|
||||
- char *newp = (v ? NULL
|
||||
- : realloc (malloc_pwtmpbuf, newlen));
|
||||
- if (newp == NULL)
|
||||
- {
|
||||
- free (malloc_pwtmpbuf);
|
||||
- if (__glibc_unlikely (malloc_name))
|
||||
- free (name);
|
||||
- retval = GLOB_NOSPACE;
|
||||
- goto out;
|
||||
- }
|
||||
- malloc_pwtmpbuf = pwtmpbuf = newp;
|
||||
- }
|
||||
- pwbuflen = newlen;
|
||||
- __set_errno (save);
|
||||
}
|
||||
# else
|
||||
p = getpwnam (name);
|
||||
# endif
|
||||
- if (__glibc_unlikely (malloc_name))
|
||||
- free (name);
|
||||
if (p != NULL)
|
||||
{
|
||||
- if (malloc_pwtmpbuf == NULL)
|
||||
- home_dir = p->pw_dir;
|
||||
- else
|
||||
+ home_dir = strdup (p->pw_dir);
|
||||
+ malloc_home_dir = 1;
|
||||
+ if (home_dir == NULL)
|
||||
{
|
||||
- size_t home_dir_len = strlen (p->pw_dir) + 1;
|
||||
- if (glob_use_alloca (alloca_used, home_dir_len))
|
||||
- home_dir = alloca_account (home_dir_len,
|
||||
- alloca_used);
|
||||
- else
|
||||
- {
|
||||
- home_dir = malloc (home_dir_len);
|
||||
- if (home_dir == NULL)
|
||||
- {
|
||||
- free (pwtmpbuf);
|
||||
- retval = GLOB_NOSPACE;
|
||||
- goto out;
|
||||
- }
|
||||
- malloc_home_dir = 1;
|
||||
- }
|
||||
- memcpy (home_dir, p->pw_dir, home_dir_len);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
+ retval = GLOB_NOSPACE;
|
||||
+ goto out;
|
||||
}
|
||||
}
|
||||
- free (malloc_pwtmpbuf);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -878,61 +805,21 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
|
||||
/* Look up specific user's home directory. */
|
||||
{
|
||||
struct passwd *p;
|
||||
- char *malloc_pwtmpbuf = NULL;
|
||||
+ struct scratch_buffer pwtmpbuf;
|
||||
+ scratch_buffer_init (&pwtmpbuf);
|
||||
+
|
||||
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
||||
- long int buflenmax = GETPW_R_SIZE_MAX ();
|
||||
- size_t buflen = buflenmax;
|
||||
- char *pwtmpbuf;
|
||||
struct passwd pwbuf;
|
||||
- int save = errno;
|
||||
-
|
||||
-# ifndef _LIBC
|
||||
- if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
|
||||
- /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
|
||||
- moderate value. */
|
||||
- buflen = 1024;
|
||||
-# endif
|
||||
- if (glob_use_alloca (alloca_used, buflen))
|
||||
- pwtmpbuf = alloca_account (buflen, alloca_used);
|
||||
- else
|
||||
+
|
||||
+ while (getpwnam_r (user_name, &pwbuf,
|
||||
+ pwtmpbuf.data, pwtmpbuf.length, &p)
|
||||
+ == ERANGE)
|
||||
{
|
||||
- pwtmpbuf = malloc (buflen);
|
||||
- if (pwtmpbuf == NULL)
|
||||
+ if (!scratch_buffer_grow (&pwtmpbuf))
|
||||
{
|
||||
- nomem_getpw:
|
||||
- if (__glibc_unlikely (malloc_user_name))
|
||||
- free (user_name);
|
||||
retval = GLOB_NOSPACE;
|
||||
goto out;
|
||||
}
|
||||
- malloc_pwtmpbuf = pwtmpbuf;
|
||||
- }
|
||||
-
|
||||
- while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
|
||||
- {
|
||||
- size_t newlen;
|
||||
- bool v;
|
||||
- if (errno != ERANGE)
|
||||
- {
|
||||
- p = NULL;
|
||||
- break;
|
||||
- }
|
||||
- v = size_add_wrapv (buflen, buflen, &newlen);
|
||||
- if (!v && malloc_pwtmpbuf == NULL
|
||||
- && glob_use_alloca (alloca_used, newlen))
|
||||
- pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
|
||||
- newlen, alloca_used);
|
||||
- else
|
||||
- {
|
||||
- char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
|
||||
- if (newp == NULL)
|
||||
- {
|
||||
- free (malloc_pwtmpbuf);
|
||||
- goto nomem_getpw;
|
||||
- }
|
||||
- malloc_pwtmpbuf = pwtmpbuf = newp;
|
||||
- }
|
||||
- __set_errno (save);
|
||||
}
|
||||
# else
|
||||
p = getpwnam (user_name);
|
||||
@@ -959,7 +846,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
|
||||
dirname = malloc (home_len + rest_len + 1);
|
||||
if (dirname == NULL)
|
||||
{
|
||||
- free (malloc_pwtmpbuf);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
retval = GLOB_NOSPACE;
|
||||
goto out;
|
||||
}
|
||||
@@ -970,13 +857,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
|
||||
|
||||
dirlen = home_len + rest_len;
|
||||
dirname_modified = 1;
|
||||
-
|
||||
- free (malloc_pwtmpbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
- free (malloc_pwtmpbuf);
|
||||
-
|
||||
if (flags & GLOB_TILDE_CHECK)
|
||||
{
|
||||
/* We have to regard it as an error if we cannot find the
|
||||
@@ -985,6 +868,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
}
|
||||
#endif /* !WINDOWS32 */
|
||||
}
|
|
@ -156,16 +156,6 @@ Date: Sun Mar 1 19:48:31 2015 +0100
|
|||
* posix/wordexp.c (parse_tilde): Use struct scratch_buffer
|
||||
instead of extend_alloca.
|
||||
|
||||
commit 7b4c16db30304b83a5d1e913d1a8f7e90a8c398c
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sun Mar 1 19:49:50 2015 +0100
|
||||
|
||||
glob: Rewrite to use struct scratch_buffer instead of extend_alloca
|
||||
|
||||
[BZ #18023]
|
||||
* posix/glob.c (glob): Use struct scratch_buffer instead of
|
||||
extend_alloca.
|
||||
|
||||
commit 683543bbb3e2c1b17554c4096d00c2980f39a802
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sun Mar 1 23:22:45 2015 +0100
|
||||
|
@ -249,8 +239,9 @@ Date: Sun Mar 1 23:22:45 2015 +0100
|
|||
[BZ #18023]
|
||||
* include/alloca.h (stackinfo_alloca_round, extend_alloca,
|
||||
extend_alloca_account): Remove.
|
||||
Index: b/elf/dl-deps.c
|
||||
===================================================================
|
||||
|
||||
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
|
||||
index 1b8bac65932a7713..bc59f0ff7b4d7c61 100644
|
||||
--- a/elf/dl-deps.c
|
||||
+++ b/elf/dl-deps.c
|
||||
@@ -27,6 +27,7 @@
|
||||
|
@ -261,7 +252,7 @@ Index: b/elf/dl-deps.c
|
|||
|
||||
#include <dl-dst.h>
|
||||
|
||||
@@ -184,9 +185,8 @@ _dl_map_object_deps (struct link_map *ma
|
||||
@@ -184,9 +185,8 @@ _dl_map_object_deps (struct link_map *map,
|
||||
/* Pointer to last unique object. */
|
||||
tail = &known[nlist - 1];
|
||||
|
||||
|
@ -273,7 +264,7 @@ Index: b/elf/dl-deps.c
|
|||
|
||||
/* Process each element of the search list, loading each of its
|
||||
auxiliary objects and immediate dependencies. Auxiliary objects
|
||||
@@ -217,13 +217,12 @@ _dl_map_object_deps (struct link_map *ma
|
||||
@@ -217,13 +217,12 @@ _dl_map_object_deps (struct link_map *map,
|
||||
if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
|
||||
&& l != map && l->l_ldnum > 0)
|
||||
{
|
||||
|
@ -293,7 +284,7 @@ Index: b/elf/dl-deps.c
|
|||
}
|
||||
|
||||
if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
|
||||
@@ -463,8 +462,11 @@ _dl_map_object_deps (struct link_map *ma
|
||||
@@ -463,8 +462,11 @@ _dl_map_object_deps (struct link_map *map,
|
||||
struct link_map **l_initfini = (struct link_map **)
|
||||
malloc ((2 * nneeded + 1) * sizeof needed[0]);
|
||||
if (l_initfini == NULL)
|
||||
|
@ -307,7 +298,7 @@ Index: b/elf/dl-deps.c
|
|||
l_initfini[0] = l;
|
||||
memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]);
|
||||
memcpy (&l_initfini[nneeded + 1], l_initfini,
|
||||
@@ -482,6 +484,8 @@ _dl_map_object_deps (struct link_map *ma
|
||||
@@ -482,6 +484,8 @@ _dl_map_object_deps (struct link_map *map,
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -316,8 +307,8 @@ Index: b/elf/dl-deps.c
|
|||
if (errno == 0 && errno_saved != 0)
|
||||
__set_errno (errno_saved);
|
||||
|
||||
Index: b/include/alloca.h
|
||||
===================================================================
|
||||
diff --git a/include/alloca.h b/include/alloca.h
|
||||
index fd90664f0a17cd6d..c0b83954436ed4c1 100644
|
||||
--- a/include/alloca.h
|
||||
+++ b/include/alloca.h
|
||||
@@ -23,57 +23,17 @@ libc_hidden_proto (__libc_alloca_cutoff)
|
||||
|
@ -378,11 +369,11 @@ Index: b/include/alloca.h
|
|||
#endif
|
||||
|
||||
# endif /* !_ISOMAC */
|
||||
Index: b/nis/nss_compat/compat-initgroups.c
|
||||
===================================================================
|
||||
diff --git a/nis/nss_compat/compat-initgroups.c b/nis/nss_compat/compat-initgroups.c
|
||||
index 1b37e0c295f481df..cc3db7889ba289db 100644
|
||||
--- a/nis/nss_compat/compat-initgroups.c
|
||||
+++ b/nis/nss_compat/compat-initgroups.c
|
||||
@@ -310,7 +310,6 @@ getgrent_next_nss (ent_t *ent, char *buf
|
||||
@@ -310,7 +310,6 @@ getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
|
||||
overwrite the pointer with one to a bigger buffer. */
|
||||
char *tmpbuf = buffer;
|
||||
size_t tmplen = buflen;
|
||||
|
@ -390,7 +381,7 @@ Index: b/nis/nss_compat/compat-initgroups.c
|
|||
|
||||
for (int i = 0; i < mystart; i++)
|
||||
{
|
||||
@@ -319,29 +318,26 @@ getgrent_next_nss (ent_t *ent, char *buf
|
||||
@@ -319,29 +318,26 @@ getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
|
||||
== NSS_STATUS_TRYAGAIN
|
||||
&& *errnop == ERANGE)
|
||||
{
|
||||
|
@ -440,7 +431,7 @@ Index: b/nis/nss_compat/compat-initgroups.c
|
|||
}
|
||||
|
||||
if (__builtin_expect (status != NSS_STATUS_NOTFOUND, 1))
|
||||
@@ -369,7 +365,7 @@ getgrent_next_nss (ent_t *ent, char *buf
|
||||
@@ -369,7 +365,7 @@ getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
|
||||
status = NSS_STATUS_NOTFOUND;
|
||||
|
||||
done:
|
||||
|
@ -449,8 +440,8 @@ Index: b/nis/nss_compat/compat-initgroups.c
|
|||
free (tmpbuf);
|
||||
}
|
||||
|
||||
Index: b/nis/nss_nis/nis-initgroups.c
|
||||
===================================================================
|
||||
diff --git a/nis/nss_nis/nis-initgroups.c b/nis/nss_nis/nis-initgroups.c
|
||||
index 3784c101f7ee31aa..c872b32e15f55e3d 100644
|
||||
--- a/nis/nss_nis/nis-initgroups.c
|
||||
+++ b/nis/nss_nis/nis-initgroups.c
|
||||
@@ -16,7 +16,6 @@
|
||||
|
@ -469,7 +460,7 @@ Index: b/nis/nss_nis/nis-initgroups.c
|
|||
|
||||
#include "nss-nis.h"
|
||||
#include <libnsl.h>
|
||||
@@ -120,27 +120,30 @@ internal_getgrent_r (struct group *grp,
|
||||
@@ -120,27 +120,30 @@ internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
|
||||
static int
|
||||
get_uid (const char *user, uid_t *uidp)
|
||||
{
|
||||
|
@ -504,7 +495,7 @@ Index: b/nis/nss_nis/nis-initgroups.c
|
|||
return 1;
|
||||
}
|
||||
|
||||
@@ -254,8 +257,6 @@ _nss_nis_initgroups_dyn (const char *use
|
||||
@@ -254,8 +257,6 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
}
|
||||
|
||||
struct group grpbuf, *g;
|
||||
|
@ -513,7 +504,7 @@ Index: b/nis/nss_nis/nis-initgroups.c
|
|||
enum nss_status status;
|
||||
intern_t intern = { NULL, NULL, 0 };
|
||||
gid_t *groups = *groupsp;
|
||||
@@ -264,15 +265,21 @@ _nss_nis_initgroups_dyn (const char *use
|
||||
@@ -264,15 +265,21 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
|
@ -546,8 +537,8 @@ Index: b/nis/nss_nis/nis-initgroups.c
|
|||
|
||||
return status;
|
||||
}
|
||||
Index: b/nscd/aicache.c
|
||||
===================================================================
|
||||
diff --git a/nscd/aicache.c b/nscd/aicache.c
|
||||
index 7bf4131979451040..ea29b1c3d99bb530 100644
|
||||
--- a/nscd/aicache.c
|
||||
+++ b/nscd/aicache.c
|
||||
@@ -27,6 +27,7 @@
|
||||
|
@ -558,7 +549,7 @@ Index: b/nscd/aicache.c
|
|||
|
||||
#include "dbg_log.h"
|
||||
#include "nscd.h"
|
||||
@@ -113,10 +114,13 @@ addhstaiX (struct database_dyn *db, int
|
||||
@@ -113,10 +114,13 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
int old_res_options = _res.options;
|
||||
_res.options &= ~DEPRECATED_RES_USE_INET6;
|
||||
|
||||
|
@ -576,7 +567,7 @@ Index: b/nscd/aicache.c
|
|||
int32_t ttl = INT32_MAX;
|
||||
ssize_t total = 0;
|
||||
char *key_copy = NULL;
|
||||
@@ -129,6 +133,7 @@ addhstaiX (struct database_dyn *db, int
|
||||
@@ -129,6 +133,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL };
|
||||
int naddrs = 0;
|
||||
size_t addrslen = 0;
|
||||
|
@ -584,7 +575,7 @@ Index: b/nscd/aicache.c
|
|||
char *canon = NULL;
|
||||
size_t canonlen;
|
||||
|
||||
@@ -143,12 +148,17 @@ addhstaiX (struct database_dyn *db, int
|
||||
@@ -143,12 +148,17 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
at = &atmem;
|
||||
rc6 = 0;
|
||||
herrno = 0;
|
||||
|
@ -604,7 +595,7 @@ Index: b/nscd/aicache.c
|
|||
}
|
||||
|
||||
if (rc6 != 0 && herrno == NETDB_INTERNAL)
|
||||
@@ -226,41 +236,38 @@ addhstaiX (struct database_dyn *db, int
|
||||
@@ -226,41 +236,38 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
while (1)
|
||||
{
|
||||
rc6 = 0;
|
||||
|
@ -662,7 +653,7 @@ Index: b/nscd/aicache.c
|
|||
}
|
||||
|
||||
if (rc4 != 0 && herrno == NETDB_INTERNAL)
|
||||
@@ -286,13 +293,11 @@ addhstaiX (struct database_dyn *db, int
|
||||
@@ -286,13 +293,11 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
cfct = __nss_lookup_function (nip, "getcanonname_r");
|
||||
if (cfct != NULL)
|
||||
{
|
||||
|
@ -678,7 +669,7 @@ Index: b/nscd/aicache.c
|
|||
== NSS_STATUS_SUCCESS)
|
||||
canon = s;
|
||||
else
|
||||
@@ -321,18 +326,20 @@ addhstaiX (struct database_dyn *db, int
|
||||
@@ -321,18 +326,20 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
addrfamily = AF_INET6;
|
||||
}
|
||||
|
||||
|
@ -715,11 +706,11 @@ Index: b/nscd/aicache.c
|
|||
return timeout;
|
||||
}
|
||||
|
||||
Index: b/nscd/connections.c
|
||||
===================================================================
|
||||
diff --git a/nscd/connections.c b/nscd/connections.c
|
||||
index 26d2c0091b8f320d..9615c159285f0044 100644
|
||||
--- a/nscd/connections.c
|
||||
+++ b/nscd/connections.c
|
||||
@@ -1353,64 +1353,83 @@ request from '%s' [%ld] not handled due
|
||||
@@ -1353,64 +1353,83 @@ request from '%s' [%ld] not handled due to missing permission"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -739,20 +730,19 @@ Index: b/nscd/connections.c
|
|||
- size_t readlen = 0;
|
||||
int fd = open ("/proc/self/cmdline", O_RDONLY);
|
||||
- if (fd == -1)
|
||||
- {
|
||||
- dbg_log (_("\
|
||||
-cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
|
||||
- strerror (errno));
|
||||
-
|
||||
- paranoia = 0;
|
||||
- return;
|
||||
+ if (fd < 0)
|
||||
+ return NULL;
|
||||
+ size_t current = 0;
|
||||
+ size_t limit = 1024;
|
||||
+ char *buffer = malloc (limit);
|
||||
+ if (buffer == NULL)
|
||||
+ {
|
||||
{
|
||||
- dbg_log (_("\
|
||||
-cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
|
||||
- strerror (errno));
|
||||
-
|
||||
- paranoia = 0;
|
||||
- return;
|
||||
+ close (fd);
|
||||
+ errno = ENOMEM;
|
||||
+ return NULL;
|
||||
|
@ -842,7 +832,7 @@ Index: b/nscd/connections.c
|
|||
{
|
||||
argv[argc++] = cp;
|
||||
cp = (char *) rawmemchr (cp, '\0') + 1;
|
||||
@@ -1427,6 +1446,7 @@ cannot change to old UID: %s; disabling
|
||||
@@ -1427,6 +1446,7 @@ cannot change to old UID: %s; disabling paranoia mode"),
|
||||
strerror (errno));
|
||||
|
||||
paranoia = 0;
|
||||
|
@ -850,7 +840,7 @@ Index: b/nscd/connections.c
|
|||
return;
|
||||
}
|
||||
|
||||
@@ -1438,6 +1458,7 @@ cannot change to old GID: %s; disabling
|
||||
@@ -1438,6 +1458,7 @@ cannot change to old GID: %s; disabling paranoia mode"),
|
||||
|
||||
ignore_value (setuid (server_uid));
|
||||
paranoia = 0;
|
||||
|
@ -858,7 +848,7 @@ Index: b/nscd/connections.c
|
|||
return;
|
||||
}
|
||||
}
|
||||
@@ -1455,6 +1476,7 @@ cannot change to old working directory:
|
||||
@@ -1455,6 +1476,7 @@ cannot change to old working directory: %s; disabling paranoia mode"),
|
||||
ignore_value (setgid (server_gid));
|
||||
}
|
||||
paranoia = 0;
|
||||
|
@ -866,7 +856,7 @@ Index: b/nscd/connections.c
|
|||
return;
|
||||
}
|
||||
|
||||
@@ -1503,6 +1525,7 @@ cannot change to old working directory:
|
||||
@@ -1503,6 +1525,7 @@ cannot change to old working directory: %s; disabling paranoia mode"),
|
||||
dbg_log (_("cannot change current working directory to \"/\": %s"),
|
||||
strerror (errno));
|
||||
paranoia = 0;
|
||||
|
@ -874,8 +864,8 @@ Index: b/nscd/connections.c
|
|||
|
||||
/* Reenable the databases. */
|
||||
time_t now = time (NULL);
|
||||
Index: b/nscd/grpcache.c
|
||||
===================================================================
|
||||
diff --git a/nscd/grpcache.c b/nscd/grpcache.c
|
||||
index d2ad53509db97bdf..a71036512048dd81 100644
|
||||
--- a/nscd/grpcache.c
|
||||
+++ b/nscd/grpcache.c
|
||||
@@ -16,7 +16,6 @@
|
||||
|
@ -894,7 +884,7 @@ Index: b/nscd/grpcache.c
|
|||
|
||||
#include "nscd.h"
|
||||
#include "dbg_log.h"
|
||||
@@ -448,12 +448,12 @@ addgrbyX (struct database_dyn *db, int f
|
||||
@@ -448,12 +448,12 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
look again in the table whether the dataset is now available. We
|
||||
simply insert it. It does not matter if it is in there twice. The
|
||||
pruning function only will look at the timestamp. */
|
||||
|
@ -910,7 +900,7 @@ Index: b/nscd/grpcache.c
|
|||
|
||||
if (__glibc_unlikely (debug_level > 0))
|
||||
{
|
||||
@@ -463,43 +463,24 @@ addgrbyX (struct database_dyn *db, int f
|
||||
@@ -463,43 +463,24 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
dbg_log (_("Reloading \"%s\" in group cache!"), keystr);
|
||||
}
|
||||
|
||||
|
@ -969,8 +959,8 @@ Index: b/nscd/grpcache.c
|
|||
return timeout;
|
||||
}
|
||||
|
||||
Index: b/nscd/hstcache.c
|
||||
===================================================================
|
||||
diff --git a/nscd/hstcache.c b/nscd/hstcache.c
|
||||
index 9f6ce979ac333265..d0af99893dd17b9f 100644
|
||||
--- a/nscd/hstcache.c
|
||||
+++ b/nscd/hstcache.c
|
||||
@@ -34,6 +34,7 @@
|
||||
|
@ -981,7 +971,7 @@ Index: b/nscd/hstcache.c
|
|||
|
||||
#include "nscd.h"
|
||||
#include "dbg_log.h"
|
||||
@@ -463,11 +464,8 @@ addhstbyX (struct database_dyn *db, int
|
||||
@@ -463,11 +464,8 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
look again in the table whether the dataset is now available. We
|
||||
simply insert it. It does not matter if it is in there twice. The
|
||||
pruning function only will look at the timestamp. */
|
||||
|
@ -993,7 +983,7 @@ Index: b/nscd/hstcache.c
|
|||
int errval = 0;
|
||||
int32_t ttl = INT32_MAX;
|
||||
|
||||
@@ -487,46 +485,30 @@ addhstbyX (struct database_dyn *db, int
|
||||
@@ -487,46 +485,30 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str);
|
||||
}
|
||||
|
||||
|
@ -1059,8 +1049,8 @@ Index: b/nscd/hstcache.c
|
|||
return timeout;
|
||||
}
|
||||
|
||||
Index: b/nscd/pwdcache.c
|
||||
===================================================================
|
||||
diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
|
||||
index 721f4c617b0bb74a..9349b54df4241ad5 100644
|
||||
--- a/nscd/pwdcache.c
|
||||
+++ b/nscd/pwdcache.c
|
||||
@@ -16,7 +16,6 @@
|
||||
|
@ -1079,7 +1069,7 @@ Index: b/nscd/pwdcache.c
|
|||
|
||||
#include "nscd.h"
|
||||
#include "dbg_log.h"
|
||||
@@ -426,12 +426,11 @@ addpwbyX (struct database_dyn *db, int f
|
||||
@@ -426,12 +426,11 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
look again in the table whether the dataset is now available. We
|
||||
simply insert it. It does not matter if it is in there twice. The
|
||||
pruning function only will look at the timestamp. */
|
||||
|
@ -1094,7 +1084,7 @@ Index: b/nscd/pwdcache.c
|
|||
|
||||
if (__glibc_unlikely (debug_level > 0))
|
||||
{
|
||||
@@ -441,45 +440,26 @@ addpwbyX (struct database_dyn *db, int f
|
||||
@@ -441,45 +440,26 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
dbg_log (_("Reloading \"%s\" in password cache!"), keystr);
|
||||
}
|
||||
|
||||
|
@ -1155,8 +1145,8 @@ Index: b/nscd/pwdcache.c
|
|||
return timeout;
|
||||
}
|
||||
|
||||
Index: b/nscd/servicescache.c
|
||||
===================================================================
|
||||
diff --git a/nscd/servicescache.c b/nscd/servicescache.c
|
||||
index 131ba6ddcc1a5f7a..549e9a446816d760 100644
|
||||
--- a/nscd/servicescache.c
|
||||
+++ b/nscd/servicescache.c
|
||||
@@ -16,7 +16,6 @@
|
||||
|
@ -1175,7 +1165,7 @@ Index: b/nscd/servicescache.c
|
|||
|
||||
#include "nscd.h"
|
||||
#include "dbg_log.h"
|
||||
@@ -374,12 +374,11 @@ addservbyX (struct database_dyn *db, int
|
||||
@@ -374,12 +374,11 @@ addservbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
look again in the table whether the dataset is now available. We
|
||||
simply insert it. It does not matter if it is in there twice. The
|
||||
pruning function only will look at the timestamp. */
|
||||
|
@ -1190,7 +1180,7 @@ Index: b/nscd/servicescache.c
|
|||
|
||||
if (__glibc_unlikely (debug_level > 0))
|
||||
{
|
||||
@@ -389,43 +388,24 @@ addservbyX (struct database_dyn *db, int
|
||||
@@ -389,43 +388,24 @@ addservbyX (struct database_dyn *db, int fd, request_header *req,
|
||||
dbg_log (_("Reloading \"%s\" in services cache!"), key);
|
||||
}
|
||||
|
||||
|
@ -1249,8 +1239,8 @@ Index: b/nscd/servicescache.c
|
|||
return timeout;
|
||||
}
|
||||
|
||||
Index: b/nss/getent.c
|
||||
===================================================================
|
||||
diff --git a/nss/getent.c b/nss/getent.c
|
||||
index 8f8c3fe80a2cfea6..5654c5f67c4f118c 100644
|
||||
--- a/nss/getent.c
|
||||
+++ b/nss/getent.c
|
||||
@@ -39,6 +39,7 @@
|
||||
|
@ -1303,7 +1293,7 @@ Index: b/nss/getent.c
|
|||
printf ("%-21s", key[i]);
|
||||
for (int j = 0; j < n; ++j)
|
||||
if (grps[j] != -1)
|
||||
@@ -508,6 +513,8 @@ initgroups_keys (int number, char *key[]
|
||||
@@ -508,6 +513,8 @@ initgroups_keys (int number, char *key[])
|
||||
putchar_unlocked ('\n');
|
||||
}
|
||||
|
||||
|
@ -1312,111 +1302,8 @@ Index: b/nss/getent.c
|
|||
return 0;
|
||||
}
|
||||
|
||||
Index: b/nss/nss_files/files-hosts.c
|
||||
===================================================================
|
||||
--- a/nss/nss_files/files-hosts.c
|
||||
+++ b/nss/nss_files/files-hosts.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <arpa/nameser.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv/resolv-internal.h>
|
||||
-
|
||||
+#include <scratch_buffer.h>
|
||||
|
||||
/* Get implementation for some internal functions. */
|
||||
#include "../resolv/mapv4v6addr.h"
|
||||
@@ -145,15 +145,12 @@ _nss_files_gethostbyname3_r (const char
|
||||
&& _res_hconf.flags & HCONF_FLAG_MULTI)
|
||||
{
|
||||
/* We have to get all host entries from the file. */
|
||||
- size_t tmp_buflen = MIN (buflen, 4096);
|
||||
- char tmp_buffer_stack[tmp_buflen]
|
||||
- __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));
|
||||
- char *tmp_buffer = tmp_buffer_stack;
|
||||
struct hostent tmp_result_buf;
|
||||
int naddrs = 1;
|
||||
int naliases = 0;
|
||||
char *bufferend;
|
||||
- bool tmp_buffer_malloced = false;
|
||||
+ struct scratch_buffer tmpbuf;
|
||||
+ scratch_buffer_init (&tmpbuf);
|
||||
|
||||
while (result->h_aliases[naliases] != NULL)
|
||||
++naliases;
|
||||
@@ -161,9 +158,9 @@ _nss_files_gethostbyname3_r (const char
|
||||
bufferend = (char *) &result->h_aliases[naliases + 1];
|
||||
|
||||
again:
|
||||
- while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer,
|
||||
- tmp_buflen, errnop, herrnop, af,
|
||||
- flags))
|
||||
+ while ((status = internal_getent (stream, &tmp_result_buf,
|
||||
+ tmpbuf.data, tmpbuf.length,
|
||||
+ errnop, herrnop, af, flags))
|
||||
== NSS_STATUS_SUCCESS)
|
||||
{
|
||||
int matches = 1;
|
||||
@@ -287,54 +284,13 @@ _nss_files_gethostbyname3_r (const char
|
||||
}
|
||||
}
|
||||
|
||||
- if (status == NSS_STATUS_TRYAGAIN)
|
||||
- {
|
||||
- size_t newsize = 2 * tmp_buflen;
|
||||
- if (tmp_buffer_malloced)
|
||||
- {
|
||||
- char *newp = realloc (tmp_buffer, newsize);
|
||||
- if (newp != NULL)
|
||||
- {
|
||||
- assert ((((uintptr_t) newp)
|
||||
- & (__alignof__ (struct hostent_data) - 1))
|
||||
- == 0);
|
||||
- tmp_buffer = newp;
|
||||
- tmp_buflen = newsize;
|
||||
- goto again;
|
||||
- }
|
||||
- }
|
||||
- else if (!__libc_use_alloca (buflen + newsize))
|
||||
- {
|
||||
- tmp_buffer = malloc (newsize);
|
||||
- if (tmp_buffer != NULL)
|
||||
- {
|
||||
- assert ((((uintptr_t) tmp_buffer)
|
||||
- & (__alignof__ (struct hostent_data) - 1))
|
||||
- == 0);
|
||||
- tmp_buffer_malloced = true;
|
||||
- tmp_buflen = newsize;
|
||||
- goto again;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- tmp_buffer
|
||||
- = extend_alloca (tmp_buffer, tmp_buflen,
|
||||
- newsize
|
||||
- + __alignof__ (struct hostent_data));
|
||||
- tmp_buffer = (char *) (((uintptr_t) tmp_buffer
|
||||
- + __alignof__ (struct hostent_data)
|
||||
- - 1)
|
||||
- & ~(__alignof__ (struct hostent_data)
|
||||
- - 1));
|
||||
- goto again;
|
||||
- }
|
||||
- }
|
||||
+ if (status == NSS_STATUS_TRYAGAIN
|
||||
+ && scratch_buffer_grow (&tmpbuf))
|
||||
+ goto again;
|
||||
else
|
||||
status = NSS_STATUS_SUCCESS;
|
||||
out:
|
||||
- if (tmp_buffer_malloced)
|
||||
- free (tmp_buffer);
|
||||
+ scratch_buffer_free (&tmpbuf);
|
||||
}
|
||||
|
||||
internal_endent (&stream);
|
||||
Index: b/nss/nss_files/files-initgroups.c
|
||||
===================================================================
|
||||
diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c
|
||||
index 27cd8ece40434f5c..8a88f1b62357d3bd 100644
|
||||
--- a/nss/nss_files/files-initgroups.c
|
||||
+++ b/nss/nss_files/files-initgroups.c
|
||||
@@ -16,7 +16,6 @@
|
||||
|
@ -1435,7 +1322,7 @@ Index: b/nss/nss_files/files-initgroups.c
|
|||
|
||||
enum nss_status
|
||||
_nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
@@ -46,9 +46,8 @@ _nss_files_initgroups_dyn (const char *u
|
||||
@@ -46,9 +46,8 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
enum nss_status status = NSS_STATUS_SUCCESS;
|
||||
bool any = false;
|
||||
|
||||
|
@ -1447,7 +1334,7 @@ Index: b/nss/nss_files/files-initgroups.c
|
|||
|
||||
gid_t *groups = *groupsp;
|
||||
|
||||
@@ -67,26 +66,16 @@ _nss_files_initgroups_dyn (const char *u
|
||||
@@ -67,26 +66,16 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
}
|
||||
|
||||
struct group grp;
|
||||
|
@ -1480,7 +1367,7 @@ Index: b/nss/nss_files/files-initgroups.c
|
|||
/* Reread current line, the parser has clobbered it. */
|
||||
fsetpos (stream, &pos);
|
||||
continue;
|
||||
@@ -132,8 +121,7 @@ _nss_files_initgroups_dyn (const char *u
|
||||
@@ -132,8 +121,7 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
|
||||
|
||||
out:
|
||||
/* Free memory. */
|
||||
|
@ -1490,241 +1377,8 @@ Index: b/nss/nss_files/files-initgroups.c
|
|||
free (line);
|
||||
|
||||
fclose (stream);
|
||||
Index: b/posix/glob.c
|
||||
===================================================================
|
||||
--- a/posix/glob.c
|
||||
+++ b/posix/glob.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
+#include <scratch_buffer.h>
|
||||
|
||||
/* Outcomment the following line for production quality code. */
|
||||
/* #define NDEBUG 1 */
|
||||
@@ -293,7 +294,7 @@ glob (const char *pattern, int flags, in
|
||||
glob_t dirs;
|
||||
int retval = 0;
|
||||
#ifdef _LIBC
|
||||
- size_t alloca_used = 0;
|
||||
+ size_t alloca_used = sizeof (struct scratch_buffer);
|
||||
#endif
|
||||
|
||||
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
|
||||
@@ -637,33 +638,13 @@ glob (const char *pattern, int flags, in
|
||||
{
|
||||
struct passwd *p;
|
||||
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
||||
- long int pwbuflen = GETPW_R_SIZE_MAX ();
|
||||
- char *pwtmpbuf;
|
||||
struct passwd pwbuf;
|
||||
- int malloc_pwtmpbuf = 0;
|
||||
int save = errno;
|
||||
+ struct scratch_buffer pwtmpbuf;
|
||||
+ scratch_buffer_init (&pwtmpbuf);
|
||||
|
||||
-# ifndef _LIBC
|
||||
- if (pwbuflen == -1)
|
||||
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
|
||||
- Try a moderate value. */
|
||||
- pwbuflen = 1024;
|
||||
-# endif
|
||||
- if (__libc_use_alloca (alloca_used + pwbuflen))
|
||||
- pwtmpbuf = alloca_account (pwbuflen, alloca_used);
|
||||
- else
|
||||
- {
|
||||
- pwtmpbuf = malloc (pwbuflen);
|
||||
- if (pwtmpbuf == NULL)
|
||||
- {
|
||||
- retval = GLOB_NOSPACE;
|
||||
- goto out;
|
||||
- }
|
||||
- malloc_pwtmpbuf = 1;
|
||||
- }
|
||||
-
|
||||
- while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
|
||||
- != 0)
|
||||
+ while (getpwnam_r (name, &pwbuf,
|
||||
+ pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
|
||||
{
|
||||
if (errno != ERANGE)
|
||||
{
|
||||
@@ -671,67 +652,37 @@ glob (const char *pattern, int flags, in
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!malloc_pwtmpbuf
|
||||
- && __libc_use_alloca (alloca_used
|
||||
- + 2 * pwbuflen))
|
||||
- pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
|
||||
- 2 * pwbuflen,
|
||||
- alloca_used);
|
||||
- else
|
||||
+ if (!scratch_buffer_grow (&pwtmpbuf))
|
||||
{
|
||||
- char *newp = realloc (malloc_pwtmpbuf
|
||||
- ? pwtmpbuf : NULL,
|
||||
- 2 * pwbuflen);
|
||||
- if (newp == NULL)
|
||||
- {
|
||||
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
||||
- free (pwtmpbuf);
|
||||
- retval = GLOB_NOSPACE;
|
||||
- goto out;
|
||||
- }
|
||||
- pwtmpbuf = newp;
|
||||
- pwbuflen = 2 * pwbuflen;
|
||||
- malloc_pwtmpbuf = 1;
|
||||
+ retval = GLOB_NOSPACE;
|
||||
+ goto out;
|
||||
}
|
||||
__set_errno (save);
|
||||
}
|
||||
# else
|
||||
- p = getpwnam (name);
|
||||
+ p = getpwnam (namebuf.data);
|
||||
# endif
|
||||
if (p != NULL)
|
||||
{
|
||||
- if (!malloc_pwtmpbuf)
|
||||
- home_dir = p->pw_dir;
|
||||
- else
|
||||
+ home_dir = strdup (p->pw_dir);
|
||||
+ malloc_home_dir = 1;
|
||||
+ if (home_dir == NULL)
|
||||
{
|
||||
- size_t home_dir_len = strlen (p->pw_dir) + 1;
|
||||
- if (__libc_use_alloca (alloca_used + home_dir_len))
|
||||
- home_dir = alloca_account (home_dir_len,
|
||||
- alloca_used);
|
||||
- else
|
||||
- {
|
||||
- home_dir = malloc (home_dir_len);
|
||||
- if (home_dir == NULL)
|
||||
- {
|
||||
- free (pwtmpbuf);
|
||||
- retval = GLOB_NOSPACE;
|
||||
- goto out;
|
||||
- }
|
||||
- malloc_home_dir = 1;
|
||||
- }
|
||||
- memcpy (home_dir, p->pw_dir, home_dir_len);
|
||||
-
|
||||
- free (pwtmpbuf);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
+ retval = GLOB_NOSPACE;
|
||||
+ goto out;
|
||||
}
|
||||
}
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
}
|
||||
}
|
||||
if (home_dir == NULL || home_dir[0] == '\0')
|
||||
{
|
||||
+ if (malloc_home_dir)
|
||||
+ free (home_dir);
|
||||
+ malloc_home_dir = 0;
|
||||
if (flags & GLOB_TILDE_CHECK)
|
||||
{
|
||||
- if (__glibc_unlikely (malloc_home_dir))
|
||||
- free (home_dir);
|
||||
retval = GLOB_NOMATCH;
|
||||
goto out;
|
||||
}
|
||||
@@ -852,57 +803,24 @@ glob (const char *pattern, int flags, in
|
||||
{
|
||||
struct passwd *p;
|
||||
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
||||
- long int buflen = GETPW_R_SIZE_MAX ();
|
||||
- char *pwtmpbuf;
|
||||
- int malloc_pwtmpbuf = 0;
|
||||
struct passwd pwbuf;
|
||||
int save = errno;
|
||||
+ struct scratch_buffer pwtmpbuf;
|
||||
+ scratch_buffer_init (&pwtmpbuf);
|
||||
|
||||
-# ifndef _LIBC
|
||||
- if (buflen == -1)
|
||||
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
|
||||
- moderate value. */
|
||||
- buflen = 1024;
|
||||
-# endif
|
||||
- if (__libc_use_alloca (alloca_used + buflen))
|
||||
- pwtmpbuf = alloca_account (buflen, alloca_used);
|
||||
- else
|
||||
- {
|
||||
- pwtmpbuf = malloc (buflen);
|
||||
- if (pwtmpbuf == NULL)
|
||||
- {
|
||||
- nomem_getpw:
|
||||
- if (__glibc_unlikely (malloc_user_name))
|
||||
- free (user_name);
|
||||
- retval = GLOB_NOSPACE;
|
||||
- goto out;
|
||||
- }
|
||||
- malloc_pwtmpbuf = 1;
|
||||
- }
|
||||
-
|
||||
- while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
|
||||
+ while (getpwnam_r (user_name, &pwbuf,
|
||||
+ pwtmpbuf.data, pwtmpbuf.length, &p) != 0)
|
||||
{
|
||||
if (errno != ERANGE)
|
||||
{
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
- if (!malloc_pwtmpbuf
|
||||
- && __libc_use_alloca (alloca_used + 2 * buflen))
|
||||
- pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
|
||||
- 2 * buflen, alloca_used);
|
||||
- else
|
||||
+
|
||||
+ if (!scratch_buffer_grow (&pwtmpbuf))
|
||||
{
|
||||
- char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
|
||||
- 2 * buflen);
|
||||
- if (newp == NULL)
|
||||
- {
|
||||
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
||||
- free (pwtmpbuf);
|
||||
- goto nomem_getpw;
|
||||
- }
|
||||
- pwtmpbuf = newp;
|
||||
- malloc_pwtmpbuf = 1;
|
||||
+ retval = GLOB_NOSPACE;
|
||||
+ goto out;
|
||||
}
|
||||
__set_errno (save);
|
||||
}
|
||||
@@ -931,8 +849,7 @@ glob (const char *pattern, int flags, in
|
||||
dirname = malloc (home_len + rest_len + 1);
|
||||
if (dirname == NULL)
|
||||
{
|
||||
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
||||
- free (pwtmpbuf);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
retval = GLOB_NOSPACE;
|
||||
goto out;
|
||||
}
|
||||
@@ -944,13 +861,11 @@ glob (const char *pattern, int flags, in
|
||||
dirlen = home_len + rest_len;
|
||||
dirname_modified = 1;
|
||||
|
||||
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
||||
- free (pwtmpbuf);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
||||
- free (pwtmpbuf);
|
||||
+ scratch_buffer_free (&pwtmpbuf);
|
||||
|
||||
if (flags & GLOB_TILDE_CHECK)
|
||||
/* We have to regard it as an error if we cannot find the
|
||||
Index: b/posix/wordexp.c
|
||||
===================================================================
|
||||
diff --git a/posix/wordexp.c b/posix/wordexp.c
|
||||
index ba3f3ed4b66a6507..c4a6a209f416a9fb 100644
|
||||
--- a/posix/wordexp.c
|
||||
+++ b/posix/wordexp.c
|
||||
@@ -17,7 +17,6 @@
|
||||
|
@ -1743,7 +1397,7 @@ Index: b/posix/wordexp.c
|
|||
|
||||
#include <libc-lock.h>
|
||||
#include <_itoa.h>
|
||||
@@ -308,12 +308,7 @@ parse_tilde (char **word, size_t *word_l
|
||||
@@ -308,12 +308,7 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
|
||||
if (i == 1 + *offset)
|
||||
{
|
||||
/* Tilde appears on its own */
|
||||
|
@ -1756,7 +1410,7 @@ Index: b/posix/wordexp.c
|
|||
|
||||
/* POSIX.2 says ~ expands to $HOME and if HOME is unset the
|
||||
results are unspecified. We do a lookup on the uid if
|
||||
@@ -328,25 +323,38 @@ parse_tilde (char **word, size_t *word_l
|
||||
@@ -328,25 +323,38 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1802,7 +1456,7 @@ Index: b/posix/wordexp.c
|
|||
}
|
||||
}
|
||||
else
|
||||
@@ -354,13 +362,15 @@ parse_tilde (char **word, size_t *word_l
|
||||
@@ -354,13 +362,15 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
|
||||
/* Look up user name in database to get home directory */
|
||||
char *user = strndupa (&words[1 + *offset], i - (1 + *offset));
|
||||
struct passwd pwd, *tpwd;
|
||||
|
@ -1822,7 +1476,7 @@ Index: b/posix/wordexp.c
|
|||
|
||||
if (result == 0 && tpwd != NULL && pwd.pw_dir)
|
||||
*word = w_addstr (*word, word_length, max_length, pwd.pw_dir);
|
||||
@@ -372,6 +382,8 @@ parse_tilde (char **word, size_t *word_l
|
||||
@@ -372,6 +382,8 @@ parse_tilde (char **word, size_t *word_length, size_t *max_length,
|
||||
*word = w_addstr (*word, word_length, max_length, user);
|
||||
}
|
||||
|
||||
|
@ -1831,8 +1485,8 @@ Index: b/posix/wordexp.c
|
|||
*offset = i - 1;
|
||||
}
|
||||
return *word ? 0 : WRDE_NOSPACE;
|
||||
Index: b/sysdeps/unix/sysv/linux/gethostid.c
|
||||
===================================================================
|
||||
diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c
|
||||
index cc108aa2d64b616a..3529cf6fe509cfd1 100644
|
||||
--- a/sysdeps/unix/sysv/linux/gethostid.c
|
||||
+++ b/sysdeps/unix/sysv/linux/gethostid.c
|
||||
@@ -63,13 +63,12 @@ sethostid (long int id)
|
||||
|
@ -1885,8 +1539,8 @@ Index: b/sysdeps/unix/sysv/linux/gethostid.c
|
|||
/* For the return value to be not exactly the IP address we do some
|
||||
bit fiddling. */
|
||||
return (int32_t) (in.s_addr << 16 | in.s_addr >> 16);
|
||||
Index: b/sysdeps/unix/sysv/linux/getlogin_r.c
|
||||
===================================================================
|
||||
diff --git a/sysdeps/unix/sysv/linux/getlogin_r.c b/sysdeps/unix/sysv/linux/getlogin_r.c
|
||||
index 05ac36b49186b29e..37a9255e03657728 100644
|
||||
--- a/sysdeps/unix/sysv/linux/getlogin_r.c
|
||||
+++ b/sysdeps/unix/sysv/linux/getlogin_r.c
|
||||
@@ -18,6 +18,7 @@
|
||||
|
@ -1897,7 +1551,7 @@ Index: b/sysdeps/unix/sysv/linux/getlogin_r.c
|
|||
|
||||
#define STATIC static
|
||||
static int getlogin_r_fd0 (char *name, size_t namesize);
|
||||
@@ -54,28 +55,19 @@ __getlogin_r_loginuid (char *name, size_
|
||||
@@ -54,28 +55,19 @@ __getlogin_r_loginuid (char *name, size_t namesize)
|
||||
endp == uidbuf || *endp != '\0'))
|
||||
return -1;
|
||||
|
||||
|
@ -1933,7 +1587,7 @@ Index: b/sysdeps/unix/sysv/linux/getlogin_r.c
|
|||
}
|
||||
|
||||
if (res != 0 || tpwd == NULL)
|
||||
@@ -95,9 +87,7 @@ __getlogin_r_loginuid (char *name, size_
|
||||
@@ -95,9 +87,7 @@ __getlogin_r_loginuid (char *name, size_t namesize)
|
||||
memcpy (name, pwd.pw_name, needed);
|
||||
|
||||
out:
|
||||
|
|
|
@ -0,0 +1,440 @@
|
|||
commit 799c8d6905433ad56f26ccab4855b36f1d1ddbfc
|
||||
Author: Mike FABIAN <mfabian@redhat.com>
|
||||
Date: Thu Sep 7 15:28:28 2017 +0200
|
||||
|
||||
Add new codepage charmaps/IBM858 [BZ #21084]
|
||||
|
||||
This code page is identical to code page 850 except that X'D5'
|
||||
has been changed from LI61 (dotless i) to SC20 (euro symbol).
|
||||
|
||||
The code points from /x01 to /x1f in the /localedata/charmaps/IBM858
|
||||
file have the same mapping as those in localedata/charmaps/ANSI_X3.4-1968.
|
||||
That means they disagree with with
|
||||
|
||||
ftp://ftp.software.ibm.com/software/globalization/gcoc/attachments/CP00858.txt
|
||||
|
||||
in that range.
|
||||
For example, localedata/charmaps/IBM858 and localedata/charmaps/ANSI_X3.4-1968 have:
|
||||
|
||||
“<U0001> /x01 START OF HEADING (SOH)”
|
||||
|
||||
whereas CP00858.txt has:
|
||||
|
||||
“01 SS000000 Smiling Face”
|
||||
|
||||
That means that CP00858.txt is not really ASCII-compatible and to make
|
||||
it ASCII-compatible we deviate fro CP00858.txt in the code points from /x01
|
||||
to /x1f.
|
||||
|
||||
[BZ #21084]
|
||||
* benchtests/strcoll-inputs/filelist#en_US.UTF-8: Add IBM858 and ibm858.c.
|
||||
* iconvdata/Makefile: Add IBM858.
|
||||
* iconvdata/gconv-modules: Add IBM858.
|
||||
* iconvdata/ibm858.c: New file.
|
||||
* iconvdata/tst-tables.sh: Add IBM858
|
||||
* localedata/charmaps/IBM858: New file.
|
||||
|
||||
diff --git a/benchtests/strcoll-inputs/filelist#en_US.UTF-8 b/benchtests/strcoll-inputs/filelist#en_US.UTF-8
|
||||
index b7b38017d836aee8..4fd74821feb0f22b 100644
|
||||
--- a/benchtests/strcoll-inputs/filelist#en_US.UTF-8
|
||||
+++ b/benchtests/strcoll-inputs/filelist#en_US.UTF-8
|
||||
@@ -11233,6 +11233,7 @@ ISO-8859-9E
|
||||
UTF-8
|
||||
ISO-8859-2
|
||||
IBM850
|
||||
+IBM858
|
||||
EUC-TW
|
||||
KOI8-U
|
||||
IBM903
|
||||
@@ -13922,6 +13923,7 @@ ibm12712.c
|
||||
ibm1145.h
|
||||
ibm932.c
|
||||
ibm850.c
|
||||
+ibm858.c
|
||||
ibm437.c
|
||||
ibm1399.c
|
||||
stdio-common
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index e4845871f559b406..6975b46fbba422bd 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -36,9 +36,9 @@ modules := ISO8859-1 ISO8859-2 ISO8859-3 ISO8859-4 ISO8859-5 \
|
||||
IBM874 CP737 CP775 ISO-2022-KR HP-TURKISH8 HP-THAI8 HP-GREEK8 \
|
||||
KOI8-R LATIN-GREEK LATIN-GREEK-1 IBM256 IBM273 IBM277 IBM278 \
|
||||
IBM280 IBM281 IBM284 IBM285 IBM290 IBM297 IBM420 IBM424 \
|
||||
- IBM437 IBM850 IBM851 IBM852 IBM855 IBM857 IBM860 IBM861 \
|
||||
- IBM862 IBM863 IBM864 IBM865 IBM868 IBM869 IBM875 IBM880 \
|
||||
- IBM866 CP1258 IBM922 IBM1124 IBM1129 IBM932 IBM943 \
|
||||
+ IBM437 IBM850 IBM851 IBM852 IBM855 IBM857 IBM858 IBM860 \
|
||||
+ IBM861 IBM862 IBM863 IBM864 IBM865 IBM868 IBM869 IBM875 \
|
||||
+ IBM880 IBM866 CP1258 IBM922 IBM1124 IBM1129 IBM932 IBM943 \
|
||||
IBM856 IBM930 IBM933 IBM935 IBM937 IBM939 IBM1046 \
|
||||
IBM1132 IBM1133 IBM1160 IBM1161 IBM1162 IBM1163 IBM1164 \
|
||||
IBM918 IBM1004 IBM1026 CP1125 CP1250 CP1251 CP1252 CP1253 \
|
||||
@@ -153,11 +153,11 @@ gen-8bit-modules := iso8859-2 iso8859-3 iso8859-4 iso8859-6 iso8859-9 koi-8 \
|
||||
gen-8bit-gap-modules := koi8-r latin-greek latin-greek-1 ibm256 ibm273 \
|
||||
ibm277 ibm278 ibm280 ibm281 ibm284 ibm285 ibm290 \
|
||||
ibm297 ibm420 ibm424 ibm437 ibm850 ibm851 ibm852 \
|
||||
- ibm855 ibm857 ibm860 ibm861 ibm862 ibm863 ibm864 \
|
||||
- ibm865 ibm868 ibm869 ibm875 ibm880 ibm918 ibm1004 \
|
||||
- ibm1026 cp1125 cp1250 cp1251 cp1252 cp1253 cp1254 \
|
||||
- cp1256 cp1257 ibm866 iso8859-5 iso8859-7 iso8859-8 \
|
||||
- iso8859-10 macintosh iec_p27-1 asmo_449 \
|
||||
+ ibm855 ibm857 ibm858 ibm860 ibm861 ibm862 ibm863 \
|
||||
+ ibm864 ibm865 ibm868 ibm869 ibm875 ibm880 ibm918 \
|
||||
+ ibm1004 ibm1026 cp1125 cp1250 cp1251 cp1252 cp1253 \
|
||||
+ cp1254 cp1256 cp1257 ibm866 iso8859-5 iso8859-7 \
|
||||
+ iso8859-8 iso8859-10 macintosh iec_p27-1 asmo_449 \
|
||||
csn_369103 cwi dec-mcs ecma-cyrillic gost_19768-74 \
|
||||
greek-ccitt greek7 greek7-old inis inis-8 \
|
||||
inis-cyrillic iso_2033 iso_5427 iso_5427-ext \
|
||||
diff --git a/iconvdata/gconv-modules b/iconvdata/gconv-modules
|
||||
index e959f16ad9b6dd3c..7d988c8ad9972858 100644
|
||||
--- a/iconvdata/gconv-modules
|
||||
+++ b/iconvdata/gconv-modules
|
||||
@@ -744,6 +744,13 @@ module IBM850// INTERNAL IBM850 1
|
||||
module INTERNAL IBM850// IBM850 1
|
||||
|
||||
# from to module cost
|
||||
+alias CP858// IBM858//
|
||||
+alias 858// IBM858//
|
||||
+alias CSPC858MULTILINGUAL// IBM858//
|
||||
+module IBM858// INTERNAL IBM858 1
|
||||
+module INTERNAL IBM858// IBM858 1
|
||||
+
|
||||
+# from to module cost
|
||||
alias CP851// IBM851//
|
||||
alias 851// IBM851//
|
||||
alias CSIBM851// IBM851//
|
||||
diff --git a/iconvdata/ibm858.c b/iconvdata/ibm858.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..ed2a48e3cf79e2b9
|
||||
--- /dev/null
|
||||
+++ b/iconvdata/ibm858.c
|
||||
@@ -0,0 +1,27 @@
|
||||
+/* Conversion from and to IBM858.
|
||||
+ Copyright (C) 2017 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 <stdint.h>
|
||||
+
|
||||
+/* Get the conversion table. */
|
||||
+#define TABLES <ibm858.h>
|
||||
+
|
||||
+#define CHARSET_NAME "IBM858//"
|
||||
+#define HAS_HOLES 1 /* Not all 256 character are defined. */
|
||||
+
|
||||
+#include <8bit-gap.c>
|
||||
diff --git a/iconvdata/tst-tables.sh b/iconvdata/tst-tables.sh
|
||||
index a027f5df5b27b904..77338f05149ccb98 100755
|
||||
--- a/iconvdata/tst-tables.sh
|
||||
+++ b/iconvdata/tst-tables.sh
|
||||
@@ -125,6 +125,7 @@ cat <<EOF |
|
||||
IBM855
|
||||
IBM856
|
||||
IBM857
|
||||
+ IBM858
|
||||
IBM860
|
||||
IBM861
|
||||
IBM862
|
||||
diff --git a/localedata/charmaps/IBM858 b/localedata/charmaps/IBM858
|
||||
new file mode 100644
|
||||
index 0000000000000000..d8600e2456c87b48
|
||||
--- /dev/null
|
||||
+++ b/localedata/charmaps/IBM858
|
||||
@@ -0,0 +1,281 @@
|
||||
+<code_set_name> IBM858
|
||||
+<comment_char> %
|
||||
+<escape_char> /
|
||||
+% version: 1.0
|
||||
+% source: ftp://ftp.software.ibm.com/software/globalization/gcoc/attachments/CP00858.txt, 1998
|
||||
+
|
||||
+% source: UNICODE 1.0
|
||||
+
|
||||
+% This code page is identical to code page 850 except that X'D5'
|
||||
+% has been changed from LI61 (dotless i) to SC20 (euro symbol).
|
||||
+
|
||||
+% The code points from /x01 to /x1f in this file have the same mapping
|
||||
+% as those in ANSI_X3.4-1968. That means they disagree with with CP00858.txt
|
||||
+% in that range. For example, this file and ANSI_X3.4-1968 have:
|
||||
+% “<U0001> /x01 START OF HEADING (SOH)”
|
||||
+% whereas CP00858.txt has:
|
||||
+% “01 SS000000 Smiling Face”
|
||||
+% That means that CP00858.txt is not really ASCII-compatible and to make
|
||||
+% it ASCII-compatible we deviate fro CP00858.txt in the code points from /x01
|
||||
+% to /x1f.
|
||||
+
|
||||
+% alias CP858
|
||||
+% alias 858
|
||||
+CHARMAP
|
||||
+<U0000> /x00 NULL (NUL)
|
||||
+<U0001> /x01 START OF HEADING (SOH)
|
||||
+<U0002> /x02 START OF TEXT (STX)
|
||||
+<U0003> /x03 END OF TEXT (ETX)
|
||||
+<U0004> /x04 END OF TRANSMISSION (EOT)
|
||||
+<U0005> /x05 ENQUIRY (ENQ)
|
||||
+<U0006> /x06 ACKNOWLEDGE (ACK)
|
||||
+<U0007> /x07 BELL (BEL)
|
||||
+<U0008> /x08 BACKSPACE (BS)
|
||||
+<U0009> /x09 CHARACTER TABULATION (HT)
|
||||
+<U000A> /x0a LINE FEED (LF)
|
||||
+<U000B> /x0b LINE TABULATION (VT)
|
||||
+<U000C> /x0c FORM FEED (FF)
|
||||
+<U000D> /x0d CARRIAGE RETURN (CR)
|
||||
+<U000E> /x0e SHIFT OUT (SO)
|
||||
+<U000F> /x0f SHIFT IN (SI)
|
||||
+<U0010> /x10 DATALINK ESCAPE (DLE)
|
||||
+<U0011> /x11 DEVICE CONTROL ONE (DC1)
|
||||
+<U0012> /x12 DEVICE CONTROL TWO (DC2)
|
||||
+<U0013> /x13 DEVICE CONTROL THREE (DC3)
|
||||
+<U0014> /x14 DEVICE CONTROL FOUR (DC4)
|
||||
+<U0015> /x15 NEGATIVE ACKNOWLEDGE (NAK)
|
||||
+<U0016> /x16 SYNCHRONOUS IDLE (SYN)
|
||||
+<U0017> /x17 END OF TRANSMISSION BLOCK (ETB)
|
||||
+<U0018> /x18 CANCEL (CAN)
|
||||
+<U0019> /x19 END OF MEDIUM (EM)
|
||||
+<U001A> /x1a SUBSTITUTE (SUB)
|
||||
+<U001B> /x1b ESCAPE (ESC)
|
||||
+<U001C> /x1c FILE SEPARATOR (IS4)
|
||||
+<U001D> /x1d GROUP SEPARATOR (IS3)
|
||||
+<U001E> /x1e RECORD SEPARATOR (IS2)
|
||||
+<U001F> /x1f UNIT SEPARATOR (IS1)
|
||||
+<U0020> /x20 SPACE
|
||||
+<U0021> /x21 EXCLAMATION MARK
|
||||
+<U0022> /x22 QUOTATION MARK
|
||||
+<U0023> /x23 NUMBER SIGN
|
||||
+<U0024> /x24 DOLLAR SIGN
|
||||
+<U0025> /x25 PERCENT SIGN
|
||||
+<U0026> /x26 AMPERSAND
|
||||
+<U0027> /x27 APOSTROPHE
|
||||
+<U0028> /x28 LEFT PARENTHESIS
|
||||
+<U0029> /x29 RIGHT PARENTHESIS
|
||||
+<U002A> /x2a ASTERISK
|
||||
+<U002B> /x2b PLUS SIGN
|
||||
+<U002C> /x2c COMMA
|
||||
+<U002D> /x2d HYPHEN-MINUS
|
||||
+<U002E> /x2e FULL STOP
|
||||
+<U002F> /x2f SOLIDUS
|
||||
+<U0030> /x30 DIGIT ZERO
|
||||
+<U0031> /x31 DIGIT ONE
|
||||
+<U0032> /x32 DIGIT TWO
|
||||
+<U0033> /x33 DIGIT THREE
|
||||
+<U0034> /x34 DIGIT FOUR
|
||||
+<U0035> /x35 DIGIT FIVE
|
||||
+<U0036> /x36 DIGIT SIX
|
||||
+<U0037> /x37 DIGIT SEVEN
|
||||
+<U0038> /x38 DIGIT EIGHT
|
||||
+<U0039> /x39 DIGIT NINE
|
||||
+<U003A> /x3a COLON
|
||||
+<U003B> /x3b SEMICOLON
|
||||
+<U003C> /x3c LESS-THAN SIGN
|
||||
+<U003D> /x3d EQUALS SIGN
|
||||
+<U003E> /x3e GREATER-THAN SIGN
|
||||
+<U003F> /x3f QUESTION MARK
|
||||
+<U0040> /x40 COMMERCIAL AT
|
||||
+<U0041> /x41 LATIN CAPITAL LETTER A
|
||||
+<U0042> /x42 LATIN CAPITAL LETTER B
|
||||
+<U0043> /x43 LATIN CAPITAL LETTER C
|
||||
+<U0044> /x44 LATIN CAPITAL LETTER D
|
||||
+<U0045> /x45 LATIN CAPITAL LETTER E
|
||||
+<U0046> /x46 LATIN CAPITAL LETTER F
|
||||
+<U0047> /x47 LATIN CAPITAL LETTER G
|
||||
+<U0048> /x48 LATIN CAPITAL LETTER H
|
||||
+<U0049> /x49 LATIN CAPITAL LETTER I
|
||||
+<U004A> /x4a LATIN CAPITAL LETTER J
|
||||
+<U004B> /x4b LATIN CAPITAL LETTER K
|
||||
+<U004C> /x4c LATIN CAPITAL LETTER L
|
||||
+<U004D> /x4d LATIN CAPITAL LETTER M
|
||||
+<U004E> /x4e LATIN CAPITAL LETTER N
|
||||
+<U004F> /x4f LATIN CAPITAL LETTER O
|
||||
+<U0050> /x50 LATIN CAPITAL LETTER P
|
||||
+<U0051> /x51 LATIN CAPITAL LETTER Q
|
||||
+<U0052> /x52 LATIN CAPITAL LETTER R
|
||||
+<U0053> /x53 LATIN CAPITAL LETTER S
|
||||
+<U0054> /x54 LATIN CAPITAL LETTER T
|
||||
+<U0055> /x55 LATIN CAPITAL LETTER U
|
||||
+<U0056> /x56 LATIN CAPITAL LETTER V
|
||||
+<U0057> /x57 LATIN CAPITAL LETTER W
|
||||
+<U0058> /x58 LATIN CAPITAL LETTER X
|
||||
+<U0059> /x59 LATIN CAPITAL LETTER Y
|
||||
+<U005A> /x5a LATIN CAPITAL LETTER Z
|
||||
+<U005B> /x5b LEFT SQUARE BRACKET
|
||||
+<U005C> /x5c REVERSE SOLIDUS
|
||||
+<U005D> /x5d RIGHT SQUARE BRACKET
|
||||
+<U005E> /x5e CIRCUMFLEX ACCENT
|
||||
+<U005F> /x5f LOW LINE
|
||||
+<U0060> /x60 GRAVE ACCENT
|
||||
+<U0061> /x61 LATIN SMALL LETTER A
|
||||
+<U0062> /x62 LATIN SMALL LETTER B
|
||||
+<U0063> /x63 LATIN SMALL LETTER C
|
||||
+<U0064> /x64 LATIN SMALL LETTER D
|
||||
+<U0065> /x65 LATIN SMALL LETTER E
|
||||
+<U0066> /x66 LATIN SMALL LETTER F
|
||||
+<U0067> /x67 LATIN SMALL LETTER G
|
||||
+<U0068> /x68 LATIN SMALL LETTER H
|
||||
+<U0069> /x69 LATIN SMALL LETTER I
|
||||
+<U006A> /x6a LATIN SMALL LETTER J
|
||||
+<U006B> /x6b LATIN SMALL LETTER K
|
||||
+<U006C> /x6c LATIN SMALL LETTER L
|
||||
+<U006D> /x6d LATIN SMALL LETTER M
|
||||
+<U006E> /x6e LATIN SMALL LETTER N
|
||||
+<U006F> /x6f LATIN SMALL LETTER O
|
||||
+<U0070> /x70 LATIN SMALL LETTER P
|
||||
+<U0071> /x71 LATIN SMALL LETTER Q
|
||||
+<U0072> /x72 LATIN SMALL LETTER R
|
||||
+<U0073> /x73 LATIN SMALL LETTER S
|
||||
+<U0074> /x74 LATIN SMALL LETTER T
|
||||
+<U0075> /x75 LATIN SMALL LETTER U
|
||||
+<U0076> /x76 LATIN SMALL LETTER V
|
||||
+<U0077> /x77 LATIN SMALL LETTER W
|
||||
+<U0078> /x78 LATIN SMALL LETTER X
|
||||
+<U0079> /x79 LATIN SMALL LETTER Y
|
||||
+<U007A> /x7a LATIN SMALL LETTER Z
|
||||
+<U007B> /x7b LEFT CURLY BRACKET
|
||||
+<U007C> /x7c VERTICAL LINE
|
||||
+<U007D> /x7d RIGHT CURLY BRACKET
|
||||
+<U007E> /x7e TILDE
|
||||
+<U007F> /x7f DELETE (DEL)
|
||||
+<U00C7> /x80 LATIN CAPITAL LETTER C WITH CEDILLA
|
||||
+<U00FC> /x81 LATIN SMALL LETTER U WITH DIAERESIS
|
||||
+<U00E9> /x82 LATIN SMALL LETTER E WITH ACUTE
|
||||
+<U00E2> /x83 LATIN SMALL LETTER A WITH CIRCUMFLEX
|
||||
+<U00E4> /x84 LATIN SMALL LETTER A WITH DIAERESIS
|
||||
+<U00E0> /x85 LATIN SMALL LETTER A WITH GRAVE
|
||||
+<U00E5> /x86 LATIN SMALL LETTER A WITH RING ABOVE
|
||||
+<U00E7> /x87 LATIN SMALL LETTER C WITH CEDILLA
|
||||
+<U00EA> /x88 LATIN SMALL LETTER E WITH CIRCUMFLEX
|
||||
+<U00EB> /x89 LATIN SMALL LETTER E WITH DIAERESIS
|
||||
+<U00E8> /x8a LATIN SMALL LETTER E WITH GRAVE
|
||||
+<U00EF> /x8b LATIN SMALL LETTER I WITH DIAERESIS
|
||||
+<U00EE> /x8c LATIN SMALL LETTER I WITH CIRCUMFLEX
|
||||
+<U00EC> /x8d LATIN SMALL LETTER I WITH GRAVE
|
||||
+<U00C4> /x8e LATIN CAPITAL LETTER A WITH DIAERESIS
|
||||
+<U00C5> /x8f LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||
+<U00C9> /x90 LATIN CAPITAL LETTER E WITH ACUTE
|
||||
+<U00E6> /x91 LATIN SMALL LETTER AE
|
||||
+<U00C6> /x92 LATIN CAPITAL LETTER AE
|
||||
+<U00F4> /x93 LATIN SMALL LETTER O WITH CIRCUMFLEX
|
||||
+<U00F6> /x94 LATIN SMALL LETTER O WITH DIAERESIS
|
||||
+<U00F2> /x95 LATIN SMALL LETTER O WITH GRAVE
|
||||
+<U00FB> /x96 LATIN SMALL LETTER U WITH CIRCUMFLEX
|
||||
+<U00F9> /x97 LATIN SMALL LETTER U WITH GRAVE
|
||||
+<U00FF> /x98 LATIN SMALL LETTER Y WITH DIAERESIS
|
||||
+<U00D6> /x99 LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||
+<U00DC> /x9a LATIN CAPITAL LETTER U WITH DIAERESIS
|
||||
+<U00F8> /x9b LATIN SMALL LETTER O WITH STROKE
|
||||
+<U00A3> /x9c POUND SIGN
|
||||
+<U00D8> /x9d LATIN CAPITAL LETTER O WITH STROKE
|
||||
+<U00D7> /x9e MULTIPLICATION SIGN
|
||||
+<U0192> /x9f LATIN SMALL LETTER F WITH HOOK
|
||||
+<U00E1> /xa0 LATIN SMALL LETTER A WITH ACUTE
|
||||
+<U00ED> /xa1 LATIN SMALL LETTER I WITH ACUTE
|
||||
+<U00F3> /xa2 LATIN SMALL LETTER O WITH ACUTE
|
||||
+<U00FA> /xa3 LATIN SMALL LETTER U WITH ACUTE
|
||||
+<U00F1> /xa4 LATIN SMALL LETTER N WITH TILDE
|
||||
+<U00D1> /xa5 LATIN CAPITAL LETTER N WITH TILDE
|
||||
+<U00AA> /xa6 FEMININE ORDINAL INDICATOR
|
||||
+<U00BA> /xa7 MASCULINE ORDINAL INDICATOR
|
||||
+<U00BF> /xa8 INVERTED QUESTION MARK
|
||||
+<U00AE> /xa9 REGISTERED SIGN
|
||||
+<U00AC> /xaa NOT SIGN
|
||||
+<U00BD> /xab VULGAR FRACTION ONE HALF
|
||||
+<U00BC> /xac VULGAR FRACTION ONE QUARTER
|
||||
+<U00A1> /xad INVERTED EXCLAMATION MARK
|
||||
+<U00AB> /xae LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||
+<U00BB> /xaf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||
+<U2591> /xb0 LIGHT SHADE
|
||||
+<U2592> /xb1 MEDIUM SHADE
|
||||
+<U2593> /xb2 DARK SHADE
|
||||
+<U2502> /xb3 BOX DRAWINGS LIGHT VERTICAL
|
||||
+<U2524> /xb4 BOX DRAWINGS LIGHT VERTICAL AND LEFT
|
||||
+<U00C1> /xb5 LATIN CAPITAL LETTER A WITH ACUTE
|
||||
+<U00C2> /xb6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
|
||||
+<U00C0> /xb7 LATIN CAPITAL LETTER A WITH GRAVE
|
||||
+<U00A9> /xb8 COPYRIGHT SIGN
|
||||
+<U2563> /xb9 BOX DRAWINGS DOUBLE VERTICAL AND LEFT
|
||||
+<U2551> /xba BOX DRAWINGS DOUBLE VERTICAL
|
||||
+<U2557> /xbb BOX DRAWINGS DOUBLE DOWN AND LEFT
|
||||
+<U255D> /xbc BOX DRAWINGS DOUBLE UP AND LEFT
|
||||
+<U00A2> /xbd CENT SIGN
|
||||
+<U00A5> /xbe YEN SIGN
|
||||
+<U2510> /xbf BOX DRAWINGS LIGHT DOWN AND LEFT
|
||||
+<U2514> /xc0 BOX DRAWINGS LIGHT UP AND RIGHT
|
||||
+<U2534> /xc1 BOX DRAWINGS LIGHT UP AND HORIZONTAL
|
||||
+<U252C> /xc2 BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
|
||||
+<U251C> /xc3 BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||
+<U2500> /xc4 BOX DRAWINGS LIGHT HORIZONTAL
|
||||
+<U253C> /xc5 BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
|
||||
+<U00E3> /xc6 LATIN SMALL LETTER A WITH TILDE
|
||||
+<U00C3> /xc7 LATIN CAPITAL LETTER A WITH TILDE
|
||||
+<U255A> /xc8 BOX DRAWINGS DOUBLE UP AND RIGHT
|
||||
+<U2554> /xc9 BOX DRAWINGS DOUBLE DOWN AND RIGHT
|
||||
+<U2569> /xca BOX DRAWINGS DOUBLE UP AND HORIZONTAL
|
||||
+<U2566> /xcb BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
|
||||
+<U2560> /xcc BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
|
||||
+<U2550> /xcd BOX DRAWINGS DOUBLE HORIZONTAL
|
||||
+<U256C> /xce BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
|
||||
+<U00A4> /xcf CURRENCY SIGN
|
||||
+<U00F0> /xd0 LATIN SMALL LETTER ETH (Icelandic)
|
||||
+<U00D0> /xd1 LATIN CAPITAL LETTER ETH (Icelandic)
|
||||
+<U00CA> /xd2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX
|
||||
+<U00CB> /xd3 LATIN CAPITAL LETTER E WITH DIAERESIS
|
||||
+<U00C8> /xd4 LATIN CAPITAL LETTER E WITH GRAVE
|
||||
+<U20AC> /xd5 EURO SIGN
|
||||
+<U00CD> /xd6 LATIN CAPITAL LETTER I WITH ACUTE
|
||||
+<U00CE> /xd7 LATIN CAPITAL LETTER I WITH CIRCUMFLEX
|
||||
+<U00CF> /xd8 LATIN CAPITAL LETTER I WITH DIAERESIS
|
||||
+<U2518> /xd9 BOX DRAWINGS LIGHT UP AND LEFT
|
||||
+<U250C> /xda BOX DRAWINGS LIGHT DOWN AND RIGHT
|
||||
+<U2588> /xdb FULL BLOCK
|
||||
+<U2584> /xdc LOWER HALF BLOCK
|
||||
+<U00A6> /xdd BROKEN BAR
|
||||
+<U00CC> /xde LATIN CAPITAL LETTER I WITH GRAVE
|
||||
+<U2580> /xdf UPPER HALF BLOCK
|
||||
+<U00D3> /xe0 LATIN CAPITAL LETTER O WITH ACUTE
|
||||
+<U00DF> /xe1 LATIN SMALL LETTER SHARP S (German)
|
||||
+<U00D4> /xe2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX
|
||||
+<U00D2> /xe3 LATIN CAPITAL LETTER O WITH GRAVE
|
||||
+<U00F5> /xe4 LATIN SMALL LETTER O WITH TILDE
|
||||
+<U00D5> /xe5 LATIN CAPITAL LETTER O WITH TILDE
|
||||
+<U00B5> /xe6 MICRO SIGN
|
||||
+<U00FE> /xe7 LATIN SMALL LETTER THORN (Icelandic)
|
||||
+<U00DE> /xe8 LATIN CAPITAL LETTER THORN (Icelandic)
|
||||
+<U00DA> /xe9 LATIN CAPITAL LETTER U WITH ACUTE
|
||||
+<U00DB> /xea LATIN CAPITAL LETTER U WITH CIRCUMFLEX
|
||||
+<U00D9> /xeb LATIN CAPITAL LETTER U WITH GRAVE
|
||||
+<U00FD> /xec LATIN SMALL LETTER Y WITH ACUTE
|
||||
+<U00DD> /xed LATIN CAPITAL LETTER Y WITH ACUTE
|
||||
+<U00AF> /xee MACRON
|
||||
+<U00B4> /xef ACUTE ACCENT
|
||||
+<U00AD> /xf0 SOFT HYPHEN
|
||||
+<U00B1> /xf1 PLUS-MINUS SIGN
|
||||
+<U2017> /xf2 DOUBLE LOW LINE
|
||||
+<U00BE> /xf3 VULGAR FRACTION THREE QUARTERS
|
||||
+<U00B6> /xf4 PILCROW SIGN
|
||||
+<U00A7> /xf5 SECTION SIGN
|
||||
+<U00F7> /xf6 DIVISION SIGN
|
||||
+<U00B8> /xf7 CEDILLA
|
||||
+<U00B0> /xf8 DEGREE SIGN
|
||||
+<U00A8> /xf9 DIAERESIS
|
||||
+<U00B7> /xfa MIDDLE DOT
|
||||
+<U00B9> /xfb SUPERSCRIPT ONE
|
||||
+<U00B3> /xfc SUPERSCRIPT THREE
|
||||
+<U00B2> /xfd SUPERSCRIPT TWO
|
||||
+<U25A0> /xfe BLACK SQUARE
|
||||
+<U00A0> /xff NO-BREAK SPACE
|
||||
+END CHARMAP
|
|
@ -0,0 +1,201 @@
|
|||
commit e6b4e2de6dd91efdcac80b79149c596de8a26b70
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jun 27 09:26:46 2017 +0200
|
||||
|
||||
resolv: Call _res_hconf_init from __res_vinit
|
||||
|
||||
Many callers of __res_maybe_init also call _res_hconf_init.
|
||||
Additional calls to the latter do not hurt because the function
|
||||
does its work only once. (/etc/hosts.conf is not reloaded or
|
||||
even checked for changes.) This means that we can simplify the
|
||||
code by calling _res_hconf_init directly from __res_vinit.
|
||||
|
||||
diff --git a/inet/gethstbyad_r.c b/inet/gethstbyad_r.c
|
||||
index 88f428c1dbd3c177..6b5c13105059dd35 100644
|
||||
--- a/inet/gethstbyad_r.c
|
||||
+++ b/inet/gethstbyad_r.c
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
-
|
||||
+#include <resolv/res_hconf.h>
|
||||
|
||||
#define LOOKUP_TYPE struct hostent
|
||||
#define FUNCTION_NAME gethostbyaddr
|
||||
@@ -27,7 +27,6 @@
|
||||
#define ADD_VARIABLES addr, len, type
|
||||
#define NEED_H_ERRNO 1
|
||||
#define NEED__RES 1
|
||||
-#define NEED__RES_HCONF 1
|
||||
/* If the addr parameter is the IPv6 unspecified address no query must
|
||||
be performed. */
|
||||
#define PREPROCESS \
|
||||
diff --git a/inet/gethstbynm2_r.c b/inet/gethstbynm2_r.c
|
||||
index 57047979900accfc..580ba6d1cfbd63ec 100644
|
||||
--- a/inet/gethstbynm2_r.c
|
||||
+++ b/inet/gethstbynm2_r.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
-
|
||||
+#include <resolv/res_hconf.h>
|
||||
|
||||
#define LOOKUP_TYPE struct hostent
|
||||
#define FUNCTION_NAME gethostbyname2
|
||||
@@ -30,7 +30,7 @@
|
||||
#define ADD_PARAMS const char *name, int af
|
||||
#define ADD_VARIABLES name, af
|
||||
#define NEED_H_ERRNO 1
|
||||
-#define NEED__RES_HCONF 1
|
||||
+#define NEED__RES 1
|
||||
#define POSTPROCESS \
|
||||
if (status == NSS_STATUS_SUCCESS) \
|
||||
_res_hconf_reorder_addrs (resbuf);
|
||||
diff --git a/inet/gethstbynm_r.c b/inet/gethstbynm_r.c
|
||||
index 3758a9dde8e016f4..8f464b5ff1914b86 100644
|
||||
--- a/inet/gethstbynm_r.c
|
||||
+++ b/inet/gethstbynm_r.c
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
-
|
||||
+#include <resolv/res_hconf.h>
|
||||
|
||||
#define LOOKUP_TYPE struct hostent
|
||||
#define FUNCTION_NAME gethostbyname
|
||||
@@ -30,7 +30,7 @@
|
||||
#define ADD_PARAMS const char *name
|
||||
#define ADD_VARIABLES name
|
||||
#define NEED_H_ERRNO 1
|
||||
-#define NEED__RES_HCONF 1
|
||||
+#define NEED__RES 1
|
||||
#define POSTPROCESS \
|
||||
if (status == NSS_STATUS_SUCCESS) \
|
||||
_res_hconf_reorder_addrs (resbuf);
|
||||
diff --git a/nscd/aicache.c b/nscd/aicache.c
|
||||
index ea29b1c3d99bb530..358945140e04b2a9 100644
|
||||
--- a/nscd/aicache.c
|
||||
+++ b/nscd/aicache.c
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <resolv/resolv-internal.h>
|
||||
-#include <resolv/res_hconf.h>
|
||||
#include <scratch_buffer.h>
|
||||
|
||||
#include "dbg_log.h"
|
||||
@@ -103,7 +102,6 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
nip = hosts_database;
|
||||
|
||||
/* Initialize configurations. */
|
||||
- _res_hconf_init ();
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
no_more = 1;
|
||||
|
||||
diff --git a/nscd/gethstbyad_r.c b/nscd/gethstbyad_r.c
|
||||
index b17f0d2b5100c151..842ced2ec64048ea 100644
|
||||
--- a/nscd/gethstbyad_r.c
|
||||
+++ b/nscd/gethstbyad_r.c
|
||||
@@ -28,7 +28,6 @@
|
||||
#define EXTRA_VARIABLES , ttlp
|
||||
#define NEED_H_ERRNO 1
|
||||
#define NEED__RES 1
|
||||
-#define NEED__RES_HCONF 1
|
||||
|
||||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||||
#undef USE_NSCD
|
||||
diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c
|
||||
index 41bb26845d7b9592..2ab75e469eca1589 100644
|
||||
--- a/nscd/gethstbynm3_r.c
|
||||
+++ b/nscd/gethstbynm3_r.c
|
||||
@@ -32,7 +32,7 @@
|
||||
#define ADD_VARIABLES name, af
|
||||
#define EXTRA_VARIABLES , ttlp, canonp
|
||||
#define NEED_H_ERRNO 1
|
||||
-#define NEED__RES_HCONF 1
|
||||
+#define NEED__RES 1
|
||||
|
||||
#define HANDLE_DIGITS_DOTS 1
|
||||
#define HAVE_LOOKUP_BUFFER 1
|
||||
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
|
||||
index 5962475737dee6ba..7cab825cf05503f6 100644
|
||||
--- a/nss/getXXbyYY_r.c
|
||||
+++ b/nss/getXXbyYY_r.c
|
||||
@@ -25,9 +25,6 @@
|
||||
#ifdef USE_NSCD
|
||||
# include <nscd/nscd_proto.h>
|
||||
#endif
|
||||
-#ifdef NEED__RES_HCONF
|
||||
-# include <resolv/res_hconf.h>
|
||||
-#endif
|
||||
#ifdef NEED__RES
|
||||
# include <resolv.h>
|
||||
#endif
|
||||
@@ -273,9 +270,6 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
return errno;
|
||||
}
|
||||
#endif /* need _res */
|
||||
-#ifdef NEED__RES_HCONF
|
||||
- _res_hconf_init ();
|
||||
-#endif /* need _res_hconf */
|
||||
|
||||
void *tmp_ptr = fct.l;
|
||||
#ifdef PTR_MANGLE
|
||||
diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h
|
||||
index 6eaf4039f3451511..209f76a0d6ef8193 100644
|
||||
--- a/resolv/res_hconf.h
|
||||
+++ b/resolv/res_hconf.h
|
||||
@@ -46,7 +46,7 @@ struct hconf
|
||||
};
|
||||
extern struct hconf _res_hconf;
|
||||
|
||||
-extern void _res_hconf_init (void);
|
||||
+extern void _res_hconf_init (void) attribute_hidden;
|
||||
extern void _res_hconf_trim_domain (char *domain);
|
||||
extern void _res_hconf_trim_domains (struct hostent *hp);
|
||||
extern void _res_hconf_reorder_addrs (struct hostent *hp);
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 9aa907ee199f01a6..821f06061b4c3fb1 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -85,6 +85,7 @@
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv/resolv-internal.h>
|
||||
+#include <res_hconf.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
@@ -430,6 +431,9 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
int
|
||||
__res_vinit (res_state statp, int preinit)
|
||||
{
|
||||
+ /* Ensure that /etc/hosts.conf has been loaded (once). */
|
||||
+ _res_hconf_init ();
|
||||
+
|
||||
FILE *fp = fopen (_PATH_RESCONF, "rce");
|
||||
if (fp == NULL)
|
||||
switch (errno)
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 91e0a76c5cfa027f..4fb1eaef79bc66a3 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -80,7 +80,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <not-cancel.h>
|
||||
#include <nscd/nscd-client.h>
|
||||
#include <nscd/nscd_proto.h>
|
||||
-#include <resolv/res_hconf.h>
|
||||
#include <scratch_buffer.h>
|
||||
#include <inet/net-internal.h>
|
||||
|
||||
@@ -767,7 +766,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
nip = __nss_hosts_database;
|
||||
|
||||
/* Initialize configurations. */
|
||||
- _res_hconf_init ();
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
no_more = 1;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
commit b1e7c13cc58572600809d5173fed2c00c38af2e7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 23 17:52:55 2017 +0200
|
||||
|
||||
resolv: Clean up declarations of the __res_initstamp variable
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index ed5a4d4804a792de..9aa907ee199f01a6 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -105,7 +105,7 @@
|
||||
static void res_setoptions (res_state, const char *, const char *);
|
||||
static uint32_t net_mask (struct in_addr);
|
||||
|
||||
-unsigned long long int __res_initstamp attribute_hidden;
|
||||
+unsigned long long int __res_initstamp;
|
||||
|
||||
int
|
||||
res_ninit (res_state statp)
|
||||
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
|
||||
index 3ef885762e890a40..5202b756ff17518a 100644
|
||||
--- a/resolv/res_libc.c
|
||||
+++ b/resolv/res_libc.c
|
||||
@@ -25,8 +25,8 @@
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#include <libc-lock.h>
|
||||
+#include <resolv-internal.h>
|
||||
|
||||
-extern unsigned long long int __res_initstamp attribute_hidden;
|
||||
/* We have atomic increment operations on 64-bit platforms. */
|
||||
#if __WORDSIZE == 64
|
||||
# define atomicinclock(lock) (void) 0
|
||||
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
|
||||
index 9afaa07d8b03d31f..5a9faf8de975f316 100644
|
||||
--- a/resolv/resolv-internal.h
|
||||
+++ b/resolv/resolv-internal.h
|
||||
@@ -65,4 +65,7 @@ int __res_nopt (res_state, int n0, unsigned char *buf, int buflen,
|
||||
int __inet_pton_length (int af, const char *src, size_t srclen, void *);
|
||||
libc_hidden_proto (__inet_pton_length)
|
||||
|
||||
+/* Used to propagate the effect of res_init calls across threads. */
|
||||
+extern unsigned long long int __res_initstamp attribute_hidden;
|
||||
+
|
||||
#endif /* _RESOLV_INTERNAL_H */
|
|
@ -0,0 +1,162 @@
|
|||
commit 89f6307c5d270ed4f11cee373031fa9f2222f2b9
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jul 4 11:18:34 2017 +0200
|
||||
|
||||
resolv: Fix improper assert in __resolv_conf_attach
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index c1fcf341746cf1a8..e80583c72b96efb4 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -51,6 +51,7 @@ tests += \
|
||||
tst-resolv-basic \
|
||||
tst-resolv-edns \
|
||||
tst-resolv-network \
|
||||
+ tst-resolv-res_init-multi \
|
||||
tst-resolv-search \
|
||||
|
||||
# These tests need libdl.
|
||||
@@ -160,6 +161,8 @@ $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so
|
||||
+$(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
|
||||
+ $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index b98cf92890a121f9..0ed36cde02608f2d 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -58,8 +58,10 @@ struct resolv_conf_global
|
||||
the array element is overwritten with NULL. */
|
||||
struct resolv_conf_array array;
|
||||
|
||||
- /* Start of the free list in the array. The MSB is set if this
|
||||
- field has been initialized. */
|
||||
+ /* Start of the free list in the array. Zero if the free list is
|
||||
+ empty. Otherwise, free_list_start >> 1 is the first element of
|
||||
+ the free list (and the free list entries all have their LSB set
|
||||
+ and are shifted one to the left). */
|
||||
uintptr_t free_list_start;
|
||||
|
||||
/* Cached current configuration object for /etc/resolv.conf. */
|
||||
@@ -567,11 +569,7 @@ decrement_at_index (struct resolv_conf_global *global_copy, size_t index)
|
||||
struct resolv_conf *conf = (struct resolv_conf *) *slot;
|
||||
conf_decrement (conf);
|
||||
/* Put the slot onto the free list. */
|
||||
- if (global_copy->free_list_start == 0)
|
||||
- /* Not yet initialized. */
|
||||
- *slot = 1;
|
||||
- else
|
||||
- *slot = global_copy->free_list_start;
|
||||
+ *slot = global_copy->free_list_start;
|
||||
global_copy->free_list_start = (index << 1) | 1;
|
||||
}
|
||||
}
|
||||
@@ -598,7 +596,8 @@ __resolv_conf_attach (struct __res_state *resp, struct resolv_conf *conf)
|
||||
index = global_copy->free_list_start >> 1;
|
||||
uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
|
||||
global_copy->free_list_start = *slot;
|
||||
- assert (global_copy->free_list_start & 1);
|
||||
+ assert (global_copy->free_list_start == 0
|
||||
+ || global_copy->free_list_start & 1);
|
||||
/* Install the configuration pointer. */
|
||||
*slot = (uintptr_t) conf;
|
||||
}
|
||||
diff --git a/resolv/tst-resolv-res_init-multi.c b/resolv/tst-resolv-res_init-multi.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..bdc68a5a33f7f017
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-res_init-multi.c
|
||||
@@ -0,0 +1,89 @@
|
||||
+/* Multi-threaded test for resolver initialization.
|
||||
+ Copyright (C) 2017 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 <netdb.h>
|
||||
+#include <resolv.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+/* Whether name lookups succeed does not really matter. We use this
|
||||
+ to trigger initialization of the resolver. */
|
||||
+static const char *test_hostname = "www.gnu.org";
|
||||
+
|
||||
+/* The different initialization methods. */
|
||||
+enum test_type { init, byname, gai };
|
||||
+enum { type_count = 3 };
|
||||
+
|
||||
+/* Thread function. Perform a few resolver options. */
|
||||
+static void *
|
||||
+thread_func (void *closure)
|
||||
+{
|
||||
+ enum test_type *ptype = closure;
|
||||
+ /* Perform a few calls to the requested operation. */
|
||||
+ TEST_VERIFY (*ptype >= 0);
|
||||
+ TEST_VERIFY (*ptype < (int) type_count);
|
||||
+ for (int i = 0; i < 3; ++i)
|
||||
+ switch (*ptype)
|
||||
+ {
|
||||
+ case init:
|
||||
+ res_init ();
|
||||
+ break;
|
||||
+ case byname:
|
||||
+ gethostbyname (test_hostname);
|
||||
+ break;
|
||||
+ case gai:
|
||||
+ {
|
||||
+ struct addrinfo hints = { 0, };
|
||||
+ struct addrinfo *ai = NULL;
|
||||
+ if (getaddrinfo (test_hostname, "80", &hints, &ai) == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ free (ptype);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Start a small number of threads which perform resolver
|
||||
+ operations. */
|
||||
+ enum { thread_count = 30 };
|
||||
+
|
||||
+ pthread_t threads[thread_count];
|
||||
+ for (int i = 0; i < thread_count; ++i)
|
||||
+ {
|
||||
+ enum test_type *ptype = xmalloc (sizeof (*ptype));
|
||||
+ *ptype = i % type_count;
|
||||
+ threads[i] = xpthread_create (NULL, thread_func, ptype);
|
||||
+ }
|
||||
+ for (int i = 0; i < type_count; ++i)
|
||||
+ {
|
||||
+ enum test_type *ptype = xmalloc (sizeof (*ptype));
|
||||
+ *ptype = i;
|
||||
+ thread_func (ptype);
|
||||
+ }
|
||||
+ for (int i = 0; i < thread_count; ++i)
|
||||
+ xpthread_join (threads[i]);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,24 @@
|
|||
commit 27233446a62ca35ce0b54566279a99a6774d4210
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Sep 6 15:47:27 2017 +0200
|
||||
|
||||
resolv: __resolv_conf_attach must not free passed conf object [BZ #22096]
|
||||
|
||||
(cherry picked from commit a83047308196e3e54716a39dd85c0a08b198d6bd)
|
||||
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index f391d30c277bb348..e0f296d02e061a89 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -600,10 +600,7 @@ __resolv_conf_attach (struct __res_state *resp, struct resolv_conf *conf)
|
||||
|
||||
struct resolv_conf_global *global_copy = get_locked_global ();
|
||||
if (global_copy == NULL)
|
||||
- {
|
||||
- free (conf);
|
||||
- return false;
|
||||
- }
|
||||
+ return false;
|
||||
|
||||
/* Try to find an unused index in the array. */
|
||||
size_t index;
|
|
@ -0,0 +1,63 @@
|
|||
Partial backport of:
|
||||
|
||||
commit 6781d8e693eb9e1251875222db5c9885d7ebb596
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:41 2017 +0200
|
||||
|
||||
resolv: Turn _res_opcodes into a compatibility symbol
|
||||
|
||||
The backport avoids depending on the GLIBC_2.26 symbol version.
|
||||
|
||||
diff --git a/include/resolv.h b/include/resolv.h
|
||||
index 4d5b51e873ad62a1..2938506d75ee5d43 100644
|
||||
--- a/include/resolv.h
|
||||
+++ b/include/resolv.h
|
||||
@@ -90,8 +90,5 @@ libresolv_hidden_proto (__b64_ntop)
|
||||
libresolv_hidden_proto (__dn_count_labels)
|
||||
libresolv_hidden_proto (__p_secstodate)
|
||||
|
||||
-extern const char *_res_opcodes[];
|
||||
-libresolv_hidden_proto (_res_opcodes)
|
||||
-
|
||||
# endif /* _RESOLV_H_ && !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
|
||||
index 182aeefa1f8683f4..b26c38bae0a1674b 100644
|
||||
--- a/resolv/res_debug.c
|
||||
+++ b/resolv/res_debug.c
|
||||
@@ -106,6 +106,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
+#include <shlib-compat.h>
|
||||
|
||||
#ifdef SPRINTF_CHAR
|
||||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||||
@@ -115,7 +116,8 @@
|
||||
|
||||
extern const char *_res_sectioncodes[] attribute_hidden;
|
||||
|
||||
-const char *_res_opcodes[] =
|
||||
+/* _res_opcodes was exported by accident as a variable. */
|
||||
+static const char *res_opcodes[] =
|
||||
{
|
||||
"QUERY",
|
||||
"IQUERY",
|
||||
@@ -134,7 +136,7 @@ const char *_res_opcodes[] =
|
||||
"ZONEINIT",
|
||||
"ZONEREF",
|
||||
};
|
||||
-libresolv_hidden_data_def (_res_opcodes)
|
||||
+strong_alias (res_opcodes, _res_opcodes)
|
||||
|
||||
static const char *p_section(int section, int opcode);
|
||||
|
||||
@@ -259,7 +261,7 @@ fp_nquery (const unsigned char *msg, int len, FILE *file)
|
||||
if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode)
|
||||
fprintf(file,
|
||||
";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
|
||||
- _res_opcodes[opcode], p_rcode(rcode), id);
|
||||
+ res_opcodes[opcode], p_rcode(rcode), id);
|
||||
if ((!pfcode) || (pfcode & RES_PRF_HEADX))
|
||||
putc(';', file);
|
||||
if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) {
|
|
@ -0,0 +1,21 @@
|
|||
commit a0704b1ac7e8dc26f0e0feac58468958305ae844
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Apr 19 19:34:42 2017 +0200
|
||||
|
||||
nss_dns: Correct parentheses for the __glibc_unlikely argument
|
||||
|
||||
This fixes commit bee05c9d58a34ec5886faf3b56ecaa56355d94bf.
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 7099d093f357e16c..f121aa3de73704ea 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -633,7 +633,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
packtmp, sizeof packtmp);
|
||||
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
{
|
||||
- if (__glibc_unlikely (errno) == EMSGSIZE)
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
goto too_small;
|
||||
|
||||
n = -1;
|
|
@ -0,0 +1,206 @@
|
|||
commit bee05c9d58a34ec5886faf3b56ecaa56355d94bf
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Apr 19 14:29:11 2017 +0200
|
||||
|
||||
resolv: Replace __builtin_expect with __glibc_unlikely/__glibc_likely
|
||||
|
||||
diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c
|
||||
index 3ee6a08b4fd9f2fb..a86bd4360d6b03e8 100644
|
||||
--- a/resolv/gai_suspend.c
|
||||
+++ b/resolv/gai_suspend.c
|
||||
@@ -141,7 +141,7 @@ gai_suspend (const struct gaicb *const list[], int ent,
|
||||
/* An error occurred. Possibly it's EINTR. We have to translate
|
||||
the timeout error report of `pthread_cond_timedwait' to the
|
||||
form expected from `gai_suspend'. */
|
||||
- if (__builtin_expect (result, ETIMEDOUT) == ETIMEDOUT)
|
||||
+ if (__glibc_likely (result == ETIMEDOUT))
|
||||
result = EAI_AGAIN;
|
||||
else if (result == EINTR)
|
||||
result = EAI_INTR;
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 705b3c9c078c41bf..7099d093f357e16c 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -619,7 +619,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
ancount = ntohs (hp->ancount);
|
||||
qdcount = ntohs (hp->qdcount);
|
||||
cp = answer->buf + HFIXEDSZ;
|
||||
- if (__builtin_expect (qdcount, 1) != 1)
|
||||
+ if (__glibc_unlikely (qdcount != 1))
|
||||
{
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
@@ -633,7 +633,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
packtmp, sizeof packtmp);
|
||||
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
{
|
||||
- if (__builtin_expect (errno, 0) == EMSGSIZE)
|
||||
+ if (__glibc_unlikely (errno) == EMSGSIZE)
|
||||
goto too_small;
|
||||
|
||||
n = -1;
|
||||
@@ -642,13 +642,19 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
if (n > 0 && bp[0] == '.')
|
||||
bp[0] = '\0';
|
||||
|
||||
- if (__builtin_expect (n < 0 || ((*name_ok) (bp) == 0 && (errno = EBADMSG)),
|
||||
- 0))
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
{
|
||||
*errnop = errno;
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
+ if (__glibc_unlikely (name_ok (bp) == 0))
|
||||
+ {
|
||||
+ errno = EBADMSG;
|
||||
+ *errnop = EBADMSG;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
cp += n + QFIXEDSZ;
|
||||
|
||||
if (qtype == T_A || qtype == T_AAAA)
|
||||
@@ -690,7 +696,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
packtmp, sizeof packtmp);
|
||||
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
{
|
||||
- if (__builtin_expect (errno, 0) == EMSGSIZE)
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
goto too_small;
|
||||
|
||||
n = -1;
|
||||
@@ -750,7 +756,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
/* Store alias. */
|
||||
*ap++ = bp;
|
||||
n = strlen (bp) + 1; /* For the \0. */
|
||||
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
|
||||
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -761,7 +767,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
n = strlen (tbuf) + 1; /* For the \0. */
|
||||
if (__glibc_unlikely (n > linebuflen))
|
||||
goto too_small;
|
||||
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
|
||||
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -789,7 +795,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
n = strlen (tbuf) + 1; /* For the \0. */
|
||||
if (__glibc_unlikely (n > linebuflen))
|
||||
goto too_small;
|
||||
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
|
||||
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -821,7 +827,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
packtmp, sizeof packtmp);
|
||||
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
{
|
||||
- if (__builtin_expect (errno, 0) == EMSGSIZE)
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
goto too_small;
|
||||
|
||||
n = -1;
|
||||
@@ -854,7 +860,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
return NSS_STATUS_SUCCESS;
|
||||
case T_A:
|
||||
case T_AAAA:
|
||||
- if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
|
||||
+ if (__glibc_unlikely (strcasecmp (result->h_name, bp) != 0))
|
||||
{
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
@@ -975,7 +981,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
it later. */
|
||||
if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
|
||||
{
|
||||
- if (__builtin_expect (errno, 0) == EMSGSIZE)
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
{
|
||||
too_small:
|
||||
*errnop = ERANGE;
|
||||
@@ -986,13 +992,19 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
n = -1;
|
||||
}
|
||||
|
||||
- if (__builtin_expect (n < 0 || (res_hnok (buffer) == 0
|
||||
- && (errno = EBADMSG)), 0))
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
{
|
||||
*errnop = errno;
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
+ if (__glibc_unlikely (res_hnok (buffer) == 0))
|
||||
+ {
|
||||
+ errno = EBADMSG;
|
||||
+ *errnop = EBADMSG;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
cp += n + QFIXEDSZ;
|
||||
|
||||
int haveanswer = 0;
|
||||
@@ -1014,7 +1026,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
if (n != -1 &&
|
||||
(h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
|
||||
{
|
||||
- if (__builtin_expect (errno, 0) == EMSGSIZE)
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
goto too_small;
|
||||
|
||||
n = -1;
|
||||
@@ -1128,8 +1140,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
buffer += pad;
|
||||
buflen = buflen > pad ? buflen - pad : 0;
|
||||
|
||||
- if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple),
|
||||
- 0))
|
||||
+ if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
|
||||
goto too_small;
|
||||
|
||||
*pat = (struct gaih_addrtuple *) buffer;
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 923724f86d6a0edc..23676e994dd58be7 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -356,7 +356,7 @@ __res_vinit(res_state statp, int preinit) {
|
||||
statp->nsort = nsort;
|
||||
(void) fclose(fp);
|
||||
}
|
||||
- if (__builtin_expect(statp->nscount == 0, 0)) {
|
||||
+ if (__glibc_unlikely (statp->nscount == 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_query.c b/resolv/res_query.c
|
||||
index ec65bab04153c2ff..0ca3a650282ec7f0 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -199,7 +199,7 @@ __libc_res_nquery(res_state statp,
|
||||
nquery1 = n;
|
||||
}
|
||||
|
||||
- if (__builtin_expect (n <= 0, 0) && !use_malloc) {
|
||||
+ if (__glibc_unlikely (n <= 0) && !use_malloc) {
|
||||
/* Retry just in case res_nmkquery failed because of too
|
||||
short buffer. Shouldn't happen. */
|
||||
bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 440da90a0b381b84..1835ec7ee507d215 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -424,7 +424,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
* Some resolvers want to even out the load on their nameservers.
|
||||
* Note that RES_BLAST overrides RES_ROTATE.
|
||||
*/
|
||||
- if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0)) {
|
||||
+ if (__glibc_unlikely ((statp->options & RES_ROTATE) != 0)) {
|
||||
struct sockaddr_in ina;
|
||||
struct sockaddr_in6 *inp;
|
||||
int lastns = statp->nscount - 1;
|
|
@ -0,0 +1,230 @@
|
|||
commit d85f99679d89fb47426301620b7a980388fddcfd
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:35 2017 +0200
|
||||
|
||||
resolv: Move fp_nquery, fp_query, p_query, _res_opcodes
|
||||
|
||||
From res_data.c to res_debug.c.
|
||||
|
||||
Also drop the unnecessary _res initialization from fp_nquery.
|
||||
|
||||
diff --git a/include/resolv.h b/include/resolv.h
|
||||
index 37e4047ac40c6ae1..4d5b51e873ad62a1 100644
|
||||
--- a/include/resolv.h
|
||||
+++ b/include/resolv.h
|
||||
@@ -32,8 +32,6 @@ extern struct hostent *_gethtbyname2 (const char *__name, int __af);
|
||||
struct hostent *_gethtbyaddr (const char *addr, size_t __len, int __af);
|
||||
extern uint32_t _getlong (const unsigned char *__src);
|
||||
extern uint16_t _getshort (const unsigned char *__src);
|
||||
-extern void res_pquery (const res_state __statp, const unsigned char *__msg,
|
||||
- int __len, FILE *__file);
|
||||
extern int res_ourserver_p (const res_state __statp,
|
||||
const struct sockaddr_in6 *__inp);
|
||||
extern void __res_iclose (res_state statp, bool free_addr);
|
||||
diff --git a/resolv/res_data.c b/resolv/res_data.c
|
||||
index d907bfc9bd8a55fd..d05389e1347a57ab 100644
|
||||
--- a/resolv/res_data.c
|
||||
+++ b/resolv/res_data.c
|
||||
@@ -32,46 +32,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-const char *_res_opcodes[] = {
|
||||
- "QUERY",
|
||||
- "IQUERY",
|
||||
- "CQUERYM",
|
||||
- "CQUERYU", /* experimental */
|
||||
- "NOTIFY", /* experimental */
|
||||
- "UPDATE",
|
||||
- "6",
|
||||
- "7",
|
||||
- "8",
|
||||
- "9",
|
||||
- "10",
|
||||
- "11",
|
||||
- "12",
|
||||
- "13",
|
||||
- "ZONEINIT",
|
||||
- "ZONEREF",
|
||||
-};
|
||||
-libresolv_hidden_data_def (_res_opcodes)
|
||||
-
|
||||
-void
|
||||
-p_query(const u_char *msg) {
|
||||
- fp_query(msg, stdout);
|
||||
-}
|
||||
-
|
||||
-void
|
||||
-fp_query(const u_char *msg, FILE *file) {
|
||||
- fp_nquery(msg, PACKETSZ, file);
|
||||
-}
|
||||
-libresolv_hidden_def (fp_query)
|
||||
-
|
||||
-void
|
||||
-fp_nquery(const u_char *msg, int len, FILE *file) {
|
||||
- if (__res_maybe_init (&_res, 0) == -1)
|
||||
- return;
|
||||
-
|
||||
- res_pquery(&_res, msg, len, file);
|
||||
-}
|
||||
-libresolv_hidden_def (fp_nquery)
|
||||
-
|
||||
int
|
||||
res_query(const char *name, /* domain name */
|
||||
int class, int type, /* class and type of query */
|
||||
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
|
||||
index e23559bad3d92e71..182aeefa1f8683f4 100644
|
||||
--- a/resolv/res_debug.c
|
||||
+++ b/resolv/res_debug.c
|
||||
@@ -115,6 +115,27 @@
|
||||
|
||||
extern const char *_res_sectioncodes[] attribute_hidden;
|
||||
|
||||
+const char *_res_opcodes[] =
|
||||
+ {
|
||||
+ "QUERY",
|
||||
+ "IQUERY",
|
||||
+ "CQUERYM",
|
||||
+ "CQUERYU", /* experimental */
|
||||
+ "NOTIFY", /* experimental */
|
||||
+ "UPDATE",
|
||||
+ "6",
|
||||
+ "7",
|
||||
+ "8",
|
||||
+ "9",
|
||||
+ "10",
|
||||
+ "11",
|
||||
+ "12",
|
||||
+ "13",
|
||||
+ "ZONEINIT",
|
||||
+ "ZONEREF",
|
||||
+ };
|
||||
+libresolv_hidden_data_def (_res_opcodes)
|
||||
+
|
||||
static const char *p_section(int section, int opcode);
|
||||
|
||||
/*
|
||||
@@ -132,9 +153,7 @@ fp_resstat(const res_state statp, FILE *file) {
|
||||
}
|
||||
|
||||
static void
|
||||
-do_section(const res_state statp,
|
||||
- ns_msg *handle, ns_sect section,
|
||||
- int pflag, FILE *file)
|
||||
+do_section (int pfcode, ns_msg *handle, ns_sect section, int pflag, FILE *file)
|
||||
{
|
||||
int n, sflag, rrnum;
|
||||
static int buflen = 2048;
|
||||
@@ -145,8 +164,8 @@ do_section(const res_state statp,
|
||||
/*
|
||||
* Print answer records.
|
||||
*/
|
||||
- sflag = (statp->pfcode & pflag);
|
||||
- if (statp->pfcode && !sflag)
|
||||
+ sflag = (pfcode & pflag);
|
||||
+ if (pfcode && !sflag)
|
||||
return;
|
||||
|
||||
buf = malloc(buflen);
|
||||
@@ -163,11 +182,11 @@ do_section(const res_state statp,
|
||||
fprintf(file, ";; ns_parserr: %s\n",
|
||||
strerror(errno));
|
||||
else if (rrnum > 0 && sflag != 0 &&
|
||||
- (statp->pfcode & RES_PRF_HEAD1))
|
||||
+ (pfcode & RES_PRF_HEAD1))
|
||||
putc('\n', file);
|
||||
goto cleanup;
|
||||
}
|
||||
- if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
|
||||
+ if (rrnum == 0 && sflag != 0 && (pfcode & RES_PRF_HEAD1))
|
||||
fprintf(file, ";; %s SECTION:\n",
|
||||
p_section(section, opcode));
|
||||
if (section == ns_s_qd)
|
||||
@@ -209,11 +228,19 @@ do_section(const res_state statp,
|
||||
* This is intended to be primarily a debugging routine.
|
||||
*/
|
||||
void
|
||||
-res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
|
||||
+fp_nquery (const unsigned char *msg, int len, FILE *file)
|
||||
+{
|
||||
ns_msg handle;
|
||||
int qdcount, ancount, nscount, arcount;
|
||||
u_int opcode, rcode, id;
|
||||
|
||||
+ /* There is no need to initialize _res: If _res is not yet
|
||||
+ initialized, _res.pfcode is zero. But initialization will
|
||||
+ leave it at zero, too. _res.pfcode is an unsigned long,
|
||||
+ but the code here assumes that the flags fit into an int,
|
||||
+ so use that. */
|
||||
+ int pfcode = _res.pfcode;
|
||||
+
|
||||
if (ns_initparse(msg, len, &handle) < 0) {
|
||||
fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
|
||||
return;
|
||||
@@ -229,13 +256,13 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
|
||||
/*
|
||||
* Print header fields.
|
||||
*/
|
||||
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
|
||||
+ if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode)
|
||||
fprintf(file,
|
||||
";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
|
||||
_res_opcodes[opcode], p_rcode(rcode), id);
|
||||
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
|
||||
+ if ((!pfcode) || (pfcode & RES_PRF_HEADX))
|
||||
putc(';', file);
|
||||
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
|
||||
+ if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) {
|
||||
fprintf(file, "; flags:");
|
||||
if (ns_msg_getflag(handle, ns_f_qr))
|
||||
fprintf(file, " qr");
|
||||
@@ -254,7 +281,7 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
|
||||
if (ns_msg_getflag(handle, ns_f_cd))
|
||||
fprintf(file, " cd");
|
||||
}
|
||||
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
|
||||
+ if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) {
|
||||
fprintf(file, "; %s: %d",
|
||||
p_section(ns_s_qd, opcode), qdcount);
|
||||
fprintf(file, ", %s: %d",
|
||||
@@ -264,21 +291,35 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
|
||||
fprintf(file, ", %s: %d",
|
||||
p_section(ns_s_ar, opcode), arcount);
|
||||
}
|
||||
- if ((!statp->pfcode) || (statp->pfcode &
|
||||
+ if ((!pfcode) || (pfcode &
|
||||
(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
|
||||
putc('\n',file);
|
||||
}
|
||||
/*
|
||||
* Print the various sections.
|
||||
*/
|
||||
- do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
|
||||
- do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
|
||||
- do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
|
||||
- do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
|
||||
+ do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file);
|
||||
+ do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file);
|
||||
+ do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file);
|
||||
+ do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file);
|
||||
if (qdcount == 0 && ancount == 0 &&
|
||||
nscount == 0 && arcount == 0)
|
||||
putc('\n', file);
|
||||
}
|
||||
+libresolv_hidden_def (fp_nquery)
|
||||
+
|
||||
+void
|
||||
+fp_query (const unsigned char *msg, FILE *file)
|
||||
+{
|
||||
+ fp_nquery (msg, PACKETSZ, file);
|
||||
+}
|
||||
+libresolv_hidden_def (fp_query)
|
||||
+
|
||||
+void
|
||||
+p_query (const unsigned char *msg)
|
||||
+{
|
||||
+ fp_query (msg, stdout);
|
||||
+}
|
||||
|
||||
const u_char *
|
||||
p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
|
|
@ -0,0 +1,21 @@
|
|||
This change happened upstream in this commit:
|
||||
|
||||
commit ae65d4f3c3995279ca458c460ebf8bab1885fa03
|
||||
Author: Wilco Dijkstra <wdijkstr@arm.com>
|
||||
Date: Mon Mar 13 18:42:35 2017 +0000
|
||||
|
||||
Remove the str(n)dup inlines from string/bits/string2.h.
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 317413c9ef1559e6..b3d0a5ca74d926bb 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -1106,7 +1106,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
canonbuf = NULL;
|
||||
else
|
||||
{
|
||||
- canon = strdup (canon);
|
||||
+ canon = __strdup (canon);
|
||||
if (canon == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
|
@ -0,0 +1,33 @@
|
|||
commit 513a71a420e74270a6a9702ec916e807be51350a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Jun 24 16:51:31 2017 +0200
|
||||
|
||||
resolv/tst-resolv-basic: Add test cases for bug 21295
|
||||
|
||||
diff --git a/resolv/tst-resolv-basic.c b/resolv/tst-resolv-basic.c
|
||||
index 66a0e8a1659219b4..95aea1bcfb266017 100644
|
||||
--- a/resolv/tst-resolv-basic.c
|
||||
+++ b/resolv/tst-resolv-basic.c
|
||||
@@ -495,6 +495,22 @@ do_test (void)
|
||||
test_bug_21295 ();
|
||||
test_nodata_nxdomain ();
|
||||
|
||||
+ /* Test for bug 21295. */
|
||||
+ check_ai_hints ("www.example", "80",
|
||||
+ (struct addrinfo) { .ai_family = AF_INET6,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ .ai_flags = AI_V4MAPPED | AI_ALL, },
|
||||
+ "flags: AI_V4MAPPED AI_ALL\n"
|
||||
+ "address: STREAM/TCP 2001:db8::1 80\n"
|
||||
+ "address: STREAM/TCP ::ffff:192.0.2.17 80\n");
|
||||
+ check_ai_hints ("t.www.example", "80",
|
||||
+ (struct addrinfo) { .ai_family = AF_INET6,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ .ai_flags = AI_V4MAPPED | AI_ALL, },
|
||||
+ "flags: AI_V4MAPPED AI_ALL\n"
|
||||
+ "address: STREAM/TCP 2001:db8::3 80\n"
|
||||
+ "address: STREAM/TCP ::ffff:192.0.2.19 80\n");
|
||||
+
|
||||
resolv_test_end (aux);
|
||||
|
||||
return 0;
|
|
@ -0,0 +1,33 @@
|
|||
commit f768b450204f54b080ea5dc5c2071940604b424c
|
||||
Author: Benjamin Cama <b.cama@kerlink.fr>
|
||||
Date: Thu Jun 22 15:49:28 2017 +0200
|
||||
|
||||
inet: __inet6_scopeid_pton should accept node-local addresses [BZ #21657]
|
||||
|
||||
diff --git a/inet/inet6_scopeid_pton.c b/inet/inet6_scopeid_pton.c
|
||||
index f842ffcadb391960..e09b1cb34dcc9424 100644
|
||||
--- a/inet/inet6_scopeid_pton.c
|
||||
+++ b/inet/inet6_scopeid_pton.c
|
||||
@@ -33,6 +33,7 @@ __inet6_scopeid_pton (const struct in6_addr *address, const char *scope,
|
||||
uint32_t *result)
|
||||
{
|
||||
if (IN6_IS_ADDR_LINKLOCAL (address)
|
||||
+ || IN6_IS_ADDR_MC_NODELOCAL (address)
|
||||
|| IN6_IS_ADDR_MC_LINKLOCAL (address))
|
||||
{
|
||||
uint32_t number = __if_nametoindex (scope);
|
||||
diff --git a/inet/tst-inet6_scopeid_pton.c b/inet/tst-inet6_scopeid_pton.c
|
||||
index a1bafa9021c5cf3b..8225b3b80abe6331 100644
|
||||
--- a/inet/tst-inet6_scopeid_pton.c
|
||||
+++ b/inet/tst-inet6_scopeid_pton.c
|
||||
@@ -218,9 +218,9 @@ do_test (void)
|
||||
{
|
||||
expect_success ("fe80::1", interface_name, interface_index);
|
||||
expect_success ("ff02::1", interface_name, interface_index);
|
||||
+ expect_success ("ff01::1", interface_name, interface_index);
|
||||
expect_failure ("::", interface_name);
|
||||
expect_failure ("::1", interface_name);
|
||||
- expect_failure ("ff01::1", interface_name);
|
||||
expect_failure ("2001:db8::1", interface_name);
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
commit 9a0cc8c1bd7645bf3c988890ffb59639c07a5812
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 23 22:51:00 2017 +0200
|
||||
|
||||
inet_pton: Reject IPv6 addresses with many leading zeros [BZ #16637]
|
||||
|
||||
2001:db8:00001::f is not a valid IPv6 address according to RFC 2373.
|
||||
|
||||
diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c
|
||||
index b95da47c17ef8afc..16ee33e0c0dfb015 100644
|
||||
--- a/resolv/inet_pton.c
|
||||
+++ b/resolv/inet_pton.c
|
||||
@@ -144,7 +144,8 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
|
||||
{
|
||||
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *curtok;
|
||||
- int ch, saw_xdigit;
|
||||
+ int ch;
|
||||
+ size_t xdigits_seen; /* Number of hex digits since colon. */
|
||||
unsigned int val;
|
||||
|
||||
tp = memset (tmp, '\0', NS_IN6ADDRSZ);
|
||||
@@ -162,7 +163,7 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
|
||||
}
|
||||
|
||||
curtok = src;
|
||||
- saw_xdigit = 0;
|
||||
+ xdigits_seen = 0;
|
||||
val = 0;
|
||||
while (src < src_endp)
|
||||
{
|
||||
@@ -170,17 +171,19 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
|
||||
int digit = hex_digit_value (ch);
|
||||
if (digit >= 0)
|
||||
{
|
||||
+ if (xdigits_seen == 4)
|
||||
+ return 0;
|
||||
val <<= 4;
|
||||
val |= digit;
|
||||
if (val > 0xffff)
|
||||
return 0;
|
||||
- saw_xdigit = 1;
|
||||
+ ++xdigits_seen;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':')
|
||||
{
|
||||
curtok = src;
|
||||
- if (!saw_xdigit)
|
||||
+ if (xdigits_seen == 0)
|
||||
{
|
||||
if (colonp)
|
||||
return 0;
|
||||
@@ -193,7 +196,7 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
|
||||
return 0;
|
||||
*tp++ = (unsigned char) (val >> 8) & 0xff;
|
||||
*tp++ = (unsigned char) val & 0xff;
|
||||
- saw_xdigit = 0;
|
||||
+ xdigits_seen = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -201,12 +204,12 @@ inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
|
||||
&& inet_pton4 (curtok, src_endp, tp) > 0)
|
||||
{
|
||||
tp += NS_INADDRSZ;
|
||||
- saw_xdigit = 0;
|
||||
+ xdigits_seen = 0;
|
||||
break; /* '\0' was seen by inet_pton4. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
- if (saw_xdigit)
|
||||
+ if (xdigits_seen > 0)
|
||||
{
|
||||
if (tp + NS_INT16SZ > endp)
|
||||
return 0;
|
||||
diff --git a/resolv/tst-inet_pton.c b/resolv/tst-inet_pton.c
|
||||
index 7fffb24cdf9eb1f4..4bb9f8119378b467 100644
|
||||
--- a/resolv/tst-inet_pton.c
|
||||
+++ b/resolv/tst-inet_pton.c
|
||||
@@ -226,13 +226,7 @@ const struct test_case test_cases[] =
|
||||
},
|
||||
{.input = "2", },
|
||||
{.input = "2.", },
|
||||
- {.input = "2001:db8:00001::f",
|
||||
- .ipv6_ok = true,
|
||||
- .ipv6_expected = {
|
||||
- 0x20, 0x1, 0xd, 0xb8, 0x0, 0x1, 0x0, 0x0,
|
||||
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf
|
||||
- },
|
||||
- },
|
||||
+ {.input = "2001:db8:00001::f", },
|
||||
{.input = "2001:db8:10000::f", },
|
||||
{.input = "2001:db8:1234:5678:abcd:ef01:2345:67",
|
||||
.ipv6_ok = true,
|
||||
@@ -454,13 +448,7 @@ const struct test_case test_cases[] =
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
|
||||
},
|
||||
},
|
||||
- {.input = "::00001",
|
||||
- .ipv6_ok = true,
|
||||
- .ipv6_expected = {
|
||||
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
|
||||
- },
|
||||
- },
|
||||
+ {.input = "::00001", },
|
||||
{.input = "::1",
|
||||
.ipv6_ok = true,
|
||||
.ipv6_expected = {
|
|
@ -0,0 +1,20 @@
|
|||
commit 60149b28590be28051f99d0a343d7fbe002f2a8c
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Jun 21 13:09:08 2017 +0200
|
||||
|
||||
__inet_pton_length: Implement new internal helper function
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 3854ff4ad4156c15..692b2322cf7a3cab 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -65,6 +65,9 @@ tests += \
|
||||
|
||||
endif
|
||||
|
||||
+# This test accesses __inet_ntop_range, an internal libc function.
|
||||
+tests += tst-inet_pton
|
||||
+
|
||||
# This test sends millions of packets and is rather slow.
|
||||
xtests += tst-resolv-qtypes
|
||||
endif
|
|
@ -0,0 +1,52 @@
|
|||
commit 94f094f22b50a20de9042cb1e78c7299992a91c9
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 13:19:00 2017 +0200
|
||||
|
||||
resolv: Introduce is_sort_mask and call it from res_vinit
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index eb24fca3a6ecef9a..eb8e308fdaa899ef 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -85,9 +85,6 @@
|
||||
|
||||
static void res_setoptions (res_state, const char *, const char *)
|
||||
internal_function;
|
||||
-
|
||||
-static const char sort_mask_chars[] = "/&";
|
||||
-#define ISSORTMASK(ch) (strchr(sort_mask_chars, ch) != NULL)
|
||||
static u_int32_t net_mask (struct in_addr) __THROW;
|
||||
|
||||
unsigned long long int __res_initstamp attribute_hidden;
|
||||
@@ -109,6 +106,14 @@ res_ninit(res_state statp) {
|
||||
}
|
||||
libc_hidden_def (__res_ninit)
|
||||
|
||||
+/* Return true if CH separates the netmask in the "sortlist"
|
||||
+ directive. */
|
||||
+static inline bool
|
||||
+is_sort_mask (char ch)
|
||||
+{
|
||||
+ return ch == '/' || ch == '&';
|
||||
+}
|
||||
+
|
||||
/* This function has to be reachable by res_data.c but not publically. */
|
||||
int
|
||||
__res_vinit(res_state statp, int preinit) {
|
||||
@@ -305,14 +310,14 @@ __res_vinit(res_state statp, int preinit) {
|
||||
if (*cp == '\0' || *cp == '\n' || *cp == ';')
|
||||
break;
|
||||
net = cp;
|
||||
- while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
|
||||
+ while (*cp && !is_sort_mask (*cp) && *cp != ';' &&
|
||||
isascii(*cp) && !isspace(*cp))
|
||||
cp++;
|
||||
n = *cp;
|
||||
*cp = 0;
|
||||
if (__inet_aton(net, &a)) {
|
||||
statp->sort_list[nsort].addr = a;
|
||||
- if (ISSORTMASK(n)) {
|
||||
+ if (is_sort_mask (n)) {
|
||||
*cp++ = n;
|
||||
net = cp;
|
||||
while (*cp && *cp != ';' &&
|
|
@ -0,0 +1,32 @@
|
|||
commit 75b3a15e077dbfdfd8cbb3449369379e700b9972
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Apr 4 14:13:03 2017 +0200
|
||||
|
||||
nss_dns: Remove superfluous dn_expand call from network handling
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
|
||||
index 45f7f1805701e0a4..fd8c5656c0cedd27 100644
|
||||
--- a/resolv/nss_dns/dns-network.c
|
||||
+++ b/resolv/nss_dns/dns-network.c
|
||||
@@ -324,11 +324,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||||
|
||||
while (--answer_count >= 0 && cp < end_of_message)
|
||||
{
|
||||
- int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
|
||||
- int type, class;
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
+ int n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
+ packtmp, sizeof packtmp);
|
||||
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
{
|
||||
if (errno == EMSGSIZE)
|
||||
@@ -350,6 +347,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
+ int type, class;
|
||||
GETSHORT (type, cp);
|
||||
GETSHORT (class, cp);
|
||||
cp += INT32SZ; /* TTL */
|
|
@ -0,0 +1,289 @@
|
|||
commit 3005466abe8fb80ad4ff51865f1e28dd81c43347
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Sep 6 15:11:44 2017 +0200
|
||||
|
||||
nss_dns: Remove dead PTR IPv4-to-IPv6 mapping code
|
||||
|
||||
(cherry picked from commit c77eb96925b719001237ca7c9e3cef40d795d66b)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 7cd54ab5048dcd37..1e85e4f08ffc8600 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -889,19 +889,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
/* bind would put multiple PTR records as aliases, but we don't do
|
||||
that. */
|
||||
result->h_name = bp;
|
||||
- if (have_to_map)
|
||||
- {
|
||||
- n = strlen (bp) + 1; /* for the \0 */
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
- {
|
||||
- ++had_error;
|
||||
- break;
|
||||
- }
|
||||
- bp += n;
|
||||
- linebuflen -= n;
|
||||
- if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
- goto too_small;
|
||||
- }
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
case T_A:
|
||||
diff --git a/resolv/tst-res_use_inet6.c b/resolv/tst-res_use_inet6.c
|
||||
index 1522d5c5f5e4d860..d819f921d6e6746d 100644
|
||||
--- a/resolv/tst-res_use_inet6.c
|
||||
+++ b/resolv/tst-res_use_inet6.c
|
||||
@@ -16,31 +16,101 @@
|
||||
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.
|
||||
|
||||
- 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')
|
||||
@@ -49,6 +119,10 @@ response (const struct resolv_response_context *ctx,
|
||||
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)
|
||||
{
|
||||
@@ -70,11 +144,17 @@ response (const struct resolv_response_context *ctx,
|
||||
}
|
||||
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);
|
||||
+ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +242,65 @@ test_gai (void)
|
||||
}
|
||||
}
|
||||
|
||||
+/* 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
|
||||
@@ -207,6 +346,8 @@ test_get2_any (void)
|
||||
"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. */
|
||||
@@ -254,6 +395,10 @@ test_no_inet6 (void)
|
||||
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"
|
||||
@@ -307,6 +452,28 @@ threadfunc (void *ignored)
|
||||
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 ();
|
|
@ -0,0 +1,72 @@
|
|||
commit 44f28da7cab271b659551c4fe1a7d2e420803576
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Apr 4 14:36:02 2017 +0200
|
||||
|
||||
nss_dns: Replace local declarations with declarations from a header file
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index cd7ab6e925b25687..7a8290e1f26070e0 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -51,6 +51,9 @@ extern const struct _ns_flagdata _ns_flagdata[] attribute_hidden;
|
||||
|
||||
extern unsigned int __ns_get16 (const unsigned char *) __THROW;
|
||||
extern unsigned long __ns_get32 (const unsigned char *) __THROW;
|
||||
+int __ns_name_ntop (const unsigned char *, char *, size_t) __THROW;
|
||||
+int __ns_name_unpack (const unsigned char *, const unsigned char *,
|
||||
+ const unsigned char *, unsigned char *, size_t) __THROW;
|
||||
|
||||
#define ns_msg_getflag(handle, flag) \
|
||||
(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 01864dc96e639873..705b3c9c078c41bf 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -80,6 +80,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "nsswitch.h"
|
||||
+#include <arpa/nameser.h>
|
||||
|
||||
/* Get implementeation for some internal functions. */
|
||||
#include <resolv/resolv-internal.h>
|
||||
@@ -106,13 +107,6 @@ typedef union querybuf
|
||||
u_char buf[MAXPACKET];
|
||||
} querybuf;
|
||||
|
||||
-/* These functions are defined in res_comp.c. */
|
||||
-#define NS_MAXCDNAME 255 /* maximum compressed domain name */
|
||||
-extern int __ns_name_ntop (const u_char *, char *, size_t);
|
||||
-extern int __ns_name_unpack (const u_char *, const u_char *,
|
||||
- const u_char *, u_char *, size_t);
|
||||
-
|
||||
-
|
||||
static enum nss_status getanswer_r (const querybuf *answer, int anslen,
|
||||
const char *qname, int qtype,
|
||||
struct hostent *result, char *buffer,
|
||||
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
|
||||
index fd8c5656c0cedd27..2be72d33a30f917e 100644
|
||||
--- a/resolv/nss_dns/dns-network.c
|
||||
+++ b/resolv/nss_dns/dns-network.c
|
||||
@@ -66,6 +66,7 @@
|
||||
|
||||
#include "nsswitch.h"
|
||||
#include <arpa/inet.h>
|
||||
+#include <arpa/nameser.h>
|
||||
|
||||
/* Maximum number of aliases we allow. */
|
||||
#define MAX_NR_ALIASES 48
|
||||
@@ -92,13 +93,6 @@ typedef union querybuf
|
||||
u_char buf[MAXPACKET];
|
||||
} querybuf;
|
||||
|
||||
-/* These functions are defined in res_comp.c. */
|
||||
-#define NS_MAXCDNAME 255 /* maximum compressed domain name */
|
||||
-extern int __ns_name_ntop (const u_char *, char *, size_t) __THROW;
|
||||
-extern int __ns_name_unpack (const u_char *, const u_char *,
|
||||
- const u_char *, u_char *, size_t) __THROW;
|
||||
-
|
||||
-
|
||||
/* Prototypes for local functions. */
|
||||
static enum nss_status getanswer_r (const querybuf *answer, int anslen,
|
||||
struct netent *result, char *buffer,
|
|
@ -0,0 +1,217 @@
|
|||
commit 44500cbb25bc6e76723304b9ff39f875c04309f9
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 13 13:22:51 2017 +0200
|
||||
|
||||
resolv: Remove EDNS fallback [BZ #21369]
|
||||
|
||||
EDNS is disabled by default (so there is interoperability issue), and
|
||||
the fallback code is problematic because it prevents an application
|
||||
from obtaining DNSSEC data after a FORMERR response.
|
||||
|
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||||
index c3ebcbf6b50fcf4b..ec65bab04153c2ff 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -122,7 +122,6 @@ __libc_res_nquery(res_state statp,
|
||||
HEADER *hp = (HEADER *) answer;
|
||||
HEADER *hp2;
|
||||
int n, use_malloc = 0;
|
||||
- u_int oflags = statp->_flags;
|
||||
|
||||
size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
|
||||
u_char *buf = alloca (bufsize);
|
||||
@@ -145,8 +144,7 @@ __libc_res_nquery(res_state statp,
|
||||
query1, bufsize);
|
||||
if (n > 0)
|
||||
{
|
||||
- if ((oflags & RES_F_EDNS0ERR) == 0
|
||||
- && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
|
||||
+ if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
|
||||
{
|
||||
/* Use RESOLV_EDNS_BUFFER_SIZE because the receive
|
||||
buffer can be reallocated. */
|
||||
@@ -170,7 +168,6 @@ __libc_res_nquery(res_state statp,
|
||||
n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0,
|
||||
NULL, query2, bufsize - nused);
|
||||
if (n > 0
|
||||
- && (oflags & RES_F_EDNS0ERR) == 0
|
||||
&& (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
|
||||
/* Use RESOLV_EDNS_BUFFER_SIZE because the receive
|
||||
buffer can be reallocated. */
|
||||
@@ -187,7 +184,6 @@ __libc_res_nquery(res_state statp,
|
||||
query1, bufsize);
|
||||
|
||||
if (n > 0
|
||||
- && (oflags & RES_F_EDNS0ERR) == 0
|
||||
&& (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
|
||||
{
|
||||
/* Use RESOLV_EDNS_BUFFER_SIZE if the receive buffer
|
||||
@@ -215,16 +211,6 @@ __libc_res_nquery(res_state statp,
|
||||
}
|
||||
}
|
||||
if (__glibc_unlikely (n <= 0)) {
|
||||
- /* If the query choked with EDNS0, retry without EDNS0. */
|
||||
- if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0
|
||||
- && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
|
||||
- statp->_flags |= RES_F_EDNS0ERR;
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_nquery: retry without EDNS0\n");
|
||||
-#endif
|
||||
- goto again;
|
||||
- }
|
||||
#ifdef DEBUG
|
||||
if (statp->options & RES_DEBUG)
|
||||
printf(";; res_query: mkquery failed\n");
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 77d59dcc4e3b8d23..98968d6239d0c8f7 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -1321,26 +1321,6 @@ send_dg(res_state statp,
|
||||
? *thisanssizp : *thisresplenp);
|
||||
goto wait;
|
||||
}
|
||||
-#ifdef RES_USE_EDNS0
|
||||
- if (anhp->rcode == FORMERR
|
||||
- && (statp->options & RES_USE_EDNS0) != 0U) {
|
||||
- /*
|
||||
- * Do not retry if the server does not understand
|
||||
- * EDNS0. The case has to be captured here, as
|
||||
- * FORMERR packet do not carry query section, hence
|
||||
- * res_queriesmatch() returns 0.
|
||||
- */
|
||||
- DprintQ(statp->options & RES_DEBUG,
|
||||
- (stdout,
|
||||
- "server rejected query with EDNS0:\n"),
|
||||
- *thisansp,
|
||||
- (*thisresplenp > *thisanssizp)
|
||||
- ? *thisanssizp : *thisresplenp);
|
||||
- /* record the error */
|
||||
- statp->_flags |= RES_F_EDNS0ERR;
|
||||
- return close_and_return_error (statp, resplen2);
|
||||
- }
|
||||
-#endif
|
||||
if (!(statp->options & RES_INSECURE2)
|
||||
&& (recvresp1 || !res_queriesmatch(buf, buf + buflen,
|
||||
*thisansp,
|
||||
diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c
|
||||
index f17dbc3450f52b85..093a4f5f22aaaa51 100644
|
||||
--- a/resolv/tst-resolv-edns.c
|
||||
+++ b/resolv/tst-resolv-edns.c
|
||||
@@ -115,8 +115,23 @@ response (const struct resolv_response_context *ctx,
|
||||
{
|
||||
TEST_VERIFY_EXIT (qname != NULL);
|
||||
|
||||
- /* The "tcp." prefix can be used to request TCP fallback. */
|
||||
const char *qname_compare = qname;
|
||||
+
|
||||
+ /* The "formerr." prefix can be used to request a FORMERR response on the
|
||||
+ first server. */
|
||||
+ bool send_formerr;
|
||||
+ if (strncmp ("formerr.", qname, strlen ("formerr.")) == 0)
|
||||
+ {
|
||||
+ send_formerr = true;
|
||||
+ qname_compare = qname + strlen ("formerr.");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ send_formerr = false;
|
||||
+ qname_compare = qname;
|
||||
+ }
|
||||
+
|
||||
+ /* The "tcp." prefix can be used to request TCP fallback. */
|
||||
bool force_tcp;
|
||||
if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0)
|
||||
{
|
||||
@@ -132,14 +147,20 @@ response (const struct resolv_response_context *ctx,
|
||||
else
|
||||
{
|
||||
support_record_failure ();
|
||||
- printf ("error: unexpected QNAME: %s\n", qname);
|
||||
+ printf ("error: unexpected QNAME: %s (reduced: %s)\n",
|
||||
+ qname, qname_compare);
|
||||
return;
|
||||
}
|
||||
TEST_VERIFY_EXIT (qclass == C_IN);
|
||||
- struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp};
|
||||
+ struct resolv_response_flags flags = { };
|
||||
+ flags.tc = force_tcp && !ctx->tcp;
|
||||
+ if (!flags.tc && send_formerr && ctx->server_index == 0)
|
||||
+ /* Send a FORMERR for the first full response from the first
|
||||
+ server. */
|
||||
+ flags.rcode = 1; /* FORMERR */
|
||||
resolv_response_init (b, flags);
|
||||
resolv_response_add_question (b, qname, qclass, qtype);
|
||||
- if (flags.tc)
|
||||
+ if (flags.tc || flags.rcode != 0)
|
||||
return;
|
||||
|
||||
if (test_verbose)
|
||||
@@ -466,33 +487,42 @@ do_test (void)
|
||||
for (int do_edns = 0; do_edns < 2; ++do_edns)
|
||||
for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec)
|
||||
for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
|
||||
- {
|
||||
- struct resolv_test *aux = resolv_test_start
|
||||
- ((struct resolv_redirect_config)
|
||||
- {
|
||||
- .response_callback = response,
|
||||
- });
|
||||
-
|
||||
- use_edns = do_edns;
|
||||
- if (do_edns)
|
||||
- _res.options |= RES_USE_EDNS0;
|
||||
- use_dnssec = do_dnssec;
|
||||
- if (do_dnssec)
|
||||
- _res.options |= RES_USE_DNSSEC;
|
||||
-
|
||||
- char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
|
||||
- if (do_tcp)
|
||||
- {
|
||||
- char *n = xasprintf ("tcp.%s", probe_name);
|
||||
- free (probe_name);
|
||||
- probe_name = n;
|
||||
- }
|
||||
+ for (int do_formerr = 0; do_formerr < 2; ++do_formerr)
|
||||
+ {
|
||||
+ struct resolv_test *aux = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ });
|
||||
+
|
||||
+ use_edns = do_edns;
|
||||
+ if (do_edns)
|
||||
+ _res.options |= RES_USE_EDNS0;
|
||||
+ use_dnssec = do_dnssec;
|
||||
+ if (do_dnssec)
|
||||
+ _res.options |= RES_USE_DNSSEC;
|
||||
+
|
||||
+ char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
|
||||
+ if (do_tcp)
|
||||
+ {
|
||||
+ char *n = xasprintf ("tcp.%s", probe_name);
|
||||
+ free (probe_name);
|
||||
+ probe_name = n;
|
||||
+ }
|
||||
+ if (do_formerr)
|
||||
+ {
|
||||
+ /* Send a garbage query in an attempt to trigger EDNS
|
||||
+ fallback. */
|
||||
+ char *n = xasprintf ("formerr.%s", probe_name);
|
||||
+ gethostbyname (n);
|
||||
+ free (n);
|
||||
+ }
|
||||
|
||||
- run_test (probe_name);
|
||||
+ run_test (probe_name);
|
||||
|
||||
- free (probe_name);
|
||||
- resolv_test_end (aux);
|
||||
- }
|
||||
+ free (probe_name);
|
||||
+ resolv_test_end (aux);
|
||||
+ }
|
||||
|
||||
free_response_data ();
|
||||
return 0;
|
|
@ -0,0 +1,35 @@
|
|||
commit e4e794841e3140875f2aa86b90e2ada3d61e1244
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Apr 7 13:01:21 2017 +0200
|
||||
|
||||
resolv: Remove IQUERY support
|
||||
|
||||
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
|
||||
index 5a0bb1044b55a643..8279d15de4271c84 100644
|
||||
--- a/resolv/res_mkquery.c
|
||||
+++ b/resolv/res_mkquery.c
|
||||
@@ -188,24 +188,6 @@ res_nmkquery(res_state statp,
|
||||
hp->arcount = htons(1);
|
||||
break;
|
||||
|
||||
- case IQUERY:
|
||||
- /*
|
||||
- * Initialize answer section
|
||||
- */
|
||||
- if (__glibc_unlikely (buflen < 1 + RRFIXEDSZ + datalen))
|
||||
- return (-1);
|
||||
- *cp++ = '\0'; /* no domain name */
|
||||
- NS_PUT16 (type, cp);
|
||||
- NS_PUT16 (class, cp);
|
||||
- NS_PUT32 (0, cp);
|
||||
- NS_PUT16 (datalen, cp);
|
||||
- if (datalen) {
|
||||
- memcpy(cp, data, datalen);
|
||||
- cp += datalen;
|
||||
- }
|
||||
- hp->ancount = htons(1);
|
||||
- break;
|
||||
-
|
||||
default:
|
||||
return (-1);
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
commit e4e5b57d23b4ebdbf773fedba91160158f95af94
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 13:17:49 2017 +0200
|
||||
|
||||
resolv: Move _res deallocation functions to their own file
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index c2a8a3a631f6bb2e..f9d8bceb9b4bc8b0 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -28,7 +28,7 @@ headers := resolv.h \
|
||||
sys/bitypes.h
|
||||
|
||||
routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
|
||||
- res_hconf res_libc res-state res_randomid
|
||||
+ res_hconf res_libc res-state res_randomid res-close
|
||||
|
||||
tests = tst-aton tst-leaks tst-inet_ntop
|
||||
xtests = tst-leaks2
|
||||
diff --git a/resolv/res-close.c b/resolv/res-close.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..73f18d15256c6f87
|
||||
--- /dev/null
|
||||
+++ b/resolv/res-close.c
|
||||
@@ -0,0 +1,137 @@
|
||||
+/* Deallocation functions for the resolver state.
|
||||
+ Copyright (C) 1995-2017 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/>. */
|
||||
+
|
||||
+/*
|
||||
+ * Copyright (c) 1985, 1989, 1993
|
||||
+ * The Regents of the University of California. All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 4. Neither the name of the University nor the names of its contributors
|
||||
+ * may be used to endorse or promote products derived from this software
|
||||
+ * without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies, and that
|
||||
+ * the name of Digital Equipment Corporation not be used in advertising or
|
||||
+ * publicity pertaining to distribution of the document or software without
|
||||
+ * specific, written prior permission.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
+ * SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
+ * SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include <resolv-internal.h>
|
||||
+#include <not-cancel.h>
|
||||
+
|
||||
+/* Close all open sockets. If FREE_ADDR is true, deallocate any
|
||||
+ separately allocated name server addresses. */
|
||||
+void
|
||||
+__res_iclose (res_state statp, bool free_addr)
|
||||
+{
|
||||
+ if (statp->_vcsock >= 0)
|
||||
+ {
|
||||
+ close_not_cancel_no_status (statp->_vcsock);
|
||||
+ statp->_vcsock = -1;
|
||||
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
|
||||
+ }
|
||||
+ for (int ns = 0; ns < statp->nscount; ns++)
|
||||
+ if (statp->_u._ext.nsaddrs[ns] != NULL)
|
||||
+ {
|
||||
+ if (statp->_u._ext.nssocks[ns] != -1)
|
||||
+ {
|
||||
+ close_not_cancel_no_status (statp->_u._ext.nssocks[ns]);
|
||||
+ statp->_u._ext.nssocks[ns] = -1;
|
||||
+ }
|
||||
+ if (free_addr)
|
||||
+ {
|
||||
+ free (statp->_u._ext.nsaddrs[ns]);
|
||||
+ statp->_u._ext.nsaddrs[ns] = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+libc_hidden_def (__res_iclose)
|
||||
+
|
||||
+void
|
||||
+res_nclose (res_state statp)
|
||||
+{
|
||||
+ __res_iclose (statp, true);
|
||||
+}
|
||||
+libc_hidden_def (__res_nclose)
|
||||
+
|
||||
+/* This is called when a thread is exiting to free resources held in _res. */
|
||||
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
||||
+res_thread_freeres (void)
|
||||
+{
|
||||
+ if (_res.nscount == 0)
|
||||
+ /* Never called res_ninit. */
|
||||
+ return;
|
||||
+
|
||||
+ __res_iclose (&_res, true); /* Close any VC sockets. */
|
||||
+
|
||||
+ /* Make sure we do a full re-initialization the next time. */
|
||||
+ _res.options = 0;
|
||||
+}
|
||||
+text_set_element (__libc_thread_subfreeres, res_thread_freeres);
|
||||
+text_set_element (__libc_subfreeres, res_thread_freeres);
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index ef2e7c0db465dba6..eb380d3d56bc018c 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -83,8 +83,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <inet/net-internal.h>
|
||||
|
||||
-#include <not-cancel.h>
|
||||
-
|
||||
/* Options. Should all be left alone. */
|
||||
/* #undef DEBUG */
|
||||
|
||||
@@ -478,56 +476,3 @@ net_mask (struct in_addr in)
|
||||
return (htonl(IN_CLASSB_NET));
|
||||
return (htonl(IN_CLASSC_NET));
|
||||
}
|
||||
-
|
||||
-/*
|
||||
- * This routine is for closing the socket if a virtual circuit is used and
|
||||
- * the program wants to close it. This provides support for endhostent()
|
||||
- * which expects to close the socket.
|
||||
- *
|
||||
- * This routine is not expected to be user visible.
|
||||
- */
|
||||
-void
|
||||
-__res_iclose(res_state statp, bool free_addr) {
|
||||
- int ns;
|
||||
-
|
||||
- if (statp->_vcsock >= 0) {
|
||||
- close_not_cancel_no_status(statp->_vcsock);
|
||||
- statp->_vcsock = -1;
|
||||
- statp->_flags &= ~(RES_F_VC | RES_F_CONN);
|
||||
- }
|
||||
- for (ns = 0; ns < statp->nscount; ns++)
|
||||
- if (statp->_u._ext.nsaddrs[ns]) {
|
||||
- if (statp->_u._ext.nssocks[ns] != -1) {
|
||||
- close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
|
||||
- statp->_u._ext.nssocks[ns] = -1;
|
||||
- }
|
||||
- if (free_addr) {
|
||||
- free (statp->_u._ext.nsaddrs[ns]);
|
||||
- statp->_u._ext.nsaddrs[ns] = NULL;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-libc_hidden_def (__res_iclose)
|
||||
-
|
||||
-void
|
||||
-res_nclose(res_state statp)
|
||||
-{
|
||||
- __res_iclose (statp, true);
|
||||
-}
|
||||
-libc_hidden_def (__res_nclose)
|
||||
-
|
||||
-/* This is called when a thread is exiting to free resources held in _res. */
|
||||
-static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
||||
-res_thread_freeres (void)
|
||||
-{
|
||||
- if (_res.nscount == 0)
|
||||
- /* Never called res_ninit. */
|
||||
- return;
|
||||
-
|
||||
- __res_iclose (&_res, true); /* Close any VC sockets. */
|
||||
-
|
||||
- /* Make sure we do a full re-initialization the next time. */
|
||||
- _res.options = 0;
|
||||
-}
|
||||
-text_set_element (__libc_thread_subfreeres, res_thread_freeres);
|
||||
-text_set_element (__libc_subfreeres, res_thread_freeres);
|
|
@ -0,0 +1,66 @@
|
|||
commit 6da48ca0b2cf328d9ef43c510e74a858c77a1e96
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:32:04 2017 +0200
|
||||
|
||||
resolv: Reformat resolv/res_data.c to GNU style
|
||||
|
||||
diff --git a/resolv/res_data.c b/resolv/res_data.c
|
||||
index 5e7688c706bf8e99..2cafd3805548d8e4 100644
|
||||
--- a/resolv/res_data.c
|
||||
+++ b/resolv/res_data.c
|
||||
@@ -1,3 +1,21 @@
|
||||
+/* Miscellaneous definitions for libresolv.
|
||||
+ Copyright (C) 1995-2017 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/>. */
|
||||
+
|
||||
/*
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium.
|
||||
*
|
||||
@@ -17,18 +35,20 @@
|
||||
|
||||
#include <resolv.h>
|
||||
|
||||
+/* This function belongs to libresolv, which is why it is not included
|
||||
+ in res-close.c. */
|
||||
void
|
||||
-res_close(void) {
|
||||
- /*
|
||||
- * Some stupid programs out there call res_close() before res_init().
|
||||
- * Since _res._vcsock isn't explicitly initialized, these means that
|
||||
- * we could do a close(0), which might lead to some security problems.
|
||||
- * Therefore we check if res_init() was called before by looking at
|
||||
- * the RES_INIT bit in _res.options. If it hasn't been set we bail out
|
||||
- * early. */
|
||||
- if ((_res.options & RES_INIT) == 0)
|
||||
- return;
|
||||
- /* We don't free the name server addresses because we never
|
||||
- did it and it would be done implicitly on shutdown. */
|
||||
- __res_iclose(&_res, false);
|
||||
+__res_close (void)
|
||||
+{
|
||||
+ /* Some programs call res_close before res_init. Since _res._vcsock
|
||||
+ isn't explicitly initialized, these means that we could call
|
||||
+ close (0), which might lead to some security problems. Therefore
|
||||
+ we check if res_init was called before by looking at the RES_INIT
|
||||
+ bit in _res.options. If it hasn't been set we bail out
|
||||
+ early. */
|
||||
+ if ((_res.options & RES_INIT) == 0)
|
||||
+ return;
|
||||
+ /* We don't free the name server addresses because we never did it
|
||||
+ and it would be done implicitly on shutdown. */
|
||||
+ __res_iclose (&_res, false);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
commit 4d4ce84924dbde90294522598212e997b5f719e9
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:29 2017 +0200
|
||||
|
||||
resolv: Remove unused resolv/res_debug.h header file
|
||||
|
||||
diff --git a/resolv/README b/resolv/README
|
||||
index c50025168cd2b99e..514e9bb617e710f1 100644
|
||||
--- a/resolv/README
|
||||
+++ b/resolv/README
|
||||
@@ -114,7 +114,6 @@ src/lib/resolv/
|
||||
res_comp.c
|
||||
res_data.c
|
||||
res_debug.c
|
||||
- res_debug.h
|
||||
res_init.c
|
||||
res_mkquery.c
|
||||
res_query.c
|
||||
diff --git a/resolv/res_debug.h b/resolv/res_debug.h
|
||||
deleted file mode 100644
|
||||
index 2d8ad15d60dc3b79..0000000000000000
|
||||
--- a/resolv/res_debug.h
|
||||
+++ /dev/null
|
||||
@@ -1,34 +0,0 @@
|
||||
-/*
|
||||
- * Copyright (c) 1999 by Internet Software Consortium.
|
||||
- *
|
||||
- * Permission to use, copy, modify, and distribute this software for any
|
||||
- * purpose with or without fee is hereby granted, provided that the above
|
||||
- * copyright notice and this permission notice appear in all copies.
|
||||
- *
|
||||
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
- * SOFTWARE.
|
||||
- */
|
||||
-
|
||||
-#ifndef _RES_DEBUG_H_
|
||||
-#define _RES_DEBUG_H_
|
||||
-
|
||||
-#ifndef DEBUG
|
||||
-# define Dprint(cond, args) /*empty*/
|
||||
-# define DprintQ(cond, args, query, size) /*empty*/
|
||||
-# define Aerror(statp, file, string, error, address) /*empty*/
|
||||
-# define Perror(statp, file, string, error) /*empty*/
|
||||
-#else
|
||||
-# define Dprint(cond, args) if (cond) {fprintf args;} else {}
|
||||
-# define DprintQ(cond, args, query, size) if (cond) {\
|
||||
- fprintf args;\
|
||||
- res_pquery(statp, query, size, stdout);\
|
||||
- } else {}
|
||||
-#endif
|
||||
-
|
||||
-#endif /* _RES_DEBUG_H_ */
|
|
@ -0,0 +1,28 @@
|
|||
commit 0ad970bb13920b6471ccc4503cf1f0d8b2352f05
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue May 9 12:28:01 2017 +0200
|
||||
|
||||
resolv: Use RES_DFLRETRY consistently [BZ #21474]
|
||||
|
||||
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
|
||||
index a4b376f15b0b0e98..c52574f895d4f19d 100644
|
||||
--- a/resolv/res_libc.c
|
||||
+++ b/resolv/res_libc.c
|
||||
@@ -65,7 +65,7 @@ res_init(void) {
|
||||
if (!_res.retrans)
|
||||
_res.retrans = RES_TIMEOUT;
|
||||
if (!_res.retry)
|
||||
- _res.retry = 4;
|
||||
+ _res.retry = RES_DFLRETRY;
|
||||
if (!(_res.options & RES_INIT))
|
||||
_res.options = RES_DEFAULT;
|
||||
else if (_res.nscount > 0)
|
||||
@@ -103,7 +103,7 @@ __res_maybe_init (res_state resp, int preinit)
|
||||
if (!resp->retrans)
|
||||
resp->retrans = RES_TIMEOUT;
|
||||
if (!resp->retry)
|
||||
- resp->retry = 4;
|
||||
+ resp->retry = RES_DFLRETRY;
|
||||
resp->options = RES_DEFAULT;
|
||||
if (!resp->id)
|
||||
resp->id = res_randomid ();
|
|
@ -0,0 +1,691 @@
|
|||
commit 2714c5f3c95f90977167c1d21326d907fb76b419
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 2 15:50:36 2017 +0200
|
||||
|
||||
resolv: Tests for various versions of res_init
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index d41fd4603d7b7d77..0ebb2af795c6fb7b 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -57,6 +57,11 @@ ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
tst-resolv-canonname \
|
||||
|
||||
+# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>.
|
||||
+tests += \
|
||||
+ tst-resolv-res_init \
|
||||
+ tst-resolv-res_init-thread \
|
||||
+
|
||||
endif
|
||||
|
||||
# This test sends millions of packets and is rather slow.
|
||||
@@ -136,6 +141,9 @@ $(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so
|
||||
+$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
|
||||
+ $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-canonname: \
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1d2c475c4b233131
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -0,0 +1,601 @@
|
||||
+/* Test parsing of /etc/resolv.conf. Genric version.
|
||||
+ Copyright (C) 2017 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/>. */
|
||||
+
|
||||
+/* Before including this file, TEST_THREAD has to be defined to 0 or
|
||||
+ 1, depending on whether the threading tests should be compiled
|
||||
+ in. */
|
||||
+
|
||||
+#include <arpa/inet.h>
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <netdb.h>
|
||||
+#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/run_diff.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+#if TEST_THREAD
|
||||
+# include <support/xthread.h>
|
||||
+#endif
|
||||
+
|
||||
+/* This is the host name used to ensure predictable behavior of
|
||||
+ res_init. */
|
||||
+static const char *const test_hostname = "www.example.com";
|
||||
+
|
||||
+/* Path to the test root directory. */
|
||||
+static char *path_chroot;
|
||||
+
|
||||
+/* Path to resolv.conf under path_chroot (outside the chroot). */
|
||||
+static char *path_resolv_conf;
|
||||
+
|
||||
+static void
|
||||
+prepare (int argc, char **argv)
|
||||
+{
|
||||
+ path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
|
||||
+ if (mkdtemp (path_chroot) == NULL)
|
||||
+ FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", path_chroot);
|
||||
+ add_temp_file (path_chroot);
|
||||
+
|
||||
+ /* Create the /etc directory in the chroot environment. */
|
||||
+ char *path_etc = xasprintf ("%s/etc", path_chroot);
|
||||
+ xmkdir (path_etc, 0777);
|
||||
+ add_temp_file (path_etc);
|
||||
+
|
||||
+ /* Create an empty resolv.conf file. */
|
||||
+ path_resolv_conf = xasprintf ("%s/resolv.conf", path_etc);
|
||||
+ add_temp_file (path_resolv_conf);
|
||||
+ support_write_file_string (path_resolv_conf, "");
|
||||
+
|
||||
+ free (path_etc);
|
||||
+
|
||||
+ /* valgrind needs a temporary directory in the chroot. */
|
||||
+ {
|
||||
+ char *path_tmp = xasprintf ("%s/tmp", path_chroot);
|
||||
+ xmkdir (path_tmp, 0777);
|
||||
+ add_temp_file (path_tmp);
|
||||
+ free (path_tmp);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Verify that the chroot environment has been set up. */
|
||||
+static void
|
||||
+check_chroot_working (void *closure)
|
||||
+{
|
||||
+ xchroot (path_chroot);
|
||||
+ FILE *fp = xfopen (_PATH_RESCONF, "r");
|
||||
+ xfclose (fp);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (res_init () == 0);
|
||||
+ TEST_VERIFY (_res.options & RES_INIT);
|
||||
+
|
||||
+ char buf[100];
|
||||
+ if (gethostname (buf, sizeof (buf)) < 0)
|
||||
+ FAIL_EXIT1 ("gethostname: %m");
|
||||
+ if (strcmp (buf, test_hostname) != 0)
|
||||
+ FAIL_EXIT1 ("unexpected host name: %s", buf);
|
||||
+}
|
||||
+
|
||||
+/* If FLAG is set in *OPTIONS, write NAME to FP, and clear it in
|
||||
+ *OPTIONS. */
|
||||
+static void
|
||||
+print_option_flag (FILE *fp, int *options, int flag, const char *name)
|
||||
+{
|
||||
+ if (*options & flag)
|
||||
+ {
|
||||
+ fprintf (fp, " %s", name);
|
||||
+ *options &= ~flag;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Write a decoded version of the resolver configuration *RESP to the
|
||||
+ stream FP. */
|
||||
+static void
|
||||
+print_resp (FILE *fp, res_state resp)
|
||||
+{
|
||||
+ /* The options directive. */
|
||||
+ {
|
||||
+ /* RES_INIT is used internally for tracking initialization. */
|
||||
+ TEST_VERIFY (resp->options & RES_INIT);
|
||||
+ /* Also mask out other default flags which cannot be set through
|
||||
+ the options directive. */
|
||||
+ int options
|
||||
+ = resp->options & ~(RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH);
|
||||
+ if (options != 0
|
||||
+ || resp->ndots != 1
|
||||
+ || resp->retrans != RES_TIMEOUT
|
||||
+ || resp->retry != RES_DFLRETRY)
|
||||
+ {
|
||||
+ fputs ("options", fp);
|
||||
+ if (resp->ndots != 1)
|
||||
+ fprintf (fp, " ndots:%d", resp->ndots);
|
||||
+ if (resp->retrans != RES_TIMEOUT)
|
||||
+ fprintf (fp, " timeout:%d", resp->retrans);
|
||||
+ if (resp->retry != RES_DFLRETRY)
|
||||
+ fprintf (fp, " attempts:%d", resp->retry);
|
||||
+ 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_USE_EDNS0, "edns0");
|
||||
+ print_option_flag (fp, &options, RES_SNGLKUP,
|
||||
+ "single-request");
|
||||
+ print_option_flag (fp, &options, RES_SNGLKUPREOP,
|
||||
+ "single-request-reopen");
|
||||
+ print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query");
|
||||
+ fputc ('\n', fp);
|
||||
+ if (options != 0)
|
||||
+ fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* The search and domain directives. */
|
||||
+ if (resp->dnsrch[0] != NULL)
|
||||
+ {
|
||||
+ fputs ("search", fp);
|
||||
+ for (int i = 0; i < MAXDNSRCH && resp->dnsrch[i] != NULL; ++i)
|
||||
+ {
|
||||
+ fputc (' ', fp);
|
||||
+ fputs (resp->dnsrch[i], fp);
|
||||
+ }
|
||||
+ fputc ('\n', fp);
|
||||
+ }
|
||||
+ else if (resp->defdname[0] != '\0')
|
||||
+ fprintf (fp, "domain %s\n", resp->defdname);
|
||||
+
|
||||
+ /* The sortlist directive. */
|
||||
+ if (resp->nsort > 0)
|
||||
+ {
|
||||
+ fputs ("sortlist", fp);
|
||||
+ for (int i = 0; i < resp->nsort && i < MAXRESOLVSORT; ++i)
|
||||
+ {
|
||||
+ char net[20];
|
||||
+ if (inet_ntop (AF_INET, &resp->sort_list[i].addr,
|
||||
+ net, sizeof (net)) == NULL)
|
||||
+ FAIL_EXIT1 ("inet_ntop: %m\n");
|
||||
+ char mask[20];
|
||||
+ if (inet_ntop (AF_INET, &resp->sort_list[i].mask,
|
||||
+ mask, sizeof (mask)) == NULL)
|
||||
+ FAIL_EXIT1 ("inet_ntop: %m\n");
|
||||
+ fprintf (fp, " %s/%s", net, mask);
|
||||
+ }
|
||||
+ fputc ('\n', fp);
|
||||
+ }
|
||||
+
|
||||
+ /* The nameserver directives. */
|
||||
+ for (size_t i = 0; i < resp->nscount; ++i)
|
||||
+ {
|
||||
+ char host[NI_MAXHOST];
|
||||
+ char service[NI_MAXSERV];
|
||||
+
|
||||
+ /* See get_nsaddr in res_send.c. */
|
||||
+ void *addr;
|
||||
+ size_t addrlen;
|
||||
+ if (resp->nsaddr_list[i].sin_family == 0
|
||||
+ && resp->_u._ext.nsaddrs[i] != NULL)
|
||||
+ {
|
||||
+ addr = resp->_u._ext.nsaddrs[i];
|
||||
+ addrlen = sizeof (*resp->_u._ext.nsaddrs[i]);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ addr = &resp->nsaddr_list[i];
|
||||
+ addrlen = sizeof (resp->nsaddr_list[i]);
|
||||
+ }
|
||||
+
|
||||
+ int ret = getnameinfo (addr, addrlen,
|
||||
+ host, sizeof (host), service, sizeof (service),
|
||||
+ NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ if (ret == EAI_SYSTEM)
|
||||
+ fprintf (fp, "; error: getnameinfo: %m\n");
|
||||
+ else
|
||||
+ fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret));
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ fprintf (fp, "nameserver %s\n", host);
|
||||
+ if (strcmp (service, "53") != 0)
|
||||
+ fprintf (fp, "; unrepresentable port number %s\n\n", service);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY (!ferror (fp));
|
||||
+}
|
||||
+
|
||||
+/* Parameters of one test case. */
|
||||
+struct test_case
|
||||
+{
|
||||
+ /* A short, descriptive name of the test. */
|
||||
+ const char *name;
|
||||
+
|
||||
+ /* The contents of the /etc/resolv.conf file. */
|
||||
+ const char *conf;
|
||||
+
|
||||
+ /* The expected output from print_resp. */
|
||||
+ const char *expected;
|
||||
+
|
||||
+ /* Setting for the LOCALDOMAIN environment variable. NULL if the
|
||||
+ variable is not to be set. */
|
||||
+ const char *localdomain;
|
||||
+
|
||||
+ /* Setting for the RES_OPTIONS environment variable. NULL if the
|
||||
+ variable is not to be set. */
|
||||
+ const char *res_options;
|
||||
+};
|
||||
+
|
||||
+enum test_init
|
||||
+{
|
||||
+ test_init,
|
||||
+ test_ninit,
|
||||
+ test_mkquery,
|
||||
+ test_gethostbyname,
|
||||
+ test_getaddrinfo,
|
||||
+ test_init_method_last = test_getaddrinfo
|
||||
+};
|
||||
+
|
||||
+/* Closure argument for run_res_init. */
|
||||
+struct test_context
|
||||
+{
|
||||
+ enum test_init init;
|
||||
+ const struct test_case *t;
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+setup_nss_dns_and_chroot (void)
|
||||
+{
|
||||
+ /* Load nss_dns outside of the chroot. */
|
||||
+ if (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) == NULL)
|
||||
+ FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ());
|
||||
+ xchroot (path_chroot);
|
||||
+ /* Force the use of nss_dns. */
|
||||
+ __nss_configure_lookup ("hosts", "dns");
|
||||
+}
|
||||
+
|
||||
+/* Run res_ninit or res_init in a subprocess and dump the parsed
|
||||
+ resolver state to standard output. */
|
||||
+static void
|
||||
+run_res_init (void *closure)
|
||||
+{
|
||||
+ struct test_context *ctx = closure;
|
||||
+ TEST_VERIFY (getenv ("LOCALDOMAIN") == NULL);
|
||||
+ TEST_VERIFY (getenv ("RES_OPTIONS") == NULL);
|
||||
+ if (ctx->t->localdomain != NULL)
|
||||
+ setenv ("LOCALDOMAIN", ctx->t->localdomain, 1);
|
||||
+ if (ctx->t->res_options != NULL)
|
||||
+ setenv ("RES_OPTIONS", ctx->t->res_options, 1);
|
||||
+
|
||||
+ switch (ctx->init)
|
||||
+ {
|
||||
+ case test_init:
|
||||
+ xchroot (path_chroot);
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ print_resp (stdout, &_res);
|
||||
+ return;
|
||||
+
|
||||
+ case test_ninit:
|
||||
+ xchroot (path_chroot);
|
||||
+ res_state resp = xmalloc (sizeof (*resp));
|
||||
+ memset (resp, 0, sizeof (*resp));
|
||||
+ TEST_VERIFY (res_ninit (resp) == 0);
|
||||
+ print_resp (stdout, resp);
|
||||
+ res_nclose (resp);
|
||||
+ free (resp);
|
||||
+ return;
|
||||
+
|
||||
+ case test_mkquery:
|
||||
+ xchroot (path_chroot);
|
||||
+ unsigned char buf[512];
|
||||
+ TEST_VERIFY (res_mkquery (QUERY, "www.example",
|
||||
+ C_IN, ns_t_a, NULL, 0,
|
||||
+ NULL, buf, sizeof (buf)) > 0);
|
||||
+ print_resp (stdout, &_res);
|
||||
+ return;
|
||||
+
|
||||
+ case test_gethostbyname:
|
||||
+ setup_nss_dns_and_chroot ();
|
||||
+ /* Trigger implicit initialization of the _res structure. The
|
||||
+ actual lookup result is immaterial. */
|
||||
+ (void )gethostbyname ("www.example");
|
||||
+ print_resp (stdout, &_res);
|
||||
+ return;
|
||||
+
|
||||
+ case test_getaddrinfo:
|
||||
+ setup_nss_dns_and_chroot ();
|
||||
+ /* Trigger implicit initialization of the _res structure. The
|
||||
+ actual lookup result is immaterial. */
|
||||
+ struct addrinfo *ai;
|
||||
+ (void) getaddrinfo ("www.example", NULL, NULL, &ai);
|
||||
+ print_resp (stdout, &_res);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ FAIL_EXIT1 ("invalid init method %d", ctx->init);
|
||||
+}
|
||||
+
|
||||
+#if TEST_THREAD
|
||||
+/* Helper function which calls run_res_init from a thread. */
|
||||
+static void *
|
||||
+run_res_init_thread_func (void *closure)
|
||||
+{
|
||||
+ run_res_init (closure);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Variant of res_run_init which runs the function on a non-main
|
||||
+ thread. */
|
||||
+static void
|
||||
+run_res_init_on_thread (void *closure)
|
||||
+{
|
||||
+ xpthread_join (xpthread_create (NULL, run_res_init_thread_func, closure));
|
||||
+}
|
||||
+#endif /* TEST_THREAD */
|
||||
+
|
||||
+struct test_case test_cases[] =
|
||||
+ {
|
||||
+ {.name = "empty file",
|
||||
+ .conf = "",
|
||||
+ .expected = "search example.com\n"
|
||||
+ "nameserver 127.0.0.1\n"
|
||||
+ },
|
||||
+ {.name = "empty file with LOCALDOMAIN",
|
||||
+ .conf = "",
|
||||
+ .expected = "search example.net\n"
|
||||
+ "nameserver 127.0.0.1\n",
|
||||
+ .localdomain = "example.net",
|
||||
+ },
|
||||
+ {.name = "empty file with RES_OPTIONS",
|
||||
+ .conf = "",
|
||||
+ .expected = "options attempts:5 edns0\n"
|
||||
+ "search example.com\n"
|
||||
+ "nameserver 127.0.0.1\n",
|
||||
+ .res_options = "edns0 attempts:5",
|
||||
+ },
|
||||
+ {.name = "empty file with RES_OPTIONS and LOCALDOMAIN",
|
||||
+ .conf = "",
|
||||
+ .expected = "options attempts:5 edns0\n"
|
||||
+ "search example.org\n"
|
||||
+ "nameserver 127.0.0.1\n",
|
||||
+ .localdomain = "example.org",
|
||||
+ .res_options = "edns0 attempts:5",
|
||||
+ },
|
||||
+ {.name = "basic",
|
||||
+ .conf = "domain example.net\n"
|
||||
+ "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ },
|
||||
+ {.name = "whitespace",
|
||||
+ .conf = "# This test covers comment and whitespace processing "
|
||||
+ " (trailing whitespace,\n"
|
||||
+ "# missing newline at end of file).\n"
|
||||
+ "\n"
|
||||
+ "domain example.net\n"
|
||||
+ ";search commented out\n"
|
||||
+ "search corp.example.com\texample.com\n"
|
||||
+ "#nameserver 192.0.2.3\n"
|
||||
+ "nameserver 192.0.2.1 \n"
|
||||
+ "nameserver 192.0.2.2", /* No \n at end of file. */
|
||||
+ .expected = "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 192.0.2.2\n"
|
||||
+ },
|
||||
+ {.name = "option values, multiple servers",
|
||||
+ .conf = "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n"
|
||||
+ "domain example.net\n"
|
||||
+ ";domain comment\n"
|
||||
+ "search corp.example.com\texample.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver ::1\n"
|
||||
+ "nameserver 192.0.2.2\n",
|
||||
+ .expected = "options ndots:3 timeout:19 attempts:5 inet6 edns0\n"
|
||||
+ "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver ::1\n"
|
||||
+ "nameserver 192.0.2.2\n"
|
||||
+ },
|
||||
+ {.name = "out-of-range option vales",
|
||||
+ .conf = "options use-vc timeout:999 attempts:999 ndots:99\n"
|
||||
+ "search example.com\n",
|
||||
+ .expected = "options ndots:15 timeout:30 attempts:5 use-vc\n"
|
||||
+ "search example.com\n"
|
||||
+ "nameserver 127.0.0.1\n"
|
||||
+ },
|
||||
+ {.name = "repeated directives",
|
||||
+ .conf = "options ndots:3 use-vc\n"
|
||||
+ "options edns0 ndots:2\n"
|
||||
+ "domain corp.example\n"
|
||||
+ "search example.net corp.example.com example.com\n"
|
||||
+ "search example.org\n"
|
||||
+ "search\n",
|
||||
+ .expected = "options ndots:2 use-vc edns0\n"
|
||||
+ "search example.org\n"
|
||||
+ "nameserver 127.0.0.1\n"
|
||||
+ },
|
||||
+ {.name = "many name servers, sortlist",
|
||||
+ .conf = "options single-request\n"
|
||||
+ "search example.org example.com example.net corp.example.com\n"
|
||||
+ "sortlist 192.0.2.0/255.255.255.0\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 192.0.2.2\n"
|
||||
+ "nameserver 192.0.2.3\n"
|
||||
+ "nameserver 192.0.2.4\n"
|
||||
+ "nameserver 192.0.2.5\n"
|
||||
+ "nameserver 192.0.2.6\n"
|
||||
+ "nameserver 192.0.2.7\n"
|
||||
+ "nameserver 192.0.2.8\n",
|
||||
+ .expected = "options single-request\n"
|
||||
+ "search example.org example.com example.net corp.example.com\n"
|
||||
+ "sortlist 192.0.2.0/255.255.255.0\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 192.0.2.2\n"
|
||||
+ "nameserver 192.0.2.3\n"
|
||||
+ },
|
||||
+ {.name = "IPv4 and IPv6 nameservers",
|
||||
+ .conf = "options single-request\n"
|
||||
+ "search example.org example.com example.net corp.example.com"
|
||||
+ " legacy.example.com\n"
|
||||
+ "sortlist 192.0.2.0\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 2001:db8::2\n"
|
||||
+ "nameserver 192.0.2.3\n"
|
||||
+ "nameserver 2001:db8::4\n"
|
||||
+ "nameserver 192.0.2.5\n"
|
||||
+ "nameserver 2001:db8::6\n"
|
||||
+ "nameserver 192.0.2.7\n"
|
||||
+ "nameserver 2001:db8::8\n",
|
||||
+ .expected = "options single-request\n"
|
||||
+ "search example.org example.com example.net corp.example.com"
|
||||
+ " legacy.example.com\n"
|
||||
+ "sortlist 192.0.2.0/255.255.255.0\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 2001:db8::2\n"
|
||||
+ "nameserver 192.0.2.3\n"
|
||||
+ },
|
||||
+ {.name = "garbage after nameserver",
|
||||
+ .conf = "nameserver 192.0.2.1 garbage\n"
|
||||
+ "nameserver 192.0.2.2:5353\n"
|
||||
+ "nameserver 192.0.2.3 5353\n",
|
||||
+ .expected = "search example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 192.0.2.3\n"
|
||||
+ },
|
||||
+ {.name = "RES_OPTIONS is cummulative",
|
||||
+ .conf = "options timeout:7 ndots:2 use-vc\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "options ndots:3 timeout:7 attempts:5 use-vc edns0\n"
|
||||
+ "search example.com\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .res_options = "attempts:5 ndots:3 edns0 ",
|
||||
+ },
|
||||
+ { NULL }
|
||||
+ };
|
||||
+
|
||||
+/* Run the indicated test case. This function assumes that the chroot
|
||||
+ contents has already been set up. */
|
||||
+static void
|
||||
+test_file_contents (const struct test_case *t)
|
||||
+{
|
||||
+#if TEST_THREAD
|
||||
+ for (int do_thread = 0; do_thread < 2; ++do_thread)
|
||||
+#endif
|
||||
+ for (int init_method = 0; init_method <= test_init_method_last;
|
||||
+ ++init_method)
|
||||
+ {
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: testing init method %d\n", init_method);
|
||||
+ struct test_context ctx = { .init = init_method, .t = t };
|
||||
+ void (*func) (void *) = run_res_init;
|
||||
+#if TEST_THREAD
|
||||
+ if (do_thread)
|
||||
+ func = run_res_init_on_thread;
|
||||
+#endif
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprocess (func, &ctx);
|
||||
+ if (strcmp (proc.out.buffer, t->expected) != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: output mismatch for %s\n", t->name);
|
||||
+ support_run_diff ("expected", t->expected,
|
||||
+ "actual", proc.out.buffer);
|
||||
+ }
|
||||
+ support_capture_subprocess_check (&proc, t->name, 0,
|
||||
+ sc_allow_stdout);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ support_become_root ();
|
||||
+ support_enter_network_namespace ();
|
||||
+ if (!support_in_uts_namespace () || !support_can_chroot ())
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ /* We are in an UTS namespace, so we can set the host name without
|
||||
+ altering the state of the entire system. */
|
||||
+ if (sethostname (test_hostname, strlen (test_hostname)) != 0)
|
||||
+ FAIL_EXIT1 ("sethostname: %m");
|
||||
+
|
||||
+ /* These environment variables affect resolv.conf parsing. */
|
||||
+ unsetenv ("LOCALDOMAIN");
|
||||
+ unsetenv ("RES_OPTIONS");
|
||||
+
|
||||
+ /* Ensure that the chroot setup worked. */
|
||||
+ {
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprocess (check_chroot_working, NULL);
|
||||
+ support_capture_subprocess_check (&proc, "chroot", 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ }
|
||||
+
|
||||
+ for (size_t i = 0; test_cases[i].name != NULL; ++i)
|
||||
+ {
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: running test: %s\n", test_cases[i].name);
|
||||
+ TEST_VERIFY (test_cases[i].conf != NULL);
|
||||
+ TEST_VERIFY (test_cases[i].expected != NULL);
|
||||
+
|
||||
+ support_write_file_string (path_resolv_conf, test_cases[i].conf);
|
||||
+
|
||||
+ test_file_contents (&test_cases[i]);
|
||||
+
|
||||
+ /* The expected output from the empty file test is used for
|
||||
+ further tests. */
|
||||
+ if (test_cases[i].conf[0] == '\0')
|
||||
+ {
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: special test: missing file\n");
|
||||
+ TEST_VERIFY (unlink (path_resolv_conf) == 0);
|
||||
+ test_file_contents (&test_cases[i]);
|
||||
+
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: special test: dangling symbolic link\n");
|
||||
+ TEST_VERIFY (symlink ("does-not-exist", path_resolv_conf) == 0);
|
||||
+ test_file_contents (&test_cases[i]);
|
||||
+ TEST_VERIFY (unlink (path_resolv_conf) == 0);
|
||||
+
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: special test: unreadable file\n");
|
||||
+ support_write_file_string (path_resolv_conf, "");
|
||||
+ TEST_VERIFY (chmod (path_resolv_conf, 0) == 0);
|
||||
+ test_file_contents (&test_cases[i]);
|
||||
+
|
||||
+ /* Restore the empty file. */
|
||||
+ TEST_VERIFY (unlink (path_resolv_conf) == 0);
|
||||
+ support_write_file_string (path_resolv_conf, "");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ free (path_chroot);
|
||||
+ path_chroot = NULL;
|
||||
+ free (path_resolv_conf);
|
||||
+ path_resolv_conf = NULL;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define PREPARE prepare
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/resolv/tst-resolv-res_init-thread.c b/resolv/tst-resolv-res_init-thread.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f47ac34f7fc7a6c8
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-res_init-thread.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* Test parsing of /etc/resolv.conf, threading version.
|
||||
+ Copyright (C) 2017 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/>. */
|
||||
+
|
||||
+#define TEST_THREAD 1
|
||||
+#include "tst-resolv-res_init-skeleton.c"
|
||||
diff --git a/resolv/tst-resolv-res_init.c b/resolv/tst-resolv-res_init.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..40c0154eca7363cb
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-res_init.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/* Test parsing of /etc/resolv.conf, non-threading version.
|
||||
+ Copyright (C) 2017 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/>. */
|
||||
+
|
||||
+#define TEST_THREAD 0
|
||||
+#include "tst-resolv-res_init-skeleton.c"
|
|
@ -0,0 +1,66 @@
|
|||
commit ded603542a8af41dc0c45af883d52390683f63aa
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:47 2017 +0200
|
||||
|
||||
resolv: Move res_isourserver, res_send from res_data.c to res_send.c
|
||||
|
||||
diff --git a/resolv/res_data.c b/resolv/res_data.c
|
||||
index d05389e1347a57ab..b790b4b725bc9edd 100644
|
||||
--- a/resolv/res_data.c
|
||||
+++ b/resolv/res_data.c
|
||||
@@ -45,22 +45,6 @@ res_query(const char *name, /* domain name */
|
||||
return (res_nquery(&_res, name, class, type, answer, anslen));
|
||||
}
|
||||
|
||||
-int
|
||||
-res_isourserver(const struct sockaddr_in *inp) {
|
||||
- return (res_ourserver_p(&_res, (const struct sockaddr_in6 *) inp));
|
||||
-}
|
||||
-
|
||||
-int
|
||||
-res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
|
||||
- if (__res_maybe_init (&_res, 1) == -1) {
|
||||
- /* errno should have been set by res_init() in this case. */
|
||||
- return (-1);
|
||||
- }
|
||||
-
|
||||
- return (res_nsend(&_res, buf, buflen, ans, anssiz));
|
||||
-}
|
||||
-
|
||||
-
|
||||
void
|
||||
res_close(void) {
|
||||
/*
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 18308709542da6e6..2e0b6c226105400a 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -244,6 +244,12 @@ res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
+int
|
||||
+res_isourserver (const struct sockaddr_in *inp)
|
||||
+{
|
||||
+ return res_ourserver_p (&_res, (const struct sockaddr_in6 *) inp);
|
||||
+}
|
||||
+
|
||||
/* int
|
||||
* res_nameinquery(name, type, class, buf, eom)
|
||||
* look for (name,type,class) in the query section of packet (buf,eom)
|
||||
@@ -545,6 +551,15 @@ res_nsend(res_state statp,
|
||||
}
|
||||
libresolv_hidden_def (res_nsend)
|
||||
|
||||
+int
|
||||
+res_send (const unsigned char *buf, int buflen, unsigned char *ans, int anssiz)
|
||||
+{
|
||||
+ if (__res_maybe_init (&_res, 1) == -1)
|
||||
+ /* errno should have been set by res_init in this case. */
|
||||
+ return -1;
|
||||
+ return res_nsend (&_res, buf, buflen, ans, anssiz);
|
||||
+}
|
||||
+
|
||||
/* Private */
|
||||
|
||||
static struct sockaddr *
|
|
@ -0,0 +1,184 @@
|
|||
commit b87d47396f8e036a111fed8816254cfe1cf87cb2
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 23 18:10:41 2017 +0200
|
||||
|
||||
resolv/res_libc.c: Reformat to GNU style
|
||||
|
||||
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
|
||||
index 5202b756ff17518a..4b979f39a7c8e8ba 100644
|
||||
--- a/resolv/res_libc.c
|
||||
+++ b/resolv/res_libc.c
|
||||
@@ -1,3 +1,21 @@
|
||||
+/* Definitions related to res_init linked into libc instead of libresolv.
|
||||
+ Copyright (C) 1995-2017 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/>. */
|
||||
+
|
||||
/*
|
||||
* Copyright (c) 1995-1999 by Internet Software Consortium.
|
||||
*
|
||||
@@ -15,9 +33,6 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
-/* This file contains the definitions related to res_init which are
|
||||
- linked into libc instead of libresolv. */
|
||||
-
|
||||
#include <atomic.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
@@ -40,74 +55,78 @@ __libc_lock_define_initialized (static, lock);
|
||||
#endif
|
||||
|
||||
int
|
||||
-res_init(void) {
|
||||
- /*
|
||||
- * 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.
|
||||
- *
|
||||
- * _res.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 (!_res.retrans)
|
||||
- _res.retrans = RES_TIMEOUT;
|
||||
- if (!_res.retry)
|
||||
- _res.retry = RES_DFLRETRY;
|
||||
- if (!(_res.options & RES_INIT))
|
||||
- _res.options = RES_DEFAULT;
|
||||
- else if (_res.nscount > 0)
|
||||
- __res_iclose (&_res, true); /* Close any VC sockets. */
|
||||
-
|
||||
- /*
|
||||
- * 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.id)
|
||||
- _res.id = res_randomid();
|
||||
-
|
||||
- atomicinclock (lock);
|
||||
- /* Request all threads to re-initialize their resolver states,
|
||||
- resolv.conf might have changed. */
|
||||
- atomicinc (__res_initstamp);
|
||||
- atomicincunlock (lock);
|
||||
-
|
||||
- return (__res_vinit(&_res, 1));
|
||||
+res_init (void)
|
||||
+{
|
||||
+ /* 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.
|
||||
+
|
||||
+ _res.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 (!_res.retrans)
|
||||
+ _res.retrans = RES_TIMEOUT;
|
||||
+ if (!_res.retry)
|
||||
+ _res.retry = RES_DFLRETRY;
|
||||
+ if (!(_res.options & RES_INIT))
|
||||
+ _res.options = RES_DEFAULT;
|
||||
+ else if (_res.nscount > 0)
|
||||
+ __res_iclose (&_res, true); /* Close any VC sockets. */
|
||||
+
|
||||
+ /* 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.id)
|
||||
+ _res.id = res_randomid ();
|
||||
+
|
||||
+ atomicinclock (lock);
|
||||
+ /* Request all threads to re-initialize their resolver states,
|
||||
+ resolv.conf might have changed. */
|
||||
+ atomicinc (__res_initstamp);
|
||||
+ atomicincunlock (lock);
|
||||
+
|
||||
+ return __res_vinit (&_res, 1);
|
||||
}
|
||||
|
||||
-/* Initialize resp if RES_INIT is not yet set or if res_init in some other
|
||||
- thread requested re-initializing. */
|
||||
+/* Initialize *RESP if RES_INIT is not yet set in RESP->options, or if
|
||||
+ res_init in some other thread requested re-initializing. */
|
||||
int
|
||||
__res_maybe_init (res_state resp, int preinit)
|
||||
{
|
||||
- if (resp->options & RES_INIT) {
|
||||
- if (__res_initstamp != resp->_u._ext.initstamp) {
|
||||
- if (resp->nscount > 0)
|
||||
- __res_iclose (resp, true);
|
||||
- return __res_vinit (resp, 1);
|
||||
- }
|
||||
- return 0;
|
||||
- } else if (preinit) {
|
||||
- if (!resp->retrans)
|
||||
- resp->retrans = RES_TIMEOUT;
|
||||
- if (!resp->retry)
|
||||
- resp->retry = RES_DFLRETRY;
|
||||
- resp->options = RES_DEFAULT;
|
||||
- if (!resp->id)
|
||||
- resp->id = res_randomid ();
|
||||
- return __res_vinit (resp, 1);
|
||||
- } else
|
||||
- return __res_ninit (resp);
|
||||
+ if (resp->options & RES_INIT)
|
||||
+ {
|
||||
+ if (__res_initstamp != resp->_u._ext.initstamp)
|
||||
+ {
|
||||
+ if (resp->nscount > 0)
|
||||
+ __res_iclose (resp, true);
|
||||
+ return __res_vinit (resp, 1);
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+ else if (preinit)
|
||||
+ {
|
||||
+ if (!resp->retrans)
|
||||
+ resp->retrans = RES_TIMEOUT;
|
||||
+ if (!resp->retry)
|
||||
+ resp->retry = RES_DFLRETRY;
|
||||
+ resp->options = RES_DEFAULT;
|
||||
+ if (!resp->id)
|
||||
+ resp->id = res_randomid ();
|
||||
+ return __res_vinit (resp, 1);
|
||||
+ }
|
||||
+ else
|
||||
+ return __res_ninit (resp);
|
||||
}
|
||||
libc_hidden_def (__res_maybe_init)
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
commit 7ab27b76d2d47942bc2ed74f674b62c3a51994bb
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:02 2017 +0200
|
||||
|
||||
resolv: Remove DEBUG macro from resolv/res_mkquery.c
|
||||
|
||||
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
|
||||
index 8279d15de4271c84..2e3aa39cf088adf9 100644
|
||||
--- a/resolv/res_mkquery.c
|
||||
+++ b/resolv/res_mkquery.c
|
||||
@@ -1,3 +1,21 @@
|
||||
+/* Creation of DNS query packets.
|
||||
+ Copyright (C) 1995-2017 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/>. */
|
||||
+
|
||||
/*
|
||||
* Copyright (c) 1985, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@@ -70,13 +88,9 @@
|
||||
#include <arpa/nameser.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv/resolv-internal.h>
|
||||
-#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
-/* Options. Leave them on. */
|
||||
-/* #define DEBUG */
|
||||
-
|
||||
#include <hp-timing.h>
|
||||
#include <stdint.h>
|
||||
#if HP_TIMING_AVAIL
|
||||
@@ -107,11 +121,6 @@ res_nmkquery(res_state statp,
|
||||
|| type < 0 || type > 65535)
|
||||
return -1;
|
||||
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_nmkquery(%s, %s, %s, %s)\n",
|
||||
- _res_opcodes[op], dname, p_class(class), p_type(type));
|
||||
-#endif
|
||||
/*
|
||||
* Initialize header fields.
|
||||
*/
|
||||
@@ -210,11 +219,6 @@ __res_nopt(res_state statp,
|
||||
{
|
||||
u_int16_t flags = 0;
|
||||
|
||||
-#ifdef DEBUG
|
||||
- if ((statp->options & RES_DEBUG) != 0U)
|
||||
- printf(";; res_nopt()\n");
|
||||
-#endif
|
||||
-
|
||||
HEADER *hp = (HEADER *) buf;
|
||||
u_char *cp = buf + n0;
|
||||
u_char *ep = buf + buflen;
|
||||
@@ -253,10 +257,6 @@ __res_nopt(res_state statp,
|
||||
*cp++ = 0; /* EDNS version */
|
||||
|
||||
if (statp->options & RES_USE_DNSSEC) {
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_opt()... ENDS0 DNSSEC\n");
|
||||
-#endif
|
||||
flags |= NS_OPT_DNSSEC_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,323 @@
|
|||
commit 74084febc4b668ca2258d88cade6fa5e28364ac6
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:12 2017 +0200
|
||||
|
||||
resolv: Reformat resolv/res_mkquery.c to GNU style
|
||||
|
||||
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
|
||||
index 2e3aa39cf088adf9..a601b6988545a149 100644
|
||||
--- a/resolv/res_mkquery.c
|
||||
+++ b/resolv/res_mkquery.c
|
||||
@@ -97,172 +97,168 @@
|
||||
# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
|
||||
#endif
|
||||
|
||||
-/*
|
||||
- * Form all types of queries.
|
||||
- * Returns the size of the result or -1.
|
||||
- */
|
||||
+/* Form all types of queries. Returns the size of the result or -1 on
|
||||
+ error.
|
||||
+
|
||||
+ STATP points to an initialized resolver state. OP is the opcode of
|
||||
+ the query. DNAME is the domain. CLASS and TYPE are the DNS query
|
||||
+ class and type. DATA can be NULL; otherwise, it is a pointer to a
|
||||
+ domain name which is included in the generated packet (if op ==
|
||||
+ NS_NOTIFY_OP). BUF must point to the out buffer of BUFLEN bytes.
|
||||
+
|
||||
+ DATALEN and NEWRR_IN are currently ignored. */
|
||||
int
|
||||
-res_nmkquery(res_state statp,
|
||||
- int op, /* opcode of query */
|
||||
- const char *dname, /* domain name */
|
||||
- int class, int type, /* class and type of query */
|
||||
- const u_char *data, /* resource record data */
|
||||
- int datalen, /* length of data */
|
||||
- const u_char *newrr_in, /* new rr for modify or append */
|
||||
- u_char *buf, /* buffer to put query */
|
||||
- int buflen) /* size of buffer */
|
||||
+res_nmkquery (res_state statp, int op, const char *dname,
|
||||
+ int class, int type,
|
||||
+ const unsigned char *data, int datalen,
|
||||
+ const unsigned char *newrr_in,
|
||||
+ unsigned char *buf, int buflen)
|
||||
{
|
||||
- HEADER *hp;
|
||||
- u_char *cp;
|
||||
- int n;
|
||||
- u_char *dnptrs[20], **dpp, **lastdnptr;
|
||||
+ HEADER *hp;
|
||||
+ unsigned char *cp;
|
||||
+ int n;
|
||||
+ unsigned char *dnptrs[20], **dpp, **lastdnptr;
|
||||
|
||||
- if (class < 0 || class > 65535
|
||||
- || type < 0 || type > 65535)
|
||||
- return -1;
|
||||
+ if (class < 0 || class > 65535 || type < 0 || type > 65535)
|
||||
+ return -1;
|
||||
|
||||
- /*
|
||||
- * Initialize header fields.
|
||||
- */
|
||||
- if ((buf == NULL) || (buflen < HFIXEDSZ))
|
||||
- return (-1);
|
||||
- memset(buf, 0, HFIXEDSZ);
|
||||
- hp = (HEADER *) buf;
|
||||
- /* We randomize the IDs every time. The old code just
|
||||
- incremented by one after the initial randomization which
|
||||
- still predictable if the application does multiple
|
||||
- requests. */
|
||||
- int randombits;
|
||||
- do
|
||||
- {
|
||||
+ /* Initialize header fields. */
|
||||
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
|
||||
+ return -1;
|
||||
+ memset (buf, 0, HFIXEDSZ);
|
||||
+ hp = (HEADER *) buf;
|
||||
+ /* We randomize the IDs every time. The old code just incremented
|
||||
+ by one after the initial randomization which still predictable if
|
||||
+ the application does multiple requests. */
|
||||
+ int randombits;
|
||||
+ do
|
||||
+ {
|
||||
#ifdef RANDOM_BITS
|
||||
- RANDOM_BITS (randombits);
|
||||
+ RANDOM_BITS (randombits);
|
||||
#else
|
||||
- struct timeval tv;
|
||||
- __gettimeofday (&tv, NULL);
|
||||
- randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
|
||||
+ struct timeval tv;
|
||||
+ __gettimeofday (&tv, NULL);
|
||||
+ randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
|
||||
#endif
|
||||
- }
|
||||
- while ((randombits & 0xffff) == 0);
|
||||
- statp->id = (statp->id + randombits) & 0xffff;
|
||||
- hp->id = statp->id;
|
||||
- hp->opcode = op;
|
||||
- hp->rd = (statp->options & RES_RECURSE) != 0;
|
||||
- hp->rcode = NOERROR;
|
||||
- cp = buf + HFIXEDSZ;
|
||||
- buflen -= HFIXEDSZ;
|
||||
- dpp = dnptrs;
|
||||
- *dpp++ = buf;
|
||||
- *dpp++ = NULL;
|
||||
- lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
|
||||
- /*
|
||||
- * perform opcode specific processing
|
||||
- */
|
||||
- switch (op) {
|
||||
- case NS_NOTIFY_OP:
|
||||
- if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
|
||||
- return (-1);
|
||||
- goto compose;
|
||||
+ }
|
||||
+ while ((randombits & 0xffff) == 0);
|
||||
+
|
||||
+ statp->id = (statp->id + randombits) & 0xffff;
|
||||
+ hp->id = statp->id;
|
||||
+ hp->opcode = op;
|
||||
+ hp->rd = (statp->options & RES_RECURSE) != 0;
|
||||
+ hp->rcode = NOERROR;
|
||||
+ cp = buf + HFIXEDSZ;
|
||||
+ buflen -= HFIXEDSZ;
|
||||
+ dpp = dnptrs;
|
||||
+ *dpp++ = buf;
|
||||
+ *dpp++ = NULL;
|
||||
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
|
||||
|
||||
- case QUERY:
|
||||
- if ((buflen -= QFIXEDSZ) < 0)
|
||||
- return (-1);
|
||||
- compose:
|
||||
- n = ns_name_compress(dname, cp, buflen,
|
||||
- (const u_char **) dnptrs,
|
||||
- (const u_char **) lastdnptr);
|
||||
- if (n < 0)
|
||||
- return (-1);
|
||||
- cp += n;
|
||||
- buflen -= n;
|
||||
- NS_PUT16 (type, cp);
|
||||
- NS_PUT16 (class, cp);
|
||||
- hp->qdcount = htons(1);
|
||||
- if (op == QUERY || data == NULL)
|
||||
- break;
|
||||
- /*
|
||||
- * Make an additional record for completion domain.
|
||||
- */
|
||||
- n = ns_name_compress((char *)data, cp, buflen,
|
||||
- (const u_char **) dnptrs,
|
||||
- (const u_char **) lastdnptr);
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- return (-1);
|
||||
- cp += n;
|
||||
- buflen -= n;
|
||||
- NS_PUT16 (T_NULL, cp);
|
||||
- NS_PUT16 (class, cp);
|
||||
- NS_PUT32 (0, cp);
|
||||
- NS_PUT16 (0, cp);
|
||||
- hp->arcount = htons(1);
|
||||
- break;
|
||||
+ /* Perform opcode specific processing. */
|
||||
+ switch (op)
|
||||
+ {
|
||||
+ case NS_NOTIFY_OP:
|
||||
+ if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
|
||||
+ return -1;
|
||||
+ goto compose;
|
||||
|
||||
- default:
|
||||
- return (-1);
|
||||
- }
|
||||
- return (cp - buf);
|
||||
+ case QUERY:
|
||||
+ if ((buflen -= QFIXEDSZ) < 0)
|
||||
+ return -1;
|
||||
+ compose:
|
||||
+ n = ns_name_compress (dname, cp, buflen,
|
||||
+ (const unsigned char **) dnptrs,
|
||||
+ (const unsigned char **) lastdnptr);
|
||||
+ if (n < 0)
|
||||
+ return -1;
|
||||
+ cp += n;
|
||||
+ buflen -= n;
|
||||
+ NS_PUT16 (type, cp);
|
||||
+ NS_PUT16 (class, cp);
|
||||
+ hp->qdcount = htons (1);
|
||||
+ if (op == QUERY || data == NULL)
|
||||
+ break;
|
||||
+
|
||||
+ /* Make an additional record for completion domain. */
|
||||
+ n = ns_name_compress ((char *)data, cp, buflen,
|
||||
+ (const unsigned char **) dnptrs,
|
||||
+ (const unsigned char **) lastdnptr);
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
+ return -1;
|
||||
+ cp += n;
|
||||
+ buflen -= n;
|
||||
+ NS_PUT16 (T_NULL, cp);
|
||||
+ NS_PUT16 (class, cp);
|
||||
+ NS_PUT32 (0, cp);
|
||||
+ NS_PUT16 (0, cp);
|
||||
+ hp->arcount = htons (1);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return cp - buf;
|
||||
}
|
||||
libresolv_hidden_def (res_nmkquery)
|
||||
|
||||
+/* Create an OPT resource record. Return the length of the final
|
||||
+ packet, or -1 on error.
|
||||
|
||||
-/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
|
||||
-#ifndef T_OPT
|
||||
-#define T_OPT 41
|
||||
-#endif
|
||||
-
|
||||
+ STATP must be an initialized resolver state. N0 is the current
|
||||
+ number of bytes of the packet (already written to BUF by the
|
||||
+ aller). BUF is the packet being constructed. The array it
|
||||
+ pointers to must be BUFLEN bytes long. ANSLEN is the advertised
|
||||
+ EDNS buffer size (to be included in the OPT resource record). */
|
||||
int
|
||||
-__res_nopt(res_state statp,
|
||||
- int n0, /* current offset in buffer */
|
||||
- u_char *buf, /* buffer to put query */
|
||||
- int buflen, /* size of buffer */
|
||||
- int anslen) /* UDP answer buffer size */
|
||||
+__res_nopt (res_state statp, int n0, unsigned char *buf, int buflen,
|
||||
+ int anslen)
|
||||
{
|
||||
- u_int16_t flags = 0;
|
||||
-
|
||||
- HEADER *hp = (HEADER *) buf;
|
||||
- u_char *cp = buf + n0;
|
||||
- u_char *ep = buf + buflen;
|
||||
+ uint16_t flags = 0;
|
||||
+ HEADER *hp = (HEADER *) buf;
|
||||
+ unsigned char *cp = buf + n0;
|
||||
+ unsigned char *ep = buf + buflen;
|
||||
|
||||
- if ((ep - cp) < 1 + RRFIXEDSZ)
|
||||
- return -1;
|
||||
+ if ((ep - cp) < 1 + RRFIXEDSZ)
|
||||
+ return -1;
|
||||
|
||||
- *cp++ = 0; /* "." */
|
||||
+ /* Add the root label. */
|
||||
+ *cp++ = 0;
|
||||
|
||||
- NS_PUT16(T_OPT, cp); /* TYPE */
|
||||
+ NS_PUT16 (T_OPT, cp); /* Record type. */
|
||||
|
||||
- /* Lowering the advertised buffer size based on the actual
|
||||
- answer buffer size is desirable because the server will
|
||||
- minimize the reply to fit into the UDP packet (and A
|
||||
- non-minimal response might not fit the buffer).
|
||||
+ /* Lowering the advertised buffer size based on the actual
|
||||
+ answer buffer size is desirable because the server will
|
||||
+ minimize the reply to fit into the UDP packet (and A
|
||||
+ non-minimal response might not fit the buffer).
|
||||
|
||||
- The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP
|
||||
- fallback and a non-minimal response which has to be
|
||||
- hard-truncated in the stub resolver, but this is price to
|
||||
- pay for avoiding fragmentation. (This issue does not
|
||||
- affect the nss_dns functions because they use the stub
|
||||
- resolver in such a way that it allocates a properly sized
|
||||
- response buffer.) */
|
||||
- {
|
||||
- uint16_t buffer_size;
|
||||
- if (anslen < 512)
|
||||
- buffer_size = 512;
|
||||
- else if (anslen > RESOLV_EDNS_BUFFER_SIZE)
|
||||
- buffer_size = RESOLV_EDNS_BUFFER_SIZE;
|
||||
- else
|
||||
- buffer_size = anslen;
|
||||
- NS_PUT16 (buffer_size, cp);
|
||||
- }
|
||||
+ The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP
|
||||
+ fallback and a non-minimal response which has to be
|
||||
+ hard-truncated in the stub resolver, but this is price to
|
||||
+ pay for avoiding fragmentation. (This issue does not
|
||||
+ affect the nss_dns functions because they use the stub
|
||||
+ resolver in such a way that it allocates a properly sized
|
||||
+ response buffer.) */
|
||||
+ {
|
||||
+ uint16_t buffer_size;
|
||||
+ if (anslen < 512)
|
||||
+ buffer_size = 512;
|
||||
+ else if (anslen > RESOLV_EDNS_BUFFER_SIZE)
|
||||
+ buffer_size = RESOLV_EDNS_BUFFER_SIZE;
|
||||
+ else
|
||||
+ buffer_size = anslen;
|
||||
+ NS_PUT16 (buffer_size, cp);
|
||||
+ }
|
||||
|
||||
- *cp++ = NOERROR; /* extended RCODE */
|
||||
- *cp++ = 0; /* EDNS version */
|
||||
+ *cp++ = NOERROR; /* Extended RCODE. */
|
||||
+ *cp++ = 0; /* EDNS version. */
|
||||
|
||||
- if (statp->options & RES_USE_DNSSEC) {
|
||||
- flags |= NS_OPT_DNSSEC_OK;
|
||||
- }
|
||||
+ if (statp->options & RES_USE_DNSSEC)
|
||||
+ flags |= NS_OPT_DNSSEC_OK;
|
||||
|
||||
- NS_PUT16(flags, cp);
|
||||
- NS_PUT16(0, cp); /* RDLEN */
|
||||
- hp->arcount = htons(ntohs(hp->arcount) + 1);
|
||||
+ NS_PUT16 (flags, cp);
|
||||
+ NS_PUT16 (0, cp); /* RDATA length (no options are preent). */
|
||||
+ hp->arcount = htons (ntohs (hp->arcount) + 1);
|
||||
|
||||
- return cp - buf;
|
||||
+ return cp - buf;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
commit 5ca4aaea1840b3005c2de4cc73269a55e34ae2c3
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:18 2017 +0200
|
||||
|
||||
resolv: Move the res_mkquery function to the resolv/mk_query.c file
|
||||
|
||||
diff --git a/resolv/res_data.c b/resolv/res_data.c
|
||||
index 569ff4c0ea306e74..d907bfc9bd8a55fd 100644
|
||||
--- a/resolv/res_data.c
|
||||
+++ b/resolv/res_data.c
|
||||
@@ -73,25 +73,6 @@ fp_nquery(const u_char *msg, int len, FILE *file) {
|
||||
libresolv_hidden_def (fp_nquery)
|
||||
|
||||
int
|
||||
-res_mkquery(int op, /* opcode of query */
|
||||
- const char *dname, /* domain name */
|
||||
- int class, int type, /* class and type of query */
|
||||
- const u_char *data, /* resource record data */
|
||||
- int datalen, /* length of data */
|
||||
- const u_char *newrr_in, /* new rr for modify or append */
|
||||
- u_char *buf, /* buffer to put query */
|
||||
- int buflen) /* size of buffer */
|
||||
-{
|
||||
- if (__res_maybe_init (&_res, 1) == -1) {
|
||||
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
|
||||
- return (-1);
|
||||
- }
|
||||
- return (res_nmkquery(&_res, op, dname, class, type,
|
||||
- data, datalen,
|
||||
- newrr_in, buf, buflen));
|
||||
-}
|
||||
-
|
||||
-int
|
||||
res_query(const char *name, /* domain name */
|
||||
int class, int type, /* class and type of query */
|
||||
u_char *answer, /* buffer to put answer */
|
||||
@@ -180,11 +161,9 @@ libresolv_hidden_def (hostalias)
|
||||
#include <shlib-compat.h>
|
||||
|
||||
#if SHLIB_COMPAT(libresolv, GLIBC_2_0, GLIBC_2_2)
|
||||
-# undef res_mkquery
|
||||
# undef res_query
|
||||
# undef res_querydomain
|
||||
# undef res_search
|
||||
-weak_alias (__res_mkquery, res_mkquery);
|
||||
weak_alias (__res_query, res_query);
|
||||
weak_alias (__res_querydomain, res_querydomain);
|
||||
weak_alias (__res_search, res_search);
|
||||
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
|
||||
index a601b6988545a149..9afb410980e47ca7 100644
|
||||
--- a/resolv/res_mkquery.c
|
||||
+++ b/resolv/res_mkquery.c
|
||||
@@ -90,6 +90,7 @@
|
||||
#include <resolv/resolv-internal.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
+#include <shlib-compat.h>
|
||||
|
||||
#include <hp-timing.h>
|
||||
#include <stdint.h>
|
||||
@@ -202,6 +203,21 @@ res_nmkquery (res_state statp, int op, const char *dname,
|
||||
}
|
||||
libresolv_hidden_def (res_nmkquery)
|
||||
|
||||
+int
|
||||
+res_mkquery (int op, const char *dname, int class, int type,
|
||||
+ const unsigned char *data, int datalen,
|
||||
+ const unsigned char *newrr_in,
|
||||
+ unsigned char *buf, int buflen)
|
||||
+{
|
||||
+ if (__res_maybe_init (&_res, 1) == -1)
|
||||
+ {
|
||||
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return res_nmkquery (&_res, op, dname, class, type,
|
||||
+ data, datalen, newrr_in, buf, buflen);
|
||||
+}
|
||||
+
|
||||
/* Create an OPT resource record. Return the length of the final
|
||||
packet, or -1 on error.
|
||||
|
||||
@@ -262,3 +278,8 @@ __res_nopt (res_state statp, int n0, unsigned char *buf, int buflen,
|
||||
|
||||
return cp - buf;
|
||||
}
|
||||
+
|
||||
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
|
||||
+# undef res_mkquery
|
||||
+weak_alias (__res_mkquery, res_mkquery);
|
||||
+#endif
|
|
@ -0,0 +1,46 @@
|
|||
commit b606c6ce66d4772068bfe3e410c28a247633ee24
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:32:19 2017 +0200
|
||||
|
||||
resolv: Remove source argument fron res_options
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 821f06061b4c3fb1..5d8b2c994d8e6f04 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -103,7 +103,7 @@
|
||||
#include <inet/net-internal.h>
|
||||
#include <errno.h>
|
||||
|
||||
-static void res_setoptions (res_state, const char *, const char *);
|
||||
+static void res_setoptions (res_state, const char *);
|
||||
static uint32_t net_mask (struct in_addr);
|
||||
|
||||
unsigned long long int __res_initstamp;
|
||||
@@ -381,7 +381,7 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
}
|
||||
if (MATCH (*buffer, "options"))
|
||||
{
|
||||
- res_setoptions (statp, *buffer + sizeof ("options") - 1, "conf");
|
||||
+ res_setoptions (statp, *buffer + sizeof ("options") - 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -417,7 +417,7 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
}
|
||||
|
||||
if ((cp = getenv ("RES_OPTIONS")) != NULL)
|
||||
- res_setoptions (statp, cp, "env");
|
||||
+ res_setoptions (statp, cp);
|
||||
statp->options |= RES_INIT;
|
||||
return true;
|
||||
}
|
||||
@@ -469,7 +469,7 @@ __res_vinit (res_state statp, int preinit)
|
||||
}
|
||||
|
||||
static void
|
||||
-res_setoptions (res_state statp, const char *options, const char *source)
|
||||
+res_setoptions (res_state statp, const char *options)
|
||||
{
|
||||
const char *cp = options;
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
commit 3f8f1eb6b0ca45205cea3591f27727e21d598f62
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:32:12 2017 +0200
|
||||
|
||||
resolv: Remove DEBUG from resolv/res_query.c
|
||||
|
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||||
index 5312c8e729c39516..760bf324e817c79e 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -80,9 +80,6 @@
|
||||
#include <string.h>
|
||||
#include <shlib-compat.h>
|
||||
|
||||
-/* Options. Leave them on. */
|
||||
-/* #undef DEBUG */
|
||||
-
|
||||
#if PACKETSZ > 65536
|
||||
#define MAXPACKET PACKETSZ
|
||||
#else
|
||||
@@ -133,11 +130,6 @@ __libc_res_nquery(res_state statp,
|
||||
again:
|
||||
hp->rcode = NOERROR; /* default */
|
||||
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
||||
-#endif
|
||||
-
|
||||
if (type == T_QUERY_A_AND_AAAA)
|
||||
{
|
||||
n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
|
||||
@@ -211,10 +203,6 @@ __libc_res_nquery(res_state statp,
|
||||
}
|
||||
}
|
||||
if (__glibc_unlikely (n <= 0)) {
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_query: mkquery failed\n");
|
||||
-#endif
|
||||
RES_SET_H_ERRNO(statp, NO_RECOVERY);
|
||||
if (use_malloc)
|
||||
free (buf);
|
||||
@@ -227,10 +215,6 @@ __libc_res_nquery(res_state statp,
|
||||
if (use_malloc)
|
||||
free (buf);
|
||||
if (n < 0) {
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_query: send error\n");
|
||||
-#endif
|
||||
RES_SET_H_ERRNO(statp, TRY_AGAIN);
|
||||
return (n);
|
||||
}
|
||||
@@ -260,15 +244,6 @@ __libc_res_nquery(res_state statp,
|
||||
|
||||
if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
|
||||
&& (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG) {
|
||||
- printf(";; rcode = %d, ancount=%d\n", hp->rcode,
|
||||
- ntohs(hp->ancount));
|
||||
- if (hp != hp2)
|
||||
- printf(";; rcode2 = %d, ancount2=%d\n", hp2->rcode,
|
||||
- ntohs(hp2->ancount));
|
||||
- }
|
||||
-#endif
|
||||
switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) {
|
||||
case NXDOMAIN:
|
||||
if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
|
||||
@@ -374,12 +349,6 @@ __libc_res_nsearch(res_state statp,
|
||||
anslen, answerp, answerp2,
|
||||
nanswerp2, resplen2, answerp2_malloced));
|
||||
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf("dots=%d, statp->ndots=%d, trailing_dot=%d, name=%s\n",
|
||||
- (int)dots,(int)statp->ndots,(int)trailing_dot,name);
|
||||
-#endif
|
||||
-
|
||||
/*
|
||||
* If there are enough dots in the name, let's just give it a
|
||||
* try 'as is'. The threshold can be set with the "ndots" option.
|
||||
@@ -590,11 +559,6 @@ __libc_res_nquerydomain(res_state statp,
|
||||
const char *longname = nbuf;
|
||||
size_t n, d;
|
||||
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
|
||||
- name, domain?domain:"<Nil>", class, type);
|
||||
-#endif
|
||||
if (domain == NULL) {
|
||||
n = strlen(name);
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
commit 037751179905c7d6d624f287029237565465fa9a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:54 2017 +0200
|
||||
|
||||
resolv: Move res_query, res_search res_querydomain, hostalias
|
||||
|
||||
From res_data.c to query.c
|
||||
|
||||
diff --git a/resolv/res_data.c b/resolv/res_data.c
|
||||
index b790b4b725bc9edd..5e7688c706bf8e99 100644
|
||||
--- a/resolv/res_data.c
|
||||
+++ b/resolv/res_data.c
|
||||
@@ -15,35 +15,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
-#include <sys/types.h>
|
||||
-#include <sys/param.h>
|
||||
-#include <sys/socket.h>
|
||||
-#include <sys/time.h>
|
||||
-
|
||||
-#include <netinet/in.h>
|
||||
-#include <arpa/inet.h>
|
||||
-#include <arpa/nameser.h>
|
||||
-
|
||||
-#include <ctype.h>
|
||||
-#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
-#include <stdio.h>
|
||||
-#include <stdlib.h>
|
||||
-#include <string.h>
|
||||
-#include <unistd.h>
|
||||
-
|
||||
-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 (__res_maybe_init (&_res, 1) == -1) {
|
||||
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
|
||||
- return (-1);
|
||||
- }
|
||||
- return (res_nquery(&_res, name, class, type, answer, anslen));
|
||||
-}
|
||||
|
||||
void
|
||||
res_close(void) {
|
||||
@@ -60,55 +32,3 @@ res_close(void) {
|
||||
did it and it would be done implicitly on shutdown. */
|
||||
__res_iclose(&_res, false);
|
||||
}
|
||||
-
|
||||
-int
|
||||
-res_search(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 */
|
||||
-{
|
||||
- if (__res_maybe_init (&_res, 1) == -1) {
|
||||
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
|
||||
- return (-1);
|
||||
- }
|
||||
-
|
||||
- return (res_nsearch(&_res, name, class, type, answer, anslen));
|
||||
-}
|
||||
-
|
||||
-int
|
||||
-res_querydomain(const char *name,
|
||||
- const char *domain,
|
||||
- int class, int type, /* class and type of query */
|
||||
- u_char *answer, /* buffer to put answer */
|
||||
- int anslen) /* size of answer */
|
||||
-{
|
||||
- if (__res_maybe_init (&_res, 1) == -1) {
|
||||
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
|
||||
- return (-1);
|
||||
- }
|
||||
-
|
||||
- return (res_nquerydomain(&_res, name, domain,
|
||||
- class, type,
|
||||
- answer, anslen));
|
||||
-}
|
||||
-
|
||||
-const char *
|
||||
-hostalias(const char *name) {
|
||||
- static char abuf[MAXDNAME];
|
||||
-
|
||||
- return (res_hostalias(&_res, name, abuf, sizeof abuf));
|
||||
-}
|
||||
-libresolv_hidden_def (hostalias)
|
||||
-
|
||||
-
|
||||
-
|
||||
-#include <shlib-compat.h>
|
||||
-
|
||||
-#if SHLIB_COMPAT(libresolv, GLIBC_2_0, GLIBC_2_2)
|
||||
-# undef res_query
|
||||
-# undef res_querydomain
|
||||
-# undef res_search
|
||||
-weak_alias (__res_query, res_query);
|
||||
-weak_alias (__res_querydomain, res_querydomain);
|
||||
-weak_alias (__res_search, res_search);
|
||||
-#endif
|
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||||
index 0ca3a650282ec7f0..5312c8e729c39516 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -78,7 +78,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
-#include <resolv/resolv-internal.h>
|
||||
+#include <shlib-compat.h>
|
||||
|
||||
/* Options. Leave them on. */
|
||||
/* #undef DEBUG */
|
||||
@@ -319,6 +319,18 @@ res_nquery(res_state statp,
|
||||
}
|
||||
libresolv_hidden_def (res_nquery)
|
||||
|
||||
+int
|
||||
+res_query (const char *name, int class, int type,
|
||||
+ unsigned char *answer, int anslen)
|
||||
+{
|
||||
+ if (__res_maybe_init (&_res, 1) == -1)
|
||||
+ {
|
||||
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return res_nquery (&_res, name, class, type, answer, anslen);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Formulate a normal query, send, and retrieve answer in supplied buffer.
|
||||
* Return the size of the response on success, -1 on error.
|
||||
@@ -545,6 +557,19 @@ res_nsearch(res_state statp,
|
||||
}
|
||||
libresolv_hidden_def (res_nsearch)
|
||||
|
||||
+int
|
||||
+res_search (const char *name, int class, int type,
|
||||
+ unsigned char *answer, int anslen)
|
||||
+{
|
||||
+ if (__res_maybe_init (&_res, 1) == -1)
|
||||
+ {
|
||||
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return res_nsearch (&_res, name, class, type, answer, anslen);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Perform a call on res_query on the concatenation of name and domain.
|
||||
*/
|
||||
@@ -610,6 +635,19 @@ res_nquerydomain(res_state statp,
|
||||
}
|
||||
libresolv_hidden_def (res_nquerydomain)
|
||||
|
||||
+int
|
||||
+res_querydomain (const char *name, const char *domain, int class, int type,
|
||||
+ unsigned char *answer, int anslen)
|
||||
+{
|
||||
+ if (__res_maybe_init (&_res, 1) == -1)
|
||||
+ {
|
||||
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return res_nquerydomain (&_res, name, domain, class, type, answer, anslen);
|
||||
+}
|
||||
+
|
||||
const char *
|
||||
res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
|
||||
char *file, *cp1, *cp2;
|
||||
@@ -647,3 +685,20 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
|
||||
return (NULL);
|
||||
}
|
||||
libresolv_hidden_def (res_hostalias)
|
||||
+
|
||||
+const char *
|
||||
+hostalias (const char *name)
|
||||
+{
|
||||
+ static char abuf[MAXDNAME];
|
||||
+ return res_hostalias (&_res, name, abuf, sizeof abuf);
|
||||
+}
|
||||
+libresolv_hidden_def (hostalias)
|
||||
+
|
||||
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
|
||||
+# undef res_query
|
||||
+# undef res_querydomain
|
||||
+# undef res_search
|
||||
+weak_alias (__res_query, res_query);
|
||||
+weak_alias (__res_querydomain, res_querydomain);
|
||||
+weak_alias (__res_search, res_search);
|
||||
+#endif
|
|
@ -0,0 +1,135 @@
|
|||
commit 26bf5a1029434c98db85947eed11ce3090b2f5db
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 13:17:03 2017 +0200
|
||||
|
||||
resolv: Move res_randomid to its own file
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 0ebb2af795c6fb7b..c2a8a3a631f6bb2e 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -28,7 +28,7 @@ headers := resolv.h \
|
||||
sys/bitypes.h
|
||||
|
||||
routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
|
||||
- res_hconf res_libc res-state
|
||||
+ res_hconf res_libc res-state res_randomid
|
||||
|
||||
tests = tst-aton tst-leaks tst-inet_ntop
|
||||
xtests = tst-leaks2
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 57223b470af9ba4d..ef2e7c0db465dba6 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -479,13 +479,6 @@ net_mask (struct in_addr in)
|
||||
return (htonl(IN_CLASSC_NET));
|
||||
}
|
||||
|
||||
-u_int
|
||||
-res_randomid(void) {
|
||||
- return 0xffff & __getpid();
|
||||
-}
|
||||
-libc_hidden_def (__res_randomid)
|
||||
-
|
||||
-
|
||||
/*
|
||||
* This routine is for closing the socket if a virtual circuit is used and
|
||||
* the program wants to close it. This provides support for endhostent()
|
||||
diff --git a/resolv/res_randomid.c b/resolv/res_randomid.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e0dbe4c8ff259527
|
||||
--- /dev/null
|
||||
+++ b/resolv/res_randomid.c
|
||||
@@ -0,0 +1,92 @@
|
||||
+/* Legacy libresolv random number generator.
|
||||
+ Copyright (C) 1995-2017 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/>. */
|
||||
+
|
||||
+/*
|
||||
+ * Copyright (c) 1985, 1989, 1993
|
||||
+ * The Regents of the University of California. All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 4. Neither the name of the University nor the names of its contributors
|
||||
+ * may be used to endorse or promote products derived from this software
|
||||
+ * without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies, and that
|
||||
+ * the name of Digital Equipment Corporation not be used in advertising or
|
||||
+ * publicity pertaining to distribution of the document or software without
|
||||
+ * specific, written prior permission.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
+ * SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
+ * SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include <resolv.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+unsigned int
|
||||
+res_randomid (void) {
|
||||
+ return 0xffff & __getpid ();
|
||||
+}
|
||||
+libc_hidden_def (__res_randomid)
|
|
@ -0,0 +1,468 @@
|
|||
commit 5b757a51b514ea163bbec0a53dbbc06bb1b29241
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 10:43:33 2017 +0200
|
||||
|
||||
resolv: Make RES_ROTATE start with a random name server [BZ #19570]
|
||||
|
||||
Do not copy the actual name server addresses to rotate them. Use a
|
||||
global rotation offset instead.
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 88766729087d54cf..79843d0d7ca92ffd 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -69,6 +69,9 @@ tests += tst-inet_pton
|
||||
|
||||
# This test sends millions of packets and is rather slow.
|
||||
xtests += tst-resolv-qtypes
|
||||
+
|
||||
+# This test has dropped packet tests and runs for a long time.
|
||||
+xtests += tst-resolv-rotate
|
||||
endif
|
||||
extra-libs-others = $(extra-libs)
|
||||
libresolv-routines := res_comp res_debug \
|
||||
@@ -148,6 +151,7 @@ $(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so
|
||||
$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-canonname: \
|
||||
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 1835ec7ee507d215..1dbe30088167636c 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -109,6 +109,8 @@
|
||||
#include <unistd.h>
|
||||
#include <kernel-features.h>
|
||||
#include <libc-internal.h>
|
||||
+#include <libc-diag.h>
|
||||
+#include <hp-timing.h>
|
||||
|
||||
#if PACKETSZ > 65536
|
||||
#define MAXPACKET PACKETSZ
|
||||
@@ -188,7 +190,7 @@ evNowTime(struct timespec *res) {
|
||||
|
||||
/* Forward. */
|
||||
|
||||
-static struct sockaddr *get_nsaddr (res_state, int);
|
||||
+static struct sockaddr *get_nsaddr (res_state, unsigned int);
|
||||
static int send_vc(res_state, const u_char *, int,
|
||||
const u_char *, int,
|
||||
u_char **, int *, int *, int, u_char **,
|
||||
@@ -291,6 +293,62 @@ res_nameinquery(const char *name, int type, int class,
|
||||
}
|
||||
libresolv_hidden_def (res_nameinquery)
|
||||
|
||||
+/* Returns a shift value for the name server index. Used to implement
|
||||
+ RES_ROTATE. */
|
||||
+static unsigned int
|
||||
+nameserver_offset (struct __res_state *statp)
|
||||
+{
|
||||
+ /* If we only have one name server or rotation is disabled, return
|
||||
+ offset 0 (no rotation). */
|
||||
+ unsigned int nscount = statp->nscount;
|
||||
+ if (nscount <= 1 || !(statp->options & RES_ROTATE))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Global offset. The lowest bit indicates whether the offset has
|
||||
+ been initialized with a random value. Use relaxed MO to access
|
||||
+ global_offset because all we need is a sequence of roughly
|
||||
+ sequential value. */
|
||||
+ static unsigned int global_offset;
|
||||
+ unsigned int offset = atomic_fetch_add_relaxed (&global_offset, 2);
|
||||
+ if ((offset & 1) == 0)
|
||||
+ {
|
||||
+ /* Initialization is required. */
|
||||
+#if HP_TIMING_AVAIL
|
||||
+ uint64_t ticks;
|
||||
+ HP_TIMING_NOW (ticks);
|
||||
+ offset = ticks;
|
||||
+#else
|
||||
+ struct timeval tv;
|
||||
+ __gettimeofday (&tv, NULL);
|
||||
+ offset = ((tv.tv_sec << 8) ^ tv.tv_usec);
|
||||
+#endif
|
||||
+ /* The lowest bit is the most random. Preserve it. */
|
||||
+ offset <<= 1;
|
||||
+
|
||||
+ /* Store the new starting value. atomic_fetch_add_relaxed
|
||||
+ returns the old value, so emulate that by storing the new
|
||||
+ (incremented) value. Concurrent initialization with
|
||||
+ different random values is harmless. */
|
||||
+ atomic_store_relaxed (&global_offset, (offset | 1) + 2);
|
||||
+ }
|
||||
+
|
||||
+ /* Remove the initialization bit. */
|
||||
+ offset >>= 1;
|
||||
+
|
||||
+ /* Avoid the division in the most common cases. */
|
||||
+ switch (nscount)
|
||||
+ {
|
||||
+ case 2:
|
||||
+ return offset & 1;
|
||||
+ case 3:
|
||||
+ return offset % 3;
|
||||
+ case 4:
|
||||
+ return offset & 3;
|
||||
+ default:
|
||||
+ return offset % nscount;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* int
|
||||
* res_queriesmatch(buf1, eom1, buf2, eom2)
|
||||
* is there a 1:1 mapping of (name,type,class)
|
||||
@@ -352,7 +410,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
|
||||
int *nansp2, int *resplen2, int *ansp2_malloced)
|
||||
{
|
||||
- int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
|
||||
+ int gotsomewhere, terrno, try, v_circuit, resplen, n;
|
||||
|
||||
if (statp->nscount == 0) {
|
||||
__set_errno (ESRCH);
|
||||
@@ -382,7 +440,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
if (EXT(statp).nscount != statp->nscount)
|
||||
needclose++;
|
||||
else
|
||||
- for (ns = 0; ns < statp->nscount; ns++) {
|
||||
+ for (unsigned int ns = 0; ns < statp->nscount; ns++) {
|
||||
if (statp->nsaddr_list[ns].sin_family != 0
|
||||
&& !sock_eq((struct sockaddr_in6 *)
|
||||
&statp->nsaddr_list[ns],
|
||||
@@ -402,7 +460,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
* Maybe initialize our private copy of the ns_addr_list.
|
||||
*/
|
||||
if (EXT(statp).nscount == 0) {
|
||||
- for (ns = 0; ns < statp->nscount; ns++) {
|
||||
+ for (unsigned int ns = 0; ns < statp->nscount; ns++) {
|
||||
EXT(statp).nssocks[ns] = -1;
|
||||
if (statp->nsaddr_list[ns].sin_family == 0)
|
||||
continue;
|
||||
@@ -420,35 +478,21 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
EXT(statp).nscount = statp->nscount;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Some resolvers want to even out the load on their nameservers.
|
||||
- * Note that RES_BLAST overrides RES_ROTATE.
|
||||
- */
|
||||
- if (__glibc_unlikely ((statp->options & RES_ROTATE) != 0)) {
|
||||
- struct sockaddr_in ina;
|
||||
- struct sockaddr_in6 *inp;
|
||||
- int lastns = statp->nscount - 1;
|
||||
- int fd;
|
||||
-
|
||||
- inp = EXT(statp).nsaddrs[0];
|
||||
- ina = statp->nsaddr_list[0];
|
||||
- fd = EXT(statp).nssocks[0];
|
||||
- for (ns = 0; ns < lastns; ns++) {
|
||||
- EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
|
||||
- statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
|
||||
- EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
|
||||
- }
|
||||
- EXT(statp).nsaddrs[lastns] = inp;
|
||||
- statp->nsaddr_list[lastns] = ina;
|
||||
- EXT(statp).nssocks[lastns] = fd;
|
||||
- }
|
||||
+ /* Name server index offset. Used to implement
|
||||
+ RES_ROTATE. */
|
||||
+ unsigned int ns_offset = nameserver_offset (statp);
|
||||
|
||||
/*
|
||||
* Send request, RETRY times, or until successful.
|
||||
*/
|
||||
for (try = 0; try < statp->retry; try++) {
|
||||
- for (ns = 0; ns < statp->nscount; ns++)
|
||||
+ for (unsigned ns_shift = 0; ns_shift < statp->nscount; ns_shift++)
|
||||
{
|
||||
+ /* The actual name server index. This implements
|
||||
+ RES_ROTATE. */
|
||||
+ unsigned int ns = ns_shift + ns_offset;
|
||||
+ if (ns >= statp->nscount)
|
||||
+ ns -= statp->nscount;
|
||||
#ifdef DEBUG
|
||||
char tmpbuf[40];
|
||||
struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||||
@@ -544,8 +588,9 @@ libresolv_hidden_def (res_nsend)
|
||||
/* Private */
|
||||
|
||||
static struct sockaddr *
|
||||
-get_nsaddr (res_state statp, int n)
|
||||
+get_nsaddr (res_state statp, unsigned int n)
|
||||
{
|
||||
+ assert (n < statp->nscount);
|
||||
|
||||
if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
|
||||
/* EXT(statp).nsaddrs[n] holds an address that is larger than
|
||||
diff --git a/resolv/tst-resolv-rotate.c b/resolv/tst-resolv-rotate.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d01b85b2fe82930b
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-rotate.c
|
||||
@@ -0,0 +1,263 @@
|
||||
+/* Check that RES_ROTATE works with few nameserver entries (bug 13028).
|
||||
+ Copyright (C) 2017 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 <netdb.h>
|
||||
+#include <resolv.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/test-driver.h>
|
||||
+
|
||||
+static volatile int drop_server = -1;
|
||||
+static volatile unsigned int query_counts[resolv_max_test_servers];
|
||||
+
|
||||
+static const char address_ipv4[4] = {192, 0, 2, 1};
|
||||
+static const char address_ipv6[16]
|
||||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ if (ctx->server_index == drop_server)
|
||||
+ {
|
||||
+ resolv_response_drop (b);
|
||||
+ resolv_response_close (b);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bool force_tcp = strncmp (qname, "2.", 2) == 0;
|
||||
+ struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp};
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ if (flags.tc)
|
||||
+ return;
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (ctx->server_index < resolv_max_test_servers);
|
||||
+ ++query_counts[ctx->server_index];
|
||||
+
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||||
+ switch (qtype)
|
||||
+ {
|
||||
+ case T_A:
|
||||
+ {
|
||||
+ char addr[sizeof (address_ipv4)];
|
||||
+ memcpy (addr, address_ipv4, sizeof (address_ipv4));
|
||||
+ addr[3] = 1 + ctx->tcp;
|
||||
+ resolv_response_add_data (b, addr, sizeof (addr));
|
||||
+ }
|
||||
+ break;
|
||||
+ case T_AAAA:
|
||||
+ {
|
||||
+ char addr[sizeof (address_ipv6)];
|
||||
+ memcpy (addr, address_ipv6, sizeof (address_ipv6));
|
||||
+ addr[15] = 1 + ctx->tcp;
|
||||
+ resolv_response_add_data (b, addr, sizeof (addr));
|
||||
+ }
|
||||
+ break;
|
||||
+ case T_PTR:
|
||||
+ if (force_tcp)
|
||||
+ resolv_response_add_name (b, "2.host.example");
|
||||
+ else
|
||||
+ resolv_response_add_name (b, "host.example");
|
||||
+ break;
|
||||
+ default:
|
||||
+ FAIL_EXIT1 ("unexpected QTYPE: %s/%u/%u", qname, qclass, qtype);
|
||||
+ }
|
||||
+ resolv_response_close_record (b);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check_forward_1 (const char *name, int family)
|
||||
+{
|
||||
+ unsigned char lsb;
|
||||
+ if (strncmp (name, "2.", 2) == 0)
|
||||
+ lsb = 2;
|
||||
+ else
|
||||
+ lsb = 1;
|
||||
+
|
||||
+ char expected_hostent_v4[200];
|
||||
+ snprintf (expected_hostent_v4, sizeof (expected_hostent_v4),
|
||||
+ "name: %s\naddress: 192.0.2.%d\n", name, lsb);
|
||||
+ char expected_hostent_v6[200];
|
||||
+ snprintf (expected_hostent_v6, sizeof (expected_hostent_v6),
|
||||
+ "name: %s\naddress: 2001:db8::%d\n", name, lsb);
|
||||
+ char expected_ai[200];
|
||||
+
|
||||
+ unsigned char address[16];
|
||||
+ size_t address_length;
|
||||
+
|
||||
+ char *expected_hostent;
|
||||
+ switch (family)
|
||||
+ {
|
||||
+ case AF_INET:
|
||||
+ expected_hostent = expected_hostent_v4;
|
||||
+ snprintf (expected_ai, sizeof (expected_ai),
|
||||
+ "address: STREAM/TCP 192.0.2.%d 80\n", lsb);
|
||||
+ TEST_VERIFY_EXIT (sizeof (address_ipv4) == sizeof (struct in_addr));
|
||||
+ memcpy (address, address_ipv4, sizeof (address_ipv4));
|
||||
+ address_length = sizeof (address_ipv4);
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ expected_hostent = expected_hostent_v6;
|
||||
+ snprintf (expected_ai, sizeof (expected_ai),
|
||||
+ "address: STREAM/TCP 2001:db8::%d 80\n", lsb);
|
||||
+ TEST_VERIFY_EXIT (sizeof (address_ipv6) == sizeof (struct in6_addr));
|
||||
+ memcpy (address, address_ipv6, sizeof (address_ipv6));
|
||||
+ address_length = sizeof (address_ipv6);
|
||||
+ break;
|
||||
+ case AF_UNSPEC:
|
||||
+ expected_hostent = NULL;
|
||||
+ snprintf (expected_ai, sizeof (expected_ai),
|
||||
+ "address: STREAM/TCP 192.0.2.%d 80\n"
|
||||
+ "address: STREAM/TCP 2001:db8::%d 80\n",
|
||||
+ lsb, lsb);
|
||||
+ address_length = 0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ FAIL_EXIT1 ("unknown address family %d", family);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ if (family == AF_INET)
|
||||
+ {
|
||||
+ struct hostent *e = gethostbyname (name);
|
||||
+ check_hostent (name, e, expected_hostent_v4);
|
||||
+ }
|
||||
+
|
||||
+ if (family != AF_UNSPEC)
|
||||
+ {
|
||||
+ struct hostent *e = gethostbyname2 (name, family);
|
||||
+ check_hostent (name, e, expected_hostent);
|
||||
+ }
|
||||
+
|
||||
+ if (address_length > 0)
|
||||
+ {
|
||||
+ address[address_length - 1] = lsb;
|
||||
+ struct hostent *e = gethostbyaddr (address, address_length, family);
|
||||
+ check_hostent (name, e, expected_hostent);
|
||||
+ }
|
||||
+
|
||||
+ struct addrinfo hints =
|
||||
+ {
|
||||
+ .ai_family = family,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ .ai_protocol = IPPROTO_TCP,
|
||||
+ };
|
||||
+ struct addrinfo *ai;
|
||||
+ int ret = getaddrinfo (name, "80", &hints, &ai);
|
||||
+ check_addrinfo (name, ai, ret, expected_ai);
|
||||
+ if (ret == 0)
|
||||
+ {
|
||||
+ for (struct addrinfo *p = ai; p != NULL; p = p->ai_next)
|
||||
+ {
|
||||
+ char host[200];
|
||||
+ ret = getnameinfo (p->ai_addr, p->ai_addrlen,
|
||||
+ host, sizeof (host),
|
||||
+ NULL, 0, /* service */
|
||||
+ 0);
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: getnameinfo: %d\n", ret);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (lsb == 1)
|
||||
+ TEST_VERIFY (strcmp (host, "host.example") == 0);
|
||||
+ else
|
||||
+ TEST_VERIFY (strcmp (host, "2.host.example") == 0);
|
||||
+ }
|
||||
+ }
|
||||
+ freeaddrinfo (ai);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check_forward (int family)
|
||||
+{
|
||||
+ check_forward_1 ("host.example", family);
|
||||
+ check_forward_1 ("2.host.example", family);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ for (int force_tcp = 0; force_tcp < 2; ++force_tcp)
|
||||
+ for (int nscount = 1; nscount <= 3; ++nscount)
|
||||
+ for (int disable_server = -1; disable_server < nscount; ++disable_server)
|
||||
+ for (drop_server = -1; drop_server < nscount; ++drop_server)
|
||||
+ {
|
||||
+ /* A disabled server will never receive queries and
|
||||
+ therefore cannot drop them. */
|
||||
+ if (drop_server >= 0 && drop_server == disable_server)
|
||||
+ continue;
|
||||
+ /* No servers remaining to query, all queries are expected
|
||||
+ to fail. */
|
||||
+ int broken_servers = (disable_server >= 0) + (drop_server >= 0);
|
||||
+ if (nscount <= broken_servers)
|
||||
+ continue;
|
||||
+
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: tcp=%d nscount=%d disable=%d drop=%d\n",
|
||||
+ force_tcp, nscount, disable_server, drop_server);
|
||||
+ struct resolv_redirect_config config =
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ .nscount = nscount
|
||||
+ };
|
||||
+ if (disable_server >= 0)
|
||||
+ {
|
||||
+ config.servers[disable_server].disable_udp = true;
|
||||
+ config.servers[disable_server].disable_tcp = true;
|
||||
+ }
|
||||
+
|
||||
+ struct resolv_test *aux = resolv_test_start (config);
|
||||
+ _res.options |= RES_ROTATE;
|
||||
+
|
||||
+ /* Run a few queries to make sure that all of them
|
||||
+ succeed. We always perform more than nscount queries,
|
||||
+ so we cover all active servers due to RES_ROTATE. */
|
||||
+ for (size_t i = 0; i < resolv_max_test_servers; ++i)
|
||||
+ query_counts[i] = 0;
|
||||
+ check_forward (AF_INET);
|
||||
+ check_forward (AF_INET6);
|
||||
+ check_forward (AF_UNSPEC);
|
||||
+
|
||||
+ for (int i = 0; i < nscount; ++i)
|
||||
+ {
|
||||
+ if (i != disable_server && i != drop_server
|
||||
+ && query_counts[i] == 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: nscount=%d, but no query to server %d\n",
|
||||
+ nscount, i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (aux);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TIMEOUT 300
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,366 @@
|
|||
commit 09fbb56ad69b9e02fb3710a9234566536a96facf
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 11:31:23 2017 +0200
|
||||
|
||||
resolv: Remove DEBUG from resolv/res_send.c
|
||||
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 1dbe30088167636c..18308709542da6e6 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -103,7 +103,6 @@
|
||||
#include <netdb.h>
|
||||
#include <resolv/resolv-internal.h>
|
||||
#include <signal.h>
|
||||
-#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -182,10 +181,6 @@ evNowTime(struct timespec *res) {
|
||||
}
|
||||
|
||||
|
||||
-/* Options. Leave them on. */
|
||||
-/* #undef DEBUG */
|
||||
-#include "res_debug.h"
|
||||
-
|
||||
#define EXT(res) ((res)->_u._ext)
|
||||
|
||||
/* Forward. */
|
||||
@@ -200,11 +195,6 @@ static int send_dg(res_state, const u_char *, int,
|
||||
u_char **, int *, int *, int,
|
||||
int *, int *, u_char **,
|
||||
u_char **, int *, int *, int *);
|
||||
-#ifdef DEBUG
|
||||
-static void Aerror(const res_state, FILE *, const char *, int,
|
||||
- const struct sockaddr *);
|
||||
-static void Perror(const res_state, FILE *, const char *, int);
|
||||
-#endif
|
||||
static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
|
||||
|
||||
/* Public. */
|
||||
@@ -422,8 +412,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
return (-1);
|
||||
}
|
||||
|
||||
- DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
|
||||
- (stdout, ";; res_send()\n"), buf, buflen);
|
||||
v_circuit = ((statp->options & RES_USEVC)
|
||||
|| buflen > PACKETSZ
|
||||
|| buflen2 > PACKETSZ);
|
||||
@@ -493,20 +481,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
unsigned int ns = ns_shift + ns_offset;
|
||||
if (ns >= statp->nscount)
|
||||
ns -= statp->nscount;
|
||||
-#ifdef DEBUG
|
||||
- char tmpbuf[40];
|
||||
- struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||||
-#endif
|
||||
|
||||
same_ns:
|
||||
- Dprint(statp->options & RES_DEBUG,
|
||||
- (stdout, ";; Querying server (# %d) address = %s\n",
|
||||
- ns + 1, inet_ntop(nsap->sa_family,
|
||||
- (nsap->sa_family == AF_INET6
|
||||
- ? (void *) &((struct sockaddr_in6 *) nsap)->sin6_addr
|
||||
- : (void *) &((struct sockaddr_in *) nsap)->sin_addr),
|
||||
- tmpbuf, sizeof (tmpbuf))));
|
||||
-
|
||||
if (__glibc_unlikely (v_circuit)) {
|
||||
/* Use VC; at most one attempt per server. */
|
||||
try = statp->retry;
|
||||
@@ -536,22 +512,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
|
||||
resplen = n;
|
||||
|
||||
- Dprint((statp->options & RES_DEBUG) ||
|
||||
- ((statp->pfcode & RES_PRF_REPLY) &&
|
||||
- (statp->pfcode & RES_PRF_HEAD1)),
|
||||
- (stdout, ";; got answer:\n"));
|
||||
-
|
||||
- DprintQ((statp->options & RES_DEBUG) ||
|
||||
- (statp->pfcode & RES_PRF_REPLY),
|
||||
- (stdout, "%s", ""),
|
||||
- ans, (resplen > anssiz) ? anssiz : resplen);
|
||||
- if (buf2 != NULL) {
|
||||
- DprintQ((statp->options & RES_DEBUG) ||
|
||||
- (statp->pfcode & RES_PRF_REPLY),
|
||||
- (stdout, "%s", ""),
|
||||
- *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* If we have temporarily opened a virtual circuit,
|
||||
* or if we haven't been asked to keep a socket open,
|
||||
@@ -741,7 +701,6 @@ send_vc(res_state statp,
|
||||
(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (statp->_vcsock < 0) {
|
||||
*terrno = errno;
|
||||
- Perror(statp, stderr, "socket(vc)", errno);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return (-1);
|
||||
@@ -752,7 +711,6 @@ send_vc(res_state statp,
|
||||
? sizeof (struct sockaddr_in)
|
||||
: sizeof (struct sockaddr_in6)) < 0) {
|
||||
*terrno = errno;
|
||||
- Aerror(statp, stderr, "connect/vc", errno, nsap);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
statp->_flags |= RES_F_VC;
|
||||
@@ -775,7 +733,6 @@ send_vc(res_state statp,
|
||||
}
|
||||
if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
|
||||
*terrno = errno;
|
||||
- Perror(statp, stderr, "write failed", errno);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
/*
|
||||
@@ -797,7 +754,6 @@ send_vc(res_state statp,
|
||||
}
|
||||
if (n <= 0) {
|
||||
*terrno = errno;
|
||||
- Perror(statp, stderr, "read failed", errno);
|
||||
/*
|
||||
* A long running process might get its TCP
|
||||
* connection reset if the remote server was
|
||||
@@ -860,9 +816,6 @@ send_vc(res_state statp,
|
||||
read RLEN bytes instead. */
|
||||
len = rlen;
|
||||
} else {
|
||||
- Dprint(statp->options & RES_DEBUG,
|
||||
- (stdout, ";; response truncated\n")
|
||||
- );
|
||||
truncating = 1;
|
||||
len = *thisanssizp;
|
||||
}
|
||||
@@ -873,8 +826,6 @@ send_vc(res_state statp,
|
||||
/*
|
||||
* Undersized message.
|
||||
*/
|
||||
- Dprint(statp->options & RES_DEBUG,
|
||||
- (stdout, ";; undersized: %d\n", len));
|
||||
*terrno = EMSGSIZE;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
@@ -886,7 +837,6 @@ send_vc(res_state statp,
|
||||
}
|
||||
if (__glibc_unlikely (n <= 0)) {
|
||||
*terrno = errno;
|
||||
- Perror(statp, stderr, "read(vc)", errno);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
if (__glibc_unlikely (truncating)) {
|
||||
@@ -914,14 +864,8 @@ send_vc(res_state statp,
|
||||
* wait for the correct one.
|
||||
*/
|
||||
if ((recvresp1 || hp->id != anhp->id)
|
||||
- && (recvresp2 || hp2->id != anhp->id)) {
|
||||
- DprintQ((statp->options & RES_DEBUG) ||
|
||||
- (statp->pfcode & RES_PRF_REPLY),
|
||||
- (stdout, ";; old answer (unexpected):\n"),
|
||||
- *thisansp,
|
||||
- (rlen > *thisanssizp) ? *thisanssizp: rlen);
|
||||
+ && (recvresp2 || hp2->id != anhp->id))
|
||||
goto read_len;
|
||||
- }
|
||||
|
||||
/* Mark which reply we received. */
|
||||
if (recvresp1 == 0 && hp->id == anhp->id)
|
||||
@@ -962,7 +906,6 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
}
|
||||
if (EXT(statp).nssocks[ns] < 0) {
|
||||
*terrno = errno;
|
||||
- Perror(statp, stderr, "socket(dg)", errno);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -987,7 +930,6 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||||
if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
- Aerror(statp, stderr, "connect(dg)", errno, nsap);
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
}
|
||||
@@ -1112,7 +1054,6 @@ send_dg(res_state statp,
|
||||
evNowTime(&now);
|
||||
if (evCmpTime(finish, now) <= 0) {
|
||||
poll_err_out:
|
||||
- Perror(statp, stderr, "poll", errno);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
evSubTime(&timeout, &finish, &now);
|
||||
@@ -1129,7 +1070,6 @@ send_dg(res_state statp,
|
||||
need_recompute = 1;
|
||||
}
|
||||
if (n == 0) {
|
||||
- Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
|
||||
if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
|
||||
{
|
||||
/* There are quite a few broken name servers out
|
||||
@@ -1229,7 +1169,6 @@ send_dg(res_state statp,
|
||||
#endif
|
||||
|
||||
fail_sendmmsg:
|
||||
- Perror(statp, stderr, "sendmmsg", errno);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
}
|
||||
@@ -1247,7 +1186,6 @@ send_dg(res_state statp,
|
||||
if (sr != (nwritten != 0 ? buflen2 : buflen)) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
goto recompute_resend;
|
||||
- Perror(statp, stderr, "send", errno);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
just_one:
|
||||
@@ -1308,12 +1246,6 @@ send_dg(res_state statp,
|
||||
MSG_TRUNC which is only available on Linux. We
|
||||
can abstract out the Linux-specific feature in the
|
||||
future to detect truncation. */
|
||||
- if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
|
||||
- Dprint(statp->options & RES_DEBUG,
|
||||
- (stdout, ";; response may be truncated (UDP)\n")
|
||||
- );
|
||||
- }
|
||||
-
|
||||
HEADER *anhp = (HEADER *) *thisansp;
|
||||
socklen_t fromlen = sizeof(struct sockaddr_in6);
|
||||
assert (sizeof(from) <= fromlen);
|
||||
@@ -1325,7 +1257,6 @@ send_dg(res_state statp,
|
||||
need_recompute = 1;
|
||||
goto wait;
|
||||
}
|
||||
- Perror(statp, stderr, "recvfrom", errno);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
*gotsomewhere = 1;
|
||||
@@ -1333,9 +1264,6 @@ send_dg(res_state statp,
|
||||
/*
|
||||
* Undersized message.
|
||||
*/
|
||||
- Dprint(statp->options & RES_DEBUG,
|
||||
- (stdout, ";; undersized: %d\n",
|
||||
- *thisresplenp));
|
||||
*terrno = EMSGSIZE;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
@@ -1346,12 +1274,6 @@ send_dg(res_state statp,
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
- DprintQ((statp->options & RES_DEBUG) ||
|
||||
- (statp->pfcode & RES_PRF_REPLY),
|
||||
- (stdout, ";; old answer:\n"),
|
||||
- *thisansp,
|
||||
- (*thisresplenp > *thisanssizp)
|
||||
- ? *thisanssizp : *thisresplenp);
|
||||
goto wait;
|
||||
}
|
||||
if (!(statp->options & RES_INSECURE1) &&
|
||||
@@ -1361,12 +1283,6 @@ send_dg(res_state statp,
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
- DprintQ((statp->options & RES_DEBUG) ||
|
||||
- (statp->pfcode & RES_PRF_REPLY),
|
||||
- (stdout, ";; not our server:\n"),
|
||||
- *thisansp,
|
||||
- (*thisresplenp > *thisanssizp)
|
||||
- ? *thisanssizp : *thisresplenp);
|
||||
goto wait;
|
||||
}
|
||||
if (!(statp->options & RES_INSECURE2)
|
||||
@@ -1383,23 +1299,11 @@ send_dg(res_state statp,
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
- DprintQ((statp->options & RES_DEBUG) ||
|
||||
- (statp->pfcode & RES_PRF_REPLY),
|
||||
- (stdout, ";; wrong query name:\n"),
|
||||
- *thisansp,
|
||||
- (*thisresplenp > *thisanssizp)
|
||||
- ? *thisanssizp : *thisresplenp);
|
||||
goto wait;
|
||||
}
|
||||
if (anhp->rcode == SERVFAIL ||
|
||||
anhp->rcode == NOTIMP ||
|
||||
anhp->rcode == REFUSED) {
|
||||
- DprintQ(statp->options & RES_DEBUG,
|
||||
- (stdout, "server rejected query:\n"),
|
||||
- *thisansp,
|
||||
- (*thisresplenp > *thisanssizp)
|
||||
- ? *thisanssizp : *thisresplenp);
|
||||
-
|
||||
next_ns:
|
||||
if (recvresp1 || (buf2 != NULL && recvresp2)) {
|
||||
*resplen2 = 0;
|
||||
@@ -1425,11 +1329,6 @@ send_dg(res_state statp,
|
||||
}
|
||||
if (anhp->rcode == NOERROR && anhp->ancount == 0
|
||||
&& anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
|
||||
- DprintQ(statp->options & RES_DEBUG,
|
||||
- (stdout, "referred query:\n"),
|
||||
- *thisansp,
|
||||
- (*thisresplenp > *thisanssizp)
|
||||
- ? *thisanssizp : *thisresplenp);
|
||||
goto next_ns;
|
||||
}
|
||||
if (!(statp->options & RES_IGNTC) && anhp->tc) {
|
||||
@@ -1437,8 +1336,6 @@ send_dg(res_state statp,
|
||||
* To get the rest of answer,
|
||||
* use TCP with same server.
|
||||
*/
|
||||
- Dprint(statp->options & RES_DEBUG,
|
||||
- (stdout, ";; truncated answer\n"));
|
||||
*v_circuit = 1;
|
||||
__res_iclose(statp, false);
|
||||
// XXX if we have received one reply we could
|
||||
@@ -1482,46 +1379,6 @@ send_dg(res_state statp,
|
||||
}
|
||||
}
|
||||
|
||||
-#ifdef DEBUG
|
||||
-static void
|
||||
-Aerror(const res_state statp, FILE *file, const char *string, int error,
|
||||
- const struct sockaddr *address)
|
||||
-{
|
||||
- int save = errno;
|
||||
-
|
||||
- if ((statp->options & RES_DEBUG) != 0) {
|
||||
- char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
|
||||
-
|
||||
- fprintf(file, "res_send: %s ([%s].%u): %s\n",
|
||||
- string,
|
||||
- (address->sa_family == AF_INET
|
||||
- ? inet_ntop(address->sa_family,
|
||||
- &((const struct sockaddr_in *) address)->sin_addr,
|
||||
- tmp, sizeof tmp)
|
||||
- : inet_ntop(address->sa_family,
|
||||
- &((const struct sockaddr_in6 *) address)->sin6_addr,
|
||||
- tmp, sizeof tmp)),
|
||||
- (address->sa_family == AF_INET
|
||||
- ? ntohs(((struct sockaddr_in *) address)->sin_port)
|
||||
- : address->sa_family == AF_INET6
|
||||
- ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
|
||||
- : 0),
|
||||
- strerror(error));
|
||||
- }
|
||||
- __set_errno (save);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-Perror(const res_state statp, FILE *file, const char *string, int error) {
|
||||
- int save = errno;
|
||||
-
|
||||
- if ((statp->options & RES_DEBUG) != 0)
|
||||
- fprintf(file, "res_send: %s: %s\n",
|
||||
- string, strerror(error));
|
||||
- __set_errno (save);
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
static int
|
||||
sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
|
||||
if (a1->sin6_family == a2->sin6_family) {
|
|
@ -0,0 +1,59 @@
|
|||
commit e68111fbd63e84b66bd9e03b42721c79230b9b6d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 13:18:45 2017 +0200
|
||||
|
||||
resolv: Remove DEBUG preprocessor conditionals from res_setoptions
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index eb380d3d56bc018c..eb24fca3a6ecef9a 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -83,9 +83,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <inet/net-internal.h>
|
||||
|
||||
-/* Options. Should all be left alone. */
|
||||
-/* #undef DEBUG */
|
||||
-
|
||||
static void res_setoptions (res_state, const char *, const char *)
|
||||
internal_function;
|
||||
|
||||
@@ -383,11 +380,6 @@ res_setoptions(res_state statp, const char *options, const char *source) {
|
||||
const char *cp = options;
|
||||
int i;
|
||||
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";; res_setoptions(\"%s\", \"%s\")...\n",
|
||||
- options, source);
|
||||
-#endif
|
||||
while (*cp) {
|
||||
/* skip leading and inner runs of spaces */
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
@@ -399,10 +391,6 @@ res_setoptions(res_state statp, const char *options, const char *source) {
|
||||
statp->ndots = i;
|
||||
else
|
||||
statp->ndots = RES_MAXNDOTS;
|
||||
-#ifdef DEBUG
|
||||
- if (statp->options & RES_DEBUG)
|
||||
- printf(";;\tndots=%d\n", statp->ndots);
|
||||
-#endif
|
||||
} else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
|
||||
i = atoi(cp + sizeof("timeout:") - 1);
|
||||
if (i <= RES_MAXRETRANS)
|
||||
@@ -415,15 +403,6 @@ res_setoptions(res_state statp, const char *options, const char *source) {
|
||||
statp->retry = i;
|
||||
else
|
||||
statp->retry = RES_MAXRETRY;
|
||||
- } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
|
||||
-#ifdef DEBUG
|
||||
- if (!(statp->options & RES_DEBUG)) {
|
||||
- printf(";; res_setoptions(\"%s\", \"%s\")..\n",
|
||||
- options, source);
|
||||
- statp->options |= RES_DEBUG;
|
||||
- }
|
||||
- printf(";;\tdebug\n");
|
||||
-#endif
|
||||
} else {
|
||||
static const struct
|
||||
{
|
|
@ -0,0 +1,211 @@
|
|||
commit ea4924ce5bccfccc4e8a492faa96933131abd9ef
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 14:05:49 2017 +0200
|
||||
|
||||
resolv: Report allocation errors in __res_vinit
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index f121aa3de73704ea..206924de8603b4dd 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -164,7 +164,11 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
||||
enum nss_status status;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
@@ -289,7 +293,11 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
int *herrnop, int32_t *ttlp)
|
||||
{
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *herrnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* if there aren't any dots, it could be a user-level alias.
|
||||
@@ -416,7 +424,11 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
host_data = (struct host_data *) buffer;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
|
||||
if (af == AF_INET6 && len == IN6ADDRSZ
|
||||
&& (memcmp (uaddr, mapped, sizeof mapped) == 0
|
||||
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
|
||||
index 2be72d33a30f917e..dc1599b47122fea2 100644
|
||||
--- a/resolv/nss_dns/dns-network.c
|
||||
+++ b/resolv/nss_dns/dns-network.c
|
||||
@@ -116,7 +116,11 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
|
||||
enum nss_status status;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *herrnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
|
||||
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
|
||||
|
||||
@@ -166,7 +170,11 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *herrnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
|
||||
net2 = (u_int32_t) net;
|
||||
for (cnt = 4; net2 != 0; net2 >>= 8)
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 49fc94595bfe147f..e604a0212fa13624 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -100,6 +100,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <inet/net-internal.h>
|
||||
+#include <errno.h>
|
||||
|
||||
static void res_setoptions (res_state, const char *, const char *);
|
||||
static uint32_t net_mask (struct in_addr);
|
||||
@@ -121,14 +122,11 @@ is_sort_mask (char ch)
|
||||
return ch == '/' || ch == '&';
|
||||
}
|
||||
|
||||
-/* Set up default settings. If the /etc/resolv.conf configuration
|
||||
- file exist, the values there will have precedence. Otherwise, the
|
||||
- server address is set to INADDR_LOOPBACK and the default domain
|
||||
- name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN
|
||||
- environment variables can be used to override some settings.
|
||||
- Return 0 if completes successfully, -1 on error. */
|
||||
-int
|
||||
-__res_vinit (res_state statp, int preinit)
|
||||
+/* Internal helper function for __res_vinit, to aid with resource
|
||||
+ deallocation and error handling. Return true on success, false on
|
||||
+ failure. */
|
||||
+static bool
|
||||
+res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
{
|
||||
char *cp, **pp;
|
||||
char buf[BUFSIZ];
|
||||
@@ -203,7 +201,6 @@ __res_vinit (res_state statp, int preinit)
|
||||
&& (line[sizeof (name) - 1] == ' ' \
|
||||
|| line[sizeof (name) - 1] == '\t'))
|
||||
|
||||
- FILE *fp = fopen (_PATH_RESCONF, "rce");
|
||||
if (fp != NULL)
|
||||
{
|
||||
/* No threads use this stream. */
|
||||
@@ -302,26 +299,26 @@ __res_vinit (res_state statp, int preinit)
|
||||
struct sockaddr_in6 *sa6;
|
||||
|
||||
sa6 = malloc (sizeof (*sa6));
|
||||
- if (sa6 != NULL)
|
||||
- {
|
||||
- sa6->sin6_family = AF_INET6;
|
||||
- sa6->sin6_port = htons (NAMESERVER_PORT);
|
||||
- sa6->sin6_flowinfo = 0;
|
||||
- sa6->sin6_addr = a6;
|
||||
-
|
||||
- sa6->sin6_scope_id = 0;
|
||||
- if (__glibc_likely (el != NULL))
|
||||
- /* Ignore errors, for backwards
|
||||
- compatibility. */
|
||||
- __inet6_scopeid_pton
|
||||
- (&a6, el + 1, &sa6->sin6_scope_id);
|
||||
-
|
||||
- statp->nsaddr_list[nserv].sin_family = 0;
|
||||
- statp->_u._ext.nsaddrs[nserv] = sa6;
|
||||
- statp->_u._ext.nssocks[nserv] = -1;
|
||||
- have_serv6 = true;
|
||||
- nserv++;
|
||||
- }
|
||||
+ if (sa6 == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ sa6->sin6_family = AF_INET6;
|
||||
+ sa6->sin6_port = htons (NAMESERVER_PORT);
|
||||
+ sa6->sin6_flowinfo = 0;
|
||||
+ sa6->sin6_addr = a6;
|
||||
+
|
||||
+ sa6->sin6_scope_id = 0;
|
||||
+ if (__glibc_likely (el != NULL))
|
||||
+ /* Ignore errors, for backwards
|
||||
+ compatibility. */
|
||||
+ __inet6_scopeid_pton
|
||||
+ (&a6, el + 1, &sa6->sin6_scope_id);
|
||||
+
|
||||
+ statp->nsaddr_list[nserv].sin_family = 0;
|
||||
+ statp->_u._ext.nsaddrs[nserv] = sa6;
|
||||
+ statp->_u._ext.nssocks[nserv] = -1;
|
||||
+ have_serv6 = true;
|
||||
+ nserv++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -410,6 +407,44 @@ __res_vinit (res_state statp, int preinit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Set up default settings. If the /etc/resolv.conf configuration
|
||||
+ file exist, the values there will have precedence. Otherwise, the
|
||||
+ server address is set to INADDR_LOOPBACK and the default domain
|
||||
+ name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN
|
||||
+ environment variables can be used to override some settings.
|
||||
+ Return 0 if completes successfully, -1 on error. */
|
||||
+int
|
||||
+__res_vinit (res_state statp, int preinit)
|
||||
+{
|
||||
+ FILE *fp = fopen (_PATH_RESCONF, "rce");
|
||||
+ if (fp == NULL)
|
||||
+ switch (errno)
|
||||
+ {
|
||||
+ case EACCES:
|
||||
+ case EISDIR:
|
||||
+ case ELOOP:
|
||||
+ case ENOENT:
|
||||
+ case ENOTDIR:
|
||||
+ case EPERM:
|
||||
+ /* Ignore these errors. They are persistent errors caused
|
||||
+ by file system contents. */
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* Other errors refer to resource allocation problems and
|
||||
+ need to be handled by the application. */
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (!res_vinit_1 (statp, preinit, fp))
|
||||
+ {
|
||||
+ /* Deallocate the name server addresses which have been
|
||||
+ allocated. */
|
||||
+ for (int n = 0; n < MAXNS; n++)
|
||||
+ free (statp->_u._ext.nsaddrs[n]);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
res_setoptions (res_state statp, const char *options, const char *source)
|
||||
{
|
|
@ -0,0 +1,759 @@
|
|||
commit 4c4480eecb2e00764dd3bf79d68ea4e1d747d78c
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 13:20:46 2017 +0200
|
||||
|
||||
resolv: Reformat res_vinit and related functions to GNU style
|
||||
|
||||
Also remove some obsolete comments.
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index eb8e308fdaa899ef..49fc94595bfe147f 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -1,3 +1,21 @@
|
||||
+/* Resolver state initialization and resolv.conf parsing.
|
||||
+ Copyright (C) 1995-2017 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/>. */
|
||||
+
|
||||
/*
|
||||
* Copyright (c) 1985, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@@ -83,26 +101,15 @@
|
||||
#include <sys/types.h>
|
||||
#include <inet/net-internal.h>
|
||||
|
||||
-static void res_setoptions (res_state, const char *, const char *)
|
||||
- internal_function;
|
||||
-static u_int32_t net_mask (struct in_addr) __THROW;
|
||||
+static void res_setoptions (res_state, const char *, const char *);
|
||||
+static uint32_t net_mask (struct in_addr);
|
||||
|
||||
unsigned long long int __res_initstamp attribute_hidden;
|
||||
|
||||
-/*
|
||||
- * Resolver state default settings.
|
||||
- */
|
||||
-
|
||||
-/*
|
||||
- * Set up default settings. If the configuration file exist, the values
|
||||
- * there will have precedence. Otherwise, the server address is set to
|
||||
- * INADDR_LOOPBACK and the default domain name comes from gethostname.
|
||||
- *
|
||||
- * Return 0 if completes successfully, -1 on error
|
||||
- */
|
||||
int
|
||||
-res_ninit(res_state statp) {
|
||||
- return (__res_vinit(statp, 0));
|
||||
+res_ninit (res_state statp)
|
||||
+{
|
||||
+ return __res_vinit (statp, 0);
|
||||
}
|
||||
libc_hidden_def (__res_ninit)
|
||||
|
||||
@@ -114,349 +121,374 @@ is_sort_mask (char ch)
|
||||
return ch == '/' || ch == '&';
|
||||
}
|
||||
|
||||
-/* This function has to be reachable by res_data.c but not publically. */
|
||||
+/* Set up default settings. If the /etc/resolv.conf configuration
|
||||
+ file exist, the values there will have precedence. Otherwise, the
|
||||
+ server address is set to INADDR_LOOPBACK and the default domain
|
||||
+ name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN
|
||||
+ environment variables can be used to override some settings.
|
||||
+ Return 0 if completes successfully, -1 on error. */
|
||||
int
|
||||
-__res_vinit(res_state statp, int preinit) {
|
||||
- FILE *fp;
|
||||
- char *cp, **pp;
|
||||
- int n;
|
||||
- char buf[BUFSIZ];
|
||||
- int nserv = 0; /* number of nameservers read from file */
|
||||
- int have_serv6 = 0;
|
||||
- int haveenv = 0;
|
||||
- int havesearch = 0;
|
||||
- int nsort = 0;
|
||||
- char *net;
|
||||
- statp->_u._ext.initstamp = __res_initstamp;
|
||||
+__res_vinit (res_state statp, int preinit)
|
||||
+{
|
||||
+ char *cp, **pp;
|
||||
+ char buf[BUFSIZ];
|
||||
+ int nserv = 0; /* Number of nameservers read from file. */
|
||||
+ bool have_serv6 = false;
|
||||
+ bool haveenv = false;
|
||||
+ bool havesearch = false;
|
||||
+ int nsort = 0;
|
||||
+ char *net;
|
||||
+ statp->_u._ext.initstamp = __res_initstamp;
|
||||
|
||||
- if (!preinit) {
|
||||
- statp->retrans = RES_TIMEOUT;
|
||||
- statp->retry = RES_DFLRETRY;
|
||||
- statp->options = RES_DEFAULT;
|
||||
- statp->id = res_randomid();
|
||||
- }
|
||||
+ if (!preinit)
|
||||
+ {
|
||||
+ statp->retrans = RES_TIMEOUT;
|
||||
+ statp->retry = RES_DFLRETRY;
|
||||
+ statp->options = RES_DEFAULT;
|
||||
+ statp->id = res_randomid ();
|
||||
+ }
|
||||
|
||||
- statp->nscount = 0;
|
||||
- statp->defdname[0] = '\0';
|
||||
- statp->ndots = 1;
|
||||
- statp->pfcode = 0;
|
||||
- statp->_vcsock = -1;
|
||||
- statp->_flags = 0;
|
||||
- statp->__glibc_unused_qhook = NULL;
|
||||
- statp->__glibc_unused_rhook = NULL;
|
||||
- statp->_u._ext.nscount = 0;
|
||||
- for (n = 0; n < MAXNS; n++)
|
||||
- statp->_u._ext.nsaddrs[n] = NULL;
|
||||
+ statp->nscount = 0;
|
||||
+ statp->defdname[0] = '\0';
|
||||
+ statp->ndots = 1;
|
||||
+ statp->pfcode = 0;
|
||||
+ statp->_vcsock = -1;
|
||||
+ statp->_flags = 0;
|
||||
+ statp->__glibc_unused_qhook = NULL;
|
||||
+ statp->__glibc_unused_rhook = NULL;
|
||||
+ statp->_u._ext.nscount = 0;
|
||||
+ for (int n = 0; n < MAXNS; n++)
|
||||
+ statp->_u._ext.nsaddrs[n] = NULL;
|
||||
|
||||
- /* Allow user to override the local domain definition */
|
||||
- if ((cp = getenv("LOCALDOMAIN")) != NULL) {
|
||||
- (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
|
||||
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
|
||||
- haveenv++;
|
||||
+ /* Allow user to override the local domain definition. */
|
||||
+ if ((cp = getenv ("LOCALDOMAIN")) != NULL)
|
||||
+ {
|
||||
+ strncpy (statp->defdname, cp, sizeof (statp->defdname) - 1);
|
||||
+ statp->defdname[sizeof (statp->defdname) - 1] = '\0';
|
||||
+ haveenv = true;
|
||||
|
||||
- /*
|
||||
- * Set search list to be blank-separated strings
|
||||
- * from rest of env value. Permits users of LOCALDOMAIN
|
||||
- * to still have a search list, and anyone to set the
|
||||
- * one that they want to use as an individual (even more
|
||||
- * important now that the rfc1535 stuff restricts searches)
|
||||
- */
|
||||
- cp = statp->defdname;
|
||||
- pp = statp->dnsrch;
|
||||
- *pp++ = cp;
|
||||
- for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
|
||||
- if (*cp == '\n') /* silly backwards compat */
|
||||
- break;
|
||||
- else if (*cp == ' ' || *cp == '\t') {
|
||||
- *cp = 0;
|
||||
- n = 1;
|
||||
- } else if (n) {
|
||||
- *pp++ = cp;
|
||||
- n = 0;
|
||||
- havesearch = 1;
|
||||
- }
|
||||
- }
|
||||
- /* null terminate last domain if there are excess */
|
||||
- while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
- cp++;
|
||||
- *cp = '\0';
|
||||
- *pp++ = 0;
|
||||
- }
|
||||
+ /* Set search list to be blank-separated strings from rest of
|
||||
+ env value. Permits users of LOCALDOMAIN to still have a
|
||||
+ search list, and anyone to set the one that they want to use
|
||||
+ as an individual (even more important now that the rfc1535
|
||||
+ stuff restricts searches). */
|
||||
+ cp = statp->defdname;
|
||||
+ pp = statp->dnsrch;
|
||||
+ *pp++ = cp;
|
||||
+ for (int n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++)
|
||||
+ {
|
||||
+ if (*cp == '\n')
|
||||
+ break;
|
||||
+ else if (*cp == ' ' || *cp == '\t')
|
||||
+ {
|
||||
+ *cp = 0;
|
||||
+ n = 1;
|
||||
+ }
|
||||
+ else if (n > 0)
|
||||
+ {
|
||||
+ *pp++ = cp;
|
||||
+ n = 0;
|
||||
+ havesearch = true;
|
||||
+ }
|
||||
+ }
|
||||
+ /* Null terminate last domain if there are excess. */
|
||||
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
+ cp++;
|
||||
+ *cp = '\0';
|
||||
+ *pp++ = 0;
|
||||
+ }
|
||||
|
||||
-#define MATCH(line, name) \
|
||||
- (!strncmp(line, name, sizeof(name) - 1) && \
|
||||
- (line[sizeof(name) - 1] == ' ' || \
|
||||
- line[sizeof(name) - 1] == '\t'))
|
||||
+#define MATCH(line, name) \
|
||||
+ (!strncmp (line, name, sizeof (name) - 1) \
|
||||
+ && (line[sizeof (name) - 1] == ' ' \
|
||||
+ || line[sizeof (name) - 1] == '\t'))
|
||||
|
||||
- if ((fp = fopen(_PATH_RESCONF, "rce")) != NULL) {
|
||||
- /* No threads use this stream. */
|
||||
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
- /* read the config file */
|
||||
- while (__fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
|
||||
- /* skip comments */
|
||||
- if (*buf == ';' || *buf == '#')
|
||||
- continue;
|
||||
- /* read default domain name */
|
||||
- if (MATCH(buf, "domain")) {
|
||||
- if (haveenv) /* skip if have from environ */
|
||||
- continue;
|
||||
- cp = buf + sizeof("domain") - 1;
|
||||
- while (*cp == ' ' || *cp == '\t')
|
||||
- cp++;
|
||||
- if ((*cp == '\0') || (*cp == '\n'))
|
||||
- continue;
|
||||
- strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
|
||||
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
|
||||
- if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
|
||||
- *cp = '\0';
|
||||
- havesearch = 0;
|
||||
- continue;
|
||||
- }
|
||||
- /* set search list */
|
||||
- if (MATCH(buf, "search")) {
|
||||
- if (haveenv) /* skip if have from environ */
|
||||
- continue;
|
||||
- cp = buf + sizeof("search") - 1;
|
||||
- while (*cp == ' ' || *cp == '\t')
|
||||
- cp++;
|
||||
- if ((*cp == '\0') || (*cp == '\n'))
|
||||
- continue;
|
||||
- strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
|
||||
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
|
||||
- if ((cp = strchr(statp->defdname, '\n')) != NULL)
|
||||
- *cp = '\0';
|
||||
- /*
|
||||
- * Set search list to be blank-separated strings
|
||||
- * on rest of line.
|
||||
- */
|
||||
- cp = statp->defdname;
|
||||
- pp = statp->dnsrch;
|
||||
- *pp++ = cp;
|
||||
- for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
|
||||
- if (*cp == ' ' || *cp == '\t') {
|
||||
- *cp = 0;
|
||||
- n = 1;
|
||||
- } else if (n) {
|
||||
- *pp++ = cp;
|
||||
- n = 0;
|
||||
- }
|
||||
- }
|
||||
- /* null terminate last domain if there are excess */
|
||||
- while (*cp != '\0' && *cp != ' ' && *cp != '\t')
|
||||
- cp++;
|
||||
- *cp = '\0';
|
||||
- *pp++ = 0;
|
||||
- havesearch = 1;
|
||||
- continue;
|
||||
- }
|
||||
- /* read nameservers to query */
|
||||
- if (MATCH(buf, "nameserver") && nserv < MAXNS) {
|
||||
- struct in_addr a;
|
||||
+ FILE *fp = fopen (_PATH_RESCONF, "rce");
|
||||
+ if (fp != NULL)
|
||||
+ {
|
||||
+ /* No threads use this stream. */
|
||||
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
+ /* Read the config file. */
|
||||
+ while (__fgets_unlocked (buf, sizeof (buf), fp) != NULL)
|
||||
+ {
|
||||
+ /* Skip comments. */
|
||||
+ if (*buf == ';' || *buf == '#')
|
||||
+ continue;
|
||||
+ /* Read default domain name. */
|
||||
+ if (MATCH (buf, "domain"))
|
||||
+ {
|
||||
+ if (haveenv)
|
||||
+ /* LOCALDOMAIN overrides the configuration file. */
|
||||
+ continue;
|
||||
+ cp = buf + sizeof ("domain") - 1;
|
||||
+ while (*cp == ' ' || *cp == '\t')
|
||||
+ cp++;
|
||||
+ if ((*cp == '\0') || (*cp == '\n'))
|
||||
+ continue;
|
||||
+ strncpy (statp->defdname, cp, sizeof (statp->defdname) - 1);
|
||||
+ statp->defdname[sizeof (statp->defdname) - 1] = '\0';
|
||||
+ if ((cp = strpbrk (statp->defdname, " \t\n")) != NULL)
|
||||
+ *cp = '\0';
|
||||
+ havesearch = false;
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* Set search list. */
|
||||
+ if (MATCH (buf, "search"))
|
||||
+ {
|
||||
+ if (haveenv)
|
||||
+ /* LOCALDOMAIN overrides the configuration file. */
|
||||
+ continue;
|
||||
+ cp = buf + sizeof ("search") - 1;
|
||||
+ while (*cp == ' ' || *cp == '\t')
|
||||
+ cp++;
|
||||
+ if ((*cp == '\0') || (*cp == '\n'))
|
||||
+ continue;
|
||||
+ strncpy (statp->defdname, cp, sizeof (statp->defdname) - 1);
|
||||
+ statp->defdname[sizeof (statp->defdname) - 1] = '\0';
|
||||
+ if ((cp = strchr (statp->defdname, '\n')) != NULL)
|
||||
+ *cp = '\0';
|
||||
+ /* Set search list to be blank-separated strings on rest
|
||||
+ of line. */
|
||||
+ cp = statp->defdname;
|
||||
+ pp = statp->dnsrch;
|
||||
+ *pp++ = cp;
|
||||
+ for (int n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++)
|
||||
+ {
|
||||
+ if (*cp == ' ' || *cp == '\t')
|
||||
+ {
|
||||
+ *cp = 0;
|
||||
+ n = 1;
|
||||
+ }
|
||||
+ else if (n)
|
||||
+ {
|
||||
+ *pp++ = cp;
|
||||
+ n = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ /* Null terminate last domain if there are excess. */
|
||||
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
|
||||
+ cp++;
|
||||
+ *cp = '\0';
|
||||
+ *pp++ = 0;
|
||||
+ havesearch = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* Read nameservers to query. */
|
||||
+ if (MATCH (buf, "nameserver") && nserv < MAXNS)
|
||||
+ {
|
||||
+ struct in_addr a;
|
||||
|
||||
- cp = buf + sizeof("nameserver") - 1;
|
||||
- while (*cp == ' ' || *cp == '\t')
|
||||
- cp++;
|
||||
- if ((*cp != '\0') && (*cp != '\n')
|
||||
- && __inet_aton(cp, &a)) {
|
||||
- statp->nsaddr_list[nserv].sin_addr = a;
|
||||
- statp->nsaddr_list[nserv].sin_family = AF_INET;
|
||||
- statp->nsaddr_list[nserv].sin_port =
|
||||
- htons(NAMESERVER_PORT);
|
||||
- nserv++;
|
||||
- } else {
|
||||
- struct in6_addr a6;
|
||||
- char *el;
|
||||
+ cp = buf + sizeof ("nameserver") - 1;
|
||||
+ while (*cp == ' ' || *cp == '\t')
|
||||
+ cp++;
|
||||
+ if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
|
||||
+ {
|
||||
+ statp->nsaddr_list[nserv].sin_addr = a;
|
||||
+ statp->nsaddr_list[nserv].sin_family = AF_INET;
|
||||
+ statp->nsaddr_list[nserv].sin_port = htons (NAMESERVER_PORT);
|
||||
+ nserv++;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ struct in6_addr a6;
|
||||
+ char *el;
|
||||
|
||||
- if ((el = strpbrk(cp, " \t\n")) != NULL)
|
||||
- *el = '\0';
|
||||
- if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL)
|
||||
- *el = '\0';
|
||||
- if ((*cp != '\0') &&
|
||||
- (__inet_pton(AF_INET6, cp, &a6) > 0)) {
|
||||
- struct sockaddr_in6 *sa6;
|
||||
+ if ((el = strpbrk (cp, " \t\n")) != NULL)
|
||||
+ *el = '\0';
|
||||
+ if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL)
|
||||
+ *el = '\0';
|
||||
+ if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0))
|
||||
+ {
|
||||
+ struct sockaddr_in6 *sa6;
|
||||
|
||||
- sa6 = malloc(sizeof(*sa6));
|
||||
- if (sa6 != NULL) {
|
||||
- sa6->sin6_family = AF_INET6;
|
||||
- sa6->sin6_port = htons(NAMESERVER_PORT);
|
||||
- sa6->sin6_flowinfo = 0;
|
||||
- sa6->sin6_addr = a6;
|
||||
+ sa6 = malloc (sizeof (*sa6));
|
||||
+ if (sa6 != NULL)
|
||||
+ {
|
||||
+ sa6->sin6_family = AF_INET6;
|
||||
+ sa6->sin6_port = htons (NAMESERVER_PORT);
|
||||
+ sa6->sin6_flowinfo = 0;
|
||||
+ sa6->sin6_addr = a6;
|
||||
|
||||
- sa6->sin6_scope_id = 0;
|
||||
- if (__glibc_likely (el != NULL)) {
|
||||
- /* Ignore errors, for backwards
|
||||
- compatibility. */
|
||||
- (void) __inet6_scopeid_pton
|
||||
- (&a6, el + 1, &sa6->sin6_scope_id);
|
||||
- }
|
||||
+ sa6->sin6_scope_id = 0;
|
||||
+ if (__glibc_likely (el != NULL))
|
||||
+ /* Ignore errors, for backwards
|
||||
+ compatibility. */
|
||||
+ __inet6_scopeid_pton
|
||||
+ (&a6, el + 1, &sa6->sin6_scope_id);
|
||||
|
||||
- statp->nsaddr_list[nserv].sin_family = 0;
|
||||
- statp->_u._ext.nsaddrs[nserv] = sa6;
|
||||
- statp->_u._ext.nssocks[nserv] = -1;
|
||||
- have_serv6 = 1;
|
||||
- nserv++;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- continue;
|
||||
- }
|
||||
- if (MATCH(buf, "sortlist")) {
|
||||
- struct in_addr a;
|
||||
+ statp->nsaddr_list[nserv].sin_family = 0;
|
||||
+ statp->_u._ext.nsaddrs[nserv] = sa6;
|
||||
+ statp->_u._ext.nssocks[nserv] = -1;
|
||||
+ have_serv6 = true;
|
||||
+ nserv++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (MATCH (buf, "sortlist"))
|
||||
+ {
|
||||
+ struct in_addr a;
|
||||
|
||||
- cp = buf + sizeof("sortlist") - 1;
|
||||
- while (nsort < MAXRESOLVSORT) {
|
||||
- while (*cp == ' ' || *cp == '\t')
|
||||
- cp++;
|
||||
- if (*cp == '\0' || *cp == '\n' || *cp == ';')
|
||||
- break;
|
||||
- net = cp;
|
||||
- while (*cp && !is_sort_mask (*cp) && *cp != ';' &&
|
||||
- isascii(*cp) && !isspace(*cp))
|
||||
- cp++;
|
||||
- n = *cp;
|
||||
- *cp = 0;
|
||||
- if (__inet_aton(net, &a)) {
|
||||
- statp->sort_list[nsort].addr = a;
|
||||
- if (is_sort_mask (n)) {
|
||||
- *cp++ = n;
|
||||
- net = cp;
|
||||
- while (*cp && *cp != ';' &&
|
||||
- isascii(*cp) && !isspace(*cp))
|
||||
- cp++;
|
||||
- n = *cp;
|
||||
- *cp = 0;
|
||||
- if (__inet_aton(net, &a)) {
|
||||
- statp->sort_list[nsort].mask = a.s_addr;
|
||||
- } else {
|
||||
- statp->sort_list[nsort].mask =
|
||||
- net_mask(statp->sort_list[nsort].addr);
|
||||
- }
|
||||
- } else {
|
||||
- statp->sort_list[nsort].mask =
|
||||
- net_mask(statp->sort_list[nsort].addr);
|
||||
- }
|
||||
- nsort++;
|
||||
- }
|
||||
- *cp = n;
|
||||
- }
|
||||
- continue;
|
||||
- }
|
||||
- if (MATCH(buf, "options")) {
|
||||
- res_setoptions(statp, buf + sizeof("options") - 1, "conf");
|
||||
- continue;
|
||||
- }
|
||||
- }
|
||||
- statp->nscount = nserv;
|
||||
- if (have_serv6) {
|
||||
- /* We try IPv6 servers again. */
|
||||
- statp->ipv6_unavail = false;
|
||||
- }
|
||||
- statp->nsort = nsort;
|
||||
- (void) fclose(fp);
|
||||
- }
|
||||
- if (__glibc_unlikely (statp->nscount == 0)) {
|
||||
- statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1);
|
||||
- statp->nsaddr.sin_family = AF_INET;
|
||||
- statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
|
||||
- statp->nscount = 1;
|
||||
- }
|
||||
- if (statp->defdname[0] == 0 &&
|
||||
- __gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
|
||||
- (cp = strchr(buf, '.')) != NULL)
|
||||
- strcpy(statp->defdname, cp + 1);
|
||||
+ cp = buf + sizeof ("sortlist") - 1;
|
||||
+ while (nsort < MAXRESOLVSORT)
|
||||
+ {
|
||||
+ while (*cp == ' ' || *cp == '\t')
|
||||
+ cp++;
|
||||
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
|
||||
+ break;
|
||||
+ net = cp;
|
||||
+ while (*cp && !is_sort_mask (*cp) && *cp != ';'
|
||||
+ && isascii (*cp) && !isspace (*cp))
|
||||
+ cp++;
|
||||
+ char separator = *cp;
|
||||
+ *cp = 0;
|
||||
+ if (__inet_aton (net, &a))
|
||||
+ {
|
||||
+ statp->sort_list[nsort].addr = a;
|
||||
+ if (is_sort_mask (separator))
|
||||
+ {
|
||||
+ *cp++ = separator;
|
||||
+ net = cp;
|
||||
+ while (*cp && *cp != ';'
|
||||
+ && isascii (*cp) && !isspace (*cp))
|
||||
+ cp++;
|
||||
+ separator = *cp;
|
||||
+ *cp = 0;
|
||||
+ if (__inet_aton (net, &a))
|
||||
+ statp->sort_list[nsort].mask = a.s_addr;
|
||||
+ else
|
||||
+ statp->sort_list[nsort].mask
|
||||
+ = net_mask (statp->sort_list[nsort].addr);
|
||||
+ }
|
||||
+ else
|
||||
+ statp->sort_list[nsort].mask
|
||||
+ = net_mask (statp->sort_list[nsort].addr);
|
||||
+ nsort++;
|
||||
+ }
|
||||
+ *cp = separator;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (MATCH (buf, "options"))
|
||||
+ {
|
||||
+ res_setoptions (statp, buf + sizeof ("options") - 1, "conf");
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ statp->nscount = nserv;
|
||||
+ if (have_serv6)
|
||||
+ /* We try IPv6 servers again. */
|
||||
+ statp->ipv6_unavail = false;
|
||||
+ statp->nsort = nsort;
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ if (__glibc_unlikely (statp->nscount == 0))
|
||||
+ {
|
||||
+ statp->nsaddr.sin_addr = __inet_makeaddr (IN_LOOPBACKNET, 1);
|
||||
+ statp->nsaddr.sin_family = AF_INET;
|
||||
+ statp->nsaddr.sin_port = htons (NAMESERVER_PORT);
|
||||
+ statp->nscount = 1;
|
||||
+ }
|
||||
+ if (statp->defdname[0] == 0
|
||||
+ && __gethostname (buf, sizeof (statp->defdname) - 1) == 0
|
||||
+ && (cp = strchr (buf, '.')) != NULL)
|
||||
+ strcpy (statp->defdname, cp + 1);
|
||||
|
||||
- /* find components of local domain that might be searched */
|
||||
- if (havesearch == 0) {
|
||||
- pp = statp->dnsrch;
|
||||
- *pp++ = statp->defdname;
|
||||
- *pp = NULL;
|
||||
+ /* Find components of local domain that might be searched. */
|
||||
+ if (!havesearch)
|
||||
+ {
|
||||
+ pp = statp->dnsrch;
|
||||
+ *pp++ = statp->defdname;
|
||||
+ *pp = NULL;
|
||||
|
||||
- }
|
||||
+ }
|
||||
|
||||
- if ((cp = getenv("RES_OPTIONS")) != NULL)
|
||||
- res_setoptions(statp, cp, "env");
|
||||
- statp->options |= RES_INIT;
|
||||
- return (0);
|
||||
+ if ((cp = getenv ("RES_OPTIONS")) != NULL)
|
||||
+ res_setoptions (statp, cp, "env");
|
||||
+ statp->options |= RES_INIT;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
-internal_function
|
||||
-res_setoptions(res_state statp, const char *options, const char *source) {
|
||||
- const char *cp = options;
|
||||
- int i;
|
||||
+res_setoptions (res_state statp, const char *options, const char *source)
|
||||
+{
|
||||
+ const char *cp = options;
|
||||
|
||||
- while (*cp) {
|
||||
- /* skip leading and inner runs of spaces */
|
||||
- while (*cp == ' ' || *cp == '\t')
|
||||
- cp++;
|
||||
- /* search for and process individual options */
|
||||
- if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
|
||||
- i = atoi(cp + sizeof("ndots:") - 1);
|
||||
- if (i <= RES_MAXNDOTS)
|
||||
- statp->ndots = i;
|
||||
- else
|
||||
- statp->ndots = RES_MAXNDOTS;
|
||||
- } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
|
||||
- i = atoi(cp + sizeof("timeout:") - 1);
|
||||
- if (i <= RES_MAXRETRANS)
|
||||
- statp->retrans = i;
|
||||
- else
|
||||
- statp->retrans = RES_MAXRETRANS;
|
||||
- } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
|
||||
- i = atoi(cp + sizeof("attempts:") - 1);
|
||||
- if (i <= RES_MAXRETRY)
|
||||
- statp->retry = i;
|
||||
- else
|
||||
- statp->retry = RES_MAXRETRY;
|
||||
- } else {
|
||||
- static const struct
|
||||
- {
|
||||
- char str[22];
|
||||
- uint8_t len;
|
||||
- uint8_t clear;
|
||||
- unsigned long int flag;
|
||||
- } options[] = {
|
||||
+ while (*cp)
|
||||
+ {
|
||||
+ /* Skip leading and inner runs of spaces. */
|
||||
+ while (*cp == ' ' || *cp == '\t')
|
||||
+ cp++;
|
||||
+ /* Search for and process individual options. */
|
||||
+ if (!strncmp (cp, "ndots:", sizeof ("ndots:") - 1))
|
||||
+ {
|
||||
+ int i = atoi (cp + sizeof ("ndots:") - 1);
|
||||
+ if (i <= RES_MAXNDOTS)
|
||||
+ statp->ndots = i;
|
||||
+ else
|
||||
+ statp->ndots = RES_MAXNDOTS;
|
||||
+ }
|
||||
+ else if (!strncmp (cp, "timeout:", sizeof ("timeout:") - 1))
|
||||
+ {
|
||||
+ int i = atoi (cp + sizeof ("timeout:") - 1);
|
||||
+ if (i <= RES_MAXRETRANS)
|
||||
+ statp->retrans = i;
|
||||
+ else
|
||||
+ statp->retrans = RES_MAXRETRANS;
|
||||
+ }
|
||||
+ else if (!strncmp (cp, "attempts:", sizeof ("attempts:") - 1))
|
||||
+ {
|
||||
+ int i = atoi (cp + sizeof ("attempts:") - 1);
|
||||
+ if (i <= RES_MAXRETRY)
|
||||
+ statp->retry = i;
|
||||
+ else
|
||||
+ statp->retry = RES_MAXRETRY;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ static const struct
|
||||
+ {
|
||||
+ char str[22];
|
||||
+ uint8_t len;
|
||||
+ uint8_t clear;
|
||||
+ unsigned long int flag;
|
||||
+ } options[] = {
|
||||
#define STRnLEN(str) str, sizeof (str) - 1
|
||||
- { STRnLEN ("inet6"), 0, DEPRECATED_RES_USE_INET6 },
|
||||
- { STRnLEN ("rotate"), 0, RES_ROTATE },
|
||||
- { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
|
||||
- { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },
|
||||
- { STRnLEN ("single-request"), 0, RES_SNGLKUP },
|
||||
- { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
|
||||
- { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
|
||||
- { STRnLEN ("use-vc"), 0, RES_USEVC }
|
||||
- };
|
||||
+ { STRnLEN ("inet6"), 0, DEPRECATED_RES_USE_INET6 },
|
||||
+ { STRnLEN ("rotate"), 0, RES_ROTATE },
|
||||
+ { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
|
||||
+ { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },
|
||||
+ { STRnLEN ("single-request"), 0, RES_SNGLKUP },
|
||||
+ { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
|
||||
+ { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
|
||||
+ { STRnLEN ("use-vc"), 0, RES_USEVC }
|
||||
+ };
|
||||
#define noptions (sizeof (options) / sizeof (options[0]))
|
||||
- int i;
|
||||
- for (i = 0; i < noptions; ++i)
|
||||
- if (strncmp (cp, options[i].str, options[i].len) == 0)
|
||||
- {
|
||||
- if (options[i].clear)
|
||||
- statp->options &= options[i].flag;
|
||||
- else
|
||||
- statp->options |= options[i].flag;
|
||||
- break;
|
||||
- }
|
||||
- if (i == noptions) {
|
||||
- /* XXX - print a warning here? */
|
||||
- }
|
||||
- }
|
||||
- /* skip to next run of spaces */
|
||||
- while (*cp && *cp != ' ' && *cp != '\t')
|
||||
- cp++;
|
||||
- }
|
||||
+ for (int i = 0; i < noptions; ++i)
|
||||
+ if (strncmp (cp, options[i].str, options[i].len) == 0)
|
||||
+ {
|
||||
+ if (options[i].clear)
|
||||
+ statp->options &= options[i].flag;
|
||||
+ else
|
||||
+ statp->options |= options[i].flag;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ /* Skip to next run of spaces. */
|
||||
+ while (*cp && *cp != ' ' && *cp != '\t')
|
||||
+ cp++;
|
||||
+ }
|
||||
}
|
||||
|
||||
-/* XXX - should really support CIDR which means explicit masks always. */
|
||||
-/* XXX - should really use system's version of this */
|
||||
-static u_int32_t
|
||||
+static uint32_t
|
||||
net_mask (struct in_addr in)
|
||||
{
|
||||
- u_int32_t i = ntohl(in.s_addr);
|
||||
+ uint32_t i = ntohl (in.s_addr);
|
||||
|
||||
- if (IN_CLASSA(i))
|
||||
- return (htonl(IN_CLASSA_NET));
|
||||
- else if (IN_CLASSB(i))
|
||||
- return (htonl(IN_CLASSB_NET));
|
||||
- return (htonl(IN_CLASSC_NET));
|
||||
+ if (IN_CLASSA (i))
|
||||
+ return htonl (IN_CLASSA_NET);
|
||||
+ else if (IN_CLASSB (i))
|
||||
+ return htonl (IN_CLASSB_NET);
|
||||
+ return htonl (IN_CLASSC_NET);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
commit ca3d65ff69d5187cb4d6b7f81d414427c7007e22
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jun 19 13:15:11 2017 +0200
|
||||
|
||||
resolv: Make __res_vinit hidden
|
||||
|
||||
And remove unnecessary separate declarations.
|
||||
|
||||
diff --git a/include/resolv.h b/include/resolv.h
|
||||
index e8f477cd86b7be11..37e4047ac40c6ae1 100644
|
||||
--- a/include/resolv.h
|
||||
+++ b/include/resolv.h
|
||||
@@ -23,7 +23,7 @@ extern __thread struct __res_state *__resp attribute_tls_model_ie;
|
||||
# define _res (*__resp)
|
||||
|
||||
/* Now define the internal interfaces. */
|
||||
-extern int __res_vinit (res_state, int);
|
||||
+extern int __res_vinit (res_state, int) attribute_hidden;
|
||||
extern int __res_maybe_init (res_state, int);
|
||||
extern void _sethtent (int);
|
||||
extern struct hostent *_gethtent (void);
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 23676e994dd58be7..57223b470af9ba4d 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -110,8 +110,6 @@ unsigned long long int __res_initstamp attribute_hidden;
|
||||
*/
|
||||
int
|
||||
res_ninit(res_state statp) {
|
||||
- extern int __res_vinit(res_state, int);
|
||||
-
|
||||
return (__res_vinit(statp, 0));
|
||||
}
|
||||
libc_hidden_def (__res_ninit)
|
||||
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
|
||||
index c52574f895d4f19d..3ef885762e890a40 100644
|
||||
--- a/resolv/res_libc.c
|
||||
+++ b/resolv/res_libc.c
|
||||
@@ -41,8 +41,6 @@ __libc_lock_define_initialized (static, lock);
|
||||
|
||||
int
|
||||
res_init(void) {
|
||||
- extern int __res_vinit(res_state, int);
|
||||
-
|
||||
/*
|
||||
* These three fields used to be statically initialized. This made
|
||||
* it hard to use this code in a shared library. It is necessary,
|
|
@ -0,0 +1,174 @@
|
|||
commit 89f187a40fc0ad4e22838526bfe34d73f758b776
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 16 20:54:43 2017 +0200
|
||||
|
||||
resolv: Use getline for configuration file reading in res_vinit_1
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index e604a0212fa13624..ed5a4d4804a792de 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -126,10 +126,10 @@ is_sort_mask (char ch)
|
||||
deallocation and error handling. Return true on success, false on
|
||||
failure. */
|
||||
static bool
|
||||
-res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
+res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
{
|
||||
char *cp, **pp;
|
||||
- char buf[BUFSIZ];
|
||||
+ size_t buffer_size = 0;
|
||||
int nserv = 0; /* Number of nameservers read from file. */
|
||||
bool have_serv6 = false;
|
||||
bool haveenv = false;
|
||||
@@ -197,27 +197,38 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
}
|
||||
|
||||
#define MATCH(line, name) \
|
||||
- (!strncmp (line, name, sizeof (name) - 1) \
|
||||
- && (line[sizeof (name) - 1] == ' ' \
|
||||
- || line[sizeof (name) - 1] == '\t'))
|
||||
+ (!strncmp ((line), name, sizeof (name) - 1) \
|
||||
+ && ((line)[sizeof (name) - 1] == ' ' \
|
||||
+ || (line)[sizeof (name) - 1] == '\t'))
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
/* No threads use this stream. */
|
||||
__fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
/* Read the config file. */
|
||||
- while (__fgets_unlocked (buf, sizeof (buf), fp) != NULL)
|
||||
+ while (true)
|
||||
{
|
||||
+ {
|
||||
+ ssize_t ret = __getline (buffer, &buffer_size, fp);
|
||||
+ if (ret <= 0)
|
||||
+ {
|
||||
+ if (_IO_ferror_unlocked (fp))
|
||||
+ return false;
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Skip comments. */
|
||||
- if (*buf == ';' || *buf == '#')
|
||||
+ if (**buffer == ';' || **buffer == '#')
|
||||
continue;
|
||||
/* Read default domain name. */
|
||||
- if (MATCH (buf, "domain"))
|
||||
+ if (MATCH (*buffer, "domain"))
|
||||
{
|
||||
if (haveenv)
|
||||
/* LOCALDOMAIN overrides the configuration file. */
|
||||
continue;
|
||||
- cp = buf + sizeof ("domain") - 1;
|
||||
+ cp = *buffer + sizeof ("domain") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
@@ -230,12 +241,12 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
continue;
|
||||
}
|
||||
/* Set search list. */
|
||||
- if (MATCH (buf, "search"))
|
||||
+ if (MATCH (*buffer, "search"))
|
||||
{
|
||||
if (haveenv)
|
||||
/* LOCALDOMAIN overrides the configuration file. */
|
||||
continue;
|
||||
- cp = buf + sizeof ("search") - 1;
|
||||
+ cp = *buffer + sizeof ("search") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
@@ -271,11 +282,11 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
continue;
|
||||
}
|
||||
/* Read nameservers to query. */
|
||||
- if (MATCH (buf, "nameserver") && nserv < MAXNS)
|
||||
+ if (MATCH (*buffer, "nameserver") && nserv < MAXNS)
|
||||
{
|
||||
struct in_addr a;
|
||||
|
||||
- cp = buf + sizeof ("nameserver") - 1;
|
||||
+ cp = *buffer + sizeof ("nameserver") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
|
||||
@@ -300,7 +311,7 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
|
||||
sa6 = malloc (sizeof (*sa6));
|
||||
if (sa6 == NULL)
|
||||
- return -1;
|
||||
+ return false;
|
||||
|
||||
sa6->sin6_family = AF_INET6;
|
||||
sa6->sin6_port = htons (NAMESERVER_PORT);
|
||||
@@ -323,11 +334,11 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
- if (MATCH (buf, "sortlist"))
|
||||
+ if (MATCH (*buffer, "sortlist"))
|
||||
{
|
||||
struct in_addr a;
|
||||
|
||||
- cp = buf + sizeof ("sortlist") - 1;
|
||||
+ cp = *buffer + sizeof ("sortlist") - 1;
|
||||
while (nsort < MAXRESOLVSORT)
|
||||
{
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
@@ -367,9 +378,9 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
- if (MATCH (buf, "options"))
|
||||
+ if (MATCH (*buffer, "options"))
|
||||
{
|
||||
- res_setoptions (statp, buf + sizeof ("options") - 1, "conf");
|
||||
+ res_setoptions (statp, *buffer + sizeof ("options") - 1, "conf");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -387,10 +398,13 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
statp->nsaddr.sin_port = htons (NAMESERVER_PORT);
|
||||
statp->nscount = 1;
|
||||
}
|
||||
- if (statp->defdname[0] == 0
|
||||
- && __gethostname (buf, sizeof (statp->defdname) - 1) == 0
|
||||
- && (cp = strchr (buf, '.')) != NULL)
|
||||
- strcpy (statp->defdname, cp + 1);
|
||||
+ if (statp->defdname[0] == 0)
|
||||
+ {
|
||||
+ char buf[sizeof (statp->defdname)];
|
||||
+ if (__gethostname (buf, sizeof (statp->defdname) - 1) == 0
|
||||
+ && (cp = strchr (buf, '.')) != NULL)
|
||||
+ strcpy (statp->defdname, cp + 1);
|
||||
+ }
|
||||
|
||||
/* Find components of local domain that might be searched. */
|
||||
if (!havesearch)
|
||||
@@ -404,7 +418,7 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp)
|
||||
if ((cp = getenv ("RES_OPTIONS")) != NULL)
|
||||
res_setoptions (statp, cp, "env");
|
||||
statp->options |= RES_INIT;
|
||||
- return 0;
|
||||
+ return true;
|
||||
}
|
||||
|
||||
/* Set up default settings. If the /etc/resolv.conf configuration
|
||||
@@ -434,7 +448,12 @@ __res_vinit (res_state statp, int preinit)
|
||||
need to be handled by the application. */
|
||||
return -1;
|
||||
}
|
||||
- if (!res_vinit_1 (statp, preinit, fp))
|
||||
+
|
||||
+ char *buffer = NULL;
|
||||
+ bool ok = res_vinit_1 (statp, preinit, fp, &buffer);
|
||||
+ free (buffer);
|
||||
+
|
||||
+ if (!ok)
|
||||
{
|
||||
/* Deallocate the name server addresses which have been
|
||||
allocated. */
|
|
@ -0,0 +1,602 @@
|
|||
commit aef16cc8a4c670036d45590877d411a97f01e0cd
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jul 3 21:06:23 2017 +0200
|
||||
|
||||
resolv: Automatically reload a changed /etc/resolv.conf file [BZ #984]
|
||||
|
||||
This commit enhances the stub resolver to reload the configuration
|
||||
in the per-thread _res object if the /etc/resolv.conf file has
|
||||
changed. The resolver checks whether the application has modified
|
||||
_res and will not overwrite the _res object in that case.
|
||||
|
||||
The struct resolv_context mechanism is used to check the
|
||||
configuration file only once per name lookup.
|
||||
|
||||
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
|
||||
index b26c38bae0a1674b..1914324dcc3cabc3 100644
|
||||
--- a/resolv/res_debug.c
|
||||
+++ b/resolv/res_debug.c
|
||||
@@ -607,6 +607,7 @@ p_option(u_long option) {
|
||||
case RES_SNGLKUPREOP: return "single-request-reopen";
|
||||
case RES_USE_DNSSEC: return "dnssec";
|
||||
case RES_NOTLDQUERY: return "no-tld-query";
|
||||
+ case RES_NORELOAD: return "no-reload";
|
||||
/* XXX nonreentrant */
|
||||
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
|
||||
return (nbuf);
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 80a21fb90d991e95..fa46ce7813c1f8af 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -106,8 +106,6 @@
|
||||
|
||||
static uint32_t net_mask (struct in_addr);
|
||||
|
||||
-unsigned long long int __res_initstamp;
|
||||
-
|
||||
int
|
||||
res_ninit (res_state statp)
|
||||
{
|
||||
@@ -164,6 +162,16 @@ struct resolv_conf_parser
|
||||
struct resolv_conf template;
|
||||
};
|
||||
|
||||
+/* Return true if *PREINIT contains actual preinitialization. */
|
||||
+static bool
|
||||
+has_preinit_values (const struct __res_state *preinit)
|
||||
+{
|
||||
+ return (preinit->retrans != 0 && preinit->retrans != RES_TIMEOUT)
|
||||
+ || (preinit->retry != 0 && preinit->retry != RES_DFLRETRY)
|
||||
+ || (preinit->options != 0
|
||||
+ && (preinit->options & ~RES_INIT) != RES_DEFAULT);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
resolv_conf_parser_init (struct resolv_conf_parser *parser,
|
||||
const struct __res_state *preinit)
|
||||
@@ -531,14 +539,8 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
|
||||
return true;
|
||||
}
|
||||
|
||||
-/* Set up default settings. If the /etc/resolv.conf configuration
|
||||
- file exist, the values there will have precedence. Otherwise, the
|
||||
- server address is set to INADDR_LOOPBACK and the default domain
|
||||
- name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN
|
||||
- environment variables can be used to override some settings.
|
||||
- Return 0 if completes successfully, -1 on error. */
|
||||
-int
|
||||
-__res_vinit (res_state statp, int preinit)
|
||||
+struct resolv_conf *
|
||||
+__resolv_conf_load (struct __res_state *preinit)
|
||||
{
|
||||
/* Ensure that /etc/hosts.conf has been loaded (once). */
|
||||
_res_hconf_init ();
|
||||
@@ -559,20 +561,14 @@ __res_vinit (res_state statp, int preinit)
|
||||
default:
|
||||
/* Other errors refer to resource allocation problems and
|
||||
need to be handled by the application. */
|
||||
- return -1;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
struct resolv_conf_parser parser;
|
||||
- if (preinit)
|
||||
- {
|
||||
- resolv_conf_parser_init (&parser, statp);
|
||||
- statp->id = res_randomid ();
|
||||
- }
|
||||
- else
|
||||
- resolv_conf_parser_init (&parser, NULL);
|
||||
+ resolv_conf_parser_init (&parser, preinit);
|
||||
|
||||
- bool ok = res_vinit_1 (fp, &parser);
|
||||
- if (ok)
|
||||
+ struct resolv_conf *conf = NULL;
|
||||
+ if (res_vinit_1 (fp, &parser))
|
||||
{
|
||||
parser.template.nameserver_list
|
||||
= nameserver_list_begin (&parser.nameserver_list);
|
||||
@@ -583,21 +579,42 @@ __res_vinit (res_state statp, int preinit)
|
||||
= search_list_size (&parser.search_list);
|
||||
parser.template.sort_list = sort_list_begin (&parser.sort_list);
|
||||
parser.template.sort_list_size = sort_list_size (&parser.sort_list);
|
||||
- struct resolv_conf *conf = __resolv_conf_allocate (&parser.template);
|
||||
- if (conf == NULL)
|
||||
- ok = false;
|
||||
- else
|
||||
- {
|
||||
- ok = __resolv_conf_attach (statp, conf);
|
||||
- __resolv_conf_put (conf);
|
||||
- }
|
||||
+ conf = __resolv_conf_allocate (&parser.template);
|
||||
}
|
||||
resolv_conf_parser_free (&parser);
|
||||
|
||||
- if (!ok)
|
||||
+ return conf;
|
||||
+}
|
||||
+
|
||||
+/* Set up default settings. If the /etc/resolv.conf configuration
|
||||
+ file exist, the values there will have precedence. Otherwise, the
|
||||
+ server address is set to INADDR_LOOPBACK and the default domain
|
||||
+ name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN
|
||||
+ environment variables can be used to override some settings.
|
||||
+ Return 0 if completes successfully, -1 on error. */
|
||||
+int
|
||||
+__res_vinit (res_state statp, int preinit)
|
||||
+{
|
||||
+ struct resolv_conf *conf;
|
||||
+ if (preinit && has_preinit_values (statp))
|
||||
+ /* For the preinit case, we cannot use the cached configuration
|
||||
+ because some settings could be different. */
|
||||
+ conf = __resolv_conf_load (statp);
|
||||
+ else
|
||||
+ conf = __resolv_conf_get_current ();
|
||||
+ if (conf == NULL)
|
||||
return -1;
|
||||
+
|
||||
+ bool ok = __resolv_conf_attach (statp, conf);
|
||||
+ __resolv_conf_put (conf);
|
||||
+ if (ok)
|
||||
+ {
|
||||
+ if (preinit)
|
||||
+ statp->id = res_randomid ();
|
||||
+ return 0;
|
||||
+ }
|
||||
else
|
||||
- return 0;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -652,6 +669,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
|
||||
{ STRnLEN ("single-request"), 0, RES_SNGLKUP },
|
||||
{ STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
|
||||
{ STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
|
||||
+ { STRnLEN ("no-reload"), 0, RES_NORELOAD },
|
||||
{ STRnLEN ("use-vc"), 0, RES_USEVC }
|
||||
};
|
||||
#define noptions (sizeof (options) / sizeof (options[0]))
|
||||
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
|
||||
index b90816472ab09dc2..8dd06f9f1310248a 100644
|
||||
--- a/resolv/res_libc.c
|
||||
+++ b/resolv/res_libc.c
|
||||
@@ -42,18 +42,6 @@
|
||||
#include <libc-lock.h>
|
||||
#include <resolv-internal.h>
|
||||
|
||||
-/* We have atomic increment operations on 64-bit platforms. */
|
||||
-#if __WORDSIZE == 64
|
||||
-# define atomicinclock(lock) (void) 0
|
||||
-# define atomicincunlock(lock) (void) 0
|
||||
-# define atomicinc(var) catomic_increment (&(var))
|
||||
-#else
|
||||
-__libc_lock_define_initialized (static, lock);
|
||||
-# define atomicinclock(lock) __libc_lock_lock (lock)
|
||||
-# define atomicincunlock(lock) __libc_lock_unlock (lock)
|
||||
-# define atomicinc(var) ++var
|
||||
-#endif
|
||||
-
|
||||
int
|
||||
res_init (void)
|
||||
{
|
||||
@@ -90,12 +78,6 @@ res_init (void)
|
||||
if (!_res.id)
|
||||
_res.id = res_randomid ();
|
||||
|
||||
- atomicinclock (lock);
|
||||
- /* Request all threads to re-initialize their resolver states,
|
||||
- resolv.conf might have changed. */
|
||||
- atomicinc (__res_initstamp);
|
||||
- atomicincunlock (lock);
|
||||
-
|
||||
return __res_vinit (&_res, 1);
|
||||
}
|
||||
|
||||
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
|
||||
index 9246497196adab7d..32dc44777e311849 100644
|
||||
--- a/resolv/resolv-internal.h
|
||||
+++ b/resolv/resolv-internal.h
|
||||
@@ -97,7 +97,4 @@ int __res_nopt (struct resolv_context *, int n0,
|
||||
int __inet_pton_length (int af, const char *src, size_t srclen, void *);
|
||||
libc_hidden_proto (__inet_pton_length)
|
||||
|
||||
-/* Used to propagate the effect of res_init calls across threads. */
|
||||
-extern unsigned long long int __res_initstamp attribute_hidden;
|
||||
-
|
||||
#endif /* _RESOLV_INTERNAL_H */
|
||||
diff --git a/resolv/resolv.h b/resolv/resolv.h
|
||||
index b83232cca8e8f0c3..6d4271987a0d705a 100644
|
||||
--- a/resolv/resolv.h
|
||||
+++ b/resolv/resolv.h
|
||||
@@ -196,6 +196,7 @@ struct res_sym {
|
||||
#define RES_USE_DNSSEC 0x00800000 /* use DNSSEC using OK bit in OPT */
|
||||
#define RES_NOTLDQUERY 0x01000000 /* Do not look up unqualified name
|
||||
as a TLD. */
|
||||
+#define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */
|
||||
|
||||
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
|
||||
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index dd665239926cbac7..9ef59240ebc57a70 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <assert.h>
|
||||
#include <libc-lock.h>
|
||||
#include <resolv-internal.h>
|
||||
+#include <sys/stat.h>
|
||||
|
||||
/* _res._u._ext.__glibc_extension_index is used as an index into a
|
||||
struct resolv_conf_array object. The intent of this construction
|
||||
@@ -54,6 +55,15 @@ struct resolv_conf_global
|
||||
the array element is overwritten with NULL. */
|
||||
struct resolv_conf_array array;
|
||||
|
||||
+ /* Cached current configuration object for /etc/resolv.conf. */
|
||||
+ struct resolv_conf *conf_current;
|
||||
+
|
||||
+ /* These properties of /etc/resolv.conf are used to check if the
|
||||
+ configuration needs reloading. */
|
||||
+ struct timespec conf_mtime;
|
||||
+ struct timespec conf_ctime;
|
||||
+ off64_t conf_size;
|
||||
+ ino64_t conf_ino;
|
||||
};
|
||||
|
||||
/* Lazily allocated storage for struct resolv_conf_global. */
|
||||
@@ -100,6 +110,75 @@ conf_decrement (struct resolv_conf *conf)
|
||||
free (conf);
|
||||
}
|
||||
|
||||
+struct resolv_conf *
|
||||
+__resolv_conf_get_current (void)
|
||||
+{
|
||||
+ struct stat64 st;
|
||||
+ if (stat64 (_PATH_RESCONF, &st) != 0)
|
||||
+ {
|
||||
+ switch (errno)
|
||||
+ {
|
||||
+ case EACCES:
|
||||
+ case EISDIR:
|
||||
+ case ELOOP:
|
||||
+ case ENOENT:
|
||||
+ case ENOTDIR:
|
||||
+ case EPERM:
|
||||
+ /* Ignore errors due to file system contents. */
|
||||
+ memset (&st, 0, sizeof (st));
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* Other errors are fatal. */
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ struct resolv_conf_global *global_copy = get_locked_global ();
|
||||
+ if (global_copy == NULL)
|
||||
+ return NULL;
|
||||
+ struct resolv_conf *conf;
|
||||
+ if (global_copy->conf_current != NULL
|
||||
+ && (global_copy->conf_mtime.tv_sec == st.st_mtim.tv_sec
|
||||
+ && global_copy->conf_mtime.tv_nsec == st.st_mtim.tv_nsec
|
||||
+ && global_copy->conf_ctime.tv_sec == st.st_ctim.tv_sec
|
||||
+ && global_copy->conf_ctime.tv_nsec == st.st_ctim.tv_nsec
|
||||
+ && global_copy->conf_ino == st.st_ino
|
||||
+ && global_copy->conf_size == st.st_size))
|
||||
+ /* We can reuse the cached configuration object. */
|
||||
+ conf = global_copy->conf_current;
|
||||
+ else
|
||||
+ {
|
||||
+ /* Parse configuration while holding the lock. This avoids
|
||||
+ duplicate work. */
|
||||
+ conf = __resolv_conf_load (NULL);
|
||||
+ if (conf != NULL)
|
||||
+ {
|
||||
+ if (global_copy->conf_current != NULL)
|
||||
+ conf_decrement (global_copy->conf_current);
|
||||
+ global_copy->conf_current = conf; /* Takes ownership. */
|
||||
+
|
||||
+ /* Update file modification stamps. The configuration we
|
||||
+ read could be a newer version of the file, but this does
|
||||
+ not matter because this will lead to an extraneous reload
|
||||
+ later. */
|
||||
+ global_copy->conf_mtime = st.st_mtim;
|
||||
+ global_copy->conf_ctime = st.st_ctim;
|
||||
+ global_copy->conf_ino = st.st_ino;
|
||||
+ global_copy->conf_size = st.st_size;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (conf != NULL)
|
||||
+ {
|
||||
+ /* Return an additional reference. */
|
||||
+ assert (conf->__refcount > 0);
|
||||
+ ++conf->__refcount;
|
||||
+ assert (conf->__refcount > 0);
|
||||
+ }
|
||||
+ put_locked_global (global_copy);
|
||||
+ return conf;
|
||||
+}
|
||||
+
|
||||
/* Internal implementation of __resolv_conf_get, without validation
|
||||
against *RESP. */
|
||||
static struct resolv_conf *
|
||||
@@ -320,7 +399,6 @@ __resolv_conf_allocate (const struct resolv_conf *init)
|
||||
conf->retry = init->retry;
|
||||
conf->options = init->options;
|
||||
conf->ndots = init->ndots;
|
||||
- conf->initstamp = __res_initstamp;
|
||||
|
||||
/* Allocate the arrays with pointers. These must come first because
|
||||
they have the highets alignment. */
|
||||
@@ -580,6 +658,12 @@ freeres (void)
|
||||
if (global == NULL)
|
||||
return;
|
||||
|
||||
+ if (global->conf_current != NULL)
|
||||
+ {
|
||||
+ conf_decrement (global->conf_current);
|
||||
+ global->conf_current = NULL;
|
||||
+ }
|
||||
+
|
||||
/* Note that this frees only the array itself. The pointed-to
|
||||
configuration objects should have been deallocated by res_nclose
|
||||
and per-thread cleanup functions. */
|
||||
diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h
|
||||
index 7ca80cdeba115c12..0ff8bd7e928708fc 100644
|
||||
--- a/resolv/resolv_conf.h
|
||||
+++ b/resolv/resolv_conf.h
|
||||
@@ -35,11 +35,6 @@ struct resolv_sortlist_entry
|
||||
object. */
|
||||
struct resolv_conf
|
||||
{
|
||||
- /* Used to propagate the effect of res_init across threads. This
|
||||
- member is mutable and prevents sharing of the same struct
|
||||
- resolv_conf object among multiple struct __res_state objects. */
|
||||
- unsigned long long int initstamp;
|
||||
-
|
||||
/* Reference counter. The object is deallocated once it reaches
|
||||
zero. For internal use within resolv_conf only. */
|
||||
size_t __refcount;
|
||||
@@ -69,6 +64,18 @@ struct resolv_conf
|
||||
|
||||
struct __res_state;
|
||||
|
||||
+/* Read /etc/resolv.conf and return a configuration object, or NULL if
|
||||
+ /etc/resolv.conf cannot be read due to memory allocation errors.
|
||||
+ If PREINIT is not NULL, some configuration values are taken from the
|
||||
+ struct __res_state object. */
|
||||
+struct resolv_conf *__resolv_conf_load (struct __res_state *preinit)
|
||||
+ attribute_hidden __attribute__ ((warn_unused_result));
|
||||
+
|
||||
+/* Return a configuration object for the current /etc/resolv.conf
|
||||
+ settings, or NULL on failure. The object is cached. */
|
||||
+struct resolv_conf *__resolv_conf_get_current (void)
|
||||
+ attribute_hidden __attribute__ ((warn_unused_result));
|
||||
+
|
||||
/* Return the extended resolver state for *RESP, or NULL if it cannot
|
||||
be determined. A call to this function must be paired with a call
|
||||
to __resolv_conf_put. */
|
||||
diff --git a/resolv/resolv_context.c b/resolv/resolv_context.c
|
||||
index 0ee2184055911d02..35d4b3d41d59fc98 100644
|
||||
--- a/resolv/resolv_context.c
|
||||
+++ b/resolv/resolv_context.c
|
||||
@@ -51,6 +51,20 @@
|
||||
resolver state. */
|
||||
static __thread struct resolv_context *current attribute_tls_model_ie;
|
||||
|
||||
+/* The resolv_conf handling will gives us a ctx->conf pointer even if
|
||||
+ these fields do not match because a mis-match does not cause a loss
|
||||
+ of state (_res objects can store the full information). This
|
||||
+ function checks to ensure that there is a full patch, to prevent
|
||||
+ overwriting a patched configuration. */
|
||||
+static bool
|
||||
+replicated_configuration_matches (const struct resolv_context *ctx)
|
||||
+{
|
||||
+ return ctx->resp->options == ctx->conf->options
|
||||
+ && ctx->resp->retrans == ctx->conf->retrans
|
||||
+ && ctx->resp->retry == ctx->conf->retry
|
||||
+ && ctx->resp->ndots == ctx->conf->ndots;
|
||||
+}
|
||||
+
|
||||
/* Initialize *RESP if RES_INIT is not yet set in RESP->options, or if
|
||||
res_init in some other thread requested re-initializing. */
|
||||
static __attribute__ ((warn_unused_result)) bool
|
||||
@@ -59,27 +73,36 @@ maybe_init (struct resolv_context *ctx, bool preinit)
|
||||
struct __res_state *resp = ctx->resp;
|
||||
if (resp->options & RES_INIT)
|
||||
{
|
||||
+ if (resp->options & RES_NORELOAD)
|
||||
+ /* Configuration reloading was explicitly disabled. */
|
||||
+ return true;
|
||||
+
|
||||
/* If there is no associated resolv_conf object despite the
|
||||
initialization, something modified *ctx->resp. Do not
|
||||
override those changes. */
|
||||
- if (ctx->conf != NULL && ctx->conf->initstamp != __res_initstamp)
|
||||
+ if (ctx->conf != NULL && replicated_configuration_matches (ctx))
|
||||
{
|
||||
- if (resp->nscount > 0)
|
||||
- /* This call will detach the extended resolver state. */
|
||||
- __res_iclose (resp, true);
|
||||
- /* And this call will attach it again. */
|
||||
- if (__res_vinit (resp, 1) < 0)
|
||||
+ struct resolv_conf *current = __resolv_conf_get_current ();
|
||||
+ if (current == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ /* Check if the configuration changed. */
|
||||
+ if (current != ctx->conf)
|
||||
{
|
||||
- /* The configuration no longer matches after failed
|
||||
- initialization. */
|
||||
- __resolv_conf_put (ctx->conf);
|
||||
- ctx->conf = NULL;
|
||||
- return false;
|
||||
+ /* This call will detach the extended resolver state. */
|
||||
+ if (resp->nscount > 0)
|
||||
+ __res_iclose (resp, true);
|
||||
+ /* Reattach the current configuration. */
|
||||
+ if (__resolv_conf_attach (ctx->resp, current))
|
||||
+ {
|
||||
+ __resolv_conf_put (ctx->conf);
|
||||
+ /* ctx takes ownership, so we do not release current. */
|
||||
+ ctx->conf = current;
|
||||
+ }
|
||||
}
|
||||
- /* Delay the release of the old configuration until this
|
||||
- point, so that __res_vinit can reuse it if possible. */
|
||||
- __resolv_conf_put (ctx->conf);
|
||||
- ctx->conf = __resolv_conf_get (ctx->resp);
|
||||
+ else
|
||||
+ /* No change. Drop the reference count for current. */
|
||||
+ __resolv_conf_put (current);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index f98e9f40305d4897..9e496a3212b0f2ab 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -151,6 +151,7 @@ print_resp (FILE *fp, res_state resp)
|
||||
print_option_flag (fp, &options, RES_SNGLKUPREOP,
|
||||
"single-request-reopen");
|
||||
print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query");
|
||||
+ print_option_flag (fp, &options, RES_NORELOAD, "no-reload");
|
||||
fputc ('\n', fp);
|
||||
if (options != 0)
|
||||
fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
|
||||
@@ -470,6 +471,28 @@ struct test_case test_cases[] =
|
||||
"nameserver 192.0.2.1\n"
|
||||
"; nameserver[0]: [192.0.2.1]:53\n"
|
||||
},
|
||||
+ {.name = "basic no-reload",
|
||||
+ .conf = "options no-reload\n"
|
||||
+ "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "options no-reload\n"
|
||||
+ "search corp.example.com example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "; nameserver[0]: [192.0.2.1]:53\n"
|
||||
+ },
|
||||
+ {.name = "basic no-reload via RES_OPTIONS",
|
||||
+ .conf = "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "options no-reload\n"
|
||||
+ "search corp.example.com example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "; nameserver[0]: [192.0.2.1]:53\n",
|
||||
+ .res_options = "no-reload"
|
||||
+ },
|
||||
{.name = "whitespace",
|
||||
.conf = "# This test covers comment and whitespace processing "
|
||||
" (trailing whitespace,\n"
|
||||
@@ -722,18 +745,7 @@ test_file_contents (const struct test_case *t)
|
||||
}
|
||||
|
||||
/* Special tests which do not follow the general pattern. */
|
||||
-enum { special_tests_count = 7 };
|
||||
-
|
||||
-#if TEST_THREAD
|
||||
-/* Called from test number 3-6 to trigger reloading of the
|
||||
- configuration. */
|
||||
-static void *
|
||||
-special_test_call_res_init (void *closure)
|
||||
-{
|
||||
- TEST_VERIFY (res_init () == 0);
|
||||
- return NULL;
|
||||
-}
|
||||
-#endif
|
||||
+enum { special_tests_count = 11 };
|
||||
|
||||
/* Implementation of special tests. */
|
||||
static void
|
||||
@@ -800,20 +812,29 @@ special_test_callback (void *closure)
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
- /* Test res_init change broadcast. This requires a second
|
||||
- thread to trigger the reload. */
|
||||
-#if TEST_THREAD
|
||||
support_write_file_string (_PATH_RESCONF,
|
||||
"options edns0\n"
|
||||
"nameserver 192.0.2.1\n");
|
||||
+ goto reload_tests;
|
||||
+ case 7: /* 7 and the following tests are with no-reload. */
|
||||
+ case 8:
|
||||
+ case 9:
|
||||
+ case 10:
|
||||
+ support_write_file_string (_PATH_RESCONF,
|
||||
+ "options edns0 no-reload\n"
|
||||
+ "nameserver 192.0.2.1\n");
|
||||
+ /* Fall through. */
|
||||
+ reload_tests:
|
||||
for (int iteration = 0; iteration < 2; ++iteration)
|
||||
{
|
||||
switch (test_index)
|
||||
{
|
||||
case 3:
|
||||
+ case 7:
|
||||
TEST_VERIFY (res_init () == 0);
|
||||
break;
|
||||
case 4:
|
||||
+ case 8:
|
||||
{
|
||||
unsigned char buf[512];
|
||||
TEST_VERIFY
|
||||
@@ -822,37 +843,44 @@ special_test_callback (void *closure)
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
+ case 9:
|
||||
gethostbyname (test_hostname);
|
||||
break;
|
||||
case 6:
|
||||
+ case 10:
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
(void) getaddrinfo (test_hostname, NULL, NULL, &ai);
|
||||
}
|
||||
break;
|
||||
}
|
||||
- if (iteration == 0)
|
||||
+ /* test_index == 7 is res_init and performs a reload even
|
||||
+ with no-reload. */
|
||||
+ if (iteration == 0 || test_index > 7)
|
||||
{
|
||||
TEST_VERIFY (_res.options & RES_USE_EDNS0);
|
||||
TEST_VERIFY (!(_res.options & RES_ROTATE));
|
||||
+ if (test_index < 7)
|
||||
+ TEST_VERIFY (!(_res.options & RES_NORELOAD));
|
||||
+ else
|
||||
+ TEST_VERIFY (_res.options & RES_NORELOAD);
|
||||
TEST_VERIFY (_res.nscount == 1);
|
||||
+ /* File change triggers automatic reloading. */
|
||||
support_write_file_string (_PATH_RESCONF,
|
||||
"options rotate\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
"nameserver 192.0.2.2\n");
|
||||
- xpthread_join (xpthread_create
|
||||
- (NULL, special_test_call_res_init, NULL));
|
||||
}
|
||||
else
|
||||
{
|
||||
- /* edns0 was dropped, but the flag is not cleared. See
|
||||
- bug 21701. */
|
||||
- /* TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); */
|
||||
+ if (test_index != 3 && test_index != 7)
|
||||
+ /* test_index 3, 7 are res_init; this function does
|
||||
+ not reset flags. See bug 21701. */
|
||||
+ TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
|
||||
TEST_VERIFY (_res.options & RES_ROTATE);
|
||||
TEST_VERIFY (_res.nscount == 2);
|
||||
}
|
||||
}
|
||||
-#endif
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
commit a7ff1da8239a5f0e1927db9d5310f53cfea97fc2
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 13 10:52:27 2017 +0200
|
||||
|
||||
resolv: Remove internal and unused definitions from <resolv.h>
|
||||
|
||||
The RES_F_* constants are only used with the private _res._flags
|
||||
member. RES_EXHAUSTIVE is unused. The removed function
|
||||
declarations refer to functions not actually exported by glibc,
|
||||
so they are unusable by applications.
|
||||
|
||||
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
|
||||
index 14557dd323f5f4b2..e23559bad3d92e71 100644
|
||||
--- a/resolv/res_debug.c
|
||||
+++ b/resolv/res_debug.c
|
||||
@@ -115,6 +115,8 @@
|
||||
|
||||
extern const char *_res_sectioncodes[] attribute_hidden;
|
||||
|
||||
+static const char *p_section(int section, int opcode);
|
||||
+
|
||||
/*
|
||||
* Print the current options.
|
||||
*/
|
||||
@@ -512,7 +514,7 @@ libresolv_hidden_def (p_type)
|
||||
/*
|
||||
* Return a string for the type.
|
||||
*/
|
||||
-const char *
|
||||
+static const char *
|
||||
p_section(int section, int opcode) {
|
||||
const struct res_sym *symbols;
|
||||
|
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||||
index 57156d01ec3c9fc2..c3ebcbf6b50fcf4b 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
+#include <resolv/resolv-internal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 93db5b9a615ffde7..77d59dcc4e3b8d23 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -101,7 +101,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
-#include <resolv.h>
|
||||
+#include <resolv/resolv-internal.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
|
||||
index 76fbe2f1a61b79bb..0d69ce10d33afcc5 100644
|
||||
--- a/resolv/resolv-internal.h
|
||||
+++ b/resolv/resolv-internal.h
|
||||
@@ -22,6 +22,12 @@
|
||||
#include <resolv.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
+/* Resolver flags. Used for _flags in struct __res_state. */
|
||||
+#define RES_F_VC 0x00000001 /* Socket is TCP. */
|
||||
+#define RES_F_CONN 0x00000002 /* Socket is connected. */
|
||||
+#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */
|
||||
+
|
||||
+
|
||||
/* Internal version of RES_USE_INET6 which does not trigger a
|
||||
deprecation warning. */
|
||||
#define DEPRECATED_RES_USE_INET6 0x00002000
|
||||
diff --git a/resolv/resolv.h b/resolv/resolv.h
|
||||
index 7809e2eb194f48ef..9fef8e9f248c84e6 100644
|
||||
--- a/resolv/resolv.h
|
||||
+++ b/resolv/resolv.h
|
||||
@@ -163,16 +163,6 @@ struct res_sym {
|
||||
};
|
||||
|
||||
/*
|
||||
- * Resolver flags (used to be discrete per-module statics ints).
|
||||
- */
|
||||
-#define RES_F_VC 0x00000001 /* socket is TCP */
|
||||
-#define RES_F_CONN 0x00000002 /* socket is connected */
|
||||
-#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */
|
||||
-
|
||||
-/* res_findzonecut() options */
|
||||
-#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */
|
||||
-
|
||||
-/*
|
||||
* Resolver options (keep these in synch with res_debug.c, please)
|
||||
*/
|
||||
#define RES_INIT 0x00000001 /* address initialized */
|
||||
@@ -285,7 +275,6 @@ __END_DECLS
|
||||
#define p_fqnname __p_fqnname
|
||||
#define p_option __p_option
|
||||
#define p_secstodate __p_secstodate
|
||||
-#define p_section __p_section
|
||||
#define p_time __p_time
|
||||
#define p_type __p_type
|
||||
#define p_rcode __p_rcode
|
||||
@@ -299,12 +288,10 @@ __END_DECLS
|
||||
#define res_nclose __res_nclose
|
||||
#define res_ninit __res_ninit
|
||||
#define res_nmkquery __res_nmkquery
|
||||
-#define res_npquery __res_npquery
|
||||
#define res_nquery __res_nquery
|
||||
#define res_nquerydomain __res_nquerydomain
|
||||
#define res_nsearch __res_nsearch
|
||||
#define res_nsend __res_nsend
|
||||
-#define res_nisourserver __res_nisourserver
|
||||
#define res_ownok __res_ownok
|
||||
#define res_queriesmatch __res_queriesmatch
|
||||
#define res_randomid __res_randomid
|
||||
@@ -356,14 +343,9 @@ int res_queriesmatch (const unsigned char *,
|
||||
const unsigned char *,
|
||||
const unsigned char *,
|
||||
const unsigned char *) __THROW;
|
||||
-const char * p_section (int __section, int __opcode) __THROW;
|
||||
/* Things involving a resolver context. */
|
||||
int res_ninit (res_state) __THROW;
|
||||
-int res_nisourserver (const res_state,
|
||||
- const struct sockaddr_in *) __THROW;
|
||||
void fp_resstat (const res_state, FILE *) __THROW;
|
||||
-void res_npquery (const res_state, const unsigned char *, int,
|
||||
- FILE *) __THROW;
|
||||
const char * res_hostalias (const res_state, const char *, char *, size_t)
|
||||
__THROW;
|
||||
int res_nquery (res_state, const char *, int, int,
|
|
@ -0,0 +1,24 @@
|
|||
commit 905a6129147e7ee80e8918e23efe212433b8cce7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Sep 6 15:46:54 2017 +0200
|
||||
|
||||
resolv: Fix memory leak with OOM during resolv.conf parsing [BZ #22095]
|
||||
|
||||
(cherry picked from commit 5670c4ab256114e869b1df4b05653aa5f909182c)
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index fa46ce7813c1f8af..4e1f9fe8dea93e8a 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -446,6 +446,11 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
|
||||
(&parser->nameserver_list);
|
||||
if (p != NULL)
|
||||
*p = sa;
|
||||
+ else
|
||||
+ {
|
||||
+ free (sa);
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
continue;
|
||||
}
|
|
@ -0,0 +1,520 @@
|
|||
commit cb3c27e87b914bde5ec00a02363536c76e08b850
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Jul 5 17:39:33 2017 +0200
|
||||
|
||||
support: Add resolver testing mode which does not patch _res
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index e80583c72b96efb4..83f99791e3a097cc 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -65,7 +65,9 @@ tests += \
|
||||
tst-resolv-res_init-thread \
|
||||
|
||||
# Needs resolv_context.
|
||||
-tests += tst-resolv-res_ninit
|
||||
+tests += \
|
||||
+ tst-resolv-res_ninit \
|
||||
+ tst-resolv-threads \
|
||||
|
||||
endif
|
||||
|
||||
@@ -168,6 +170,8 @@ $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-threads: \
|
||||
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-canonname: \
|
||||
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||
|
||||
diff --git a/resolv/tst-resolv-threads.c b/resolv/tst-resolv-threads.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..7be417b056f720d8
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-threads.c
|
||||
@@ -0,0 +1,484 @@
|
||||
+/* Test basic nss_dns functionality with multiple threads.
|
||||
+ Copyright (C) 2016-2017 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/>. */
|
||||
+
|
||||
+/* Unlike tst-resolv-basic, this test does not overwrite the _res
|
||||
+ structure and relies on namespaces to achieve the redirection to
|
||||
+ the test servers with a custom /etc/resolv.conf file. */
|
||||
+
|
||||
+#include <dlfcn.h>
|
||||
+#include <errno.h>
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <netdb.h>
|
||||
+#include <resolv/resolv-internal.h>
|
||||
+#include <resolv/resolv_context.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+/* Each client thread sends this many queries. */
|
||||
+enum { queries_per_thread = 500 };
|
||||
+
|
||||
+/* Return a small positive number identifying this thread. */
|
||||
+static int
|
||||
+get_thread_number (void)
|
||||
+{
|
||||
+ static int __thread local;
|
||||
+ if (local != 0)
|
||||
+ return local;
|
||||
+ static int global = 1;
|
||||
+ local = __atomic_fetch_add (&global, 1, __ATOMIC_RELAXED);
|
||||
+ return local;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (qname != NULL);
|
||||
+
|
||||
+ int counter = 0;
|
||||
+ int thread = 0;
|
||||
+ int dummy = 0;
|
||||
+ TEST_VERIFY (sscanf (qname, "counter%d.thread%d.example.com%n",
|
||||
+ &counter, &thread, &dummy) == 2);
|
||||
+ TEST_VERIFY (dummy > 0);
|
||||
+
|
||||
+ struct resolv_response_flags flags = { 0 };
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||||
+ switch (qtype)
|
||||
+ {
|
||||
+ case T_A:
|
||||
+ {
|
||||
+ char ipv4[4] = {10, 0, counter, thread};
|
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||
+ }
|
||||
+ break;
|
||||
+ case T_AAAA:
|
||||
+ {
|
||||
+ char ipv6[16]
|
||||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0,
|
||||
+ counter, 0, thread, 0, 0};
|
||||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
|
||||
+ qname, qclass, qtype);
|
||||
+ }
|
||||
+ resolv_response_close_record (b);
|
||||
+}
|
||||
+
|
||||
+/* Check that the resolver configuration for this thread has an
|
||||
+ extended resolver configuration. */
|
||||
+static void
|
||||
+check_have_conf (void)
|
||||
+{
|
||||
+ struct resolv_context *ctx = __resolv_context_get ();
|
||||
+ TEST_VERIFY_EXIT (ctx != NULL);
|
||||
+ TEST_VERIFY (ctx->conf != NULL);
|
||||
+ __resolv_context_put (ctx);
|
||||
+}
|
||||
+
|
||||
+/* Verify that E matches the expected response for FAMILY and
|
||||
+ COUNTER. */
|
||||
+static void
|
||||
+check_hostent (const char *caller, const char *function, const char *qname,
|
||||
+ int ret, struct hostent *e, int family, int counter)
|
||||
+{
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ errno = ret;
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: %s: %s for %s failed: %m\n", caller, function, qname);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (e != NULL);
|
||||
+ TEST_VERIFY (strcmp (qname, e->h_name) == 0);
|
||||
+ TEST_VERIFY (e->h_addrtype == family);
|
||||
+ TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL);
|
||||
+ TEST_VERIFY (e->h_addr_list[1] == NULL);
|
||||
+ switch (family)
|
||||
+ {
|
||||
+ case AF_INET:
|
||||
+ {
|
||||
+ char addr[4] = {10, 0, counter, get_thread_number ()};
|
||||
+ TEST_VERIFY (e->h_length == sizeof (addr));
|
||||
+ TEST_VERIFY (memcmp (e->h_addr_list[0], addr, sizeof (addr)) == 0);
|
||||
+ }
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ {
|
||||
+ char addr[16]
|
||||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
|
||||
+ 0, counter, 0, get_thread_number (), 0, 0};
|
||||
+ TEST_VERIFY (e->h_length == sizeof (addr));
|
||||
+ TEST_VERIFY (memcmp (e->h_addr_list[0], addr, sizeof (addr)) == 0);
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ FAIL_EXIT1 ("%s: invalid address family %d", caller, family);
|
||||
+ }
|
||||
+ check_have_conf ();
|
||||
+}
|
||||
+
|
||||
+/* Check a getaddrinfo result. */
|
||||
+static void
|
||||
+check_addrinfo (const char *caller, const char *qname,
|
||||
+ int ret, struct addrinfo *ai, int family, int counter)
|
||||
+{
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: %s: getaddrinfo for %s failed: %s\n",
|
||||
+ caller, qname, gai_strerror (ret));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (ai != NULL);
|
||||
+
|
||||
+ /* Check that available data matches the requirements. */
|
||||
+ bool have_ipv4 = false;
|
||||
+ bool have_ipv6 = false;
|
||||
+ for (struct addrinfo *p = ai; p != NULL; p = p->ai_next)
|
||||
+ {
|
||||
+ TEST_VERIFY (p->ai_socktype == SOCK_STREAM);
|
||||
+ TEST_VERIFY (p->ai_protocol == IPPROTO_TCP);
|
||||
+ TEST_VERIFY_EXIT (p->ai_addr != NULL);
|
||||
+ TEST_VERIFY (p->ai_addr->sa_family == p->ai_family);
|
||||
+
|
||||
+ switch (p->ai_family)
|
||||
+ {
|
||||
+ case AF_INET:
|
||||
+ {
|
||||
+ TEST_VERIFY (!have_ipv4);
|
||||
+ have_ipv4 = true;
|
||||
+ struct sockaddr_in *sa = (struct sockaddr_in *) p->ai_addr;
|
||||
+ TEST_VERIFY (p->ai_addrlen == sizeof (*sa));
|
||||
+ char addr[4] = {10, 0, counter, get_thread_number ()};
|
||||
+ TEST_VERIFY (memcmp (&sa->sin_addr, addr, sizeof (addr)) == 0);
|
||||
+ TEST_VERIFY (ntohs (sa->sin_port) == 80);
|
||||
+ }
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ {
|
||||
+ TEST_VERIFY (!have_ipv6);
|
||||
+ have_ipv6 = true;
|
||||
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *) p->ai_addr;
|
||||
+ TEST_VERIFY (p->ai_addrlen == sizeof (*sa));
|
||||
+ char addr[16]
|
||||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
|
||||
+ 0, counter, 0, get_thread_number (), 0, 0};
|
||||
+ TEST_VERIFY (memcmp (&sa->sin6_addr, addr, sizeof (addr)) == 0);
|
||||
+ TEST_VERIFY (ntohs (sa->sin6_port) == 80);
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ FAIL_EXIT1 ("%s: invalid address family %d", caller, family);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ switch (family)
|
||||
+ {
|
||||
+ case AF_INET:
|
||||
+ TEST_VERIFY (have_ipv4);
|
||||
+ TEST_VERIFY (!have_ipv6);
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ TEST_VERIFY (!have_ipv4);
|
||||
+ TEST_VERIFY (have_ipv6);
|
||||
+ break;
|
||||
+ case AF_UNSPEC:
|
||||
+ TEST_VERIFY (have_ipv4);
|
||||
+ TEST_VERIFY (have_ipv6);
|
||||
+ break;
|
||||
+ default:
|
||||
+ FAIL_EXIT1 ("%s: invalid address family %d", caller, family);
|
||||
+ }
|
||||
+
|
||||
+ check_have_conf ();
|
||||
+}
|
||||
+
|
||||
+/* This barrier ensures that all test threads begin their work
|
||||
+ simultaneously. */
|
||||
+static pthread_barrier_t barrier;
|
||||
+
|
||||
+/* Test gethostbyname2_r (if do_2 is false) or gethostbyname2_r with
|
||||
+ AF_INET (if do_2 is true). */
|
||||
+static void *
|
||||
+byname (bool do_2)
|
||||
+{
|
||||
+ int this_thread = get_thread_number ();
|
||||
+ xpthread_barrier_wait (&barrier);
|
||||
+ for (int i = 0; i < queries_per_thread; ++i)
|
||||
+ {
|
||||
+ char qname[100];
|
||||
+ snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com",
|
||||
+ i, this_thread);
|
||||
+ struct hostent storage;
|
||||
+ char buf[1000];
|
||||
+ struct hostent *e = NULL;
|
||||
+ int herrno;
|
||||
+ int ret;
|
||||
+ if (do_2)
|
||||
+ ret = gethostbyname_r (qname, &storage, buf, sizeof (buf),
|
||||
+ &e, &herrno);
|
||||
+ else
|
||||
+ ret = gethostbyname2_r (qname, AF_INET, &storage, buf, sizeof (buf),
|
||||
+ &e, &herrno);
|
||||
+ check_hostent (__func__, do_2 ? "gethostbyname2_r" : "gethostbyname_r",
|
||||
+ qname, ret, e, AF_INET, i);
|
||||
+ }
|
||||
+ check_have_conf ();
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Test gethostbyname_r. */
|
||||
+static void *
|
||||
+thread_byname (void *closure)
|
||||
+{
|
||||
+ return byname (false);
|
||||
+}
|
||||
+
|
||||
+/* Test gethostbyname2_r with AF_INET. */
|
||||
+static void *
|
||||
+thread_byname2 (void *closure)
|
||||
+{
|
||||
+ return byname (true);
|
||||
+}
|
||||
+
|
||||
+/* Call gethostbyname_r with RES_USE_INET6 (if do_2 is false), or
|
||||
+ gethostbyname_r with AF_INET6 (if do_2 is true). */
|
||||
+static void *
|
||||
+byname_inet6 (bool do_2)
|
||||
+{
|
||||
+ int this_thread = get_thread_number ();
|
||||
+ 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)
|
||||
+ {
|
||||
+ char qname[100];
|
||||
+ snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com",
|
||||
+ i, this_thread);
|
||||
+ struct hostent storage;
|
||||
+ char buf[1000];
|
||||
+ struct hostent *e = NULL;
|
||||
+ int herrno;
|
||||
+ int ret;
|
||||
+ if (do_2)
|
||||
+ ret = gethostbyname2_r (qname, AF_INET6, &storage, buf, sizeof (buf),
|
||||
+ &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;
|
||||
+}
|
||||
+
|
||||
+/* 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. */
|
||||
+static void *
|
||||
+gai (int family, bool do_inet6)
|
||||
+{
|
||||
+ int this_thread = get_thread_number ();
|
||||
+ 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)
|
||||
+ {
|
||||
+ char qname[100];
|
||||
+ snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com",
|
||||
+ i, this_thread);
|
||||
+ struct addrinfo hints =
|
||||
+ {
|
||||
+ .ai_family = family,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ .ai_protocol = IPPROTO_TCP,
|
||||
+ };
|
||||
+ struct addrinfo *ai;
|
||||
+ int ret = getaddrinfo (qname, "80", &hints, &ai);
|
||||
+ check_addrinfo (__func__, qname, ret, ai, family, i);
|
||||
+ if (ret == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Test getaddrinfo with AF_INET. */
|
||||
+static void *
|
||||
+thread_gai_inet (void *closure)
|
||||
+{
|
||||
+ return gai (AF_INET, false);
|
||||
+}
|
||||
+
|
||||
+/* Test getaddrinfo with AF_INET6. */
|
||||
+static void *
|
||||
+thread_gai_inet6 (void *closure)
|
||||
+{
|
||||
+ return gai (AF_INET6, false);
|
||||
+}
|
||||
+
|
||||
+/* Test getaddrinfo with AF_UNSPEC. */
|
||||
+static void *
|
||||
+thread_gai_unspec (void *closure)
|
||||
+{
|
||||
+ return gai (AF_UNSPEC, false);
|
||||
+}
|
||||
+
|
||||
+/* 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. */
|
||||
+static struct support_chroot *chroot_env;
|
||||
+
|
||||
+/* Set up the chroot environment. */
|
||||
+static void
|
||||
+prepare (int argc, char **argv)
|
||||
+{
|
||||
+ chroot_env = support_chroot_create
|
||||
+ ((struct support_chroot_configuration)
|
||||
+ {
|
||||
+ .resolv_conf =
|
||||
+ "search example.com\n"
|
||||
+ "nameserver 127.0.0.1\n"
|
||||
+ "nameserver 127.0.0.2\n"
|
||||
+ "nameserver 127.0.0.3\n",
|
||||
+ });
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ support_become_root ();
|
||||
+ if (!support_enter_network_namespace ())
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+ if (!support_can_chroot ())
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ /* Load the shared object outside of the chroot. */
|
||||
+ TEST_VERIFY (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) != NULL);
|
||||
+
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
+ TEST_VERIFY_EXIT (chdir ("/") == 0);
|
||||
+
|
||||
+ struct sockaddr_in server_address =
|
||||
+ {
|
||||
+ .sin_family = AF_INET,
|
||||
+ .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) },
|
||||
+ .sin_port = htons (53)
|
||||
+ };
|
||||
+ const struct sockaddr *server_addresses[1] =
|
||||
+ { (const struct sockaddr *) &server_address };
|
||||
+
|
||||
+ struct resolv_test *aux = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ .nscount = 1,
|
||||
+ .disable_redirect = true,
|
||||
+ .server_address_overrides = server_addresses,
|
||||
+ });
|
||||
+
|
||||
+ enum { thread_count = 10 };
|
||||
+ xpthread_barrier_init (&barrier, NULL, thread_count + 1);
|
||||
+ pthread_t threads[thread_count];
|
||||
+ typedef void *(*thread_func) (void *);
|
||||
+ thread_func thread_funcs[thread_count] =
|
||||
+ {
|
||||
+ thread_byname,
|
||||
+ thread_byname2,
|
||||
+ thread_byname_inet6,
|
||||
+ thread_byname2_af_inet6,
|
||||
+ thread_gai_inet,
|
||||
+ thread_gai_inet6,
|
||||
+ thread_gai_unspec,
|
||||
+ thread_gai_inet_inet6,
|
||||
+ thread_gai_inet6_inet6,
|
||||
+ thread_gai_unspec_inet6,
|
||||
+ };
|
||||
+ for (int i = 0; i < thread_count; ++i)
|
||||
+ threads[i] = xpthread_create (NULL, thread_funcs[i], NULL);
|
||||
+ xpthread_barrier_wait (&barrier); /* Start the test threads. */
|
||||
+ for (int i = 0; i < thread_count; ++i)
|
||||
+ xpthread_join (threads[i]);
|
||||
+
|
||||
+ resolv_test_end (aux);
|
||||
+ support_chroot_free (chroot_env);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define PREPARE prepare
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,33 @@
|
|||
commit 9f5a1271315b0e7c7828f2d8077ab33dca3ee8bd
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Jul 6 14:03:39 2017 +0200
|
||||
|
||||
resolv: Deal with non-deterministic address order in tst-resolv-basic
|
||||
|
||||
diff --git a/resolv/tst-resolv-basic.c b/resolv/tst-resolv-basic.c
|
||||
index 95aea1bcfb266017..66a0e8a1659219b4 100644
|
||||
--- a/resolv/tst-resolv-basic.c
|
||||
+++ b/resolv/tst-resolv-basic.c
|
||||
@@ -495,22 +495,6 @@ do_test (void)
|
||||
test_bug_21295 ();
|
||||
test_nodata_nxdomain ();
|
||||
|
||||
- /* Test for bug 21295. */
|
||||
- check_ai_hints ("www.example", "80",
|
||||
- (struct addrinfo) { .ai_family = AF_INET6,
|
||||
- .ai_socktype = SOCK_STREAM,
|
||||
- .ai_flags = AI_V4MAPPED | AI_ALL, },
|
||||
- "flags: AI_V4MAPPED AI_ALL\n"
|
||||
- "address: STREAM/TCP 2001:db8::1 80\n"
|
||||
- "address: STREAM/TCP ::ffff:192.0.2.17 80\n");
|
||||
- check_ai_hints ("t.www.example", "80",
|
||||
- (struct addrinfo) { .ai_family = AF_INET6,
|
||||
- .ai_socktype = SOCK_STREAM,
|
||||
- .ai_flags = AI_V4MAPPED | AI_ALL, },
|
||||
- "flags: AI_V4MAPPED AI_ALL\n"
|
||||
- "address: STREAM/TCP 2001:db8::3 80\n"
|
||||
- "address: STREAM/TCP ::ffff:192.0.2.19 80\n");
|
||||
-
|
||||
resolv_test_end (aux);
|
||||
|
||||
return 0;
|
|
@ -0,0 +1,224 @@
|
|||
commit 4e45d83c92dbb5b8dc20654f32395108d18cf739
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jul 3 17:41:19 2017 +0200
|
||||
|
||||
resolv: Add preinit tests to resolv/tst-resolv-res_init-skeleton.c
|
||||
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index b5fe2cfb002679f2..ce206f52c4c27c32 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -260,7 +260,7 @@ enum test_init
|
||||
static const char *const test_init_names[] =
|
||||
{
|
||||
[test_init] = "res_init",
|
||||
- [test_ninit] = "res_init",
|
||||
+ [test_ninit] = "res_ninit",
|
||||
[test_mkquery] = "res_mkquery",
|
||||
[test_gethostbyname] = "gethostbyname",
|
||||
[test_getaddrinfo] = "getaddrinfo",
|
||||
@@ -540,6 +540,192 @@ test_file_contents (const struct test_case *t)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Special tests which do not follow the general pattern. */
|
||||
+enum { special_tests_count = 7 };
|
||||
+
|
||||
+#if TEST_THREAD
|
||||
+/* Called from test number 3-6 to trigger reloading of the
|
||||
+ configuration. */
|
||||
+static void *
|
||||
+special_test_call_res_init (void *closure)
|
||||
+{
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/* Implementation of special tests. */
|
||||
+static void
|
||||
+special_test_callback (void *closure)
|
||||
+{
|
||||
+ unsigned int *test_indexp = closure;
|
||||
+ unsigned test_index = *test_indexp;
|
||||
+ TEST_VERIFY (test_index < special_tests_count);
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: special test %u\n", test_index);
|
||||
+ xchroot (path_chroot);
|
||||
+
|
||||
+ switch (test_index)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ case 1:
|
||||
+ /* Second res_init with missing or empty file preserves
|
||||
+ flags. */
|
||||
+ if (test_index == 1)
|
||||
+ TEST_VERIFY (unlink (_PATH_RESCONF) == 0);
|
||||
+ _res.options = RES_USE_EDNS0;
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ /* First res_init clears flag. */
|
||||
+ TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
|
||||
+ _res.options |= RES_USE_EDNS0;
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ /* Second res_init preserves flag. */
|
||||
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
|
||||
+ if (test_index == 1)
|
||||
+ /* Restore empty file. */
|
||||
+ support_write_file_string (_PATH_RESCONF, "");
|
||||
+ break;
|
||||
+
|
||||
+ case 2:
|
||||
+ /* Second res_init is cumulative. */
|
||||
+ support_write_file_string (_PATH_RESCONF,
|
||||
+ "options rotate\n"
|
||||
+ "nameserver 192.0.2.1\n");
|
||||
+ _res.options = RES_USE_EDNS0;
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ /* First res_init clears flag. */
|
||||
+ TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
|
||||
+ /* And sets RES_ROTATE. */
|
||||
+ TEST_VERIFY (_res.options & RES_ROTATE);
|
||||
+ _res.options |= RES_USE_EDNS0;
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ /* Second res_init preserves flag. */
|
||||
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
|
||||
+ TEST_VERIFY (_res.options & RES_ROTATE);
|
||||
+ /* Reloading the configuration does not clear the explicitly set
|
||||
+ flag. */
|
||||
+ support_write_file_string (_PATH_RESCONF,
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 192.0.2.2\n");
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ TEST_VERIFY (_res.nscount == 2);
|
||||
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
|
||||
+ /* Whether RES_ROTATE (originally in resolv.conf, now removed)
|
||||
+ should be preserved is subject to debate. See bug 21701. */
|
||||
+ /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */
|
||||
+ break;
|
||||
+
|
||||
+ case 3:
|
||||
+ case 4:
|
||||
+ case 5:
|
||||
+ case 6:
|
||||
+ /* Test res_init change broadcast. This requires a second
|
||||
+ thread to trigger the reload. */
|
||||
+#if TEST_THREAD
|
||||
+ support_write_file_string (_PATH_RESCONF,
|
||||
+ "options edns0\n"
|
||||
+ "nameserver 192.0.2.1\n");
|
||||
+ for (int iteration = 0; iteration < 2; ++iteration)
|
||||
+ {
|
||||
+ switch (test_index)
|
||||
+ {
|
||||
+ case 3:
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ {
|
||||
+ unsigned char buf[512];
|
||||
+ TEST_VERIFY
|
||||
+ (res_mkquery (QUERY, test_hostname, C_IN, T_A,
|
||||
+ NULL, 0, NULL, buf, sizeof (buf)) > 0);
|
||||
+ }
|
||||
+ break;
|
||||
+ case 5:
|
||||
+ gethostbyname (test_hostname);
|
||||
+ break;
|
||||
+ case 6:
|
||||
+ {
|
||||
+ struct addrinfo *ai;
|
||||
+ (void) getaddrinfo (test_hostname, NULL, NULL, &ai);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ if (iteration == 0)
|
||||
+ {
|
||||
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
|
||||
+ TEST_VERIFY (!(_res.options & RES_ROTATE));
|
||||
+ TEST_VERIFY (_res.nscount == 1);
|
||||
+ support_write_file_string (_PATH_RESCONF,
|
||||
+ "options rotate\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "nameserver 192.0.2.2\n");
|
||||
+ xpthread_join (xpthread_create
|
||||
+ (NULL, special_test_call_res_init, NULL));
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* edns0 was dropped, but the flag is not cleared. See
|
||||
+ bug 21701. */
|
||||
+ /* TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); */
|
||||
+ TEST_VERIFY (_res.options & RES_ROTATE);
|
||||
+ TEST_VERIFY (_res.nscount == 2);
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#if TEST_THREAD
|
||||
+/* Helper function which calls special_test_callback from a
|
||||
+ thread. */
|
||||
+static void *
|
||||
+special_test_thread_func (void *closure)
|
||||
+{
|
||||
+ special_test_callback (closure);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Variant of special_test_callback which runs the function on a
|
||||
+ non-main thread. */
|
||||
+static void
|
||||
+run_special_test_on_thread (void *closure)
|
||||
+{
|
||||
+ xpthread_join (xpthread_create (NULL, special_test_thread_func, closure));
|
||||
+}
|
||||
+#endif /* TEST_THREAD */
|
||||
+
|
||||
+/* Perform the requested special test in a subprocess using
|
||||
+ special_test_callback. */
|
||||
+static void
|
||||
+special_test (unsigned int test_index)
|
||||
+{
|
||||
+#if TEST_THREAD
|
||||
+ for (int do_thread = 0; do_thread < 2; ++do_thread)
|
||||
+#endif
|
||||
+ {
|
||||
+ void (*func) (void *) = special_test_callback;
|
||||
+#if TEST_THREAD
|
||||
+ if (do_thread)
|
||||
+ func = run_special_test_on_thread;
|
||||
+#endif
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprocess (func, &test_index);
|
||||
+ char *test_name = xasprintf ("special test %u", test_index);
|
||||
+ if (strcmp (proc.out.buffer, "") != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: output mismatch for %s\n", test_name);
|
||||
+ support_run_diff ("expected", "",
|
||||
+ "actual", proc.out.buffer);
|
||||
+ }
|
||||
+ support_capture_subprocess_check (&proc, test_name, 0, sc_allow_stdout);
|
||||
+ free (test_name);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Dummy DNS server. It ensures that the probe queries sent by
|
||||
gethostbyname and getaddrinfo receive a reply even if the system
|
||||
applies a very strict rate limit to localhost. */
|
||||
@@ -672,6 +858,11 @@ do_test (void)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* The tests which do not follow a regular pattern. */
|
||||
+ for (unsigned int test_index = 0;
|
||||
+ test_index < special_tests_count; ++test_index)
|
||||
+ special_test (test_index);
|
||||
+
|
||||
if (server > 0)
|
||||
{
|
||||
if (kill (server, SIGTERM) < 0)
|
|
@ -0,0 +1,128 @@
|
|||
commit 39bd76df3d61c6d83c5aa8bab06c7c1dbe7159ac
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jun 27 10:21:34 2017 +0200
|
||||
|
||||
resolv: Avoid timeouts in test-resolv-res-init, test-resolv-res_init-thread
|
||||
|
||||
Some Linux kernels have very aggressive ICMP rate limiting on the
|
||||
loopback interface. This commit introduces a minimal echoing DNS server
|
||||
inside the network namespace, so that there is no need for ICMP error
|
||||
messages anymore.
|
||||
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index 1d2c475c4b233131..2b68c5ff9a69a291 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -21,6 +21,7 @@
|
||||
in. */
|
||||
|
||||
#include <arpa/inet.h>
|
||||
+#include <errno.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */
|
||||
@@ -33,6 +34,7 @@
|
||||
#include <support/support.h>
|
||||
#include <support/temp_file.h>
|
||||
#include <support/test-driver.h>
|
||||
+#include <support/xsocket.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
@@ -527,6 +529,73 @@ test_file_contents (const struct test_case *t)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Dummy DNS server. It ensures that the probe queries sent by
|
||||
+ gethostbyname and getaddrinfo receive a reply even if the system
|
||||
+ applies a very strict rate limit to localhost. */
|
||||
+static pid_t
|
||||
+start_dummy_server (void)
|
||||
+{
|
||||
+ int server_socket = xsocket (AF_INET, SOCK_DGRAM, 0);
|
||||
+ {
|
||||
+ struct sockaddr_in sin =
|
||||
+ {
|
||||
+ .sin_family = AF_INET,
|
||||
+ .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) },
|
||||
+ .sin_port = htons (53),
|
||||
+ };
|
||||
+ int ret = bind (server_socket, (struct sockaddr *) &sin, sizeof (sin));
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ if (errno == EACCES)
|
||||
+ /* The port is reserved, which means we cannot start the
|
||||
+ server. */
|
||||
+ return -1;
|
||||
+ FAIL_EXIT1 ("cannot bind socket to port 53: %m");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pid_t pid = xfork ();
|
||||
+ if (pid == 0)
|
||||
+ {
|
||||
+ /* Child process. Echo back queries as SERVFAIL responses. */
|
||||
+ while (true)
|
||||
+ {
|
||||
+ union
|
||||
+ {
|
||||
+ HEADER header;
|
||||
+ unsigned char bytes[512];
|
||||
+ } packet;
|
||||
+ struct sockaddr_in sin;
|
||||
+ socklen_t sinlen = sizeof (sin);
|
||||
+
|
||||
+ ssize_t ret = recvfrom
|
||||
+ (server_socket, &packet, sizeof (packet),
|
||||
+ MSG_NOSIGNAL, (struct sockaddr *) &sin, &sinlen);
|
||||
+ if (ret < 0)
|
||||
+ FAIL_EXIT1 ("recvfrom on fake server socket: %m");
|
||||
+ if (ret > sizeof (HEADER))
|
||||
+ {
|
||||
+ /* Turn the query into a SERVFAIL response. */
|
||||
+ packet.header.qr = 1;
|
||||
+ packet.header.rcode = ns_r_servfail;
|
||||
+
|
||||
+ /* Send the response. */
|
||||
+ ret = sendto (server_socket, &packet, ret,
|
||||
+ MSG_NOSIGNAL, (struct sockaddr *) &sin, sinlen);
|
||||
+ if (ret < 0)
|
||||
+ /* The peer may have closed socket prematurely, so
|
||||
+ this is not an error. */
|
||||
+ printf ("warning: sending DNS server reply: %m\n");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* In the parent, close the socket. */
|
||||
+ xclose (server_socket);
|
||||
+
|
||||
+ return pid;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
@@ -552,6 +621,8 @@ do_test (void)
|
||||
support_capture_subprocess_free (&proc);
|
||||
}
|
||||
|
||||
+ pid_t server = start_dummy_server ();
|
||||
+
|
||||
for (size_t i = 0; test_cases[i].name != NULL; ++i)
|
||||
{
|
||||
if (test_verbose > 0)
|
||||
@@ -590,6 +661,13 @@ do_test (void)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (server > 0)
|
||||
+ {
|
||||
+ if (kill (server, SIGTERM) < 0)
|
||||
+ FAIL_EXIT1 ("could not terminate server process: %m");
|
||||
+ xwaitpid (server, NULL, 0);
|
||||
+ }
|
||||
+
|
||||
free (path_chroot);
|
||||
path_chroot = NULL;
|
||||
free (path_resolv_conf);
|
|
@ -0,0 +1,132 @@
|
|||
commit 4446a885f3aeb3a33b95c72bae1f115bed77f0cb
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jul 4 14:47:29 2017 +0200
|
||||
|
||||
resolv: Fix resolv_conf _res matching
|
||||
|
||||
A dot-less host name without an /etc/resolv.conf file caused an
|
||||
assertion failure in update_from_conf because the function would not
|
||||
deal correctly with the empty search list case.
|
||||
|
||||
Thanks to Andreas Schwab for debugging assistence.
|
||||
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index 0ed36cde02608f2d..f391d30c277bb348 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -272,7 +272,7 @@ resolv_conf_matches (const struct __res_state *resp,
|
||||
nserv = MAXNS;
|
||||
/* _ext.nscount is 0 until initialized by res_send.c. */
|
||||
if (resp->nscount != nserv
|
||||
- && (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv))
|
||||
+ || (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv))
|
||||
return false;
|
||||
for (size_t i = 0; i < nserv; ++i)
|
||||
{
|
||||
@@ -295,9 +295,25 @@ resolv_conf_matches (const struct __res_state *resp,
|
||||
/* Check that the search list in *RESP has not been modified by the
|
||||
application. */
|
||||
{
|
||||
- if (!(resp->dnsrch[0] == resp->defdname
|
||||
- && resp->dnsrch[MAXDNSRCH] == NULL))
|
||||
+ if (resp->dnsrch[0] == NULL)
|
||||
+ {
|
||||
+ /* Empty search list. No default domain name. */
|
||||
+ return conf->search_list_size == 0 && resp->defdname[0] == '\0';
|
||||
+ }
|
||||
+
|
||||
+ if (resp->dnsrch[0] != resp->defdname)
|
||||
+ /* If the search list is not empty, it must start with the
|
||||
+ default domain name. */
|
||||
+ return false;
|
||||
+
|
||||
+ size_t nsearch;
|
||||
+ for (nsearch = 0; nsearch < MAXDNSRCH; ++nsearch)
|
||||
+ if (resp->dnsrch[nsearch] == NULL)
|
||||
+ break;
|
||||
+ if (nsearch > MAXDNSRCH)
|
||||
+ /* Search list is not null-terminated. */
|
||||
return false;
|
||||
+
|
||||
size_t search_list_size = 0;
|
||||
for (size_t i = 0; i < conf->search_list_size; ++i)
|
||||
{
|
||||
@@ -326,6 +342,8 @@ resolv_conf_matches (const struct __res_state *resp,
|
||||
size_t nsort = conf->sort_list_size;
|
||||
if (nsort > MAXRESOLVSORT)
|
||||
nsort = MAXRESOLVSORT;
|
||||
+ if (resp->nsort != nsort)
|
||||
+ return false;
|
||||
for (size_t i = 0; i < nsort; ++i)
|
||||
if (resp->sort_list[i].addr.s_addr != conf->sort_list[i].addr.s_addr
|
||||
|| resp->sort_list[i].mask != conf->sort_list[i].mask)
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index 9e496a3212b0f2ab..8f395d8ce92773a9 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -307,6 +307,10 @@ struct test_case
|
||||
/* Setting for the RES_OPTIONS environment variable. NULL if the
|
||||
variable is not to be set. */
|
||||
const char *res_options;
|
||||
+
|
||||
+ /* Override the system host name. NULL means that no change is made
|
||||
+ and the default is used (test_hostname). */
|
||||
+ const char *hostname;
|
||||
};
|
||||
|
||||
enum test_init
|
||||
@@ -358,6 +362,14 @@ run_res_init (void *closure)
|
||||
setenv ("LOCALDOMAIN", ctx->t->localdomain, 1);
|
||||
if (ctx->t->res_options != NULL)
|
||||
setenv ("RES_OPTIONS", ctx->t->res_options, 1);
|
||||
+ if (ctx->t->hostname != NULL)
|
||||
+ {
|
||||
+ /* This test needs its own namespace, to avoid changing the host
|
||||
+ name for the parent, too. */
|
||||
+ TEST_VERIFY_EXIT (unshare (CLONE_NEWUTS) == 0);
|
||||
+ if (sethostname (ctx->t->hostname, strlen (ctx->t->hostname)) != 0)
|
||||
+ FAIL_EXIT1 ("sethostname (\"%s\"): %m", ctx->t->hostname);
|
||||
+ }
|
||||
|
||||
switch (ctx->init)
|
||||
{
|
||||
@@ -434,6 +446,12 @@ struct test_case test_cases[] =
|
||||
"nameserver 127.0.0.1\n"
|
||||
"; nameserver[0]: [127.0.0.1]:53\n"
|
||||
},
|
||||
+ {.name = "empty file, no-dot hostname",
|
||||
+ .conf = "",
|
||||
+ .expected = "nameserver 127.0.0.1\n"
|
||||
+ "; nameserver[0]: [127.0.0.1]:53\n",
|
||||
+ .hostname = "example",
|
||||
+ },
|
||||
{.name = "empty file with LOCALDOMAIN",
|
||||
.conf = "",
|
||||
.expected = "search example.net\n"
|
||||
@@ -462,8 +480,7 @@ struct test_case test_cases[] =
|
||||
.res_options = "edns0 attempts:5",
|
||||
},
|
||||
{.name = "basic",
|
||||
- .conf = "domain example.net\n"
|
||||
- "search corp.example.com example.com\n"
|
||||
+ .conf = "search corp.example.com example.com\n"
|
||||
"nameserver 192.0.2.1\n",
|
||||
.expected = "search corp.example.com example.com\n"
|
||||
"; search[0]: corp.example.com\n"
|
||||
@@ -471,6 +488,16 @@ struct test_case test_cases[] =
|
||||
"nameserver 192.0.2.1\n"
|
||||
"; nameserver[0]: [192.0.2.1]:53\n"
|
||||
},
|
||||
+ {.name = "basic with no-dot hostname",
|
||||
+ .conf = "search corp.example.com example.com\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "search corp.example.com example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "; nameserver[0]: [192.0.2.1]:53\n",
|
||||
+ .hostname = "example",
|
||||
+ },
|
||||
{.name = "basic no-reload",
|
||||
.conf = "options no-reload\n"
|
||||
"search corp.example.com example.com\n"
|
|
@ -0,0 +1,251 @@
|
|||
commit e237357a5a0559dee92261f1914d1fa2cd43a1a8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jul 3 15:01:34 2017 +0200
|
||||
|
||||
resolv: Introduce free list for resolv_conf index slosts
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index ef5ed2966e4d6c51..c1fcf341746cf1a8 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -63,6 +63,9 @@ tests += \
|
||||
tst-resolv-res_init \
|
||||
tst-resolv-res_init-thread \
|
||||
|
||||
+# Needs resolv_context.
|
||||
+tests += tst-resolv-res_ninit
|
||||
+
|
||||
endif
|
||||
|
||||
# This test accesses __inet_ntop_range, an internal libc function.
|
||||
@@ -103,6 +106,7 @@ ifeq ($(run-built-tests),yes)
|
||||
ifneq (no,$(PERL))
|
||||
tests-special += $(objpfx)mtrace-tst-leaks.out
|
||||
xtests-special += $(objpfx)mtrace-tst-leaks2.out
|
||||
+tests-special += $(objpfx)mtrace-tst-resolv-res_ninit.out
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -114,7 +118,8 @@ headers += rpc/netdb.h
|
||||
endif
|
||||
|
||||
generated += mtrace-tst-leaks.out tst-leaks.mtrace \
|
||||
- mtrace-tst-leaks2.out tst-leaks2.mtrace
|
||||
+ mtrace-tst-leaks2.out tst-leaks2.mtrace \
|
||||
+ mtrace-tst-resolv-res_ninit.out tst-resolv-res_ninit.mtrace \
|
||||
|
||||
include ../Rules
|
||||
|
||||
@@ -142,6 +147,12 @@ $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+tst-resolv-res_ninit-ENV = MALLOC_TRACE=$(objpfx)tst-resolv-res_ninit.mtrace
|
||||
+$(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out
|
||||
+ $(common-objpfx)malloc/mtrace \
|
||||
+ $(objpfx)tst-resolv-res_ninit.mtrace > $@; \
|
||||
+ $(evaluate-test)
|
||||
+
|
||||
$(objpfx)tst-bug18665-tcp: $(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)
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index 9ef59240ebc57a70..b98cf92890a121f9 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -28,9 +28,12 @@
|
||||
struct resolv_conf_array object. The intent of this construction
|
||||
is to make reasonably sure that even if struct __res_state objects
|
||||
are copied around and patched by applications, we can still detect
|
||||
- accesses to stale extended resolver state. */
|
||||
+ accesses to stale extended resolver state. The array elements are
|
||||
+ either struct resolv_conf * pointers (if the LSB is cleared) or
|
||||
+ free list entries (if the LSB is set). The free list is used to
|
||||
+ speed up finding available entries in the array. */
|
||||
#define DYNARRAY_STRUCT resolv_conf_array
|
||||
-#define DYNARRAY_ELEMENT struct resolv_conf *
|
||||
+#define DYNARRAY_ELEMENT uintptr_t
|
||||
#define DYNARRAY_PREFIX resolv_conf_array_
|
||||
#define DYNARRAY_INITIAL_SIZE 0
|
||||
#include <malloc/dynarray-skeleton.c>
|
||||
@@ -55,6 +58,10 @@ struct resolv_conf_global
|
||||
the array element is overwritten with NULL. */
|
||||
struct resolv_conf_array array;
|
||||
|
||||
+ /* Start of the free list in the array. The MSB is set if this
|
||||
+ field has been initialized. */
|
||||
+ uintptr_t free_list_start;
|
||||
+
|
||||
/* Cached current configuration object for /etc/resolv.conf. */
|
||||
struct resolv_conf *conf_current;
|
||||
|
||||
@@ -194,15 +201,17 @@ resolv_conf_get_1 (const struct __res_state *resp)
|
||||
contexts exists, so returning NULL is correct. */
|
||||
return NULL;
|
||||
size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC;
|
||||
- struct resolv_conf *conf;
|
||||
+ struct resolv_conf *conf = NULL;
|
||||
if (index < resolv_conf_array_size (&global_copy->array))
|
||||
{
|
||||
- conf = *resolv_conf_array_at (&global_copy->array, index);
|
||||
- assert (conf->__refcount > 0);
|
||||
- ++conf->__refcount;
|
||||
+ uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
|
||||
+ if (!(*slot & 1))
|
||||
+ {
|
||||
+ conf = (struct resolv_conf *) *slot;
|
||||
+ assert (conf->__refcount > 0);
|
||||
+ ++conf->__refcount;
|
||||
+ }
|
||||
}
|
||||
- else
|
||||
- conf = NULL;
|
||||
put_locked_global (global_copy);
|
||||
return conf;
|
||||
}
|
||||
@@ -550,17 +559,20 @@ decrement_at_index (struct resolv_conf_global *global_copy, size_t index)
|
||||
{
|
||||
if (index < resolv_conf_array_size (&global_copy->array))
|
||||
{
|
||||
- /* Index found. Deallocate the struct resolv_conf object once
|
||||
- the reference counter reaches. Free the array slot. */
|
||||
- struct resolv_conf **slot
|
||||
- = resolv_conf_array_at (&global_copy->array, index);
|
||||
- struct resolv_conf *conf = *slot;
|
||||
- if (conf != NULL)
|
||||
+ /* Index found. */
|
||||
+ uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
|
||||
+ /* Check that the slot is not already part of the free list. */
|
||||
+ if (!(*slot & 1))
|
||||
{
|
||||
+ struct resolv_conf *conf = (struct resolv_conf *) *slot;
|
||||
conf_decrement (conf);
|
||||
- /* Clear the slot even if the reference count is positive.
|
||||
- Slots are not shared. */
|
||||
- *slot = NULL;
|
||||
+ /* Put the slot onto the free list. */
|
||||
+ if (global_copy->free_list_start == 0)
|
||||
+ /* Not yet initialized. */
|
||||
+ *slot = 1;
|
||||
+ else
|
||||
+ *slot = global_copy->free_list_start;
|
||||
+ global_copy->free_list_start = (index << 1) | 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -580,24 +592,21 @@ __resolv_conf_attach (struct __res_state *resp, struct resolv_conf *conf)
|
||||
/* Try to find an unused index in the array. */
|
||||
size_t index;
|
||||
{
|
||||
- size_t size = resolv_conf_array_size (&global_copy->array);
|
||||
- bool found = false;
|
||||
- for (index = 0; index < size; ++index)
|
||||
+ if (global_copy->free_list_start & 1)
|
||||
{
|
||||
- struct resolv_conf **p
|
||||
- = resolv_conf_array_at (&global_copy->array, index);
|
||||
- if (*p == NULL)
|
||||
- {
|
||||
- *p = conf;
|
||||
- found = true;
|
||||
- break;
|
||||
- }
|
||||
+ /* Unlink from the free list. */
|
||||
+ index = global_copy->free_list_start >> 1;
|
||||
+ uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
|
||||
+ global_copy->free_list_start = *slot;
|
||||
+ assert (global_copy->free_list_start & 1);
|
||||
+ /* Install the configuration pointer. */
|
||||
+ *slot = (uintptr_t) conf;
|
||||
}
|
||||
-
|
||||
- if (!found)
|
||||
+ else
|
||||
{
|
||||
+ size_t size = resolv_conf_array_size (&global_copy->array);
|
||||
/* No usable index found. Increase the array size. */
|
||||
- resolv_conf_array_add (&global_copy->array, conf);
|
||||
+ resolv_conf_array_add (&global_copy->array, (uintptr_t) conf);
|
||||
if (resolv_conf_array_has_failed (&global_copy->array))
|
||||
{
|
||||
put_locked_global (global_copy);
|
||||
diff --git a/resolv/tst-resolv-res_ninit.c b/resolv/tst-resolv-res_ninit.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d08153fed78b5f03
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-res_ninit.c
|
||||
@@ -0,0 +1,74 @@
|
||||
+/* Test the creation of many struct __res_state objects.
|
||||
+ Copyright (C) 2017 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 <mcheck.h>
|
||||
+#include <resolv.h>
|
||||
+#include <resolv/resolv_context.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+/* Order the resolver states by their extended resolver state
|
||||
+ index. */
|
||||
+static int
|
||||
+sort_res_state (const void *a, const void *b)
|
||||
+{
|
||||
+ res_state left = (res_state) a;
|
||||
+ res_state right = (res_state) b;
|
||||
+ return memcmp (&left->_u._ext.__glibc_extension_index,
|
||||
+ &right->_u._ext.__glibc_extension_index,
|
||||
+ sizeof (left->_u._ext.__glibc_extension_index));
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+
|
||||
+ enum { count = 100 * 1000 };
|
||||
+ res_state array = calloc (count, sizeof (*array));
|
||||
+ const struct resolv_conf *conf = NULL;
|
||||
+ for (size_t i = 0; i < count; ++i)
|
||||
+ {
|
||||
+ TEST_VERIFY (res_ninit (array + i) == 0);
|
||||
+ TEST_VERIFY (array[i].nscount > 0);
|
||||
+ struct resolv_context *ctx = __resolv_context_get_override (array + i);
|
||||
+ TEST_VERIFY_EXIT (ctx != NULL);
|
||||
+ TEST_VERIFY (ctx->resp == array + i);
|
||||
+ if (i == 0)
|
||||
+ {
|
||||
+ conf = ctx->conf;
|
||||
+ TEST_VERIFY (conf != NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ /* The underyling configuration should be identical across all
|
||||
+ res_state opjects because resolv.conf did not change. */
|
||||
+ TEST_VERIFY (ctx->conf == conf);
|
||||
+ }
|
||||
+ qsort (array, count, sizeof (*array), sort_res_state);
|
||||
+ for (size_t i = 1; i < count; ++i)
|
||||
+ /* All extension indices should be different. */
|
||||
+ TEST_VERIFY (sort_res_state (array + i - 1, array + i) < 0);
|
||||
+ for (size_t i = 0; i < count; ++i)
|
||||
+ res_nclose (array + i);
|
||||
+ free (array);
|
||||
+
|
||||
+ TEST_VERIFY (res_init () == 0);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,788 @@
|
|||
commit 3f853f22c87f0b671c0366eb290919719fa56c0e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Jul 1 00:53:05 2017 +0200
|
||||
|
||||
resolv: Lift domain search list limits [BZ #19569] [BZ #21475]
|
||||
|
||||
This change uses the extended resolver state in struct resolv_conf to
|
||||
store the search list. If applications have not patched the _res
|
||||
object directly, this extended search list will be used by the stub
|
||||
resolver during name resolution.
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 659d3ea81f973257..5941d37f3241b1e7 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -124,18 +124,75 @@ is_sort_mask (char ch)
|
||||
return ch == '/' || ch == '&';
|
||||
}
|
||||
|
||||
+/* Array of strings for the search array. The backing store is
|
||||
+ managed separately. */
|
||||
+#define DYNARRAY_STRUCT search_list
|
||||
+#define DYNARRAY_ELEMENT const char *
|
||||
+#define DYNARRAY_INITIAL_SIZE 4
|
||||
+#define DYNARRAY_PREFIX search_list_
|
||||
+#include <malloc/dynarray-skeleton.c>
|
||||
+
|
||||
+/* resolv.conf parser state and results. */
|
||||
+struct resolv_conf_parser
|
||||
+{
|
||||
+ char *buffer; /* Temporary buffer for reading lines. */
|
||||
+ char *search_list_store; /* Backing storage for search list entries. */
|
||||
+ struct search_list search_list; /* Points into search_list_store. */
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+resolv_conf_parser_init (struct resolv_conf_parser *parser)
|
||||
+{
|
||||
+ parser->buffer = NULL;
|
||||
+ parser->search_list_store = NULL;
|
||||
+ search_list_init (&parser->search_list);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+resolv_conf_parser_free (struct resolv_conf_parser *parser)
|
||||
+{
|
||||
+ free (parser->buffer);
|
||||
+ free (parser->search_list_store);
|
||||
+ search_list_free (&parser->search_list);
|
||||
+}
|
||||
+
|
||||
+/* Try to obtain the domain name from the host name and store it in
|
||||
+ *RESULT. Return false on memory allocation failure. If the domain
|
||||
+ name cannot be determined for any other reason, write NULL to
|
||||
+ *RESULT and return true. */
|
||||
+static bool
|
||||
+domain_from_hostname (char **result)
|
||||
+{
|
||||
+ char buf[256];
|
||||
+ /* gethostbyname may not terminate the buffer. */
|
||||
+ buf[sizeof (buf) - 1] = '\0';
|
||||
+ if (__gethostname (buf, sizeof (buf) - 1) == 0)
|
||||
+ {
|
||||
+ char *dot = strchr (buf, '.');
|
||||
+ if (dot != NULL)
|
||||
+ {
|
||||
+ *result = __strdup (dot + 1);
|
||||
+ if (*result == NULL)
|
||||
+ return false;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ *result = NULL;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
/* Internal helper function for __res_vinit, to aid with resource
|
||||
deallocation and error handling. Return true on success, false on
|
||||
failure. */
|
||||
static bool
|
||||
-res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
+res_vinit_1 (res_state statp, bool preinit, FILE *fp,
|
||||
+ struct resolv_conf_parser *parser)
|
||||
{
|
||||
- char *cp, **pp;
|
||||
+ char *cp;
|
||||
size_t buffer_size = 0;
|
||||
int nserv = 0; /* Number of nameservers read from file. */
|
||||
bool have_serv6 = false;
|
||||
bool haveenv = false;
|
||||
- bool havesearch = false;
|
||||
int nsort = 0;
|
||||
char *net;
|
||||
|
||||
@@ -162,39 +219,40 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
/* Allow user to override the local domain definition. */
|
||||
if ((cp = getenv ("LOCALDOMAIN")) != NULL)
|
||||
{
|
||||
- strncpy (statp->defdname, cp, sizeof (statp->defdname) - 1);
|
||||
- statp->defdname[sizeof (statp->defdname) - 1] = '\0';
|
||||
+ /* The code below splits the string in place. */
|
||||
+ cp = __strdup (cp);
|
||||
+ if (cp == NULL)
|
||||
+ return false;
|
||||
+ free (parser->search_list_store);
|
||||
+ parser->search_list_store = cp;
|
||||
haveenv = true;
|
||||
|
||||
+ /* The string will be truncated as needed below. */
|
||||
+ search_list_add (&parser->search_list, cp);
|
||||
+
|
||||
/* Set search list to be blank-separated strings from rest of
|
||||
env value. Permits users of LOCALDOMAIN to still have a
|
||||
search list, and anyone to set the one that they want to use
|
||||
as an individual (even more important now that the rfc1535
|
||||
stuff restricts searches). */
|
||||
- cp = statp->defdname;
|
||||
- pp = statp->dnsrch;
|
||||
- *pp++ = cp;
|
||||
- for (int n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++)
|
||||
+ for (bool in_name = true; *cp != '\0'; cp++)
|
||||
{
|
||||
if (*cp == '\n')
|
||||
- break;
|
||||
+ {
|
||||
+ *cp = '\0';
|
||||
+ break;
|
||||
+ }
|
||||
else if (*cp == ' ' || *cp == '\t')
|
||||
{
|
||||
- *cp = 0;
|
||||
- n = 1;
|
||||
+ *cp = '\0';
|
||||
+ in_name = false;
|
||||
}
|
||||
- else if (n > 0)
|
||||
+ else if (!in_name)
|
||||
{
|
||||
- *pp++ = cp;
|
||||
- n = 0;
|
||||
- havesearch = true;
|
||||
+ search_list_add (&parser->search_list, cp);
|
||||
+ in_name = true;
|
||||
}
|
||||
}
|
||||
- /* Null terminate last domain if there are excess. */
|
||||
- while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
- cp++;
|
||||
- *cp = '\0';
|
||||
- *pp++ = 0;
|
||||
}
|
||||
|
||||
#define MATCH(line, name) \
|
||||
@@ -210,7 +268,7 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
- ssize_t ret = __getline (buffer, &buffer_size, fp);
|
||||
+ ssize_t ret = __getline (&parser->buffer, &buffer_size, fp);
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (_IO_ferror_unlocked (fp))
|
||||
@@ -221,73 +279,82 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
}
|
||||
|
||||
/* Skip comments. */
|
||||
- if (**buffer == ';' || **buffer == '#')
|
||||
+ if (*parser->buffer == ';' || *parser->buffer == '#')
|
||||
continue;
|
||||
/* Read default domain name. */
|
||||
- if (MATCH (*buffer, "domain"))
|
||||
+ if (MATCH (parser->buffer, "domain"))
|
||||
{
|
||||
if (haveenv)
|
||||
/* LOCALDOMAIN overrides the configuration file. */
|
||||
continue;
|
||||
- cp = *buffer + sizeof ("domain") - 1;
|
||||
+ cp = parser->buffer + sizeof ("domain") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
- strncpy (statp->defdname, cp, sizeof (statp->defdname) - 1);
|
||||
- statp->defdname[sizeof (statp->defdname) - 1] = '\0';
|
||||
- if ((cp = strpbrk (statp->defdname, " \t\n")) != NULL)
|
||||
+
|
||||
+ cp = __strdup (cp);
|
||||
+ if (cp == NULL)
|
||||
+ return false;
|
||||
+ free (parser->search_list_store);
|
||||
+ parser->search_list_store = cp;
|
||||
+ search_list_clear (&parser->search_list);
|
||||
+ search_list_add (&parser->search_list, cp);
|
||||
+ /* Replace trailing whitespace. */
|
||||
+ if ((cp = strpbrk (cp, " \t\n")) != NULL)
|
||||
*cp = '\0';
|
||||
- havesearch = false;
|
||||
continue;
|
||||
}
|
||||
/* Set search list. */
|
||||
- if (MATCH (*buffer, "search"))
|
||||
+ if (MATCH (parser->buffer, "search"))
|
||||
{
|
||||
if (haveenv)
|
||||
/* LOCALDOMAIN overrides the configuration file. */
|
||||
continue;
|
||||
- cp = *buffer + sizeof ("search") - 1;
|
||||
+ cp = parser->buffer + sizeof ("search") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
- strncpy (statp->defdname, cp, sizeof (statp->defdname) - 1);
|
||||
- statp->defdname[sizeof (statp->defdname) - 1] = '\0';
|
||||
- if ((cp = strchr (statp->defdname, '\n')) != NULL)
|
||||
- *cp = '\0';
|
||||
+
|
||||
+ {
|
||||
+ char *p = strchr (cp, '\n');
|
||||
+ if (p != NULL)
|
||||
+ *p = '\0';
|
||||
+ }
|
||||
+ cp = __strdup (cp);
|
||||
+ if (cp == NULL)
|
||||
+ return false;
|
||||
+ free (parser->search_list_store);
|
||||
+ parser->search_list_store = cp;
|
||||
+
|
||||
+ /* The string is truncated below. */
|
||||
+ search_list_clear (&parser->search_list);
|
||||
+ search_list_add (&parser->search_list, cp);
|
||||
+
|
||||
/* Set search list to be blank-separated strings on rest
|
||||
of line. */
|
||||
- cp = statp->defdname;
|
||||
- pp = statp->dnsrch;
|
||||
- *pp++ = cp;
|
||||
- for (int n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++)
|
||||
+ for (bool in_name = true; *cp != '\0'; cp++)
|
||||
{
|
||||
if (*cp == ' ' || *cp == '\t')
|
||||
{
|
||||
- *cp = 0;
|
||||
- n = 1;
|
||||
+ *cp = '\0';
|
||||
+ in_name = false;
|
||||
}
|
||||
- else if (n)
|
||||
+ else if (!in_name)
|
||||
{
|
||||
- *pp++ = cp;
|
||||
- n = 0;
|
||||
+ search_list_add (&parser->search_list, cp);
|
||||
+ in_name = true;
|
||||
}
|
||||
}
|
||||
- /* Null terminate last domain if there are excess. */
|
||||
- while (*cp != '\0' && *cp != ' ' && *cp != '\t')
|
||||
- cp++;
|
||||
- *cp = '\0';
|
||||
- *pp++ = 0;
|
||||
- havesearch = true;
|
||||
continue;
|
||||
}
|
||||
/* Read nameservers to query. */
|
||||
- if (MATCH (*buffer, "nameserver") && nserv < MAXNS)
|
||||
+ if (MATCH (parser->buffer, "nameserver") && nserv < MAXNS)
|
||||
{
|
||||
struct in_addr a;
|
||||
|
||||
- cp = *buffer + sizeof ("nameserver") - 1;
|
||||
+ cp = parser->buffer + sizeof ("nameserver") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
|
||||
@@ -335,11 +402,11 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
- if (MATCH (*buffer, "sortlist"))
|
||||
+ if (MATCH (parser->buffer, "sortlist"))
|
||||
{
|
||||
struct in_addr a;
|
||||
|
||||
- cp = *buffer + sizeof ("sortlist") - 1;
|
||||
+ cp = parser->buffer + sizeof ("sortlist") - 1;
|
||||
while (nsort < MAXRESOLVSORT)
|
||||
{
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
@@ -379,9 +446,9 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
- if (MATCH (*buffer, "options"))
|
||||
+ if (MATCH (parser->buffer, "options"))
|
||||
{
|
||||
- res_setoptions (statp, *buffer + sizeof ("options") - 1);
|
||||
+ res_setoptions (statp, parser->buffer + sizeof ("options") - 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -399,25 +466,29 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
statp->nsaddr.sin_port = htons (NAMESERVER_PORT);
|
||||
statp->nscount = 1;
|
||||
}
|
||||
- if (statp->defdname[0] == 0)
|
||||
- {
|
||||
- char buf[sizeof (statp->defdname)];
|
||||
- if (__gethostname (buf, sizeof (statp->defdname) - 1) == 0
|
||||
- && (cp = strchr (buf, '.')) != NULL)
|
||||
- strcpy (statp->defdname, cp + 1);
|
||||
- }
|
||||
|
||||
- /* Find components of local domain that might be searched. */
|
||||
- if (!havesearch)
|
||||
+ if (search_list_size (&parser->search_list) == 0)
|
||||
{
|
||||
- pp = statp->dnsrch;
|
||||
- *pp++ = statp->defdname;
|
||||
- *pp = NULL;
|
||||
-
|
||||
+ char *domain;
|
||||
+ if (!domain_from_hostname (&domain))
|
||||
+ return false;
|
||||
+ if (domain != NULL)
|
||||
+ {
|
||||
+ free (parser->search_list_store);
|
||||
+ parser->search_list_store = domain;
|
||||
+ search_list_add (&parser->search_list, domain);
|
||||
+ }
|
||||
}
|
||||
|
||||
if ((cp = getenv ("RES_OPTIONS")) != NULL)
|
||||
res_setoptions (statp, cp);
|
||||
+
|
||||
+ if (search_list_has_failed (&parser->search_list))
|
||||
+ {
|
||||
+ __set_errno (ENOMEM);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
statp->options |= RES_INIT;
|
||||
return true;
|
||||
}
|
||||
@@ -453,13 +524,17 @@ __res_vinit (res_state statp, int preinit)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- char *buffer = NULL;
|
||||
- bool ok = res_vinit_1 (statp, preinit, fp, &buffer);
|
||||
- free (buffer);
|
||||
+ struct resolv_conf_parser parser;
|
||||
+ resolv_conf_parser_init (&parser);
|
||||
+ bool ok = res_vinit_1 (statp, preinit, fp, &parser);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
- struct resolv_conf init = { 0 }; /* No data yet. */
|
||||
+ struct resolv_conf init =
|
||||
+ {
|
||||
+ .search_list = search_list_begin (&parser.search_list),
|
||||
+ .search_list_size = search_list_size (&parser.search_list),
|
||||
+ };
|
||||
struct resolv_conf *conf = __resolv_conf_allocate (&init);
|
||||
if (conf == NULL)
|
||||
ok = false;
|
||||
@@ -469,6 +544,7 @@ __res_vinit (res_state statp, int preinit)
|
||||
__resolv_conf_put (conf);
|
||||
}
|
||||
}
|
||||
+ resolv_conf_parser_free (&parser);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||||
index 33249e36f51bcf9a..ebbe5a6a4ed86abe 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -326,7 +326,7 @@ __res_context_search (struct resolv_context *ctx,
|
||||
int *nanswerp2, int *resplen2, int *answerp2_malloced)
|
||||
{
|
||||
struct __res_state *statp = ctx->resp;
|
||||
- const char *cp, * const *domain;
|
||||
+ const char *cp;
|
||||
HEADER *hp = (HEADER *) answer;
|
||||
char tmp[NS_MAXDNAME];
|
||||
u_int dots;
|
||||
@@ -392,10 +392,11 @@ __res_context_search (struct resolv_context *ctx,
|
||||
(dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
|
||||
int done = 0;
|
||||
|
||||
- for (domain = (const char * const *)statp->dnsrch;
|
||||
- *domain && !done;
|
||||
- domain++) {
|
||||
- const char *dname = domain[0];
|
||||
+ for (size_t domain_index = 0; !done; ++domain_index) {
|
||||
+ const char *dname = __resolv_context_search_list
|
||||
+ (ctx, domain_index);
|
||||
+ if (dname == NULL)
|
||||
+ break;
|
||||
searched = 1;
|
||||
|
||||
/* __res_context_querydoman concatenates name
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index cabe69cf1ba3f4d5..76d55fc32c8f0662 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -133,6 +133,34 @@ static bool
|
||||
resolv_conf_matches (const struct __res_state *resp,
|
||||
const struct resolv_conf *conf)
|
||||
{
|
||||
+ /* Check that the search list in *RESP has not been modified by the
|
||||
+ application. */
|
||||
+ {
|
||||
+ if (!(resp->dnsrch[0] == resp->defdname
|
||||
+ && resp->dnsrch[MAXDNSRCH] == NULL))
|
||||
+ return false;
|
||||
+ size_t search_list_size = 0;
|
||||
+ for (size_t i = 0; i < conf->search_list_size; ++i)
|
||||
+ {
|
||||
+ if (resp->dnsrch[i] != NULL)
|
||||
+ {
|
||||
+ search_list_size += strlen (resp->dnsrch[i]) + 1;
|
||||
+ if (strcmp (resp->dnsrch[i], conf->search_list[i]) != 0)
|
||||
+ return false;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* resp->dnsrch is truncated if the number of elements
|
||||
+ exceeds MAXDNSRCH, or if the combined storage space for
|
||||
+ the search list exceeds what can be stored in
|
||||
+ resp->defdname. */
|
||||
+ if (i == MAXDNSRCH || search_list_size > sizeof (resp->dnsrch))
|
||||
+ break;
|
||||
+ /* Otherwise, a mismatch indicates a match failure. */
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -162,10 +190,17 @@ __resolv_conf_put (struct resolv_conf *conf)
|
||||
struct resolv_conf *
|
||||
__resolv_conf_allocate (const struct resolv_conf *init)
|
||||
{
|
||||
+ /* Space needed by the strings. */
|
||||
+ size_t string_space = 0;
|
||||
+ for (size_t i = 0; i < init->search_list_size; ++i)
|
||||
+ string_space += strlen (init->search_list[i]) + 1;
|
||||
+
|
||||
/* Allocate the buffer. */
|
||||
void *ptr;
|
||||
struct alloc_buffer buffer = alloc_buffer_allocate
|
||||
- (sizeof (struct resolv_conf),
|
||||
+ (sizeof (struct resolv_conf)
|
||||
+ + init->search_list_size * sizeof (init->search_list[0])
|
||||
+ + string_space,
|
||||
&ptr);
|
||||
struct resolv_conf *conf
|
||||
= alloc_buffer_alloc (&buffer, struct resolv_conf);
|
||||
@@ -178,6 +213,16 @@ __resolv_conf_allocate (const struct resolv_conf *init)
|
||||
conf->__refcount = 1;
|
||||
conf->initstamp = __res_initstamp;
|
||||
|
||||
+ /* Allocate and fill the search list array. */
|
||||
+ {
|
||||
+ conf->search_list_size = init->search_list_size;
|
||||
+ const char **array = alloc_buffer_alloc_array
|
||||
+ (&buffer, const char *, init->search_list_size);
|
||||
+ conf->search_list = array;
|
||||
+ for (size_t i = 0; i < init->search_list_size; ++i)
|
||||
+ array[i] = alloc_buffer_copy_string (&buffer, init->search_list[i]);
|
||||
+ }
|
||||
+
|
||||
assert (!alloc_buffer_has_failed (&buffer));
|
||||
return conf;
|
||||
}
|
||||
@@ -186,6 +231,24 @@ __resolv_conf_allocate (const struct resolv_conf *init)
|
||||
static __attribute__ ((nonnull (1, 2), warn_unused_result)) bool
|
||||
update_from_conf (struct __res_state *resp, const struct resolv_conf *conf)
|
||||
{
|
||||
+ /* Fill in the prefix of the search list. It is truncated either at
|
||||
+ MAXDNSRCH, or if reps->defdname has insufficient space. */
|
||||
+ {
|
||||
+ struct alloc_buffer buffer
|
||||
+ = alloc_buffer_create (resp->defdname, sizeof (resp->defdname));
|
||||
+ size_t size = conf->search_list_size;
|
||||
+ size_t i;
|
||||
+ for (i = 0; i < size && i < MAXDNSRCH; ++i)
|
||||
+ {
|
||||
+ resp->dnsrch[i] = alloc_buffer_copy_string
|
||||
+ (&buffer, conf->search_list[i]);
|
||||
+ if (resp->dnsrch[i] == NULL)
|
||||
+ /* No more space in resp->defdname. Truncate. */
|
||||
+ break;
|
||||
+ }
|
||||
+ resp->dnsrch[i] = NULL;
|
||||
+ }
|
||||
+
|
||||
/* The overlapping parts of both configurations should agree after
|
||||
initialization. */
|
||||
assert (resolv_conf_matches (resp, conf));
|
||||
diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h
|
||||
index 48f92d6d5753aef1..80a0b93f94588e89 100644
|
||||
--- a/resolv/resolv_conf.h
|
||||
+++ b/resolv/resolv_conf.h
|
||||
@@ -35,6 +35,10 @@ struct resolv_conf
|
||||
/* Reference counter. The object is deallocated once it reaches
|
||||
zero. For internal use within resolv_conf only. */
|
||||
size_t __refcount;
|
||||
+
|
||||
+ /* The domain names forming the search list. */
|
||||
+ const char *const *search_list;
|
||||
+ size_t search_list_size;
|
||||
};
|
||||
|
||||
/* The functions below are for use by the res_init resolv.conf parser
|
||||
diff --git a/resolv/resolv_context.h b/resolv/resolv_context.h
|
||||
index ff9ef2c7fe6101f3..0f4d47d26dd513f4 100644
|
||||
--- a/resolv/resolv_context.h
|
||||
+++ b/resolv/resolv_context.h
|
||||
@@ -93,6 +93,25 @@ struct resolv_context *__resolv_context_get_override (struct __res_state *)
|
||||
__attribute__ ((nonnull (1), warn_unused_result));
|
||||
libc_hidden_proto (__resolv_context_get_override)
|
||||
|
||||
+/* Return the search path entry at INDEX, or NULL if there are fewer
|
||||
+ than INDEX entries. */
|
||||
+static __attribute__ ((nonnull (1), unused)) const char *
|
||||
+__resolv_context_search_list (const struct resolv_context *ctx, size_t index)
|
||||
+{
|
||||
+ if (ctx->conf != NULL)
|
||||
+ {
|
||||
+ if (index < ctx->conf->search_list_size)
|
||||
+ return ctx->conf->search_list[index];
|
||||
+ else
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ /* Fallback. ctx->resp->dnsrch is a NULL-terminated array. */
|
||||
+ for (size_t i = 0; ctx->resp->dnsrch[i] != NULL && i < MAXDNSRCH; ++i)
|
||||
+ if (i == index)
|
||||
+ return ctx->resp->dnsrch[i];
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/* Called during thread shutdown to free the associated resolver
|
||||
context (mostly in response to cancellation, otherwise the
|
||||
__resolv_context_get/__resolv_context_put pairing will already have
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index ce206f52c4c27c32..cea14569b89cb51f 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <gnu/lib-names.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */
|
||||
+#include <resolv/resolv_context.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
@@ -116,6 +117,11 @@ print_option_flag (FILE *fp, int *options, int flag, const char *name)
|
||||
static void
|
||||
print_resp (FILE *fp, res_state resp)
|
||||
{
|
||||
+ struct resolv_context *ctx = __resolv_context_get_override (resp);
|
||||
+ TEST_VERIFY_EXIT (ctx != NULL);
|
||||
+ if (ctx->conf == NULL)
|
||||
+ fprintf (fp, "; extended resolver state missing\n");
|
||||
+
|
||||
/* The options directive. */
|
||||
{
|
||||
/* RES_INIT is used internally for tracking initialization. */
|
||||
@@ -165,6 +171,19 @@ print_resp (FILE *fp, res_state resp)
|
||||
else if (resp->defdname[0] != '\0')
|
||||
fprintf (fp, "domain %s\n", resp->defdname);
|
||||
|
||||
+ /* The extended search path. */
|
||||
+ {
|
||||
+ size_t i = 0;
|
||||
+ while (true)
|
||||
+ {
|
||||
+ const char *name = __resolv_context_search_list (ctx, i);
|
||||
+ if (name == NULL)
|
||||
+ break;
|
||||
+ fprintf (fp, "; search[%zu]: %s\n", i, name);
|
||||
+ ++i;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* The sortlist directive. */
|
||||
if (resp->nsort > 0)
|
||||
{
|
||||
@@ -224,6 +243,8 @@ print_resp (FILE *fp, res_state resp)
|
||||
}
|
||||
|
||||
TEST_VERIFY (!ferror (fp));
|
||||
+
|
||||
+ __resolv_context_put (ctx);
|
||||
}
|
||||
|
||||
/* Parameters of one test case. */
|
||||
@@ -368,11 +389,13 @@ struct test_case test_cases[] =
|
||||
{.name = "empty file",
|
||||
.conf = "",
|
||||
.expected = "search example.com\n"
|
||||
+ "; search[0]: example.com\n"
|
||||
"nameserver 127.0.0.1\n"
|
||||
},
|
||||
{.name = "empty file with LOCALDOMAIN",
|
||||
.conf = "",
|
||||
.expected = "search example.net\n"
|
||||
+ "; search[0]: example.net\n"
|
||||
"nameserver 127.0.0.1\n",
|
||||
.localdomain = "example.net",
|
||||
},
|
||||
@@ -380,6 +403,7 @@ struct test_case test_cases[] =
|
||||
.conf = "",
|
||||
.expected = "options attempts:5 edns0\n"
|
||||
"search example.com\n"
|
||||
+ "; search[0]: example.com\n"
|
||||
"nameserver 127.0.0.1\n",
|
||||
.res_options = "edns0 attempts:5",
|
||||
},
|
||||
@@ -387,6 +411,7 @@ struct test_case test_cases[] =
|
||||
.conf = "",
|
||||
.expected = "options attempts:5 edns0\n"
|
||||
"search example.org\n"
|
||||
+ "; search[0]: example.org\n"
|
||||
"nameserver 127.0.0.1\n",
|
||||
.localdomain = "example.org",
|
||||
.res_options = "edns0 attempts:5",
|
||||
@@ -396,6 +421,8 @@ struct test_case test_cases[] =
|
||||
"search corp.example.com example.com\n"
|
||||
"nameserver 192.0.2.1\n",
|
||||
.expected = "search corp.example.com example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
},
|
||||
{.name = "whitespace",
|
||||
@@ -403,16 +430,46 @@ struct test_case test_cases[] =
|
||||
" (trailing whitespace,\n"
|
||||
"# missing newline at end of file).\n"
|
||||
"\n"
|
||||
- "domain example.net\n"
|
||||
";search commented out\n"
|
||||
- "search corp.example.com\texample.com\n"
|
||||
+ "search corp.example.com\texample.com \n"
|
||||
"#nameserver 192.0.2.3\n"
|
||||
"nameserver 192.0.2.1 \n"
|
||||
"nameserver 192.0.2.2", /* No \n at end of file. */
|
||||
.expected = "search corp.example.com example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
"nameserver 192.0.2.2\n"
|
||||
},
|
||||
+ {.name = "domain",
|
||||
+ .conf = "domain example.net\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "search example.net\n"
|
||||
+ "; search[0]: example.net\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ },
|
||||
+ {.name = "domain space",
|
||||
+ .conf = "domain example.net \n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "search example.net\n"
|
||||
+ "; search[0]: example.net\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ },
|
||||
+ {.name = "domain tab",
|
||||
+ .conf = "domain example.net\t\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ .expected = "search example.net\n"
|
||||
+ "; search[0]: example.net\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ },
|
||||
+ {.name = "domain override",
|
||||
+ .conf = "search example.com example.org\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ "domain example.net", /* No \n at end of file. */
|
||||
+ .expected = "search example.net\n"
|
||||
+ "; search[0]: example.net\n"
|
||||
+ "nameserver 192.0.2.1\n"
|
||||
+ },
|
||||
{.name = "option values, multiple servers",
|
||||
.conf = "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n"
|
||||
"domain example.net\n"
|
||||
@@ -423,6 +480,8 @@ struct test_case test_cases[] =
|
||||
"nameserver 192.0.2.2\n",
|
||||
.expected = "options ndots:3 timeout:19 attempts:5 inet6 edns0\n"
|
||||
"search corp.example.com example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
"nameserver ::1\n"
|
||||
"nameserver 192.0.2.2\n"
|
||||
@@ -432,6 +491,7 @@ struct test_case test_cases[] =
|
||||
"search example.com\n",
|
||||
.expected = "options ndots:15 timeout:30 attempts:5 use-vc\n"
|
||||
"search example.com\n"
|
||||
+ "; search[0]: example.com\n"
|
||||
"nameserver 127.0.0.1\n"
|
||||
},
|
||||
{.name = "repeated directives",
|
||||
@@ -443,6 +503,7 @@ struct test_case test_cases[] =
|
||||
"search\n",
|
||||
.expected = "options ndots:2 use-vc edns0\n"
|
||||
"search example.org\n"
|
||||
+ "; search[0]: example.org\n"
|
||||
"nameserver 127.0.0.1\n"
|
||||
},
|
||||
{.name = "many name servers, sortlist",
|
||||
@@ -459,6 +520,10 @@ struct test_case test_cases[] =
|
||||
"nameserver 192.0.2.8\n",
|
||||
.expected = "options single-request\n"
|
||||
"search example.org example.com example.net corp.example.com\n"
|
||||
+ "; search[0]: example.org\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
+ "; search[2]: example.net\n"
|
||||
+ "; search[3]: corp.example.com\n"
|
||||
"sortlist 192.0.2.0/255.255.255.0\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
"nameserver 192.0.2.2\n"
|
||||
@@ -480,6 +545,11 @@ struct test_case test_cases[] =
|
||||
.expected = "options single-request\n"
|
||||
"search example.org example.com example.net corp.example.com"
|
||||
" legacy.example.com\n"
|
||||
+ "; search[0]: example.org\n"
|
||||
+ "; search[1]: example.com\n"
|
||||
+ "; search[2]: example.net\n"
|
||||
+ "; search[3]: corp.example.com\n"
|
||||
+ "; search[4]: legacy.example.com\n"
|
||||
"sortlist 192.0.2.0/255.255.255.0\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
"nameserver 2001:db8::2\n"
|
||||
@@ -490,6 +560,7 @@ struct test_case test_cases[] =
|
||||
"nameserver 192.0.2.2:5353\n"
|
||||
"nameserver 192.0.2.3 5353\n",
|
||||
.expected = "search example.com\n"
|
||||
+ "; search[0]: example.com\n"
|
||||
"nameserver 192.0.2.1\n"
|
||||
"nameserver 192.0.2.3\n"
|
||||
},
|
||||
@@ -498,9 +569,42 @@ struct test_case test_cases[] =
|
||||
"nameserver 192.0.2.1\n",
|
||||
.expected = "options ndots:3 timeout:7 attempts:5 use-vc edns0\n"
|
||||
"search example.com\n"
|
||||
+ "; search[0]: example.com\n"
|
||||
"nameserver 192.0.2.1\n",
|
||||
.res_options = "attempts:5 ndots:3 edns0 ",
|
||||
},
|
||||
+ {.name = "many search list entries (bug 19569)",
|
||||
+ .conf = "nameserver 192.0.2.1\n"
|
||||
+ "search corp.example.com support.example.com"
|
||||
+ " community.example.org wan.example.net vpn.example.net"
|
||||
+ " example.com example.org example.net\n",
|
||||
+ .expected = "search corp.example.com support.example.com"
|
||||
+ " community.example.org wan.example.net vpn.example.net example.com\n"
|
||||
+ "; search[0]: corp.example.com\n"
|
||||
+ "; search[1]: support.example.com\n"
|
||||
+ "; search[2]: community.example.org\n"
|
||||
+ "; search[3]: wan.example.net\n"
|
||||
+ "; search[4]: vpn.example.net\n"
|
||||
+ "; search[5]: example.com\n"
|
||||
+ "; search[6]: example.org\n"
|
||||
+ "; search[7]: example.net\n"
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ },
|
||||
+ {.name = "very long search list entries (bug 21475)",
|
||||
+ .conf = "nameserver 192.0.2.1\n"
|
||||
+ "search example.com "
|
||||
+#define H63 "this-host-name-is-longer-than-yours-yes-I-really-really-mean-it"
|
||||
+#define D63 "this-domain-name-is-as-long-as-the-previous-name--63-characters"
|
||||
+ " " H63 "." D63 ".example.org"
|
||||
+ " " H63 "." D63 ".example.net\n",
|
||||
+ .expected = "search example.com " H63 "." D63 ".example.org\n"
|
||||
+ "; search[0]: example.com\n"
|
||||
+ "; search[1]: " H63 "." D63 ".example.org\n"
|
||||
+ "; search[2]: " H63 "." D63 ".example.net\n"
|
||||
+#undef H63
|
||||
+#undef D63
|
||||
+ "nameserver 192.0.2.1\n",
|
||||
+ },
|
||||
{ NULL }
|
||||
};
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
commit 2f83a7294d0d0904d72839843a80531769525d59
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Apr 19 07:45:04 2017 +0200
|
||||
|
||||
Create more sockets with SOCK_CLOEXEC [BZ #15722]
|
||||
|
||||
diff --git a/inet/rcmd.c b/inet/rcmd.c
|
||||
index 8613d96764b08cc8..f6c9ec54acfc800f 100644
|
||||
--- a/inet/rcmd.c
|
||||
+++ b/inet/rcmd.c
|
||||
@@ -383,6 +383,7 @@ rresvport_af (int *alport, sa_family_t family)
|
||||
__set_errno (EAFNOSUPPORT);
|
||||
return -1;
|
||||
}
|
||||
+ /* NB: No SOCK_CLOXEC for backwards compatibility. */
|
||||
s = __socket(family, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
return -1;
|
||||
diff --git a/inet/rexec.c b/inet/rexec.c
|
||||
index 24ac4b11b6d745aa..96ebf3d59a5d97ac 100644
|
||||
--- a/inet/rexec.c
|
||||
+++ b/inet/rexec.c
|
||||
@@ -86,6 +86,7 @@ rexec_af (char **ahost, int rport, const char *name, const char *pass,
|
||||
}
|
||||
ruserpass(res0->ai_canonname, &name, &pass);
|
||||
retry:
|
||||
+ /* NB: No SOCK_CLOXEC for backwards compatibility. */
|
||||
s = __socket(res0->ai_family, res0->ai_socktype, 0);
|
||||
if (s < 0) {
|
||||
perror("rexec: socket");
|
||||
diff --git a/nis/nis_findserv.c b/nis/nis_findserv.c
|
||||
index 77f3c7c3cea14fbc..8e01164e3db9252e 100644
|
||||
--- a/nis/nis_findserv.c
|
||||
+++ b/nis/nis_findserv.c
|
||||
@@ -142,7 +142,7 @@ __nis_findfastest_with_timeout (dir_binding *bind,
|
||||
}
|
||||
|
||||
/* Create RPC handle */
|
||||
- sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
+ sock = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
|
||||
clnt = clntudp_create (&saved_sin, NIS_PROG, NIS_VERSION, *timeout, &sock);
|
||||
if (clnt == NULL)
|
||||
{
|
||||
diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
|
||||
index d0d116d308b31b40..8fc06e9abdc084f6 100644
|
||||
--- a/resolv/res_hconf.c
|
||||
+++ b/resolv/res_hconf.c
|
||||
@@ -388,7 +388,7 @@ _res_hconf_reorder_addrs (struct hostent *hp)
|
||||
/* Initialize interface table. */
|
||||
|
||||
/* The SIOCGIFNETMASK ioctl will only work on an AF_INET socket. */
|
||||
- sd = __socket (AF_INET, SOCK_DGRAM, 0);
|
||||
+ sd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (sd < 0)
|
||||
return;
|
||||
|
||||
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||
index 98968d6239d0c8f7..440da90a0b381b84 100644
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -692,7 +692,8 @@ send_vc(res_state statp,
|
||||
if (statp->_vcsock >= 0)
|
||||
__res_iclose(statp, false);
|
||||
|
||||
- statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
|
||||
+ statp->_vcsock = socket
|
||||
+ (nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (statp->_vcsock < 0) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "socket(vc)", errno);
|
||||
@@ -902,14 +903,16 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
|
||||
/* only try IPv6 if IPv6 NS and if not failed before */
|
||||
if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
|
||||
- EXT(statp).nssocks[ns]
|
||||
- = socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0);
|
||||
+ EXT(statp).nssocks[ns] = socket
|
||||
+ (PF_INET6,
|
||||
+ SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
if (EXT(statp).nssocks[ns] < 0)
|
||||
statp->ipv6_unavail = errno == EAFNOSUPPORT;
|
||||
slen = sizeof (struct sockaddr_in6);
|
||||
} else if (nsap->sa_family == AF_INET) {
|
||||
- EXT(statp).nssocks[ns]
|
||||
- = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0);
|
||||
+ EXT(statp).nssocks[ns] = socket
|
||||
+ (PF_INET,
|
||||
+ SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
slen = sizeof (struct sockaddr_in);
|
||||
}
|
||||
if (EXT(statp).nssocks[ns] < 0) {
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 43eb31365ed10059..1ea2b2218d263b28 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -2472,7 +2472,7 @@ getaddrinfo (const char *name, const char *service,
|
||||
close_retry:
|
||||
close_not_cancel_no_status (fd);
|
||||
af = q->ai_family;
|
||||
- fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
|
||||
+ fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP);
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/sysdeps/unix/sysv/linux/check_native.c b/sysdeps/unix/sysv/linux/check_native.c
|
||||
index 4a1646089ffb7f1e..7e5a7c9be30c05e7 100644
|
||||
--- a/sysdeps/unix/sysv/linux/check_native.c
|
||||
+++ b/sysdeps/unix/sysv/linux/check_native.c
|
||||
@@ -41,7 +41,7 @@ void
|
||||
__check_native (uint32_t a1_index, int *a1_native,
|
||||
uint32_t a2_index, int *a2_native)
|
||||
{
|
||||
- int fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
+ int fd = __socket (PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||
|
||||
struct sockaddr_nl nladdr;
|
||||
memset (&nladdr, '\0', sizeof (nladdr));
|
||||
diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c
|
||||
index cff12c2ac4517741..3bc99028639c7149 100644
|
||||
--- a/sysdeps/unix/sysv/linux/ifaddrs.c
|
||||
+++ b/sysdeps/unix/sysv/linux/ifaddrs.c
|
||||
@@ -255,7 +255,7 @@ __netlink_open (struct netlink_handle *h)
|
||||
{
|
||||
struct sockaddr_nl nladdr;
|
||||
|
||||
- h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
+ h->fd = __socket (PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||
if (h->fd < 0)
|
||||
goto out;
|
||||
|
|
@ -0,0 +1,637 @@
|
|||
commit f30a54b21b83f254533c59ca72ad17af5249c6be
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jul 3 20:31:23 2017 +0200
|
||||
|
||||
resolv: Introduce struct resolv_conf with extended resolver state
|
||||
|
||||
This change provides additional resolver configuration state which
|
||||
is not exposed through the _res ABI. It reuses the existing
|
||||
initstamp field in the supposedly-private part of _res. Some effort
|
||||
is undertaken to avoid memory safety issues introduced by applications
|
||||
which directly patch the _res object.
|
||||
|
||||
With this commit, only the initstamp field is moved into struct
|
||||
resolv_conf. Additional members will be added later, eventually
|
||||
migrating the entire resolver configuration.
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 7f5e07d618297f60..ef5ed2966e4d6c51 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -29,7 +29,7 @@ headers := resolv.h \
|
||||
|
||||
routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
|
||||
res_hconf res_libc res-state res_randomid res-close \
|
||||
- resolv_context
|
||||
+ resolv_context resolv_conf
|
||||
|
||||
tests = tst-aton tst-leaks tst-inet_ntop
|
||||
xtests = tst-leaks2
|
||||
diff --git a/resolv/res-close.c b/resolv/res-close.c
|
||||
index 97da73c99cfd0e12..21f038c2c77f7375 100644
|
||||
--- a/resolv/res-close.c
|
||||
+++ b/resolv/res-close.c
|
||||
@@ -84,6 +84,7 @@
|
||||
|
||||
#include <resolv-internal.h>
|
||||
#include <resolv_context.h>
|
||||
+#include <resolv_conf.h>
|
||||
#include <not-cancel.h>
|
||||
|
||||
/* Close all open sockets. If FREE_ADDR is true, deallocate any
|
||||
@@ -111,6 +112,8 @@ __res_iclose (res_state statp, bool free_addr)
|
||||
statp->_u._ext.nsaddrs[ns] = NULL;
|
||||
}
|
||||
}
|
||||
+ if (free_addr)
|
||||
+ __resolv_conf_detach (statp);
|
||||
}
|
||||
libc_hidden_def (__res_iclose)
|
||||
|
||||
diff --git a/resolv/res_init.c b/resolv/res_init.c
|
||||
index 5d8b2c994d8e6f04..659d3ea81f973257 100644
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -102,6 +102,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <inet/net-internal.h>
|
||||
#include <errno.h>
|
||||
+#include <resolv_conf.h>
|
||||
|
||||
static void res_setoptions (res_state, const char *);
|
||||
static uint32_t net_mask (struct in_addr);
|
||||
@@ -137,7 +138,6 @@ res_vinit_1 (res_state statp, bool preinit, FILE *fp, char **buffer)
|
||||
bool havesearch = false;
|
||||
int nsort = 0;
|
||||
char *net;
|
||||
- statp->_u._ext.initstamp = __res_initstamp;
|
||||
|
||||
if (!preinit)
|
||||
{
|
||||
@@ -457,6 +457,19 @@ __res_vinit (res_state statp, int preinit)
|
||||
bool ok = res_vinit_1 (statp, preinit, fp, &buffer);
|
||||
free (buffer);
|
||||
|
||||
+ if (ok)
|
||||
+ {
|
||||
+ struct resolv_conf init = { 0 }; /* No data yet. */
|
||||
+ struct resolv_conf *conf = __resolv_conf_allocate (&init);
|
||||
+ if (conf == NULL)
|
||||
+ ok = false;
|
||||
+ else
|
||||
+ {
|
||||
+ ok = __resolv_conf_attach (statp, conf);
|
||||
+ __resolv_conf_put (conf);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (!ok)
|
||||
{
|
||||
/* Deallocate the name server addresses which have been
|
||||
diff --git a/resolv/resolv.h b/resolv/resolv.h
|
||||
index 9fef8e9f248c84e6..b83232cca8e8f0c3 100644
|
||||
--- a/resolv/resolv.h
|
||||
+++ b/resolv/resolv.h
|
||||
@@ -122,10 +122,10 @@ struct __res_state {
|
||||
uint16_t nsinit;
|
||||
struct sockaddr_in6 *nsaddrs[MAXNS];
|
||||
#ifdef _LIBC
|
||||
- unsigned long long int initstamp
|
||||
+ unsigned long long int __glibc_extension_index
|
||||
__attribute__((packed));
|
||||
#else
|
||||
- unsigned int _initstamp[2];
|
||||
+ unsigned int __glibc_reserved[2];
|
||||
#endif
|
||||
} _ext;
|
||||
} _u;
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..cabe69cf1ba3f4d5
|
||||
--- /dev/null
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -0,0 +1,322 @@
|
||||
+/* Extended resolver state separate from struct __res_state.
|
||||
+ Copyright (C) 2017 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 <resolv_conf.h>
|
||||
+
|
||||
+#include <alloc_buffer.h>
|
||||
+#include <assert.h>
|
||||
+#include <libc-lock.h>
|
||||
+#include <resolv-internal.h>
|
||||
+
|
||||
+/* _res._u._ext.__glibc_extension_index is used as an index into a
|
||||
+ struct resolv_conf_array object. The intent of this construction
|
||||
+ is to make reasonably sure that even if struct __res_state objects
|
||||
+ are copied around and patched by applications, we can still detect
|
||||
+ accesses to stale extended resolver state. */
|
||||
+#define DYNARRAY_STRUCT resolv_conf_array
|
||||
+#define DYNARRAY_ELEMENT struct resolv_conf *
|
||||
+#define DYNARRAY_PREFIX resolv_conf_array_
|
||||
+#define DYNARRAY_INITIAL_SIZE 0
|
||||
+#include <malloc/dynarray-skeleton.c>
|
||||
+
|
||||
+/* A magic constant for XORing the extension index
|
||||
+ (_res._u._ext.__glibc_extension_index). This makes it less likely
|
||||
+ that a valid index is created by accident. In particular, a zero
|
||||
+ value leads to an invalid index. */
|
||||
+#define INDEX_MAGIC 0x26a8fa5e48af8061ULL
|
||||
+
|
||||
+/* Global resolv.conf-related state. */
|
||||
+struct resolv_conf_global
|
||||
+{
|
||||
+ /* struct __res_state objects contain the extension index
|
||||
+ (_res._u._ext.__glibc_extension_index ^ INDEX_MAGIC), which
|
||||
+ refers to an element of this array. When a struct resolv_conf
|
||||
+ object (extended resolver state) is associated with a struct
|
||||
+ __res_state object (legacy resolver state), its reference count
|
||||
+ is increased and added to this array. Conversely, if the
|
||||
+ extended state is detached from the basic state (during
|
||||
+ reinitialization or deallocation), the index is decremented, and
|
||||
+ the array element is overwritten with NULL. */
|
||||
+ struct resolv_conf_array array;
|
||||
+
|
||||
+};
|
||||
+
|
||||
+/* Lazily allocated storage for struct resolv_conf_global. */
|
||||
+static struct resolv_conf_global *global;
|
||||
+
|
||||
+/* The lock synchronizes access to global and *global. It also
|
||||
+ protects the __refcount member of struct resolv_conf. */
|
||||
+__libc_lock_define_initialized (static, lock);
|
||||
+
|
||||
+/* Ensure that GLOBAL is allocated and lock it. Return NULL if
|
||||
+ memory allocation failes. */
|
||||
+static struct resolv_conf_global *
|
||||
+get_locked_global (void)
|
||||
+{
|
||||
+ __libc_lock_lock (lock);
|
||||
+ /* Use relaxed MO through because of load outside the lock in
|
||||
+ __resolv_conf_detach. */
|
||||
+ struct resolv_conf_global *global_copy = atomic_load_relaxed (&global);
|
||||
+ if (global_copy == NULL)
|
||||
+ {
|
||||
+ global_copy = calloc (1, sizeof (*global));
|
||||
+ if (global_copy == NULL)
|
||||
+ return NULL;
|
||||
+ atomic_store_relaxed (&global, global_copy);
|
||||
+ resolv_conf_array_init (&global_copy->array);
|
||||
+ }
|
||||
+ return global_copy;
|
||||
+}
|
||||
+
|
||||
+/* Relinquish the lock acquired by get_locked_global. */
|
||||
+static void
|
||||
+put_locked_global (struct resolv_conf_global *global_copy)
|
||||
+{
|
||||
+ __libc_lock_unlock (lock);
|
||||
+}
|
||||
+
|
||||
+/* Decrement the reference counter. The caller must acquire the lock
|
||||
+ around the function call. */
|
||||
+static void
|
||||
+conf_decrement (struct resolv_conf *conf)
|
||||
+{
|
||||
+ assert (conf->__refcount > 0);
|
||||
+ if (--conf->__refcount == 0)
|
||||
+ free (conf);
|
||||
+}
|
||||
+
|
||||
+/* Internal implementation of __resolv_conf_get, without validation
|
||||
+ against *RESP. */
|
||||
+static struct resolv_conf *
|
||||
+resolv_conf_get_1 (const struct __res_state *resp)
|
||||
+{
|
||||
+ /* Not initialized, and therefore no assoicated context. */
|
||||
+ if (!(resp->options & RES_INIT))
|
||||
+ return NULL;
|
||||
+
|
||||
+ struct resolv_conf_global *global_copy = get_locked_global ();
|
||||
+ if (global_copy == NULL)
|
||||
+ /* A memory allocation failure here means that no associated
|
||||
+ contexts exists, so returning NULL is correct. */
|
||||
+ return NULL;
|
||||
+ size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC;
|
||||
+ struct resolv_conf *conf;
|
||||
+ if (index < resolv_conf_array_size (&global_copy->array))
|
||||
+ {
|
||||
+ conf = *resolv_conf_array_at (&global_copy->array, index);
|
||||
+ assert (conf->__refcount > 0);
|
||||
+ ++conf->__refcount;
|
||||
+ }
|
||||
+ else
|
||||
+ conf = NULL;
|
||||
+ put_locked_global (global_copy);
|
||||
+ return conf;
|
||||
+}
|
||||
+
|
||||
+/* Check that *RESP and CONF match. Used by __resolv_conf_get. */
|
||||
+static bool
|
||||
+resolv_conf_matches (const struct __res_state *resp,
|
||||
+ const struct resolv_conf *conf)
|
||||
+{
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+struct resolv_conf *
|
||||
+__resolv_conf_get (struct __res_state *resp)
|
||||
+{
|
||||
+ struct resolv_conf *conf = resolv_conf_get_1 (resp);
|
||||
+ if (conf == NULL)
|
||||
+ return NULL;
|
||||
+ if (resolv_conf_matches (resp, conf))
|
||||
+ return conf;
|
||||
+ __resolv_conf_put (conf);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+__resolv_conf_put (struct resolv_conf *conf)
|
||||
+{
|
||||
+ if (conf == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ __libc_lock_lock (lock);
|
||||
+ conf_decrement (conf);
|
||||
+ __libc_lock_unlock (lock);
|
||||
+}
|
||||
+
|
||||
+struct resolv_conf *
|
||||
+__resolv_conf_allocate (const struct resolv_conf *init)
|
||||
+{
|
||||
+ /* Allocate the buffer. */
|
||||
+ void *ptr;
|
||||
+ struct alloc_buffer buffer = alloc_buffer_allocate
|
||||
+ (sizeof (struct resolv_conf),
|
||||
+ &ptr);
|
||||
+ struct resolv_conf *conf
|
||||
+ = alloc_buffer_alloc (&buffer, struct resolv_conf);
|
||||
+ if (conf == NULL)
|
||||
+ /* Memory allocation failure. */
|
||||
+ return NULL;
|
||||
+ assert (conf == ptr);
|
||||
+
|
||||
+ /* Initialize the contents. */
|
||||
+ conf->__refcount = 1;
|
||||
+ conf->initstamp = __res_initstamp;
|
||||
+
|
||||
+ assert (!alloc_buffer_has_failed (&buffer));
|
||||
+ return conf;
|
||||
+}
|
||||
+
|
||||
+/* Update *RESP from the extended state. */
|
||||
+static __attribute__ ((nonnull (1, 2), warn_unused_result)) bool
|
||||
+update_from_conf (struct __res_state *resp, const struct resolv_conf *conf)
|
||||
+{
|
||||
+ /* The overlapping parts of both configurations should agree after
|
||||
+ initialization. */
|
||||
+ assert (resolv_conf_matches (resp, conf));
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* Decrement the configuration object at INDEX and free it if the
|
||||
+ reference counter reaches 0. *GLOBAL_COPY must be locked and
|
||||
+ remains so. */
|
||||
+static void
|
||||
+decrement_at_index (struct resolv_conf_global *global_copy, size_t index)
|
||||
+{
|
||||
+ if (index < resolv_conf_array_size (&global_copy->array))
|
||||
+ {
|
||||
+ /* Index found. Deallocate the struct resolv_conf object once
|
||||
+ the reference counter reaches. Free the array slot. */
|
||||
+ struct resolv_conf **slot
|
||||
+ = resolv_conf_array_at (&global_copy->array, index);
|
||||
+ struct resolv_conf *conf = *slot;
|
||||
+ if (conf != NULL)
|
||||
+ {
|
||||
+ conf_decrement (conf);
|
||||
+ /* Clear the slot even if the reference count is positive.
|
||||
+ Slots are not shared. */
|
||||
+ *slot = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+__resolv_conf_attach (struct __res_state *resp, struct resolv_conf *conf)
|
||||
+{
|
||||
+ assert (conf->__refcount > 0);
|
||||
+
|
||||
+ struct resolv_conf_global *global_copy = get_locked_global ();
|
||||
+ if (global_copy == NULL)
|
||||
+ {
|
||||
+ free (conf);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* Try to find an unused index in the array. */
|
||||
+ size_t index;
|
||||
+ {
|
||||
+ size_t size = resolv_conf_array_size (&global_copy->array);
|
||||
+ bool found = false;
|
||||
+ for (index = 0; index < size; ++index)
|
||||
+ {
|
||||
+ struct resolv_conf **p
|
||||
+ = resolv_conf_array_at (&global_copy->array, index);
|
||||
+ if (*p == NULL)
|
||||
+ {
|
||||
+ *p = conf;
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ /* No usable index found. Increase the array size. */
|
||||
+ resolv_conf_array_add (&global_copy->array, conf);
|
||||
+ if (resolv_conf_array_has_failed (&global_copy->array))
|
||||
+ {
|
||||
+ put_locked_global (global_copy);
|
||||
+ __set_errno (ENOMEM);
|
||||
+ return false;
|
||||
+ }
|
||||
+ /* The new array element was added at the end. */
|
||||
+ index = size;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* We have added a new reference to the object. */
|
||||
+ ++conf->__refcount;
|
||||
+ assert (conf->__refcount > 0);
|
||||
+ put_locked_global (global_copy);
|
||||
+
|
||||
+ if (!update_from_conf (resp, conf))
|
||||
+ {
|
||||
+ /* Drop the reference we acquired. Reacquire the lock. The
|
||||
+ object has already been allocated, so it cannot be NULL this
|
||||
+ time. */
|
||||
+ global_copy = get_locked_global ();
|
||||
+ decrement_at_index (global_copy, index);
|
||||
+ put_locked_global (global_copy);
|
||||
+ return false;
|
||||
+ }
|
||||
+ resp->_u._ext.__glibc_extension_index = index ^ INDEX_MAGIC;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+__resolv_conf_detach (struct __res_state *resp)
|
||||
+{
|
||||
+ if (atomic_load_relaxed (&global) == NULL)
|
||||
+ /* Detach operation after a shutdown, or without any prior
|
||||
+ attachment. We cannot free the data (and there might not be
|
||||
+ anything to free anyway). */
|
||||
+ return;
|
||||
+
|
||||
+ struct resolv_conf_global *global_copy = get_locked_global ();
|
||||
+ size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC;
|
||||
+ decrement_at_index (global_copy, index);
|
||||
+
|
||||
+ /* Clear the index field, so that accidental reuse is less
|
||||
+ likely. */
|
||||
+ resp->_u._ext.__glibc_extension_index = 0;
|
||||
+
|
||||
+ put_locked_global (global_copy);
|
||||
+}
|
||||
+
|
||||
+/* Deallocate the global data. */
|
||||
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
||||
+freeres (void)
|
||||
+{
|
||||
+ /* No locking because this function is supposed to be called when
|
||||
+ the process has turned single-threaded. */
|
||||
+ if (global == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /* Note that this frees only the array itself. The pointed-to
|
||||
+ configuration objects should have been deallocated by res_nclose
|
||||
+ and per-thread cleanup functions. */
|
||||
+ resolv_conf_array_free (&global->array);
|
||||
+
|
||||
+ free (global);
|
||||
+
|
||||
+ /* Stop potential future __resolv_conf_detach calls from accessing
|
||||
+ deallocated memory. */
|
||||
+ global = NULL;
|
||||
+}
|
||||
+text_set_element (__libc_subfreeres, freeres);
|
||||
diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..48f92d6d5753aef1
|
||||
--- /dev/null
|
||||
+++ b/resolv/resolv_conf.h
|
||||
@@ -0,0 +1,69 @@
|
||||
+/* Extended resolver state separate from struct __res_state.
|
||||
+ Copyright (C) 2017 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 RESOLV_STATE_H
|
||||
+#define RESOLV_STATE_H
|
||||
+
|
||||
+#include <stdbool.h>
|
||||
+#include <stddef.h>
|
||||
+
|
||||
+/* Extended resolver state associated with res_state objects. Client
|
||||
+ code can reach this state through a struct resolv_context
|
||||
+ object. */
|
||||
+struct resolv_conf
|
||||
+{
|
||||
+ /* Used to propagate the effect of res_init across threads. This
|
||||
+ member is mutable and prevents sharing of the same struct
|
||||
+ resolv_conf object among multiple struct __res_state objects. */
|
||||
+ unsigned long long int initstamp;
|
||||
+
|
||||
+ /* Reference counter. The object is deallocated once it reaches
|
||||
+ zero. For internal use within resolv_conf only. */
|
||||
+ size_t __refcount;
|
||||
+};
|
||||
+
|
||||
+/* The functions below are for use by the res_init resolv.conf parser
|
||||
+ and the struct resolv_context facility. */
|
||||
+
|
||||
+struct __res_state;
|
||||
+
|
||||
+/* Return the extended resolver state for *RESP, or NULL if it cannot
|
||||
+ be determined. A call to this function must be paired with a call
|
||||
+ to __resolv_conf_put. */
|
||||
+struct resolv_conf *__resolv_conf_get (struct __res_state *) attribute_hidden;
|
||||
+
|
||||
+/* Converse of __resolv_conf_get. */
|
||||
+void __resolv_conf_put (struct resolv_conf *) attribute_hidden;
|
||||
+
|
||||
+/* Allocate a new struct resolv_conf object and copy the
|
||||
+ pre-configured values from *INIT. Return NULL on allocation
|
||||
+ failure. The object must be deallocated using
|
||||
+ __resolv_conf_put. */
|
||||
+struct resolv_conf *__resolv_conf_allocate (const struct resolv_conf *init)
|
||||
+ attribute_hidden __attribute__ ((nonnull (1), warn_unused_result));
|
||||
+
|
||||
+/* Associate an existing extended resolver state with *RESP. Return
|
||||
+ false on allocation failure. In addition, update *RESP with the
|
||||
+ overlapping non-extended resolver state. */
|
||||
+bool __resolv_conf_attach (struct __res_state *, struct resolv_conf *)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
+/* Detach the extended resolver state from *RESP. */
|
||||
+void __resolv_conf_detach (struct __res_state *resp) attribute_hidden;
|
||||
+
|
||||
+#endif /* RESOLV_STATE_H */
|
||||
diff --git a/resolv/resolv_context.c b/resolv/resolv_context.c
|
||||
index 5083a40419bc463c..0ee2184055911d02 100644
|
||||
--- a/resolv/resolv_context.c
|
||||
+++ b/resolv/resolv_context.c
|
||||
@@ -17,9 +17,11 @@
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <resolv_context.h>
|
||||
+#include <resolv_conf.h>
|
||||
#include <resolv-internal.h>
|
||||
|
||||
#include <assert.h>
|
||||
+#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -52,19 +54,37 @@ static __thread struct resolv_context *current attribute_tls_model_ie;
|
||||
/* Initialize *RESP if RES_INIT is not yet set in RESP->options, or if
|
||||
res_init in some other thread requested re-initializing. */
|
||||
static __attribute__ ((warn_unused_result)) bool
|
||||
-maybe_init (struct __res_state *resp, bool preinit)
|
||||
+maybe_init (struct resolv_context *ctx, bool preinit)
|
||||
{
|
||||
+ struct __res_state *resp = ctx->resp;
|
||||
if (resp->options & RES_INIT)
|
||||
{
|
||||
- if (__res_initstamp != resp->_u._ext.initstamp)
|
||||
+ /* If there is no associated resolv_conf object despite the
|
||||
+ initialization, something modified *ctx->resp. Do not
|
||||
+ override those changes. */
|
||||
+ if (ctx->conf != NULL && ctx->conf->initstamp != __res_initstamp)
|
||||
{
|
||||
if (resp->nscount > 0)
|
||||
+ /* This call will detach the extended resolver state. */
|
||||
__res_iclose (resp, true);
|
||||
- return __res_vinit (resp, 1) == 0;
|
||||
+ /* And this call will attach it again. */
|
||||
+ if (__res_vinit (resp, 1) < 0)
|
||||
+ {
|
||||
+ /* The configuration no longer matches after failed
|
||||
+ initialization. */
|
||||
+ __resolv_conf_put (ctx->conf);
|
||||
+ ctx->conf = NULL;
|
||||
+ return false;
|
||||
+ }
|
||||
+ /* Delay the release of the old configuration until this
|
||||
+ point, so that __res_vinit can reuse it if possible. */
|
||||
+ __resolv_conf_put (ctx->conf);
|
||||
+ ctx->conf = __resolv_conf_get (ctx->resp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+ assert (ctx->conf == NULL);
|
||||
if (preinit)
|
||||
{
|
||||
if (!resp->retrans)
|
||||
@@ -75,7 +95,11 @@ maybe_init (struct __res_state *resp, bool preinit)
|
||||
if (!resp->id)
|
||||
resp->id = res_randomid ();
|
||||
}
|
||||
- return __res_vinit (resp, preinit) == 0;
|
||||
+
|
||||
+ if (__res_vinit (resp, preinit) < 0)
|
||||
+ return false;
|
||||
+ ctx->conf = __resolv_conf_get (ctx->resp);
|
||||
+ return true;
|
||||
}
|
||||
|
||||
/* Allocate a new context object and initialize it. The object is put
|
||||
@@ -87,6 +111,7 @@ context_alloc (struct __res_state *resp)
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
ctx->resp = resp;
|
||||
+ ctx->conf = __resolv_conf_get (resp);
|
||||
ctx->__refcount = 1;
|
||||
ctx->__from_res = true;
|
||||
ctx->__next = current;
|
||||
@@ -98,8 +123,11 @@ context_alloc (struct __res_state *resp)
|
||||
static void
|
||||
context_free (struct resolv_context *ctx)
|
||||
{
|
||||
+ int error_code = errno;
|
||||
current = ctx->__next;
|
||||
+ __resolv_conf_put (ctx->conf);
|
||||
free (ctx);
|
||||
+ __set_errno (error_code);
|
||||
}
|
||||
|
||||
/* Reuse the current context object. */
|
||||
@@ -130,7 +158,7 @@ context_get (bool preinit)
|
||||
struct resolv_context *ctx = context_alloc (&_res);
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
- if (!maybe_init (ctx->resp, preinit))
|
||||
+ if (!maybe_init (ctx, preinit))
|
||||
{
|
||||
context_free (ctx);
|
||||
return NULL;
|
||||
diff --git a/resolv/resolv_context.h b/resolv/resolv_context.h
|
||||
index 27c8d56b36104521..ff9ef2c7fe6101f3 100644
|
||||
--- a/resolv/resolv_context.h
|
||||
+++ b/resolv/resolv_context.h
|
||||
@@ -40,15 +40,22 @@
|
||||
#ifndef _RESOLV_CONTEXT_H
|
||||
#define _RESOLV_CONTEXT_H
|
||||
|
||||
+#include <bits/types/res_state.h>
|
||||
+#include <resolv/resolv_conf.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
-#include <bits/types/res_state.h>
|
||||
|
||||
/* Temporary resolver state. */
|
||||
struct resolv_context
|
||||
{
|
||||
struct __res_state *resp; /* Backing resolver state. */
|
||||
|
||||
+ /* Extended resolver state. This is set to NULL if the
|
||||
+ __resolv_context_get functions are unable to locate an associated
|
||||
+ extended state. In this case, the configuration data in *resp
|
||||
+ has to be used; otherwise, the data from *conf should be
|
||||
+ preferred (because it is a superset). */
|
||||
+ struct resolv_conf *conf;
|
||||
|
||||
/* The following fields are for internal use within the
|
||||
resolv_context module. */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,161 @@
|
|||
commit d4165eedf5b85bfda3ea6b251f69838857e44925
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Jul 5 15:38:42 2017 +0200
|
||||
|
||||
support: Add support_chroot_create and support_chroot_free
|
||||
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index 8f395d8ce92773a9..3b7b4129e31eaa22 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -47,46 +47,23 @@
|
||||
res_init. */
|
||||
static const char *const test_hostname = "www.example.com";
|
||||
|
||||
-/* Path to the test root directory. */
|
||||
-static char *path_chroot;
|
||||
-
|
||||
-/* Path to resolv.conf under path_chroot (outside the chroot). */
|
||||
-static char *path_resolv_conf;
|
||||
+struct support_chroot *chroot_env;
|
||||
|
||||
static void
|
||||
prepare (int argc, char **argv)
|
||||
{
|
||||
- path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
|
||||
- if (mkdtemp (path_chroot) == NULL)
|
||||
- FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", path_chroot);
|
||||
- add_temp_file (path_chroot);
|
||||
-
|
||||
- /* Create the /etc directory in the chroot environment. */
|
||||
- char *path_etc = xasprintf ("%s/etc", path_chroot);
|
||||
- xmkdir (path_etc, 0777);
|
||||
- add_temp_file (path_etc);
|
||||
-
|
||||
- /* Create an empty resolv.conf file. */
|
||||
- path_resolv_conf = xasprintf ("%s/resolv.conf", path_etc);
|
||||
- add_temp_file (path_resolv_conf);
|
||||
- support_write_file_string (path_resolv_conf, "");
|
||||
-
|
||||
- free (path_etc);
|
||||
-
|
||||
- /* valgrind needs a temporary directory in the chroot. */
|
||||
- {
|
||||
- char *path_tmp = xasprintf ("%s/tmp", path_chroot);
|
||||
- xmkdir (path_tmp, 0777);
|
||||
- add_temp_file (path_tmp);
|
||||
- free (path_tmp);
|
||||
- }
|
||||
+ chroot_env = support_chroot_create
|
||||
+ ((struct support_chroot_configuration)
|
||||
+ {
|
||||
+ .resolv_conf = "",
|
||||
+ });
|
||||
}
|
||||
|
||||
/* Verify that the chroot environment has been set up. */
|
||||
static void
|
||||
check_chroot_working (void *closure)
|
||||
{
|
||||
- xchroot (path_chroot);
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
FILE *fp = xfopen (_PATH_RESCONF, "r");
|
||||
xfclose (fp);
|
||||
|
||||
@@ -345,7 +322,7 @@ setup_nss_dns_and_chroot (void)
|
||||
/* Load nss_dns outside of the chroot. */
|
||||
if (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) == NULL)
|
||||
FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ());
|
||||
- xchroot (path_chroot);
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
/* Force the use of nss_dns. */
|
||||
__nss_configure_lookup ("hosts", "dns");
|
||||
}
|
||||
@@ -374,13 +351,13 @@ run_res_init (void *closure)
|
||||
switch (ctx->init)
|
||||
{
|
||||
case test_init:
|
||||
- xchroot (path_chroot);
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
TEST_VERIFY (res_init () == 0);
|
||||
print_resp (stdout, &_res);
|
||||
return;
|
||||
|
||||
case test_ninit:
|
||||
- xchroot (path_chroot);
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
res_state resp = xmalloc (sizeof (*resp));
|
||||
memset (resp, 0, sizeof (*resp));
|
||||
TEST_VERIFY (res_ninit (resp) == 0);
|
||||
@@ -390,7 +367,7 @@ run_res_init (void *closure)
|
||||
return;
|
||||
|
||||
case test_mkquery:
|
||||
- xchroot (path_chroot);
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
unsigned char buf[512];
|
||||
TEST_VERIFY (res_mkquery (QUERY, "www.example",
|
||||
C_IN, ns_t_a, NULL, 0,
|
||||
@@ -783,7 +760,7 @@ special_test_callback (void *closure)
|
||||
TEST_VERIFY (test_index < special_tests_count);
|
||||
if (test_verbose > 0)
|
||||
printf ("info: special test %u\n", test_index);
|
||||
- xchroot (path_chroot);
|
||||
+ xchroot (chroot_env->path_chroot);
|
||||
|
||||
switch (test_index)
|
||||
{
|
||||
@@ -1063,7 +1040,8 @@ do_test (void)
|
||||
TEST_VERIFY (test_cases[i].conf != NULL);
|
||||
TEST_VERIFY (test_cases[i].expected != NULL);
|
||||
|
||||
- support_write_file_string (path_resolv_conf, test_cases[i].conf);
|
||||
+ support_write_file_string (chroot_env->path_resolv_conf,
|
||||
+ test_cases[i].conf);
|
||||
|
||||
test_file_contents (&test_cases[i]);
|
||||
|
||||
@@ -1073,24 +1051,24 @@ do_test (void)
|
||||
{
|
||||
if (test_verbose > 0)
|
||||
printf ("info: special test: missing file\n");
|
||||
- TEST_VERIFY (unlink (path_resolv_conf) == 0);
|
||||
+ TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
|
||||
test_file_contents (&test_cases[i]);
|
||||
|
||||
if (test_verbose > 0)
|
||||
printf ("info: special test: dangling symbolic link\n");
|
||||
- TEST_VERIFY (symlink ("does-not-exist", path_resolv_conf) == 0);
|
||||
+ TEST_VERIFY (symlink ("does-not-exist", chroot_env->path_resolv_conf) == 0);
|
||||
test_file_contents (&test_cases[i]);
|
||||
- TEST_VERIFY (unlink (path_resolv_conf) == 0);
|
||||
+ TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
|
||||
|
||||
if (test_verbose > 0)
|
||||
printf ("info: special test: unreadable file\n");
|
||||
- support_write_file_string (path_resolv_conf, "");
|
||||
- TEST_VERIFY (chmod (path_resolv_conf, 0) == 0);
|
||||
+ support_write_file_string (chroot_env->path_resolv_conf, "");
|
||||
+ TEST_VERIFY (chmod (chroot_env->path_resolv_conf, 0) == 0);
|
||||
test_file_contents (&test_cases[i]);
|
||||
|
||||
/* Restore the empty file. */
|
||||
- TEST_VERIFY (unlink (path_resolv_conf) == 0);
|
||||
- support_write_file_string (path_resolv_conf, "");
|
||||
+ TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
|
||||
+ support_write_file_string (chroot_env->path_resolv_conf, "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1106,10 +1084,7 @@ do_test (void)
|
||||
xwaitpid (server, NULL, 0);
|
||||
}
|
||||
|
||||
- free (path_chroot);
|
||||
- path_chroot = NULL;
|
||||
- free (path_resolv_conf);
|
||||
- path_resolv_conf = NULL;
|
||||
+ support_chroot_free (chroot_env);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
commit 965d5c391c86eb3a812ce308411c32754f12a9d2
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Jun 21 12:51:54 2017 +0200
|
||||
|
||||
inet: Add IPv6 getaddrinfo coverage to tst-inet6_scopeid_pton.c
|
||||
|
||||
diff --git a/inet/tst-inet6_scopeid_pton.c b/inet/tst-inet6_scopeid_pton.c
|
||||
index 2178c5b4d2b19544..a1bafa9021c5cf3b 100644
|
||||
--- a/inet/tst-inet6_scopeid_pton.c
|
||||
+++ b/inet/tst-inet6_scopeid_pton.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* Tests for __inet6_scopeid_pton.
|
||||
+/* Tests for __inet6_scopeid_pton and IPv6 scopes in getaddrinfo.
|
||||
Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
@@ -20,8 +20,13 @@
|
||||
#include <inttypes.h>
|
||||
#include <net-internal.h>
|
||||
#include <net/if.h>
|
||||
+#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/test-driver.h>
|
||||
|
||||
/* An interface which is known to the system. */
|
||||
static const char *interface_name;
|
||||
@@ -45,30 +50,103 @@ from_string (const char *address)
|
||||
{
|
||||
struct in6_addr addr;
|
||||
if (inet_pton (AF_INET6, address, &addr) != 1)
|
||||
+ FAIL_EXIT1 ("inet_pton (\"%s\")", address);
|
||||
+ return addr;
|
||||
+}
|
||||
+
|
||||
+/* Invoke getaddrinfo to parse ADDRESS%SCOPE. Return true if
|
||||
+ getaddrinfo was successful. */
|
||||
+static bool
|
||||
+call_gai (int family, const char *address, const char *scope,
|
||||
+ struct sockaddr_in6 *result)
|
||||
+{
|
||||
+ struct addrinfo hints =
|
||||
{
|
||||
- printf ("error: inet_pton (\"%s\") failed\n", address);
|
||||
- exit (1);
|
||||
+ .ai_family = family,
|
||||
+ .ai_flags = AI_NUMERICHOST,
|
||||
+ .ai_socktype = SOCK_DGRAM,
|
||||
+ .ai_protocol = IPPROTO_UDP,
|
||||
+ };
|
||||
+ char *fulladdr = xasprintf ("%s%%%s", address, scope);
|
||||
+ struct addrinfo *ai = NULL;
|
||||
+ int ret = getaddrinfo (fulladdr, NULL, &hints, &ai);
|
||||
+ if (ret == EAI_ADDRFAMILY || ret == EAI_NONAME)
|
||||
+ {
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: getaddrinfo (\"%s\"): %s (%d)\n",
|
||||
+ fulladdr, gai_strerror (ret), ret);
|
||||
+ free (fulladdr);
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (ret != 0)
|
||||
+ FAIL_EXIT1 ("getaddrinfo (\"%s\"): %s (%d)\n",
|
||||
+ fulladdr, gai_strerror (ret), ret);
|
||||
+ TEST_VERIFY_EXIT (ai != NULL);
|
||||
+ TEST_VERIFY_EXIT (ai->ai_addrlen == sizeof (*result));
|
||||
+ TEST_VERIFY (ai->ai_family == AF_INET6);
|
||||
+ TEST_VERIFY (ai->ai_next == NULL);
|
||||
+ memcpy (result, ai->ai_addr, sizeof (*result));
|
||||
+ free (fulladdr);
|
||||
+ freeaddrinfo (ai);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* Verify that a successful call to getaddrinfo returned the expected
|
||||
+ scope data. */
|
||||
+static void
|
||||
+check_ai (const char *what, const char *addr_string, const char *scope_string,
|
||||
+ const struct sockaddr_in6 *sa,
|
||||
+ const struct in6_addr *addr, uint32_t scope)
|
||||
+{
|
||||
+ if (memcmp (addr, &sa->sin6_addr, sizeof (*addr)) != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: getaddrinfo %s address mismatch for %s%%%s\n",
|
||||
+ what, addr_string, scope_string);
|
||||
+ }
|
||||
+ if (sa->sin6_scope_id != scope)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: getaddrinfo %s scope mismatch for %s%%%s\n"
|
||||
+ " expected: %" PRIu32 "\n"
|
||||
+ " actual: %" PRIu32 "\n",
|
||||
+ what, addr_string, scope_string, scope, sa->sin6_scope_id);
|
||||
}
|
||||
- return addr;
|
||||
}
|
||||
|
||||
/* Check a single address were we expected a failure. */
|
||||
static void
|
||||
expect_failure (const char *address, const char *scope)
|
||||
{
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: expecting failure for %s%%%s\n", address, scope);
|
||||
struct in6_addr addr = from_string (address);
|
||||
uint32_t result = 1234;
|
||||
if (__inet6_scopeid_pton (&addr, scope, &result) == 0)
|
||||
{
|
||||
+ support_record_failure ();
|
||||
printf ("error: unexpected success for %s%%%s\n",
|
||||
address, scope);
|
||||
- exit (1);
|
||||
}
|
||||
if (result != 1234)
|
||||
{
|
||||
+ support_record_failure ();
|
||||
printf ("error: unexpected result update for %s%%%s\n",
|
||||
address, scope);
|
||||
- exit (1);
|
||||
+ }
|
||||
+
|
||||
+ struct sockaddr_in6 sa;
|
||||
+ if (call_gai (AF_UNSPEC, address, scope, &sa))
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: unexpected getaddrinfo success for %s%%%s (AF_UNSPEC)\n",
|
||||
+ address, scope);
|
||||
+ }
|
||||
+ if (call_gai (AF_INET6, address, scope, &sa))
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: unexpected getaddrinfo success for %s%%%s (AF_INET6)\n",
|
||||
+ address, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,21 +154,43 @@ expect_failure (const char *address, const char *scope)
|
||||
static void
|
||||
expect_success (const char *address, const char *scope, uint32_t expected)
|
||||
{
|
||||
+ if (test_verbose > 0)
|
||||
+ printf ("info: expecting success for %s%%%s\n", address, scope);
|
||||
struct in6_addr addr = from_string (address);
|
||||
uint32_t actual = expected + 1;
|
||||
if (__inet6_scopeid_pton (&addr, scope, &actual) != 0)
|
||||
{
|
||||
+ support_record_failure ();
|
||||
printf ("error: unexpected failure for %s%%%s\n",
|
||||
address, scope);
|
||||
- exit (1);
|
||||
}
|
||||
if (actual != expected)
|
||||
{
|
||||
+ support_record_failure ();
|
||||
printf ("error: unexpected result for for %s%%%s\n",
|
||||
address, scope);
|
||||
printf (" expected: %" PRIu32 "\n", expected);
|
||||
printf (" actual: %" PRIu32 "\n", actual);
|
||||
- exit (1);
|
||||
+ }
|
||||
+
|
||||
+ struct sockaddr_in6 sa;
|
||||
+ memset (&sa, 0xc0, sizeof (sa));
|
||||
+ if (call_gai (AF_UNSPEC, address, scope, &sa))
|
||||
+ check_ai ("AF_UNSPEC", address, scope, &sa, &addr, expected);
|
||||
+ else
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_UNSPEC)\n",
|
||||
+ address, scope);
|
||||
+ }
|
||||
+ memset (&sa, 0xc0, sizeof (sa));
|
||||
+ if (call_gai (AF_INET6, address, scope, &sa))
|
||||
+ check_ai ("AF_INET6", address, scope, &sa, &addr, expected);
|
||||
+ else
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_INET6)\n",
|
||||
+ address, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,5 +227,4 @@ do_test (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-#define TEST_FUNCTION do_test ()
|
||||
-#include "../test-skeleton.c"
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,321 @@
|
|||
commit 85cfe508568530eed2d9cfd34110c21721d1f99e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Sep 6 13:43:01 2017 +0200
|
||||
|
||||
tst-res_use_inet6: Enhance test to cover IPv4-to-IPv6 address mapping
|
||||
|
||||
This requires more control over the response data, so it is now
|
||||
determined by flags embedded in the query name.
|
||||
|
||||
(cherry picked from commit 5e9c4d17feb9910f489ad2915d0b6e00597a0f11)
|
||||
|
||||
diff --git a/resolv/tst-res_use_inet6.c b/resolv/tst-res_use_inet6.c
|
||||
index 6f3db088929027b7..1522d5c5f5e4d860 100644
|
||||
--- a/resolv/tst-res_use_inet6.c
|
||||
+++ b/resolv/tst-res_use_inet6.c
|
||||
@@ -19,18 +19,44 @@
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
+#include <support/check.h>
|
||||
#include <support/check_nss.h>
|
||||
#include <support/resolv_test.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
+/* 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)
|
||||
+ 'm' record type must match QTYPE (no additional records)
|
||||
+
|
||||
+ QTYPE is ignored for record type selection if 'm' is not
|
||||
+ specified. */
|
||||
static void
|
||||
response (const struct resolv_response_context *ctx,
|
||||
struct resolv_response_builder *b,
|
||||
const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
{
|
||||
- bool include_both = strcmp (qname, "both.example") == 0;
|
||||
- bool include_a = qtype == T_A || include_both;
|
||||
- bool include_aaaa = qtype == T_AAAA || include_both;
|
||||
+ bool include_a = false;
|
||||
+ bool include_aaaa = false;
|
||||
+ bool include_match = 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;
|
||||
+ }
|
||||
+ 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);
|
||||
@@ -64,16 +90,21 @@ test_gai (void)
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
};
|
||||
struct addrinfo *ai;
|
||||
- int ret = getaddrinfo ("www1.example", "80", &hints, &ai);
|
||||
- check_addrinfo ("getaddrinfo AF_UNSPEC www1.example", ai, ret,
|
||||
+ 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 ("both.example", "80", &hints, &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 both.example", ai, ret,
|
||||
+ 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"
|
||||
@@ -89,13 +120,18 @@ test_gai (void)
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
};
|
||||
struct addrinfo *ai;
|
||||
- int ret = getaddrinfo ("www1.example", "80", &hints, &ai);
|
||||
- check_addrinfo ("getaddrinfo AF_INET www1.example", ai, ret,
|
||||
+ 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 ("both.example", "80", &hints, &ai);
|
||||
- check_addrinfo ("getaddrinfo AF_INET both.example", ai, ret,
|
||||
+ 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);
|
||||
@@ -108,40 +144,131 @@ test_gai (void)
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
};
|
||||
struct addrinfo *ai;
|
||||
- int ret = getaddrinfo ("www1.example", "80", &hints, &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 ("both.example", "80", &hints, &ai);
|
||||
- check_addrinfo ("getaddrinfo AF_INET6 both.example", ai, ret,
|
||||
+ 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 that gethostbyname2 is not influenced by RES_USE_INET6. */
|
||||
+/* Test that gethostbyname2 is mostly not influenced by
|
||||
+ RES_USE_INET6. */
|
||||
static void
|
||||
-test_get2 (void)
|
||||
+test_get2_any (void)
|
||||
{
|
||||
- check_hostent ("gethostbyname2 AF_INET www1.example",
|
||||
- gethostbyname2 ("www1.example", AF_INET),
|
||||
- "name: www1.example\n"
|
||||
+ 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 both.example",
|
||||
- gethostbyname2 ("both.example", AF_INET),
|
||||
- "name: both.example\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 www1.example",
|
||||
- gethostbyname2 ("www1.example", AF_INET6),
|
||||
- "name: www1.example\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 both.example",
|
||||
- gethostbyname2 ("both.example", AF_INET6),
|
||||
- "name: both.example\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. */
|
||||
+}
|
||||
+
|
||||
+/* 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 (\"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 *
|
||||
@@ -153,28 +280,42 @@ threadfunc (void *ignored)
|
||||
.response_callback = response
|
||||
});
|
||||
|
||||
- check_hostent ("gethostbyname (\"www1.example\")",
|
||||
- gethostbyname ("www1.example"),
|
||||
- "name: www1.example\n"
|
||||
- "address: 192.0.2.17\n");
|
||||
- check_hostent ("gethostbyname (\"both.example\")",
|
||||
- gethostbyname ("both.example"),
|
||||
- "name: both.example\n"
|
||||
- "address: 192.0.2.17\n");
|
||||
- test_get2 ();
|
||||
- test_gai ();
|
||||
+ TEST_VERIFY ((_res.options & RES_USE_INET6) == 0);
|
||||
+ test_no_inet6 ();
|
||||
|
||||
_res.options |= RES_USE_INET6;
|
||||
- check_hostent ("gethostbyname (\"www1.example\")",
|
||||
- gethostbyname ("www1.example"),
|
||||
- "name: www1.example\n"
|
||||
+ 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 (\"both.example\")",
|
||||
- gethostbyname ("both.example"),
|
||||
- "name: both.example\n"
|
||||
+ check_hostent ("gethostbyname (\"q.inet6.example\")",
|
||||
+ gethostbyname ("q.inet6.example"),
|
||||
+ "name: q.inet6.example\n"
|
||||
"address: 2001:db8::1\n");
|
||||
- test_get2 ();
|
||||
+ check_hostent ("gethostbyname (\"qm.inet6.example\")",
|
||||
+ gethostbyname ("qm.inet6.example"),
|
||||
+ "name: qm.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);
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
commit c3261cdb5b739c1e814de32e40ecd712ad987cdb
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Apr 4 17:31:52 2017 +0200
|
||||
|
||||
resolv: Add tst-resolv-canonname
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 8441f9d30d83a209..db287947a4f7e9a6 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -51,6 +51,13 @@ tests += \
|
||||
tst-resolv-network \
|
||||
tst-resolv-search \
|
||||
|
||||
+# These tests need libdl.
|
||||
+ifeq (yes,$(build-shared))
|
||||
+tests += \
|
||||
+ tst-resolv-canonname \
|
||||
+
|
||||
+endif
|
||||
+
|
||||
# This test sends millions of packets and is rather slow.
|
||||
xtests += tst-resolv-qtypes
|
||||
endif
|
||||
@@ -130,6 +137,8 @@ $(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-canonname: \
|
||||
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
|
||||
|
||||
$(objpfx)tst-ns_name: $(objpfx)libresolv.so
|
||||
$(objpfx)tst-ns_name.out: tst-ns_name.data
|
||||
diff --git a/resolv/tst-resolv-canonname.c b/resolv/tst-resolv-canonname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..5daac33882957791
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-canonname.c
|
||||
@@ -0,0 +1,313 @@
|
||||
+/* Test _nss_dns_getcanonname_r corner cases.
|
||||
+ Copyright (C) 2017 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 <dlfcn.h>
|
||||
+#include <errno.h>
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <netdb.h>
|
||||
+#include <nss.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+/* _nss_dns_getcanonname_r is not called during regular operation
|
||||
+ because nss_dns directly provides a canonical name, so we have to
|
||||
+ test it directly. The function pointer is initialized by do_test
|
||||
+ below. */
|
||||
+static enum nss_status
|
||||
+(*getcanonname) (const char *name, char *buffer, size_t buflen,
|
||||
+ char **result, int *errnop, int *h_errnop);
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ int code;
|
||||
+ {
|
||||
+ char *tail;
|
||||
+ if (sscanf (qname, "code%d.%ms", &code, &tail) != 2
|
||||
+ || strcmp (tail, "example") != 0)
|
||||
+ FAIL_EXIT1 ("error: invalid QNAME: %s\n", qname);
|
||||
+ free (tail);
|
||||
+ }
|
||||
+
|
||||
+ switch (code)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ 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, "www.example", qclass, qtype, 0);
|
||||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||||
+ resolv_response_close_record (b);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ if (qtype == T_AAAA)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||||
+ resolv_response_close_record (b);
|
||||
+ for (int i = 0; i < 30000; ++i)
|
||||
+ resolv_response_add_data (b, "", 1);
|
||||
+ }
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ if (qtype == T_AAAA)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ for (int i = 0; i < 30000; ++i)
|
||||
+ resolv_response_add_data (b, "", 1);
|
||||
+ }
|
||||
+ break;
|
||||
+ case 4:
|
||||
+ 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_CNAME, 0);
|
||||
+ resolv_response_add_name (b, "www.example");
|
||||
+ resolv_response_close_record (b);
|
||||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||||
+ resolv_response_close_record (b);
|
||||
+ break;
|
||||
+ case 5:
|
||||
+ 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_CNAME, 0);
|
||||
+ resolv_response_add_name (b, "www.example");
|
||||
+ resolv_response_close_record (b);
|
||||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||||
+ resolv_response_add_name (b, "www1.example");
|
||||
+ resolv_response_close_record (b);
|
||||
+ resolv_response_open_record (b, "www1.example", qclass, qtype, 0);
|
||||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||||
+ resolv_response_close_record (b);
|
||||
+ break;
|
||||
+ case 6:
|
||||
+ 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_CNAME, 0);
|
||||
+ resolv_response_add_name (b, "www.example");
|
||||
+ resolv_response_close_record (b);
|
||||
+ resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0);
|
||||
+ resolv_response_add_name (b, ".");
|
||||
+ resolv_response_close_record (b);
|
||||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||||
+ resolv_response_close_record (b);
|
||||
+ break;
|
||||
+ case 102:
|
||||
+ if (!ctx->tcp)
|
||||
+ {
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {.tc = true});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ resolv_response_init
|
||||
+ (b, (struct resolv_response_flags) {.ancount = 1});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||||
+ size_t to_fill = 65535 - resolv_response_length (b)
|
||||
+ - 2 /* length, "n" */ - 2 /* compression reference */
|
||||
+ - 2 /* RR type */;
|
||||
+ for (size_t i = 0; i < to_fill; ++i)
|
||||
+ resolv_response_add_data (b, "", 1);
|
||||
+ resolv_response_close_record (b);
|
||||
+ resolv_response_add_name (b, "n.example");
|
||||
+ uint16_t rrtype = htons (T_CNAME);
|
||||
+ resolv_response_add_data (b, &rrtype, sizeof (rrtype));
|
||||
+ }
|
||||
+ break;
|
||||
+ case 103:
|
||||
+ /* NODATA repsonse. */
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ break;
|
||||
+ case 104:
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ /* No RR metadata. */
|
||||
+ resolv_response_add_name (b, "www.example");
|
||||
+ break;
|
||||
+ case 105:
|
||||
+ if (qtype == T_A)
|
||||
+ {
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ /* No data, trigger AAAA query. */
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ resolv_response_init
|
||||
+ (b, (struct resolv_response_flags) {.ancount = 1});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ /* No RR metadata. */
|
||||
+ resolv_response_add_name
|
||||
+ (b, "long-name-exceed-previously-initialized-buffer.example");
|
||||
+ }
|
||||
+ break;
|
||||
+ case 106:
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ /* No RR metadata. */
|
||||
+ resolv_response_add_name (b, "www.example");
|
||||
+ resolv_response_add_data (b, "\xff\xff", 2);
|
||||
+ break;
|
||||
+ case 107:
|
||||
+ if (qtype == T_A)
|
||||
+ {
|
||||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ /* No data, trigger AAAA query. */
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ resolv_response_init
|
||||
+ (b, (struct resolv_response_flags) {.ancount = 1});
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ /* No RR metadata. */
|
||||
+ resolv_response_add_name (b, "www.example");
|
||||
+ resolv_response_add_data (b, "\xff\xff", 2);
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ FAIL_EXIT1 ("error: invalid QNAME: %s (code %d)\n", qname, code);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check (int code, const char *expected)
|
||||
+{
|
||||
+ char qname[200];
|
||||
+ snprintf (qname, sizeof (qname), "code%d.example", code);
|
||||
+ char *result;
|
||||
+ enum nss_status status;
|
||||
+ {
|
||||
+ enum { buffer_size = 4096 };
|
||||
+ char *buffer = xmalloc (buffer_size);
|
||||
+ char *temp_result;
|
||||
+ int temp_errno;
|
||||
+ int temp_herrno;
|
||||
+ status = getcanonname
|
||||
+ (qname, buffer, buffer_size, &temp_result, &temp_errno, &temp_herrno);
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ result = xstrdup (temp_result);
|
||||
+ else
|
||||
+ {
|
||||
+ errno = temp_errno;
|
||||
+ h_errno = temp_herrno;
|
||||
+ }
|
||||
+ free (buffer);
|
||||
+ }
|
||||
+
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (expected != NULL)
|
||||
+ {
|
||||
+ if (strcmp (result, expected) != 0)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: getcanonname (%s) failed\n", qname);
|
||||
+ printf ("error: expected: %s\n", expected);
|
||||
+ printf ("error: actual: %s\n", result);
|
||||
+ free (result);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: getcanonname (%s) unexpected success\n", qname);
|
||||
+ printf ("error: actual: %s\n", result);
|
||||
+ free (result);
|
||||
+ return;
|
||||
+ }
|
||||
+ free (result);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (expected != NULL)
|
||||
+ {
|
||||
+ support_record_failure ();
|
||||
+ printf ("error: getcanonname (%s) failed\n", qname);
|
||||
+ printf ("error: expected: %s\n", expected);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ void *nss_dns_handle = dlopen (LIBNSS_DNS_SO, RTLD_LAZY);
|
||||
+ if (nss_dns_handle == NULL)
|
||||
+ FAIL_EXIT1 ("could not dlopen %s: %s", LIBNSS_DNS_SO, dlerror ());
|
||||
+ {
|
||||
+ const char *func = "_nss_dns_getcanonname_r";
|
||||
+ void *ptr = dlsym (nss_dns_handle, func);
|
||||
+ if (ptr == NULL)
|
||||
+ FAIL_EXIT1 ("could not look up %s: %s", func, dlerror ());
|
||||
+ getcanonname = ptr;
|
||||
+ }
|
||||
+
|
||||
+ struct resolv_test *aux = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ });
|
||||
+
|
||||
+ check (1, "www.example");
|
||||
+ check (2, "www.example");
|
||||
+ check (3, "www.example");
|
||||
+ check (4, "www.example");
|
||||
+ check (5, "www1.example");
|
||||
+
|
||||
+ /* This should really result in "www.example", but the fake RRSIG
|
||||
+ record causes the current implementation to stop parsing. */
|
||||
+ check (6, NULL);
|
||||
+
|
||||
+ for (int i = 102; i <= 107; ++i)
|
||||
+ check (i, NULL);
|
||||
+
|
||||
+ resolv_test_end (aux);
|
||||
+
|
||||
+ TEST_VERIFY (dlclose (nss_dns_handle) == 0);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,46 @@
|
|||
commit a9270e673dcc1ef1d2c2d96fa09d468c59883d88
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 30 18:02:11 2017 +0200
|
||||
|
||||
resolv: Improve debugging output from tst-resolv-res_init
|
||||
|
||||
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
|
||||
index 2b68c5ff9a69a291..b5fe2cfb002679f2 100644
|
||||
--- a/resolv/tst-resolv-res_init-skeleton.c
|
||||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||||
@@ -257,6 +257,15 @@ enum test_init
|
||||
test_init_method_last = test_getaddrinfo
|
||||
};
|
||||
|
||||
+static const char *const test_init_names[] =
|
||||
+ {
|
||||
+ [test_init] = "res_init",
|
||||
+ [test_ninit] = "res_init",
|
||||
+ [test_mkquery] = "res_mkquery",
|
||||
+ [test_gethostbyname] = "gethostbyname",
|
||||
+ [test_getaddrinfo] = "getaddrinfo",
|
||||
+ };
|
||||
+
|
||||
/* Closure argument for run_res_init. */
|
||||
struct test_context
|
||||
{
|
||||
@@ -507,7 +516,8 @@ test_file_contents (const struct test_case *t)
|
||||
++init_method)
|
||||
{
|
||||
if (test_verbose > 0)
|
||||
- printf ("info: testing init method %d\n", init_method);
|
||||
+ printf ("info: testing init method %s\n",
|
||||
+ test_init_names[init_method]);
|
||||
struct test_context ctx = { .init = init_method, .t = t };
|
||||
void (*func) (void *) = run_res_init;
|
||||
#if TEST_THREAD
|
||||
@@ -519,7 +529,8 @@ test_file_contents (const struct test_case *t)
|
||||
if (strcmp (proc.out.buffer, t->expected) != 0)
|
||||
{
|
||||
support_record_failure ();
|
||||
- printf ("error: output mismatch for %s\n", t->name);
|
||||
+ printf ("error: output mismatch for %s (init method %s)\n",
|
||||
+ t->name, test_init_names[init_method]);
|
||||
support_run_diff ("expected", t->expected,
|
||||
"actual", proc.out.buffer);
|
||||
}
|
400
glibc.spec
400
glibc.spec
|
@ -1,6 +1,6 @@
|
|||
%define glibcsrcdir glibc-2.25-3-g93cf93e
|
||||
%define glibcsrcdir glibc-2.25-123-gedcf13e25c
|
||||
%define glibcversion 2.25
|
||||
%define glibcrelease 3%{?dist}
|
||||
%define glibcrelease 13%{?dist}
|
||||
# Pre-release tarballs are pulled in from git using a command that is
|
||||
# effectively:
|
||||
#
|
||||
|
@ -9,7 +9,8 @@
|
|||
# gzip -9 $(git describe --match 'glibc-*').tar
|
||||
#
|
||||
# glibc_release_url is only defined when we have a release tarball.
|
||||
%define glibc_release_url http://ftp.gnu.org/gnu/glibc/
|
||||
%{lua: if string.match(rpm.expand("%glibcsrcdir"), "^glibc%-[0-9.]+$") then
|
||||
rpm.define("glibc_release_url https://ftp.gnu.org/gnu/glibc/") end}
|
||||
##############################################################################
|
||||
# We support hte following options:
|
||||
# --with/--without,
|
||||
|
@ -131,14 +132,6 @@
|
|||
# will be created for the architecture.
|
||||
%define debuginfocommonarches %{biarcharches} alpha alphaev6
|
||||
##############################################################################
|
||||
# If the architecture has multiarch support in glibc then it should be listed
|
||||
# here to enable support in the build. Multiarch support is a single library
|
||||
# with implementations of certain functions for multiple architectures. The
|
||||
# most optimal function is selected at runtime based on the hardware that is
|
||||
# detected by glibc. The underlying support for function selection and
|
||||
# execution is provided by STT_GNU_IFUNC.
|
||||
%define multiarcharches %{power64} %{ix86} x86_64 %{sparc}
|
||||
##############################################################################
|
||||
# Add -s for a less verbose build output.
|
||||
%define silentrules PARALLELMFLAGS=
|
||||
##############################################################################
|
||||
|
@ -251,9 +244,6 @@ Patch0059: glibc-c-utf8-locale.patch
|
|||
# Build libcrypt twice, with and without NSS.
|
||||
Patch0060: glibc-rh1324623.patch
|
||||
|
||||
# Fix -Wstrict-overflow issues with gcc 7.0.
|
||||
Patch0061: glibc-gcc-strict-overflow.patch
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Patches from upstream
|
||||
|
@ -290,6 +280,7 @@ Patch2036: glibc-gcc-PR69537.patch
|
|||
|
||||
# extend_alloca removal, BZ 18023
|
||||
Patch2037: glibc-rh1315108.patch
|
||||
Patch2038: glibc-rh1315108-glob.patch
|
||||
|
||||
# Upstream BZ 20313
|
||||
Patch2110: glibc-rh1351108-update-to-unicode-9.0.0.patch
|
||||
|
@ -297,6 +288,72 @@ Patch2110: glibc-rh1351108-update-to-unicode-9.0.0.patch
|
|||
# sln implemented by ldconfig, to conserve disk space.
|
||||
Patch2112: glibc-rh1315476-2.patch
|
||||
|
||||
Patch61: glibc-nscd-reproducible.patch
|
||||
Patch62: glibc-nss_compat.patch
|
||||
Patch63: glibc-rh1416405.patch
|
||||
Patch64: glibc-bits-types-res_state.patch
|
||||
Patch69: glibc-libc_diag.patch
|
||||
Patch77: glibc-alloc_buffer-2.patch
|
||||
Patch79: glibc-rh168253-network-dn_expand-cleanup.patch
|
||||
Patch80: glibc-rh168253-nss_dns-declaration-cleanup.patch
|
||||
Patch81: glibc-rh168253-tst-resolv-canonname.patch
|
||||
Patch82: glibc-rh168253-remove-iquery.patch
|
||||
Patch83: glibc-rh168253-resolv-h-definitions-cleanup.patch
|
||||
Patch85: glibc-rh168253-remove-ends-fallback.patch
|
||||
Patch86: glibc-rh168253-sock_cloexec.patch
|
||||
Patch87: glibc-rh168253-builtin_expect.patch
|
||||
Patch88: glibc-rh168253-builtin_expect-fixup.patch
|
||||
Patch89: glibc-rh168253-res_dflretry.patch
|
||||
Patch94: glibc-rh168253-res_init-tests.patch
|
||||
Patch97: glibc-rh168253-getaddrinfo-malloc-canonname-strdup-3.patch
|
||||
Patch98: glibc-rh168253-res_vinit-hidden.patch
|
||||
Patch99: glibc-rh168253-res_randomid-reorg.patch
|
||||
Patch100: glibc-rh168253-res-close.patch
|
||||
Patch101: glibc-rh168253-res_setoptions-debug-cleanup.patch
|
||||
Patch102: glibc-rh168253-is_sort_mask.patch
|
||||
Patch103: glibc-rh168253-res_vinit-gnu-style.patch
|
||||
Patch104: glibc-rh168253-res_vinit-check-allocations.patch
|
||||
Patch105: glibc-rh168253-res_vinit_1-getline.patch
|
||||
Patch106: glibc-rh168253-tst-inet6_scopeid_pton-getaddrinfo.patch
|
||||
Patch107: glibc-rh168253-inet_pton_length.patch
|
||||
Patch109: glibc-rh168253-inet6_scopeid_pton-node-local.patch
|
||||
Patch110: glibc-rh168253-__res_initstamp-cleanup.patch
|
||||
Patch111: glibc-rh168253-res_libc-gnu-style.patch
|
||||
Patch112: glibc-rh168253-inet_pton-leading-zeros.patch
|
||||
Patch114: glibc-rh168253-getaddrinfo-tests-bug21295.patch
|
||||
Patch115: glibc-rh168253-_-res_vinit-_res_hconf_init.patch
|
||||
Patch116: glibc-rh168253-resolv-tests-timeout.patch
|
||||
Patch117: glibc-rh168253-res_rotate-random.patch
|
||||
Patch118: glibc-rh168253-res_mkquery-debug-cleanup.patch
|
||||
Patch119: glibc-rh168253-res_mkquery-gnu-style.patch
|
||||
Patch120: glibc-rh168253-res_mkquery-reorg.patch
|
||||
Patch121: glibc-rh168253-res_send-debug-cleanup.patch
|
||||
Patch122: glibc-rh168253-res_debug-removal.patch
|
||||
Patch123: glibc-rh168253-fp_nquery-reorg.patch
|
||||
Patch124: glibc-rh168253-_res_opcodes-compat.patch
|
||||
Patch125: glibc-rh168253-res_isourserver-reorg.patch
|
||||
Patch126: glibc-rh168253-res_query-reorg.patch
|
||||
Patch127: glibc-rh168253-res_data-gnu-style.patch
|
||||
Patch128: glibc-rh168253-res_query-debug-cleanup.patch
|
||||
Patch129: glibc-rh168253-res_options-source-cleanup.patch
|
||||
Patch130: glibc-rh168253-tst-resolv-res_init-debugging.patch
|
||||
Patch131: glibc-rh168253-resolv-tests-preinit.patch
|
||||
Patch132: glibc-rh168253-struct-resolv_context.patch
|
||||
Patch133: glibc-rh168253-struct-resolv_conf.patch
|
||||
Patch134: glibc-rh168253-search-list-limit.patch
|
||||
Patch135: glibc-rh168253-resolv_conf-full-config.patch
|
||||
Patch136: glibc-rh168253-resolv-conf-reload.patch
|
||||
Patch137: glibc-rh168253-resolv_conf-free-list.patch
|
||||
Patch138: glibc-rh168253-__resolv_conf_attach-assert.patch
|
||||
Patch139: glibc-rh168253-resolv_conf-_res-matching.patch
|
||||
Patch140: glibc-rh168253-support_chroot.patch
|
||||
Patch141: glibc-rh168253-resolv-tests-no-patching.patch
|
||||
Patch142: glibc-rh168253-resolv-tests-nondeterministic.patch
|
||||
Patch151: glibc-rh168253-tst-res_use_inet6-mapping.patch
|
||||
Patch152: glibc-rh168253-nss_dns-dead-code.patch
|
||||
Patch153: glibc-rh168253-resolv-oom-memory-leak.patch
|
||||
Patch154: glibc-rh168253-__resolv_conf_attach-improper-free.patch
|
||||
|
||||
##############################################################################
|
||||
# End of glibc patches.
|
||||
##############################################################################
|
||||
|
@ -380,29 +437,9 @@ Conflicts: kernel < %{enablekernel}
|
|||
%endif
|
||||
%endif
|
||||
|
||||
%ifarch %{multiarcharches}
|
||||
# Need STT_IFUNC support
|
||||
%ifarch %{power64}
|
||||
BuildRequires: binutils >= 2.20.51.0.2
|
||||
Conflicts: binutils < 2.20.51.0.2
|
||||
%else
|
||||
%ifarch s390 s390x
|
||||
# Needed for STT_GNU_IFUNC support for s390/390x
|
||||
BuildRequires: binutils >= 2.23.52.0.1-8
|
||||
Conflicts: binutils < 2.23.52.0.1-8
|
||||
%else
|
||||
# Default to this version
|
||||
BuildRequires: binutils >= 2.19.51.0.10
|
||||
Conflicts: binutils < 2.19.51.0.10
|
||||
%endif
|
||||
%endif
|
||||
BuildRequires: binutils >= 2.25
|
||||
# Earlier releases have broken support for IRELATIVE relocations
|
||||
Conflicts: prelink < 0.4.2
|
||||
%else
|
||||
# Need AS_NEEDED directive
|
||||
# Need --hash-style=* support
|
||||
BuildRequires: binutils >= 2.17.50.0.2-5
|
||||
%endif
|
||||
|
||||
BuildRequires: gcc >= 3.2.1-5
|
||||
%ifarch s390 s390x
|
||||
|
@ -607,47 +644,92 @@ The sources for all locales provided in the language packs.
|
|||
If you are building custom locales you will most likely use
|
||||
these sources as the basis for your new locale.
|
||||
|
||||
%define lang_package()\
|
||||
%package langpack-%{1}\
|
||||
Summary: Locale data for %{1}\
|
||||
Provides: glibc-langpack = %{version}-%{release}\
|
||||
Requires: %{name} = %{version}-%{release}\
|
||||
Requires: %{name}-common = %{version}-%{release}\
|
||||
%define supplements_list %(cat %{SOURCE11} | grep ^%{1}_ | cut -d / -f 1 | cut -d @ -f 1 | cut -d . -f 1 | sort -u | tr "\\\\n" " " | sed 's/ $//' | sed 's/ / or langpacks-/g' | sed 's/^/ or langpacks-/')\
|
||||
Supplements: (glibc = %{version}-%{release} and (langpacks-%{1}%{supplements_list}))\
|
||||
Group: System Environment/Base\
|
||||
%description langpack-%{1}\
|
||||
The glibc-langpack-%{1} package includes the basic information required\
|
||||
to support the %{1} language in your applications.\
|
||||
%ifnarch %{auxarches}\
|
||||
%files -f langpack-%{1}.filelist langpack-%{1}\
|
||||
%defattr(-,root,root)\
|
||||
%endif\
|
||||
%{nil}
|
||||
%{lua:
|
||||
-- Array of languages (ISO-639 codes).
|
||||
local languages = {}
|
||||
-- Dictionary from language codes (as in the languages array) to arrays
|
||||
-- of regions.
|
||||
local supplements = {}
|
||||
do
|
||||
-- Parse the SUPPORTED file. Eliminate duplicates.
|
||||
local lang_region_seen = {}
|
||||
for line in io.lines(rpm.expand("%{SOURCE11}")) do
|
||||
-- Match lines which contain a language (eo) or language/region
|
||||
-- (en_US) strings.
|
||||
local lang_region = string.match(line, "^([a-z][^/@.]+)")
|
||||
if lang_region ~= nil then
|
||||
if lang_region_seen[lang_region] == nil then
|
||||
lang_region_seen[lang_region] = true
|
||||
|
||||
# language_list will contain a list of all supported language
|
||||
# names in iso-639 format, i.e. something like "aa af ... yue zh zu"
|
||||
# We add "eo" (Esperanto) manually because currently glibc has no
|
||||
# Esperanto locale in SUPPORTED but translations for Esperanto exist.
|
||||
# Therefore, we want a glibc-langpack-eo sub-package containing these
|
||||
# translations.
|
||||
%define language_list eo %(cat %{SOURCE11} | grep -E '^[a-z]+_' | cut -d _ -f 1 | sort -u | tr "\\\\n" " " | sed 's/ $//')
|
||||
-- Split language/region pair.
|
||||
local lang, region = string.match(lang_region, "^(.+)_(.+)")
|
||||
if lang == nil then
|
||||
-- Region is missing, use only the language.
|
||||
lang = lang_region
|
||||
end
|
||||
local suppl = supplements[lang]
|
||||
if suppl == nil then
|
||||
suppl = {}
|
||||
supplements[lang] = suppl
|
||||
-- New language not seen before.
|
||||
languages[#languages + 1] = lang
|
||||
end
|
||||
if region ~= nil then
|
||||
-- New region because of the check against
|
||||
-- lang_region_seen above.
|
||||
suppl[#suppl + 1] = region
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Sort for determinism.
|
||||
table.sort(languages)
|
||||
for _, supples in pairs(supplements) do
|
||||
table.sort(supplements)
|
||||
end
|
||||
end
|
||||
|
||||
%define create_lang_packages()\
|
||||
%{lua:\
|
||||
local languages = rpm.expand("%1")\
|
||||
string.gsub(languages, "(%a+)",\
|
||||
function(i) print(rpm.expand("%lang_package "..i.."")) end)}\
|
||||
%{nil}
|
||||
-- Compute the Supplements: list for a language, based on the regions.
|
||||
local function compute_supplements(lang)
|
||||
result = "langpacks-" .. lang
|
||||
regions = supplements[lang]
|
||||
if regions ~= nil then
|
||||
for i = 1, #regions do
|
||||
result = result .. " or langpacks-" .. lang .. "_" .. regions[i]
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
%create_lang_packages %language_list
|
||||
-- Emit the definition of a language pack package.
|
||||
local function lang_package(lang)
|
||||
local suppl = compute_supplements(lang)
|
||||
print(rpm.expand([[
|
||||
|
||||
%define require_langpacks()\
|
||||
%{lua:\
|
||||
local languages = rpm.expand("%1")\
|
||||
string.gsub(languages, "(%a+)",\
|
||||
function(i) print(rpm.expand("Requires: %{name}-langpack-"..i.." = %{version}-%{release}\\n")) end)}\
|
||||
%{nil}
|
||||
%package langpack-]]..lang..[[
|
||||
|
||||
Summary: Locale data for ]]..lang..[[
|
||||
|
||||
Provides: glibc-langpack = %{version}-%{release}
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: %{name}-common = %{version}-%{release}
|
||||
Supplements: (glibc = %{version}-%{release} and (]]..suppl..[[))
|
||||
%description langpack-]]..lang..[[
|
||||
|
||||
The glibc-langpack-]]..lang..[[ package includes the basic information required
|
||||
to support the ]]..lang..[[ language in your applications.
|
||||
%ifnarch %{auxarches}
|
||||
%files -f langpack-]]..lang..[[.filelist langpack-]]..lang..[[
|
||||
|
||||
%defattr(-,root,root)
|
||||
%endif
|
||||
]]))
|
||||
end
|
||||
|
||||
for i = 1, #languages do
|
||||
lang_package(languages[i])
|
||||
end
|
||||
}
|
||||
|
||||
# The glibc-all-langpacks provides the virtual glibc-langpack,
|
||||
# and thus satisfies glibc's requirement for installed locales.
|
||||
|
@ -720,9 +802,9 @@ Group: System Environment/Base
|
|||
Requires: %{name}%{_isa} = %{version}-%{release}
|
||||
|
||||
%description -n nss_nis
|
||||
The nss_nis, nss_nisplus, and nss_compat Name Service Switch modules
|
||||
uses the Network Information System (NIS) to obtain user, group, host
|
||||
name, and other data.
|
||||
The nss_nis and nss_nisplus Name Service Switch modules uses the
|
||||
Network Information System (NIS) to obtain user, group, host name, and
|
||||
other data.
|
||||
|
||||
%package -n nss_hesiod
|
||||
Summary: Name Service Switch (NSS) module using Hesiod
|
||||
|
@ -863,9 +945,74 @@ microbenchmark tests on the system.
|
|||
%patch0060 -p1
|
||||
%patch2036 -p1
|
||||
%patch2037 -p1
|
||||
%patch2038 -p1
|
||||
%patch2110 -p1
|
||||
%patch2112 -p1
|
||||
%patch0061 -p1
|
||||
%patch61 -p1
|
||||
%patch62 -p1
|
||||
%patch63 -p1
|
||||
%patch64 -p1
|
||||
%patch69 -p1
|
||||
%patch77 -p1
|
||||
%patch79 -p1
|
||||
%patch80 -p1
|
||||
%patch81 -p1
|
||||
%patch82 -p1
|
||||
%patch83 -p1
|
||||
%patch85 -p1
|
||||
%patch86 -p1
|
||||
%patch87 -p1
|
||||
%patch88 -p1
|
||||
%patch89 -p1
|
||||
%patch94 -p1
|
||||
%patch97 -p1
|
||||
%patch98 -p1
|
||||
%patch99 -p1
|
||||
%patch100 -p1
|
||||
%patch101 -p1
|
||||
%patch102 -p1
|
||||
%patch103 -p1
|
||||
%patch104 -p1
|
||||
%patch105 -p1
|
||||
%patch106 -p1
|
||||
%patch107 -p1
|
||||
%patch109 -p1
|
||||
%patch110 -p1
|
||||
%patch111 -p1
|
||||
%patch112 -p1
|
||||
%patch114 -p1
|
||||
%patch115 -p1
|
||||
%patch116 -p1
|
||||
%patch117 -p1
|
||||
%patch118 -p1
|
||||
%patch119 -p1
|
||||
%patch120 -p1
|
||||
%patch121 -p1
|
||||
%patch122 -p1
|
||||
%patch123 -p1
|
||||
%patch124 -p1
|
||||
%patch125 -p1
|
||||
%patch126 -p1
|
||||
%patch127 -p1
|
||||
%patch128 -p1
|
||||
%patch129 -p1
|
||||
%patch130 -p1
|
||||
%patch131 -p1
|
||||
%patch132 -p1
|
||||
%patch133 -p1
|
||||
%patch134 -p1
|
||||
%patch135 -p1
|
||||
%patch136 -p1
|
||||
%patch137 -p1
|
||||
%patch138 -p1
|
||||
%patch139 -p1
|
||||
%patch140 -p1
|
||||
%patch141 -p1
|
||||
%patch142 -p1
|
||||
%patch151 -p1
|
||||
%patch152 -p1
|
||||
%patch153 -p1
|
||||
%patch154 -p1
|
||||
|
||||
##############################################################################
|
||||
# %%prep - Additional prep required...
|
||||
|
@ -1012,7 +1159,7 @@ AddOns=`echo */configure | sed -e 's!/configure!!g;s!\(nptl\|powerpc-cpu\)\( \|$
|
|||
# Build glibc in `build-%{target}$1', passing the rest of the arguments
|
||||
# as CFLAGS to the build (not the same as configure CFLAGS). Several
|
||||
# global values are used to determine build flags, add-ons, kernel
|
||||
# version, multiarch support, system tap support, etc.
|
||||
# version, system tap support, etc.
|
||||
##############################################################################
|
||||
build()
|
||||
{
|
||||
|
@ -1030,14 +1177,14 @@ build()
|
|||
--enable-add-ons=$AddOns \
|
||||
--with-headers=%{_prefix}/include $EnableKernel --enable-bind-now \
|
||||
--build=%{target} \
|
||||
%ifarch %{multiarcharches}
|
||||
--enable-multi-arch \
|
||||
%endif
|
||||
--enable-stack-protector=strong \
|
||||
--enable-tunables \
|
||||
--enable-obsolete-rpc \
|
||||
--enable-systemtap \
|
||||
${core_with_options} \
|
||||
%ifarch %{ix86}
|
||||
--disable-multi-arch \
|
||||
%endif
|
||||
%ifarch %{lock_elision_arches}
|
||||
--enable-lock-elision \
|
||||
%endif
|
||||
|
@ -1629,18 +1776,18 @@ for module in db nis nisplus compat hesiod files dns; do
|
|||
grep -E "/libnss_$module(\.so\.[0-9.]+|-[0-9.]+\.so)$" \
|
||||
rpm.filelist > nss_$module.filelist
|
||||
done
|
||||
# nis includes nisplus and compat
|
||||
cat nss_nisplus.filelist nss_compat.filelist >> nss_nis.filelist
|
||||
# nis includes nisplus
|
||||
cat nss_nisplus.filelist >> nss_nis.filelist
|
||||
# Symlinks go into the nss-devel package (instead of the main devel
|
||||
# package).
|
||||
grep '/libnss_[a-z]*\.so$' devel.filelist > nss-devel.filelist
|
||||
# /var/db/Makefile goes into nss_hesiod, remove the other files from
|
||||
# /var/db/Makefile goes into nss_db, remove the other files from
|
||||
# the main and devel file list.
|
||||
sed -i -e '\,/libnss_.*\.so[0-9.]*$,d' \
|
||||
-e '\,/var/db/Makefile,d' \
|
||||
rpm.filelist devel.filelist
|
||||
# Restore the built-in NSS modules.
|
||||
cat nss_files.filelist nss_dns.filelist >> rpm.filelist
|
||||
cat nss_files.filelist nss_dns.filelist nss_compat.filelist >> rpm.filelist
|
||||
|
||||
# Prepare the libcrypt-related file lists.
|
||||
grep '/libcrypt-[0-9.]*.so$' rpm.filelist > libcrypt.filelist
|
||||
|
@ -1786,9 +1933,7 @@ find_debuginfo_args="$find_debuginfo_args \
|
|||
-l nosegneg.filelist"
|
||||
%endif
|
||||
%endif
|
||||
eval /usr/lib/rpm/find-debuginfo.sh \
|
||||
"$find_debuginfo_args" \
|
||||
-o debuginfo.filelist
|
||||
/usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist
|
||||
|
||||
# List all of the *.a archives in the debug directory.
|
||||
list_debug_archives()
|
||||
|
@ -2239,9 +2384,9 @@ rm -f *.filelist*
|
|||
%endif
|
||||
|
||||
%files -f nss_db.filelist -n nss_db
|
||||
/var/db/Makefile
|
||||
%files -f nss_nis.filelist -n nss_nis
|
||||
%files -f nss_hesiod.filelist -n nss_hesiod
|
||||
/var/db/Makefile
|
||||
%doc hesiod/README.hesiod
|
||||
%files -f nss-devel.filelist nss-devel
|
||||
|
||||
|
@ -2270,6 +2415,85 @@ rm -f *.filelist*
|
|||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Jan 17 2018 Florian Weimer <fweimer@redhat.com> - 2.25-13
|
||||
- PTHREAD_STACK_MIN is too small on x86-64 (#1527887)
|
||||
- CVE-2018-1000001: Make getcwd fail if it cannot obtain an absolute path
|
||||
(#1533837)
|
||||
- CVE-2017-16997: Check for empty tokens before dynamic string token
|
||||
expansion in the dynamic linker (#1526866)
|
||||
- CVE-2017-15804: glob: Fix overflow in GLOB_TILDE unescaping (swbz#22332)
|
||||
- CVE-2017-15670: glob: Fix one-byte overflow (#1504807)
|
||||
- CVE-2017-15671: glob: Fix memory leak (#1504807)
|
||||
- Auto-sync with upstream branch release/2.25/master,
|
||||
commit edcf13e25c1559558a6f12ff5a71d4136a39235e:
|
||||
- nss_files: Avoid large buffers with many host addresses (swbz#22078)
|
||||
- nss_files: Use struct scratch_buffer for gethostbyname (swbz#18023)
|
||||
- posix: Fix improper assert in Linux posix_spawn (BZ#22273)
|
||||
- Don't use IFUNC resolver for longjmp or system in libpthread (swbz#21041)
|
||||
- x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve (swbz#21265)
|
||||
|
||||
* Wed Oct 11 2017 Florian Weimer <fweimer@redhat.com> - 2.25-12
|
||||
- Support an arbitrary number of search domains (#168253)
|
||||
- Detect and apply /etc/resolv.conf changes in libresolv (#1374239)
|
||||
- CVE-2015-5180: DNS stub resolver crash with crafted record type (#1251403)
|
||||
- Auto-sync with upstream branch release/2.25/master,
|
||||
commit 595f287ae092dd973f6d5fb748cbe31ef7d82b2d.
|
||||
|
||||
* Mon Oct 09 2017 Florian Weimer <fweimer@redhat.com> - 2.25-11
|
||||
- Move /var/db/Makefile to nss_db (#1498900)
|
||||
- Move nss_compat to the main glibc package (#1400538)
|
||||
- iconv: Support the IBM858 character set (#1416405)
|
||||
- Auto-sync with upstream branch release/2.25/master,
|
||||
commit 864ea5f6579edfee41f7d4a778807045b5aff66b:
|
||||
- nss: Fix pointer alignment/endianness issue in group merging (#1471985)
|
||||
- elf: Place $(elf-objpfx)sofini.os last (swbz#22051)
|
||||
|
||||
* Mon Aug 28 2017 Florian Weimer <fweimer@redhat.com> - 2.25-10
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit bc5ace67fe9823757532e0273f6c1cdfda065433:
|
||||
- mutex: Fix robust mutex lock acquire (#1485900)
|
||||
- rwlock: Fix explicit hand-over (swbz#21298)
|
||||
|
||||
* Tue Aug 22 2017 Florian Weimer <fweimer@redhat.com> - 2.25-9
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit 02aaa3c749bf18a3dbafff4c1f0180f135cad7ed:
|
||||
- assert: Support types without operator== (int) (#1483005)
|
||||
|
||||
* Wed Aug 16 2017 Florian Weimer <fweimer@redhat.com> - 2.25-8
|
||||
- Disable SSE2 usage on i686 (#1471427)
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit 47db584c74e2bbcf1ba55e62d949c1a738da5e0a:
|
||||
- CVE-2017-12132: Reduce EDNS payload size to 1200 bytes (#1477530)
|
||||
- Call exit directly in clone (swbz#21512)
|
||||
- assert: Suppress pedantic warning caused by statement expression (swbz#21242)
|
||||
- x86-64: Use _dl_runtime_resolve_opt only with AVX512F (swbz#21871)
|
||||
- powerpc: Fix logbl on power7 (swbz#21280)
|
||||
- Avoid .symver on common symbols (swbz#21666)
|
||||
- aarch64: Use hidden __GI__dl_argv in rtld startup code
|
||||
|
||||
* Thu Jul 06 2017 Florian Weimer <fweimer@redhat.com> - 2.25-7
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit 49f97e641e4e84a42246655d30adbc4756e67114:
|
||||
- x86-64: Align the stack in __tls_get_addr (#1440287)
|
||||
|
||||
* Tue Jun 20 2017 Florian Weimer <fweimer@redhat.com> - 2.25-6
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit adc7e06fb412a2a1ee52f8cb788caf436335b9f3, fixing:
|
||||
- CVE-2017-1000366: Avoid large allocas in the dynamic linker (#1462820)
|
||||
- Ignore and remove LD_HWCAP_MASK for AT_SECURE programs (swbz#21209)
|
||||
- Correct collation rules for Malayalam (swbz#19922, swbz#19919)
|
||||
- fork: Remove bogus parent PID assertions (swbz#21386)
|
||||
|
||||
* Mon Jun 05 2017 Arjun Shankar <arjun.is@lostca.se> - 2.25-5
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit 34b6f41c14d09fe627c6a6224880d76d0959079e, fixing:
|
||||
- Fix test-math-vector-sincos.h aliasing (ffe308e)
|
||||
|
||||
* Thu Mar 02 2017 Florian Weimer <fweimer@redhat.com> - 2.25-4
|
||||
- Auto-sync with upstream release/2.25/master,
|
||||
commit 69e0a87cc4c570e3b7218392fc3e743b5bddcce2, fixing:
|
||||
- Build all DSOs with BIND_NOW (#1406731)
|
||||
|
||||
* Wed Mar 1 2017 Jakub Hrozek <jhrozek@redhat.com> - 2.25-3
|
||||
- NSS: Prefer sss service for passwd, group databases (#1427646)
|
||||
|
||||
|
|
2
sources
2
sources
|
@ -1 +1 @@
|
|||
SHA512 (glibc-2.25-3-g93cf93e.tar.gz) = 2fc0b4e1edade43ba7cd59a6eff0eb77058a742ae6b112e76ddde7c5ac951d361f5da74f7cf1bf5b404e1ca1439609cc49a26a2cd2143bec008ffbf2aecafd51
|
||||
SHA512 (glibc-2.25-123-gedcf13e25c.tar.gz) = b9eb5ae4c2f1f26d5bc9a21e2f59e700cf5a3fe01501e19c5da762e92e493fd0da9476536b4e0724cb0751cb0cb6884d91a26c4a6a2c32a4d1154f5a30f4dbea
|
||||
|
|
Loading…
Reference in New Issue