namecache updates and trustdom patch n+4

Rafal Szczesniak mimir at diament.ists.pwr.wroc.pl
Sun Nov 3 19:47:01 GMT 2002


These are namecache fixes and n+4 update to trusted domains:
Changes include:
 - namecache uses now new ipstr_list_* functions to operate
   on lists of IP addresses converted to string
   It doesn't use (yet) str_list_make routine since it lacks
   support for expandable strings (ie. you cannot add another
   address to a list)
 - implemented ipstr_list_make, ipstr_list_add, ipstr_list_parse
   and ipstr_list_free functions and, I suspect this code will
   be modified to cooperate with str_list_make;
   one step at a time, however...
 - updated 'net cache' code to improve displaying cache contents'
   readability
 - trustdom_cache implementation extended to use by ADS environments
   as well (alt_name and friends...)
 - small update of rpcclient to make trusted domains enumeration
   command more flexible about parameters


This part works for me, but it wasn't extensively tested, so
comments and fixes (memleaks in paricular) are welcome.



-- 
cheers,
+------------------------------------------------------------+
|Rafal 'Mimir' Szczesniak <mimir at diament.ists.pwr.wroc.pl>   |
|*BSD, GNU/Linux and Samba                                  /
|__________________________________________________________/
-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /cvsroot/samba/source/Makefile.in,v
retrieving revision 1.555
diff -u -r1.555 Makefile.in
--- Makefile.in	1 Nov 2002 05:41:56 -0000	1.555
+++ Makefile.in	3 Nov 2002 19:04:02 -0000
@@ -173,7 +173,7 @@
              libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
 	     libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \
 	     libsmb/passchange.o libsmb/unexpected.o libsmb/doserr.o \
-	     libsmb/namecache.o $(RPC_PARSE_OBJ1)
+	     libsmb/namecache.o libsmb/trustdom_cache.o $(RPC_PARSE_OBJ1)
 
 LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
 	       rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
Index: lib/gencache.c
===================================================================
RCS file: /cvsroot/samba/source/lib/gencache.c,v
retrieving revision 1.1
diff -u -r1.1 gencache.c
--- lib/gencache.c	11 Sep 2002 14:07:15 -0000	1.1
+++ lib/gencache.c	3 Nov 2002 19:04:03 -0000
@@ -92,7 +92,6 @@
 
 /**
  * Add one entry to the cache file.
- * (it part of tridge's proposed API)
  *
  * @param key string that represents a key of this entry
  * @param value text representation value being cached
@@ -133,7 +132,6 @@
 
 /**
  * Set existing entry to the cache file.
- * (it part of tridge's proposed API)
  *
  * @param key string that represents a key of this entry
  * @param value text representation value being cached
@@ -189,7 +187,6 @@
 
 /**
  * Delete one entry from the cache file.
- * (it part of tridge's proposed API)
  *
  * @param key string that represents a key of this entry
  *
@@ -219,11 +216,10 @@
 
 /**
  * Get existing entry from the cache file.
- * (it part of tridge's proposed API)
  *
  * @param key string that represents a key of this entry
  * @param value buffer that is allocated and filled with the entry value
- *        buffer's disposing is done outside
+ *        buffer's disposing must be done outside
  * @param timeout pointer to a time_t that is filled with entry's
  *        timeout
  *
@@ -269,12 +265,14 @@
  *
  * @param fn pointer to the function that will be supplied with each single
  *        matching cache entry (key, value and timeout) as an arguments
+ * @param data void pointer to an arbitrary data that is passed directly to the fn
+ *        function on each call
  * @param keystr_pattern pattern the existing entries' keys are matched to
  *
  **/
 
-void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout),
-                      const char* keystr_pattern)
+void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr),
+                      void* data, const char* keystr_pattern)
 {
 	TDB_LIST_NODE *node, *first_node;
 	TDB_DATA databuf;
@@ -286,7 +284,7 @@
 
 	if (!gencache_init()) return;
 
-	DEBUG(5, ("Searching cache keys with pattern %s", keystr_pattern));
+	DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern));
 	node = tdb_search_keys(cache, keystr_pattern);
 	first_node = node;
 	
