summary refs log tree commit diff
path: root/nis/ypclnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'nis/ypclnt.c')
-rw-r--r--nis/ypclnt.c311
1 files changed, 190 insertions, 121 deletions
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 85292b62d9..ae04ee9212 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
 
@@ -45,12 +46,12 @@ struct dom_binding
   };
 typedef struct dom_binding dom_binding;
 
-static struct timeval RPCTIMEOUT = {25, 0};
-static struct timeval UDPTIMEOUT = {5, 0};
+static const struct timeval RPCTIMEOUT = {25, 0};
+static const struct timeval UDPTIMEOUT = {5, 0};
 static int const MAXTRIES = 2;
-static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
+static char ypdomainname[NIS_MAXNAMELEN + 1];
 __libc_lock_define_initialized (static, ypbindlist_lock)
-static dom_binding *__ypbindlist = NULL;
+static dom_binding *ypbindlist = NULL;
 
 
 static void
@@ -110,8 +111,8 @@ yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
   int clnt_sock;
   CLIENT *client;
 
-  memset (&clnt_saddr, '\0', sizeof clnt_saddr);
   clnt_saddr.sin_family = AF_INET;
+  clnt_saddr.sin_port = 0;
   clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
   clnt_sock = RPC_ANYSOCK;
   client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
