1778c7b1cSBill Paul /* 2778c7b1cSBill Paul * Copyright (c) 1995 3778c7b1cSBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4778c7b1cSBill Paul * 5778c7b1cSBill Paul * Redistribution and use in source and binary forms, with or without 6778c7b1cSBill Paul * modification, are permitted provided that the following conditions 7778c7b1cSBill Paul * are met: 8778c7b1cSBill Paul * 1. Redistributions of source code must retain the above copyright 9778c7b1cSBill Paul * notice, this list of conditions and the following disclaimer. 10778c7b1cSBill Paul * 2. Redistributions in binary form must reproduce the above copyright 11778c7b1cSBill Paul * notice, this list of conditions and the following disclaimer in the 12778c7b1cSBill Paul * documentation and/or other materials provided with the distribution. 13778c7b1cSBill Paul * 3. All advertising materials mentioning features or use of this software 14778c7b1cSBill Paul * must display the following acknowledgement: 15778c7b1cSBill Paul * This product includes software developed by Bill Paul. 16778c7b1cSBill Paul * 4. Neither the name of the author nor the names of any co-contributors 17778c7b1cSBill Paul * may be used to endorse or promote products derived from this software 18778c7b1cSBill Paul * without specific prior written permission. 19778c7b1cSBill Paul * 20778c7b1cSBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21778c7b1cSBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22778c7b1cSBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23778c7b1cSBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24778c7b1cSBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25778c7b1cSBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26778c7b1cSBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27778c7b1cSBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28778c7b1cSBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29778c7b1cSBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30778c7b1cSBill Paul * SUCH DAMAGE. 31778c7b1cSBill Paul */ 32778c7b1cSBill Paul 33b728350eSDavid E. O'Brien #include <sys/cdefs.h> 34b728350eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 3598834523SPhilippe Charnier 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 91dc584ddbSDag-Erling Smørgrav yp_init_dbs(void) 92b2264be8SBill Paul { 93c5e5cd90SPoul-Henning Kamp TAILQ_INIT(&qhead); 94b2264be8SBill Paul return; 95b2264be8SBill Paul } 96b2264be8SBill Paul 971fbdac93SBill Paul /* 9879acf67fSBill Paul * Dynamically allocate an entry for the circular queue. 9979acf67fSBill Paul * Return a NULL pointer on failure. 1001fbdac93SBill Paul */ 101dc584ddbSDag-Erling Smørgrav static struct circleq_entry * 102dc584ddbSDag-Erling Smørgrav yp_malloc_qent(void) 103b2264be8SBill Paul { 10479acf67fSBill Paul register struct circleq_entry *q; 10579acf67fSBill Paul 10679acf67fSBill Paul q = (struct circleq_entry *)malloc(sizeof(struct circleq_entry)); 10779acf67fSBill Paul if (q == NULL) { 10898834523SPhilippe Charnier yp_error("failed to malloc() circleq entry"); 10979acf67fSBill Paul return(NULL); 11079acf67fSBill Paul } 11179acf67fSBill Paul bzero((char *)q, sizeof(struct circleq_entry)); 11279acf67fSBill Paul q->dbptr = (struct dbent *)malloc(sizeof(struct dbent)); 11379acf67fSBill Paul if (q->dbptr == NULL) { 11498834523SPhilippe Charnier yp_error("failed to malloc() circleq entry"); 11579acf67fSBill Paul free(q); 11679acf67fSBill Paul return(NULL); 11779acf67fSBill Paul } 11879acf67fSBill Paul bzero((char *)q->dbptr, sizeof(struct dbent)); 11979acf67fSBill Paul 12079acf67fSBill Paul return(q); 121b2264be8SBill Paul } 122b2264be8SBill Paul 123b2264be8SBill Paul /* 12479acf67fSBill Paul * Free a previously allocated circular queue 12579acf67fSBill Paul * entry. 12679acf67fSBill Paul */ 127dc584ddbSDag-Erling Smørgrav static void 128dc584ddbSDag-Erling Smørgrav yp_free_qent(struct circleq_entry *q) 12979acf67fSBill Paul { 13079acf67fSBill Paul /* 13179acf67fSBill Paul * First, close the database. In theory, this is also 13279acf67fSBill Paul * supposed to free the resources allocated by the DB 13379acf67fSBill Paul * package, including the memory pointed to by q->dbptr->key. 13479acf67fSBill Paul * This means we don't have to free q->dbptr->key here. 13579acf67fSBill Paul */ 13679acf67fSBill Paul if (q->dbptr->dbp) { 13779acf67fSBill Paul (void)(q->dbptr->dbp->close)(q->dbptr->dbp); 13879acf67fSBill Paul q->dbptr->dbp = NULL; 13979acf67fSBill Paul } 14079acf67fSBill Paul /* 14179acf67fSBill Paul * Then free the database name, which was strdup()'ed. 14279acf67fSBill Paul */ 14379acf67fSBill Paul free(q->dbptr->name); 14479acf67fSBill Paul 14579acf67fSBill Paul /* 14679acf67fSBill Paul * Free the rest of the dbent struct. 14779acf67fSBill Paul */ 14879acf67fSBill Paul free(q->dbptr); 14979acf67fSBill Paul q->dbptr = NULL; 15079acf67fSBill Paul 15179acf67fSBill Paul /* 15279acf67fSBill Paul * Free the circleq struct. 15379acf67fSBill Paul */ 15479acf67fSBill Paul free(q); 15579acf67fSBill Paul q = NULL; 15679acf67fSBill Paul 15779acf67fSBill Paul return; 15879acf67fSBill Paul } 15979acf67fSBill Paul 16079acf67fSBill Paul /* 16179acf67fSBill Paul * Zorch a single entry in the dbent queue and release 16279acf67fSBill Paul * all its resources. (This always removes the last entry 16379acf67fSBill Paul * in the queue.) 16479acf67fSBill Paul */ 165dc584ddbSDag-Erling Smørgrav static void 166dc584ddbSDag-Erling Smørgrav yp_flush(void) 16779acf67fSBill Paul { 16879acf67fSBill Paul register struct circleq_entry *qptr; 16979acf67fSBill Paul 170c5e5cd90SPoul-Henning Kamp qptr = TAILQ_LAST(&qhead, circlehead); 171c5e5cd90SPoul-Henning Kamp TAILQ_REMOVE(&qhead, qptr, links); 17279acf67fSBill Paul yp_free_qent(qptr); 17379acf67fSBill Paul numdbs--; 17479acf67fSBill Paul 17579acf67fSBill Paul return; 17679acf67fSBill Paul } 17779acf67fSBill Paul 17879acf67fSBill Paul /* 17979acf67fSBill Paul * Close all databases, erase all database names and empty the queue. 180b2264be8SBill Paul */ 181dc584ddbSDag-Erling Smørgrav void 182dc584ddbSDag-Erling Smørgrav yp_flush_all(void) 183b2264be8SBill Paul { 18479acf67fSBill Paul register struct circleq_entry *qptr; 185b2264be8SBill Paul 186c5e5cd90SPoul-Henning Kamp while (!TAILQ_EMPTY(&qhead)) { 187c5e5cd90SPoul-Henning Kamp qptr = TAILQ_FIRST(&qhead); /* save this */ 188c5e5cd90SPoul-Henning Kamp TAILQ_REMOVE(&qhead, qptr, links); 18979acf67fSBill Paul yp_free_qent(qptr); 190b2264be8SBill Paul } 19179acf67fSBill Paul numdbs = 0; 19279acf67fSBill Paul 19379acf67fSBill Paul return; 194b2264be8SBill Paul } 195b2264be8SBill Paul 19644519760SBill Paul static char *inter_string = "YP_INTERDOMAIN"; 19744519760SBill Paul static char *secure_string = "YP_SECURE"; 19844519760SBill Paul static int inter_sz = sizeof("YP_INTERDOMAIN") - 1; 19944519760SBill Paul static int secure_sz = sizeof("YP_SECURE") - 1; 20044519760SBill Paul 201dc584ddbSDag-Erling Smørgrav static int 202dc584ddbSDag-Erling Smørgrav yp_setflags(DB *dbp) 20344519760SBill Paul { 20444519760SBill Paul DBT key = { NULL, 0 }, data = { NULL, 0 }; 20544519760SBill Paul int flags = 0; 20644519760SBill Paul 20744519760SBill Paul key.data = inter_string; 20844519760SBill Paul key.size = inter_sz; 20944519760SBill Paul 21044519760SBill Paul if (!(dbp->get)(dbp, &key, &data, 0)) 21144519760SBill Paul flags |= YP_INTERDOMAIN; 21244519760SBill Paul 21344519760SBill Paul key.data = secure_string; 21444519760SBill Paul key.size = secure_sz; 21544519760SBill Paul 21644519760SBill Paul if (!(dbp->get)(dbp, &key, &data, 0)) 21744519760SBill Paul flags |= YP_SECURE; 21844519760SBill Paul 21944519760SBill Paul return(flags); 22044519760SBill Paul } 22144519760SBill Paul 222dc584ddbSDag-Erling Smørgrav int 223dc584ddbSDag-Erling Smørgrav yp_testflag(char *map, char *domain, int flag) 22444519760SBill Paul { 22544519760SBill Paul char buf[MAXPATHLEN + 2]; 22644519760SBill Paul register struct circleq_entry *qptr; 22744519760SBill Paul 22844519760SBill Paul if (map == NULL || domain == NULL) 22944519760SBill Paul return(0); 23044519760SBill Paul 23144519760SBill Paul strcpy(buf, domain); 23244519760SBill Paul strcat(buf, "/"); 23344519760SBill Paul strcat(buf, map); 23444519760SBill Paul 235c5e5cd90SPoul-Henning Kamp TAILQ_FOREACH(qptr, &qhead, links) { 23644519760SBill Paul if (!strcmp(qptr->dbptr->name, buf)) { 23744519760SBill Paul if (qptr->dbptr->flags & flag) 23844519760SBill Paul return(1); 23944519760SBill Paul else 24044519760SBill Paul return(0); 24144519760SBill Paul } 24244519760SBill Paul } 24344519760SBill Paul 24444519760SBill Paul if (yp_open_db_cache(domain, map, NULL, 0) == NULL) 24544519760SBill Paul return(0); 24644519760SBill Paul 247c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->flags & flag) 24844519760SBill Paul return(1); 24944519760SBill Paul 25044519760SBill Paul return(0); 25144519760SBill Paul } 252b2264be8SBill Paul 253b2264be8SBill Paul /* 254b2264be8SBill Paul * Add a DB handle and database name to the cache. We only maintain 255b2264be8SBill Paul * fixed number of entries in the cache, so if we're asked to store 256b2264be8SBill Paul * a new entry when all our slots are already filled, we have to kick 257b2264be8SBill Paul * out the entry in the last slot to make room. 258b2264be8SBill Paul */ 259dc584ddbSDag-Erling Smørgrav static int 260dc584ddbSDag-Erling Smørgrav yp_cache_db(DB *dbp, char *name, int size) 261b2264be8SBill Paul { 26279acf67fSBill Paul register struct circleq_entry *qptr; 263b2264be8SBill Paul 26479acf67fSBill Paul if (numdbs == MAXDBS) { 265b2264be8SBill Paul if (ypdb_debug) 26679acf67fSBill Paul yp_error("queue overflow -- releasing last slot"); 26779acf67fSBill Paul yp_flush(); 268b2264be8SBill Paul } 269b2264be8SBill Paul 270b2264be8SBill Paul /* 27179acf67fSBill Paul * Allocate a new queue entry. 272b2264be8SBill Paul */ 27379acf67fSBill Paul 27479acf67fSBill Paul if ((qptr = yp_malloc_qent()) == NULL) { 27579acf67fSBill Paul yp_error("failed to allocate a new cache entry"); 27679acf67fSBill Paul return(1); 277b2264be8SBill Paul } 278b2264be8SBill Paul 27979acf67fSBill Paul qptr->dbptr->dbp = dbp; 28079acf67fSBill Paul qptr->dbptr->name = strdup(name); 28179acf67fSBill Paul qptr->dbptr->size = size; 28279acf67fSBill Paul qptr->dbptr->key = NULL; 28379acf67fSBill Paul 28444519760SBill Paul qptr->dbptr->flags = yp_setflags(dbp); 28544519760SBill Paul 286c5e5cd90SPoul-Henning Kamp TAILQ_INSERT_HEAD(&qhead, qptr, links); 287b2264be8SBill Paul numdbs++; 28879acf67fSBill Paul 28979acf67fSBill Paul return(0); 290b2264be8SBill Paul } 291b2264be8SBill Paul 292b2264be8SBill Paul /* 293b2264be8SBill Paul * Search the list for a database matching 'name.' If we find it, 294b2264be8SBill Paul * move it to the head of the list and return its DB handle. If 295b2264be8SBill Paul * not, just fail: yp_open_db_cache() will subsequently try to open 29679acf67fSBill Paul * the database itself and call yp_cache_db() to add it to the 297b2264be8SBill Paul * list. 298b2264be8SBill Paul * 299b2264be8SBill Paul * The search works like this: 300b2264be8SBill Paul * 301b2264be8SBill Paul * - The caller specifies the name of a database to locate. We try to 30279acf67fSBill Paul * find an entry in our queue with a matching name. 303b2264be8SBill Paul * 304b2264be8SBill Paul * - If the caller doesn't specify a key or size, we assume that the 305b2264be8SBill Paul * first entry that we encounter with a matching name is returned. 30679acf67fSBill Paul * This will result in matches regardless of the key/size values 30779acf67fSBill Paul * stored in the queue entry. 308b2264be8SBill Paul * 30979acf67fSBill Paul * - If the caller also specifies a key and length, we check to see 31079acf67fSBill Paul * if the key and length saved in the queue entry also matches. 311b2264be8SBill Paul * This lets us return a DB handle that's already positioned at the 312b2264be8SBill Paul * correct location within a database. 313b2264be8SBill Paul * 31479acf67fSBill Paul * - Once we have a match, it gets migrated to the top of the queue 31579acf67fSBill Paul * so that it will be easier to find if another request for 316b2264be8SBill Paul * the same database comes in later. 317b2264be8SBill Paul */ 318dc584ddbSDag-Erling Smørgrav static DB * 319f249dbccSDag-Erling Smørgrav yp_find_db(const char *name, const char *key, int size) 320b2264be8SBill Paul { 32179acf67fSBill Paul register struct circleq_entry *qptr; 322b2264be8SBill Paul 323c5e5cd90SPoul-Henning Kamp TAILQ_FOREACH(qptr, &qhead, links) { 32479acf67fSBill Paul if (!strcmp(qptr->dbptr->name, name)) { 325b2264be8SBill Paul if (size) { 32679acf67fSBill Paul if (size != qptr->dbptr->size || 32779acf67fSBill Paul strncmp(qptr->dbptr->key, key, size)) 328b2264be8SBill Paul continue; 329b2264be8SBill Paul } else { 33079acf67fSBill Paul if (qptr->dbptr->size) 331b2264be8SBill Paul continue; 332b2264be8SBill Paul } 333c5e5cd90SPoul-Henning Kamp if (qptr != TAILQ_FIRST(&qhead)) { 334c5e5cd90SPoul-Henning Kamp TAILQ_REMOVE(&qhead, qptr, links); 335c5e5cd90SPoul-Henning Kamp TAILQ_INSERT_HEAD(&qhead, qptr, links); 336b2264be8SBill Paul } 33779acf67fSBill Paul return(qptr->dbptr->dbp); 338b2264be8SBill Paul } 339b2264be8SBill Paul } 340b3e93234SBill Paul 341b2264be8SBill Paul return(NULL); 342b2264be8SBill Paul } 343b2264be8SBill Paul 344b2264be8SBill Paul /* 345b2264be8SBill Paul * Open a DB database and cache the handle for later use. We first 346b2264be8SBill Paul * check the cache to see if the required database is already open. 347b2264be8SBill Paul * If so, we fetch the handle from the cache. If not, we try to open 348b2264be8SBill Paul * the database and save the handle in the cache for later use. 349b2264be8SBill Paul */ 350dc584ddbSDag-Erling Smørgrav DB * 351dc584ddbSDag-Erling Smørgrav yp_open_db_cache(const char *domain, const char *map, const char *key, 352dc584ddbSDag-Erling Smørgrav const int size) 353b2264be8SBill Paul { 354b2264be8SBill Paul DB *dbp = NULL; 355b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 356b3e93234SBill Paul /* 357b3e93234SBill Paul snprintf(buf, sizeof(buf), "%s/%s", domain, map); 358b3e93234SBill Paul */ 35979acf67fSBill Paul yp_errno = YP_TRUE; 360b2264be8SBill Paul 3611fbdac93SBill Paul strcpy(buf, domain); 3621fbdac93SBill Paul strcat(buf, "/"); 3631fbdac93SBill Paul strcat(buf, map); 364b2264be8SBill Paul 365f249dbccSDag-Erling Smørgrav if ((dbp = yp_find_db(buf, key, size)) != NULL) { 366b2264be8SBill Paul return(dbp); 367b2264be8SBill Paul } else { 36879acf67fSBill Paul if ((dbp = yp_open_db(domain, map)) != NULL) { 369f249dbccSDag-Erling Smørgrav if (yp_cache_db(dbp, buf, size)) { 37079acf67fSBill Paul (void)(dbp->close)(dbp); 37179acf67fSBill Paul yp_errno = YP_YPERR; 37279acf67fSBill Paul return(NULL); 37379acf67fSBill Paul } 37479acf67fSBill Paul } 375b2264be8SBill Paul } 376b2264be8SBill Paul 377b2264be8SBill Paul return (dbp); 378b2264be8SBill Paul } 379b2264be8SBill Paul #endif 380b2264be8SBill Paul 381b2264be8SBill Paul /* 382b2264be8SBill Paul * Open a DB database. 383778c7b1cSBill Paul */ 384dc584ddbSDag-Erling Smørgrav DB * 385dc584ddbSDag-Erling Smørgrav yp_open_db(const char *domain, const char *map) 386778c7b1cSBill Paul { 387b2264be8SBill Paul DB *dbp = NULL; 388b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 389778c7b1cSBill Paul 390778c7b1cSBill Paul yp_errno = YP_TRUE; 391778c7b1cSBill Paul 392778c7b1cSBill Paul if (map[0] == '.' || strchr(map, '/')) { 393778c7b1cSBill Paul yp_errno = YP_BADARGS; 394778c7b1cSBill Paul return (NULL); 395778c7b1cSBill Paul } 396778c7b1cSBill Paul 397b2264be8SBill Paul #ifdef DB_CACHE 398b2264be8SBill Paul if (yp_validdomain(domain)) { 399b2264be8SBill Paul yp_errno = YP_NODOM; 400b2264be8SBill Paul return(NULL); 401b2264be8SBill Paul } 402b2264be8SBill Paul #endif 403778c7b1cSBill Paul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); 404778c7b1cSBill Paul 405b2264be8SBill Paul #ifdef DB_CACHE 406b2264be8SBill Paul again: 407b2264be8SBill Paul #endif 408b2264be8SBill Paul dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL); 409778c7b1cSBill Paul 410778c7b1cSBill Paul if (dbp == NULL) { 411778c7b1cSBill Paul switch (errno) { 412b2264be8SBill Paul #ifdef DB_CACHE 413b2264be8SBill Paul case ENFILE: 414b2264be8SBill Paul /* 415b2264be8SBill Paul * We ran out of file descriptors. Nuke an 416b2264be8SBill Paul * open one and try again. 417b2264be8SBill Paul */ 418b2264be8SBill Paul yp_error("ran out of file descriptors"); 41979acf67fSBill Paul yp_flush(); 420b2264be8SBill Paul goto again; 421b2264be8SBill Paul break; 422b2264be8SBill Paul #endif 423778c7b1cSBill Paul case ENOENT: 424778c7b1cSBill Paul yp_errno = YP_NOMAP; 425778c7b1cSBill Paul break; 426778c7b1cSBill Paul case EFTYPE: 427778c7b1cSBill Paul yp_errno = YP_BADDB; 428778c7b1cSBill Paul break; 429778c7b1cSBill Paul default: 430778c7b1cSBill Paul yp_errno = YP_YPERR; 431778c7b1cSBill Paul break; 432778c7b1cSBill Paul } 433778c7b1cSBill Paul } 434778c7b1cSBill Paul 435778c7b1cSBill Paul return (dbp); 436778c7b1cSBill Paul } 437778c7b1cSBill Paul 438778c7b1cSBill Paul /* 439778c7b1cSBill Paul * Database access routines. 440778c7b1cSBill Paul * 441778c7b1cSBill Paul * - yp_get_record(): retrieve an arbitrary key/data pair given one key 442778c7b1cSBill Paul * to match against. 443778c7b1cSBill Paul * 444778c7b1cSBill Paul * - yp_first_record(): retrieve first key/data base in a database. 445778c7b1cSBill Paul * 446778c7b1cSBill Paul * - yp_next_record(): retrieve key/data pair that sequentially follows 447778c7b1cSBill Paul * the supplied key value in the database. 448778c7b1cSBill Paul */ 449778c7b1cSBill Paul 450180807d2SBill Paul #ifdef DB_CACHE 451dc584ddbSDag-Erling Smørgrav int 452dc584ddbSDag-Erling Smørgrav yp_get_record(DB *dbp, const DBT *key, DBT *data, int allow) 453180807d2SBill Paul #else 454dc584ddbSDag-Erling Smørgrav int 455dc584ddbSDag-Erling Smørgrav yp_get_record(const char *domain, const char *map, 456dc584ddbSDag-Erling Smørgrav const DBT *key, DBT *data, int allow) 457180807d2SBill Paul #endif 458778c7b1cSBill Paul { 459180807d2SBill Paul #ifndef DB_CACHE 460778c7b1cSBill Paul DB *dbp; 461180807d2SBill Paul #endif 462b2264be8SBill Paul int rval = 0; 46379acf67fSBill Paul #ifndef DB_CACHE 46479acf67fSBill Paul static unsigned char buf[YPMAXRECORD]; 46579acf67fSBill Paul #endif 466778c7b1cSBill Paul 46777732bc5SBill Paul if (ypdb_debug) 46898834523SPhilippe Charnier yp_error("looking up key [%.*s]", 469e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data); 470778c7b1cSBill Paul 471778c7b1cSBill Paul /* 472778c7b1cSBill Paul * Avoid passing back magic "YP_*" entries unless 473778c7b1cSBill Paul * the caller specifically requested them by setting 474778c7b1cSBill Paul * the 'allow' flag. 475778c7b1cSBill Paul */ 476778c7b1cSBill Paul if (!allow && !strncmp(key->data, "YP_", 3)) 477778c7b1cSBill Paul return(YP_NOKEY); 478778c7b1cSBill Paul 479180807d2SBill Paul #ifndef DB_CACHE 480778c7b1cSBill Paul if ((dbp = yp_open_db(domain, map)) == NULL) { 481778c7b1cSBill Paul return(yp_errno); 482778c7b1cSBill Paul } 483180807d2SBill Paul #endif 484778c7b1cSBill Paul 485920491cfSBill Paul if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { 486b2264be8SBill Paul #ifdef DB_CACHE 487c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 488b2264be8SBill Paul #else 489778c7b1cSBill Paul (void)(dbp->close)(dbp); 490b2264be8SBill Paul #endif 491920491cfSBill Paul if (rval == 1) 492778c7b1cSBill Paul return(YP_NOKEY); 493920491cfSBill Paul else 494920491cfSBill Paul return(YP_BADDB); 495778c7b1cSBill Paul } 496778c7b1cSBill Paul 49777732bc5SBill Paul if (ypdb_debug) 49898834523SPhilippe Charnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 499e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data, 500e009976aSDag-Erling Smørgrav (int)data->size, (char *)data->data); 501778c7b1cSBill Paul 502b2264be8SBill Paul #ifdef DB_CACHE 503c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->size) { 504c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = ""; 505c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 506b2264be8SBill Paul } 507b2264be8SBill Paul #else 508f249dbccSDag-Erling Smørgrav bcopy(data->data, &buf, data->size); 509f249dbccSDag-Erling Smørgrav data->data = &buf; 510b2264be8SBill Paul (void)(dbp->close)(dbp); 511b2264be8SBill Paul #endif 512b2264be8SBill Paul 513778c7b1cSBill Paul return(YP_TRUE); 514778c7b1cSBill Paul } 515778c7b1cSBill Paul 516dc584ddbSDag-Erling Smørgrav int 517dc584ddbSDag-Erling Smørgrav yp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) 518778c7b1cSBill Paul { 519920491cfSBill Paul int rval; 52079acf67fSBill Paul #ifndef DB_CACHE 52179acf67fSBill Paul static unsigned char buf[YPMAXRECORD]; 52279acf67fSBill Paul #endif 523778c7b1cSBill Paul 52477732bc5SBill Paul if (ypdb_debug) 52598834523SPhilippe Charnier yp_error("retrieving first key in map"); 526778c7b1cSBill Paul 527920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { 528b2264be8SBill Paul #ifdef DB_CACHE 529c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 530b2264be8SBill Paul #endif 531920491cfSBill Paul if (rval == 1) 532920491cfSBill Paul return(YP_NOKEY); 533920491cfSBill Paul else 534778c7b1cSBill Paul return(YP_BADDB); 535920491cfSBill Paul } 536778c7b1cSBill Paul 537778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 538b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) { 539920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { 540b2264be8SBill Paul #ifdef DB_CACHE 541c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 542b2264be8SBill Paul #endif 543920491cfSBill Paul if (rval == 1) 544920491cfSBill Paul return(YP_NOKEY); 545920491cfSBill Paul else 546778c7b1cSBill Paul return(YP_BADDB); 547778c7b1cSBill Paul } 548920491cfSBill Paul } 549778c7b1cSBill Paul 55077732bc5SBill Paul if (ypdb_debug) 55198834523SPhilippe Charnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 552e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data, 553e009976aSDag-Erling Smørgrav (int)data->size, (char *)data->data); 554778c7b1cSBill Paul 555b2264be8SBill Paul #ifdef DB_CACHE 556c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->size) { 557c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = key->data; 558c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = key->size; 559b2264be8SBill Paul } 56079acf67fSBill Paul #else 561f249dbccSDag-Erling Smørgrav bcopy(data->data, &buf, data->size); 562f249dbccSDag-Erling Smørgrav data->data = &buf; 563b2264be8SBill Paul #endif 564b2264be8SBill Paul 565778c7b1cSBill Paul return(YP_TRUE); 566778c7b1cSBill Paul } 567778c7b1cSBill Paul 568dc584ddbSDag-Erling Smørgrav int 569dc584ddbSDag-Erling Smørgrav yp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) 570778c7b1cSBill Paul { 571b2264be8SBill Paul static DBT lkey = { NULL, 0 }; 572b2264be8SBill Paul static DBT ldata = { NULL, 0 }; 573920491cfSBill Paul int rval; 57479acf67fSBill Paul #ifndef DB_CACHE 57579acf67fSBill Paul static unsigned char keybuf[YPMAXRECORD]; 57679acf67fSBill Paul static unsigned char datbuf[YPMAXRECORD]; 57779acf67fSBill Paul #endif 578778c7b1cSBill Paul 579180807d2SBill Paul if (key == NULL || !key->size || key->data == NULL) { 580b2264be8SBill Paul rval = yp_first_record(dbp,key,data,allow); 581920491cfSBill Paul if (rval == YP_NOKEY) 582920491cfSBill Paul return(YP_NOMORE); 583559605f1SBill Paul else { 584559605f1SBill Paul #ifdef DB_CACHE 585c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = key->data; 586c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = key->size; 587559605f1SBill Paul #endif 588920491cfSBill Paul return(rval); 589920491cfSBill Paul } 590559605f1SBill Paul } 591778c7b1cSBill Paul 59277732bc5SBill Paul if (ypdb_debug) 59398834523SPhilippe Charnier yp_error("retrieving next key, previous was: [%.*s]", 594e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data); 595778c7b1cSBill Paul 596778c7b1cSBill Paul if (!all) { 597b3e93234SBill Paul #ifdef DB_CACHE 598c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->key == NULL) { 599b2264be8SBill Paul #endif 600778c7b1cSBill Paul (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); 60168cd9748SBill Paul while (key->size != lkey.size || 602f249dbccSDag-Erling Smørgrav strncmp(key->data, lkey.data, 60368cd9748SBill Paul (int)key->size)) 604b3e93234SBill Paul if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) { 605b3e93234SBill Paul #ifdef DB_CACHE 606c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 607b3e93234SBill Paul #endif 608b3e93234SBill Paul return(YP_NOKEY); 609778c7b1cSBill Paul } 610b3e93234SBill Paul 611b3e93234SBill Paul #ifdef DB_CACHE 612b3e93234SBill Paul } 613b3e93234SBill Paul #endif 614b2264be8SBill Paul } 615778c7b1cSBill Paul 616b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 617b2264be8SBill Paul #ifdef DB_CACHE 618c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 619b2264be8SBill Paul #endif 620778c7b1cSBill Paul return(YP_NOMORE); 621b2264be8SBill Paul } 622778c7b1cSBill Paul 623778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 624b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) 625b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 626b2264be8SBill Paul #ifdef DB_CACHE 627c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = 0; 628b2264be8SBill Paul #endif 629778c7b1cSBill Paul return(YP_NOMORE); 630b2264be8SBill Paul } 631778c7b1cSBill Paul 63277732bc5SBill Paul if (ypdb_debug) 63398834523SPhilippe Charnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 634e009976aSDag-Erling Smørgrav (int)key->size, (char *)key->data, 635e009976aSDag-Erling Smørgrav (int)data->size, (char *)data->data); 636778c7b1cSBill Paul 637b2264be8SBill Paul #ifdef DB_CACHE 638c5e5cd90SPoul-Henning Kamp if (TAILQ_FIRST(&qhead)->dbptr->size) { 639c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->key = key->data; 640c5e5cd90SPoul-Henning Kamp TAILQ_FIRST(&qhead)->dbptr->size = key->size; 641b2264be8SBill Paul } 642b2264be8SBill Paul #else 643f249dbccSDag-Erling Smørgrav bcopy(key->data, &keybuf, key->size); 644f249dbccSDag-Erling Smørgrav lkey.data = &keybuf; 645b2264be8SBill Paul lkey.size = key->size; 646f249dbccSDag-Erling Smørgrav bcopy(data->data, &datbuf, data->size); 647f249dbccSDag-Erling Smørgrav data->data = &datbuf; 648b2264be8SBill Paul #endif 649b2264be8SBill Paul 650778c7b1cSBill Paul return(YP_TRUE); 651778c7b1cSBill Paul } 652180807d2SBill Paul 653180807d2SBill Paul #ifdef DB_CACHE 654180807d2SBill Paul /* 655180807d2SBill Paul * Database glue functions. 656180807d2SBill Paul */ 657180807d2SBill Paul 658180807d2SBill Paul static DB *yp_currmap_db = NULL; 659180807d2SBill Paul static int yp_allow_db = 0; 660180807d2SBill Paul 661dc584ddbSDag-Erling Smørgrav ypstat 662dc584ddbSDag-Erling Smørgrav yp_select_map(char *map, char *domain, keydat *key, int allow) 663180807d2SBill Paul { 6640d15a950SBill Paul if (key == NULL) 6650d15a950SBill Paul yp_currmap_db = yp_open_db_cache(domain, map, NULL, 0); 6660d15a950SBill Paul else 6670d15a950SBill Paul yp_currmap_db = yp_open_db_cache(domain, map, 6680d15a950SBill Paul key->keydat_val, 669180807d2SBill Paul key->keydat_len); 670180807d2SBill Paul 671180807d2SBill Paul yp_allow_db = allow; 672180807d2SBill Paul return(yp_errno); 673180807d2SBill Paul } 674180807d2SBill Paul 675dc584ddbSDag-Erling Smørgrav ypstat 676dc584ddbSDag-Erling Smørgrav yp_getbykey(keydat *key, valdat *val) 677180807d2SBill Paul { 678180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 679180807d2SBill Paul ypstat rval; 680180807d2SBill Paul 681180807d2SBill Paul db_key.data = key->keydat_val; 682180807d2SBill Paul db_key.size = key->keydat_len; 683180807d2SBill Paul 684180807d2SBill Paul rval = yp_get_record(yp_currmap_db, 685180807d2SBill Paul &db_key, &db_val, yp_allow_db); 686180807d2SBill Paul 687180807d2SBill Paul if (rval == YP_TRUE) { 688180807d2SBill Paul val->valdat_val = db_val.data; 689180807d2SBill Paul val->valdat_len = db_val.size; 690180807d2SBill Paul } 691180807d2SBill Paul 692180807d2SBill Paul return(rval); 693180807d2SBill Paul } 694180807d2SBill Paul 695dc584ddbSDag-Erling Smørgrav ypstat 696dc584ddbSDag-Erling Smørgrav yp_firstbykey(keydat *key, valdat *val) 697180807d2SBill Paul { 698180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 699180807d2SBill Paul ypstat rval; 700180807d2SBill Paul 701180807d2SBill Paul rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db); 702180807d2SBill Paul 703180807d2SBill Paul if (rval == YP_TRUE) { 704180807d2SBill Paul key->keydat_val = db_key.data; 705180807d2SBill Paul key->keydat_len = db_key.size; 706180807d2SBill Paul val->valdat_val = db_val.data; 707180807d2SBill Paul val->valdat_len = db_val.size; 708180807d2SBill Paul } 709180807d2SBill Paul 710180807d2SBill Paul return(rval); 711180807d2SBill Paul } 712180807d2SBill Paul 713dc584ddbSDag-Erling Smørgrav ypstat 714dc584ddbSDag-Erling Smørgrav yp_nextbykey(keydat *key, valdat *val) 715180807d2SBill Paul { 716180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 717180807d2SBill Paul ypstat rval; 718180807d2SBill Paul 719180807d2SBill Paul db_key.data = key->keydat_val; 720180807d2SBill Paul db_key.size = key->keydat_len; 721180807d2SBill Paul 722180807d2SBill Paul rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db); 723180807d2SBill Paul 724180807d2SBill Paul if (rval == YP_TRUE) { 725180807d2SBill Paul key->keydat_val = db_key.data; 726180807d2SBill Paul key->keydat_len = db_key.size; 727180807d2SBill Paul val->valdat_val = db_val.data; 728180807d2SBill Paul val->valdat_len = db_val.size; 729180807d2SBill Paul } 730180807d2SBill Paul 731180807d2SBill Paul return(rval); 732180807d2SBill Paul } 733180807d2SBill Paul #endif 734