xref: /freebsd/usr.sbin/ypserv/yp_dblookup.c (revision b5ebd8bb4e90b810c834aabb78c87054ab84db8e)
1*df57947fSPedro F. Giffuni /*-
2*df57947fSPedro F. Giffuni  * SPDX-License-Identifier: BSD-4-Clause
3*df57947fSPedro F. Giffuni  *
4778c7b1cSBill Paul  * Copyright (c) 1995
5778c7b1cSBill Paul  *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
6778c7b1cSBill Paul  *
7778c7b1cSBill Paul  * Redistribution and use in source and binary forms, with or without
8778c7b1cSBill Paul  * modification, are permitted provided that the following conditions
9778c7b1cSBill Paul  * are met:
10778c7b1cSBill Paul  * 1. Redistributions of source code must retain the above copyright
11778c7b1cSBill Paul  *    notice, this list of conditions and the following disclaimer.
12778c7b1cSBill Paul  * 2. Redistributions in binary form must reproduce the above copyright
13778c7b1cSBill Paul  *    notice, this list of conditions and the following disclaimer in the
14778c7b1cSBill Paul  *    documentation and/or other materials provided with the distribution.
15778c7b1cSBill Paul  * 3. All advertising materials mentioning features or use of this software
16778c7b1cSBill Paul  *    must display the following acknowledgement:
17778c7b1cSBill Paul  *	This product includes software developed by Bill Paul.
18778c7b1cSBill Paul  * 4. Neither the name of the author nor the names of any co-contributors
19778c7b1cSBill Paul  *    may be used to endorse or promote products derived from this software
20778c7b1cSBill Paul  *    without specific prior written permission.
21778c7b1cSBill Paul  *
22778c7b1cSBill Paul  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23778c7b1cSBill Paul  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24778c7b1cSBill Paul  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25778c7b1cSBill Paul  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
26778c7b1cSBill Paul  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27778c7b1cSBill Paul  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28778c7b1cSBill Paul  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29778c7b1cSBill Paul  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30778c7b1cSBill Paul  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31778c7b1cSBill Paul  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32778c7b1cSBill Paul  * SUCH DAMAGE.
33778c7b1cSBill Paul  */
34778c7b1cSBill Paul 
35b728350eSDavid E. O'Brien #include <sys/cdefs.h>
3698834523SPhilippe Charnier #include <db.h>
3798834523SPhilippe Charnier #include <errno.h>
3898834523SPhilippe Charnier #include <fcntl.h>
3998834523SPhilippe Charnier #include <limits.h>
4098834523SPhilippe Charnier #include <paths.h>
4198834523SPhilippe Charnier #include <stdio.h>
4298834523SPhilippe Charnier #include <stdlib.h>
4398834523SPhilippe Charnier #include <string.h>
4498834523SPhilippe Charnier #include <unistd.h>
4598834523SPhilippe Charnier #include <sys/stat.h>
4698834523SPhilippe Charnier #include <sys/param.h>
4798834523SPhilippe Charnier #include <rpcsvc/yp.h>
4898834523SPhilippe Charnier #include "yp_extern.h"
491fbdac93SBill Paul 
5077732bc5SBill Paul int ypdb_debug = 0;
51180807d2SBill Paul enum ypstat yp_errno = YP_TRUE;
52778c7b1cSBill Paul 
53778c7b1cSBill Paul #define PERM_SECURE (S_IRUSR|S_IWUSR)
54778c7b1cSBill Paul HASHINFO openinfo = {
55778c7b1cSBill Paul 	4096,		/* bsize */
56778c7b1cSBill Paul 	32,		/* ffactor */
57b3e93234SBill Paul 	256,		/* nelem */
58b2264be8SBill Paul 	2048 * 512, 	/* cachesize */
59778c7b1cSBill Paul 	NULL,		/* hash */
60778c7b1cSBill Paul 	0,		/* lorder */
61778c7b1cSBill Paul };
62778c7b1cSBill Paul 
63b2264be8SBill Paul #ifdef DB_CACHE
6479acf67fSBill Paul #include <sys/queue.h>
6579acf67fSBill Paul 
6679acf67fSBill Paul #ifndef MAXDBS
67b2264be8SBill Paul #define MAXDBS 20
6879acf67fSBill Paul #endif
6979acf67fSBill Paul 
7079acf67fSBill Paul static int numdbs = 0;
71b2264be8SBill Paul 
72b2264be8SBill Paul struct dbent {
73b2264be8SBill Paul 	DB *dbp;
74b2264be8SBill Paul 	char *name;
75b2264be8SBill Paul 	char *key;
76b2264be8SBill Paul 	int size;
7744519760SBill Paul 	int flags;
78b2264be8SBill Paul };
79b2264be8SBill Paul 
80c5e5cd90SPoul-Henning Kamp static TAILQ_HEAD(circlehead, circleq_entry) qhead;
8179acf67fSBill Paul 
8279acf67fSBill Paul struct circleq_entry {
8379acf67fSBill Paul 	struct dbent *dbptr;
84c5e5cd90SPoul-Henning Kamp 	TAILQ_ENTRY(circleq_entry) links;
8579acf67fSBill Paul };
86b2264be8SBill Paul 
87778c7b1cSBill Paul /*
8879acf67fSBill Paul  * Initialize the circular queue.
89b2264be8SBill Paul  */
90dc584ddbSDag-Erling Smørgrav void
yp_init_dbs(void)91dc584ddbSDag-Erling Smørgrav yp_init_dbs(void)
92b2264be8SBill Paul {
93c5e5cd90SPoul-Henning Kamp 	TAILQ_INIT(&qhead);
94b2264be8SBill Paul }
95b2264be8SBill Paul 
961fbdac93SBill Paul /*
9779acf67fSBill Paul  * Dynamically allocate an entry for the circular queue.
9879acf67fSBill Paul  * Return a NULL pointer on failure.
991fbdac93SBill Paul  */
100dc584ddbSDag-Erling Smørgrav static struct circleq_entry *
yp_malloc_qent(void)101dc584ddbSDag-Erling Smørgrav yp_malloc_qent(void)
102b2264be8SBill Paul {
10379acf67fSBill Paul 	register struct circleq_entry *q;
10479acf67fSBill Paul 
105650dae44SMarcelo Araujo 	q = malloc(sizeof(struct circleq_entry));
10679acf67fSBill Paul 	if (q == NULL) {
10798834523SPhilippe Charnier 		yp_error("failed to malloc() circleq entry");
10879acf67fSBill Paul 		return(NULL);
10979acf67fSBill Paul 	}
11079acf67fSBill Paul 	bzero((char *)q, sizeof(struct circleq_entry));
111650dae44SMarcelo Araujo 	q->dbptr = malloc(sizeof(struct dbent));
11279acf67fSBill Paul 	if (q->dbptr == NULL) {
11398834523SPhilippe Charnier 		yp_error("failed to malloc() circleq entry");
11479acf67fSBill Paul 		free(q);
11579acf67fSBill Paul 		return(NULL);
11679acf67fSBill Paul 	}
11779acf67fSBill Paul 	bzero((char *)q->dbptr, sizeof(struct dbent));
11879acf67fSBill Paul 
11979acf67fSBill Paul 	return(q);
120b2264be8SBill Paul }
121b2264be8SBill Paul 
122b2264be8SBill Paul /*
12379acf67fSBill Paul  * Free a previously allocated circular queue
12479acf67fSBill Paul  * entry.
12579acf67fSBill Paul  */
126dc584ddbSDag-Erling Smørgrav static void
yp_free_qent(struct circleq_entry * q)127dc584ddbSDag-Erling Smørgrav yp_free_qent(struct circleq_entry *q)
12879acf67fSBill Paul {
12979acf67fSBill Paul 	/*
13079acf67fSBill Paul 	 * First, close the database. In theory, this is also
13179acf67fSBill Paul 	 * supposed to free the resources allocated by the DB
13279acf67fSBill Paul 	 * package, including the memory pointed to by q->dbptr->key.
13379acf67fSBill Paul 	 * This means we don't have to free q->dbptr->key here.
13479acf67fSBill Paul 	 */
13579acf67fSBill Paul 	if (q->dbptr->dbp) {
13679acf67fSBill Paul 		(void)(q->dbptr->dbp->close)(q->dbptr->dbp);
13779acf67fSBill Paul 		q->dbptr->dbp = NULL;
13879acf67fSBill Paul 	}
13979acf67fSBill Paul 	/*
14079acf67fSBill Paul 	 * Then free the database name, which was strdup()'ed.
14179acf67fSBill Paul 	 */
14279acf67fSBill Paul 	free(q->dbptr->name);
14379acf67fSBill Paul 
14479acf67fSBill Paul 	/*
14579acf67fSBill Paul 	 * Free the rest of the dbent struct.
14679acf67fSBill Paul 	 */
14779acf67fSBill Paul 	free(q->dbptr);
14879acf67fSBill Paul 	q->dbptr = NULL;
14979acf67fSBill Paul 
15079acf67fSBill Paul 	/*
15179acf67fSBill Paul 	 * Free the circleq struct.
15279acf67fSBill Paul 	 */
15379acf67fSBill Paul 	free(q);
15479acf67fSBill Paul 	q = NULL;
15579acf67fSBill Paul }
15679acf67fSBill Paul 
15779acf67fSBill Paul /*
15879acf67fSBill Paul  * Zorch a single entry in the dbent queue and release
15979acf67fSBill Paul  * all its resources. (This always removes the last entry
16079acf67fSBill Paul  * in the queue.)
16179acf67fSBill Paul  */
162dc584ddbSDag-Erling Smørgrav static void
yp_flush(void)163dc584ddbSDag-Erling Smørgrav yp_flush(void)
16479acf67fSBill Paul {
16579acf67fSBill Paul 	register struct circleq_entry *qptr;
16679acf67fSBill Paul 
167c5e5cd90SPoul-Henning Kamp 	qptr = TAILQ_LAST(&qhead, circlehead);
168c5e5cd90SPoul-Henning Kamp 	TAILQ_REMOVE(&qhead, qptr, links);
16979acf67fSBill Paul 	yp_free_qent(qptr);
17079acf67fSBill Paul 	numdbs--;
17179acf67fSBill Paul }
17279acf67fSBill Paul 
17379acf67fSBill Paul /*
17479acf67fSBill Paul  * Close all databases, erase all database names and empty the queue.
175b2264be8SBill Paul  */
176dc584ddbSDag-Erling Smørgrav void
yp_flush_all(void)177dc584ddbSDag-Erling Smørgrav yp_flush_all(void)
178b2264be8SBill Paul {
17979acf67fSBill Paul 	register struct circleq_entry *qptr;
180b2264be8SBill Paul 
181c5e5cd90SPoul-Henning Kamp 	while (!TAILQ_EMPTY(&qhead)) {
182c5e5cd90SPoul-Henning Kamp 		qptr = TAILQ_FIRST(&qhead); /* save this */
183c5e5cd90SPoul-Henning Kamp 		TAILQ_REMOVE(&qhead, qptr, links);
18479acf67fSBill Paul 		yp_free_qent(qptr);
185b2264be8SBill Paul 	}
18679acf67fSBill Paul 	numdbs = 0;
18779acf67fSBill Paul 
188b2264be8SBill Paul }
189b2264be8SBill Paul 
19044519760SBill Paul static char *inter_string = "YP_INTERDOMAIN";
19144519760SBill Paul static char *secure_string = "YP_SECURE";
19244519760SBill Paul static int inter_sz = sizeof("YP_INTERDOMAIN") - 1;
19344519760SBill Paul static int secure_sz = sizeof("YP_SECURE") - 1;
19444519760SBill Paul 
195dc584ddbSDag-Erling Smørgrav static int
yp_setflags(DB * dbp)196dc584ddbSDag-Erling Smørgrav yp_setflags(DB *dbp)
19744519760SBill Paul {
19844519760SBill Paul 	DBT key = { NULL, 0 }, data = { NULL, 0 };
19944519760SBill Paul 	int flags = 0;
20044519760SBill Paul 
20144519760SBill Paul 	key.data = inter_string;
20244519760SBill Paul 	key.size = inter_sz;
20344519760SBill Paul 
20444519760SBill Paul 	if (!(dbp->get)(dbp, &key, &data, 0))
20544519760SBill Paul 		flags |= YP_INTERDOMAIN;
20644519760SBill Paul 
20744519760SBill Paul 	key.data = secure_string;
20844519760SBill Paul 	key.size = secure_sz;
20944519760SBill Paul 
21044519760SBill Paul 	if (!(dbp->get)(dbp, &key, &data, 0))
21144519760SBill Paul 		flags |= YP_SECURE;
21244519760SBill Paul 
21344519760SBill Paul 	return(flags);
21444519760SBill Paul }
21544519760SBill Paul 
216dc584ddbSDag-Erling Smørgrav int
yp_testflag(char * map,char * domain,int flag)217dc584ddbSDag-Erling Smørgrav yp_testflag(char *map, char *domain, int flag)
21844519760SBill Paul {
21944519760SBill Paul 	char buf[MAXPATHLEN + 2];
22044519760SBill Paul 	register struct circleq_entry *qptr;
22144519760SBill Paul 
22244519760SBill Paul 	if (map == NULL || domain == NULL)
22344519760SBill Paul 		return(0);
22444519760SBill Paul 
22544519760SBill Paul 	strcpy(buf, domain);
22644519760SBill Paul 	strcat(buf, "/");
22744519760SBill Paul 	strcat(buf, map);
22844519760SBill Paul 
229c5e5cd90SPoul-Henning Kamp 	TAILQ_FOREACH(qptr, &qhead, links) {
23044519760SBill Paul 		if (!strcmp(qptr->dbptr->name, buf)) {
23144519760SBill Paul 			if (qptr->dbptr->flags & flag)
23244519760SBill Paul 				return(1);
23344519760SBill Paul 			else
23444519760SBill Paul 				return(0);
23544519760SBill Paul 		}
23644519760SBill Paul 	}
23744519760SBill Paul 
23844519760SBill Paul 	if (yp_open_db_cache(domain, map, NULL, 0) == NULL)
23944519760SBill Paul 		return(0);
24044519760SBill Paul 
241c5e5cd90SPoul-Henning Kamp 	if (TAILQ_FIRST(&qhead)->dbptr->flags & flag)
24244519760SBill Paul 		return(1);
24344519760SBill Paul 
24444519760SBill Paul 	return(0);
24544519760SBill Paul }
246b2264be8SBill Paul 
247b2264be8SBill Paul /*
248b2264be8SBill Paul  * Add a DB handle and database name to the cache. We only maintain
249b2264be8SBill Paul  * fixed number of entries in the cache, so if we're asked to store
250b2264be8SBill Paul  * a new entry when all our slots are already filled, we have to kick
251b2264be8SBill Paul  * out the entry in the last slot to make room.
252b2264be8SBill Paul  */
253dc584ddbSDag-Erling Smørgrav static int
yp_cache_db(DB * dbp,char * name,int size)254dc584ddbSDag-Erling Smørgrav yp_cache_db(DB *dbp, char *name, int size)
255b2264be8SBill Paul {
25679acf67fSBill Paul 	register struct circleq_entry *qptr;
257b2264be8SBill Paul 
25879acf67fSBill Paul 	if (numdbs == MAXDBS) {
259b2264be8SBill Paul 		if (ypdb_debug)
26079acf67fSBill Paul 			yp_error("queue overflow -- releasing last slot");
26179acf67fSBill Paul 		yp_flush();
262b2264be8SBill Paul 	}
263b2264be8SBill Paul 
264b2264be8SBill Paul 	/*
26579acf67fSBill Paul 	 * Allocate a new queue entry.
266b2264be8SBill Paul 	 */
26779acf67fSBill Paul 
26879acf67fSBill Paul 	if ((qptr = yp_malloc_qent()) == NULL) {
26979acf67fSBill Paul 		yp_error("failed to allocate a new cache entry");
27079acf67fSBill Paul 		return(1);
271b2264be8SBill Paul 	}
272b2264be8SBill Paul 
27379acf67fSBill Paul 	qptr->dbptr->dbp = dbp;
27479acf67fSBill Paul 	qptr->dbptr->name = strdup(name);
27579acf67fSBill Paul 	qptr->dbptr->size = size;
27679acf67fSBill Paul 	qptr->dbptr->key = NULL;
27779acf67fSBill Paul 
27844519760SBill Paul 	qptr->dbptr->flags = yp_setflags(dbp);
27944519760SBill Paul 
280c5e5cd90SPoul-Henning Kamp 	TAILQ_INSERT_HEAD(&qhead, qptr, links);
281b2264be8SBill Paul 	numdbs++;
28279acf67fSBill Paul 
28379acf67fSBill Paul 	return(0);
284b2264be8SBill Paul }
285b2264be8SBill Paul 
286b2264be8SBill Paul /*
287b2264be8SBill Paul  * Search the list for a database matching 'name.' If we find it,
288b2264be8SBill Paul  * move it to the head of the list and return its DB handle. If
289b2264be8SBill Paul  * not, just fail: yp_open_db_cache() will subsequently try to open
29079acf67fSBill Paul  * the database itself and call yp_cache_db() to add it to the
291b2264be8SBill Paul  * list.
292b2264be8SBill Paul  *
293b2264be8SBill Paul  * The search works like this:
294b2264be8SBill Paul  *
295b2264be8SBill Paul  * - The caller specifies the name of a database to locate. We try to
29679acf67fSBill Paul  *   find an entry in our queue with a matching name.
297b2264be8SBill Paul  *
298b2264be8SBill Paul  * - If the caller doesn't specify a key or size, we assume that the
299b2264be8SBill Paul  *   first entry that we encounter with a matching name is returned.
30079acf67fSBill Paul  *   This will result in matches regardless of the key/size values
30179acf67fSBill Paul  *   stored in the queue entry.
302b2264be8SBill Paul  *
30379acf67fSBill Paul  * - If the caller also specifies a key and length, we check to see
30479acf67fSBill Paul  *   if the key and length saved in the queue entry also matches.
305b2264be8SBill Paul  *   This lets us return a DB handle that's already positioned at the
306b2264be8SBill Paul  *   correct location within a database.
307b2264be8SBill Paul  *
30879acf67fSBill Paul  * - Once we have a match, it gets migrated to the top of the queue
30979acf67fSBill Paul  *   so that it will be easier to find if another request for
310b2264be8SBill Paul  *   the same database comes in later.
311b2264be8SBill Paul  */
312dc584ddbSDag-Erling Smørgrav static DB *
yp_find_db(const char * name,const char * key,int size)313f249dbccSDag-Erling Smørgrav yp_find_db(const char *name, const char *key, int size)
314b2264be8SBill Paul {
31579acf67fSBill Paul 	register struct circleq_entry *qptr;
316b2264be8SBill Paul 
317c5e5cd90SPoul-Henning Kamp 	TAILQ_FOREACH(qptr, &qhead, links) {
31879acf67fSBill Paul 		if (!strcmp(qptr->dbptr->name, name)) {
319b2264be8SBill Paul 			if (size) {
32079acf67fSBill Paul 				if (size != qptr->dbptr->size ||
32179acf67fSBill Paul 				   strncmp(qptr->dbptr->key, key, size))
322b2264be8SBill Paul 					continue;
323b2264be8SBill Paul 			} else {
32479acf67fSBill Paul 				if (qptr->dbptr->size)
325b2264be8SBill Paul 					continue;
326b2264be8SBill Paul 			}
327c5e5cd90SPoul-Henning Kamp 			if (qptr != TAILQ_FIRST(&qhead)) {
328c5e5cd90SPoul-Henning Kamp 				TAILQ_REMOVE(&qhead, qptr, links);
329c5e5cd90SPoul-Henning Kamp 				TAILQ_INSERT_HEAD(&qhead, qptr, links);
330b2264be8SBill Paul 			}
33179acf67fSBill Paul 			return(qptr->dbptr->dbp);
332b2264be8SBill Paul 		}
333b2264be8SBill Paul 	}
334b3e93234SBill Paul 
335b2264be8SBill Paul 	return(NULL);
336b2264be8SBill Paul }
337b2264be8SBill Paul 
338b2264be8SBill Paul /*
339b2264be8SBill Paul  * Open a DB database and cache the handle for later use. We first
340b2264be8SBill Paul  * check the cache to see if the required database is already open.
341b2264be8SBill Paul  * If so, we fetch the handle from the cache. If not, we try to open
342b2264be8SBill Paul  * the database and save the handle in the cache for later use.
343b2264be8SBill Paul  */
344dc584ddbSDag-Erling Smørgrav DB *
yp_open_db_cache(const char * domain,const char * map,const char * key,const int size)345dc584ddbSDag-Erling Smørgrav yp_open_db_cache(const char *domain, const char *map, const char *key,
346dc584ddbSDag-Erling Smørgrav     const int size)
347b2264be8SBill Paul {
348b2264be8SBill Paul 	DB *dbp = NULL;
349b2264be8SBill Paul 	char buf[MAXPATHLEN + 2];
350b3e93234SBill Paul /*
351b3e93234SBill Paul 	snprintf(buf, sizeof(buf), "%s/%s", domain, map);
352b3e93234SBill Paul */
35379acf67fSBill Paul 	yp_errno = YP_TRUE;
354b2264be8SBill Paul 
3551fbdac93SBill Paul 	strcpy(buf, domain);
3561fbdac93SBill Paul 	strcat(buf, "/");
3571fbdac93SBill Paul 	strcat(buf, map);
358b2264be8SBill Paul 
359f249dbccSDag-Erling Smørgrav 	if ((dbp = yp_find_db(buf, key, size)) != NULL) {
360b2264be8SBill Paul 		return(dbp);
361b2264be8SBill Paul 	} else {
36279acf67fSBill Paul 		if ((dbp = yp_open_db(domain, map)) != NULL) {
363f249dbccSDag-Erling Smørgrav 			if (yp_cache_db(dbp, buf, size)) {
36479acf67fSBill Paul 				(void)(dbp->close)(dbp);
36579acf67fSBill Paul 				yp_errno = YP_YPERR;
36679acf67fSBill Paul 				return(NULL);
36779acf67fSBill Paul 			}
36879acf67fSBill Paul 		}
369b2264be8SBill Paul 	}
370b2264be8SBill Paul 
371b2264be8SBill Paul 	return (dbp);
372b2264be8SBill Paul }
373b2264be8SBill Paul #endif
374b2264be8SBill Paul 
375b2264be8SBill Paul /*
376b2264be8SBill Paul  * Open a DB database.
377778c7b1cSBill Paul  */
378dc584ddbSDag-Erling Smørgrav DB *
yp_open_db(const char * domain,const char * map)379dc584ddbSDag-Erling Smørgrav yp_open_db(const char *domain, const char *map)
380778c7b1cSBill Paul {
381b2264be8SBill Paul 	DB *dbp = NULL;
382b2264be8SBill Paul 	char buf[MAXPATHLEN + 2];
383778c7b1cSBill Paul 
384778c7b1cSBill Paul 	yp_errno = YP_TRUE;
385778c7b1cSBill Paul 
386778c7b1cSBill Paul 	if (map[0] == '.' || strchr(map, '/')) {
387778c7b1cSBill Paul 		yp_errno = YP_BADARGS;
388778c7b1cSBill Paul 		return (NULL);
389778c7b1cSBill Paul 	}
390778c7b1cSBill Paul 
391b2264be8SBill Paul #ifdef DB_CACHE
392b2264be8SBill Paul 	if (yp_validdomain(domain)) {
393b2264be8SBill Paul 		yp_errno = YP_NODOM;
394b2264be8SBill Paul 		return(NULL);
395b2264be8SBill Paul 	}
396b2264be8SBill Paul #endif
397778c7b1cSBill Paul 	snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map);
398778c7b1cSBill Paul 
399b2264be8SBill Paul #ifdef DB_CACHE
400b2264be8SBill Paul again:
401b2264be8SBill Paul #endif
402b2264be8SBill Paul 	dbp = dbopen(buf, O_RDONLY, PERM_SECURE, DB_HASH, NULL);
403778c7b1cSBill Paul 
404778c7b1cSBill Paul 	if (dbp == NULL) {
405778c7b1cSBill Paul 		switch (errno) {
406b2264be8SBill Paul #ifdef DB_CACHE
407b2264be8SBill Paul 		case ENFILE:
408b2264be8SBill Paul 			/*
409b2264be8SBill Paul 			 * We ran out of file descriptors. Nuke an
410b2264be8SBill Paul 			 * open one and try again.
411b2264be8SBill Paul 			 */
412b2264be8SBill Paul 			yp_error("ran out of file descriptors");
41379acf67fSBill Paul 			yp_flush();
414b2264be8SBill Paul 			goto again;
415b2264be8SBill Paul 			break;
416b2264be8SBill Paul #endif
417778c7b1cSBill Paul 		case ENOENT:
418778c7b1cSBill Paul 			yp_errno = YP_NOMAP;
419778c7b1cSBill Paul 			break;
420778c7b1cSBill Paul 		case EFTYPE:
421778c7b1cSBill Paul 			yp_errno = YP_BADDB;
422778c7b1cSBill Paul 			break;
423778c7b1cSBill Paul 		default:
424778c7b1cSBill Paul 			yp_errno = YP_YPERR;
425778c7b1cSBill Paul 			break;
426778c7b1cSBill Paul 		}
427778c7b1cSBill Paul 	}
428778c7b1cSBill Paul 
429778c7b1cSBill Paul 	return (dbp);
430778c7b1cSBill Paul }
431778c7b1cSBill Paul 
432778c7b1cSBill Paul /*
433778c7b1cSBill Paul  * Database access routines.
434778c7b1cSBill Paul  *
435778c7b1cSBill Paul  * - yp_get_record(): retrieve an arbitrary key/data pair given one key
436778c7b1cSBill Paul  *                 to match against.
437778c7b1cSBill Paul  *
438778c7b1cSBill Paul  * - yp_first_record(): retrieve first key/data base in a database.
439778c7b1cSBill Paul  *
440778c7b1cSBill Paul  * - yp_next_record(): retrieve key/data pair that sequentially follows
441778c7b1cSBill Paul  *                   the supplied key value in the database.
442778c7b1cSBill Paul  */
443778c7b1cSBill Paul 
444180807d2SBill Paul #ifdef DB_CACHE
445dc584ddbSDag-Erling Smørgrav int
yp_get_record(DB * dbp,const DBT * key,DBT * data,int allow)446dc584ddbSDag-Erling Smørgrav yp_get_record(DB *dbp, const DBT *key, DBT *data, int allow)
447180807d2SBill Paul #else
448dc584ddbSDag-Erling Smørgrav int
449dc584ddbSDag-Erling Smørgrav yp_get_record(const char *domain, const char *map,
450dc584ddbSDag-Erling Smørgrav     const DBT *key, DBT *data, int allow)
451180807d2SBill Paul #endif
452778c7b1cSBill Paul {
453180807d2SBill Paul #ifndef DB_CACHE
454778c7b1cSBill Paul 	DB *dbp;
455180807d2SBill Paul #endif
456b2264be8SBill Paul 	int rval = 0;
45779acf67fSBill Paul #ifndef DB_CACHE
45879acf67fSBill Paul 	static unsigned char buf[YPMAXRECORD];
45979acf67fSBill Paul #endif
460778c7b1cSBill Paul 
46177732bc5SBill Paul 	if (ypdb_debug)
46298834523SPhilippe Charnier 		yp_error("looking up key [%.*s]",
463e009976aSDag-Erling Smørgrav 		    (int)key->size, (char *)key->data);
464778c7b1cSBill Paul 
465778c7b1cSBill Paul 	/*
466778c7b1cSBill Paul 	 * Avoid passing back magic "YP_*" entries unless
467778c7b1cSBill Paul 	 * the caller specifically requested them by setting
468778c7b1cSBill Paul 	 * the 'allow' flag.
469778c7b1cSBill Paul 	 */
470778c7b1cSBill Paul 	if (!allow && !strncmp(key->data, "YP_", 3))
471778c7b1cSBill Paul 		return(YP_NOKEY);
472778c7b1cSBill Paul 
473180807d2SBill Paul #ifndef DB_CACHE
474778c7b1cSBill Paul 	if ((dbp = yp_open_db(domain, map)) == NULL) {
475778c7b1cSBill Paul 		return(yp_errno);
476778c7b1cSBill Paul 	}
477180807d2SBill Paul #endif
478778c7b1cSBill Paul 
479920491cfSBill Paul 	if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) {
480b2264be8SBill Paul #ifdef DB_CACHE
481c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = 0;
482b2264be8SBill Paul #else
483778c7b1cSBill Paul 		(void)(dbp->close)(dbp);
484b2264be8SBill Paul #endif
485920491cfSBill Paul 		if (rval == 1)
486778c7b1cSBill Paul 			return(YP_NOKEY);
487920491cfSBill Paul 		else
488920491cfSBill Paul 			return(YP_BADDB);
489778c7b1cSBill Paul 	}
490778c7b1cSBill Paul 
49177732bc5SBill Paul 	if (ypdb_debug)
49298834523SPhilippe Charnier 		yp_error("result of lookup: key: [%.*s] data: [%.*s]",
493e009976aSDag-Erling Smørgrav 		    (int)key->size, (char *)key->data,
494e009976aSDag-Erling Smørgrav 		    (int)data->size, (char *)data->data);
495778c7b1cSBill Paul 
496b2264be8SBill Paul #ifdef DB_CACHE
497c5e5cd90SPoul-Henning Kamp 	if (TAILQ_FIRST(&qhead)->dbptr->size) {
498c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->key = "";
499c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = 0;
500b2264be8SBill Paul 	}
501b2264be8SBill Paul #else
502f249dbccSDag-Erling Smørgrav 	bcopy(data->data, &buf, data->size);
503f249dbccSDag-Erling Smørgrav 	data->data = &buf;
504b2264be8SBill Paul 	(void)(dbp->close)(dbp);
505b2264be8SBill Paul #endif
506b2264be8SBill Paul 
507778c7b1cSBill Paul 	return(YP_TRUE);
508778c7b1cSBill Paul }
509778c7b1cSBill Paul 
510dc584ddbSDag-Erling Smørgrav int
yp_first_record(const DB * dbp,DBT * key,DBT * data,int allow)511dc584ddbSDag-Erling Smørgrav yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow)
512778c7b1cSBill Paul {
513920491cfSBill Paul 	int rval;
51479acf67fSBill Paul #ifndef DB_CACHE
51579acf67fSBill Paul 	static unsigned char buf[YPMAXRECORD];
51679acf67fSBill Paul #endif
517778c7b1cSBill Paul 
51877732bc5SBill Paul 	if (ypdb_debug)
51998834523SPhilippe Charnier 		yp_error("retrieving first key in map");
520778c7b1cSBill Paul 
521920491cfSBill Paul 	if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) {
522b2264be8SBill Paul #ifdef DB_CACHE
523c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = 0;
524b2264be8SBill Paul #endif
525920491cfSBill Paul 		if (rval == 1)
526920491cfSBill Paul 			return(YP_NOKEY);
527920491cfSBill Paul 		else
528778c7b1cSBill Paul 			return(YP_BADDB);
529920491cfSBill Paul 	}
530778c7b1cSBill Paul 
531778c7b1cSBill Paul 	/* Avoid passing back magic "YP_*" records. */
532b2264be8SBill Paul 	while (!strncmp(key->data, "YP_", 3) && !allow) {
533920491cfSBill Paul 		if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) {
534b2264be8SBill Paul #ifdef DB_CACHE
535c5e5cd90SPoul-Henning Kamp 			TAILQ_FIRST(&qhead)->dbptr->size = 0;
536b2264be8SBill Paul #endif
537920491cfSBill Paul 			if (rval == 1)
538920491cfSBill Paul 				return(YP_NOKEY);
539920491cfSBill Paul 			else
540778c7b1cSBill Paul 				return(YP_BADDB);
541778c7b1cSBill Paul 		}
542920491cfSBill Paul 	}
543778c7b1cSBill Paul 
54477732bc5SBill Paul 	if (ypdb_debug)
54598834523SPhilippe Charnier 		yp_error("result of lookup: key: [%.*s] data: [%.*s]",
546e009976aSDag-Erling Smørgrav 		    (int)key->size, (char *)key->data,
547e009976aSDag-Erling Smørgrav 		    (int)data->size, (char *)data->data);
548778c7b1cSBill Paul 
549b2264be8SBill Paul #ifdef DB_CACHE
550c5e5cd90SPoul-Henning Kamp 	if (TAILQ_FIRST(&qhead)->dbptr->size) {
551c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->key = key->data;
552c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = key->size;
553b2264be8SBill Paul 	}
55479acf67fSBill Paul #else
555f249dbccSDag-Erling Smørgrav 	bcopy(data->data, &buf, data->size);
556f249dbccSDag-Erling Smørgrav 	data->data = &buf;
557b2264be8SBill Paul #endif
558b2264be8SBill Paul 
559778c7b1cSBill Paul 	return(YP_TRUE);
560778c7b1cSBill Paul }
561778c7b1cSBill Paul 
562dc584ddbSDag-Erling Smørgrav int
yp_next_record(const DB * dbp,DBT * key,DBT * data,int all,int allow)563dc584ddbSDag-Erling Smørgrav yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow)
564778c7b1cSBill Paul {
565b2264be8SBill Paul 	static DBT lkey = { NULL, 0 };
566b2264be8SBill Paul 	static DBT ldata = { NULL, 0 };
567920491cfSBill Paul 	int rval;
56879acf67fSBill Paul #ifndef DB_CACHE
56979acf67fSBill Paul 	static unsigned char keybuf[YPMAXRECORD];
57079acf67fSBill Paul 	static unsigned char datbuf[YPMAXRECORD];
57179acf67fSBill Paul #endif
572778c7b1cSBill Paul 
573180807d2SBill Paul 	if (key == NULL || !key->size || key->data == NULL) {
574b2264be8SBill Paul 		rval = yp_first_record(dbp,key,data,allow);
575920491cfSBill Paul 		if (rval == YP_NOKEY)
576920491cfSBill Paul 			return(YP_NOMORE);
577559605f1SBill Paul 		else {
578559605f1SBill Paul #ifdef DB_CACHE
579c5e5cd90SPoul-Henning Kamp 			TAILQ_FIRST(&qhead)->dbptr->key = key->data;
580c5e5cd90SPoul-Henning Kamp 			TAILQ_FIRST(&qhead)->dbptr->size = key->size;
581559605f1SBill Paul #endif
582920491cfSBill Paul 			return(rval);
583920491cfSBill Paul 		}
584559605f1SBill Paul 	}
585778c7b1cSBill Paul 
58677732bc5SBill Paul 	if (ypdb_debug)
58798834523SPhilippe Charnier 		yp_error("retrieving next key, previous was: [%.*s]",
588e009976aSDag-Erling Smørgrav 		    (int)key->size, (char *)key->data);
589778c7b1cSBill Paul 
590778c7b1cSBill Paul 	if (!all) {
591b3e93234SBill Paul #ifdef DB_CACHE
592c5e5cd90SPoul-Henning Kamp 		if (TAILQ_FIRST(&qhead)->dbptr->key == NULL) {
593b2264be8SBill Paul #endif
594778c7b1cSBill Paul 			(dbp->seq)(dbp,&lkey,&ldata,R_FIRST);
59568cd9748SBill Paul 			while (key->size != lkey.size ||
596f249dbccSDag-Erling Smørgrav 			    strncmp(key->data, lkey.data,
59768cd9748SBill Paul 			    (int)key->size))
598b3e93234SBill Paul 				if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) {
599b3e93234SBill Paul #ifdef DB_CACHE
600c5e5cd90SPoul-Henning Kamp 					TAILQ_FIRST(&qhead)->dbptr->size = 0;
601b3e93234SBill Paul #endif
602b3e93234SBill Paul 					return(YP_NOKEY);
603778c7b1cSBill Paul 				}
604b3e93234SBill Paul 
605b3e93234SBill Paul #ifdef DB_CACHE
606b3e93234SBill Paul 		}
607b3e93234SBill Paul #endif
608b2264be8SBill Paul 	}
609778c7b1cSBill Paul 
610b2264be8SBill Paul 	if ((dbp->seq)(dbp,key,data,R_NEXT)) {
611b2264be8SBill Paul #ifdef DB_CACHE
612c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = 0;
613b2264be8SBill Paul #endif
614778c7b1cSBill Paul 		return(YP_NOMORE);
615b2264be8SBill Paul 	}
616778c7b1cSBill Paul 
617778c7b1cSBill Paul 	/* Avoid passing back magic "YP_*" records. */
618b2264be8SBill Paul 	while (!strncmp(key->data, "YP_", 3) && !allow)
619b2264be8SBill Paul 		if ((dbp->seq)(dbp,key,data,R_NEXT)) {
620b2264be8SBill Paul #ifdef DB_CACHE
621c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = 0;
622b2264be8SBill Paul #endif
623778c7b1cSBill Paul 			return(YP_NOMORE);
624b2264be8SBill Paul 		}
625778c7b1cSBill Paul 
62677732bc5SBill Paul 	if (ypdb_debug)
62798834523SPhilippe Charnier 		yp_error("result of lookup: key: [%.*s] data: [%.*s]",
628e009976aSDag-Erling Smørgrav 		    (int)key->size, (char *)key->data,
629e009976aSDag-Erling Smørgrav 		    (int)data->size, (char *)data->data);
630778c7b1cSBill Paul 
631b2264be8SBill Paul #ifdef DB_CACHE
632c5e5cd90SPoul-Henning Kamp 	if (TAILQ_FIRST(&qhead)->dbptr->size) {
633c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->key = key->data;
634c5e5cd90SPoul-Henning Kamp 		TAILQ_FIRST(&qhead)->dbptr->size = key->size;
635b2264be8SBill Paul 	}
636b2264be8SBill Paul #else
637f249dbccSDag-Erling Smørgrav 	bcopy(key->data, &keybuf, key->size);
638f249dbccSDag-Erling Smørgrav 	lkey.data = &keybuf;
639b2264be8SBill Paul 	lkey.size = key->size;
640f249dbccSDag-Erling Smørgrav 	bcopy(data->data, &datbuf, data->size);
641f249dbccSDag-Erling Smørgrav 	data->data = &datbuf;
642b2264be8SBill Paul #endif
643b2264be8SBill Paul 
644778c7b1cSBill Paul 	return(YP_TRUE);
645778c7b1cSBill Paul }
646180807d2SBill Paul 
647180807d2SBill Paul #ifdef DB_CACHE
648180807d2SBill Paul /*
649180807d2SBill Paul  * Database glue functions.
650180807d2SBill Paul  */
651180807d2SBill Paul 
652180807d2SBill Paul static DB *yp_currmap_db = NULL;
653180807d2SBill Paul static int yp_allow_db = 0;
654180807d2SBill Paul 
655dc584ddbSDag-Erling Smørgrav ypstat
yp_select_map(char * map,char * domain,keydat * key,int allow)656dc584ddbSDag-Erling Smørgrav yp_select_map(char *map, char *domain, keydat *key, int allow)
657180807d2SBill Paul {
6580d15a950SBill Paul 	if (key == NULL)
6590d15a950SBill Paul 		yp_currmap_db = yp_open_db_cache(domain, map, NULL, 0);
6600d15a950SBill Paul 	else
6610d15a950SBill Paul 		yp_currmap_db = yp_open_db_cache(domain, map,
6620d15a950SBill Paul 						 key->keydat_val,
663180807d2SBill Paul 						 key->keydat_len);
664180807d2SBill Paul 
665180807d2SBill Paul 	yp_allow_db = allow;
666180807d2SBill Paul 	return(yp_errno);
667180807d2SBill Paul }
668180807d2SBill Paul 
669dc584ddbSDag-Erling Smørgrav ypstat
yp_getbykey(keydat * key,valdat * val)670dc584ddbSDag-Erling Smørgrav yp_getbykey(keydat *key, valdat *val)
671180807d2SBill Paul {
672180807d2SBill Paul 	DBT db_key = { NULL, 0 }, db_val = { NULL, 0 };
673180807d2SBill Paul 	ypstat rval;
674180807d2SBill Paul 
675180807d2SBill Paul 	db_key.data = key->keydat_val;
676180807d2SBill Paul 	db_key.size = key->keydat_len;
677180807d2SBill Paul 
678180807d2SBill Paul 	rval = yp_get_record(yp_currmap_db,
679180807d2SBill Paul 				&db_key, &db_val, yp_allow_db);
680180807d2SBill Paul 
681180807d2SBill Paul 	if (rval == YP_TRUE) {
682180807d2SBill Paul 		val->valdat_val = db_val.data;
683180807d2SBill Paul 		val->valdat_len = db_val.size;
684180807d2SBill Paul 	}
685180807d2SBill Paul 
686180807d2SBill Paul 	return(rval);
687180807d2SBill Paul }
688180807d2SBill Paul 
689dc584ddbSDag-Erling Smørgrav ypstat
yp_firstbykey(keydat * key,valdat * val)690dc584ddbSDag-Erling Smørgrav yp_firstbykey(keydat *key, valdat *val)
691180807d2SBill Paul {
692180807d2SBill Paul 	DBT db_key = { NULL, 0 }, db_val = { NULL, 0 };
693180807d2SBill Paul 	ypstat rval;
694180807d2SBill Paul 
695180807d2SBill Paul 	rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db);
696180807d2SBill Paul 
697180807d2SBill Paul 	if (rval == YP_TRUE) {
698180807d2SBill Paul 		key->keydat_val = db_key.data;
699180807d2SBill Paul 		key->keydat_len = db_key.size;
700180807d2SBill Paul 		val->valdat_val = db_val.data;
701180807d2SBill Paul 		val->valdat_len = db_val.size;
702180807d2SBill Paul 	}
703180807d2SBill Paul 
704180807d2SBill Paul 	return(rval);
705180807d2SBill Paul }
706180807d2SBill Paul 
707dc584ddbSDag-Erling Smørgrav ypstat
yp_nextbykey(keydat * key,valdat * val)708dc584ddbSDag-Erling Smørgrav yp_nextbykey(keydat *key, valdat *val)
709180807d2SBill Paul {
710180807d2SBill Paul 	DBT db_key = { NULL, 0 }, db_val = { NULL, 0 };
711180807d2SBill Paul 	ypstat rval;
712180807d2SBill Paul 
713180807d2SBill Paul 	db_key.data = key->keydat_val;
714180807d2SBill Paul 	db_key.size = key->keydat_len;
715180807d2SBill Paul 
716180807d2SBill Paul 	rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db);
717180807d2SBill Paul 
718180807d2SBill Paul 	if (rval == YP_TRUE) {
719180807d2SBill Paul 		key->keydat_val = db_key.data;
720180807d2SBill Paul 		key->keydat_len = db_key.size;
721180807d2SBill Paul 		val->valdat_val = db_val.data;
722180807d2SBill Paul 		val->valdat_len = db_val.size;
723180807d2SBill Paul 	}
724180807d2SBill Paul 
725180807d2SBill Paul 	return(rval);
726180807d2SBill Paul }
727180807d2SBill Paul #endif
728