summaryrefslogtreecommitdiffstats
path: root/lib/libc/net/nss_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/net/nss_compat.c')
-rw-r--r--lib/libc/net/nss_compat.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/lib/libc/net/nss_compat.c b/lib/libc/net/nss_compat.c
new file mode 100644
index 0000000..8441103
--- /dev/null
+++ b/lib/libc/net/nss_compat.c
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Compatibility shims for the GNU C Library-style nsswitch interface.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <nss.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include "un-namespace.h"
+
+
+struct group;
+struct passwd;
+
+static int terminator;
+
+#define DECLARE_TERMINATOR(x) \
+static pthread_key_t _term_key_##x; \
+static void \
+_term_create_##x(void) \
+{ \
+ (void)_pthread_key_create(&_term_key_##x, NULL); \
+} \
+static void *_term_main_##x; \
+static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT
+
+#define SET_TERMINATOR(x, y) \
+do { \
+ if (_pthread_main_np()) \
+ _term_main_##x = (y); \
+ else { \
+ (void)_pthread_once(&_term_once_##x, _term_create_##x); \
+ (void)_pthread_setspecific(_term_key_##x, y); \
+ } \
+} while (0)
+
+#define CHECK_TERMINATOR(x) \
+(_pthread_main_np() ? \
+ (_term_main_##x) : \
+ ((void)_pthread_once(&_term_once_##x, _term_create_##x), \
+ _pthread_getspecific(_term_key_##x)))
+
+
+
+DECLARE_TERMINATOR(group);
+
+
+int
+__nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(const char *, struct group *, char *, size_t, int *);
+ const char *name;
+ struct group *grp;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ name = va_arg(ap, const char *);
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(name, grp, buffer, bufsize, errnop);
+ if (status == NS_SUCCESS)
+ *(struct group **)retval = grp;
+ return (__nss_compat_result(status));
+}
+
+
+int
+__nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(gid_t, struct group *, char *, size_t, int *);
+ gid_t gid;
+ struct group *grp;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ gid = va_arg(ap, gid_t);
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(gid, grp, buffer, bufsize, errnop);
+ if (status == NS_SUCCESS)
+ *(struct group **)retval = grp;
+ return (__nss_compat_result(status));
+}
+
+
+int
+__nss_compat_getgrent_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(struct group *, char *, size_t, int *);
+ struct group *grp;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ if (CHECK_TERMINATOR(group))
+ return (NS_NOTFOUND);
+ fn = mdata;
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(grp, buffer, bufsize, errnop);
+ if (status == NS_SUCCESS)
+ *(struct group **)retval = grp;
+ else
+ SET_TERMINATOR(group, &terminator);
+ return (__nss_compat_result(status));
+}
+
+
+int
+__nss_compat_setgrent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(group, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
+
+
+int
+__nss_compat_endgrent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(group, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
+
+
+
+DECLARE_TERMINATOR(passwd);
+
+
+int
+__nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(const char *, struct passwd *, char *, size_t, int *);
+ const char *name;
+ struct passwd *pwd;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ name = va_arg(ap, const char *);
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(name, pwd, buffer, bufsize, errnop);
+ if (status == NS_SUCCESS)
+ *(struct passwd **)retval = pwd;
+ return (__nss_compat_result(status));
+}
+
+
+int
+__nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(uid_t, struct passwd *, char *, size_t, int *);
+ uid_t uid;
+ struct passwd *pwd;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ uid = va_arg(ap, uid_t);
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(uid, pwd, buffer, bufsize, errnop);
+ if (status == NS_SUCCESS)
+ *(struct passwd **)retval = pwd;
+ return (__nss_compat_result(status));
+}
+
+
+int
+__nss_compat_getpwent_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(struct passwd *, char *, size_t, int *);
+ struct passwd *pwd;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ if (CHECK_TERMINATOR(passwd))
+ return (NS_NOTFOUND);
+ fn = mdata;
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(pwd, buffer, bufsize, errnop);
+ if (status == NS_SUCCESS)
+ *(struct passwd **)retval = pwd;
+ else
+ SET_TERMINATOR(passwd, &terminator);
+ return (__nss_compat_result(status));
+}
+
+
+int
+__nss_compat_setpwent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(passwd, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
+
+
+int
+__nss_compat_endpwent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(passwd, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
OpenPOWER on IntegriCloud