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> 36b728350eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 3798834523SPhilippe Charnier 3898834523SPhilippe Charnier #include <db.h> 3998834523SPhilippe Charnier #include <errno.h> 4098834523SPhilippe Charnier #include <fcntl.h> 4198834523SPhilippe Charnier #include <limits.h> 4298834523SPhilippe Charnier #include <paths.h> 4398834523SPhilippe Charnier #include <stdio.h> 4498834523SPhilippe Charnier #include <stdlib.h> 4598834523SPhilippe Charnier #include <string.h> 4698834523SPhilippe Charnier #include <unistd.h> 4798834523SPhilippe Charnier #include <sys/stat.h> 4898834523SPhilippe Charnier #include <sys/param.h> 4998834523SPhilippe Charnier #include <rpcsvc/yp.h> 5098834523SPhilippe Charnier #include "yp_extern.h" 511fbdac93SBill Paul 5277732bc5SBill Paul int ypdb_debug = 0; 53180807d2SBill Paul enum ypstat yp_errno = YP_TRUE; 54778c7b1cSBill Paul 55778c7b1cSBill Paul #define PERM_SECURE (S_IRUSR|S_IWUSR) 56778c7b1cSBill Paul HASHINFO openinfo = { 57778c7b1cSBill Paul 4096, /* bsize */ 58778c7b1cSBill Paul 32, /* ffactor */ 59b3e93234SBill Paul 256, /* nelem */ 60b2264be8SBill Paul 2048 * 512, /* cachesize */ 61778c7b1cSBill Paul NULL, /* hash */ 62778c7b1cSBill Paul 0, /* lorder */ 63778c7b1cSBill Paul }; 64778c7b1cSBill Paul 65b2264be8SBill Paul #ifdef DB_CACHE 6679acf67fSBill Paul #include <sys/queue.h> 6779acf67fSBill Paul 6879acf67fSBill Paul #ifndef MAXDBS 69b2264be8SBill Paul #define MAXDBS 20 7079acf67fSBill Paul #endif 7179acf67fSBill Paul 7279acf67fSBill Paul static int numdbs = 0; 73b2264be8SBill Paul 74b2264be8SBill Paul struct dbent { 75b2264be8SBill Paul DB *dbp; 76b2264be8SBill Paul char *name; 77b2264be8SBill Paul char *key; 78b2264be8SBill Paul int size; 7944519760SBill Paul int flags; 80b2264be8SBill Paul }; 81b2264be8SBill Paul 82c5e5cd90SPoul-Henning Kamp static TAILQ_HEAD(circlehead, circleq_entry) qhead; 8379acf67fSBill Paul 8479acf67fSBill Paul struct circleq_entry { 8579acf67fSBill Paul struct dbent *dbptr; 86c5e5cd90SPoul-Henning Kamp TAILQ_ENTRY(circleq_entry) links; 8779acf67fSBill Paul }; 88b2264be8SBill Paul 89778c7b1cSBill Paul /* 9079acf67fSBill Paul * Initialize the circular queue. 91b2264be8SBill Paul */ 92dc584ddbSDag-Erling Smørgrav void 93dc584ddbSDag-Erling Smørgrav yp_init_dbs(void) 94b2264be8SBill Paul { 95c5e5cd90SPoul-Henning Kamp TAILQ_INIT(&qhead); 96b2264be8SBill Paul return; 97b2264be8SBill Paul } 98b2264be8SBill Paul 991fbdac93SBill Paul /* 10079acf67fSBill Paul * Dynamically allocate an entry for the circular queue. 10179acf67fSBill Paul * Return a NULL pointer on failure. 1021fbdac93SBill Paul */ 103dc584ddbSDag-Erling Smørgrav static struct circleq_entry * 104dc584ddbSDag-Erling Smørgrav yp_malloc_qent(void) 105b2264be8SBill Paul { 10679acf67fSBill Paul register struct circleq_entry *q; 10779acf67fSBill Paul 108650dae44SMarcelo Araujo q = malloc(sizeof(struct circleq_entry)); 10979acf67fSBill Paul if (q == NULL) { 11098834523SPhilippe Charnier yp_error("failed to malloc() circleq entry"); 11179acf67fSBill Paul return(NULL); 11279acf67fSBill Paul } 11379acf67fSBill Paul bzero((char *)q, sizeof(struct circleq_entry)); 114650dae44SMarcelo Araujo q->dbptr = malloc(sizeof(struct dbent)); 11579acf67fSBill Paul if (q->dbptr == NULL) { 11698834523SPhilippe Charnier yp_error("failed to malloc() circleq entry"); 11779acf67fSBill Paul free(q); 11879acf67fSBill Paul return(NULL); 11979acf67fSBill Paul } 12079acf67fSBill Paul bzero((char *)q->dbptr, sizeof(struct dbent)); 12179acf67fSBill Paul 12279acf67fSBill Paul return(q); 123b2264be8SBill Paul } 124b2264be8SBill Paul 125b2264be8SBill Paul /* 12679acf67fSBill Paul * Free a previously allocated circular queue 12779acf67fSBill Paul * entry. 12879acf67fSBill Paul */ 129dc584ddbSDag-Erling Smørgrav static void 130dc584ddbSDag-Erling Smørgrav yp_free_qent(struct circleq_entry *q) 13179acf67fSBill Paul { 13279acf67fSBill Paul /* 13379acf67fSBill Paul * First, close the database. In theory, this is also 13479acf67fSBill Paul * supposed to free the resources allocated by the DB 13579acf67fSBill Paul * package, including the memory pointed to by q->dbptr->key. 13679acf67fSBill Paul * This means we don't have to free q->dbptr->key here. 13779acf67fSBill Paul */ 13879acf67fSBill Paul if (q->dbptr->dbp) { 13979acf67fSBill Paul (void)(q->dbptr->dbp->close)(q->dbptr->dbp); 14079acf67fSBill Paul q->dbptr->dbp = NULL; 14179acf67fSBill Paul } 14279acf67fSBill Paul /* 14379acf67fSBill Paul * Then free the database name, which was strdup()'ed. 14479acf67fSBill Paul */ 14579acf67fSBill Paul free(q->dbptr->name); 14679acf67fSBill Paul 14779acf67fSBill Paul /* 14879acf67fSBill Paul * Free the rest of the dbent struct. 14979acf67fSBill Paul */ 15079acf67fSBill Paul free(q->dbptr); 15179acf67fSBill Paul q->dbptr = NULL; 15279acf67fSBill Paul 15379acf67fSBill Paul /* 15479acf67fSBill Paul * Free the circleq struct. 15579acf67fSBill Paul */ 15679acf67fSBill Paul free(q); 15779acf67fSBill Paul q = NULL; 15879acf67fSBill Paul 15979acf67fSBill Paul return; 16079acf67fSBill Paul } 16179acf67fSBill Paul 16279acf67fSBill Paul /* 16379acf67fSBill Paul * Zorch a single entry in the dbent queue and release 16479acf67fSBill Paul * all its resources. (This always removes the last entry 16579acf67fSBill Paul * in the queue.) 16679acf67fSBill Paul */ 167dc584ddbSDag-Erling Smørgrav static void 168dc584ddbSDag-Erling Smørgrav yp_flush(void) 16979acf67fSBill Paul { 17079acf67fSBill Paul register struct circleq_entry *qptr; 17179acf67fSBill Paul 172c5e5cd90SPoul-Henning Kamp qptr = TAILQ_LAST(&qhead, circlehead); 173c5e5cd90SPoul-Henning Kamp TAILQ_REMOVE(&qhead, qptr, links); 17479acf67fSBill Paul yp_free_qent(qptr); 17579acf67fSBill Paul numdbs--; 17679acf67fSBill Paul 17779acf67fSBill Paul return; 17879acf67fSBill Paul } 17979acf67fSBill Paul 18079acf67fSBill Paul /* 18179acf67fSBill Paul * Close all databases, erase all database names and empty the queue. 182b2264be8SBill Paul */ 183dc584ddbSDag-Erling Smørgrav void 184dc584ddbSDag-Erling Smørgrav yp_flush_all(void) 185b2264be8SBill Paul { 18679acf67fSBill Paul register struct circleq_entry *qptr; 187b2264be8SBill Paul 188c5e5cd90SPoul-Henning Kamp while (!TAILQ_EMPTY(&qhead)) { 189c5e5cd90SPoul-Henning Kamp qptr = TAILQ_FIRST(&qhead); /* save this */ 190c5e5cd90SPoul-Henning Kamp TAILQ_REMOVE(&qhead, qptr, links); 19179acf67fSBill Paul yp_free_qent(qptr); 192b2264be8SBill Paul } 19379acf67fSBill Paul numdbs = 0; 19479acf67fSBill Paul 19579acf67fSBill Paul return; 196b2264be8SBill Paul } 197b2264be8SBill Paul 19844519760SBill Paul static char *inter_string = "YP_INTERDOMAIN"; 19944519760SBill Paul static char *secure_string = "YP_SECURE"; 20044519760SBill Paul static int inter_sz = sizeof("YP_INTERDOMAIN") - 1; 20144519760SBill Paul static int secure_sz = sizeof("YP_SECURE") - 1; 20244519760SBill Paul 203dc584ddbSDag-Erling Smørgrav static int 204dc584ddbSDag-Erling Smørgrav yp_setflags(DB *dbp) 20544519760SBill Paul { 20644519760SBill Paul DBT key = { NULL, 0 }, data = { NULL, 0 }; 20744519760SBill Paul int flags = 0; 20844519760SBill Paul 20944519760SBill Paul key.data = inter_string; 21044519760SBill Paul key.size = inter_sz; 21144519760SBill Paul 21244519760SBill Paul if (!(dbp->get)(dbp, &key, &data, 0)) 21344519760SBill Paul flags |= YP_INTERDOMAIN; 21444519760SBill Paul 21544519760SBill Paul key.data = secure_string; 21644519760SBill Paul key.size = secure_sz; 21744519760SBill Paul 21844519760SBill Paul if (!(dbp->get)(dbp, &key, &data, 0)) 21944519760SBill Paul flags |= YP_SECURE; 22044519760SBill Paul 22144519760SBill Paul return(flags); 22244519760SBill Paul } 22344519760SBill Paul 224dc584ddbSDag-Erling Smørgrav int 225dc584ddbSDag-Erling Smørgrav yp_testflag(char *map, char *domain, int flag) 22644519760SBill Paul { 22744519760SBill Paul char buf[MAXPATHLEN + 2]; 22844519760SBill Paul register struct circleq_entry *qptr; 22944519760SBill Paul 23044519760SBill Paul if (map == NULL || domain == NULL) 23144519760SBill Paul return(0); 23244519760SBill Paul 23344519760SBill Paul strcpy(buf, domain); 23444519760SBill Paul strcat(buf, "/"); 23544519760SBill Paul strcat(buf, map); 23644519760SBill Paul 237c5e5cd90SPoul-Henning Kamp TAILQ_FOREACH(qptr, &qhead, links) { 23844519760SBill Paul if (!strcmp(qptr->dbptr->name, buf)) { 23944519760SBill Paul if (qptr->dbptr->flags & flag) 24044519760SBill Paul return(1); 24144519760SBill Paul else 24244519760SBill Paul return(0); 24344519760SBill Paul } 24444519760SBill Paul } 24544519760SBill Paul 24644519760SBill Paul if (yp_open_db_cache(domain, map, NULL, 0) == NULL) 24744519760SBill Paul return(0); 24844519760SBill Paul 249c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->flags & flag) 25044519760SBill Paul return(1); 25144519760SBill Paul 25244519760SBill Paul return(0); 25344519760SBill Paul } 254b2264be8SBill Paul 255b2264be8SBill Paul /* 256b2264be8SBill Paul * Add a DB handle and database name to the cache. We only maintain 257b2264be8SBill Paul * fixed number of entries in the cache, so if we're asked to store 258b2264be8SBill Paul * a new entry when all our slots are already filled, we have to kick 259b2264be8SBill Paul * out the entry in the last slot to make room. 260b2264be8SBill Paul */ 261dc584ddbSDag-Erling Smørgrav static int 262dc584ddbSDag-Erling Smørgrav yp_cache_db(DB *dbp, char *name, int size) 263b2264be8SBill Paul { 26479acf67fSBill Paul register struct circleq_entry *qptr; 265b2264be8SBill Paul 26679acf67fSBill Paul if (numdbs == MAXDBS) { 267b2264be8SBill Paul if (ypdb_debug) 26879acf67fSBill Paul yp_error("queue overflow -- releasing last slot"); 26979acf67fSBill Paul yp_flush(); 270b2264be8SBill Paul } 271b2264be8SBill Paul 272b2264be8SBill Paul /* 27379acf67fSBill Paul * Allocate a new queue entry. 274b2264be8SBill Paul */ 27579acf67fSBill Paul 27679acf67fSBill Paul if ((qptr = yp_malloc_qent()) == NULL) { 27779acf67fSBill Paul yp_error("failed to allocate a new cache entry"); 27879acf67fSBill Paul return(1); 279b2264be8SBill Paul } 280b2264be8SBill Paul 28179acf67fSBill Paul qptr->dbptr->dbp = dbp; 28279acf67fSBill Paul qptr->dbptr->name = strdup(name); 28379acf67fSBill Paul qptr->dbptr->size = size; 28479acf67fSBill Paul qptr->dbptr->key = NULL; 28579acf67fSBill Paul 28644519760SBill Paul qptr->dbptr->flags = yp_setflags(dbp); 28744519760SBill Paul 288c5e5cd90SPoul-Henning Kamp TAILQ_INSERT_HEAD(&qhead, qptr, links); 289b2264be8SBill Paul numdbs++; 29079acf67fSBill Paul 29179acf67fSBill Paul return(0); 292b2264be8SBill Paul } 293b2264be8SBill Paul 294b2264be8SBill Paul /* 295b2264be8SBill Paul * Search the list for a database matching 'name.' If we find it, 296b2264be8SBill Paul * move it to the head of the list and return its DB handle. If 297b2264be8SBill Paul * not, just fail: yp_open_db_cache() will subsequently try to open 29879acf67fSBill Paul * the database itself and call yp_cache_db() to add it to the 299b2264be8SBill Paul * list. 300b2264be8SBill Paul * 301b2264be8SBill Paul * The search works like this: 302b2264be8SBill Paul * 303b2264be8SBill Paul * - The caller specifies the name of a database to locate. We try to 30479acf67fSBill Paul * find an entry in our queue with a matching name. 305b2264be8SBill Paul * 306b2264be8SBill Paul * - If the caller doesn't specify a key or size, we assume that the 307b2264be8SBill Paul * first entry that we encounter with a matching name is returned. 30879acf67fSBill Paul * This will result in matches regardless of the key/size values 30979acf67fSBill Paul * stored in the queue entry. 310b2264be8SBill Paul * 31179acf67fSBill Paul * - If the caller also specifies a key and length, we check to see 31279acf67fSBill Paul * if the key and length saved in the queue entry also matches. 313b2264be8SBill Paul * This lets us return a DB handle that's already positioned at the 314b2264be8SBill Paul * correct location within a database. 315b2264be8SBill Paul * 31679acf67fSBill Paul * - Once we have a match, it gets migrated to the top of the queue 31779acf67fSBill Paul * so that it will be easier to find if another request for 318b2264be8SBill Paul * the same database comes in later. 319b2264be8SBill Paul */ 320dc584ddbSDag-Erling Smørgrav static DB * 321f249dbccSDag-Erling Smørgrav yp_find_db(const char *name, const char *key, int size) 322b2264be8SBill Paul { 32379acf67fSBill Paul register struct circleq_entry *qptr; 324b2264be8SBill Paul 325c5e5cd90SPoul-Henning Kamp TAILQ_FOREACH(qptr, &qhead, links) { 32679acf67fSBill Paul if (!strcmp(qptr->dbptr->name, name)) { 327b2264be8SBill Paul if (size) { 32879acf67fSBill Paul if (size != qptr->dbptr->size || 32979acf67fSBill Paul strncmp(qptr->dbptr->key, key, size)) 330b2264be8SBill Paul continue; 331b2264be8SBill Paul } else { 33279acf67fSBill Paul if (qptr->dbptr->size) 333b2264be8SBill Paul continue; 334b2264be8SBill Paul } 335c5e5cd90SPoul-Henning Kamp if (qptr != TAILQ_FIRST(&qhead)) { 336c5e5cd90SPoul-Henning Kamp TAILQ_REMOVE(&qhead, qptr, links); 337c5e5cd90SPoul-Henning Kamp TAILQ_INSERT_HEAD(&qhead, qptr, links); 338b2264be8SBill Paul } 33979acf67fSBill Paul return(qptr->dbptr->dbp); 340b2264be8SBill Paul } 341b2264be8SBill Paul } 342b3e93234SBill Paul 343b2264be8SBill Paul return(NULL); 344b2264be8SBill Paul } 345b2264be8SBill Paul 346b2264be8SBill Paul /* 347b2264be8SBill Paul * Open a DB database and cache the handle for later use. We first 348b2264be8SBill Paul * check the cache to see if the required database is already open. 349b2264be8SBill Paul * If so, we fetch the handle from the cache. If not, we try to open 350b2264be8SBill Paul * the database and save the handle in the cache for later use. 351b2264be8SBill Paul */ 352dc584ddbSDag-Erling Smørgrav DB * 353dc584ddbSDag-Erling Smørgrav yp_open_db_cache(const char *domain, const char *map, const char *key, 354dc584ddbSDag-Erling Smørgrav const int size) 355b2264be8SBill Paul { 356b2264be8SBill Paul DB *dbp = NULL; 357b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 358b3e93234SBill Paul /* 359b3e93234SBill Paul snprintf(buf, sizeof(buf), "%s/%s", domain, map); 360b3e93234SBill Paul */ 36179acf67fSBill Paul yp_errno = YP_TRUE; 362b2264be8SBill Paul 3631fbdac93SBill Paul strcpy(buf, domain); 3641fbdac93SBill Paul strcat(buf, "/"); 3651fbdac93SBill Paul strcat(buf, map); 366b2264be8SBill Paul 367f249dbccSDag-Erling Smørgrav if ((dbp = yp_find_db(buf, key, size)) != NULL) { 368b2264be8SBill Paul return(dbp); 369b2264be8SBill Paul } else { 37079acf67fSBill Paul if ((dbp = yp_open_db(domain, map)) != NULL) { 371f249dbccSDag-Erling Smørgrav if (yp_cache_db(dbp, buf, size)) { 37279acf67fSBill Paul (void)(dbp->close)(dbp); 37379acf67fSBill Paul yp_errno = YP_YPERR; 37479acf67fSBill Paul return(NULL); 37579acf67fSBill Paul } 37679acf67fSBill Paul } 377b2264be8SBill Paul } 378b2264be8SBill Paul 379b2264be8SBill Paul return (dbp); 380b2264be8SBill Paul } 381b2264be8SBill Paul #endif 382b2264be8SBill Paul 383b2264be8SBill Paul /* 384b2264be8SBill Paul * Open a DB database. 385778c7b1cSBill Paul */ 386dc584ddbSDag-Erling Smørgrav DB * 387dc584ddbSDag-Erling Smørgrav yp_open_db(const char *domain, const char *map) 388778c7b1cSBill Paul { 389b2264be8SBill Paul DB *dbp = NULL; 390b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 391778c7b1cSBill Paul 392778c7b1cSBill Paul yp_errno = YP_TRUE; 393778c7b1cSBill Paul 394778c7b1cSBill Paul if (map[0] == '.' || strchr(map, '/')) { 395778c7b1cSBill Paul yp_errno = YP_BADARGS; 396778c7b1cSBill Paul return (NULL); 397778c7b1cSBill Paul } 398778c7b1cSBill Paul 399b2264be8SBill Paul #ifdef DB_CACHE 400b2264be8SBill Paul if (yp_validdomain(domain)) { 401b2264be8SBill Paul yp_errno = YP_NODOM; 402b2264be8SBill Paul return(NULL); 403b2264be8SBill Paul } 404b2264be8SBill Paul #endif 405778c7b1cSBill Paul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); 406778c7b1cSBill Paul 407b2264be8SBill Paul #ifdef DB_CACHE 408b2264be8SBill Paul again: 409b2264be8SBill Paul #endif 410b2264be8SBill Paul dbp = dbopen(buf, O_RDONLY, PERM_SECURE, DB_HASH, NULL); 411778c7b1cSBill Paul 412778c7b1cSBill Paul if (dbp == NULL) { 413778c7b1cSBill Paul switch (errno) { 414b2264be8SBill Paul #ifdef DB_CACHE 415b2264be8SBill Paul case ENFILE: 416b2264be8SBill Paul /* 417b2264be8SBill Paul * We ran out of file descriptors. Nuke an 418b2264be8SBill Paul * open one and try again. 419b2264be8SBill Paul */ 420b2264be8SBill Paul yp_error("ran out of file descriptors"); 42179acf67fSBill Paul yp_flush(); 422b2264be8SBill Paul goto again; 423b2264be8SBill Paul break; 424b2264be8SBill Paul #endif 425778c7b1cSBill Paul case ENOENT: 426778c7b1cSBill Paul yp_errno = YP_NOMAP; 427778c7b1cSBill Paul break; 428778c7b1cSBill Paul case EFTYPE: 429778c7b1cSBill Paul yp_errno = YP_BADDB; 430778c7b1cSBill Paul break; 431778c7b1cSBill Paul default: 432778c7b1cSBill Paul yp_errno = YP_YPERR; 433778c7b1cSBill Paul break; 434778c7b1cSBill Paul } 435778c7b1cSBill Paul } 436778c7b1cSBill Paul 437778c7b1cSBill Paul return (dbp); 438778c7b1cSBill Paul } 439778c7b1cSBill Paul 440778c7b1cSBill Paul /* 441778c7b1cSBill Paul * Database access routines. 442778c7b1cSBill Paul * 443778c7b1cSBill Paul * - yp_get_record(): retrieve an arbitrary key/data pair given one key 444778c7b1cSBill Paul * to match against. 445778c7b1cSBill Paul * 446778c7b1cSBill Paul * - yp_first_record(): retrieve first key/data base in a database. 447778c7b1cSBill Paul * 448778c7b1cSBill Paul * - yp_next_record(): retrieve key/data pair that sequentially follows 449778c7b1cSBill Paul * the supplied key value in the database. 450778c7b1cSBill Paul */ 451778c7b1cSBill Paul 452180807d2SBill Paul #ifdef DB_CACHE 453dc584ddbSDag-Erling Smørgrav int 454dc584ddbSDag-Erling Smørgrav yp_get_record(DB *dbp, const DBT *key, DBT *data, int allow) 455180807d2SBill Paul #else 456dc584ddbSDag-Erling Smørgrav int 457dc584ddbSDag-Erling Smørgrav yp_get_record(const char *domain, const char *map, 458dc584ddbSDag-Erling Smørgrav const DBT *key, DBT *data, int allow) 459180807d2SBill Paul #endif 460778c7b1cSBill Paul { 461180807d2SBill Paul #ifndef DB_CACHE 462778c7b1cSBill Paul DB *dbp; 463180807d2SBill Paul #endif 464b2264be8SBill Paul int rval = 0; 46579acf67fSBill Paul #ifndef DB_CACHE 46679acf67fSBill Paul static unsigned char buf[YPMAXRECORD]; 46779acf67fSBill Paul #endif 468778c7b1cSBill Paul 46977732bc5SBill Paul if (ypdb_debug) 47098834523SPhilippe Charnier yp_error("looking up key [%.*s]", 471e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data); 472778c7b1cSBill Paul 473778c7b1cSBill Paul /* 474778c7b1cSBill Paul * Avoid passing back magic "YP_*" entries unless 475778c7b1cSBill Paul * the caller specifically requested them by setting 476778c7b1cSBill Paul * the 'allow' flag. 477778c7b1cSBill Paul */ 478778c7b1cSBill Paul if (!allow && !strncmp(key->data, "YP_", 3)) 479778c7b1cSBill Paul return(YP_NOKEY); 480778c7b1cSBill Paul 481180807d2SBill Paul #ifndef DB_CACHE 482778c7b1cSBill Paul if ((dbp = yp_open_db(domain, map)) == NULL) { 483778c7b1cSBill Paul return(yp_errno); 484778c7b1cSBill Paul } 485180807d2SBill Paul #endif 486778c7b1cSBill Paul 487920491cfSBill Paul if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { 488b2264be8SBill Paul #ifdef DB_CACHE 489c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 490b2264be8SBill Paul #else 491778c7b1cSBill Paul (void)(dbp->close)(dbp); 492b2264be8SBill Paul #endif 493920491cfSBill Paul if (rval == 1) 494778c7b1cSBill Paul return(YP_NOKEY); 495920491cfSBill Paul else 496920491cfSBill Paul return(YP_BADDB); 497778c7b1cSBill Paul } 498778c7b1cSBill Paul 49977732bc5SBill Paul if (ypdb_debug) 50098834523SPhilippe Charnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 501e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data, 502e009976aSDag-Erling Smørgrav (int)data->size, (char *)data->data); 503778c7b1cSBill Paul 504b2264be8SBill Paul #ifdef DB_CACHE 505c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->size) { 506c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = ""; 507c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 508b2264be8SBill Paul } 509b2264be8SBill Paul #else 510f249dbccSDag-Erling Smørgrav bcopy(data->data, &buf, data->size); 511f249dbccSDag-Erling Smørgrav data->data = &buf; 512b2264be8SBill Paul (void)(dbp->close)(dbp); 513b2264be8SBill Paul #endif 514b2264be8SBill Paul 515778c7b1cSBill Paul return(YP_TRUE); 516778c7b1cSBill Paul } 517778c7b1cSBill Paul 518dc584ddbSDag-Erling Smørgrav int 519dc584ddbSDag-Erling Smørgrav yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) 520778c7b1cSBill Paul { 521920491cfSBill Paul int rval; 52279acf67fSBill Paul #ifndef DB_CACHE 52379acf67fSBill Paul static unsigned char buf[YPMAXRECORD]; 52479acf67fSBill Paul #endif 525778c7b1cSBill Paul 52677732bc5SBill Paul if (ypdb_debug) 52798834523SPhilippe Charnier yp_error("retrieving first key in map"); 528778c7b1cSBill Paul 529920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { 530b2264be8SBill Paul #ifdef DB_CACHE 531c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 532b2264be8SBill Paul #endif 533920491cfSBill Paul if (rval == 1) 534920491cfSBill Paul return(YP_NOKEY); 535920491cfSBill Paul else 536778c7b1cSBill Paul return(YP_BADDB); 537920491cfSBill Paul } 538778c7b1cSBill Paul 539778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 540b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) { 541920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { 542b2264be8SBill Paul #ifdef DB_CACHE 543c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 544b2264be8SBill Paul #endif 545920491cfSBill Paul if (rval == 1) 546920491cfSBill Paul return(YP_NOKEY); 547920491cfSBill Paul else 548778c7b1cSBill Paul return(YP_BADDB); 549778c7b1cSBill Paul } 550920491cfSBill Paul } 551778c7b1cSBill Paul 55277732bc5SBill Paul if (ypdb_debug) 55398834523SPhilippe Charnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 554e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data, 555e009976aSDag-Erling Smørgrav (int)data->size, (char *)data->data); 556778c7b1cSBill Paul 557b2264be8SBill Paul #ifdef DB_CACHE 558c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->size) { 559c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = key->data; 560c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = key->size; 561b2264be8SBill Paul } 56279acf67fSBill Paul #else 563f249dbccSDag-Erling Smørgrav bcopy(data->data, &buf, data->size); 564f249dbccSDag-Erling Smørgrav data->data = &buf; 565b2264be8SBill Paul #endif 566b2264be8SBill Paul 567778c7b1cSBill Paul return(YP_TRUE); 568778c7b1cSBill Paul } 569778c7b1cSBill Paul 570dc584ddbSDag-Erling Smørgrav int 571dc584ddbSDag-Erling Smørgrav yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) 572778c7b1cSBill Paul { 573b2264be8SBill Paul static DBT lkey = { NULL, 0 }; 574b2264be8SBill Paul static DBT ldata = { NULL, 0 }; 575920491cfSBill Paul int rval; 57679acf67fSBill Paul #ifndef DB_CACHE 57779acf67fSBill Paul static unsigned char keybuf[YPMAXRECORD]; 57879acf67fSBill Paul static unsigned char datbuf[YPMAXRECORD]; 57979acf67fSBill Paul #endif 580778c7b1cSBill Paul 581180807d2SBill Paul if (key == NULL || !key->size || key->data == NULL) { 582b2264be8SBill Paul rval = yp_first_record(dbp,key,data,allow); 583920491cfSBill Paul if (rval == YP_NOKEY) 584920491cfSBill Paul return(YP_NOMORE); 585559605f1SBill Paul else { 586559605f1SBill Paul #ifdef DB_CACHE 587c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = key->data; 588c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = key->size; 589559605f1SBill Paul #endif 590920491cfSBill Paul return(rval); 591920491cfSBill Paul } 592559605f1SBill Paul } 593778c7b1cSBill Paul 59477732bc5SBill Paul if (ypdb_debug) 59598834523SPhilippe Charnier yp_error("retrieving next key, previous was: [%.*s]", 596e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data); 597778c7b1cSBill Paul 598778c7b1cSBill Paul if (!all) { 599b3e93234SBill Paul #ifdef DB_CACHE 600c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->key == NULL) { 601b2264be8SBill Paul #endif 602778c7b1cSBill Paul (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); 60368cd9748SBill Paul while (key->size != lkey.size || 604f249dbccSDag-Erling Smørgrav strncmp(key->data, lkey.data, 60568cd9748SBill Paul (int)key->size)) 606b3e93234SBill Paul if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) { 607b3e93234SBill Paul #ifdef DB_CACHE 608c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 609b3e93234SBill Paul #endif 610b3e93234SBill Paul return(YP_NOKEY); 611778c7b1cSBill Paul } 612b3e93234SBill Paul 613b3e93234SBill Paul #ifdef DB_CACHE 614b3e93234SBill Paul } 615b3e93234SBill Paul #endif 616b2264be8SBill Paul } 617778c7b1cSBill Paul 618b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 619b2264be8SBill Paul #ifdef DB_CACHE 620c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 621b2264be8SBill Paul #endif 622778c7b1cSBill Paul return(YP_NOMORE); 623b2264be8SBill Paul } 624778c7b1cSBill Paul 625778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 626b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) 627b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 628b2264be8SBill Paul #ifdef DB_CACHE 629c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 630b2264be8SBill Paul #endif 631778c7b1cSBill Paul return(YP_NOMORE); 632b2264be8SBill Paul } 633778c7b1cSBill Paul 63477732bc5SBill Paul if (ypdb_debug) 63598834523SPhilippe Charnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 636e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data, 637e009976aSDag-Erling Smørgrav (int)data->size, (char *)data->data); 638778c7b1cSBill Paul 639b2264be8SBill Paul #ifdef DB_CACHE 640c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->size) { 641c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = key->data; 642c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = key->size; 643b2264be8SBill Paul } 644b2264be8SBill Paul #else 645f249dbccSDag-Erling Smørgrav bcopy(key->data, &keybuf, key->size); 646f249dbccSDag-Erling Smørgrav lkey.data = &keybuf; 647b2264be8SBill Paul lkey.size = key->size; 648f249dbccSDag-Erling Smørgrav bcopy(data->data, &datbuf, data->size); 649f249dbccSDag-Erling Smørgrav data->data = &datbuf; 650b2264be8SBill Paul #endif 651b2264be8SBill Paul 652778c7b1cSBill Paul return(YP_TRUE); 653778c7b1cSBill Paul } 654180807d2SBill Paul 655180807d2SBill Paul #ifdef DB_CACHE 656180807d2SBill Paul /* 657180807d2SBill Paul * Database glue functions. 658180807d2SBill Paul */ 659180807d2SBill Paul 660180807d2SBill Paul static DB *yp_currmap_db = NULL; 661180807d2SBill Paul static int yp_allow_db = 0; 662180807d2SBill Paul 663dc584ddbSDag-Erling Smørgrav ypstat 664dc584ddbSDag-Erling Smørgrav yp_select_map(char *map, char *domain, keydat *key, int allow) 665180807d2SBill Paul { 6660d15a950SBill Paul if (key == NULL) 6670d15a950SBill Paul yp_currmap_db = yp_open_db_cache(domain, map, NULL, 0); 6680d15a950SBill Paul else 6690d15a950SBill Paul yp_currmap_db = yp_open_db_cache(domain, map, 6700d15a950SBill Paul key->keydat_val, 671180807d2SBill Paul key->keydat_len); 672180807d2SBill Paul 673180807d2SBill Paul yp_allow_db = allow; 674180807d2SBill Paul return(yp_errno); 675180807d2SBill Paul } 676180807d2SBill Paul 677dc584ddbSDag-Erling Smørgrav ypstat 678dc584ddbSDag-Erling Smørgrav yp_getbykey(keydat *key, valdat *val) 679180807d2SBill Paul { 680180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 681180807d2SBill Paul ypstat rval; 682180807d2SBill Paul 683180807d2SBill Paul db_key.data = key->keydat_val; 684180807d2SBill Paul db_key.size = key->keydat_len; 685180807d2SBill Paul 686180807d2SBill Paul rval = yp_get_record(yp_currmap_db, 687180807d2SBill Paul &db_key, &db_val, yp_allow_db); 688180807d2SBill Paul 689180807d2SBill Paul if (rval == YP_TRUE) { 690180807d2SBill Paul val->valdat_val = db_val.data; 691180807d2SBill Paul val->valdat_len = db_val.size; 692180807d2SBill Paul } 693180807d2SBill Paul 694180807d2SBill Paul return(rval); 695180807d2SBill Paul } 696180807d2SBill Paul 697dc584ddbSDag-Erling Smørgrav ypstat 698dc584ddbSDag-Erling Smørgrav yp_firstbykey(keydat *key, valdat *val) 699180807d2SBill Paul { 700180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 701180807d2SBill Paul ypstat rval; 702180807d2SBill Paul 703180807d2SBill Paul rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db); 704180807d2SBill Paul 705180807d2SBill Paul if (rval == YP_TRUE) { 706180807d2SBill Paul key->keydat_val = db_key.data; 707180807d2SBill Paul key->keydat_len = db_key.size; 708180807d2SBill Paul val->valdat_val = db_val.data; 709180807d2SBill Paul val->valdat_len = db_val.size; 710180807d2SBill Paul } 711180807d2SBill Paul 712180807d2SBill Paul return(rval); 713180807d2SBill Paul } 714180807d2SBill Paul 715dc584ddbSDag-Erling Smørgrav ypstat 716dc584ddbSDag-Erling Smørgrav yp_nextbykey(keydat *key, valdat *val) 717180807d2SBill Paul { 718180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 719180807d2SBill Paul ypstat rval; 720180807d2SBill Paul 721180807d2SBill Paul db_key.data = key->keydat_val; 722180807d2SBill Paul db_key.size = key->keydat_len; 723180807d2SBill Paul 724180807d2SBill Paul rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db); 725180807d2SBill Paul 726180807d2SBill Paul if (rval == YP_TRUE) { 727180807d2SBill Paul key->keydat_val = db_key.data; 728180807d2SBill Paul key->keydat_len = db_key.size; 729180807d2SBill Paul val->valdat_val = db_val.data; 730180807d2SBill Paul val->valdat_len = db_val.size; 731180807d2SBill Paul } 732180807d2SBill Paul 733180807d2SBill Paul return(rval); 734180807d2SBill Paul } 735180807d2SBill Paul #endif 736