@@ -306,7 +304,7 @@
 		
 		DEBUG(10, ("Calling function with arguments (key = %s, value = %s, timeout = %s)\n",
 		           keystr, valstr, ctime(&timeout)));
-		fn(keystr, valstr, timeout);
+		fn(keystr, valstr, timeout, data);
 		
 		SAFE_FREE(valstr);
 		SAFE_FREE(entry);
@@ -315,5 +313,4 @@
 	
 	tdb_search_list_free(first_node);
 }
-
 
Index: lib/util_str.c
===================================================================
RCS file: /cvsroot/samba/source/lib/util_str.c,v
retrieving revision 1.65
diff -u -r1.65 util_str.c
--- lib/util_str.c	2 Oct 2002 19:11:59 -0000	1.65
+++ lib/util_str.c	3 Nov 2002 19:04:06 -0000
@@ -1365,3 +1365,129 @@
 	
 	return True;
 }
+
+
+/**
+ * Add ip string representation to ipstr list. Used also
+ * as part of @function ipstr_list_make
+ *
+ * @param ipstr_list pointer to string containing ip list;
+ *        MUST BE already allocated and WILL BE reallocated if necessary
+ * @param ip pointer to in_addr structure
+ * @return pointer to string appended with new ip and possibly
+ *         reallocated to new length
+ **/
+
+char* ipstr_list_add(char** ipstr_list, int *ipstr_size, struct in_addr *ip)
+{
+	int ipstr_len, ipstr_chunk;
+	char* ipstr;
+	
+	/* arguments checking */
+	if (!ipstr_list || !ip) return NULL;
+
+	/* set initial values */
+	ipstr_chunk = *ipstr_size / (FSTRING_LEN / 8);
+	ipstr_len = strlen(*ipstr_list);
+			
+	/* attempt to convert ip to a string and append colon separator to it */
+	ipstr = inet_ntoa(*ip);
+	if (ipstr)
+		ipstr = safe_strcat(ipstr, ":", strlen(ipstr) + 1);
+	else
+		return NULL;
+	
+	/* calculate new size of the string and reallocate it if needed */
+	ipstr_len += strlen(ipstr);
+	if (ipstr_len >= *ipstr_size) {
+		*ipstr_size = ++ipstr_chunk * (FSTRING_LEN / 8);
+		*ipstr_list = (char*)realloc((void*)(*ipstr_list),
+		                             sizeof(char) * (*ipstr_size));
+	}
+	
+	/* append new ip string to the list */
+	safe_strcat(*ipstr_list, ipstr, *ipstr_size);
+	
+	return *ipstr_list;
+}
+
+
+/**
+ * Allocate and initialise an ipstr list using ip adresses
+ * passed as arguments.
+ *
+ * @param ipstr_list pointer to string to be allcated and set
+ * @param ip_list array of ip addresses to place in the list
+ * @param ip_count number of addresses stored in ip_list
+ * @return length of allocated ip string
+ **/
+ 
+int ipstr_list_make(char** ipstr_list, struct in_addr** ip_list, int ip_count)
+{
+	int i, alloc_size;
+	
+	/* arguments checking */
+	if (!ip_list && !ipstr_list) return 0;
+
+	alloc_size = FSTRING_LEN / 8;	/* chosen empirically */
+	*ipstr_list = NULL;
+	
+	/* allocate initial list string and clear it if allocated correctly */
+	*ipstr_list = (char*)malloc(sizeof(char) * alloc_size);
+	if (! *ipstr_list) return 0;
+	memset((void*)(*ipstr_list), 0, alloc_size);
+	
+	/* process ip addresses given as arguments */
+	for (i = 0; i < ip_count; i++)
+		*ipstr_list = ipstr_list_add(ipstr_list, &alloc_size, ip_list[i]);
+	
+	return alloc_size;
+}
+
+
+/**
+ * Parse given ip string list into array of ip addresses
+ * (as in_addr structures)
+ *
+ * @param ipstr ip string list to be parsed 
+ * @param ip_list pointer to array of ip addresses
+ *        which is allocated by this function and must be
+ *        freed by caller
+ * @return number of succesfully parsed addresses
+ **/
+ 
+int ipstr_list_parse(char* ipstr_list, struct in_addr** ip_list)
+{
+	fstring ip_str;
+	char *ipstr;
+	int value_len;
+	int i = 0;
+	
+	if (!ipstr_list || !ip_list) return 0;
+	
+	/* ip_str must be empty at the begin */
+	ip_str[i] = 0;
+	ipstr = ipstr_list;
+	
+	value_len = strlen(ipstr);		
+	while (next_token(&ipstr, ip_str, ":", value_len)) {
+		ip_list[i] = (struct in_addr*)malloc(sizeof(struct in_addr));
+		if (!ip_list[i]) return 0;
+		inet_aton(ip_str, ip_list[i++]);
+	}
+	
+	return i;
+}
+
+
+/**
+ * Safely free ip string list
+ *
+ * @param ipstr_list ip string list to be freed
+ **/
+
+void ipstr_list_free(char* ipstr_list)
+{
+	string_free(&ipstr_list);
+}
+
Index: libsmb/namecache.c
===================================================================
RCS file: /cvsroot/samba/source/libsmb/namecache.c,v
retrieving revision 1.8
diff -u -r1.8 namecache.c
--- libsmb/namecache.c	28 Aug 2002 00:17:11 -0000	1.8
+++ libsmb/namecache.c	3 Nov 2002 19:04:10 -0000
@@ -1,9 +1,10 @@
 /* 
    Unix SMB/CIFS implementation.
 
-   NetBIOS name cache module.
-
-   Copyright (C) Tim Potter, 2002
+   NetBIOS name cache module on top of gencache mechanism.
+   
+   Copyright (C) Tim Potter         2002
+   Copyright (C) Rafal Szczesniak   2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -22,242 +23,208 @@
 
 #include "includes.h"
 
-static BOOL done_namecache_init;
-static BOOL enable_namecache;
-static TDB_CONTEXT *namecache_tdb;
-
-struct nc_value {
-	time_t expiry;		     /* When entry expires */
-	int count;		     /* Number of addresses */
-	struct in_addr ip_list[1];   /* Address list */
-};
+#define NBTKEY_FMT  "NBT/%s#%02X"
 
