Blame nss/getXXbyYY_r.c

Packit 6c4009
/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <atomic.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include "nsswitch.h"
Packit 6c4009
#include "sysdep.h"
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
# include <nscd/nscd_proto.h>
Packit 6c4009
#endif
Packit 6c4009
#ifdef NEED__RES
Packit 6c4009
# include <resolv/resolv_context.h>
Packit 6c4009
#endif
Packit 6c4009
/*******************************************************************\
Packit 6c4009
|* Here we assume several symbols to be defined:		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* LOOKUP_TYPE   - the return type of the function		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* FUNCTION_NAME - name of the non-reentrant function		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* DATABASE_NAME - name of the database the function accesses	   *|
Packit 6c4009
|*		   (e.g., host, services, ...)			   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* ADD_PARAMS    - additional parameters, can vary in number	   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* ADD_VARIABLES - names of additional parameters		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* Optionally the following vars can be defined:		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* EXTRA_PARAMS  - optional parameters, can vary in number	   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* EXTRA_VARIABLES - names of optional parameter		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* FUNCTION2_NAME - alternative name of the non-reentrant function *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* NEED_H_ERRNO  - an extra parameter will be passed to point to   *|
Packit 6c4009
|*		   the global `h_errno' variable.		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* NEED__RES     - obtain a struct resolv_context resolver context *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* PREPROCESS    - code run before anything else		   *|
Packit 6c4009
|*								   *|
Packit 6c4009
|* POSTPROCESS   - code run after the lookup			   *|
Packit 6c4009
|*								   *|
Packit 6c4009
\*******************************************************************/
Packit 6c4009
Packit 6c4009
/* To make the real sources a bit prettier.  */
Packit 6c4009
#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
Packit 6c4009
#ifdef FUNCTION2_NAME
Packit 6c4009
# define REENTRANT2_NAME APPEND_R (FUNCTION2_NAME)
Packit 6c4009
#else
Packit 6c4009
# define REENTRANT2_NAME NULL
Packit 6c4009
#endif
Packit 6c4009
#define APPEND_R(name) APPEND_R1 (name)
Packit 6c4009
#define APPEND_R1(name) name##_r
Packit 6c4009
#define INTERNAL(name) INTERNAL1 (name)
Packit 6c4009
#define INTERNAL1(name) __##name
Packit 6c4009
#define NEW(name) NEW1 (name)
Packit 6c4009
#define NEW1(name) __new_##name
Packit 6c4009
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
# define NSCD_NAME ADD_NSCD (REENTRANT_NAME)
Packit 6c4009
# define ADD_NSCD(name) ADD_NSCD1 (name)
Packit 6c4009
# define ADD_NSCD1(name) __nscd_##name
Packit 6c4009
# define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
Packit 6c4009
# define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
Packit 6c4009
# define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
Packit 6c4009
# define CONCAT2(arg1, arg2) CONCAT2_2 (arg1, arg2)
Packit 6c4009
# define CONCAT2_2(arg1, arg2) arg1##arg2
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
Packit 6c4009
#define REENTRANT_NAME_STRING STRINGIZE (REENTRANT_NAME)
Packit 6c4009
#ifdef FUNCTION2_NAME
Packit 6c4009
# define REENTRANT2_NAME_STRING STRINGIZE (REENTRANT2_NAME)
Packit 6c4009
#else
Packit 6c4009
# define REENTRANT2_NAME_STRING NULL
Packit 6c4009
#endif
Packit 6c4009
#define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
Packit 6c4009
#define STRINGIZE(name) STRINGIZE1 (name)
Packit 6c4009
#define STRINGIZE1(name) #name
Packit 6c4009
Packit 6c4009
#ifndef DB_LOOKUP_FCT
Packit 6c4009
# define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup2)
Packit 6c4009
# define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
Packit 6c4009
# define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Sometimes we need to store error codes in the `h_errno' variable.  */
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
# define H_ERRNO_PARM , int *h_errnop
Packit 6c4009
# define H_ERRNO_VAR , h_errnop
Packit 6c4009
# define H_ERRNO_VAR_P h_errnop
Packit 6c4009
#else
Packit 6c4009
# define H_ERRNO_PARM
Packit 6c4009
# define H_ERRNO_VAR
Packit 6c4009
# define H_ERRNO_VAR_P NULL
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef EXTRA_PARAMS
Packit 6c4009
# define EXTRA_PARAMS
Packit 6c4009
#endif
Packit 6c4009
#ifndef EXTRA_VARIABLES
Packit 6c4009
# define EXTRA_VARIABLES
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef HAVE_AF
Packit 6c4009
# define AF_VAL af
Packit 6c4009
#else
Packit 6c4009
# define AF_VAL AF_INET
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Set defaults for merge functions that haven't been defined.  */
Packit 6c4009
#ifndef DEEPCOPY_FN
Packit 6c4009
static inline int
Packit 6c4009
__copy_einval (LOOKUP_TYPE a,
Packit 6c4009
	       const size_t b,
Packit 6c4009
	       LOOKUP_TYPE *c,
Packit 6c4009
	       char *d,
Packit 6c4009
	       char **e)
