summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--nis/nis_call.c46
-rw-r--r--nis/nis_lookup.c7
-rw-r--r--nis/nis_table.c3
-rw-r--r--nis/rpcsvc/nislib.h5
5 files changed, 56 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index 34428caa54..98ecfa6d5e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2006-08-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* nis/nis_call.c: Minor cleanups throughout.
+	(rec_dirsearch) [HIGHER_NAME]: Correctly size ndomain array.
+	(first_shoot): Add search_parent_first parameter.  Only if it is set
+	search parent server first.
+	If directory for table found through cold start cache is not the same
+	as referenced in the cache, don't use it.
+	(__nisfind_server): Take additional parameter.  Pass it on to
+	first_shoot.
+	(__prepare_niscall): Adjust __nisfind_server call.
+	* nis/rpcsvc/nislib.h: Adjust __nisfind_server prototype.
+	* nis/nis_table.c: Adjust __nisfind_server call.
+	* nis/nis_lookup.c: Likewise.
+	(nis_lookup): Don't loop endlessly if name is reduced to ".".
+
 2006-08-03  Ulrich Drepper  <drepper@redhat.com>
 
 	[BZ #2182]
diff --git a/nis/nis_call.c b/nis/nis_call.c
index f8f00d8c82..bad1f776a1 100644
--- a/nis/nis_call.c
+++ b/nis/nis_call.c
@@ -38,12 +38,12 @@ static const struct timeval UDPTIMEOUT = {5, 0};
 extern u_short __pmap_getnisport (struct sockaddr_in *address, u_long program,
 				  u_long version, u_int protocol);
 
-unsigned long
+unsigned long int
 inetstr2int (const char *str)
 {
   size_t j = 0;
   for (size_t i = 0; str[i] != '\0'; ++i)
-    if (str[i] == '.' && ++j == 4)
+    if (str[i] == '.' && __builtin_expect (++j == 4, 0))
       {
 	char buffer[i + 1];
 	buffer[i] = '\0';
@@ -68,8 +68,6 @@ libnsl_hidden_def (__nisbind_destroy)
 nis_error
 __nisbind_next (dir_binding *bind)
 {
-  u_int j;
-
   if (bind->clnt != NULL)
     {
       if (bind->use_auth)
@@ -81,7 +79,7 @@ __nisbind_next (dir_binding *bind)
   if (bind->trys >= bind->server_len)
     return NIS_FAIL;
 
-  for (j = bind->current_ep + 1;
+  for (u_int j = bind->current_ep + 1;
        j < bind->server_val[bind->server_used].ep.ep_len; ++j)
     if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
 		"inet") == 0)
@@ -96,7 +94,7 @@ __nisbind_next (dir_binding *bind)
   if (bind->server_used >= bind->server_len)
     bind->server_used = 0;
 
-  for (j = 0; j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+  for (u_int j = 0; j < bind->server_val[bind->server_used].ep.ep_len; ++j)
     if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
 		"inet") == 0)
       if (bind->server_val[bind->server_used].ep.ep_val[j].proto[0] == '-')
@@ -125,7 +123,7 @@ __nisbind_connect (dir_binding *dbp)
   dbp->addr.sin_addr.s_addr =
     inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
 
-  if (dbp->addr.sin_addr.s_addr == 0)
+  if (dbp->addr.sin_addr.s_addr == INADDR_NONE)
     return NIS_FAIL;
 
   /* Check, if the host is online and rpc.nisd is running. Much faster
@@ -340,7 +338,7 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, nis_error *status)
     case HIGHER_NAME:
       { /* We need data from a parent domain */
 	directory_obj *obj;
-	char ndomain [strlen (name) + 3];
+	char ndomain[strlen (dir->do_name) + 3];
 
 	nis_domain_of_r (dir->do_name, ndomain, sizeof (ndomain));
 
@@ -461,31 +459,44 @@ rec_dirsearch (const_nis_name name, directory_obj *dir, nis_error *status)
 /* We try to query the current server for the searched object,
    maybe he know about it ? */
 static directory_obj *
-first_shoot (const_nis_name name, directory_obj *dir)
+first_shoot (const_nis_name name, int search_parent_first, directory_obj *dir)
 {
   directory_obj *obj = NULL;
   fd_result *fd_res;
   XDR xdrs;
   char domain[strlen (name) + 3];
 
+#if 0
   if (nis_dir_cmp (name, dir->do_name) == SAME_NAME)
     return dir;
+#endif
 
-  nis_domain_of_r (name, domain, sizeof (domain));
+  const char *search_name = name;
+  if (search_parent_first)
+    {
+      nis_domain_of_r (name, domain, sizeof (domain));
+      search_name = domain;
+    }
 
-  if (nis_dir_cmp (domain, dir->do_name) == SAME_NAME)
+  if (nis_dir_cmp (search_name, dir->do_name) == SAME_NAME)
     return dir;
 
-  fd_res = __nis_finddirectory (dir, domain);
+  fd_res = __nis_finddirectory (dir, search_name);
   if (fd_res == NULL)
     return NULL;
   if (fd_res->status == NIS_SUCCESS
       && (obj = calloc (1, sizeof (directory_obj))) != NULL)
     {
-      xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val,
-		    fd_res->dir_data.dir_data_len, XDR_DECODE);
+      xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
+		     fd_res->dir_data.dir_data_len, XDR_DECODE);
       _xdr_directory_obj (&xdrs, obj);
       xdr_destroy (&xdrs);
+
+      if (strcmp (dir->do_name, obj->do_name) != 0)
+	{
+	  nis_free_directory (obj);
+	  obj = NULL;
+	}
     }
 
   __free_fdresult (fd_res);
@@ -497,7 +508,8 @@ first_shoot (const_nis_name name, directory_obj *dir)
 }
 
 nis_error
-__nisfind_server (const_nis_name name, directory_obj **dir)
+__nisfind_server (const_nis_name name, int search_parent_first,
+		  directory_obj **dir)
 {
   if (name == NULL)
     return NIS_BADNAME;
@@ -520,7 +532,7 @@ __nisfind_server (const_nis_name name, directory_obj **dir)
 	return NIS_UNAVAIL;
 
       /* Try at first, if servers in "dir" know our object */
-      obj = first_shoot (name, *dir);
+      obj = first_shoot (name, search_parent_first, *dir);
       if (obj == NULL)
 	{
 	  obj = rec_dirsearch (name, *dir, &status);
@@ -539,7 +551,7 @@ nis_error
 __prepare_niscall (const_nis_name name, directory_obj **dirp,
 		   dir_binding *bptrp, unsigned int flags)
 {
-  nis_error retcode = __nisfind_server (name, dirp);
+  nis_error retcode = __nisfind_server (name, 1, dirp);
   if (__builtin_expect (retcode != NIS_SUCCESS, 0))
     return retcode;
 
diff --git a/nis/nis_lookup.c b/nis/nis_lookup.c
index c198376464..839ee4ee42 100644
--- a/nis/nis_lookup.c
+++ b/nis/nis_lookup.c
@@ -127,7 +127,7 @@ nis_lookup (const_nis_name name, const unsigned int flags)
 			/* Otherwise __nisfind_server will not do anything.  */
 			dir = NULL;
 
-			if (__nisfind_server (req.ns_name, &dir)
+			if (__nisfind_server (req.ns_name, 1, &dir)
 			    != NIS_SUCCESS)
 			  goto out;
 
@@ -147,6 +147,11 @@ nis_lookup (const_nis_name name, const unsigned int flags)
 			  nis_domain_of_r (req.ns_name, ndomain,
 					   sizeof (ndomain));
 			  req.ns_name = strdupa (ndomain);
+			  if (strcmp (ndomain, ".") == 0)
+			    {
+			      NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+			      goto out;
+			    }
 
 			  __nisbind_destroy (&bptr);
 			  nis_free_directory (dir);
diff --git a/nis/nis_table.c b/nis/nis_table.c
index 3213035067..a92a4b64ce 100644
--- a/nis/nis_table.c
+++ b/nis/nis_table.c
@@ -271,7 +271,8 @@ nis_list (const_nis_name name, unsigned int flags,
 
       memset (res, '\0', sizeof (nis_result));
 
-      status = __nisfind_server (ibreq->ibr_name, &dir);
+      status = __nisfind_server (ibreq->ibr_name,
+				 ibreq->ibr_srch.ibr_srch_val != NULL, &dir);
       if (status != NIS_SUCCESS)
 	{
           NIS_RES_STATUS (res) = status;
diff --git a/nis/rpcsvc/nislib.h b/nis/rpcsvc/nislib.h
index a55de61830..c993bac5e8 100644
--- a/nis/rpcsvc/nislib.h
+++ b/nis/rpcsvc/nislib.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
 
@@ -276,7 +276,8 @@ extern nis_error __nisbind_create (dir_binding *, const nis_server *,
 extern nis_error __nisbind_connect (dir_binding *) __THROW;
 extern nis_error __nisbind_next (dir_binding *) __THROW;
 extern void __nisbind_destroy (dir_binding *) __THROW;
-extern nis_error __nisfind_server (const_nis_name, directory_obj **) __THROW;
+extern nis_error __nisfind_server (const_nis_name, int, directory_obj **)
+     __THROW;
 
 #endif