-/* Initialise namecache system */
+
+/**
+ * Initialise namecache system. Function calls gencache
+ * initialisation function to perform necessary actions
+ * 
+ * @return true upon successful initialisation of the cache or
+ *         false on failure
+ **/
 
 BOOL namecache_enable(void)
 {
-	/* Check if we have been here before, or name caching disabled
-           by setting the name cache timeout to zero. */ 
-
-	if (done_namecache_init)
-		return False;
-
-	done_namecache_init = True;
+	/*
+	 * Check if name caching disabled by setting the name cache
+	 * timeout to zero.
+	 */ 
 
 	if (lp_name_cache_timeout() == 0) {
 		DEBUG(5, ("namecache_init: disabling netbios name cache\n"));
 		return False;
 	}
 
-	/* Open namecache tdb in read/write or readonly mode */
+	/* Init namecache by calling gencache initialisation */
 
-	namecache_tdb = tdb_open_log(
-		lock_path("namecache.tdb"), 0,
-		TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
-
-	if (!namecache_tdb) {
-		DEBUG(5, ("namecache_init: could not open %s\n",
-			  lock_path("namecache.tdb")));
+	if (!gencache_init()) {
+		DEBUG(2, ("namecache_init: Couldn't initialise namecache on top of gencache.\n"));
 		return False;
 	}
 
+	/* I leave it for now, though I don't think we really need this (mimir, 27.09.2002) */
 	DEBUG(5, ("namecache_init: enabling netbios namecache, timeout %d "
 		  "seconds\n", lp_name_cache_timeout()));
 
-	enable_namecache = True;
-
 	return True;
 }
 
-/* Return a key for a name and name type.  The caller must free
-   retval.dptr when finished. */
+/**
+ * Generates a key for netbios name lookups on basis of
+ * netbios name and type.
+ * The caller must free returned key string when finished.
+ *
+ * @param name netbios name string (case insensitive)
+ * @param name_type netbios type of the name being looked up
+ *
+ * @return string consisted of uppercased name and appended
+ *         type number
+ */
 
-static TDB_DATA namecache_key(const char *name, int name_type)
+static char* namecache_key(const char *name, int name_type)
 {
-	TDB_DATA retval;
 	char *keystr;
+	asprintf(&keystr, NBTKEY_FMT, strupper_static(name), name_type);
 
-	asprintf(&keystr, "%s#%02X", strupper_static(name), name_type);
-
-	retval.dsize = strlen(keystr) + 1;
-	retval.dptr = keystr;
-
-	return retval;
+	return keystr;
 }
 
-/* Return a data value for an IP list.  The caller must free
-   retval.dptr when finished. */
-
-static TDB_DATA namecache_value(struct in_addr *ip_list, int num_names, 
-				time_t expiry)
-{
-	TDB_DATA retval;
-	struct nc_value *value;
-	int size = sizeof(struct nc_value);
-
-	if (num_names > 0)
-		size += sizeof(struct in_addr) * (num_names-1);
-
-	value = (struct nc_value *)malloc(size);
-
-	memset(value, 0, size);
-
-	value->expiry = expiry;
-	value->count = num_names;
 
-	if (ip_list)
-		memcpy(value->ip_list, ip_list, sizeof(struct in_addr) * num_names);
+/**
+ * Store a name(s) in the name cache
+ *
+ * @param name netbios names array
+ * @param name_type integer netbios name type
+ * @param num_names number of names being stored
+ * @param ip_list array of in_addr structures containing
+ *        ip addresses being stored
+ **/
 
-	retval.dptr = (char *)value;
-	retval.dsize = size;
-
-	return retval;
-}
-
-/* Store a name in the name cache */
-
-void namecache_store(const char *name, int name_type,
-		     int num_names, struct in_addr *ip_list)
+BOOL namecache_store(const char *name, int name_type,
+                     int num_names, struct in_addr *ip_list)
 {
-	TDB_DATA key, value;
 	time_t expiry;
-	int i;
+	char *key, *value_string;
+	int i, value_len;
 
-	if (!enable_namecache)
-		return;
+	/*
+	 * we use gecache call to avoid annoying debug messages about
+	 * initialised namecache again and again...
+	 */
+	if (!gencache_init()) return False;
 
 	DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ",
-		  num_names, num_names == 1 ? "": "es", name, name_type));
+	          num_names, num_names == 1 ? "": "es", name, name_type));
 
 	for (i = 0; i < num_names; i++) 
 		DEBUGADD(5, ("%s%s", inet_ntoa(ip_list[i]),
-			     i == (num_names - 1) ? "" : ", "));
+		             i == (num_names - 1) ? "" : ", "));
 
 	DEBUGADD(5, ("\n"));
 
 	key = namecache_key(name, name_type);
 
