Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jun 2006 16:32:36 GMT
From:      Michael Bushkov <bushman@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 99763 for review
Message-ID:  <200606211632.k5LGWanG003125@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99763

Change 99763 by bushman@bushman_nss_ldap_cached on 2006/06/21 16:32:08

	Agents system of the caching daemon reworked in order to support new nsdispatch behavior (when all nss-modules are external). Hosts agent finally implemented.

Affected files ...

.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/Makefile#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agent.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agent.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/Makefile.inc#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/group.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/group.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/hosts.c#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/hosts.h#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/net.c#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/net.h#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/passwd.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/passwd.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/proto.c#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/proto.h#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/rpc.c#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/rpc.h#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/services.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/services.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cached.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/debug.h#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/mp_rs_query.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#2 edit

Differences ...

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/Makefile#2 (text) ====

@@ -8,7 +8,7 @@
 SRCS= agent.c cached.c cachedcli.c cachelib.c cacheplcs.c debug.c log.c \
 	config.c query.c mp_ws_query.c mp_rs_query.c singletons.c protocol.c \
 	parser.c
-CFLAGS+= -DCONFIG_PATH="\"${PREFIX}/etc/cached.conf\""
+CFLAGS+= -g -DCONFIG_PATH="\"${PREFIX}/etc/cached.conf\""
 DPADD+=${LIBM} ${LIBPTHREAD} ${LIBUTIL}
 LDADD+=${LIBM} ${LIBPTHREAD} ${LIBUTIL}
 LDFLAGS+= -Xlinker --export-dynamic

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agent.c#2 (text) ====

@@ -34,6 +34,11 @@
 #include "agent.h"
 #include "debug.h"
 
+const ns_dtab emptydtab[] = {
+	{ NULL, NULL, NULL }
+};
+
+
 static int
 agent_cmp_func(const void *a1, const void *a2)
 {
@@ -54,6 +59,47 @@
 	return (res);
 }
 
