yp_server.c revision 43847
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: yp_server.c,v 1.26 1998/02/11 19:15:32 wpaul Exp $";
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, NULL, 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, NULL, 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) {
510		switch(fork()) {
511		case 0:
512			forked++;
513			break;
514		case -1:
515			yp_error("ypall fork(): %s", strerror(errno));
516			result.ypresp_all_u.val.stat = YP_YPERR;
517			return(&result);
518			break;
519		default:
520			children++;
521			forked = 0;
522			return (NULL);
523			break;
524		}
525	}
526
527	if (yp_select_map(argp->map, argp->domain,
528				&result.ypresp_all_u.val.key, 0) != YP_TRUE) {
529		result.ypresp_all_u.val.stat = yp_errno;
530		return(&result);
531	}
532
533	/* Kick off the actual data transfer. */
534	svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result);
535
536	/*
537	 * Returning NULL prevents the dispatcher from calling
538	 * svc_sendreply() since we already did it.
539	 */
540	return (NULL);
541}
542
543ypresp_master *
544ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
545{
546	static ypresp_master  result;
547	static char ypvalbuf[YPMAXRECORD];
548	keydat key = { MASTER_SZ, MASTER_STRING };
549	valdat val;
550
551	result.peer = "";
552
553#ifdef DB_CACHE
554	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
555#else
556	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
557#endif
558		result.stat = YP_YPERR;
559		return(&result);
560	}
561
562	if (argp->domain == NULL) {
563		result.stat = YP_BADARGS;
564		return (&result);
565	}
566
567	if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) {
568		result.stat = yp_errno;
569		return(&result);
570	}
571
572	/*
573	 * Note that we copy the data retrieved from the database to
574	 * a private buffer and NUL terminate the buffer rather than
575	 * terminating the data in place. We do this because by stuffing
576	 * a '\0' into data.data, we will actually be corrupting memory
577	 * allocated by the DB package. This is a bad thing now that we
578	 * cache DB handles rather than closing the database immediately.
579	 */
580	result.stat = yp_getbykey(&key, &val);
581	if (result.stat == YP_TRUE) {
582		bcopy((char *)val.valdat_val, (char *)&ypvalbuf,
583						val.valdat_len);
584		ypvalbuf[val.valdat_len] = '\0';
585		result.peer = (char *)&ypvalbuf;
586	} else
587		result.peer = "";
588
589	return (&result);
590}
591
592ypresp_order *
593ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
594{
595	static ypresp_order  result;
596	keydat key = { ORDER_SZ, ORDER_STRING };
597	valdat val;
598
599	result.ordernum = 0;
600
601#ifdef DB_CACHE
602	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
603#else
604	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
605#endif
606		result.stat = YP_YPERR;
607		return(&result);
608	}
609
610	if (argp->domain == NULL) {
611		result.stat = YP_BADARGS;
612		return (&result);
613	}
614
615	/*
616	 * We could just check the timestamp on the map file,
617	 * but that's a hack: we'll only know the last time the file
618	 * was touched, not the last time the database contents were
619	 * updated.
620	 */
621
622	if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) {
623		result.stat = yp_errno;
624		return(&result);
625	}
626
627	result.stat = yp_getbykey(&key, &val);
628
629	if (result.stat == YP_TRUE)
630		result.ordernum = atoi((char *)val.valdat_val);
631	else
632		result.ordernum = 0;
633
634	return (&result);
635}
636
637static void yp_maplist_free(yp_maplist)
638	struct ypmaplist *yp_maplist;
639{
640	register struct ypmaplist *next;
641
642	while(yp_maplist) {
643		next = yp_maplist->next;
644		free(yp_maplist->map);
645		free(yp_maplist);
646		yp_maplist = next;
647	}
648	return;
649}
650
651static struct ypmaplist *yp_maplist_create(domain)
652	const char *domain;
653{
654	char yp_mapdir[MAXPATHLEN + 2];
655	char yp_mapname[MAXPATHLEN + 2];
656	struct ypmaplist *cur = NULL;
657	struct ypmaplist *yp_maplist = NULL;
658	DIR *dird;
659	struct dirent *dirp;
660	struct stat statbuf;
661
662	snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain);
663
664	if ((dird = opendir(yp_mapdir)) == NULL) {
665		yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno));
666		return(NULL);
667	}
668
669	while ((dirp = readdir(dird)) != NULL) {
670		if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) {
671			snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s",
672							yp_mapdir,dirp->d_name);
673			if (stat(yp_mapname, &statbuf) < 0 ||
674						!S_ISREG(statbuf.st_mode))
675				continue;
676			if ((cur = (struct ypmaplist *)
677				malloc(sizeof(struct ypmaplist))) == NULL) {
678				yp_error("malloc() failed");
679				closedir(dird);
680				yp_maplist_free(yp_maplist);
681				return(NULL);
682			}
683			if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) {
684				yp_error("strdup() failed: %s",strerror(errno));
685				closedir(dird);
686				yp_maplist_free(yp_maplist);
687				return(NULL);
688			}
689			cur->next = yp_maplist;
690			yp_maplist = cur;
691			if (debug)
692				yp_error("map: %s", yp_maplist->map);
693		}
694
695	}
696	closedir(dird);
697	return(yp_maplist);
698}
699
700ypresp_maplist *
701ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp)
702{
703	static ypresp_maplist  result = { 0, NULL };
704
705#ifdef DB_CACHE
706	if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) {
707#else
708	if (yp_access(NULL, (struct svc_req *)rqstp)) {
709#endif
710		result.stat = YP_YPERR;
711		return(&result);
712	}
713
714	if (argp == NULL) {
715		result.stat = YP_BADARGS;
716		return (&result);
717	}
718
719	if (yp_validdomain(*argp)) {
720		result.stat = YP_NODOM;
721		return (&result);
722	}
723
724	/*
725	 * We have to construct a linked list for the ypproc_maplist
726	 * procedure using dynamically allocated memory. Since the XDR
727	 * layer won't free this list for us, we have to deal with it
728	 * ourselves. We call yp_maplist_free() first to free any
729	 * previously allocated data we may have accumulated to insure
730	 * that we have only one linked list in memory at any given
731	 * time.
732	 */
733
734	yp_maplist_free(result.maps);
735
736	if ((result.maps = yp_maplist_create(*argp)) == NULL) {
737		yp_error("yp_maplist_create failed");
738		result.stat = YP_YPERR;
739		return(&result);
740	} else
741		result.stat = YP_TRUE;
742
743	return (&result);
744}
745
746/*
747 * NIS v1 support. The nullproc, domain and domain_nonack
748 * functions from v1 are identical to those in v2, so all
749 * we have to do is hand off to them.
750 *
751 * The other functions are mostly just wrappers around their v2
752 * counterparts. For example, for the v1 'match' procedure, we
753 * crack open the argument structure, make a request to the v2
754 * 'match' function, repackage the data into a v1 response and
755 * then send it on its way.
756 *
757 * Note that we don't support the pull, push and get procedures.
758 * There's little documentation available to show what they
759 * do, and I suspect they're meant largely for map transfers
760 * between master and slave servers.
761 */
762
763void *
764ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp)
765{
766	return(ypproc_null_2_svc(argp, rqstp));
767}
768
769bool_t *
770ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp)
771{
772	return(ypproc_domain_2_svc(argp, rqstp));
773}
774
775bool_t *
776ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp)
777{
778	return (ypproc_domain_nonack_2_svc(argp, rqstp));
779}
780
781/*
782 * the 'match' procedure sends a response of type YPRESP_VAL
783 */
784ypresponse *
785ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp)
786{
787	static ypresponse  result;
788	ypresp_val *v2_result;
789
790	result.yp_resptype = YPRESP_VAL;
791	result.ypresponse_u.yp_resp_valtype.val.valdat_val = "";
792	result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0;
793
794	if (argp->yp_reqtype != YPREQ_KEY) {
795		result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS;
796		return(&result);
797	}
798
799	v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp);
800	if (v2_result == NULL)
801		return(NULL);
802
803	bcopy((char *)v2_result,
804	      (char *)&result.ypresponse_u.yp_resp_valtype,
805	      sizeof(ypresp_val));
806
807	return (&result);
808}
809
810/*
811 * the 'first' procedure sends a response of type YPRESP_KEY_VAL
812 */
813ypresponse *
814ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp)
815{
816	static ypresponse  result;
817	ypresp_key_val *v2_result;
818
819	result.yp_resptype = YPRESP_KEY_VAL;
820	result.ypresponse_u.yp_resp_key_valtype.val.valdat_val =
821	result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = "";
822	result.ypresponse_u.yp_resp_key_valtype.val.valdat_len =
823	result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0;
824
825	if (argp->yp_reqtype != YPREQ_NOKEY) {
826		result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS;
827		return(&result);
828	}
829
830	v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype,
831									rqstp);
832	if (v2_result == NULL)
833		return(NULL);
834
835	bcopy((char *)v2_result,
836	      (char *)&result.ypresponse_u.yp_resp_key_valtype,
837	      sizeof(ypresp_key_val));
838
839	return (&result);
840}
841
842/*
843 * the 'next' procedure sends a response of type YPRESP_KEY_VAL
844 */
845ypresponse *
846ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp)
847{
848	static ypresponse  result;
849	ypresp_key_val *v2_result;
850
851	result.yp_resptype = YPRESP_KEY_VAL;
852	result.ypresponse_u.yp_resp_key_valtype.val.valdat_val =
853	result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = "";
854	result.ypresponse_u.yp_resp_key_valtype.val.valdat_len =
855	result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0;
856
857	if (argp->yp_reqtype != YPREQ_KEY) {
858		result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS;
859		return(&result);
860	}
861
862	v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp);
863	if (v2_result == NULL)
864		return(NULL);
865
866	bcopy((char *)v2_result,
867	      (char *)&result.ypresponse_u.yp_resp_key_valtype,
868	      sizeof(ypresp_key_val));
869
870	return (&result);
871}
872
873/*
874 * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS
875 */
876ypresponse *
877ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp)
878{
879	static ypresponse  result;
880	ypresp_master *v2_result1;
881	ypresp_order *v2_result2;
882
883	result.yp_resptype = YPRESP_MAP_PARMS;
884	result.ypresponse_u.yp_resp_map_parmstype.domain =
885		argp->yprequest_u.yp_req_nokeytype.domain;
886	result.ypresponse_u.yp_resp_map_parmstype.map =
887		argp->yprequest_u.yp_req_nokeytype.map;
888	/*
889	 * Hmm... there is no 'status' value in the
890	 * yp_resp_map_parmstype structure, so I have to
891	 * guess at what to do to indicate a failure.
892	 * I hope this is right.
893	 */
894	result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0;
895	result.ypresponse_u.yp_resp_map_parmstype.peer = "";
896
897	if (argp->yp_reqtype != YPREQ_MAP_PARMS) {
898		return(&result);
899	}
900
901	v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype,
902									rqstp);
903	if (v2_result1 == NULL)
904		return(NULL);
905
906	if (v2_result1->stat != YP_TRUE) {
907		return(&result);
908	}
909
910	v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype,
911									rqstp);
912	if (v2_result2 == NULL)
913		return(NULL);
914
915	if (v2_result2->stat != YP_TRUE) {
916		return(&result);
917	}
918
919	result.ypresponse_u.yp_resp_map_parmstype.peer =
920		v2_result1->peer;
921	result.ypresponse_u.yp_resp_map_parmstype.ordernum =
922		v2_result2->ordernum;
923
924	return (&result);
925}
926
927ypresponse *
928ypoldproc_push_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_pull_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
951ypresponse *
952ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp)
953{
954	static ypresponse  result;
955
956	/*
957	 * Not implemented.
958	 */
959
960	return (&result);
961}
962