hjl / source-git / glibc

Forked from source-git/glibc 3 years ago
Clone

Blame nis/ypclnt.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 Thorsten Kukuk <kukuk@suse.de>, 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 <errno.h>
Packit 6c4009
#include <fcntl.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <libintl.h>
Packit 6c4009
#include <rpc/rpc.h>
Packit 6c4009
#include <rpcsvc/nis.h>
Packit 6c4009
#include <rpcsvc/yp.h>
Packit 6c4009
#include <rpcsvc/ypclnt.h>
Packit 6c4009
#include <rpcsvc/ypupd.h>
Packit 6c4009
#include <sys/socket.h>
Packit 6c4009
#include <sys/uio.h>
Packit 6c4009
#include <libc-lock.h>
Packit 6c4009
#include <shlib-compat.h>
Packit 6c4009
Packit 6c4009
/* This should only be defined on systems with a BSD compatible ypbind */
Packit 6c4009
#ifndef BINDINGDIR
Packit 6c4009
# define BINDINGDIR "/var/yp/binding"
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
struct dom_binding
Packit 6c4009
  {
Packit 6c4009
    struct dom_binding *dom_pnext;
Packit 6c4009
    char dom_domain[YPMAXDOMAIN + 1];
Packit 6c4009
    struct sockaddr_in dom_server_addr;
Packit 6c4009
    int dom_socket;
Packit 6c4009
    CLIENT *dom_client;
Packit 6c4009
  };
Packit 6c4009
typedef struct dom_binding dom_binding;
Packit 6c4009
Packit 6c4009
static const struct timeval RPCTIMEOUT = {25, 0};
Packit 6c4009
static const struct timeval UDPTIMEOUT = {5, 0};
Packit 6c4009
static int const MAXTRIES = 2;
Packit 6c4009
static char ypdomainname[NIS_MAXNAMELEN + 1];
Packit 6c4009
__libc_lock_define_initialized (static, ypbindlist_lock)
Packit 6c4009
static dom_binding *ypbindlist = NULL;
Packit 6c4009
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
yp_bind_client_create (const char *domain, dom_binding *ysd,
Packit 6c4009
		       struct ypbind_resp *ypbr)
Packit 6c4009
{
Packit 6c4009
  ysd->dom_server_addr.sin_family = AF_INET;
Packit 6c4009
  memcpy (&ysd->dom_server_addr.sin_port,
Packit 6c4009
	  ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
Packit 6c4009
	  sizeof (ysd->dom_server_addr.sin_port));
Packit 6c4009
  memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
Packit 6c4009
	  ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
Packit 6c4009
	  sizeof (ysd->dom_server_addr.sin_addr.s_addr));
Packit 6c4009
  strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
Packit 6c4009
  ysd->dom_domain[YPMAXDOMAIN] = '\0';
Packit 6c4009
Packit 6c4009
  ysd->dom_socket = RPC_ANYSOCK;
Packit 6c4009
  ysd->dom_client = __libc_clntudp_bufcreate (&ysd->dom_server_addr, YPPROG,
Packit 6c4009
					      YPVERS, UDPTIMEOUT,
Packit 6c4009
					      &ysd->dom_socket,
Packit 6c4009
					      UDPMSGSIZE, UDPMSGSIZE,
Packit 6c4009
					      SOCK_CLOEXEC);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#if USE_BINDINGDIR