+int 
+agent_marshal_results(char **buffer, size_t *bufsize,
+	agent_marshal_func marshal_func, void *cache_mdata, void *retval, ...)
+{
+	va_list ap;
+	size_t size;
+	int rv;
+	
+	va_start(ap, retval);
+	if (*buffer == NULL) {
+		*buffer = malloc(AGENT_BUFFER_STORAGE_INITIAL);
+		if (*buffer == NULL)
+			return (NS_UNAVAIL);
+		*bufsize = AGENT_BUFFER_STORAGE_INITIAL;		
+	}
+		
+	size = *bufsize;
+	rv = marshal_func(*buffer, &size, retval, ap, cache_mdata);
+	if (rv == NS_RETURN) {
+		*bufsize = size;
+		if (*bufsize <= AGENT_BUFFER_STORAGE_MAX) {			
+			*buffer = (char *)realloc(*buffer, *bufsize);
+			if (*buffer == NULL)
+				return (NS_UNAVAIL);
+
+			size = *bufsize;
+			rv = marshal_func(*buffer, &size, retval, ap,
+				cache_mdata);
+		}
+	}
+			
+	if (rv != NS_SUCCESS) {
+		free(*buffer);
+		*buffer = NULL;
+		*bufsize = 0;
+	}
+	
+	va_end(ap);
+	return (rv);
+}
+
 struct agent_table *
 init_agent_table()
 {

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agent.h#2 (text) ====

@@ -29,6 +29,92 @@
 #ifndef __CACHED_AGENT_H__
 #define __CACHED_AGENT_H__
 
+#include <stdarg.h>
+#include <nsswitch.h>
+
+extern int __isthreaded;
+
+/* TLS handling routine obtained from libc/include/nss_tls.h */
+#define AGENT_TLS_HANDLING(name)				\
+static pthread_key_t name##_state_key;				\
+static	void	 name##_keyinit(void);				\
+static	int	 name##_getstate(struct name##_state **);	\
+\
+static void								\
+name##_keyinit(void)							\
+{									\
+	(void)pthread_key_create(&name##_state_key, name##_endstate);	\
+}									\
+\
+static int							\
+name##_getstate(struct name##_state **p)			\
+{								\
+	static struct name##_state st;				\
+	static pthread_once_t	keyinit = PTHREAD_ONCE_INIT;	\
+	int			rv;				\
+								\
+	if (!__isthreaded || pthread_main_np() != 0) {		\
+		*p = &st;					\
+		return (0);					\
+	}							\
+	rv = pthread_once(&keyinit, name##_keyinit);		\
+	if (rv != 0)						\
+		return (rv);					\
+	*p = (struct name##_state *)pthread_getspecific(name##_state_key);\
+	if (*p != NULL)						\
+		return (0);					\
+	*p = calloc(1, sizeof(**p));				\
+	if (*p == NULL)						\
+		return (ENOMEM);				\
+	rv = pthread_setspecific(name##_state_key, *p);	\
+	if (rv != 0) {						\
+		free(*p);					\
+		*p = NULL;					\
+	}							\
+	return (rv);						\
+}								\
+/* allow the macro invocation to end with a semicolon */	\
+struct _clashproof_bmVjdGFy
+
+
+#define AGENT_DECLARE_BUFFER_TLS_HANDLING(name)			\
+struct name##_state {						\
+	char *buffer;						\
+	size_t bufsize;						\
+};								\
+								\
+static void							\
+name##_endstate(void *p)					\
+{								\
+	free(p);						\
+}								\
+								\
+AGENT_TLS_HANDLING(name);				
+
+enum agent_buffer_constants
+{
+	AGENT_BUFFER_STORAGE_INITIAL	= 1 << 10, /* 1 KByte */
+	AGENT_BUFFER_STORAGE_MAX	= 1 << 20, /* 1 MByte */
+};
+
+#define AGENT_BUFFER_TLS_HANDLING_INIT(st)				\
+	{								\
+		if (st->buffer == NULL) {				\
+			st->buffer = malloc(AGENT_BUFFER_STORAGE_INITIAL);\
+			st->bufsize = AGENT_BUFFER_STORAGE_INITIAL;	\
+		}							\
+	}								
+
+#define AGENT_BUFFER_TLS_HANDLING_CHECK(st) (st->buffer == NULL)
+	
+#define AGENT_BUFFER_TLS_HANDLING_RESIZE(st)			\
+	free(st->buffer);					\
+	st->bufsize <<= 1;					\
+	if (st->bufsize < AGENT_BUFFER_STORAGE_MAX)		\
+		st->buffer = malloc(st->bufsize);		\
+	else							\
+		st->buffer = NULL
+
 /*
  * Agents are used to perform the actual lookups from the caching daemon.
  * There are two types of daemons: for common requests and for multipart
@@ -41,21 +127,28 @@
     MULTIPART_AGENT = 1
 };
 
+typedef int (*agent_marshal_func)(char *, size_t *, void *, va_list, void *);
+typedef int (*agent_lookup_func)(const char *, size_t, char **, size_t *);
+typedef void *(*agent_mp_init_func)();
+typedef int (*agent_mp_lookup_func)(char **, size_t *, void *);
+typedef void (*agent_mp_destroy_func)(void *);
+
 struct agent {
-   	char	*name;
+   	char	*name;	
     	enum agent_type type;
 };
 
 struct common_agent {
     	struct agent	parent;
-	int (*lookup_func)(const char *, size_t, char **, size_t *);
+	agent_lookup_func lookup_func;
 };
 
 struct multipart_agent {
     	struct agent	parent;
-	void *(*mp_init_func)();
-    	int (*mp_lookup_func)(char **, size_t *, void *);
-	void (*mp_destroy_func)(void *);
+	
+	agent_mp_init_func mp_init_func;
+	agent_mp_lookup_func mp_lookup_func;
+	agent_mp_destroy_func mp_destroy_func;
 };
 
 struct agent_table {
@@ -63,6 +156,10 @@
 	size_t		agents_num;
 };
 
+extern const ns_dtab emptydtab[];
+
+extern int agent_marshal_results(char **, size_t *, agent_marshal_func, 
+	void *, void *, ...);
 extern struct agent_table *init_agent_table();
 extern void register_agent(struct agent_table *, struct agent *);
 extern struct agent *find_agent(struct agent_table *, const char *,

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/Makefile.inc#2 (text) ====

@@ -1,3 +1,3 @@
 # $FreeBSD: src/usr.sbin/cached/agents/Makefile.inc,v 1.1 2006/04/28 12:03:38 ume Exp $
 
-SRCS += passwd.c group.c services.c
+SRCS += passwd.c group.c services.c hosts.c

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/group.c#2 (text) ====

@@ -31,28 +31,73 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <assert.h>
+#include <errno.h>
+#include <nsswitch.h>
 #include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
 #include <grp.h>
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include "../debug.h"
-#include "passwd.h"
+#include "group.h"
+
+static const ns_src defaultsrc[] = {
+	{ NSSRC_COMPAT, NS_SUCCESS },
+	{ NULL, 0 }
+};
+
 
-static int group_marshal_func(struct group *, char *, size_t *);
+static int group_marshal_func(char *, size_t *, void *, va_list, void *);
 static int group_lookup_func(const char *, size_t, char **, size_t *);
 static void *group_mp_init_func();
-static int group_mp_lookup_func(char **, size_t *, void *);
-static void group_mp_destroy_func(void *);
+static int group_mp_lookup_func(char **out_buffer, size_t *out_size, void *mdata);
+static void group_mp_destroy_func(void *mdata);
+
+AGENT_DECLARE_BUFFER_TLS_HANDLING(group);
+
+#ifndef _ALIGNBYTES
+#define _ALIGNBYTES ALIGNBYTES
+#endif
+
+#ifndef _ALIGN
+#define _ALIGN(x) ALIGN(x)
+#endif
 
 static int
-group_marshal_func(struct group *grp, char *buffer, size_t *buffer_size)
+group_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+    void *cache_mdata)
 {
+	char *name;
+	gid_t gid;
+	struct group *grp;
+	char *orig_buf;
+	size_t orig_buf_size;
+
 	struct group new_grp;
 	size_t desired_size, size, mem_size;
 	char *p, **mem;
 
-	TRACE_IN(group_marshal_func);
-	desired_size = ALIGNBYTES + sizeof(struct group) + sizeof(char *);
+	switch ((enum nss_lookup_type)cache_mdata) {
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		gid = va_arg(ap, gid_t);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		/* should be unreachable */
+		return (NS_UNAVAIL);
+	}
+
+	grp = va_arg(ap, struct group *);
+	orig_buf = va_arg(ap, char *);
+	orig_buf_size = va_arg(ap, size_t);
+
+	desired_size = _ALIGNBYTES + sizeof(struct group) + sizeof(char *);
 
 	if (grp->gr_name != NULL)
 		desired_size += strlen(grp->gr_name) + 1;
@@ -66,12 +111,12 @@
 			++mem_size;
 		}
 
-		desired_size += ALIGNBYTES + (mem_size + 1) * sizeof(char *);
+		desired_size += _ALIGNBYTES + (mem_size + 1) * sizeof(char *);
 	}
 
-	if ((desired_size > *buffer_size) || (buffer == NULL)) {
+	if (desired_size > *buffer_size) {
+		/* this assignment is here for future use */
 		*buffer_size = desired_size;
-		TRACE_OUT(group_marshal_func);
 		return (NS_RETURN);
 	}
 
@@ -81,7 +126,7 @@
 	*buffer_size = desired_size;
 	p = buffer + sizeof(struct group) + sizeof(char *);
 	memcpy(buffer + sizeof(struct group), &p, sizeof(char *));
-	p = (char *)ALIGN(p);
+	p = (char *)_ALIGN(p);
 
 	if (new_grp.gr_name != NULL) {
 		size = strlen(new_grp.gr_name);
@@ -98,7 +143,7 @@
 	}
 
 	if (new_grp.gr_mem != NULL) {
-		p = (char *)ALIGN(p);
+		p = (char *)_ALIGN(p);
 		memcpy(p, new_grp.gr_mem, sizeof(char *) * mem_size);
 		new_grp.gr_mem = (char **)p;
 		p += sizeof(char *) * (mem_size + 1);
@@ -112,24 +157,24 @@
 	}
 
 	memcpy(buffer, &new_grp, sizeof(struct group));
-	TRACE_OUT(group_marshal_func);
 	return (NS_SUCCESS);
 }
 
 static int
-group_lookup_func(const char *key, size_t key_size, char **buffer,
-	size_t *buffer_size)
+group_lookup_func(const char *key, size_t key_size, char **out_buffer,
+	size_t *out_size)
 {
+	struct group_state *st;
+	struct group grp, *retval;	
 	enum nss_lookup_type lookup_type;
-	char	*name;
+	char *name;
+	gid_t	gid;
+	int	error, result;
 	size_t	size;
-	gid_t	gid;
-
-	struct group *result;
 
 	TRACE_IN(group_lookup_func);
-	assert(buffer != NULL);
-	assert(buffer_size != NULL);
+	assert(out_buffer != NULL);
+	assert(out_size != NULL);
 
 	if (key_size < sizeof(enum nss_lookup_type)) {
 		TRACE_OUT(group_lookup_func);
@@ -137,18 +182,19 @@
 	}
 	memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
 
+	name = NULL;
 	switch (lookup_type) {
 	case nss_lt_name:
-		size = key_size - sizeof(enum nss_lookup_type)	+ 1;
+		size = key_size - sizeof(enum nss_lookup_type)  + 1;
 		name = (char *)malloc(size);
 		assert(name != NULL);
 		memset(name, 0, size);
 		memcpy(name, key + sizeof(enum nss_lookup_type), size - 1);
-		break;
+                break;
 	case nss_lt_id:
 		if (key_size < sizeof(enum nss_lookup_type) +
 			sizeof(gid_t)) {
-			TRACE_OUT(passwd_lookup_func);
+			TRACE_OUT(group_lookup_func);
 			return (NS_UNAVAIL);
 		}
 
@@ -159,29 +205,67 @@
 		return (NS_UNAVAIL);
 	}
 
+	result = group_getstate(&st);
+	AGENT_BUFFER_TLS_HANDLING_INIT(st);
+	if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0) {
+		free(name);
+		TRACE_OUT(group_lookup_func);
+		return (NS_UNAVAIL);
+	}
+	
 	switch (lookup_type) {
 	case nss_lt_name:
-		TRACE_STR(name);
-		result = getgrnam(name);
-		free(name);
+		do {
+			result = nsdispatch(&retval, emptydtab, NSDB_GROUP, 
+				"getgrnam_r", defaultsrc, name,
+				&grp, st->buffer, st->bufsize, &error);
+			
+			if ((result == NS_RETURN) && (error == ERANGE)) {
+				AGENT_BUFFER_TLS_HANDLING_RESIZE(st);
+				if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0) {
+					free(name);
+					TRACE_OUT(group_lookup_func);
+					return (NS_UNAVAIL);
+				}
+			}
+		} while ((result == NS_RETURN) && (error == ERANGE));
+
+		if (result == NS_SUCCESS)
+			result = agent_marshal_results(out_buffer, out_size,
+				group_marshal_func, (void *)nss_lt_name, 
+				retval, name, &grp,
+				st->buffer, st->bufsize, &error);
+
 		break;
 	case nss_lt_id:
-		result = getgrgid(gid);
+		do {
+			result = nsdispatch(&retval, emptydtab, NSDB_GROUP, 
+				"getgrgid_r", defaultsrc, gid,
+				&grp, st->buffer, st->bufsize, &error);
+			
+			if ((result == NS_RETURN) && (error == ERANGE)) {
+				AGENT_BUFFER_TLS_HANDLING_RESIZE(st);
+				if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0) {
+					TRACE_OUT(group_lookup_func);
+					return (NS_UNAVAIL);
+				}
+			}
+		} while ((result == NS_RETURN) && (error == ERANGE));
+
+		if (result == NS_SUCCESS)
+			result = agent_marshal_results(out_buffer, out_size,
+				group_marshal_func,
+				(void *)nss_lt_id, retval, gid,
+				&grp, st->buffer, st->bufsize, &error);
 		break;
 	default:
 		/* SHOULD NOT BE REACHED */
 		break;
