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