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