-	}
+	}	
 
-	if (result != NULL) {
-		group_marshal_func(result, NULL, buffer_size);
-		*buffer = (char *)malloc(*buffer_size);
-		assert(*buffer != NULL);
-		group_marshal_func(result, *buffer, buffer_size);
-	}
-
+	free(name);
 	TRACE_OUT(group_lookup_func);
-	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+	return (result);
 }
 
 static void *
@@ -195,21 +279,40 @@
 }
 
 static int
-group_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
+group_mp_lookup_func(char **out_buffer, size_t *out_size, void *mdata)
 {
-	struct group *result;
+	struct group_state *st;
+	struct group grp, *retval;
+	int result, error;
 
 	TRACE_IN(group_mp_lookup_func);
-	result = getgrent();
-	if (result != NULL) {
-		group_marshal_func(result, NULL, buffer_size);
-		*buffer = (char *)malloc(*buffer_size);
-		assert(*buffer != NULL);
-		group_marshal_func(result, *buffer, buffer_size);
+
+	result = group_getstate(&st);
+	AGENT_BUFFER_TLS_HANDLING_INIT(st);
+	if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0)
+		return (NS_UNAVAIL);
+	
+	do {
+		result = nsdispatch(&retval, emptydtab, NSDB_GROUP, 
+			"getgrent_r", defaultsrc, &grp, st->buffer, 
+			st->bufsize, &error);
+			
+		if ((result == NS_RETURN) && (error == ERANGE)) {
+			AGENT_BUFFER_TLS_HANDLING_RESIZE(st);
+			if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0)
+				return (NS_UNAVAIL);
+		}
+	} while ((result == NS_RETURN) && (error == ERANGE));
+		
+	if (result == NS_SUCCESS) {
+		result = agent_marshal_results(out_buffer,
+			out_size, group_marshal_func, 
+			(void *)nss_lt_all, retval, &grp,
+			 st->buffer, st->bufsize, &error);
 	}
 
 	TRACE_OUT(group_mp_lookup_func);