-	/* Cache pdc location or dc lists for only a little while
-	   otherwise if we lock on to a bad DC we can potentially be
-	   out of action for the entire cache timeout time! */
+	/* 
+	 * Cache pdc location or dc lists for only a little while
+	 * otherwise if we lock on to a bad DC we can potentially be
+	 * out of action for the entire cache timeout time!
+	 */
 
 	if (name_type != 0x1b || name_type != 0x1c)
 		expiry = time(NULL) + 10;
 	else
 		expiry = time(NULL) + lp_name_cache_timeout();
 
-	value = namecache_value(ip_list, num_names, expiry);
-
-	tdb_store(namecache_tdb, key, value, TDB_REPLACE);
-
-	free(key.dptr);
-	free(value.dptr);
+	/*
+	 * Generate string representation of ip addresses list
+	 * First, store the number of ip addresses and then
+	 * place each single ip
+	 */
+	
+	value_len = ipstr_list_make(&value_string, &ip_list, num_names);
+	
+	/*
+	 * if an attempt to set fails, then perhaps there's no such
+	 * entry and it's better to add i
+	 */
+	 
+	if (!gencache_set(key, value_string, expiry))
+		return (gencache_add(key, value_string, expiry));
+	
+	return True;
 }
 
-/* Look up a name in the name cache.  Return a mallocated list of IP
-   addresses if the name is contained in the cache. */
+
+/**
+ * Look up a name in the cache.
+ *
+ * @param name netbios name to look up for
+ * @param name_type netbios name type of @param name
+ * @param ip_list mallocated list of IP addresses if found in the cache,
+ *        NULL otherwise
+ * @param num_names number of entries found
+ *
+ * @return true upon successful fetch or
+ *         false if name isn't found in the cache or has expired
+ **/
 
 BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list,