Packit 6c4009
static void
Packit 6c4009
yp_bind_file (const char *domain, dom_binding *ysd)
Packit 6c4009
{
Packit 6c4009
  char path[sizeof (BINDINGDIR) + strlen (domain) + 3 * sizeof (unsigned) + 3];
Packit 6c4009
Packit 6c4009
  snprintf (path, sizeof (path), "%s/%s.%u", BINDINGDIR, domain, YPBINDVERS);
Packit 6c4009
  int fd = open (path, O_RDONLY);
Packit 6c4009
  if (fd >= 0)
Packit 6c4009
    {
Packit 6c4009
      /* We have a binding file and could save a RPC call.  The file
Packit 6c4009
	 contains a port number and the YPBIND_RESP record.  The port
Packit 6c4009
	 number (16 bits) can be ignored.  */
Packit 6c4009
      struct ypbind_resp ypbr;
Packit 6c4009
Packit 6c4009
      if (pread (fd, &ypbr, sizeof (ypbr), 2) == sizeof (ypbr))
Packit 6c4009
	yp_bind_client_create (domain, ysd, &ypbr);
Packit 6c4009
Packit 6c4009
      close (fd);
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
Packit 6c4009
{
Packit 6c4009
  struct sockaddr_in clnt_saddr;
Packit 6c4009
  struct ypbind_resp ypbr;
Packit 6c4009
  int clnt_sock;
Packit 6c4009
  CLIENT *client;
Packit 6c4009
Packit 6c4009
  clnt_saddr.sin_family = AF_INET;
Packit 6c4009
  clnt_saddr.sin_port = 0;
Packit 6c4009
  clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
Packit 6c4009
  clnt_sock = RPC_ANYSOCK;
Packit 6c4009
  client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
Packit 6c4009
			   &clnt_sock, 0, 0);
Packit 6c4009
  if (client == NULL)
Packit 6c4009
    return YPERR_YPBIND;
Packit 6c4009
Packit 6c4009
  /* Check the port number -- should be < IPPORT_RESERVED.
Packit 6c4009
     If not, it's possible someone has registered a bogus
Packit 6c4009
     ypbind with the portmapper and is trying to trick us. */
Packit 6c4009
  if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
Packit 6c4009
    {
Packit 6c4009
      clnt_destroy (client);
Packit 6c4009
      return YPERR_YPBIND;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (clnt_call (client, YPBINDPROC_DOMAIN,
Packit 6c4009
		 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
Packit 6c4009
		 (xdrproc_t) xdr_ypbind_resp,
Packit 6c4009
		 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
Packit 6c4009
    {
Packit 6c4009
      clnt_destroy (client);
Packit 6c4009
      return YPERR_YPBIND;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  clnt_destroy (client);
Packit 6c4009
Packit 6c4009
  if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
Packit 6c4009
    {
Packit 6c4009
      fprintf (stderr, "YPBINDPROC_DOMAIN: %s\n",
Packit 6c4009
	       ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
Packit 6c4009
      return YPERR_DOMAIN;
Packit 6c4009
    }
Packit 6c4009
  memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
Packit 6c4009
Packit 6c4009
  yp_bind_client_create (domain, ysd, &ypbr);
Packit 6c4009
Packit 6c4009
  return YPERR_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
__yp_bind (const char *domain, dom_binding **ypdb)
Packit 6c4009
{
Packit 6c4009
  dom_binding *ysd = NULL;
Packit 6c4009
  int is_new = 0;
Packit 6c4009
Packit 6c4009
  if (domain == NULL || domain[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  ysd = *ypdb;
Packit 6c4009
  while (ysd != NULL)
Packit 6c4009
    {
Packit 6c4009
      if (strcmp (domain, ysd->dom_domain) == 0)
Packit 6c4009
	break;
Packit 6c4009
      ysd = ysd->dom_pnext;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (ysd == NULL)
Packit 6c4009
    {
Packit 6c4009
      is_new = 1;
Packit 6c4009
      ysd = (dom_binding *) calloc (1, sizeof *ysd);
Packit 6c4009
      if (__glibc_unlikely (ysd == NULL))
Packit 6c4009
	return YPERR_RESRC;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#if USE_BINDINGDIR
Packit 6c4009
  /* Try binding dir at first if we have no binding */
Packit 6c4009
  if (ysd->dom_client == NULL)
Packit 6c4009
    yp_bind_file (domain, ysd);
Packit 6c4009
#endif /* USE_BINDINGDIR */
Packit 6c4009
Packit 6c4009
  if (ysd->dom_client == NULL)
Packit 6c4009
    {
Packit 6c4009
      int retval = yp_bind_ypbindprog (domain, ysd);
Packit 6c4009
      if (retval != YPERR_SUCCESS)
Packit 6c4009
	{
Packit 6c4009
	  if (is_new)
Packit 6c4009
	    free (ysd);
Packit 6c4009
	  return retval;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (ysd->dom_client == NULL)
Packit 6c4009
    {
Packit 6c4009
      if (is_new)
Packit 6c4009
	free (ysd);
Packit 6c4009
      return YPERR_YPSERV;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (is_new)
Packit 6c4009
    {
Packit 6c4009
      ysd->dom_pnext = *ypdb;
Packit 6c4009
      *ypdb = ysd;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return YPERR_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
__yp_unbind (dom_binding *ydb)
Packit 6c4009
{
Packit 6c4009
  clnt_destroy (ydb->dom_client);
Packit 6c4009
  free (ydb);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_bind (const char *indomain)
Packit 6c4009
{
Packit 6c4009
  int status;
Packit 6c4009
Packit 6c4009
  __libc_lock_lock (ypbindlist_lock);
Packit 6c4009
Packit 6c4009
  status = __yp_bind (indomain, &ypbindlist);
Packit 6c4009
Packit 6c4009
  __libc_lock_unlock (ypbindlist_lock);
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (yp_bind, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
yp_unbind_locked (const char *indomain)
Packit 6c4009
{
Packit 6c4009
  dom_binding *ydbptr, *ydbptr2;
Packit 6c4009
Packit 6c4009
  ydbptr2 = NULL;
Packit 6c4009
  ydbptr = ypbindlist;
Packit 6c4009
Packit 6c4009
  while (ydbptr != NULL)
Packit 6c4009
    {
Packit 6c4009
      if (strcmp (ydbptr->dom_domain, indomain) == 0)
Packit 6c4009
	{
Packit 6c4009
	  dom_binding *work;
Packit 6c4009
Packit 6c4009
	  work = ydbptr;
Packit 6c4009
	  if (ydbptr2 == NULL)
Packit 6c4009
	    ypbindlist = ypbindlist->dom_pnext;
Packit 6c4009
	  else
Packit 6c4009
	    ydbptr2 = ydbptr->dom_pnext;
Packit 6c4009
	  __yp_unbind (work);
Packit 6c4009
	  break;
Packit 6c4009
	}
Packit 6c4009
      ydbptr2 = ydbptr;
Packit 6c4009
      ydbptr = ydbptr->dom_pnext;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
yp_unbind (const char *indomain)
Packit 6c4009
{
Packit 6c4009
  __libc_lock_lock (ypbindlist_lock);
Packit 6c4009
Packit 6c4009
  yp_unbind_locked (indomain);
Packit 6c4009
Packit 6c4009
  __libc_lock_unlock (ypbindlist_lock);
Packit 6c4009
Packit 6c4009
  return;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yp_unbind, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
__ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
Packit 6c4009
	       caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
Packit 6c4009
	       int print_error)
Packit 6c4009
{
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  result = clnt_call ((*ydb)->dom_client, prog,
Packit 6c4009
		      xargs, req, xres, resp, RPCTIMEOUT);
Packit 6c4009
Packit 6c4009
  if (result != RPC_SUCCESS)
Packit 6c4009
    {
Packit 6c4009
      /* We don't print an error message, if we try our old,
Packit 6c4009
	 cached data. Only print this for data, which should work.  */
Packit 6c4009
      if (print_error)
Packit 6c4009
	clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
Packit 6c4009
Packit 6c4009
      return YPERR_RPC;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return YPERR_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
Packit 6c4009
	   caddr_t req, xdrproc_t xres, caddr_t resp)
Packit 6c4009
{
Packit 6c4009
  dom_binding *ydb;
Packit 6c4009
  int status;
Packit 6c4009
  int saved_errno = errno;
Packit 6c4009
Packit 6c4009
  status = YPERR_YPERR;
Packit 6c4009
Packit 6c4009
  __libc_lock_lock (ypbindlist_lock);
Packit 6c4009
  ydb = ypbindlist;
Packit 6c4009
  while (ydb != NULL)
Packit 6c4009
    {
Packit 6c4009
      if (strcmp (domain, ydb->dom_domain) == 0)
Packit 6c4009
	{
Packit 6c4009
          if (__yp_bind (domain, &ydb) == 0)
Packit 6c4009
	    {
Packit 6c4009
	      /* Call server, print no error message, do not unbind.  */
Packit 6c4009
	      status = __ypclnt_call (domain, prog, xargs, req, xres,
Packit 6c4009
				      resp, &ydb, 0);
Packit 6c4009
	      if (status == YPERR_SUCCESS)
Packit 6c4009
	        {
Packit 6c4009
		  __libc_lock_unlock (ypbindlist_lock);
Packit 6c4009
	          __set_errno (saved_errno);
Packit 6c4009
	          return status;
Packit 6c4009
	        }
Packit 6c4009
	    }
Packit 6c4009
	  /* We use ypbindlist, and the old cached data is
Packit 6c4009
	     invalid. unbind now and create a new binding */
Packit 6c4009
	  yp_unbind_locked (domain);
Packit 6c4009
Packit 6c4009
	  break;
Packit 6c4009
	}
Packit 6c4009
      ydb = ydb->dom_pnext;
Packit 6c4009
    }
Packit 6c4009
  __libc_lock_unlock (ypbindlist_lock);
Packit 6c4009
Packit 6c4009
  /* First try with cached data failed. Now try to get
Packit 6c4009
     current data from the system.  */
Packit 6c4009
  ydb = NULL;
Packit 6c4009
  if (__yp_bind (domain, &ydb) == 0)
Packit 6c4009
    {
Packit 6c4009
      status = __ypclnt_call (domain, prog, xargs, req, xres,
Packit 6c4009
			      resp, &ydb, 1);
Packit 6c4009
      __yp_unbind (ydb);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#if USE_BINDINGDIR
Packit 6c4009
  /* If we support binding dir data, we have a third chance:
Packit 6c4009
     Ask ypbind.  */
Packit 6c4009
  if (status != YPERR_SUCCESS)
Packit 6c4009
    {
Packit 6c4009
      ydb = calloc (1, sizeof (dom_binding));
Packit 6c4009
      if (ydb != NULL && yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
Packit 6c4009
	{
Packit 6c4009
	  status = __ypclnt_call (domain, prog, xargs, req, xres,
Packit 6c4009
				  resp, &ydb, 1);
Packit 6c4009
	  __yp_unbind (ydb);
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	free (ydb);
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  __set_errno (saved_errno);
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Like do_ypcall, but translate the status value if necessary.  */
Packit 6c4009
static int
Packit 6c4009
do_ypcall_tr (const char *domain, u_long prog, xdrproc_t xargs,
Packit 6c4009
	      caddr_t req, xdrproc_t xres, caddr_t resp)
Packit 6c4009
{
Packit 6c4009
  int status = do_ypcall (domain, prog, xargs, req, xres, resp);
Packit 6c4009
  if (status == YPERR_SUCCESS)
Packit 6c4009
    /* We cast to ypresp_val although the pointer could also be of
Packit 6c4009
       type ypresp_key_val or ypresp_master or ypresp_order or
Packit 6c4009
       ypresp_maplist.  But the stat element is in a common prefix so
Packit 6c4009
       this does not matter.  */
Packit 6c4009
    status = ypprot_err (((struct ypresp_val *) resp)->stat);
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
__libc_lock_define_initialized (static, domainname_lock)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_get_default_domain (char **outdomain)
Packit 6c4009
{
Packit 6c4009
  int result = YPERR_SUCCESS;;
Packit 6c4009
  *outdomain = NULL;
Packit 6c4009
Packit 6c4009
  __libc_lock_lock (domainname_lock);
Packit 6c4009
Packit 6c4009
  if (ypdomainname[0] == '\0')
Packit 6c4009
    {
Packit 6c4009
      if (getdomainname (ypdomainname, NIS_MAXNAMELEN))
Packit 6c4009
	result = YPERR_NODOM;
Packit 6c4009
      else if (strcmp (ypdomainname, "(none)") == 0)
Packit 6c4009
	{
Packit 6c4009
	  /* If domainname is not set, some systems will return "(none)" */
Packit 6c4009
	  ypdomainname[0] = '\0';
Packit 6c4009
	  result = YPERR_NODOM;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	*outdomain = ypdomainname;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    *outdomain = ypdomainname;
Packit 6c4009
Packit 6c4009
  __libc_lock_unlock (domainname_lock);
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (yp_get_default_domain, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
__yp_check (char **domain)
Packit 6c4009
{
Packit 6c4009
  char *unused;
Packit 6c4009
Packit 6c4009
  if (ypdomainname[0] == '\0')
Packit 6c4009
    if (yp_get_default_domain (&unused))
Packit 6c4009
      return 0;
Packit 6c4009
Packit 6c4009
  if (domain)
Packit 6c4009
    *domain = ypdomainname;
Packit 6c4009
Packit 6c4009
  if (yp_bind (ypdomainname) == 0)
Packit 6c4009
    return 1;
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(__yp_check, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_match (const char *indomain, const char *inmap, const char *inkey,
Packit 6c4009
	  const int inkeylen, char **outval, int *outvallen)
Packit 6c4009
{
Packit 6c4009
  ypreq_key req;
Packit 6c4009
  ypresp_val resp;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0' ||
Packit 6c4009
      inmap == NULL || inmap[0] == '\0' ||
Packit 6c4009
      inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  req.domain = (char *) indomain;
Packit 6c4009
  req.map = (char *) inmap;
Packit 6c4009
  req.key.keydat_val = (char *) inkey;
Packit 6c4009
  req.key.keydat_len = inkeylen;
Packit 6c4009
Packit 6c4009
  *outval = NULL;
Packit 6c4009
  *outvallen = 0;
Packit 6c4009
  memset (&resp, '\0', sizeof (resp));
Packit 6c4009
Packit 6c4009
  result = do_ypcall_tr (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
Packit 6c4009
			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_val,
Packit 6c4009
			 (caddr_t) &resp);
Packit 6c4009
Packit 6c4009
  if (result != YPERR_SUCCESS)
Packit 6c4009
    return result;
Packit 6c4009
Packit 6c4009
  *outvallen = resp.val.valdat_len;
Packit 6c4009
  *outval = malloc (*outvallen + 1);
Packit 6c4009
  int status = YPERR_RESRC;
Packit 6c4009
  if (__glibc_likely (*outval != NULL))
Packit 6c4009
    {
Packit 6c4009
      memcpy (*outval, resp.val.valdat_val, *outvallen);
Packit 6c4009
      (*outval)[*outvallen] = '\0';
Packit 6c4009
      status = YPERR_SUCCESS;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yp_match, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_first (const char *indomain, const char *inmap, char **outkey,
Packit 6c4009
	  int *outkeylen, char **outval, int *outvallen)
Packit 6c4009
{
Packit 6c4009
  ypreq_nokey req;
Packit 6c4009
  ypresp_key_val resp;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0' ||
Packit 6c4009
      inmap == NULL || inmap[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  req.domain = (char *) indomain;
Packit 6c4009
  req.map = (char *) inmap;
Packit 6c4009
Packit 6c4009
  *outkey = *outval = NULL;
Packit 6c4009
  *outkeylen = *outvallen = 0;
Packit 6c4009
  memset (&resp, '\0', sizeof (resp));
Packit 6c4009
Packit 6c4009
  result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
Packit 6c4009
		      (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
Packit 6c4009
		      (caddr_t) &resp);
Packit 6c4009
Packit 6c4009
  if (result != RPC_SUCCESS)
Packit 6c4009
    return YPERR_RPC;
Packit 6c4009
  if (resp.stat != YP_TRUE)
Packit 6c4009
    return ypprot_err (resp.stat);
Packit 6c4009
Packit 6c4009
  int status;
Packit 6c4009
  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
Packit 6c4009
			&& (*outval = malloc (resp.val.valdat_len
Packit 6c4009
					      + 1)) != NULL, 1))
Packit 6c4009
    {
Packit 6c4009
      *outkeylen = resp.key.keydat_len;
Packit 6c4009
      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
Packit 6c4009
      (*outkey)[*outkeylen] = '\0';
Packit 6c4009
Packit 6c4009
      *outvallen = resp.val.valdat_len;
Packit 6c4009
      memcpy (*outval, resp.val.valdat_val, *outvallen);
Packit 6c4009
      (*outval)[*outvallen] = '\0';
Packit 6c4009
Packit 6c4009
      status = YPERR_SUCCESS;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      free (*outkey);
Packit 6c4009
      status = YPERR_RESRC;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yp_first, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_next (const char *indomain, const char *inmap, const char *inkey,
Packit 6c4009
	 const int inkeylen, char **outkey, int *outkeylen, char **outval,
Packit 6c4009
	 int *outvallen)
Packit 6c4009
{
Packit 6c4009
  ypreq_key req;
Packit 6c4009
  ypresp_key_val resp;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0' ||
Packit 6c4009
      inmap == NULL || inmap[0] == '\0' ||
Packit 6c4009
      inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  req.domain = (char *) indomain;
Packit 6c4009
  req.map = (char *) inmap;
Packit 6c4009
  req.key.keydat_val = (char *) inkey;
Packit 6c4009
  req.key.keydat_len = inkeylen;
Packit 6c4009
Packit 6c4009
  *outkey = *outval = NULL;
Packit 6c4009
  *outkeylen = *outvallen = 0;
Packit 6c4009
  memset (&resp, '\0', sizeof (resp));
Packit 6c4009
Packit 6c4009
  result = do_ypcall_tr (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
Packit 6c4009
			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
Packit 6c4009
			 (caddr_t) &resp);
Packit 6c4009
Packit 6c4009
  if (result != YPERR_SUCCESS)
Packit 6c4009
    return result;
Packit 6c4009
Packit 6c4009
  int status;
Packit 6c4009
  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
Packit 6c4009
			&& (*outval = malloc (resp.val.valdat_len
Packit 6c4009
					      + 1)) != NULL, 1))
Packit 6c4009
    {
Packit 6c4009
      *outkeylen = resp.key.keydat_len;
Packit 6c4009
      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
Packit 6c4009
      (*outkey)[*outkeylen] = '\0';
Packit 6c4009
Packit 6c4009
      *outvallen = resp.val.valdat_len;
Packit 6c4009
      memcpy (*outval, resp.val.valdat_val, *outvallen);
Packit 6c4009
      (*outval)[*outvallen] = '\0';
Packit 6c4009
Packit 6c4009
      status = YPERR_SUCCESS;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      free (*outkey);
Packit 6c4009
      status = YPERR_RESRC;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yp_next, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_master (const char *indomain, const char *inmap, char **outname)
Packit 6c4009
{
Packit 6c4009
  ypreq_nokey req;
Packit 6c4009
  ypresp_master resp;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0' ||
Packit 6c4009
      inmap == NULL || inmap[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  req.domain = (char *) indomain;
Packit 6c4009
  req.map = (char *) inmap;
Packit 6c4009
Packit 6c4009
  memset (&resp, '\0', sizeof (ypresp_master));
Packit 6c4009
Packit 6c4009
  result = do_ypcall_tr (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
Packit 6c4009
			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_master,
Packit 6c4009
			 (caddr_t) &resp);
Packit 6c4009
Packit 6c4009
  if (result != YPERR_SUCCESS)
Packit 6c4009
    return result;
Packit 6c4009
Packit 6c4009
  *outname = strdup (resp.peer);
Packit 6c4009
  xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
Packit 6c4009
Packit 6c4009
  return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (yp_master, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
Packit 6c4009
{
Packit 6c4009
  struct ypreq_nokey req;
Packit 6c4009
  struct ypresp_order resp;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0' ||
Packit 6c4009
      inmap == NULL || inmap[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  req.domain = (char *) indomain;
Packit 6c4009
  req.map = (char *) inmap;
Packit 6c4009
Packit 6c4009
  memset (&resp, '\0', sizeof (resp));
Packit 6c4009
Packit 6c4009
  result = do_ypcall_tr (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
Packit 6c4009
			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_order,
Packit 6c4009
			 (caddr_t) &resp);
Packit 6c4009
Packit 6c4009
  if (result != YPERR_SUCCESS)
Packit 6c4009
    return result;
Packit 6c4009
Packit 6c4009
  *outorder = resp.ordernum;
Packit 6c4009
  xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yp_order, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
struct ypresp_all_data
Packit 6c4009
{
Packit 6c4009
  unsigned long status;
Packit 6c4009
  void *data;
Packit 6c4009
  int (*foreach) (int status, char *key, int keylen,
Packit 6c4009
		  char *val, int vallen, char *data);
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static bool_t
Packit 6c4009
__xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
Packit 6c4009
{
Packit 6c4009
  while (1)
Packit 6c4009
    {
Packit 6c4009
      struct ypresp_all resp;
Packit 6c4009
Packit 6c4009
      memset (&resp, '\0', sizeof (struct ypresp_all));
Packit 6c4009
      if (!xdr_ypresp_all (xdrs, &resp))
Packit 6c4009
	{
Packit 6c4009
	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
Packit 6c4009
	  objp->status = YP_YPERR;
Packit 6c4009
	  return FALSE;
Packit 6c4009
	}
Packit 6c4009
      if (resp.more == 0)
Packit 6c4009
	{
Packit 6c4009
	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
Packit 6c4009
	  objp->status = YP_NOMORE;
Packit 6c4009
	  return TRUE;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      switch (resp.ypresp_all_u.val.stat)
Packit 6c4009
	{
Packit 6c4009
	case YP_TRUE:
Packit 6c4009
	  {
Packit 6c4009
	    char key[resp.ypresp_all_u.val.key.keydat_len + 1];
Packit 6c4009
	    char val[resp.ypresp_all_u.val.val.valdat_len + 1];
Packit 6c4009
	    int keylen = resp.ypresp_all_u.val.key.keydat_len;
Packit 6c4009
	    int vallen = resp.ypresp_all_u.val.val.valdat_len;
Packit 6c4009
Packit 6c4009
	    /* We are not allowed to modify the key and val data.
Packit 6c4009
	       But we are allowed to add data behind the buffer,
Packit 6c4009
	       if we don't modify the length. So add an extra NUL
Packit 6c4009
	       character to avoid trouble with broken code. */
Packit 6c4009
	    objp->status = YP_TRUE;
Packit 6c4009
	    *((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val,
Packit 6c4009
				  keylen)) = '\0';
Packit 6c4009
	    *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
Packit 6c4009
				  vallen)) = '\0';
Packit 6c4009
	    xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
Packit 6c4009
	    if ((*objp->foreach) (objp->status, key, keylen,
Packit 6c4009
				  val, vallen, objp->data))
Packit 6c4009
	      return TRUE;
Packit 6c4009
	  }
Packit 6c4009
	  break;
Packit 6c4009
	default:
Packit 6c4009
	  objp->status = resp.ypresp_all_u.val.stat;
Packit 6c4009
	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
Packit 6c4009
	  /* Sun says we don't need to make this call, but must return
Packit 6c4009
	     immediately. Since Solaris makes this call, we will call
Packit 6c4009
	     the callback function, too. */
Packit 6c4009
	  (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
Packit 6c4009
	  return TRUE;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_all (const char *indomain, const char *inmap,
Packit 6c4009
	const struct ypall_callback *incallback)
Packit 6c4009
{
Packit 6c4009
  struct ypreq_nokey req;
Packit 6c4009
  dom_binding *ydb = NULL;
Packit 6c4009
  int try, res;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
  struct sockaddr_in clnt_sin;
Packit 6c4009
  CLIENT *clnt;
Packit 6c4009
  struct ypresp_all_data data;
Packit 6c4009
  int clnt_sock;
Packit 6c4009
  int saved_errno = errno;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0'
Packit 6c4009
      || inmap == NULL || inmap[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  try = 0;
Packit 6c4009
  res = YPERR_YPERR;
Packit 6c4009
Packit 6c4009
  while (try < MAXTRIES && res != YPERR_SUCCESS)
Packit 6c4009
    {
Packit 6c4009
      if (__yp_bind (indomain, &ydb) != 0)
Packit 6c4009
	{
Packit 6c4009
	  __set_errno (saved_errno);
Packit 6c4009
	  return YPERR_DOMAIN;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      clnt_sock = RPC_ANYSOCK;
Packit 6c4009
      clnt_sin = ydb->dom_server_addr;
Packit 6c4009
      clnt_sin.sin_port = 0;
Packit 6c4009
Packit 6c4009
      /* We don't need the UDP connection anymore.  */
Packit 6c4009
      __yp_unbind (ydb);
Packit 6c4009
      ydb = NULL;
Packit 6c4009
Packit 6c4009
      clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
Packit 6c4009
      if (clnt == NULL)
Packit 6c4009
	{
Packit 6c4009
	  __set_errno (saved_errno);
Packit 6c4009
	  return YPERR_PMAP;
Packit 6c4009
	}
Packit 6c4009
      req.domain = (char *) indomain;
Packit 6c4009
      req.map = (char *) inmap;
Packit 6c4009
Packit 6c4009
      data.foreach = incallback->foreach;
Packit 6c4009
      data.data = (void *) incallback->data;
Packit 6c4009
Packit 6c4009
      result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
Packit 6c4009
			  (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
Packit 6c4009
			  (caddr_t) &data, RPCTIMEOUT);
Packit 6c4009
Packit 6c4009
      if (__glibc_unlikely (result != RPC_SUCCESS))
Packit 6c4009
	{
Packit 6c4009
	  /* Print the error message only on the last try.  */
Packit 6c4009
	  if (try == MAXTRIES - 1)
Packit 6c4009
	    clnt_perror (clnt, "yp_all: clnt_call");
Packit 6c4009
	  res = YPERR_RPC;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	res = YPERR_SUCCESS;
Packit 6c4009
Packit 6c4009
      clnt_destroy (clnt);
Packit 6c4009
Packit 6c4009
      if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
Packit 6c4009
	{
Packit 6c4009
	  __set_errno (saved_errno);
Packit 6c4009
	  return ypprot_err (data.status);
Packit 6c4009
	}
Packit 6c4009
      ++try;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  __set_errno (saved_errno);
Packit 6c4009
Packit 6c4009
  return res;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (yp_all, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
Packit 6c4009
{
Packit 6c4009
  struct ypresp_maplist resp;
Packit 6c4009
  enum clnt_stat result;
Packit 6c4009
Packit 6c4009
  if (indomain == NULL || indomain[0] == '\0')
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  memset (&resp, '\0', sizeof (resp));
Packit 6c4009
Packit 6c4009
  result = do_ypcall_tr (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
Packit 6c4009
			 (caddr_t) &indomain, (xdrproc_t) xdr_ypresp_maplist,
Packit 6c4009
			 (caddr_t) &resp);
Packit 6c4009
Packit 6c4009
  if (__glibc_likely (result == YPERR_SUCCESS))
Packit 6c4009
    {
Packit 6c4009
      *outmaplist = resp.maps;
Packit 6c4009
      /* We don't free the list, this will be done by ypserv
Packit 6c4009
	 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (yp_maplist, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
const char *
Packit 6c4009
yperr_string (const int error)
Packit 6c4009
{
Packit 6c4009
  const char *str;
Packit 6c4009
  switch (error)
Packit 6c4009
    {
Packit 6c4009
    case YPERR_SUCCESS:
Packit 6c4009
      str = N_("Success");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_BADARGS:
Packit 6c4009
      str = N_("Request arguments bad");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_RPC:
Packit 6c4009
      str = N_("RPC failure on NIS operation");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_DOMAIN:
Packit 6c4009
      str = N_("Can't bind to server which serves this domain");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_MAP:
Packit 6c4009
      str = N_("No such map in server's domain");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_KEY:
Packit 6c4009
      str = N_("No such key in map");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_YPERR:
Packit 6c4009
      str = N_("Internal NIS error");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_RESRC:
Packit 6c4009
      str = N_("Local resource allocation failure");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_NOMORE:
Packit 6c4009
      str = N_("No more records in map database");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_PMAP:
Packit 6c4009
      str = N_("Can't communicate with portmapper");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_YPBIND:
Packit 6c4009
      str = N_("Can't communicate with ypbind");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_YPSERV:
Packit 6c4009
      str = N_("Can't communicate with ypserv");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_NODOM:
Packit 6c4009
      str = N_("Local domain name not set");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_BADDB:
Packit 6c4009
      str = N_("NIS map database is bad");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_VERS:
Packit 6c4009
      str = N_("NIS client/server version mismatch - can't supply service");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_ACCESS:
Packit 6c4009
      str = N_("Permission denied");
Packit 6c4009
      break;
Packit 6c4009
    case YPERR_BUSY:
Packit 6c4009
      str = N_("Database is busy");
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      str = N_("Unknown NIS error code");
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
  return _(str);
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yperr_string, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
static const int8_t yp_2_yperr[] =
Packit 6c4009
  {
Packit 6c4009
#define YP2YPERR(yp, yperr)  [YP_##yp - YP_VERS] = YPERR_##yperr
Packit 6c4009
    YP2YPERR (TRUE, SUCCESS),
Packit 6c4009
    YP2YPERR (NOMORE, NOMORE),
Packit 6c4009
    YP2YPERR (FALSE, YPERR),
Packit 6c4009
    YP2YPERR (NOMAP, MAP),
Packit 6c4009
    YP2YPERR (NODOM, DOMAIN),
Packit 6c4009
    YP2YPERR (NOKEY, KEY),
Packit 6c4009
    YP2YPERR (BADOP, YPERR),
Packit 6c4009
    YP2YPERR (BADDB, BADDB),
Packit 6c4009
    YP2YPERR (YPERR, YPERR),
Packit 6c4009
    YP2YPERR (BADARGS, BADARGS),
Packit 6c4009
    YP2YPERR (VERS, VERS)
Packit 6c4009
  };
Packit 6c4009
int
Packit 6c4009
ypprot_err (const int code)
Packit 6c4009
{
Packit 6c4009
  if (code < YP_VERS || code > YP_NOMORE)
Packit 6c4009
    return YPERR_YPERR;
Packit 6c4009
  return yp_2_yperr[code - YP_VERS];
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (ypprot_err, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
const char *
Packit 6c4009
ypbinderr_string (const int error)
Packit 6c4009
{
Packit 6c4009
  const char *str;
Packit 6c4009
  switch (error)
Packit 6c4009
    {
Packit 6c4009
    case 0:
Packit 6c4009
      str = N_("Success");
Packit 6c4009
      break;
Packit 6c4009
    case YPBIND_ERR_ERR:
Packit 6c4009
      str = N_("Internal ypbind error");
Packit 6c4009
      break;
Packit 6c4009
    case YPBIND_ERR_NOSERV:
Packit 6c4009
      str = N_("Domain not bound");
Packit 6c4009
      break;
Packit 6c4009
    case YPBIND_ERR_RESC:
Packit 6c4009
      str = N_("System resource allocation failure");
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      str = N_("Unknown ypbind error");
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
  return _(str);
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def (ypbinderr_string, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
#define WINDOW 60
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
yp_update (char *domain, char *map, unsigned ypop,
Packit 6c4009
	   char *key, int keylen, char *data, int datalen)
Packit 6c4009
{
Packit 6c4009
  union
Packit 6c4009
    {
Packit 6c4009
      ypupdate_args update_args;
Packit 6c4009
      ypdelete_args delete_args;
Packit 6c4009
    }
Packit 6c4009
  args;
Packit 6c4009
  xdrproc_t xdr_argument;
Packit 6c4009
  unsigned res = 0;
Packit 6c4009
  CLIENT *clnt;
Packit 6c4009
  char *master;
Packit 6c4009
  struct sockaddr saddr;
Packit 6c4009
  char servername[MAXNETNAMELEN + 1];
Packit 6c4009
  int r;
Packit 6c4009
Packit 6c4009
  if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
Packit 6c4009
    return YPERR_BADARGS;
Packit 6c4009
Packit 6c4009
  args.update_args.mapname = map;
Packit 6c4009
  args.update_args.key.yp_buf_len = keylen;
Packit 6c4009
  args.update_args.key.yp_buf_val = key;
Packit 6c4009
  args.update_args.datum.yp_buf_len = datalen;
Packit 6c4009
  args.update_args.datum.yp_buf_val = data;
Packit 6c4009
Packit 6c4009
  if ((r = yp_master (domain, map, &master)) != YPERR_SUCCESS)
Packit 6c4009
    return r;
Packit 6c4009
Packit 6c4009
  if (!host2netname (servername, master, domain))
Packit 6c4009
    {
Packit 6c4009
      fputs (_("yp_update: cannot convert host to netname\n"), stderr);
Packit 6c4009
      free (master);
Packit 6c4009
      return YPERR_YPERR;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
Packit 6c4009
Packit 6c4009
  /* We do not need the string anymore.  */
Packit 6c4009
  free (master);
Packit 6c4009
Packit 6c4009
  if (clnt == NULL)
Packit 6c4009
    {
Packit 6c4009
      clnt_pcreateerror ("yp_update: clnt_create");
Packit 6c4009
      return YPERR_RPC;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
Packit 6c4009
    {
Packit 6c4009
      fputs (_("yp_update: cannot get server address\n"), stderr);
Packit 6c4009
      return YPERR_RPC;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  switch (ypop)
Packit 6c4009
    {
Packit 6c4009
    case YPOP_CHANGE:
Packit 6c4009
    case YPOP_INSERT:
Packit 6c4009
    case YPOP_STORE:
Packit 6c4009
      xdr_argument = (xdrproc_t) xdr_ypupdate_args;
Packit 6c4009
      break;
Packit 6c4009
    case YPOP_DELETE:
Packit 6c4009
      xdr_argument = (xdrproc_t) xdr_ypdelete_args;
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      return YPERR_BADARGS;
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
Packit 6c4009
Packit 6c4009
  if (clnt->cl_auth == NULL)
Packit 6c4009
    clnt->cl_auth = authunix_create_default ();
Packit 6c4009
Packit 6c4009
again:
Packit 6c4009
  r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
Packit 6c4009
		 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
Packit 6c4009
Packit 6c4009
  if (r == RPC_AUTHERROR)
Packit 6c4009
    {
Packit 6c4009
      if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
Packit 6c4009
	{
Packit 6c4009
	  auth_destroy (clnt->cl_auth);
Packit 6c4009
	  clnt->cl_auth = authunix_create_default ();
Packit 6c4009
	  goto again;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	return YPERR_ACCESS;
Packit 6c4009
    }
Packit 6c4009
  if (r != RPC_SUCCESS)
Packit 6c4009
    {
Packit 6c4009
      clnt_perror (clnt, "yp_update: clnt_call");
Packit 6c4009
      return YPERR_RPC;
Packit 6c4009
    }
Packit 6c4009
  return res;
Packit 6c4009
}
Packit 6c4009
libnsl_hidden_nolink_def(yp_update, GLIBC_2_0)