-	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+	return (result);
 }
 
 static void

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/group.h#2 (text) ====


==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/passwd.c#2 (text) ====

@@ -30,29 +30,65 @@
 
 #include <sys/types.h>
 #include <assert.h>
+#include <errno.h>
+#include <nsswitch.h>
 #include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
 #include <pwd.h>
 #include <string.h>
 #include <stdlib.h>
 #include "../debug.h"
 #include "passwd.h"
 
-static int passwd_marshal_func(struct passwd *, char *, size_t *);
+static const ns_src defaultsrc[] = {
+	{ NSSRC_COMPAT, NS_SUCCESS },
+	{ NULL, 0 }
+};
+
+
+static int passwd_marshal_func(char *, size_t *, void *, va_list, void *);
 static int passwd_lookup_func(const char *, size_t, char **, size_t *);
 static void *passwd_mp_init_func();
-static int passwd_mp_lookup_func(char **, size_t *, void *);
+static int passwd_mp_lookup_func(char **out_buffer, size_t *out_size, void *mdata);
 static void passwd_mp_destroy_func(void *mdata);
 
+AGENT_DECLARE_BUFFER_TLS_HANDLING(passwd);
+
 static int
-passwd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size)
+passwd_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+    void *cache_mdata)
 {
-	char		*p;
-	struct passwd	new_pwd;
-	size_t		desired_size, size;
+	char *name;
+	uid_t uid;
+	struct passwd *pwd;
+	char *orig_buf;
+	size_t orig_buf_size;
+
+	struct passwd new_pwd;
+	size_t desired_size, size;
+	char *p;
+
+	switch ((enum nss_lookup_type)cache_mdata) {
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		uid = va_arg(ap, uid_t);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		/* should be unreachable */
+		return (NS_UNAVAIL);
+	}
+
+	pwd = va_arg(ap, struct passwd *);
+	orig_buf = va_arg(ap, char *);
+	orig_buf_size = va_arg(ap, size_t);
 
-	TRACE_IN(passwd_marshal_func);
 	desired_size = sizeof(struct passwd) + sizeof(char *) +
-		strlen(pwd->pw_name) + 1;
+	    strlen(pwd->pw_name) + 1;
 	if (pwd->pw_passwd != NULL)
 		desired_size += strlen(pwd->pw_passwd) + 1;
 	if (pwd->pw_class != NULL)
@@ -64,9 +100,9 @@
 	if (pwd->pw_shell != NULL)
 		desired_size += strlen(pwd->pw_shell) + 1;
 
-	if ((*buffer_size < desired_size) || (buffer == NULL)) {
+	if (*buffer_size < desired_size) {
+		/* this assignment is here for future use */
 		*buffer_size = desired_size;
-		TRACE_OUT(passwd_marshal_func);
 		return (NS_RETURN);
 	}
 
@@ -120,34 +156,35 @@
 	}
 
 	memcpy(buffer, &new_pwd, sizeof(struct passwd));
-	TRACE_OUT(passwd_marshal_func);
 	return (NS_SUCCESS);
 }
 
 static int