Packit 6c4009
{
Packit 6c4009
  return EINVAL;
Packit 6c4009
}
Packit 6c4009
# define DEEPCOPY_FN __copy_einval
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef MERGE_FN
Packit 6c4009
static inline int
Packit 6c4009
__merge_einval (LOOKUP_TYPE *a,
Packit 6c4009
		char *b,
Packit 6c4009
		char *c,
Packit 6c4009
		size_t d,
Packit 6c4009
		LOOKUP_TYPE *e,
Packit 6c4009
		char *f)
Packit 6c4009
{
Packit 6c4009
  return EINVAL;
Packit 6c4009
}
Packit 6c4009
# define MERGE_FN __merge_einval
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#define CHECK_MERGE(err, status)		\
Packit 6c4009
  ({						\
Packit 6c4009
    do						\
Packit 6c4009
      {						\
Packit 6c4009
	if (err)				\
Packit 6c4009
	  {					\
Packit 6c4009
	    __set_errno (err);			\
Packit 6c4009
	    if (err == ERANGE)			\
Packit 6c4009
	      status = NSS_STATUS_TRYAGAIN;	\
Packit 6c4009
	    else				\
Packit 6c4009
	      status = NSS_STATUS_UNAVAIL;	\
Packit 6c4009
	    break;				\
Packit 6c4009
	  }					\
Packit 6c4009
      }						\
Packit 6c4009
    while (0);					\
Packit 6c4009
  })
Packit 6c4009
Packit 6c4009
/* Type of the lookup function we need here.  */
Packit 6c4009
typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
Packit 6c4009
					    size_t, int * H_ERRNO_PARM
Packit 6c4009
					    EXTRA_PARAMS);
Packit 6c4009
Packit 6c4009
/* The lookup function for the first entry of this service.  */
Packit 6c4009
extern int DB_LOOKUP_FCT (service_user **nip, const char *name,
Packit 6c4009
			  const char *name2, void **fctp);
Packit 6c4009
libc_hidden_proto (DB_LOOKUP_FCT)
Packit 6c4009
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
Packit 6c4009
			   size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM
Packit 6c4009
			   EXTRA_PARAMS)
