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