-		     int *num_names)
+                     int *num_names)
 {
-	TDB_DATA key, value;
-	struct nc_value *data;
-	time_t now;
-	int i;
+	char *key, *value;
+	time_t timeout;
 
-	*ip_list = NULL;
 	*num_names = 0;
 
-	if (!enable_namecache)
-		return False;
+	/* exit now if null pointers were passed as they're required further */
+	if (!ip_list || !num_names) return False;
 
-	/* Read value */
+	if (!gencache_init())
+		return False;
 
+	/* 
+	 * Use gencache interface - lookup the key
+	 */
 	key = namecache_key(name, name_type);
 
-	value = tdb_fetch(namecache_tdb, key);
+	if (!gencache_get(key, &value, &timeout)) {
+		DEBUG(5, ("no entry for %s#%02X found.\n", name, name_type));
+		return False;
+	} else
+		DEBUG(5, ("name %s#%02X found.\n", name, name_type));
 	
-	if (!value.dptr) {
-		DEBUG(5, ("namecache_fetch: %s#%02x not found\n",
-			  name, name_type));
-		goto done;
-	}
-
-	data = (struct nc_value *)value.dptr;
-
-	/* Check expiry time */
-
-	now = time(NULL);
-
-	if (now > data->expiry) {
-
-		DEBUG(5, ("namecache_fetch: entry for %s#%02x expired\n",
-			  name, name_type));
-
-		tdb_delete(namecache_tdb, key);
-
-		value = tdb_null;
-
-		goto done;
-	}
-
-	if ((data->expiry - now) > lp_name_cache_timeout()) {
-
-		/* Someone may have changed the system time on us */
-
-		DEBUG(5, ("namecache_fetch: entry for %s#%02x has bad expiry\n",
-			  name, name_type));
-
-		tdb_delete(namecache_tdb, key);
-
-		value = tdb_null;
+	/*
+	 * Split up the stored value into the list of IP adresses
+	 */
 
-		goto done;
-	}
-
-	/* Extract and return namelist */
-
-	DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
-		  data->count, data->count == 1 ? "" : "es", name, name_type));
-
-	if (data->count) {
-
-		*ip_list = (struct in_addr *)malloc(
-			sizeof(struct in_addr) * data->count);
-		
-		memcpy(*ip_list, data->ip_list, sizeof(struct in_addr) * data->count);
-		
-		*num_names = data->count;
-		
-		for (i = 0; i < *num_names; i++)
-			DEBUGADD(5, ("%s%s", inet_ntoa((*ip_list)[i]),
-				     i == (*num_names - 1) ? "" : ", "));
+	*num_names = ipstr_list_parse(value, ip_list);
+		 
+	return num_names > 0;		/* true only if some ip has been fetched */
+}
 
-	}
 
-	DEBUGADD(5, ("\n"));
+/**
+ * Delete single namecache entry. Look at the
+ * gencache_iterate definition.
+ *
+ **/
 
-done:
-	SAFE_FREE(key.dptr);
-	SAFE_FREE(value.dptr);
-
-	return value.dsize > 0;
+static void flush_netbios_name(const char* key, const char *value, time_t timeout, void* dptr)
+{
+	gencache_del(key);
+	DEBUG(5, ("Deleting entry %s\n", key));
 }
 