@@ -141,7 +142,7 @@ yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
 
   if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
     {
-      fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
+      fprintf (stderr, "YPBINDPROC_DOMAIN: %s\n",
 	       ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
       return YPERR_DOMAIN;
     }
@@ -224,7 +225,7 @@ yp_bind (const char *indomain)
 
   __libc_lock_lock (ypbindlist_lock);
 
-  status = __yp_bind (indomain, &__ypbindlist);
+  status = __yp_bind (indomain, &ypbindlist);
 
   __libc_lock_unlock (ypbindlist_lock);
 
@@ -238,7 +239,7 @@ yp_unbind_locked (const char *indomain)
   dom_binding *ydbptr, *ydbptr2;
 
   ydbptr2 = NULL;
-  ydbptr = __ypbindlist;
+  ydbptr = ypbindlist;
 
   while (ydbptr != NULL)
     {
@@ -248,7 +249,7 @@ yp_unbind_locked (const char *indomain)
 
 	  work = ydbptr;
 	  if (ydbptr2 == NULL)
-	    __ypbindlist = __ypbindlist->dom_pnext;
+	    ypbindlist = ypbindlist->dom_pnext;
 	  else
 	    ydbptr2 = ydbptr->dom_pnext;
 	  __yp_unbind (work);
@@ -305,7 +306,7 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
   status = YPERR_YPERR;
 
   __libc_lock_lock (ypbindlist_lock);
-  ydb = __ypbindlist;
+  ydb = ypbindlist;
   while (ydb != NULL)
     {
       if (strcmp (domain, ydb->dom_domain) == 0)
@@ -348,7 +349,7 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
   if (status != YPERR_SUCCESS)
     {
       ydb = calloc (1, sizeof (dom_binding));
-      if (yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
+      if (ydb != NULL && yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
 	{
 	  status = __ypclnt_call (domain, prog, xargs, req, xres,
 				  resp, &ydb, 1);
@@ -364,6 +365,21 @@ do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
   return status;
 }
 
+/* Like do_ypcall, but translate the status value if necessary.  */
+static int
+do_ypcall_tr (const char *domain, u_long prog, xdrproc_t xargs,
+	      caddr_t req, xdrproc_t xres, caddr_t resp)
+{
+  int status = do_ypcall (domain, prog, xargs, req, xres, resp);
+  if (status == YPERR_SUCCESS)
+    /* We cast to ypresp_val although the pointer could also be of
+       type ypresp_key_val or ypresp_master or ypresp_order or
+       ypresp_maplist.  But the stat element is in a common prefix so
+       this does not matter.  */
+    status = ypprot_err (((struct ypresp_val *) resp)->stat);
+  return status;
+}
+
 
 __libc_lock_define_initialized (static, domainname_lock)
 
@@ -375,21 +391,21 @@ yp_get_default_domain (char **outdomain)
 
   __libc_lock_lock (domainname_lock);
 
-  if (__ypdomainname[0] == '\0')
+  if (ypdomainname[0] == '\0')
     {
-      if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
+      if (getdomainname (ypdomainname, NIS_MAXNAMELEN))
 	result = YPERR_NODOM;
-      else if (strcmp (__ypdomainname, "(none)") == 0)
+      else if (strcmp (ypdomainname, "(none)") == 0)
 	{
 	  /* If domainname is not set, some systems will return "(none)" */
-	  __ypdomainname[0] = '\0';
+	  ypdomainname[0] = '\0';
 	  result = YPERR_NODOM;
 	}
       else
-	*outdomain = __ypdomainname;
+	*outdomain = ypdomainname;
     }
   else
-    *outdomain = __ypdomainname;
+    *outdomain = ypdomainname;
 
   __libc_lock_unlock (domainname_lock);
 
@@ -402,14 +418,14 @@ __yp_check (char **domain)
 {
   char *unused;
 
-  if (__ypdomainname[0] == '\0')
+  if (ypdomainname[0] == '\0')
     if (yp_get_default_domain (&unused))
       return 0;
 
   if (domain)
-    *domain = __ypdomainname;
+    *domain = ypdomainname;
 
-  if (yp_bind (__ypdomainname) == 0)
+  if (yp_bind (ypdomainname) == 0)
     return 1;
   return 0;
 }
@@ -436,25 +452,26 @@ yp_match (const char *indomain, const char *inmap, const char *inkey,
   *outvallen = 0;
   memset (&resp, '\0', sizeof (resp));
 
-  result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
-		      (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
-		      (caddr_t) & resp);
+  result = do_ypcall_tr (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_val,
+			 (caddr_t) &resp);
 
   if (result != YPERR_SUCCESS)
     return result;
-  if (resp.stat != YP_TRUE)
-    return ypprot_err (resp.stat);
 
   *outvallen = resp.val.valdat_len;
   *outval = malloc (*outvallen + 1);
-  if (__builtin_expect (*outval == NULL, 0))
-    return YPERR_RESRC;
-  memcpy (*outval, resp.val.valdat_val, *outvallen);
-  (*outval)[*outvallen] = '\0';
+  int status = YPERR_RESRC;
+  if (__builtin_expect (*outval != NULL, 1))
+    {
+      memcpy (*outval, resp.val.valdat_val, *outvallen);
+      (*outval)[*outvallen] = '\0';
+      status = YPERR_SUCCESS;
+    }
 
   xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
 
-  return YPERR_SUCCESS;
+  return status;
 }
 
 int
@@ -477,30 +494,38 @@ yp_first (const char *indomain, const char *inmap, char **outkey,
   memset (&resp, '\0', sizeof (resp));
 
   result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
-		      (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
-		      (caddr_t) & resp);
+		      (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
+		      (caddr_t) &resp);
 
   if (result != RPC_SUCCESS)
     return YPERR_RPC;
   if (resp.stat != YP_TRUE)
     return ypprot_err (resp.stat);
 
-  *outkeylen = resp.key.keydat_len;
-  *outkey = malloc (*outkeylen + 1);
-  if (__builtin_expect (*outkey == NULL, 0))
-    return YPERR_RESRC;
-  memcpy (*outkey, resp.key.keydat_val, *outkeylen);
-  (*outkey)[*outkeylen] = '\0';
-  *outvallen = resp.val.valdat_len;
-  *outval = malloc (*outvallen + 1);
-  if (__builtin_expect (*outval == NULL, 0))
-    return YPERR_RESRC;
-  memcpy (*outval, resp.val.valdat_val, *outvallen);
-  (*outval)[*outvallen] = '\0';
+  int status;
+  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
+			&& (*outval = malloc (resp.val.valdat_len
+					      + 1)) != NULL, 1))
+    {
+      *outkeylen = resp.key.keydat_len;
+      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+      (*outkey)[*outkeylen] = '\0';
+
+      *outvallen = resp.val.valdat_len;
+      memcpy (*outval, resp.val.valdat_val, *outvallen);
+      (*outval)[*outvallen] = '\0';
+
+      status = YPERR_SUCCESS;
+    }
+  else
+    {
+      free (*outkey);
+      status = YPERR_RESRC;
+    }
 
   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
 
-  return YPERR_SUCCESS;
+  return status;
 }
 
 int
@@ -526,31 +551,37 @@ yp_next (const char *indomain, const char *inmap, const char *inkey,
   *outkeylen = *outvallen = 0;
   memset (&resp, '\0', sizeof (resp));
 
-  result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
-		      (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
-		      (caddr_t) & resp);
+  result = do_ypcall_tr (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
+			 (caddr_t) &resp);
 
   if (result != YPERR_SUCCESS)
     return result;
-  if (resp.stat != YP_TRUE)
-    return ypprot_err (resp.stat);
 
-  *outkeylen = resp.key.keydat_len;
-  *outkey = malloc (*outkeylen + 1);
-  if (__builtin_expect (*outkey == NULL, 0))
-    return YPERR_RESRC;
-  memcpy (*outkey, resp.key.keydat_val, *outkeylen);
-  (*outkey)[*outkeylen] = '\0';
-  *outvallen = resp.val.valdat_len;
-  *outval = malloc (*outvallen + 1);
-  if (__builtin_expect (*outval == NULL, 0))
-    return YPERR_RESRC;
-  memcpy (*outval, resp.val.valdat_val, *outvallen);
-  (*outval)[*outvallen] = '\0';
+  int status;
+  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
+			&& (*outval = malloc (resp.val.valdat_len
+					      + 1)) != NULL, 1))
+    {
+      *outkeylen = resp.key.keydat_len;
+      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+      (*outkey)[*outkeylen] = '\0';
+
+      *outvallen = resp.val.valdat_len;
+      memcpy (*outval, resp.val.valdat_val, *outvallen);
+      (*outval)[*outvallen] = '\0';
+
+      status = YPERR_SUCCESS;
+    }
+  else
+    {
+      free (*outkey);
+      status = YPERR_RESRC;
+    }
 
   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
 
-  return YPERR_SUCCESS;
+  return status;
 }
 
 int
@@ -569,13 +600,12 @@ yp_master (const char *indomain, const char *inmap, char **outname)
 
   memset (&resp, '\0', sizeof (ypresp_master));
 
-  result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
-	  (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
+  result = do_ypcall_tr (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_master,
+			 (caddr_t) &resp);
 
   if (result != YPERR_SUCCESS)
     return result;
-  if (resp.stat != YP_TRUE)
-    return ypprot_err (resp.stat);
 
   *outname = strdup (resp.peer);
   xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
@@ -592,7 +622,7 @@ yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
   enum clnt_stat result;
 
   if (indomain == NULL || indomain[0] == '\0' ||
-      inmap == NULL || inmap == '\0')
+      inmap == NULL || inmap[0] == '\0')
     return YPERR_BADARGS;
 
   req.domain = (char *) indomain;
@@ -600,18 +630,17 @@ yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
 
   memset (&resp, '\0', sizeof (resp));
 
-  result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
-	   (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
+  result = do_ypcall_tr (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_order,
+			 (caddr_t) &resp);
 
-  if (result != YPERR_SUCCESS)
+  if (result == YPERR_SUCCESS)
     return result;
-  if (resp.stat != YP_TRUE)
-    return ypprot_err (resp.stat);
 
   *outorder = resp.ordernum;
   xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
 
-  return YPERR_SUCCESS;
+  return result;
 }
 
 struct ypresp_all_data
@@ -657,10 +686,10 @@ __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
 	       if we don't modify the length. So add an extra NUL
 	       character to avoid trouble with broken code. */
 	    objp->status = YP_TRUE;
-	    memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
-	    key[keylen] = '\0';
-	    memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
-	    val[vallen] = '\0';
+	    *((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val,
+				  keylen)) = '\0';
+	    *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
+				  vallen)) = '\0';
 	    xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
 	    if ((*objp->foreach) (objp->status, key, keylen,
 				  val, vallen, objp->data))