-passwd_lookup_func(const char *key, size_t key_size, char **buffer,
-	size_t *buffer_size)
+passwd_lookup_func(const char *key, size_t key_size, char **out_buffer,
+	size_t *out_size)
 {
+	struct passwd_state *st;
+	struct passwd pwd, *retval;	
 	enum nss_lookup_type lookup_type;
-	char	*login;
+	char *login;
+	uid_t	uid;
+	int	error, result;
 	size_t	size;
-	uid_t	uid;
 
-	struct passwd *result;
-
 	TRACE_IN(passwd_lookup_func);
-	assert(buffer != NULL);
-	assert(buffer_size != NULL);
+	assert(out_buffer != NULL);
+	assert(out_size != NULL);
 
-	if (key_size < sizeof(enum nss_lookup_type)) {
+	if (key_size < sizeof(enum nss_lookup_type) + 1) {
 		TRACE_OUT(passwd_lookup_func);
 		return (NS_UNAVAIL);
 	}
 	memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
 
+	login = NULL;
 	switch (lookup_type) {
 	case nss_lt_name:
-		size = key_size - sizeof(enum nss_lookup_type)	+ 1;
+		size = key_size - sizeof(enum nss_lookup_type)  + 1;
 		login = (char *)malloc(size);
 		assert(login != NULL);
 		memset(login, 0, size);
@@ -167,28 +204,67 @@
 		return (NS_UNAVAIL);
 	}
 
+	result = passwd_getstate(&st);
+	AGENT_BUFFER_TLS_HANDLING_INIT(st);
+	if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0) {
+		free(login);
+		TRACE_OUT(passwd_lookup_func);
+		return (NS_UNAVAIL);
+	}
+	
 	switch (lookup_type) {
 	case nss_lt_name:
-		result = getpwnam(login);
-		free(login);
+		do {
+			result = nsdispatch(&retval, emptydtab, NSDB_PASSWD, 
+				"getpwnam_r", defaultsrc, login,
+				&pwd, st->buffer, st->bufsize, &error);
+			
+			if ((result == NS_RETURN) && (error == ERANGE)) {
+				AGENT_BUFFER_TLS_HANDLING_RESIZE(st);
+				if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0) {
+					free(login);
+					TRACE_OUT(passwd_lookup_func);
+					return (NS_UNAVAIL);
+				}
+			}
+		} while ((result == NS_RETURN) && (error == ERANGE));
+
+		if (result == NS_SUCCESS)
+			result = agent_marshal_results(out_buffer, out_size,
+				passwd_marshal_func, (void *)nss_lt_name, 
+				retval, login, &pwd,
+				st->buffer, st->bufsize, &error);
+
 		break;
 	case nss_lt_id:
-		result = getpwuid(uid);
+		do {
+			result = nsdispatch(&retval, emptydtab, NSDB_SERVICES, 
+				"getpwuid_r", defaultsrc, uid,
+				&pwd, st->buffer, st->bufsize, &error);
+			
+			if ((result == NS_RETURN) && (error == ERANGE)) {
+				AGENT_BUFFER_TLS_HANDLING_RESIZE(st);
+				if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0) {
+					TRACE_OUT(passwd_lookup_func);
+					return (NS_UNAVAIL);
+				}
+			}
+		} while ((result == NS_RETURN) && (error == ERANGE));
+
+		if (result == NS_SUCCESS)
+			result = agent_marshal_results(out_buffer, out_size,
+				passwd_marshal_func,
+				(void *)nss_lt_id, retval, uid,
+				&pwd, st->buffer, st->bufsize, &error);
 		break;
 	default:
 		/* SHOULD NOT BE REACHED */
 		break;
