PERFORCE change 99763 for review
Michael Bushkov
bushman at FreeBSD.org
Wed Jun 21 16:32:38 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=99763
Change 99763 by bushman at 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) <<<
More information about the p4-projects
mailing list