Home | History | Annotate | Line # | Download | only in ypserv
      1 /*	$NetBSD: ypserv_db.c,v 1.23 2020/10/13 13:56:34 kamil Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994 Mats O Jansson <moj (at) stacken.kth.se>
      5  * Copyright (c) 1996 Charles D. Cranor
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 #ifndef lint
     32 __RCSID("$NetBSD: ypserv_db.c,v 1.23 2020/10/13 13:56:34 kamil Exp $");
     33 #endif
     34 
     35 /*
     36  * major revision/cleanup of Mats' version done by
     37  * Chuck Cranor <chuck@netbsd> Jan 1996.
     38  */
     39 
     40 #include <sys/types.h>
     41 #include <sys/socket.h>
     42 #include <sys/queue.h>
     43 #include <sys/stat.h>
     44 #include <sys/param.h>
     45 
     46 #include <netinet/in.h>
     47 #include <arpa/inet.h>
     48 #include <arpa/nameser.h>
     49 
     50 #include <errno.h>
     51 #include <string.h>
     52 #include <stdio.h>
     53 #include <stdlib.h>
     54 #include <netdb.h>
     55 #include <resolv.h>
     56 #include <syslog.h>
     57 
     58 #include <rpc/rpc.h>
     59 #include <rpcsvc/yp_prot.h>
     60 #include <rpcsvc/ypclnt.h>
     61 
     62 #include "ypdb.h"
     63 #include "ypdef.h"
     64 #include "ypserv.h"
     65 
     66 LIST_HEAD(domainlist, opt_domain);	/* LIST of domains */
     67 LIST_HEAD(maplist, opt_map);		/* LIST of maps (in a domain) */
     68 TAILQ_HEAD(mapq, opt_map);		/* TAILQ of maps (LRU) */
     69 
     70 struct opt_map {
     71 	char	*map;			/* map name (malloc'd) */
     72 	DBM	*db;			/* database */
     73 	struct opt_domain *dom;		/* back ptr to our domain */
     74 	int	host_lookup;		/* host lookup */
     75 	int	secure;			/* is this map secure? */
     76 	dev_t	dbdev;			/* device db is on */
     77 	ino_t	dbino;			/* inode of db */
     78 	time_t	dbmtime;		/* time of last db modification */
     79 	TAILQ_ENTRY(opt_map) mapsq;	/* map queue pointers */
     80 	LIST_ENTRY(opt_map) mapsl;	/* map list pointers */
     81 };
     82 
     83 struct opt_domain {
     84 	char	*domain;		/* domain name (malloc'd) */
     85 	struct maplist dmaps;		/* the domain's active maps */
     86 	LIST_ENTRY(opt_domain) domsl;	/* global linked list of domains */
     87 };
     88 
     89 struct domainlist doms;			/* global list of domains */
     90 struct mapq     maps;			/* global queue of maps (LRU) */
     91 
     92 extern int      usedns;
     93 
     94 int	yp_private(datum, int);
     95 void	ypdb_close_db(DBM *);
     96 void	ypdb_close_last(void);
     97 void	ypdb_close_map(struct opt_map *);
     98 DBM    *ypdb_open_db(const char *, const char *, u_int *, struct opt_map **);
     99 u_int	lookup_host(int, int, DBM *, char *, struct ypresp_val *);
    100 
    101 /*
    102  * ypdb_init: init the queues and lists
    103  */
    104 void
    105 ypdb_init(void)
    106 {
    107 
    108 	LIST_INIT(&doms);
    109 	TAILQ_INIT(&maps);
    110 }
    111 
    112 /*
    113  * yp_private:
    114  * Check if key is a YP private key.  Return TRUE if it is and
    115  * ypprivate is FALSE.
    116  */
    117 int
    118 yp_private(datum key, int ypprivate)
    119 {
    120 
    121 	if (ypprivate)
    122 		return (FALSE);
    123 
    124 	if (key.dsize == 0 || key.dptr == NULL)
    125 		return (FALSE);
    126 
    127 	if (key.dsize == YP_LAST_LEN &&
    128 	    strncmp(key.dptr, YP_LAST_KEY, YP_LAST_LEN) == 0)
    129 		return (TRUE);
    130 
    131 	if (key.dsize == YP_INPUT_LEN &&
    132 	    strncmp(key.dptr, YP_INPUT_KEY, YP_INPUT_LEN) == 0)
    133 		return (TRUE);
    134 
    135 	if (key.dsize == YP_OUTPUT_LEN &&
    136 	    strncmp(key.dptr, YP_OUTPUT_KEY, YP_OUTPUT_LEN) == 0)
    137 		return (TRUE);
    138 
    139 	if (key.dsize == YP_MASTER_LEN &&
    140 	    strncmp(key.dptr, YP_MASTER_KEY, YP_MASTER_LEN) == 0)
    141 		return (TRUE);
    142 
    143 	if (key.dsize == YP_DOMAIN_LEN &&
    144 	    strncmp(key.dptr, YP_DOMAIN_KEY, YP_DOMAIN_LEN) == 0)
    145 		return (TRUE);
    146 
    147 	if (key.dsize == YP_INTERDOMAIN_LEN &&
    148 	    strncmp(key.dptr, YP_INTERDOMAIN_KEY, YP_INTERDOMAIN_LEN) == 0)
    149 		return (TRUE);
    150 
    151 	if (key.dsize == YP_SECURE_LEN &&
    152 	    strncmp(key.dptr, YP_SECURE_KEY, YP_SECURE_LEN) == 0)
    153 		return (TRUE);
    154 
    155 	return (FALSE);
    156 }
    157 
    158 /*
    159  * Close specified map.
    160  */
    161 void
    162 ypdb_close_map(struct opt_map *map)
    163 {
    164 	TAILQ_REMOVE(&maps, map, mapsq);	/* remove from LRU tailq */
    165 	LIST_REMOVE(map, mapsl);		/* remove from domain list */
    166 
    167 #ifdef DEBUG
    168 	syslog(LOG_DEBUG,
    169 	    "ypdb_close_map: closing map %s in domain %s [db=%p]",
    170 	    map->map, map->dom->domain, map->db);
    171 #endif
    172 
    173 	ypdb_close(map->db);			/* close DB */
    174 	free(map->map);				/* free map name */
    175 	free(map);				/* free map */
    176 }
    177 
    178 /*
    179  * Close least recently used map. This routine is called when we have
    180  * no more file descriptors free, or we want to close all maps.
    181  */
    182 void
    183 ypdb_close_last(void)
    184 {
    185 	struct opt_map *last;
    186 
    187 	if (TAILQ_EMPTY(&maps)) {
    188 		syslog(LOG_ERR,
    189 		    "ypdb_close_last: LRU list is empty!");
    190 		return;
    191 	}
    192 	last = TAILQ_LAST(&maps, mapq);
    193 	ypdb_close_map(last);
    194 }
    195 
    196 /*
    197  * Close all open maps.
    198  */
    199 void
    200 ypdb_close_all(void)
    201 {
    202 
    203 #ifdef DEBUG
    204 	syslog(LOG_DEBUG, "ypdb_close_all(): start");
    205 #endif
    206 
    207 	while (!TAILQ_EMPTY(&maps))
    208 		ypdb_close_last();
    209 
    210 #ifdef DEBUG
    211 	syslog(LOG_DEBUG, "ypdb_close_all(): done");
    212 #endif
    213 }
    214 
    215 /*
    216  * Close Database if Open/Close Optimization isn't turned on.
    217  */
    218 void
    219 /*ARGSUSED*/
    220 ypdb_close_db(DBM *db)
    221 {
    222 
    223 #ifdef DEBUG
    224 	syslog(LOG_DEBUG, "ypdb_close_db(%p)", db);
    225 #endif
    226 
    227 #ifndef OPTIMIZE_DB
    228 	ypdb_close_all();
    229 #endif /* not OPTIMIZE_DB */
    230 }
    231 
    232 /*
    233  * ypdb_open_db
    234  */
    235 DBM *
    236 ypdb_open_db(const char *domain, const char *map, u_int *status,
    237 	     struct opt_map **map_info)
    238 {
    239 	static const char *domain_key = YP_INTERDOMAIN_KEY;
    240 	static const char *secure_key = YP_SECURE_KEY;
    241 	char map_path[MAXPATHLEN];
    242 	struct stat finfo;
    243 	struct opt_domain *d = NULL;
    244 	struct opt_map *m = NULL;
    245 	DBM *db;
    246 	datum k, v;
    247 
    248 	*status = YP_TRUE;	/* defaults to true */
    249 
    250 	/*
    251 	 * check for illegal domain and map names
    252 	 */
    253 	if (_yp_invalid_domain(domain)) {
    254 		*status = YP_NODOM;
    255 		return (NULL);
    256 	}
    257 	if (_yp_invalid_map(map)) {
    258 		*status = YP_NOMAP;
    259 		return (NULL);
    260 	}
    261 
    262 	/*
    263 	 * check for domain, file.
    264 	 */
    265 	(void)snprintf(map_path, sizeof(map_path), "%s/%s", YP_DB_PATH, domain);
    266 	if (stat(map_path, &finfo) < 0 || !S_ISDIR(finfo.st_mode)) {
    267 #ifdef DEBUG
    268 		syslog(LOG_DEBUG,
    269 		    "ypdb_open_db: no domain %s (map=%s)", domain, map);
    270 #endif
    271 		*status = YP_NODOM;
    272 	} else {
    273 		(void)snprintf(map_path, sizeof(map_path), "%s/%s/%s%s",
    274 		    YP_DB_PATH, domain, map, YPDB_SUFFIX);
    275 		if (stat(map_path, &finfo) < 0) {
    276 #ifdef DEBUG
    277 			syslog(LOG_DEBUG,
    278 			    "ypdb_open_db: no map %s (domain=%s)", map,
    279 			    domain);
    280 #endif
    281 			*status = YP_NOMAP;
    282 		}
    283 	}
    284 
    285 	/*
    286 	 * check for preloaded domain, map
    287 	 */
    288 	for (d = doms.lh_first; d != NULL; d = d->domsl.le_next)
    289 		if (strcmp(domain, d->domain) == 0)
    290 			break;
    291 
    292 	if (d)
    293 		for (m = d->dmaps.lh_first; m != NULL; m = m->mapsl.le_next)
    294 			if (strcmp(map, m->map) == 0)
    295 				break;
    296 
    297 	/*
    298 	 * map found open?
    299 	 */
    300 	if (m) {
    301 #ifdef DEBUG
    302 		syslog(LOG_DEBUG,
    303 		    "ypdb_open_db: cached open: domain=%s, map=%s, db=%p,",
    304 		    domain, map, m->db);
    305 		syslog(LOG_DEBUG,
    306 		    "\tdbdev %d new %d; dbino %d new %d; dbmtime %ld new %ld",
    307 		    m->dbdev, finfo.st_dev, m->dbino, finfo.st_ino,
    308 		    (long) m->dbmtime, (long) finfo.st_mtime);
    309 #endif
    310 		/*
    311 		 * if status != YP_TRUE, then this cached database is now
    312 		 * non-existent
    313 		 */
    314 		if (*status != YP_TRUE) {
    315 #ifdef DEBUG
    316 			syslog(LOG_DEBUG,
    317 			    "ypdb_open_db: cached db is now unavailable - "
    318 			    "closing: status %s",
    319 			    yperr_string(ypprot_err(*status)));
    320 #endif
    321 			ypdb_close_map(m);
    322 			return (NULL);
    323 		}
    324 
    325 		/*
    326 		 * is this the same db?
    327 		 */
    328 		if (finfo.st_dev == m->dbdev && finfo.st_ino == m->dbino &&
    329 		    finfo.st_mtime == m->dbmtime) {
    330 			TAILQ_REMOVE(&maps, m, mapsq); /* adjust LRU queue */
    331 			TAILQ_INSERT_HEAD(&maps, m, mapsq);
    332 			if (map_info)
    333 				*map_info = m;
    334 			return (m->db);
    335 		} else {
    336 #ifdef DEBUG
    337 			syslog(LOG_DEBUG,
    338 			    "ypdb_open_db: db changed; closing");
    339 #endif
    340 			ypdb_close_map(m);
    341 			m = NULL;
    342 		}
    343 	}
    344 
    345 	/*
    346 	 * not cached and non-existent, return
    347 	 */
    348 	if (*status != YP_TRUE)
    349 		return (NULL);
    350 
    351 	/*
    352 	 * open map
    353 	 */
    354 	(void)snprintf(map_path, sizeof(map_path), "%s/%s/%s",
    355 	    YP_DB_PATH, domain, map);
    356 #ifdef OPTIMIZE_DB
    357 retryopen:
    358 #endif /* OPTIMIZE_DB */
    359 	db = ypdb_open(map_path);
    360 #ifdef OPTIMIZE_DB
    361 	if (db == NULL) {
    362 #ifdef DEBUG
    363 		syslog(LOG_DEBUG,
    364 		    "ypdb_open_db: errno %d (%s)", errno, strerror(errno));
    365 #endif /* DEBUG */
    366 		if ((errno == ENFILE) || (errno == EMFILE)) {
    367 			ypdb_close_last();
    368 			goto retryopen;
    369 		}
    370 	}
    371 #endif /* OPTIMIZE_DB */
    372 
    373 	*status = YP_NOMAP;	/* see note below */
    374 
    375 	if (db == NULL) {
    376 #ifdef DEBUG
    377 		syslog(LOG_DEBUG,
    378 		    "ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)",
    379 		    map, domain);
    380 #endif
    381 		return (NULL);
    382 	}
    383 
    384 	/*
    385 	 * note: status now YP_NOMAP
    386 	 */
    387 	if (d == NULL) {	/* allocate new domain? */
    388 		d = (struct opt_domain *) malloc(sizeof(*d));
    389 		if (d)
    390 			d->domain = strdup(domain);
    391 		if (d == NULL || d->domain == NULL) {
    392 			syslog(LOG_ERR,
    393 			    "ypdb_open_db: MALLOC failed");
    394 			ypdb_close(db);
    395 			if (d)
    396 				free(d);
    397 			return (NULL);
    398 		}
    399 		LIST_INIT(&d->dmaps);
    400 		LIST_INSERT_HEAD(&doms, d, domsl);
    401 #ifdef DEBUG
    402 		syslog(LOG_DEBUG,
    403 		    "ypdb_open_db: NEW DOMAIN %s", domain);
    404 #endif
    405 	}
    406 
    407 	/*
    408 	 * m must be NULL since we couldn't find a map.  allocate new one
    409 	 */
    410 	m = (struct opt_map *) malloc(sizeof(*m));
    411 	if (m)
    412 		m->map = strdup(map);
    413 
    414 	if (m == NULL || m->map == NULL) {
    415 		if (m)
    416 			free(m);
    417 		syslog(LOG_ERR, "ypdb_open_db: MALLOC failed");
    418 		ypdb_close(db);
    419 		return (NULL);
    420 	}
    421 	m->db = db;
    422 	m->dom = d;
    423 	m->host_lookup = FALSE;
    424 	m->dbdev = finfo.st_dev;
    425 	m->dbino = finfo.st_ino;
    426 	m->dbmtime = finfo.st_mtime;
    427 	TAILQ_INSERT_HEAD(&maps, m, mapsq);
    428 	LIST_INSERT_HEAD(&d->dmaps, m, mapsl);
    429 	if (strcmp(map, YP_HOSTNAME) == 0 || strcmp(map, YP_HOSTADDR) == 0) {
    430 		if (!usedns) {
    431 			k.dptr = domain_key;
    432 			k.dsize = YP_INTERDOMAIN_LEN;
    433 			v = ypdb_fetch(db, k);
    434 			if (v.dptr)
    435 				m->host_lookup = TRUE;
    436 		} else
    437 			m->host_lookup = TRUE;
    438 	}
    439 
    440 	m->secure = FALSE;
    441 	k.dptr = secure_key;
    442 	k.dsize = YP_SECURE_LEN;
    443 	v = ypdb_fetch(db, k);
    444 	if (v.dptr != NULL)
    445 		m->secure = TRUE;
    446 
    447 	*status = YP_TRUE;
    448 
    449 	if (map_info)
    450 		*map_info = m;
    451 
    452 #ifdef DEBUG
    453 	syslog(LOG_DEBUG,
    454 	    "ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=%p",
    455 	    domain, map, m->host_lookup, m->secure, m->db);
    456 #endif
    457 
    458 	return (m->db);
    459 }
    460 
    461 /*
    462  * lookup host
    463  */
    464 u_int
    465 /*ARGSUSED*/
    466 lookup_host(int nametable, int host_lookup, DBM *db, char *keystr,
    467 	    struct ypresp_val *result)
    468 {
    469 	struct hostent *host;
    470 	struct in_addr *addr_name;
    471 	struct in_addr addr_addr;
    472 	static char val[BUFSIZ + 1];	/* match libc */
    473 	static char hostname[MAXHOSTNAMELEN];
    474 	char tmpbuf[MAXHOSTNAMELEN + 20];
    475 	char *v, *ptr;
    476 	int l;
    477 
    478 	if (!host_lookup)
    479 		return (YP_NOKEY);
    480 
    481 	if ((_res.options & RES_INIT) == 0)
    482 		(void)res_init();
    483 
    484 	if (nametable) {
    485 		host = gethostbyname(keystr);
    486 		if (host == NULL || host->h_addrtype != AF_INET)
    487 			return (YP_NOKEY);
    488 
    489 		addr_name = (struct in_addr *)(void *)host->h_addr_list[0];
    490 
    491 		v = val;
    492 
    493 		for (; host->h_addr_list[0] != NULL; host->h_addr_list++) {
    494 			addr_name = (struct in_addr *)(void *)host->h_addr_list[0];
    495 			(void)snprintf(tmpbuf, sizeof(tmpbuf), "%s %s\n",
    496 			    inet_ntoa(*addr_name), host->h_name);
    497 			if (v - val + strlen(tmpbuf) + 1 > sizeof(val))
    498 				break;
    499 			(void)strlcpy(v, tmpbuf, sizeof(val) - (v - val));
    500 			v = v + strlen(tmpbuf);
    501 		}
    502 		result->valdat.dptr = val;
    503 		result->valdat.dsize = v - val;
    504 		return (YP_TRUE);
    505 	}
    506 	if (inet_aton(keystr, &addr_addr) == -1)
    507 		return (YP_NOKEY);
    508 
    509 	host = gethostbyaddr((void *)&addr_addr, sizeof(addr_addr), AF_INET);
    510 	if (host == NULL)
    511 		return (YP_NOKEY);
    512 
    513 	(void)strlcpy(hostname, host->h_name, sizeof(hostname));
    514 	host = gethostbyname(hostname);
    515 	if (host == NULL)
    516 		return (YP_NOKEY);
    517 
    518 	l = 0;
    519 	for (; host->h_addr_list[0] != NULL; host->h_addr_list++)
    520 		if (!memcmp(host->h_addr_list[0], &addr_addr,
    521 		    sizeof(addr_addr)))
    522 			l++;
    523 
    524 	if (l == 0) {
    525 		syslog(LOG_NOTICE,
    526 		    "address %s not listed for host %s\n",
    527 		    inet_ntoa(addr_addr), hostname);
    528 		return (YP_NOKEY);
    529 	}
    530 
    531 	(void)snprintf(val, sizeof(val), "%s %s", keystr, host->h_name);
    532 	l = strlen(val);
    533 	v = val + l;
    534 	while ((ptr = *(host->h_aliases)) != NULL) {
    535 		l = strlen(ptr);
    536 		if ((v - val) + l + 1 > BUFSIZ)
    537 			break;
    538 		(void)strlcpy(v, " ", sizeof(val) - (v - val));
    539 		v += 1;
    540 		(void)strlcpy(v, ptr, sizeof(val) - (v - val));
    541 		v += l;
    542 		host->h_aliases++;
    543 	}
    544 	result->valdat.dptr = val;
    545 	result->valdat.dsize = v - val;
    546 
    547 	return (YP_TRUE);
    548 }
    549 
    550 struct ypresp_val
    551 ypdb_get_record(const char *domain, const char *map, datum key, int ypprivate)
    552 {
    553 	static struct ypresp_val res;
    554 	static char keystr[YPMAXRECORD + 1];
    555 	DBM *db;
    556 	datum k, v;
    557 	int host_lookup, hn;
    558 	struct opt_map *map_info = NULL;
    559 
    560 	host_lookup = 0;	/* XXX gcc -Wuninitialized */
    561 
    562 	(void)memset(&res, 0, sizeof(res));
    563 
    564 	db = ypdb_open_db(domain, map, &res.status, &map_info);
    565 	if (db == NULL || (int)res.status < 0)
    566 		return (res);
    567 
    568 	if (map_info)
    569 		host_lookup = map_info->host_lookup;
    570 
    571 	k.dptr = key.dptr;
    572 	k.dsize = key.dsize;
    573 
    574 	if (yp_private(k, ypprivate)) {
    575 		res.status = YP_NOKEY;
    576 		goto done;
    577 	}
    578 	v = ypdb_fetch(db, k);
    579 
    580 	if (v.dptr == NULL) {
    581 		res.status = YP_NOKEY;
    582 		if ((hn = strcmp(map, YP_HOSTNAME)) != 0 &&
    583 		    strcmp(map, YP_HOSTADDR) != 0)
    584 			return (res);
    585 
    586 		/* note: lookup_host needs null terminated string */
    587 		(void)strlcpy(keystr, key.dptr, (size_t)key.dsize + 1);
    588 		res.status = lookup_host((hn == 0) ? TRUE : FALSE,
    589 		    host_lookup, db, keystr, &res);
    590 	} else {
    591 		res.valdat.dptr = v.dptr;
    592 		res.valdat.dsize = v.dsize;
    593 	}
    594 
    595  done:
    596 	ypdb_close_db(db);
    597 	return (res);
    598 }
    599 
    600 struct ypresp_key_val
    601 ypdb_get_first(const char *domain, const char *map, int ypprivate)
    602 {
    603 	static struct ypresp_key_val res;
    604 	DBM *db;
    605 	datum k, v;
    606 
    607 	(void)memset(&res, 0, sizeof(res));
    608 
    609 	db = ypdb_open_db(domain, map, &res.status, NULL);
    610 
    611 	if (db != NULL && (int)res.status >= 0) {
    612 		k = ypdb_firstkey(db);
    613 
    614 		while (yp_private(k, ypprivate))
    615 			k = ypdb_nextkey(db);
    616 
    617 		if (k.dptr == NULL)
    618 			res.status = YP_NOKEY;
    619 		else {
    620 			res.keydat.dptr = k.dptr;
    621 			res.keydat.dsize = k.dsize;
    622 			v = ypdb_fetch(db, k);
    623 			if (v.dptr == NULL)
    624 				res.status = YP_NOKEY;
    625 			else {
    626 				res.valdat.dptr = v.dptr;
    627 				res.valdat.dsize = v.dsize;
    628 			}
    629 		}
    630 	}
    631 
    632 	if (db != NULL)
    633 		ypdb_close_db(db);
    634 
    635 	return (res);
    636 }
    637 
    638 struct ypresp_key_val
    639 ypdb_get_next(const char *domain, const char *map, datum key, int ypprivate)
    640 {
    641 	static struct ypresp_key_val res;
    642 	DBM *db;
    643 	datum k, v, n;
    644 
    645 	(void)memset(&res, 0, sizeof(res));
    646 
    647 	db = ypdb_open_db(domain, map, &res.status, NULL);
    648 
    649 	if (db != NULL && (int)res.status >= 0) {
    650 		n.dptr = key.dptr;
    651 		n.dsize = key.dsize;
    652 		v.dptr = NULL;
    653 		v.dsize = 0;
    654 		k.dptr = NULL;
    655 		k.dsize = 0;
    656 
    657 		n = ypdb_setkey(db, n);
    658 
    659 		if (n.dptr != NULL)
    660 			k = ypdb_nextkey(db);
    661 		else
    662 			k.dptr = NULL;
    663 
    664 		if (k.dptr != NULL)
    665 			while (yp_private(k, ypprivate))
    666 				k = ypdb_nextkey(db);
    667 
    668 		if (k.dptr == NULL)
    669 			res.status = YP_NOMORE;
    670 		else {
    671 			res.keydat.dptr = k.dptr;
    672 			res.keydat.dsize = k.dsize;
    673 			v = ypdb_fetch(db, k);
    674 			if (v.dptr == NULL)
    675 				res.status = YP_NOMORE;
    676 			else {
    677 				res.valdat.dptr = v.dptr;
    678 				res.valdat.dsize = v.dsize;
    679 			}
    680 		}
    681 	}
    682 
    683 	if (db != NULL)
    684 		ypdb_close_db(db);
    685 
    686 	return (res);
    687 }
    688 
    689 struct ypresp_order
    690 ypdb_get_order(const char *domain, const char *map)
    691 {
    692 	static struct ypresp_order res;
    693 	static const char *order_key = YP_LAST_KEY;
    694 	char order[MAX_LAST_LEN + 1];
    695 	DBM *db;
    696 	datum k, v;
    697 
    698 	(void)memset(&res, 0, sizeof(res));
    699 
    700 	db = ypdb_open_db(domain, map, &res.status, NULL);
    701 
    702 	if (db != NULL && (int)res.status >= 0) {
    703 		k.dptr = order_key;
    704 		k.dsize = YP_LAST_LEN;
    705 
    706 		v = ypdb_fetch(db, k);
    707 		if (v.dptr == NULL)
    708 			res.status = YP_NOKEY;
    709 		else {
    710 			(void)strlcpy(order, v.dptr, (size_t)v.dsize + 1);
    711 			res.ordernum = (u_int) atol(order);
    712 		}
    713 	}
    714 
    715 	if (db != NULL)
    716 		ypdb_close_db(db);
    717 
    718 	return (res);
    719 }
    720 
    721 struct ypresp_master
    722 ypdb_get_master(const char *domain, const char *map)
    723 {
    724 	static struct ypresp_master res;
    725 	static const char *master_key = YP_MASTER_KEY;
    726 	static char master[MAX_MASTER_LEN + 1];
    727 	DBM *db;
    728 	datum k, v;
    729 
    730 	(void)memset(&res, 0, sizeof(res));
    731 
    732 	db = ypdb_open_db(domain, map, &res.status, NULL);
    733 
    734 	if (db != NULL && (int)res.status >= 0) {
    735 		k.dptr = master_key;
    736 		k.dsize = YP_MASTER_LEN;
    737 
    738 		v = ypdb_fetch(db, k);
    739 		if (v.dptr == NULL)
    740 			res.status = YP_NOKEY;
    741 		else {
    742 			(void)strlcpy(master, v.dptr, (size_t)v.dsize + 1);
    743 			res.master = &master[0];
    744 		}
    745 	}
    746 
    747 	if (db != NULL)
    748 		ypdb_close_db(db);
    749 
    750 	return (res);
    751 }
    752 
    753 bool_t
    754 ypdb_xdr_get_all(XDR *xdrs, struct ypreq_nokey *req)
    755 {
    756 	static struct ypresp_all resp;
    757 	DBM *db;
    758 	datum k, v;
    759 
    760 	(void)memset(&resp, 0, sizeof(resp));
    761 
    762 	/*
    763 	 * open db, and advance past any private keys we may see
    764 	 */
    765 	db = ypdb_open_db(req->domain, req->map,
    766 	    &resp.ypresp_all_u.val.status, NULL);
    767 
    768 	if (db == NULL || (int)resp.ypresp_all_u.val.status < 0)
    769 		return (FALSE);
    770 
    771 	k = ypdb_firstkey(db);
    772 	while (yp_private(k, FALSE))
    773 		k = ypdb_nextkey(db);
    774 
    775 	for (;;) {
    776 		if (k.dptr == NULL)
    777 			break;
    778 
    779 		v = ypdb_fetch(db, k);
    780 
    781 		if (v.dptr == NULL)
    782 			break;
    783 
    784 		resp.more = TRUE;
    785 		resp.ypresp_all_u.val.status = YP_TRUE;
    786 		resp.ypresp_all_u.val.keydat.dptr = k.dptr;
    787 		resp.ypresp_all_u.val.keydat.dsize = k.dsize;
    788 		resp.ypresp_all_u.val.valdat.dptr = v.dptr;
    789 		resp.ypresp_all_u.val.valdat.dsize = v.dsize;
    790 
    791 		if (!xdr_ypresp_all(xdrs, &resp)) {
    792 #ifdef DEBUG
    793 			syslog(LOG_DEBUG,
    794 			    "ypdb_xdr_get_all: xdr_ypresp_all failed");
    795 #endif
    796 			return (FALSE);
    797 		}
    798 
    799 		/* advance past private keys */
    800 		k = ypdb_nextkey(db);
    801 		while (yp_private(k, FALSE))
    802 			k = ypdb_nextkey(db);
    803 	}
    804 
    805 	(void)memset(&resp, 0, sizeof(resp));
    806 	resp.ypresp_all_u.val.status = YP_NOKEY;
    807 	resp.more = FALSE;
    808 
    809 	if (!xdr_ypresp_all(xdrs, &resp)) {
    810 #ifdef DEBUG
    811 		syslog(LOG_DEBUG,
    812 		    "ypdb_xdr_get_all: final xdr_ypresp_all failed");
    813 #endif
    814 		return (FALSE);
    815 	}
    816 
    817 	if (db != NULL)
    818 		ypdb_close_db(db);
    819 
    820 	return (TRUE);
    821 }
    822 
    823 int
    824 ypdb_secure(const char *domain, const char *map)
    825 {
    826 	DBM *db;
    827 	int secure;
    828 	u_int status;
    829 	struct opt_map *map_info = NULL;
    830 
    831 	secure = FALSE;
    832 
    833 	db = ypdb_open_db(domain, map, &status, &map_info);
    834 	if (db == NULL || (int)status < 0)
    835 		return (secure);
    836 	if (map_info != NULL)
    837 		secure = map_info->secure;
    838 
    839 	ypdb_close_db(db);
    840 	return (secure);
    841 }
    842