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