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