-	}
+	}	
 
-	if (result != NULL) {
-		passwd_marshal_func(result, NULL, buffer_size);
-		*buffer = (char *)malloc(*buffer_size);
-		assert(*buffer != NULL);
-		passwd_marshal_func(result, *buffer, buffer_size);
-	}
-
+	free(login);
 	TRACE_OUT(passwd_lookup_func);
-	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+	return (result);
 }
 
 static void *
@@ -202,21 +278,40 @@
 }
 
 static int
-passwd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata)
+passwd_mp_lookup_func(char **out_buffer, size_t *out_size, void *mdata)
 {
-	struct passwd	*result;
+	struct passwd_state *st;
+	struct passwd pwd, *retval;
+	int result, error;
 
 	TRACE_IN(passwd_mp_lookup_func);
-	result = getpwent();
-	if (result != NULL) {
-		passwd_marshal_func(result, NULL, buffer_size);
-		*buffer = (char *)malloc(*buffer_size);
-		assert(*buffer != NULL);
-		passwd_marshal_func(result, *buffer, buffer_size);
+
+	result = passwd_getstate(&st);
+	AGENT_BUFFER_TLS_HANDLING_INIT(st);
+	if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0)
+		return (NS_UNAVAIL);
+	
+	do {
+		result = nsdispatch(&retval, emptydtab, NSDB_PASSWD, 
+			"getpwent_r", defaultsrc, &pwd, st->buffer, 
+			st->bufsize, &error);
+			
+		if ((result == NS_RETURN) && (error == ERANGE)) {
+			AGENT_BUFFER_TLS_HANDLING_RESIZE(st);
+			if (AGENT_BUFFER_TLS_HANDLING_CHECK(st) != 0)
+				return (NS_UNAVAIL);
+		}
+	} while ((result == NS_RETURN) && (error == ERANGE));
+		
+	if (result == NS_SUCCESS) {
+		result = agent_marshal_results(out_buffer,
+			out_size, passwd_marshal_func, 
+			(void *)nss_lt_all, retval, &pwd,
+			 st->buffer, st->bufsize, &error);
 	}
 
 	TRACE_OUT(passwd_mp_lookup_func);
-	return (result == NULL ? NS_NOTFOUND : NS_SUCCESS);
+	return (result);
 }
 
 static void

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/passwd.h#2 (text) ====


