summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netdb.h1
-rw-r--r--include/nsswitch.h1
-rw-r--r--lib/libc/net/getservent.c202
-rw-r--r--lib/libc/net/nsdispatch.33
-rw-r--r--share/man/man5/nsswitch.conf.54
-rw-r--r--share/man/man5/services.516
6 files changed, 224 insertions, 3 deletions
diff --git a/include/netdb.h b/include/netdb.h
index 2132044..2c2e4b3 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -82,6 +82,7 @@ typedef __uint32_t uint32_t;
#define _PATH_NETWORKS "/etc/networks"
#define _PATH_PROTOCOLS "/etc/protocols"
#define _PATH_SERVICES "/etc/services"
+#define _PATH_SERVICES_DB "/var/db/services.db"
#define h_errno (*__h_errno())
diff --git a/include/nsswitch.h b/include/nsswitch.h
index 0ff6cf1..1a97cea 100644
--- a/include/nsswitch.h
+++ b/include/nsswitch.h
@@ -58,6 +58,7 @@
* currently implemented sources
*/
#define NSSRC_FILES "files" /* local files */
+#define NSSRC_DB "db" /* database */
#define NSSRC_DNS "dns" /* DNS; IN for hosts, HS for others */
#define NSSRC_NIS "nis" /* YP/NIS */
#define NSSRC_COMPAT "compat" /* passwd,group in YP compat mode */
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""
diff --git a/share/man/man5/nsswitch.conf.5 b/share/man/man5/nsswitch.conf.5
index f6940bd..c28720b 100644
--- a/share/man/man5/nsswitch.conf.5
+++ b/share/man/man5/nsswitch.conf.5
@@ -33,7 +33,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 23, 2008
+.Dd April 4, 2010
.Dt NSSWITCH.CONF 5
.Os
.Sh NAME
@@ -72,6 +72,8 @@ Local files, such as
.Pa /etc/hosts ,
and
.Pa /etc/passwd .
+.It db
+Local database.
.It dns
Internet Domain Name System.
.Dq hosts
diff --git a/share/man/man5/services.5 b/share/man/man5/services.5
index 40320f9..55e0c9d 100644
--- a/share/man/man5/services.5
+++ b/share/man/man5/services.5
@@ -32,7 +32,7 @@
.\" @(#)services.5 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd June 5, 1993
+.Dd April 4, 2010
.Dt SERVICES 5
.Os
.Sh NAME
@@ -65,6 +65,18 @@ not interpreted by the routines which search the file.
Service names may contain any printable
character other than a field delimiter, newline,
or comment character.
+.Pp
+If
+.Dq db
+is specified as source in the
+.Xr nsswitch.conf 5 ,
+.Pa /var/db/services.db
+is searched.
+The database in
+.Pa /var/db/services.db
+needs to be updated with
+.Xr services_mkdb 8
+after changes to the services file have been applied.
.Sh NIS INTERACTION
Access to the NIS
.Pa services.byname
@@ -84,6 +96,8 @@ file resides in
.El
.Sh SEE ALSO
.Xr getservent 3
+.Xr nsswitch.conf 5
+.Xr services_mkdb 8
.Sh HISTORY
The
.Nm
OpenPOWER on IntegriCloud