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