-/* Flush all names from the name cache */
+
+/**
+ * Flush all names from the name cache.
+ * It's done by gencache_iterate()
+ *
+ * @return True upon successful deletion or
+ *         False in case of an error
+ **/
 
 void namecache_flush(void)
 {
-	int result;
-
-	if (!namecache_tdb)
+	if (!gencache_init())
 		return;
 
-	result = tdb_traverse(namecache_tdb, tdb_traverse_delete_fn, NULL);
-
-	if (result == -1)
-		DEBUG(5, ("namecache_flush: error deleting cache entries\n"));
-	else
-		DEBUG(5, ("namecache_flush: deleted %d cache entr%s\n", 
-			  result, result == 1 ? "y" : "ies"));
+	/* 
+	 * iterate through each NBT cache's entry and flush it
+	 * by flush_netbios_name function
+	 */
+	gencache_iterate(flush_netbios_name, NULL, "NBT/*");
+	DEBUG(5, ("Namecache flushed\n"));
 }
+
Index: libsmb/namequery.c
===================================================================
RCS file: /cvsroot/samba/source/libsmb/namequery.c,v
retrieving revision 1.111
diff -u -r1.111 namequery.c
--- libsmb/namequery.c	16 Aug 2002 00:25:47 -0000	1.111
+++ libsmb/namequery.c	3 Nov 2002 19:04:13 -0000
@@ -781,6 +781,7 @@
  or host name or NetBIOS name. This uses the name switch in the
  smb.conf to determine the order of name resolution.
 *********************************************************/
+/* TODO: restore static function */
 
 static BOOL internal_resolve_name(const char *name, int name_type,
 				  struct in_addr **return_iplist, int *return_count)
@@ -836,11 +837,6 @@
 			  if (resolve_hosts(name, return_iplist, return_count)) {
 				  result = True;
 				  goto done;
-			  } else {
-
-				  /* Store negative lookup result */
-
-				  namecache_store(name, name_type, 0, NULL);
 			  }
 		  }
 	  } else if(strequal( tok, "lmhosts")) {
@@ -915,7 +911,10 @@
   }
  
   /* Save in name cache */
-
+  for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
+    DEBUG(100, ("Storing name %s of type %d (ip: %s)\n", name,
+                name_type, inet_ntoa(*return_iplist[i])));
+    
   namecache_store(name, name_type, *return_count, *return_iplist);
 
   /* Display some debugging info */
Index: nsswitch/winbindd_util.c
===================================================================
RCS file: /cvsroot/samba/source/nsswitch/winbindd_util.c,v
retrieving revision 1.84
diff -u -r1.84 winbindd_util.c
--- nsswitch/winbindd_util.c	2 Nov 2002 01:35:18 -0000	1.84
+++ nsswitch/winbindd_util.c	3 Nov 2002 19:04:15 -0000
@@ -178,7 +178,7 @@
 		int i;
 
 		result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains,
-							  &names, &alt_names, &dom_sids);
+		                                          &names, &alt_names, &dom_sids);
 		if (!NT_STATUS_IS_OK(result)) {
 			continue;
 		}
@@ -187,9 +187,12 @@
 		   the access methods of its parent */
 		for(i = 0; i < num_domains; i++) {
 			DEBUG(10,("Found domain %s\n", names[i]));
-			add_trusted_domain(names[i], 
-					   alt_names?alt_names[i]:NULL, 
-					   domain->methods, &dom_sids[i]);
+			add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
+			                   domain->methods, &dom_sids[i]);
+			
+			/* store trusted domain in the cache */
+			trustdom_cache_store(names[i], alt_names ? alt_names[i] : NULL,
+			                     &dom_sids[i], t + WINBINDD_RESCAN_FREQ);
 		}
 	}
 
@@ -209,8 +212,10 @@
 	/* Add ourselves as the first entry */
 	domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL);
 
