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