==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/agents/services.c#2 (text) ====

@@ -31,31 +31,70 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <assert.h>
+#include <errno.h>
 #include <nsswitch.h>
 #include <netdb.h>
+#include <pthread.h>
+#include <pthread_np.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "../debug.h"
 #include "services.h"
 
-static int services_marshal_func(struct servent *, char *, size_t *);
+static const ns_src defaultsrc[] = {
+	{ NSSRC_COMPAT, NS_SUCCESS },
+	{ NULL, 0 }
+};
+
+
+static int services_marshal_func(char *, size_t *, void *, va_list, void *);
 static int services_lookup_func(const char *, size_t, char **, size_t *);
 static void *services_mp_init_func();
-static int services_mp_lookup_func(char **, size_t *, void *);
-static void services_mp_destroy_func(void *);
+static int services_mp_lookup_func(char **out_buffer, size_t *out_size, void *mdata);
+static void services_mp_destroy_func(void *mdata);
+
+AGENT_DECLARE_BUFFER_TLS_HANDLING(servent);
 
 static int
-services_marshal_func(struct servent *serv, char *buffer, size_t *buffer_size)
+services_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+    void *cache_mdata)
 {
-	struct servent	new_serv;
-	size_t	desired_size;
-	char	**alias;
-	char	*p;
-	size_t	size;
-	size_t	aliases_size;
+	char *name;
+	char *proto;
+	int port;
+	struct servent *serv;
+	char *orig_buf;
+	size_t orig_buf_size;
+
+	struct servent new_serv;
+	size_t desired_size;
+	char **alias;
+	char *p;
+	size_t size;
+	size_t aliases_size;
+
+	switch ((enum nss_lookup_type)cache_mdata) {
+	case nss_lt_name:
+		name = va_arg(ap, char *);
+		proto = va_arg(ap, char *);
+		break;
+	case nss_lt_id:
+		port = va_arg(ap, int);
+		proto = va_arg(ap, char *);
+		break;
+	case nss_lt_all:
+		break;
+	default:
+		/* should be unreachable */
+		return (NS_UNAVAIL);
+	}
+
+	serv = va_arg(ap, struct servent *);
+	orig_buf = va_arg(ap, char *);
+	orig_buf_size = va_arg(ap, size_t);
 
-	TRACE_IN(services_marshal_func);
-	desired_size = ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
+	desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
 	if (serv->s_name != NULL)
 		desired_size += strlen(serv->s_name) + 1;
 	if (serv->s_proto != NULL)
@@ -68,13 +107,13 @@
 			++aliases_size;
 		}
 
