Provide GLIBC_PRIVATE symbols no longer used by the current library
version to increase backwards compatibility during glibc updates.
This will help to avoid some of the issues that surface while a
glibc update is performed with concurrent application updates,
and it also allows old nscd to trigger cache invalidation in a
running nscd daemon.
While at this, also add interfaces for supporting old nss_dns modules.
This patch is not needed upstream because upstream does not provide
backwards compatibility for GLIBC_PRIVATE symbols.
diff --git a/inet/herrno.c b/inet/herrno.c
index 0cd84445190728b3..4d26e9b254181422 100644
--- a/inet/herrno.c
+++ b/inet/herrno.c
@@ -28,3 +28,9 @@ __thread int __h_errno;
extern __thread int __libc_h_errno __attribute__ ((alias ("__h_errno")))
attribute_hidden;
#define h_errno __libc_h_errno
+
+#ifdef SHARED
+/* Provide an alias for use by the old libpthread.so.0 during
+ updates. */
+asm (".symver __h_errno, h_errno@GLIBC_PRIVATE");
+#endif
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
index 9f2d3c3bd442bb38..5ab02c79c72eb1ac 100644
--- a/resolv/res_libc.c
+++ b/resolv/res_libc.c
@@ -41,6 +41,7 @@
#include <resolv.h>
#include <libc-lock.h>
#include <resolv-internal.h>
+#include <resolv_context.h>
int
res_init (void)
@@ -80,7 +81,34 @@ res_init (void)
return __res_vinit (&_res, 1);
}
-
+
+#ifdef SHARED
+
+/* An old nscd binary may bind to __res_maybe_init during a glibc
+ update. Emulate it using the new functions. Ignore PREINIT
+ because almost all existing __res_maybe_init callers used zero
+ PREINIT, and the difference for RESP == &_res is very minor (a
+ potential override of application configuration). */
+attribute_compat_text_section
+int
+__res_maybe_init (res_state resp, int preinit)
+{
+ if (resp == &_res)
+ {
+ /* This performs an implicit initialization of _res. */
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ return -1;
+ __resolv_context_put (ctx);
+ return 0;
+ }
+ else
+ return __res_vinit (resp, 0);
+}
+asm (".symver __res_maybe_init, __res_maybe_init@GLIBC_PRIVATE");
+
+#endif /* SHARED */
+
/* This needs to be after the use of _res in res_init, above. */
#undef _res
diff --git a/resolv/res_query.c b/resolv/res_query.c
index ebbe5a6a4ed86abe..24fefb561e7f1f5e 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -705,6 +705,96 @@ hostalias (const char *name)
(__resolv_context_get (), name, abuf, sizeof (abuf));
}
+#ifdef SHARED
+/* Compatibiliaty functions to support old nss_dns modules. */
+
+typedef int (*compat_query_function) (struct resolv_context *,
+ const char *name,
+ int class, int type,
+ u_char *answer,
+ int anslen,
+ u_char **answerp,
+ u_char **answerp2,
+ int *nanswerp2,
+ int *resplen2,
+ int *answerp2_malloced);
+
+attribute_compat_text_section
+static int
+wrap_compat_call (compat_query_function qf,
+ res_state statp,
+ 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 */
+ u_char **answerp, /* if buffer needs to be enlarged */
+ u_char **answerp2,
+ int *nanswerp2,
+ int *resplen2,
+ int *answerp2_malloced)
+{
+ if (statp == &_res)
+ {
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return -1;
+ }
+ int ret = qf (ctx, name, class, type,
+ answer, anslen, answerp, answerp2,
+ nanswerp2, resplen2, answerp2_malloced);
+ __resolv_context_put (ctx);
+ return ret;
+ }
+ else
+ {
+ __set_h_errno (NO_RECOVERY);
+ __set_errno (ENOTSUP);
+ return -1;
+ }
+}
+
+attribute_compat_text_section
+int
+__libc_res_nquery(res_state statp,
+ 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 */
+ u_char **answerp, /* if buffer needs to be enlarged */
+ u_char **answerp2,
+ int *nanswerp2,
+ int *resplen2,
+ int *answerp2_malloced)
+{
+ return wrap_compat_call (__res_context_query, statp, name, class, type,
+ answer, anslen, answerp, answerp2,
+ nanswerp2, resplen2, answerp2_malloced);
+}
+asm (".symver __libc_res_nquery, __libc_res_nquery@GLIBC_PRIVATE");
+
+attribute_compat_text_section
+int
+__libc_res_nsearch(res_state statp,
+ 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 */
+ u_char **answerp,
+ u_char **answerp2,
+ int *nanswerp2,
+ int *resplen2,
+ int *answerp2_malloced)
+{
+ return wrap_compat_call (__res_context_search, statp, name, class, type,
+ answer, anslen, answerp, answerp2,
+ nanswerp2, resplen2, answerp2_malloced);
+}
+asm (".symver __libc_res_nsearch, __libc_res_nsearch@GLIBC_PRIVATE");
+
+#endif /* SHARED */
+
#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
# undef res_query
# undef res_querydomain