@@ -671,7 +700,7 @@ __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
 	  objp->status = resp.ypresp_all_u.val.stat;
 	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
 	  /* Sun says we don't need to make this call, but must return
-	     immediatly. Since Solaris makes this call, we will call
+	     immediately. Since Solaris makes this call, we will call
 	     the callback function, too. */
 	  (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
 	  return TRUE;
@@ -693,8 +722,8 @@ yp_all (const char *indomain, const char *inmap,
   int clnt_sock;
   int saved_errno = errno;
 
-  if (indomain == NULL || indomain[0] == '\0' ||
-      inmap == NULL || inmap == '\0')
+  if (indomain == NULL || indomain[0] == '\0'
+      || inmap == NULL || inmap[0] == '\0')
     return YPERR_BADARGS;
 
   try = 0;
@@ -732,9 +761,9 @@ yp_all (const char *indomain, const char *inmap,
 			  (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
 			  (caddr_t) &data, RPCTIMEOUT);
 
-      if (result != RPC_SUCCESS)
+      if (__builtin_expect (result != RPC_SUCCESS, 0))
 	{
-	  /* Print the error message only on the last try */
+	  /* Print the error message only on the last try.  */
 	  if (try == MAXTRIES - 1)
 	    clnt_perror (clnt, "yp_all: clnt_call");
 	  res = YPERR_RPC;
@@ -758,6 +787,7 @@ yp_all (const char *indomain, const char *inmap,
 }
 
 int
+
 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
 {
   struct ypresp_maplist resp;
@@ -768,67 +798,92 @@ yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
 
   memset (&resp, '\0', sizeof (resp));
 
-  result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
-    (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
-
-  if (result != YPERR_SUCCESS)
-    return result;
-  if (resp.stat != YP_TRUE)
-    return ypprot_err (resp.stat);
+  result = do_ypcall_tr (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
+			 (caddr_t) &indomain, (xdrproc_t) xdr_ypresp_maplist,
+			 (caddr_t) &resp);
 
-  *outmaplist = resp.maps;
-  /* We give the list not free, this will be done by ypserv
-     xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
+  if (__builtin_expect (result == YPERR_SUCCESS, 1))
+    {
+      *outmaplist = resp.maps;
+      /* We don't free the list, this will be done by ypserv
+	 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
+    }
 
-  return YPERR_SUCCESS;
+  return result;
 }
 
 const char *
 yperr_string (const int error)
 {
+  const char *str;
   switch (error)
     {
     case YPERR_SUCCESS:
-      return _("Success");
+      str = N_("Success");
+      break;
     case YPERR_BADARGS:
-      return _("Request arguments bad");
+      str = N_("Request arguments bad");
+      break;
     case YPERR_RPC:
-      return _("RPC failure on NIS operation");
+      str = N_("RPC failure on NIS operation");
+      break;
     case YPERR_DOMAIN:
-      return _("Can't bind to server which serves this domain");
+      str = N_("Can't bind to server which serves this domain");
+      break;
     case YPERR_MAP:
-      return _("No such map in server's domain");
+      str = N_("No such map in server's domain");
+      break;
     case YPERR_KEY:
-      return _("No such key in map");
+      str = N_("No such key in map");
+      break;
     case YPERR_YPERR:
-      return _("Internal NIS error");
+      str = N_("Internal NIS error");
+      break;
     case YPERR_RESRC:
-      return _("Local resource allocation failure");
+      str = N_("Local resource allocation failure");
+      break;
     case YPERR_NOMORE:
-      return _("No more records in map database");
+      str = N_("No more records in map database");
+      break;
     case YPERR_PMAP:
-      return _("Can't communicate with portmapper");
+      str = N_("Can't communicate with portmapper");
+      break;
     case YPERR_YPBIND:
-      return _("Can't communicate with ypbind");
+      str = N_("Can't communicate with ypbind");
+      break;
     case YPERR_YPSERV:
-      return _("Can't communicate with ypserv");
+      str = N_("Can't communicate with ypserv");
+      break;
     case YPERR_NODOM:
-      return _("Local domain name not set");
+      str = N_("Local domain name not set");
+      break;
     case YPERR_BADDB:
-      return _("NIS map database is bad");
+      str = N_("NIS map database is bad");
+      break;
     case YPERR_VERS:
-      return _("NIS client/server version mismatch - can't supply service");
+      str = N_("NIS client/server version mismatch - can't supply service");
+      break;
     case YPERR_ACCESS:
-      return _("Permission denied");
+      str = N_("Permission denied");
+      break;
     case YPERR_BUSY:
-      return _("Database is busy");
+      str = N_("Database is busy");
+      break;
+    default:
+      str = N_("Unknown NIS error code");
+      break;
     }
-  return _("Unknown NIS error code");
+  return _(str);
 }
 
 static const int8_t yp_2_yperr[] =
   {
 #define YP2YPERR(yp, yperr)  [YP_##yp - YP_VERS] = YPERR_##yperr
+    YP2YPERR (TRUE, SUCCESS),
+    YP2YPERR (NOMORE, NOMORE),
+    YP2YPERR (FALSE, YPERR),
+    YP2YPERR (NOMAP, MAP),
+    YP2YPERR (NODOM, DOMAIN),
     YP2YPERR (NOKEY, KEY),
     YP2YPERR (BADOP, YPERR),
     YP2YPERR (BADDB, BADDB),
@@ -839,7 +894,7 @@ static const int8_t yp_2_yperr[] =
 int
 ypprot_err (const int code)
 {
-  if (code < YP_VERS || code > YP_NOKEY)
+  if (code < YP_VERS || code > YP_NOMORE)
     return YPERR_YPERR;
   return yp_2_yperr[code - YP_VERS];
 }
@@ -848,19 +903,26 @@ libnsl_hidden_def (ypprot_err)
 const char *
 ypbinderr_string (const int error)
 {
+  const char *str;
   switch (error)
     {
     case 0:
-      return _("Success");
+      str = N_("Success");
+      break;
     case YPBIND_ERR_ERR:
-      return _("Internal ypbind error");
+      str = N_("Internal ypbind error");
+      break;
     case YPBIND_ERR_NOSERV:
-      return _("Domain not bound");
+      str = N_("Domain not bound");
+      break;
     case YPBIND_ERR_RESC:
-      return _("System resource allocation failure");
+      str = N_("System resource allocation failure");
+      break;
     default:
-      return _("Unknown ypbind error");
+      str = N_("Unknown ypbind error");
+      break;
     }
+  return _(str);
 }
 libnsl_hidden_def (ypbinderr_string)
 
@@ -893,16 +955,22 @@ yp_update (char *domain, char *map, unsigned ypop,
   args.update_args.datum.yp_buf_len = datalen;
   args.update_args.datum.yp_buf_val = data;
 
-  if ((r = yp_master (domain, map, &master)) != 0)
+  if ((r = yp_master (domain, map, &master)) != YPERR_SUCCESS)
     return r;
 
   if (!host2netname (servername, master, domain))
     {
       fputs (_("yp_update: cannot convert host to netname\n"), stderr);
+      free (master);
       return YPERR_YPERR;
     }
 
-  if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
+  clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
+
+  /* We do not need the string anymore.  */
+  free (master);
+
+  if (clnt == NULL)
     {
       clnt_pcreateerror ("yp_update: clnt_create");
       return YPERR_RPC;
@@ -942,6 +1010,7 @@ again:
     {
       if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
 	{
+	  auth_destroy (clnt->cl_auth);
 	  clnt->cl_auth = authunix_create_default ();
 	  goto again;
 	}