-	/* Now we *must* get the domain sid for our primary domain. Go into
-	   a holding pattern until that is available */
+	/* 
+	 * Now we *must* get the domain sid for our primary domain. Go into
+	 * a holding pattern until that is available
+	 */
 
 	result = cache_methods.domain_sid(domain, &domain->sid);
 	while (!NT_STATUS_IS_OK(result)) {
Index: rpcclient/cmd_lsarpc.c
===================================================================
RCS file: /cvsroot/samba/source/rpcclient/cmd_lsarpc.c,v
retrieving revision 1.66
diff -u -r1.66 cmd_lsarpc.c
--- rpcclient/cmd_lsarpc.c	4 Oct 2002 19:11:36 -0000	1.66
+++ rpcclient/cmd_lsarpc.c	3 Nov 2002 19:04:27 -0000
@@ -218,18 +218,16 @@
 	uint32 num_domains = 0;
 	int i;
 
-	if (argc > 2) {
-		printf("Usage: %s [enum context (0)]\n", argv[0]);
+	if (argc > 3) {
+		printf("Usage: %s [enum context (0)] [max size (5)]\n", argv[0]);
 		return NT_STATUS_OK;
 	}
 
-	if (argc == 2 && argv[1]) {
-		enum_ctx = atoi(argv[2]);
-	}	
-
+	if (argc >= 2 && argv[1]) enum_ctx = atoi(argv[1]);
+	if (argc == 3 && argv[2]) num_domains = atoi(argv[2]);
+	
 	result = cli_lsa_open_policy(cli, mem_ctx, True, 
-				     POLICY_VIEW_LOCAL_INFORMATION,
-				     &pol);
+	                             POLICY_VIEW_LOCAL_INFORMATION, &pol);
 
 	if (!NT_STATUS_IS_OK(result))
 		goto done;
Index: utils/net_cache.c
===================================================================
RCS file: /cvsroot/samba/source/utils/net_cache.c,v
retrieving revision 1.1
diff -u -r1.1 net_cache.c
--- utils/net_cache.c	11 Sep 2002 14:07:21 -0000	1.1
+++ utils/net_cache.c	3 Nov 2002 19:04:28 -0000
@@ -34,15 +34,33 @@
  * (print_cache_entry) and to flush it (delete_cache_entry).
  * Both of them are defined by first arg of gencache_iterate() routine.
  */
-static void print_cache_entry(const char* keystr, const char* datastr, const time_t timeout)
+static void print_cache_entry(const char* keystr, const char* datastr,
+                              const time_t timeout, void* dptr)
 {
-	char* timeout_str = ctime(&timeout);
-	timeout_str[strlen(timeout_str) - 1] = '\0';
-	d_printf("Key: %s\t\t Value: %s\t\t Timeout: %s %s\n", keystr, datastr,
-	         timeout_str, timeout > time(NULL) ? "": "(expired)");
+	char* timeout_str;
+	time_t now_t = time(NULL);
+	struct tm timeout_tm, *now_tm;
+	/* localtime returns statically allocated pointer, so timeout_tm
+	   has to be copied somewhere else */
+	memcpy(&timeout_tm, localtime(&timeout), sizeof(struct tm));
+	now_tm = localtime(&now_t);
+
+	/* form up timeout string depending whether it's today's date or not */
+	if (timeout_tm.tm_year != now_tm->tm_year ||
+	    timeout_tm.tm_mon != now_tm->tm_mon ||
+	    timeout_tm.tm_mday != now_tm->tm_mday)
+	    
+	    timeout_str = asctime(&timeout_tm);
+	else
+		asprintf(&timeout_str, "%.2d:%.2d:%.2d", timeout_tm.tm_hour,
+		         timeout_tm.tm_min, timeout_tm.tm_sec);
+	
+	d_printf("Key: %s\t Timeout: %s\t Value: %s  %s\n", keystr,
+	         timeout_str, datastr, timeout > now_t ? "": "(expired)");
 }
 
-static void delete_cache_entry(const char* keystr, const char* datastr, const time_t timeout)
+static void delete_cache_entry(const char* keystr, const char* datastr,
+                               const time_t timeout, void* dptr)
 {
 	if (!gencache_del(keystr))
 		d_printf("Couldn't delete entry! key = %s", keystr);
@@ -92,7 +110,7 @@
 	case 'h': timeout *= 60*60; break;
 	case 'd': timeout *= 60*60*24; break;
 	case 'w': timeout *= 60*60*24*7; break;  /* that's fair enough, I think :) */
-	}
+	};
 	
 	switch (sign) {
 	case '!': timeout = time(NULL) - timeout; break;
@@ -136,11 +154,11 @@
 		d_printf("New cache entry stored successfully.\n");
 		gencache_shutdown();
 		return 0;
-	} 
-
-	d_printf("Entry couldn't be added. Perhaps there's already such a key.\n");
-	gencache_shutdown();
-	return -1;
+	} else {
+		d_printf("Entry couldn't be added. Perhaps there's already such a key.\n");
+		gencache_shutdown();
+		return -1;
+	}
 }
 
 