Packit 6c4009
{
Packit 6c4009
  static bool startp_initialized;
Packit 6c4009
  static service_user *startp;
Packit 6c4009
  static lookup_function start_fct;
Packit 6c4009
  service_user *nip;
Packit 6c4009
  int do_merge = 0;
Packit 6c4009
  LOOKUP_TYPE mergegrp;
Packit 6c4009
  char *mergebuf = NULL;
Packit 6c4009
  char *endptr = NULL;
Packit 6c4009
  union
Packit 6c4009
  {
Packit 6c4009
    lookup_function l;
Packit 6c4009
    void *ptr;
Packit 6c4009
  } fct;
Packit 6c4009
  int no_more, err;
Packit 6c4009
  enum nss_status status = NSS_STATUS_UNAVAIL;
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
  int nscd_status;
Packit 6c4009
#endif
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
  bool any_service = false;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef NEED__RES
Packit 6c4009
  /* The HANDLE_DIGITS_DOTS case below already needs the resolver
Packit 6c4009
     configuration, so this has to happen early.  */
Packit 6c4009
  struct resolv_context *res_ctx = __resolv_context_get ();
Packit 6c4009
  if (res_ctx == NULL)
Packit 6c4009
    {
Packit 6c4009
      *h_errnop = NETDB_INTERNAL;
Packit 6c4009
      *result = NULL;
Packit 6c4009
      return errno;
Packit 6c4009
    }
Packit 6c4009
#endif /* NEED__RES */
Packit 6c4009
Packit 6c4009
#ifdef PREPROCESS
Packit 6c4009
  PREPROCESS;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef HANDLE_DIGITS_DOTS
Packit 6c4009
  switch (__nss_hostname_digits_dots (name, resbuf, &buffer, NULL,
Packit 6c4009
				      buflen, result, &status, AF_VAL,
Packit 6c4009
				      H_ERRNO_VAR_P))
Packit 6c4009
    {
Packit 6c4009
    case -1:
Packit 6c4009
# ifdef NEED__RES
Packit 6c4009
      __resolv_context_put (res_ctx);
Packit 6c4009
# endif
Packit 6c4009
      return errno;
Packit 6c4009
    case 1:
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
      any_service = true;
Packit 6c4009
#endif
Packit 6c4009
      goto done;
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
  if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
Packit 6c4009
    NOT_USENSCD_NAME = 0;
Packit 6c4009
Packit 6c4009
  if (!NOT_USENSCD_NAME
Packit 6c4009
      && !__nss_database_custom[CONCAT2 (NSS_DBSIDX_, DATABASE_NAME)])
Packit 6c4009
    {
Packit 6c4009
      nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result
Packit 6c4009
			       H_ERRNO_VAR);
Packit 6c4009
      if (nscd_status >= 0)
Packit 6c4009
	{
Packit 6c4009
# ifdef NEED__RES
Packit 6c4009
	  __resolv_context_put (res_ctx);
Packit 6c4009
# endif
Packit 6c4009
	  return nscd_status;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  if (! startp_initialized)
Packit 6c4009
    {
Packit 6c4009
      no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING,
Packit 6c4009
			       REENTRANT2_NAME_STRING, &fct.ptr);
Packit 6c4009
      if (no_more)
Packit 6c4009
	{
Packit 6c4009
	  void *tmp_ptr = (service_user *) -1l;
Packit 6c4009
#ifdef PTR_MANGLE
Packit 6c4009
	  PTR_MANGLE (tmp_ptr);
Packit 6c4009
#endif
Packit 6c4009
	  startp = tmp_ptr;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  void *tmp_ptr = fct.l;
Packit 6c4009
#ifdef PTR_MANGLE
Packit 6c4009
	  PTR_MANGLE (tmp_ptr);
Packit 6c4009
#endif
Packit 6c4009
	  start_fct = tmp_ptr;
Packit 6c4009
	  tmp_ptr = nip;
Packit 6c4009
#ifdef PTR_MANGLE
Packit 6c4009
	  PTR_MANGLE (tmp_ptr);
Packit 6c4009
#endif
Packit 6c4009
	  startp = tmp_ptr;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      /* Make sure start_fct and startp are written before
Packit 6c4009
	 startp_initialized.  */
Packit 6c4009
      atomic_write_barrier ();
Packit 6c4009
      startp_initialized = true;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      fct.l = start_fct;
Packit 6c4009
      nip = startp;
Packit 6c4009
#ifdef PTR_DEMANGLE
Packit 6c4009
      PTR_DEMANGLE (fct.l);
Packit 6c4009
      PTR_DEMANGLE (nip);
Packit 6c4009
#endif
Packit 6c4009
      no_more = nip == (service_user *) -1l;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  while (no_more == 0)
Packit 6c4009
    {
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
      any_service = true;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
      status = DL_CALL_FCT (fct.l, (ADD_VARIABLES, resbuf, buffer, buflen,
Packit 6c4009
				    &errno H_ERRNO_VAR EXTRA_VARIABLES));
Packit 6c4009
Packit 6c4009
      /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
Packit 6c4009
	 provided buffer is too small.  In this case we should give
Packit 6c4009
	 the user the possibility to enlarge the buffer and we should
Packit 6c4009
	 not simply go on with the next service (even if the TRYAGAIN
Packit 6c4009
	 action tells us so).  */
Packit 6c4009
      if (status == NSS_STATUS_TRYAGAIN
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
	  && *h_errnop == NETDB_INTERNAL
Packit 6c4009
#endif
Packit 6c4009
	  && errno == ERANGE)
Packit 6c4009
	break;
Packit 6c4009
Packit 6c4009
      if (do_merge)
Packit 6c4009
	{
Packit 6c4009
Packit 6c4009
	  if (status == NSS_STATUS_SUCCESS)
Packit 6c4009
	    {
Packit 6c4009
	      /* The previous loop saved a buffer for merging.
Packit 6c4009
		 Perform the merge now.  */
Packit 6c4009
	      err = MERGE_FN (&mergegrp, mergebuf, endptr, buflen, resbuf,
Packit 6c4009
			      buffer);
Packit 6c4009
	      CHECK_MERGE (err,status);
Packit 6c4009
	      do_merge = 0;
Packit 6c4009
	    }
Packit 6c4009
	  else
Packit 6c4009
	    {
Packit 6c4009
	      /* If the result wasn't SUCCESS, copy the saved buffer back
Packit 6c4009
	         into the result buffer and set the status back to
Packit 6c4009
	         NSS_STATUS_SUCCESS to match the previous pass through the
Packit 6c4009
	         loop.
Packit 6c4009
	          * If the next action is CONTINUE, it will overwrite the value
Packit 6c4009
	            currently in the buffer and return the new value.
Packit 6c4009
	          * If the next action is RETURN, we'll return the previously-
Packit 6c4009
	            acquired values.
Packit 6c4009
	          * If the next action is MERGE, then it will be added to the
Packit 6c4009
	            buffer saved from the previous source.  */
Packit 6c4009
	      err = DEEPCOPY_FN (mergegrp, buflen, resbuf, buffer, NULL);
Packit 6c4009
	      CHECK_MERGE (err, status);
Packit 6c4009
	      status = NSS_STATUS_SUCCESS;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      /* If we were are configured to merge this value with the next one,
Packit 6c4009
         save the current value of the group struct.  */
Packit 6c4009
      if (nss_next_action (nip, status) == NSS_ACTION_MERGE
Packit 6c4009
	  && status == NSS_STATUS_SUCCESS)
Packit 6c4009
	{
Packit 6c4009
	  /* Copy the current values into a buffer to be merged with the next
Packit 6c4009
	     set of retrieved values.  */
Packit 6c4009
	  if (mergebuf == NULL)
Packit 6c4009
	    {
Packit 6c4009
	      /* Only allocate once and reuse it for as many merges as we need
Packit 6c4009
	         to perform.  */
Packit 6c4009
	      mergebuf = malloc (buflen);
Packit 6c4009
	      if (mergebuf == NULL)
Packit 6c4009
		{
Packit 6c4009
		  __set_errno (ENOMEM);
Packit 6c4009
		  status = NSS_STATUS_UNAVAIL;
Packit 6c4009
		  break;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  err = DEEPCOPY_FN (*resbuf, buflen, &mergegrp, mergebuf, &endptr);
Packit 6c4009
	  CHECK_MERGE (err, status);
Packit 6c4009
	  do_merge = 1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      no_more = __nss_next2 (&nip, REENTRANT_NAME_STRING,
Packit 6c4009
			     REENTRANT2_NAME_STRING, &fct.ptr, status, 0);
Packit 6c4009
    }
Packit 6c4009
  free (mergebuf);
Packit 6c4009
  mergebuf = NULL;
Packit 6c4009
Packit 6c4009
#ifdef HANDLE_DIGITS_DOTS
Packit 6c4009
done:
Packit 6c4009
#endif
Packit 6c4009
  *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
  if (status == NSS_STATUS_UNAVAIL && !any_service && errno != ENOENT)
Packit 6c4009
    /* This happens when we weren't able to use a service for reasons other
Packit 6c4009
       than the module not being found.  In such a case, we'd want to tell the
Packit 6c4009
       caller that errno has the real reason for failure.  */
Packit 6c4009
    *h_errnop = NETDB_INTERNAL;
Packit 6c4009
  else if (status != NSS_STATUS_SUCCESS && !any_service)
Packit 6c4009
    /* We were not able to use any service.  */
Packit 6c4009
    *h_errnop = NO_RECOVERY;
Packit 6c4009
#endif
Packit 6c4009
#ifdef POSTPROCESS
Packit 6c4009
  POSTPROCESS;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef NEED__RES
Packit 6c4009
  /* This has to happen late because the POSTPROCESS stage above might
Packit 6c4009
     need the resolver context.  */
Packit 6c4009
  __resolv_context_put (res_ctx);
Packit 6c4009
#endif /* NEED__RES */
Packit 6c4009
Packit 6c4009
  int res;
Packit 6c4009
  if (status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
Packit 6c4009
    res = 0;
Packit 6c4009
  /* Don't pass back ERANGE if this is not for a too-small buffer.  */
Packit 6c4009
  else if (errno == ERANGE && status != NSS_STATUS_TRYAGAIN)
Packit 6c4009
    res = EINVAL;
Packit 6c4009
#ifdef NEED_H_ERRNO
Packit 6c4009
  /* These functions only set errno if h_errno is NETDB_INTERNAL.  */
Packit 6c4009
  else if (status == NSS_STATUS_TRYAGAIN && *h_errnop != NETDB_INTERNAL)
Packit 6c4009
    res = EAGAIN;
Packit 6c4009
#endif
Packit 6c4009
  else
Packit 6c4009
    return errno;
Packit 6c4009
Packit 6c4009
  __set_errno (res);
Packit 6c4009
  return res;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
#ifdef NO_COMPAT_NEEDED
Packit 6c4009
strong_alias (INTERNAL (REENTRANT_NAME), REENTRANT_NAME);
Packit 6c4009
#elif !defined FUNCTION2_NAME
Packit 6c4009
# include <shlib-compat.h>
Packit 6c4009
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1_2)
Packit 6c4009
#  define OLD(name) OLD1 (name)
Packit 6c4009
#  define OLD1(name) __old_##name
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
OLD (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
Packit 6c4009
		      size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
Packit 6c4009
{
Packit 6c4009
  int ret = INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, resbuf, buffer,
Packit 6c4009
				       buflen, result H_ERRNO_VAR);
Packit 6c4009
Packit 6c4009
  if (ret != 0 || result == NULL)
Packit 6c4009
    ret = -1;
Packit 6c4009
Packit 6c4009
  return ret;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#  define do_symbol_version(real, name, version) \
Packit 6c4009
  compat_symbol (libc, real, name, version)
Packit 6c4009
do_symbol_version (OLD (REENTRANT_NAME), REENTRANT_NAME, GLIBC_2_0);
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
/* As INTERNAL (REENTRANT_NAME) may be hidden, we need an alias
Packit 6c4009
   in between so that the REENTRANT_NAME@@GLIBC_2.1.2 is not
Packit 6c4009
   hidden too.  */
Packit 6c4009
strong_alias (INTERNAL (REENTRANT_NAME), NEW (REENTRANT_NAME));
Packit 6c4009
Packit 6c4009
# define do_default_symbol_version(real, name, version) \
Packit 6c4009
  versioned_symbol (libc, real, name, version)
Packit 6c4009
do_default_symbol_version (NEW (REENTRANT_NAME),
Packit 6c4009
			   REENTRANT_NAME, GLIBC_2_1_2);
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
nss_interface_function (REENTRANT_NAME)