yp_server.c revision 20100
1/*
2 * Copyright (c) 1995
3 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34#include "yp_extern.h"
35#include "yp.h"
36#include <stdlib.h>
37#include <dirent.h>
38#include <sys/stat.h>
39#include <sys/param.h>
40#include <errno.h>
41#include <sys/types.h>
42#include <sys/socket.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#include <rpc/rpc.h>
46
47#ifndef lint
48static const char rcsid[] = "$Id: yp_server.c,v 1.12 1996/10/24 18:58:26 wpaul Exp $";
49#endif /* not lint */
50
51int forked = 0;
52int children = 0;
53static DB *spec_dbp = NULL;	/* Special global DB handle for ypproc_all. */
54static char *master_string = "YP_MASTER_NAME";
55static char *order_string = "YP_LAST_MODIFIED";
56static int master_sz = sizeof("YP_MASTER_NAME") - 1;
57static int order_sz = sizeof("YP_LAST_MODIFIED") - 1;
58
59/*
60 * NIS v2 support. This is where most of the action happens.
61 */
62
63void *
64ypproc_null_2_svc(void *argp, struct svc_req *rqstp)
65{
66	static char * result;
67	static char rval = 0;
68
69#ifdef DB_CACHE
70	if (yp_access(NULL, NULL, (struct svc_req *)rqstp))
71#else
72	if (yp_access(NULL, (struct svc_req *)rqstp))
73#endif
74		return(NULL);
75
76	result = &rval;
77
78	return((void *) &result);
79}
80
81bool_t *
82ypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp)
83{
84	static bool_t  result;
85
86#ifdef DB_CACHE
87	if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) {
88#else
89	if (yp_access(NULL, (struct svc_req *)rqstp)) {
90#endif
91		result = FALSE;
92		return (&result);
93	}
94
95	if (argp == NULL || yp_validdomain(*argp))
96		result = FALSE;
97	else
98		result = TRUE;
99
100	return (&result);
101}
102
103bool_t *
104ypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp)
105{
106	static bool_t  result;
107
108#ifdef DB_CACHE
109	if (yp_access(NULL, NULL, (struct svc_req *)rqstp))
110#else
111	if (yp_access(NULL, (struct svc_req *)rqstp))
112#endif
113		return (NULL);
114
115	if (argp == NULL || yp_validdomain(*argp))
116		return (NULL);
117	else
118		result = TRUE;
119
120	return (&result);
121}
122
123ypresp_val *
124ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
125{
126	static ypresp_val  result;
127	DBT key, data;
128
129	result.val.valdat_val = "";
130	result.val.valdat_len = 0;
131
132#ifdef DB_CACHE
133	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
134#else
135	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
136#endif
137		result.stat = YP_YPERR;
138		return (&result);
139	}
140
141	if (argp->domain == NULL || argp->map == NULL) {
142		result.stat = YP_BADARGS;
143		return (&result);
144	}
145
146	key.size = argp->key.keydat_len;
147	key.data = argp->key.keydat_val;
148
149	if ((result.stat = yp_get_record(argp->domain, argp->map,
150						&key, &data, 1)) == YP_TRUE) {
151		result.val.valdat_len = data.size;
152		result.val.valdat_val = data.data;
153	}
154
155	/*
156	 * Do DNS lookups for hosts maps if database lookup failed.
157	 */
158
159#ifdef DB_CACHE
160	if (result.stat != YP_TRUE &&
161	    (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) ||
162	    (strstr(argp->map, "hosts") && do_dns))) {
163#else
164	if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) {
165#endif
166		char *rval = NULL;
167
168	/* DNS lookups can take time -- do them in a subprocess */
169
170		if (!debug && children < MAX_CHILDREN && fork()) {
171			children++;
172			forked = 0;
173			/*
174			 * Returning NULL here prevents svc_sendreply()
175			 * from being called by the parent. This is vital
176			 * since having both the parent and the child process
177			 * call it would confuse the client.
178			 */
179			return (NULL);
180		} else {
181			forked++;
182		}
183
184		if (debug)
185			yp_error("Doing DNS lookup of %.*s",
186			 	  argp->key.keydat_len,
187				  argp->key.keydat_val);
188
189		/* NUL terminate! NUL terminate!! NUL TERMINATE!!! */
190		argp->key.keydat_val[argp->key.keydat_len] = '\0';
191
192		if (!strcmp(argp->map, "hosts.byname"))
193			rval = yp_dnsname((char *)argp->key.keydat_val);
194		else if (!strcmp(argp->map, "hosts.byaddr"))
195			rval = yp_dnsaddr((const char *)argp->key.keydat_val);
196
197
198		if (rval) {
199			if (debug)
200				yp_error("DNS lookup successful. Result: %s",
201									rval);
202			result.val.valdat_len = strlen(rval);
203			result.val.valdat_val = rval;
204			result.stat = YP_TRUE;
205		} else {
206			if (debug)
207				yp_error("DNS lookup failed.");
208			result.stat = YP_NOKEY;
209		}
210	}
211
212	return (&result);
213}
214
215ypresp_key_val *
216ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
217{
218	static ypresp_key_val  result;
219	DBT key, data;
220	DB *dbp;
221
222	result.val.valdat_val = result.key.keydat_val = "";
223	result.val.valdat_len = result.key.keydat_len = 0;
224
225#ifdef DB_CACHE
226	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
227#else
228	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
229#endif
230		result.stat = YP_YPERR;
231		return (&result);
232	}
233
234	if (argp->domain == NULL) {
235		result.stat = YP_BADARGS;
236		return (&result);
237	}
238
239#ifdef DB_CACHE
240	if ((dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) {
241#else
242	if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
243#endif
244		result.stat = yp_errno;
245		return(&result);
246	}
247
248	key.data = NULL;
249	key.size = 0;
250
251	if ((result.stat = yp_first_record(dbp, &key, &data, 0)) == YP_TRUE) {
252		result.key.keydat_len = key.size;
253		result.key.keydat_val = key.data;
254		result.val.valdat_len = data.size;
255		result.val.valdat_val = data.data;
256	}
257#ifndef DB_CACHE
258	(void)(dbp->close)(dbp);
259#endif
260	return (&result);
261}
262
263ypresp_key_val *
264ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp)
265{
266	static ypresp_key_val  result;
267	DBT key, data;
268	DB *dbp;
269
270	result.val.valdat_val = result.key.keydat_val = "";
271	result.val.valdat_len = result.key.keydat_len = 0;
272
273#ifdef DB_CACHE
274	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
275#else
276	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
277#endif
278		result.stat = YP_YPERR;
279		return (&result);
280	}
281
282	if (argp->domain == NULL || argp->map == NULL) {
283		result.stat = YP_BADARGS;
284		return (&result);
285	}
286
287#ifdef DB_CACHE
288	if ((dbp = yp_open_db_cache(argp->domain, argp->map,
289					argp->key.keydat_val,
290					argp->key.keydat_len)) == NULL) {
291#else
292	if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
293#endif
294		result.stat = yp_errno;
295		return(&result);
296	}
297
298	key.size = argp->key.keydat_len;
299	key.data = argp->key.keydat_val;
300
301	if ((result.stat = yp_next_record(dbp, &key, &data,0,0)) == YP_TRUE) {
302		result.key.keydat_len = key.size;
303		result.key.keydat_val = key.data;
304		result.val.valdat_len = data.size;
305		result.val.valdat_val = data.data;
306	}
307#ifndef DB_CACHE
308	(void)(dbp->close)(dbp);
309#endif
310	return (&result);
311}
312
313static void ypxfr_callback(rval,addr,transid,prognum,port)
314	ypxfrstat rval;
315	struct sockaddr_in *addr;
316	unsigned int transid;
317	unsigned int prognum;
318	unsigned long port;
319{
320	CLIENT *clnt;
321	int sock = RPC_ANYSOCK;
322	struct timeval timeout;
323	yppushresp_xfr ypxfr_resp;
324	struct rpc_err err;
325
326	timeout.tv_sec = 5;
327	timeout.tv_usec = 0;
328	addr->sin_port = htons(port);
329
330	if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) {
331		yp_error("%s: %s", inet_ntoa(addr->sin_addr),
332		  clnt_spcreateerror("failed to establish callback handle"));
333		return;
334	}
335
336	ypxfr_resp.status = rval;
337	ypxfr_resp.transid = transid;
338
339	/* Turn the timeout off -- we don't want to block. */
340	timeout.tv_sec = 0;
341	if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE)
342		yp_error("failed to set timeout on ypproc_xfr callback");
343
344	if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) {
345		clnt_geterr(clnt, &err);
346		if (err.re_status != RPC_SUCCESS &&
347		    err.re_status != RPC_TIMEDOUT)
348			yp_error("%s", clnt_sperror(clnt,
349				"ypxfr callback failed"));
350	}
351
352	clnt_destroy(clnt);
353	return;
354}
355
356#define YPXFR_RETURN(CODE) 						\
357	/* Order is important: send regular RPC reply, then callback */	\
358	result.xfrstat = CODE; 						\
359	svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \
360	ypxfr_callback(CODE,rqhost,argp->transid, 			\
361					argp->prog,argp->port); 	\
362	return(NULL);
363
364ypresp_xfr *
365ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp)
366{
367	static ypresp_xfr  result;
368	struct sockaddr_in *rqhost;
369
370	result.transid = argp->transid;
371	rqhost = svc_getcaller(rqstp->rq_xprt);
372
373#ifdef DB_CACHE
374	if (yp_access(argp->map_parms.map,
375			argp->map_parms.domain, (struct svc_req *)rqstp)) {
376#else
377	if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) {
378#endif
379		YPXFR_RETURN(YPXFR_REFUSED);
380	}
381
382	if (argp->map_parms.domain == NULL) {
383		YPXFR_RETURN(YPXFR_BADARGS);
384	}
385
386	if (yp_validdomain(argp->map_parms.domain)) {
387		YPXFR_RETURN(YPXFR_NODOM);
388	}
389
390	switch(fork()) {
391	case 0:
392	{
393		char g[11], t[11], p[11];
394		char ypxfr_command[MAXPATHLEN + 2];
395
396		sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC);
397		sprintf (t, "%u", argp->transid);
398		sprintf (g, "%u", argp->prog);
399		sprintf (p, "%u", argp->port);
400		if (debug)
401			close(0); close(1); close(2);
402		if (strcmp(yp_dir, _PATH_YP)) {
403			execl(ypxfr_command, "ypxfr",
404			"-d", argp->map_parms.domain,
405		      	"-h", argp->map_parms.peer,
406			"-p", yp_dir, "-C", t,
407		      	g, inet_ntoa(rqhost->sin_addr),
408			p, argp->map_parms.map,
409		      	NULL);
410		} else {
411			execl(ypxfr_command, "ypxfr",
412			"-d", argp->map_parms.domain,
413		      	"-h", argp->map_parms.peer,
414			"-C", t,
415		      	g, inet_ntoa(rqhost->sin_addr),
416			p, argp->map_parms.map,
417		      	NULL);
418		}
419		forked++;
420		yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno));
421		YPXFR_RETURN(YPXFR_XFRERR);
422		break;
423	}
424	case -1:
425		yp_error("ypxfr fork(): %s", strerror(errno));
426		YPXFR_RETURN(YPXFR_XFRERR);
427		break;
428	default:
429		result.xfrstat = YPXFR_SUCC;
430		children++;
431		forked = 0;
432		break;
433	}
434
435	return (&result);
436}
437#undef YPXFR_RETURN
438
439void *
440ypproc_clear_2_svc(void *argp, struct svc_req *rqstp)
441{
442	static char * result;
443	static char rval = 0;
444
445#ifdef DB_CACHE
446	if (yp_access(NULL, NULL, (struct svc_req *)rqstp))
447#else
448	if (yp_access(NULL, (struct svc_req *)rqstp))
449#endif
450		return (NULL);
451#ifdef DB_CACHE
452	/* clear out the database cache */
453	yp_flush_all();
454#endif
455	/* Re-read the securenets database for the hell of it. */
456	load_securenets();
457
458	result = &rval;
459	return((void *) &result);
460}
461
462/*
463 * For ypproc_all, we have to send a stream of ypresp_all structures
464 * via TCP, but the XDR filter generated from the yp.x protocol
465 * definition file only serializes one such structure. This means that
466 * to send the whole stream, you need a wrapper which feeds all the
467 * records into the underlying XDR routine until it hits an 'EOF.'
468 * But to use the wrapper, you have to violate the boundaries between
469 * RPC layers by calling svc_sendreply() directly from the ypproc_all
470 * service routine instead of letting the RPC dispatcher do it.
471 *
472 * Bleah.
473 */
474
475/*
476 * Custom XDR routine for serialzing results of ypproc_all: keep
477 * reading from the database and spew until we run out of records
478 * or encounter an error.
479 */
480static bool_t
481xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp)
482{
483	DBT key = { NULL, 0 } , data = { NULL, 0 };
484
485	while (1) {
486		/* Get a record. */
487		if ((objp->ypresp_all_u.val.stat =
488	    		yp_next_record(spec_dbp,&key,&data,1,0)) == YP_TRUE) {
489			objp->ypresp_all_u.val.val.valdat_len = data.size;
490			objp->ypresp_all_u.val.val.valdat_val = data.data;
491			objp->ypresp_all_u.val.key.keydat_len = key.size;
492			objp->ypresp_all_u.val.key.keydat_val = key.data;
493			objp->more = TRUE;
494		} else {
495			objp->more = FALSE;
496		}
497
498		/* Serialize. */
499		if (!xdr_ypresp_all(xdrs, objp))
500			return(FALSE);
501		if (objp->more == FALSE)
502			return(TRUE);
503	}
504}
505
506ypresp_all *
507ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
508{
509	static ypresp_all  result;
510
511	/*
512	 * Set this here so that the client will be forced to make
513	 * at least one attempt to read from us even if all we're
514	 * doing is returning an error.
515	 */
516	result.more = TRUE;
517	result.ypresp_all_u.val.key.keydat_len = 0;
518	result.ypresp_all_u.val.key.keydat_val = "";
519
520#ifdef DB_CACHE
521	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
522#else
523	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
524#endif
525		result.ypresp_all_u.val.stat = YP_YPERR;
526		return (&result);
527	}
528
529	if (argp->domain == NULL || argp->map == NULL) {
530		result.ypresp_all_u.val.stat = YP_BADARGS;
531		return (&result);
532	}
533
534	/*
535	 * The ypproc_all procedure can take a while to complete.
536	 * Best to handle it in a subprocess so the parent doesn't
537	 * block. (Is there a better way to do this? Maybe with
538	 * async socket I/O?)
539	 */
540	if (!debug && children < MAX_CHILDREN && fork()) {
541		children++;
542		forked = 0;
543		return (NULL);
544	} else {
545		forked++;
546	}
547
548#ifndef DB_CACHE
549	if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
550		result.ypresp_all_u.val.stat = yp_errno;
551		return(&result);
552	}
553#else
554	if ((spec_dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) {
555		result.ypresp_all_u.val.stat = yp_errno;
556		return(&result);
557	}
558#endif
559
560	/* Kick off the actual data transfer. */
561	svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result);
562
563#ifndef DB_CACHE
564	(void)(spec_dbp->close)(spec_dbp);
565#endif
566	/*
567	 * Returning NULL prevents the dispatcher from calling
568	 * svc_sendreply() since we already did it.
569	 */
570	return (NULL);
571}
572
573ypresp_master *
574ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
575{
576	static ypresp_master  result;
577	static char ypvalbuf[YPMAXRECORD];
578	DBT key = { master_string, master_sz }, data;
579
580	result.peer = "";
581
582#ifdef DB_CACHE
583	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
584#else
585	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
586#endif
587		result.stat = YP_YPERR;
588		return(&result);
589	}
590
591	if (argp->domain == NULL) {
592		result.stat = YP_BADARGS;
593		return (&result);
594	}
595
596	/*
597	 * Note that we copy the data retrieved from the database to
598	 * a private buffer and NUL terminate the buffer rather than
599	 * terminating the data in place. We do this because by stuffing
600	 * a '\0' into data.data, we will actually be corrupting memory
601	 * allocated by the DB package. This is a bad thing now that we
602	 * cache DB handles rather than closing the database immediately.
603	 */
604	if ((result.stat = yp_get_record(argp->domain, argp->map,
605						&key, &data, 1)) == YP_TRUE) {
606		bcopy((char *)data.data, (char *)&ypvalbuf, data.size);
607		ypvalbuf[data.size] = '\0';
608		result.peer = (char *)&ypvalbuf;
609	} else
610		result.peer = "";
611
612	return (&result);
613}
614
615ypresp_order *
616ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
617{
618	static ypresp_order  result;
619	DBT key = { order_string, order_sz }, data;
620
621	result.ordernum = 0;
622
623#ifdef DB_CACHE
624	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
625#else
626	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
627#endif
628		result.stat = YP_YPERR;
629		return(&result);
630	}
631
632	if (argp->domain == NULL) {
633		result.stat = YP_BADARGS;
634		return (&result);
635	}
636
637	/*
638	 * We could just check the timestamp on the map file,
639	 * but that's a hack: we'll only know the last time the file
640	 * was touched, not the last time the database contents were
641	 * updated.
642	 */
643
644	if ((result.stat = yp_get_record(argp->domain, argp->map,
645						&key, &data, 1)) == YP_TRUE)
646		result.ordernum = atoi((char *)data.data);
647	else
648		result.ordernum = 0;
649
650
651	return (&result);
652}
653
654static void yp_maplist_free(yp_maplist)
655	struct ypmaplist *yp_maplist;
656{
657	register struct ypmaplist *next;
658
659	while(yp_maplist) {
660		next = yp_maplist->next;
661		free(yp_maplist->map);
662		free(yp_maplist);
663		yp_maplist = next;
664	}
665	return;
666}
667
668static struct ypmaplist *yp_maplist_create(domain)
669	const char *domain;
670{
671	char yp_mapdir[MAXPATHLEN + 2];
672	char yp_mapname[MAXPATHLEN + 2];
673	struct ypmaplist *cur = NULL;
674	struct ypmaplist *yp_maplist = NULL;
675	DIR *dird;
676	struct dirent *dirp;
677	struct stat statbuf;
678
679	snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain);
680
681	if ((dird = opendir(yp_mapdir)) == NULL) {
682		yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno));
683		return(NULL);
684	}
685
686	while ((dirp = readdir(dird)) != NULL) {
687		if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) {
688			snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s",
689							yp_mapdir,dirp->d_name);
690			if (stat(yp_mapname, &statbuf) < 0 ||
691						!S_ISREG(statbuf.st_mode))
692				continue;
693			if ((cur = (struct ypmaplist *)
694				malloc(sizeof(struct ypmaplist))) == NULL) {
695				yp_error("malloc() failed: %s",strerror(errno));
696				closedir(dird);
697				yp_maplist_free(yp_maplist);
698				return(NULL);
699			}
700			if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) {
701				yp_error("strdup() failed: %s",strerror(errno));
702				closedir(dird);
703				yp_maplist_free(yp_maplist);
704				return(NULL);
705			}
706			cur->next = yp_maplist;
707			yp_maplist = cur;
708			if (debug)
709				yp_error("map: %s", yp_maplist->map);
710		}
711
712	}
713	closedir(dird);
714	return(yp_maplist);
715}
716
717ypresp_maplist *
718ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp)
719{
720	static ypresp_maplist  result = { 0, NULL };
721
722#ifdef DB_CACHE
723	if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) {
724#else
725	if (yp_access(NULL, (struct svc_req *)rqstp)) {
726#endif
727		result.stat = YP_YPERR;
728		return(&result);
729	}
730
731	if (argp == NULL) {
732		result.stat = YP_BADARGS;
733		return (&result);
734	}
735
736	if (yp_validdomain(*argp)) {
737		result.stat = YP_NODOM;
738		return (&result);
739	}
740
741	/*
742	 * We have to construct a linked list for the ypproc_maplist
743	 * procedure using dynamically allocated memory. Since the XDR
744	 * layer won't free this list for us, we have to deal with it
745	 * ourselves. We call yp_maplist_free() first to free any
746	 * previously allocated data we may have accumulated to insure
747	 * that we have only one linked list in memory at any given
748	 * time.
749	 */
750
751	yp_maplist_free(result.maps);
752
753	if ((result.maps = yp_maplist_create(*argp)) == NULL) {
754		yp_error("yp_maplist_create failed");
755		result.stat = YP_YPERR;
756		return(&result);
757	} else
758		result.stat = YP_TRUE;
759
760	return (&result);
761}
762
763/*
764 * NIS v1 support. The nullproc, domain and domain_nonack
765 * functions from v1 are identical to those in v2, so all
766 * we have to do is hand off to them.
767 *
768 * The other functions are mostly just wrappers around their v2
769 * counterparts. For example, for the v1 'match' procedure, we
770 * crack open the argument structure, make a request to the v2
771 * 'match' function, repackage the data into a v1 response and
772 * then send it on its way.
773 *
774 * Note that we don't support the pull, push and get procedures.
775 * There's little documentation available to show what they
776 * do, and I suspect they're meant largely for map transfers
777 * between master and slave servers.
778 */
779
780void *
781ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp)
782{
783	return(ypproc_null_2_svc(argp, rqstp));
784}
785
786bool_t *
787ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp)
788{
789	return(ypproc_domain_2_svc(argp, rqstp));
790}
791
792bool_t *
793ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp)
794{
795	return (ypproc_domain_nonack_2_svc(argp, rqstp));
796}
797
798/*
799 * the 'match' procedure sends a response of type YPRESP_VAL
800 */
801ypresponse *
802ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp)
803{
804	static ypresponse  result;
805	ypresp_val *v2_result;
806
807	result.yp_resptype = YPRESP_VAL;
808	result.ypresponse_u.yp_resp_valtype.val.valdat_val = "";
809	result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0;
810
811	if (argp->yp_reqtype != YPREQ_KEY) {
812		result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS;
813		return(&result);
814	}
815
816	v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp);
817	if (v2_result == NULL)
818		return(NULL);
819
820	bcopy((char *)v2_result,
821	      (char *)&result.ypresponse_u.yp_resp_valtype,
822	      sizeof(ypresp_val));
823
824	return (&result);
825}
826
827/*
828 * the 'first' procedure sends a response of type YPRESP_KEY_VAL
829 */
830ypresponse *
831ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp)
832{
833	static ypresponse  result;
834	ypresp_key_val *v2_result;
835
836	result.yp_resptype = YPRESP_KEY_VAL;
837	result.ypresponse_u.yp_resp_key_valtype.val.valdat_val =
838	result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = "";
839	result.ypresponse_u.yp_resp_key_valtype.val.valdat_len =
840	result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0;
841
842	if (argp->yp_reqtype != YPREQ_NOKEY) {
843		result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS;
844		return(&result);
845	}
846
847	v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype,
848									rqstp);
849	if (v2_result == NULL)
850		return(NULL);
851
852	bcopy((char *)v2_result,
853	      (char *)&result.ypresponse_u.yp_resp_key_valtype,
854	      sizeof(ypresp_key_val));
855
856	return (&result);
857}
858
859/*
860 * the 'next' procedure sends a response of type YPRESP_KEY_VAL
861 */
862ypresponse *
863ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp)
864{
865	static ypresponse  result;
866	ypresp_key_val *v2_result;
867
868	result.yp_resptype = YPRESP_KEY_VAL;
869	result.ypresponse_u.yp_resp_key_valtype.val.valdat_val =
870	result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = "";
871	result.ypresponse_u.yp_resp_key_valtype.val.valdat_len =
872	result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0;
873
874	if (argp->yp_reqtype != YPREQ_KEY) {
875		result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS;
876		return(&result);
877	}
878
879	v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp);
880	if (v2_result == NULL)
881		return(NULL);
882
883	bcopy((char *)v2_result,
884	      (char *)&result.ypresponse_u.yp_resp_key_valtype,
885	      sizeof(ypresp_key_val));
886
887	return (&result);
888}
889
890/*
891 * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS
892 */
893ypresponse *
894ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp)
895{
896	static ypresponse  result;
897	ypresp_master *v2_result1;
898	ypresp_order *v2_result2;
899
900	result.yp_resptype = YPRESP_MAP_PARMS;
901	result.ypresponse_u.yp_resp_map_parmstype.domain =
902		argp->yprequest_u.yp_req_nokeytype.domain;
903	result.ypresponse_u.yp_resp_map_parmstype.map =
904		argp->yprequest_u.yp_req_nokeytype.map;
905	/*
906	 * Hmm... there is no 'status' value in the
907	 * yp_resp_map_parmstype structure, so I have to
908	 * guess at what to do to indicate a failure.
909	 * I hope this is right.
910	 */
911	result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0;
912	result.ypresponse_u.yp_resp_map_parmstype.peer = "";
913
914	if (argp->yp_reqtype != YPREQ_MAP_PARMS) {
915		return(&result);
916	}
917
918	v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype,
919									rqstp);
920	if (v2_result1 == NULL)
921		return(NULL);
922
923	if (v2_result1->stat != YP_TRUE) {
924		return(&result);
925	}
926
927	v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype,
928									rqstp);
929	if (v2_result2 == NULL)
930		return(NULL);
931
932	if (v2_result2->stat != YP_TRUE) {
933		return(&result);
934	}
935
936	result.ypresponse_u.yp_resp_map_parmstype.peer =
937		v2_result1->peer;
938	result.ypresponse_u.yp_resp_map_parmstype.ordernum =
939		v2_result2->ordernum;
940
941	return (&result);
942}
943
944ypresponse *
945ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp)
946{
947	static ypresponse  result;
948
949	/*
950	 * Not implemented.
951	 */
952
953	return (&result);
954}
955
956ypresponse *
957ypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp)
958{
959	static ypresponse  result;
960
961	/*
962	 * Not implemented.
963	 */
964
965	return (&result);
966}
967
968ypresponse *
969ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp)
970{
971	static ypresponse  result;
972
973	/*
974	 * Not implemented.
975	 */
976
977	return (&result);
978}
979