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