-		desired_size += ALIGNBYTES + sizeof(char *) *
-		    (aliases_size + 1);
+		desired_size += _ALIGNBYTES +
+		    sizeof(char *) * (aliases_size + 1);
 	}
 
-	if ((*buffer_size < desired_size) || (buffer == NULL)) {
+	if (*buffer_size < desired_size) {
+		/* this assignment is here for future use */
 		*buffer_size = desired_size;
-		TRACE_OUT(services_marshal_func);
 		return (NS_RETURN);
 	}
 
@@ -84,7 +123,7 @@
 	*buffer_size = desired_size;
 	p = buffer + sizeof(struct servent) + sizeof(char *);
 	memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
-	p = (char *)ALIGN(p);
+	p = (char *)_ALIGN(p);
 
 	if (new_serv.s_name != NULL) {
 		size = strlen(new_serv.s_name);
@@ -101,7 +140,7 @@
 	}
 
 	if (new_serv.s_aliases != NULL) {
-		p = (char *)ALIGN(p);
+		p = (char *)_ALIGN(p);
 		memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
 		new_serv.s_aliases = (char **)p;
 		p += sizeof(char *) * (aliases_size + 1);
@@ -115,26 +154,24 @@
 	}
 
 	memcpy(buffer, &new_serv, sizeof(struct servent));
-	TRACE_OUT(services_marshal_func);
 	return (NS_SUCCESS);
 }
 
 static int
-services_lookup_func(const char *key, size_t key_size, char **buffer,
-	size_t *buffer_size)
+services_lookup_func(const char *key, size_t key_size, char **out_buffer,
+	size_t *out_size)
 {
+	struct servent_state *st;
+	struct servent serv, *retval;
+	char *name;
+	char *proto;
+	size_t	size, size2;
 	enum nss_lookup_type lookup_type;
-	char	*name = NULL;
-	char	*proto = NULL;
-	size_t	size, size2;
-	int	port;
+	int port, error, result;
 
-	struct servent *result;
-
 	TRACE_IN(services_lookup_func);
-
-	assert(buffer != NULL);
-	assert(buffer_size != NULL);
+	assert(out_buffer != NULL);
+	assert(out_size != NULL);	
 
 	if (key_size < sizeof(enum nss_lookup_type)) {
 		TRACE_OUT(passwd_lookup_func);
@@ -142,8 +179,9 @@
 	}
 	memcpy(&lookup_type, key, sizeof(enum nss_lookup_type));
 
+	name = NULL;
+	proto = NULL;
 	switch (lookup_type) {
-	case nss_lt_name:
 		size = key_size - sizeof(enum nss_lookup_type);

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606211632.k5LGWanG003125>