@@ -175,11 +193,11 @@
 		d_printf("Cache entry set successfully.\n");
 		gencache_shutdown();
 		return 0;
+	} else {
+		d_printf("Entry couldn't be set. Perhaps there's no such a key.\n");
+		gencache_shutdown();
+		return -1;
 	}
-
-	d_printf("Entry couldn't be set. Perhaps there's no such a key.\n");
-	gencache_shutdown();
-	return -1;
 }
 
 
@@ -201,10 +219,10 @@
 	if(gencache_del(keystr)) {
 		d_printf("Entry deleted.\n");
 		return 0;
-	} 
-
-	d_printf("Couldn't delete specified entry\n");
-	return -1;
+	} else {
+		d_printf("Couldn't delete specified entry\n");
+		return -1;
+	}
 }
 
 
@@ -226,12 +244,12 @@
 	}
 	
 	if (gencache_get(keystr, &valuestr, &timeout)) {
-		print_cache_entry(keystr, valuestr, timeout);
+		print_cache_entry(keystr, valuestr, timeout, NULL);
 		return 0;
-	} 
-
-	d_printf("Failed to find entry\n");
-	return -1;
+	} else {
+		d_printf("Failed to find entry\n");
+		return -1;
+	}
 }
 
 
@@ -251,7 +269,7 @@
 	}
 	
 	pattern = argv[0];
-	gencache_iterate(print_cache_entry, pattern);
+	gencache_iterate(print_cache_entry, NULL, pattern);
 	return 0;
 }
 
@@ -265,7 +283,7 @@
 static int net_cache_list(int argc, const char **argv)
 {
 	const char* pattern = "*";
-	gencache_iterate(print_cache_entry, pattern);
+	gencache_iterate(print_cache_entry, NULL, pattern);
 	gencache_shutdown();
 	return 0;
 }
@@ -280,7 +298,7 @@
 static int net_cache_flush(int argc, const char **argv)
 {
 	const char* pattern = "*";
-	gencache_iterate(delete_cache_entry, pattern);
+	gencache_iterate(delete_cache_entry, NULL, pattern);
 	gencache_shutdown();
 	return 0;
 }
@@ -294,7 +312,7 @@
  **/
 static int net_cache_usage(int argc, const char **argv)
 {
-	d_printf("  net cache add \t add add new cache entry\n");
+	d_printf("  net cache add \t add new cache entry\n");
 	d_printf("  net cache set \t set new value for existing cache entry\n");
 	d_printf("  net cache del \t delete existing cache entry by key\n");
 	d_printf("  net cache flush \t delete all entries existing in the cache\n");
@@ -302,7 +320,19 @@
 	d_printf("  net cache search \t search for entries in the cache, by given pattern\n");
 	d_printf("  net cache list \t list all cache entries (just like search for \"*\")\n");
 	return -1;
-}
+};
+
+
+/**
+ * Verbose help
+ *
+ * @param argv ignored here
+ * @return always returns -1
+ **/
+static int net_cache_help(int argc, const char **argv)
+{
+	return -1;
+};
 
 
 /**
@@ -321,8 +362,10 @@
 		{"search", net_cache_search},
 		{"list", net_cache_list},
 		{"flush", net_cache_flush},
+		{"help", net_cache_help},
 		{NULL, NULL}
 	};
 
 	return net_run_function(argc, argv, func, net_cache_usage);
 }
+
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trustdom_cache.c
Type: text/x-csrc
Size: 5106 bytes
Desc: not available
Url : http://lists.samba.org/archive/samba-technical/attachments/20021103/aa8ae31f/trustdom_cache.bin


More information about the samba-technical mailing list