summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2010-04-04 08:31:03 +0000
committerume <ume@FreeBSD.org>2010-04-04 08:31:03 +0000
commit7915a506541b9b6b29c31dec9643b7da9649252c (patch)
tree51cf07752246673a6578819cb07fbdc4a934f31d /lib/libc
parent6e468628cf2ea2fc37557d96be5e76436f206aed (diff)
downloadFreeBSD-src-7915a506541b9b6b29c31dec9643b7da9649252c.zip
FreeBSD-src-7915a506541b9b6b29c31dec9643b7da9649252c.tar.gz
Add capability to use a db version of services. It is enabled by
specifying `db' as source of service in /etc/nsswitch.conf. MFC after: 2 weeks
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/net/getservent.c202
-rw-r--r--lib/libc/net/nsdispatch.33
2 files changed, 204 insertions, 1 deletions
diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c
index 3dcad3f..6e04f34 100644
--- a/lib/libc/net/getservent.c
+++ b/lib/libc/net/getservent.c
@@ -37,7 +37,9 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
+#include <db.h>
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <nsswitch.h>
@@ -94,6 +96,19 @@ NSS_TLS_HANDLING(files);
static int files_servent(void *, void *, va_list);
static int files_setservent(void *, void *, va_list);
+/* db backend declarations */
+struct db_state
+{
+ DB *db;
+ int stayopen;
+ int keynum;
+};
+static void db_endstate(void *);
+NSS_TLS_HANDLING(db);
+
+static int db_servent(void *, void *, va_list);
+static int db_setservent(void *, void *, va_list);
+
#ifdef YP
/* nis backend declarations */
static int nis_servent(void *, void *, va_list);
@@ -263,6 +278,8 @@ files_servent(void *retval, void *mdata, va_list ap)
{ NULL, 0 }
};
ns_dtab compat_dtab[] = {
+ { NSSRC_DB, db_servent,
+ (void *)((struct servent_mdata *)mdata)->how },
#ifdef YP
{ NSSRC_NIS, nis_servent,
(void *)((struct servent_mdata *)mdata)->how },
@@ -452,6 +469,185 @@ files_setservent(void *retval, void *mdata, va_list ap)
return (NS_UNAVAIL);
}
+/* db backend implementation */
+static void
+db_endstate(void *p)
+{
+ DB *db;
+
+ if (p == NULL)
+ return;
+
+ db = ((struct db_state *)p)->db;
+ if (db != NULL)
+ db->close(db);
+
+ free(p);
+}
+
+static int
+db_servent(void *retval, void *mdata, va_list ap)
+{
+ char buf[BUFSIZ];
+ DBT key, data;
+ DB *db;
+
+ char *resultbuf;
+
+ struct db_state *st;
+ int rv;
+ int stayopen;
+
+ enum nss_lookup_type how;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ name = NULL;
+ proto = NULL;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ 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:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap,int *);
+
+ *errnop = db_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (how == nss_lt_all && st->keynum < 0)
+ return (NS_NOTFOUND);
+
+ if (st->db == NULL) {
+ st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
+ if (st->db == NULL) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+
+ stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
+ db = st->db;
+
+ do {
+ switch (how) {
+ case nss_lt_name:
+ key.data = buf;
+ if (proto == NULL)
+ key.size = snprintf(buf, sizeof(buf),
+ "\376%s", name);
+ else
+ key.size = snprintf(buf, sizeof(buf),
+ "\376%s/%s", name, proto);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ db->get(db, &data, &key, 0) != 0) {
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ resultbuf = key.data;
+ break;
+ case nss_lt_id:
+ key.data = buf;
+ port = htons(port);
+ if (proto == NULL)
+ key.size = snprintf(buf, sizeof(buf),
+ "\377%d", port);
+ else
+ key.size = snprintf(buf, sizeof(buf),
+ "\377%d/%s", port, proto);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ db->get(db, &data, &key, 0) != 0) {
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ resultbuf = key.data;
+ break;
+ case nss_lt_all:
+ key.data = buf;
+ key.size = snprintf(buf, sizeof(buf), "%d",
+ st->keynum++);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0) {
+ st->keynum = -1;
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ resultbuf = data.data;
+ break;
+ }
+
+ rv = parse_result(serv, buffer, bufsize, resultbuf,
+ strlen(resultbuf), errnop);
+
+ } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
+
+db_fin:
+ if (!stayopen && st->db != NULL) {
+ db->close(db);
+ st->db = NULL;
+ }
+
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct servent **)retval = serv;
+
+ return (rv);
+}
+
+static int
+db_setservent(void *retval, void *mdata, va_list ap)
+{
+ DB *db;
+ struct db_state *st;
+ int rv;
+ int f;
+
+ rv = db_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap, int);
+ st->stayopen |= f;
+ st->keynum = 0;
+ break;
+ case ENDSERVENT:
+ db = st->db;
+ if (db != NULL) {
+ db->close(db);
+ st->db = NULL;
+ }
+ st->stayopen = 0;
+ break;
+ default:
+ break;
+ };
+
+ return (NS_UNAVAIL);
+}
+
/* nis backend implementation */
#ifdef YP
static void
@@ -638,6 +834,7 @@ compat_setservent(void *retval, void *mdata, va_list ap)
{ NULL, 0 }
};
ns_dtab compat_dtab[] = {
+ { NSSRC_DB, db_setservent, mdata },
#ifdef YP
{ NSSRC_NIS, nis_setservent, mdata },
#endif
@@ -924,6 +1121,7 @@ getservbyname_r(const char *name, const char *proto, struct servent *serv,
#endif /* NS_CACHING */
static const ns_dtab dtab[] = {
{ NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_name },
#ifdef YP
{ NSSRC_NIS, nis_servent, (void *)nss_lt_name },
#endif
@@ -960,6 +1158,7 @@ getservbyport_r(int port, const char *proto, struct servent *serv,
#endif
static const ns_dtab dtab[] = {
{ NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_id },
#ifdef YP
{ NSSRC_NIS, nis_servent, (void *)nss_lt_id },
#endif
@@ -995,6 +1194,7 @@ getservent_r(struct servent *serv, char *buffer, size_t bufsize,
#endif
static const ns_dtab dtab[] = {
{ NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_all },
#ifdef YP
{ NSSRC_NIS, nis_servent, (void *)nss_lt_all },
#endif
@@ -1027,6 +1227,7 @@ setservent(int stayopen)
#endif
static const ns_dtab dtab[] = {
{ NSSRC_FILES, files_setservent, (void *)SETSERVENT },
+ { NSSRC_DB, db_setservent, (void *)SETSERVENT },
#ifdef YP
{ NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
#endif
@@ -1051,6 +1252,7 @@ endservent()
#endif
static const ns_dtab dtab[] = {
{ NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
+ { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
#ifdef YP
{ NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
#endif
diff --git a/lib/libc/net/nsdispatch.3 b/lib/libc/net/nsdispatch.3
index cf15002..8ae7540 100644
--- a/lib/libc/net/nsdispatch.3
+++ b/lib/libc/net/nsdispatch.3
@@ -32,7 +32,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 22, 2007
+.Dd April 4, 2010
.Dt NSDISPATCH 3
.Os
.Sh NAME
@@ -176,6 +176,7 @@ While there is support for arbitrary sources, the following
.Bl -column NSSRC_COMPAT compat -offset indent
.It Sy "#define value"
.It Dv NSSRC_FILES Ta """files""
+.It Dv NSSRC_DB Ta """db""
.It Dv NSSRC_DNS Ta """dns""
.It Dv NSSRC_NIS Ta """nis""
.It Dv NSSRC_COMPAT Ta """compat""
OpenPOWER on IntegriCloud