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