yp_server.c revision 19161
125723Stegge/*
225723Stegge * Copyright (c) 1995
325723Stegge *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
425723Stegge *
525723Stegge * Redistribution and use in source and binary forms, with or without
625723Stegge * modification, are permitted provided that the following conditions
725723Stegge * are met:
825723Stegge * 1. Redistributions of source code must retain the above copyright
925723Stegge *    notice, this list of conditions and the following disclaimer.
1025723Stegge * 2. Redistributions in binary form must reproduce the above copyright
1125723Stegge *    notice, this list of conditions and the following disclaimer in the
1225723Stegge *    documentation and/or other materials provided with the distribution.
1325723Stegge * 3. All advertising materials mentioning features or use of this software
1425723Stegge *    must display the following acknowledgement:
1525723Stegge *	This product includes software developed by Bill Paul.
1625723Stegge * 4. Neither the name of the author nor the names of any co-contributors
1725723Stegge *    may be used to endorse or promote products derived from this software
1825723Stegge *    without specific prior written permission.
1925723Stegge *
2025723Stegge * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2125723Stegge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2225723Stegge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2325723Stegge * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2425723Stegge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2525723Stegge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2625723Stegge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2725723Stegge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2825723Stegge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2925723Stegge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3025723Stegge * SUCH DAMAGE.
3125723Stegge *
3225723Stegge */
3325723Stegge
3425723Stegge#include "yp_extern.h"
3525723Stegge#include "yp.h"
3625723Stegge#include <stdlib.h>
3725723Stegge#include <dirent.h>
3825723Stegge#include <sys/stat.h>
3925723Stegge#include <sys/param.h>
4025723Stegge#include <errno.h>
4125723Stegge#include <sys/types.h>
4225723Stegge#include <sys/socket.h>
4383651Speter#include <netinet/in.h>
4483651Speter#include <arpa/inet.h>
4583651Speter#include <rpc/rpc.h>
4632358Seivind
4732358Seivind#ifndef lint
4825723Steggestatic const char rcsid[] = "$Id: yp_server.c,v 1.10 1996/05/31 16:01:51 wpaul Exp $";
4925723Stegge#endif /* not lint */
5025723Stegge
5125723Steggeint forked = 0;
5267834Steggeint children = 0;
5325723Steggestatic DB *spec_dbp = NULL;	/* Special global DB handle for ypproc_all. */
5425723Steggestatic char *master_string = "YP_MASTER_NAME";
5588743Srwatsonstatic char *order_string = "YP_LAST_MODIFIED";
5625723Steggestatic int master_sz = sizeof("YP_MASTER_NAME") - 1;
5725723Steggestatic int order_sz = sizeof("YP_LAST_MODIFIED") - 1;
5892219Sluigi
5934924Sbde/*
6025723Stegge * NIS v2 support. This is where most of the action happens.
6125723Stegge */
6225723Stegge
6325723Steggevoid *
6425723Steggeypproc_null_2_svc(void *argp, struct svc_req *rqstp)
6525723Stegge{
6625723Stegge	static char * result;
6725723Stegge	static char rval = 0;
6825723Stegge
6925723Stegge#ifdef DB_CACHE
7083651Speter	if (yp_access(NULL, NULL, (struct svc_req *)rqstp))
7183651Speter#else
7283651Speter	if (yp_access(NULL, (struct svc_req *)rqstp))
7325723Stegge#endif
7425723Stegge		return(NULL);
7525723Stegge
7632609Stegge	result = &rval;
7725723Stegge
7867834Stegge	return((void *) &result);
7967834Stegge}
8067834Stegge
8167834Steggebool_t *
8225723Steggeypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp)
8325723Stegge{
8425723Stegge	static bool_t  result;
8525723Stegge
8625723Stegge#ifdef DB_CACHE
8725723Stegge	if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) {
8825723Stegge#else
8925723Stegge	if (yp_access(NULL, (struct svc_req *)rqstp)) {
9025723Stegge#endif
9125723Stegge		result = FALSE;
9267531Stegge		return (&result);
9367531Stegge	}
9467531Stegge
9567531Stegge	if (argp == NULL || yp_validdomain(*argp))
9667531Stegge		result = FALSE;
9767531Stegge	else
9867531Stegge		result = TRUE;
9967531Stegge
10067531Stegge	return (&result);
10167531Stegge}
10267531Stegge
10367531Steggebool_t *
10467531Steggeypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp)
10567531Stegge{
10688680Sambrisko	static bool_t  result;
10725723Stegge
10825723Stegge#ifdef DB_CACHE
10967834Stegge	if (yp_access(NULL, NULL, (struct svc_req *)rqstp))
11067834Stegge#else
11167834Stegge	if (yp_access(NULL, (struct svc_req *)rqstp))
11267834Stegge#endif
11367834Stegge		return (NULL);
11467834Stegge
11567834Stegge	if (argp == NULL || yp_validdomain(*argp))
11667834Stegge		return (NULL);
11767834Stegge	else
11867834Stegge		result = TRUE;
11967834Stegge
12067834Stegge	return (&result);
12167834Stegge}
12267834Stegge
12367834Steggeypresp_val *
12467834Steggeypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp)
12567834Stegge{
12667834Stegge	static ypresp_val  result;
12767834Stegge	DBT key, data;
12867834Stegge
12967834Stegge	result.val.valdat_val = "";
13067834Stegge	result.val.valdat_len = 0;
13167834Stegge
13271915Stegge#ifdef DB_CACHE
13371915Stegge	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
13467834Stegge#else
13567834Stegge	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
13671915Stegge#endif
13767834Stegge		result.stat = YP_YPERR;
13871915Stegge		return (&result);
13971915Stegge	}
14071915Stegge
14167834Stegge	if (argp->domain == NULL || argp->map == NULL) {
14267834Stegge		result.stat = YP_BADARGS;
14367834Stegge		return (&result);
14467834Stegge	}
14567834Stegge
14667834Stegge	key.size = argp->key.keydat_len;
14767834Stegge	key.data = argp->key.keydat_val;
14867834Stegge
14967834Stegge	if ((result.stat = yp_get_record(argp->domain, argp->map,
15067834Stegge						&key, &data, 1)) == YP_TRUE) {
15167834Stegge		result.val.valdat_len = data.size;
15267834Stegge		result.val.valdat_val = data.data;
15367834Stegge	}
15467834Stegge
15567834Stegge	/*
15667834Stegge	 * Do DNS lookups for hosts maps if database lookup failed.
15767834Stegge	 */
15867834Stegge
15967834Stegge#ifdef DB_CACHE
16067834Stegge	if (result.stat != YP_TRUE &&
16167834Stegge	    (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) ||
16267834Stegge	    (strstr(argp->map, "hosts") && do_dns))) {
16367834Stegge#else
16467834Stegge	if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) {
16567834Stegge#endif
16667834Stegge		char *rval = NULL;
16767834Stegge
16867834Stegge	/* DNS lookups can take time -- do them in a subprocess */
16967834Stegge
17067834Stegge		if (!debug && children < MAX_CHILDREN && fork()) {
17167834Stegge			children++;
17267834Stegge			forked = 0;
17325723Stegge			/*
17425723Stegge			 * Returning NULL here prevents svc_sendreply()
17525723Stegge			 * from being called by the parent. This is vital
17667834Stegge			 * since having both the parent and the child process
17767834Stegge			 * call it would confuse the client.
17867834Stegge			 */
17967834Stegge			return (NULL);
18067834Stegge		} else {
18167834Stegge			forked++;
18267834Stegge		}
18367834Stegge
18467834Stegge		if (debug)
18567834Stegge			yp_error("Doing DNS lookup of %.*s",
18667834Stegge			 	  argp->key.keydat_len,
18767834Stegge				  argp->key.keydat_val);
18867834Stegge
18967834Stegge		/* NUL terminate! NUL terminate!! NUL TERMINATE!!! */
19067834Stegge		argp->key.keydat_val[argp->key.keydat_len] = '\0';
19167834Stegge
19267834Stegge		if (!strcmp(argp->map, "hosts.byname"))
19367834Stegge			rval = yp_dnsname((char *)argp->key.keydat_val);
19467834Stegge		else if (!strcmp(argp->map, "hosts.byaddr"))
19567834Stegge			rval = yp_dnsaddr((const char *)argp->key.keydat_val);
19667834Stegge
19767834Stegge
19867834Stegge		if (rval) {
19967834Stegge			if (debug)
20067834Stegge				yp_error("DNS lookup successful. Result: %s",
20192219Sluigi									rval);
20267834Stegge			result.val.valdat_len = strlen(rval);
20371915Stegge			result.val.valdat_val = rval;
20471915Stegge			result.stat = YP_TRUE;
20571915Stegge		} else {
20671915Stegge			if (debug)
20771915Stegge				yp_error("DNS lookup failed.");
20871915Stegge			result.stat = YP_NOKEY;
20971915Stegge		}
21071915Stegge	}
21171915Stegge
21271915Stegge	return (&result);
21371915Stegge}
21492219Sluigi
21592219Sluigiypresp_key_val *
21692219Sluigiypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
21792219Sluigi{
21825723Stegge	static ypresp_key_val  result;
21983651Speter	DBT key, data;
22083651Speter	DB *dbp;
22183651Speter
22283651Speter	result.val.valdat_val = result.key.keydat_val = "";
22383651Speter	result.val.valdat_len = result.key.keydat_len = 0;
22483651Speter
22583651Speter#ifdef DB_CACHE
22683651Speter	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
22783651Speter#else
22883651Speter	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
22983651Speter#endif
23083651Speter		result.stat = YP_YPERR;
23183651Speter		return (&result);
23283651Speter	}
23383651Speter
23483651Speter	if (argp->domain == NULL) {
23583651Speter		result.stat = YP_BADARGS;
23667834Stegge		return (&result);
23783651Speter	}
23867834Stegge
23983651Speter#ifdef DB_CACHE
24025723Stegge	if ((dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) {
24125723Stegge#else
24283651Speter	if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
24325723Stegge#endif
24425723Stegge		result.stat = yp_errno;
24525723Stegge		return(&result);
24625723Stegge	}
24767834Stegge
24825723Stegge	key.data = NULL;
24925723Stegge	key.size = 0;
25025723Stegge
25183651Speter	if ((result.stat = yp_first_record(dbp, &key, &data, 0)) == YP_TRUE) {
25283651Speter		result.key.keydat_len = key.size;
25325723Stegge		result.key.keydat_val = key.data;
25483651Speter		result.val.valdat_len = data.size;
25583651Speter		result.val.valdat_val = data.data;
25625723Stegge	}
25783651Speter#ifndef DB_CACHE
25883651Speter	(void)(dbp->close)(dbp);
25925723Stegge#endif
26083651Speter	return (&result);
26183651Speter}
26283651Speter
26367834Steggeypresp_key_val *
26483651Speterypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp)
26583651Speter{
26667834Stegge	static ypresp_key_val  result;
26771915Stegge	DBT key, data;
26871915Stegge	DB *dbp;
26971915Stegge
27071915Stegge	result.val.valdat_val = result.key.keydat_val = "";
27167834Stegge	result.val.valdat_len = result.key.keydat_len = 0;
27267834Stegge
27367834Stegge#ifdef DB_CACHE
27467834Stegge	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
27583651Speter#else
27667834Stegge	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
27767834Stegge#endif
27867834Stegge		result.stat = YP_YPERR;
27967834Stegge		return (&result);
28067834Stegge	}
28167834Stegge
28267834Stegge	if (argp->domain == NULL || argp->map == NULL) {
28325723Stegge		result.stat = YP_BADARGS;
28467531Stegge		return (&result);
28583651Speter	}
28625723Stegge
28783651Speter#ifdef DB_CACHE
28867531Stegge	if ((dbp = yp_open_db_cache(argp->domain, argp->map,
28967531Stegge					argp->key.keydat_val,
29067531Stegge					argp->key.keydat_len)) == NULL) {
29167531Stegge#else
29267531Stegge	if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
29367531Stegge#endif
29467531Stegge		result.stat = yp_errno;
29567531Stegge		return(&result);
29683651Speter	}
29767531Stegge
29867834Stegge	key.size = argp->key.keydat_len;
29967834Stegge	key.data = argp->key.keydat_val;
30067531Stegge
30167531Stegge	if ((result.stat = yp_next_record(dbp, &key, &data,0,0)) == YP_TRUE) {
30267834Stegge		result.key.keydat_len = key.size;
30367834Stegge		result.key.keydat_val = key.data;
30467531Stegge		result.val.valdat_len = data.size;
30567531Stegge		result.val.valdat_val = data.data;
30667531Stegge	}
30767531Stegge#ifndef DB_CACHE
30867531Stegge	(void)(dbp->close)(dbp);
30967531Stegge#endif
31067531Stegge	return (&result);
31183651Speter}
31267531Stegge
31367531Steggestatic void ypxfr_callback(rval,addr,transid,prognum,port)
31467531Stegge	ypxfrstat rval;
31567531Stegge	struct sockaddr_in *addr;
31667531Stegge	unsigned int transid;
31767531Stegge	unsigned int prognum;
31867531Stegge	unsigned long port;
31967531Stegge{
32067531Stegge	CLIENT *clnt;
32167531Stegge	int sock = RPC_ANYSOCK;
32267531Stegge	struct timeval timeout;
32367531Stegge	yppushresp_xfr ypxfr_resp;
32425723Stegge	struct rpc_err err;
32525723Stegge
32667531Stegge	timeout.tv_sec = 5;
32767531Stegge	timeout.tv_usec = 0;
32825723Stegge	addr->sin_port = htons(port);
32983651Speter
33067531Stegge	if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) {
33167531Stegge		yp_error("%s: %s", inet_ntoa(addr->sin_addr),
33267531Stegge		  clnt_spcreateerror("failed to establish callback handle"));
33367531Stegge		return;
33467531Stegge	}
33525723Stegge
33625723Stegge	ypxfr_resp.status = rval;
33767531Stegge	ypxfr_resp.transid = transid;
33867531Stegge
33925723Stegge	/* Turn the timeout off -- we don't want to block. */
34083651Speter	timeout.tv_sec = 0;
34167531Stegge	if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE)
34267531Stegge		yp_error("failed to set timeout on ypproc_xfr callback");
34367531Stegge
34467531Stegge	if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) {
34567531Stegge		clnt_geterr(clnt, &err);
34667531Stegge		if (err.re_status != RPC_SUCCESS &&
34767531Stegge		    err.re_status != RPC_TIMEDOUT)
34867531Stegge			yp_error("%s", clnt_sperror(clnt,
34967531Stegge				"ypxfr callback failed"));
35025723Stegge	}
35167531Stegge
35267531Stegge	clnt_destroy(clnt);
35367531Stegge	return;
35425723Stegge}
35583651Speter
35667531Stegge#define YPXFR_RETURN(CODE) 						\
35767534Stegge	/* Order is important: send regular RPC reply, then callback */	\
35867531Stegge	result.xfrstat = CODE; 						\
35967531Stegge	svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \
36067531Stegge	ypxfr_callback(CODE,rqhost,argp->transid, 			\
36167531Stegge					argp->prog,argp->port); 	\
36267531Stegge	return(NULL);
36367531Stegge
36467534Steggeypresp_xfr *
36567534Steggeypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp)
36667531Stegge{
36767531Stegge	static ypresp_xfr  result;
36867531Stegge	struct sockaddr_in *rqhost;
36925723Stegge
37025723Stegge	result.transid = argp->transid;
37167531Stegge	rqhost = svc_getcaller(rqstp->rq_xprt);
37267531Stegge
37325723Stegge#ifdef DB_CACHE
37483651Speter	if (yp_access(argp->map_parms.map,
37567531Stegge			argp->map_parms.domain, (struct svc_req *)rqstp)) {
37667531Stegge#else
37725723Stegge	if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) {
37825723Stegge#endif
37967531Stegge		YPXFR_RETURN(YPXFR_REFUSED);
38067834Stegge	}
38167834Stegge
38283651Speter	if (argp->map_parms.domain == NULL) {
38367834Stegge		YPXFR_RETURN(YPXFR_BADARGS);
38467834Stegge	}
38567834Stegge
38667834Stegge	if (yp_validdomain(argp->map_parms.domain)) {
38767834Stegge		YPXFR_RETURN(YPXFR_NODOM);
38867834Stegge	}
38967834Stegge
39067834Stegge	switch(fork()) {
39167834Stegge	case 0:
39267834Stegge	{
39367834Stegge		char g[11], t[11], p[11];
39467834Stegge		char ypxfr_command[MAXPATHLEN + 2];
39567834Stegge
39667531Stegge		sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC);
39725723Stegge		sprintf (t, "%u", argp->transid);
39867531Stegge		sprintf (g, "%u", argp->prog);
39967531Stegge		sprintf (p, "%u", argp->port);
40083651Speter		if (debug)
40167531Stegge			close(0); close(1); close(2);
40267531Stegge		if (strcmp(yp_dir, _PATH_YP)) {
40367531Stegge			execl(ypxfr_command, "ypxfr",
40467834Stegge			"-d", argp->map_parms.domain,
40567531Stegge		      	"-h", argp->map_parms.peer,
40667531Stegge			"-p", yp_dir, "-C", t,
40767834Stegge		      	g, inet_ntoa(rqhost->sin_addr),
40867834Stegge			p, argp->map_parms.map,
40967834Stegge		      	NULL);
41025723Stegge		} else {
41125723Stegge			execl(ypxfr_command, "ypxfr",
41267834Stegge			"-d", argp->map_parms.domain,
41325723Stegge		      	"-h", argp->map_parms.peer,
41467834Stegge			"-C", t,
41567834Stegge		      	g, inet_ntoa(rqhost->sin_addr),
41667834Stegge			p, argp->map_parms.map,
41783651Speter		      	NULL);
41867834Stegge		}
41967834Stegge		forked++;
42067834Stegge		yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno));
42167834Stegge		YPXFR_RETURN(YPXFR_XFRERR);
42267834Stegge		break;
42367834Stegge	}
42467834Stegge	case -1:
42567834Stegge		yp_error("ypxfr fork(): %s", strerror(errno));
42667834Stegge		YPXFR_RETURN(YPXFR_XFRERR);
42767834Stegge		break;
42867834Stegge	default:
42967834Stegge		result.xfrstat = YPXFR_SUCC;
43067834Stegge		children++;
43167834Stegge		forked = 0;
43267834Stegge		break;
43383651Speter	}
43467834Stegge
43567834Stegge	return (&result);
43671915Stegge}
43771915Stegge#undef YPXFR_RETURN
43871915Stegge
43971915Steggevoid *
44071915Steggeypproc_clear_2_svc(void *argp, struct svc_req *rqstp)
44167834Stegge{
44267834Stegge	static char * result;
44367834Stegge	static char rval = 0;
44467834Stegge
44571915Stegge#ifdef DB_CACHE
44671915Stegge	if (yp_access(NULL, NULL, (struct svc_req *)rqstp))
44771915Stegge#else
44883651Speter	if (yp_access(NULL, (struct svc_req *)rqstp))
44971915Stegge#endif
45071915Stegge		return (NULL);
45171915Stegge#ifdef DB_CACHE
45271915Stegge	/* clear out the database cache */
45371915Stegge	yp_flush_all();
45471915Stegge#endif
45571915Stegge	/* Re-read the securenets database for the hell of it. */
45671915Stegge	load_securenets();
45771915Stegge
45883651Speter	result = &rval;
45971915Stegge	return((void *) &result);
46071915Stegge}
46171915Stegge
46271915Stegge/*
46371915Stegge * For ypproc_all, we have to send a stream of ypresp_all structures
46471915Stegge * via TCP, but the XDR filter generated from the yp.x protocol
46571915Stegge * definition file only serializes one such structure. This means that
46671915Stegge * to send the whole stream, you need a wrapper which feeds all the
46771915Stegge * records into the underlying XDR routine until it hits an 'EOF.'
46883651Speter * But to use the wrapper, you have to violate the boundaries between
46971915Stegge * RPC layers by calling svc_sendreply() directly from the ypproc_all
47071915Stegge * service routine instead of letting the RPC dispatcher do it.
47171915Stegge *
47271915Stegge * Bleah.
47371915Stegge */
47471915Stegge
47533181Seivind/*
47667834Stegge * Custom XDR routine for serialzing results of ypproc_all: keep
47783651Speter * reading from the database and spew until we run out of records
47867834Stegge * or encounter an error.
47971915Stegge */
48071915Steggestatic bool_t
48183651Speterxdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp)
48267834Stegge{
48367834Stegge	DBT key = { NULL, 0 } , data = { NULL, 0 };
48467834Stegge
48567834Stegge	while (1) {
48667834Stegge		/* Get a record. */
48767834Stegge		if ((objp->ypresp_all_u.val.stat =
48867834Stegge	    		yp_next_record(spec_dbp,&key,&data,1,0)) == YP_TRUE) {
48967834Stegge			objp->ypresp_all_u.val.val.valdat_len = data.size;
49067834Stegge			objp->ypresp_all_u.val.val.valdat_val = data.data;
49167834Stegge			objp->ypresp_all_u.val.key.keydat_len = key.size;
49267834Stegge			objp->ypresp_all_u.val.key.keydat_val = key.data;
49367834Stegge			objp->more = TRUE;
49467834Stegge		} else {
49583651Speter			objp->more = FALSE;
49671915Stegge		}
49771915Stegge
49871915Stegge		/* Serialize. */
49971915Stegge		if (!xdr_ypresp_all(xdrs, objp))
50071915Stegge			return(FALSE);
50171915Stegge		if (objp->more == FALSE)
50283651Speter			return(TRUE);
50371915Stegge	}
50471915Stegge}
50571915Stegge
50671915Steggeypresp_all *
50771915Steggeypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
50871915Stegge{
50971915Stegge	static ypresp_all  result;
51071915Stegge
51171915Stegge	/*
51271915Stegge	 * Set this here so that the client will be forced to make
51371915Stegge	 * at least one attempt to read from us even if all we're
51471915Stegge	 * doing is returning an error.
51571915Stegge	 */
51671915Stegge	result.more = TRUE;
51783651Speter	result.ypresp_all_u.val.key.keydat_len = 0;
51867834Stegge	result.ypresp_all_u.val.key.keydat_val = "";
51983651Speter
52071915Stegge#ifdef DB_CACHE
52171915Stegge	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
52271915Stegge#else
52371915Stegge	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
52467834Stegge#endif
52567834Stegge		result.ypresp_all_u.val.stat = YP_YPERR;
52667834Stegge		return (&result);
52767834Stegge	}
52867834Stegge
52967834Stegge	if (argp->domain == NULL || argp->map == NULL) {
53067834Stegge		result.ypresp_all_u.val.stat = YP_BADARGS;
53183651Speter		return (&result);
53283651Speter	}
53367834Stegge
53483651Speter	/*
53567834Stegge	 * The ypproc_all procedure can take a while to complete.
53671915Stegge	 * Best to handle it in a subprocess so the parent doesn't
53771915Stegge	 * block. (Is there a better way to do this? Maybe with
53871915Stegge	 * async socket I/O?)
53971915Stegge	 */
54071915Stegge	if (!debug && children < MAX_CHILDREN && fork()) {
54171915Stegge		children++;
54271915Stegge		forked = 0;
54371915Stegge		return (NULL);
54471915Stegge	} else {
54571915Stegge		forked++;
54671915Stegge	}
54783651Speter
54883651Speter#ifndef DB_CACHE
54971915Stegge	if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) {
55071915Stegge		result.ypresp_all_u.val.stat = yp_errno;
55171915Stegge		return(&result);
55271915Stegge	}
55371915Stegge#else
55471915Stegge	if ((spec_dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) {
55571915Stegge		result.ypresp_all_u.val.stat = yp_errno;
55671915Stegge		return(&result);
55771915Stegge	}
55871915Stegge#endif
55971915Stegge
56083651Speter	/* Kick off the actual data transfer. */
56167834Stegge	svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result);
56267834Stegge
56367834Stegge#ifndef DB_CACHE
56467834Stegge	(void)(spec_dbp->close)(spec_dbp);
56567834Stegge#endif
56667834Stegge	/*
56767834Stegge	 * Returning NULL prevents the dispatcher from calling
56867834Stegge	 * svc_sendreply() since we already did it.
56967834Stegge	 */
57067834Stegge	return (NULL);
57167834Stegge}
57267834Stegge
57367834Steggeypresp_master *
57483651Speterypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
57525723Stegge{
57625723Stegge	static ypresp_master  result;
57767834Stegge	static char ypvalbuf[YPMAXRECORD];
57825723Stegge	DBT key = { master_string, master_sz }, data;
57938482Swollman
58025723Stegge	result.peer = "";
58167834Stegge
58267834Stegge#ifdef DB_CACHE
58367834Stegge	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
58438482Swollman#else
58567834Stegge	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
58667834Stegge#endif
58767834Stegge		result.stat = YP_YPERR;
58871915Stegge		return(&result);
58971915Stegge	}
59083651Speter
59125723Stegge	if (argp->domain == NULL) {
59225723Stegge		result.stat = YP_BADARGS;
59325723Stegge		return (&result);
59491406Sjhb	}
59567834Stegge
59625723Stegge	/*
59783651Speter	 * Note that we copy the data retrieved from the database to
59838482Swollman	 * a private buffer and NUL terminate the buffer rather than
59938482Swollman	 * terminating the data in place. We do this because by stuffing
60067834Stegge	 * a '\0' into data.data, we will actually be corrupting memory
60138482Swollman	 * allocated by the DB package. This is a bad thing now that we
60238482Swollman	 * cache DB handles rather than closing the database immediately.
60338482Swollman	 */
60438482Swollman	if ((result.stat = yp_get_record(argp->domain, argp->map,
60583651Speter						&key, &data, 1)) == YP_TRUE) {
60667834Stegge		bcopy((char *)data.data, (char *)&ypvalbuf, data.size);
60767834Stegge		ypvalbuf[data.size] = '\0';
60825723Stegge		result.peer = (char *)&ypvalbuf;
60983651Speter	} else
61025723Stegge		result.peer = "";
61125723Stegge
61225723Stegge	return (&result);
61338482Swollman}
61467834Stegge
61538482Swollmanypresp_order *
61638482Swollmanypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp)
61767834Stegge{
61867834Stegge	static ypresp_order  result;
61967834Stegge	DBT key = { order_string, order_sz }, data;
62038482Swollman
62125723Stegge	result.ordernum = 0;
62225723Stegge
62367834Stegge#ifdef DB_CACHE
62467834Stegge	if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) {
62567834Stegge#else
62667834Stegge	if (yp_access(argp->map, (struct svc_req *)rqstp)) {
62767834Stegge#endif
62867834Stegge		result.stat = YP_YPERR;
62967834Stegge		return(&result);
63067834Stegge	}
63167834Stegge
63267834Stegge	if (argp->domain == NULL) {
63367834Stegge		result.stat = YP_BADARGS;
63483651Speter		return (&result);
63567834Stegge	}
63625723Stegge
63725723Stegge	/*
63867834Stegge	 * We could just check the timestamp on the map file,
63967834Stegge	 * but that's a hack: we'll only know the last time the file
64025723Stegge	 * was touched, not the last time the database contents were
64183366Sjulian	 * updated.
64267834Stegge	 */
64325723Stegge
64425723Stegge	if ((result.stat = yp_get_record(argp->domain, argp->map,
64525723Stegge						&key, &data, 1)) == YP_TRUE)
64683651Speter		result.ordernum = atoi((char *)data.data);
64725723Stegge	else
64825723Stegge		result.ordernum = 0;
64925723Stegge
65067834Stegge
65167834Stegge	return (&result);
65225723Stegge}
65325723Stegge
65483651Speterstatic void yp_maplist_free(yp_maplist)
65525723Stegge	struct ypmaplist *yp_maplist;
65625723Stegge{
65725723Stegge	register struct ypmaplist *next;
65825723Stegge
65925723Stegge	while(yp_maplist) {
66025723Stegge		next = yp_maplist->next;
66167834Stegge		free(yp_maplist->map);
66225723Stegge		free(yp_maplist);
66383651Speter		yp_maplist = next;
66467834Stegge	}
66567834Stegge	return;
66667834Stegge}
66767834Stegge
66867834Steggestatic struct ypmaplist *yp_maplist_create(domain)
66967834Stegge	const char *domain;
67071915Stegge{
67167834Stegge	char yp_mapdir[MAXPATHLEN + 2];
67267834Stegge	char yp_mapname[MAXPATHLEN + 2];
67367834Stegge	struct ypmaplist *cur = NULL;
67467834Stegge	struct ypmaplist *yp_maplist = NULL;
67567834Stegge	DIR *dird;
67683651Speter	struct dirent *dirp;
67767834Stegge	struct stat statbuf;
67867834Stegge
67967834Stegge	snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain);
68067834Stegge
68171915Stegge	if ((dird = opendir(yp_mapdir)) == NULL) {
68267834Stegge		yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno));
68367834Stegge		return(NULL);
68467834Stegge	}
68571915Stegge
68667834Stegge	while ((dirp = readdir(dird)) != NULL) {
68725723Stegge		if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) {
68867834Stegge			snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s",
68967834Stegge							yp_mapdir,dirp->d_name);
69067834Stegge			if (stat(yp_mapname, &statbuf) < 0 ||
69171915Stegge						!S_ISREG(statbuf.st_mode))
69271915Stegge				continue;
69371915Stegge			if ((cur = (struct ypmaplist *)
69471915Stegge				malloc(sizeof(struct ypmaplist))) == NULL) {
69571915Stegge				yp_error("malloc() failed: %s",strerror(errno));
69671915Stegge				closedir(dird);
69771915Stegge				yp_maplist_free(yp_maplist);
69871915Stegge				return(NULL);
69983366Sjulian			}
70071915Stegge			if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) {
70183651Speter				yp_error("strdup() failed: %s",strerror(errno));
70267834Stegge				closedir(dird);
70383651Speter				yp_maplist_free(yp_maplist);
70467834Stegge				return(NULL);
70571915Stegge			}
70671915Stegge			cur->next = yp_maplist;
70771915Stegge			yp_maplist = cur;
70871915Stegge			if (debug)
70971915Stegge				yp_error("map: %s", yp_maplist->map);
71071915Stegge		}
71171915Stegge
71271915Stegge	}
71371915Stegge	closedir(dird);
71471915Stegge	return(yp_maplist);
71571915Stegge}
71671915Stegge
71771915Steggeypresp_maplist *
71867834Steggeypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp)
71971915Stegge{
72067834Stegge	static ypresp_maplist  result = { 0, NULL };
72167834Stegge
72267834Stegge#ifdef DB_CACHE
72367834Stegge	if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) {
72467834Stegge#else
72567834Stegge	if (yp_access(NULL, (struct svc_req *)rqstp)) {
72667834Stegge#endif
72767834Stegge		result.stat = YP_YPERR;
72867834Stegge		return(&result);
72983651Speter	}
73067834Stegge
73167834Stegge	if (argp == NULL) {
73267834Stegge		result.stat = YP_BADARGS;
73367834Stegge		return (&result);
73467834Stegge	}
73567834Stegge
73683366Sjulian	if (yp_validdomain(*argp)) {
73783651Speter		result.stat = YP_NODOM;
73867834Stegge		return (&result);
73983651Speter	}
74067834Stegge
74167834Stegge	/*
74267834Stegge	 * We have to construct a linked list for the ypproc_maplist
74383366Sjulian	 * procedure using dynamically allocated memory. Since the XDR
74467834Stegge	 * layer won't free this list for us, we have to deal with it
74567834Stegge	 * ourselves. We call yp_maplist_free() first to free any
74667834Stegge	 * previously allocated data we may have accumulated to insure
74767834Stegge	 * that we have only one linked list in memory at any given
74883651Speter	 * time.
74967834Stegge	 */
75083366Sjulian
75167834Stegge	yp_maplist_free(result.maps);
75267834Stegge
75367834Stegge	if ((result.maps = yp_maplist_create(*argp)) == NULL) {
75467834Stegge		yp_error("yp_maplist_create failed");
75567834Stegge		result.stat = YP_YPERR;
75667834Stegge		return(&result);
75767834Stegge	} else
75883651Speter		result.stat = YP_TRUE;
75967834Stegge
76083651Speter	return (&result);
76167834Stegge}
76267834Stegge
76367834Stegge/*
76467834Stegge * NIS v1 support. The nullproc, domain and domain_nonack
76583366Sjulian * functions from v1 are identical to those in v2, so all
76667834Stegge * we have to do is hand off to them.
76767834Stegge *
76867834Stegge * The other functions are mostly just wrappers around their v2
76967834Stegge * counterparts. For example, for the v1 'match' procedure, we
77083651Speter * crack open the argument structure, make a request to the v2
77125723Stegge * 'match' function, repackage the data into a v1 response and
77283651Speter * then send it on its way.
77367834Stegge *
77467834Stegge * Note that we don't support the pull, push and get procedures.
77567834Stegge * There's little documentation available to show what they
77667834Stegge * do, and I suspect they're meant largely for map transfers
77767834Stegge * between master and slave servers.
77883651Speter */
77925723Stegge
78025723Steggevoid *
78125723Steggeypoldproc_null_1_svc(void *argp, struct svc_req *rqstp)
78267834Stegge{
78371915Stegge	return(ypproc_null_2_svc(argp, rqstp));
78467834Stegge}
78567834Stegge
78667834Steggebool_t *
78783651Speterypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp)
78825723Stegge{
78925723Stegge	return(ypproc_domain_2_svc(argp, rqstp));
79025723Stegge}
79125723Stegge
79267834Steggebool_t *
79367834Steggeypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp)
79467834Stegge{
79567834Stegge	return (ypproc_domain_nonack_2_svc(argp, rqstp));
79683651Speter}
79725723Stegge
79825723Stegge/*
79925723Stegge * the 'match' procedure sends a response of type YPRESP_VAL
80025723Stegge */
80125723Steggeypresponse *
80267834Steggeypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp)
80383366Sjulian{
80483651Speter	static ypresponse  result;
80525723Stegge	ypresp_val *v2_result;
80667531Stegge
80767531Stegge	result.yp_resptype = YPRESP_VAL;
80867834Stegge	result.ypresponse_u.yp_resp_valtype.val.valdat_val = "";
80967834Stegge	result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0;
81067834Stegge
81167834Stegge	if (argp->yp_reqtype != YPREQ_KEY) {
81271915Stegge		result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS;
81371915Stegge		return(&result);
81467834Stegge	}
81583651Speter
81667834Stegge	v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp);
81767834Stegge	if (v2_result == NULL)
81867834Stegge		return(NULL);
81925723Stegge
82067834Stegge	bcopy((char *)v2_result,
82125723Stegge	      (char *)&result.ypresponse_u.yp_resp_valtype,
82267834Stegge	      sizeof(ypresp_val));
82383651Speter
82432609Stegge	return (&result);
82532609Stegge}
82625723Stegge
82767834Stegge/*
82883651Speter * the 'first' procedure sends a response of type YPRESP_KEY_VAL
82967834Stegge */
83067834Steggeypresponse *
83167531Steggeypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp)
83283651Speter{
83367834Stegge	static ypresponse  result;
83467834Stegge	ypresp_key_val *v2_result;
83567834Stegge
83667834Stegge	result.yp_resptype = YPRESP_KEY_VAL;
83767834Stegge	result.ypresponse_u.yp_resp_key_valtype.val.valdat_val =
83867834Stegge	result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = "";
83983651Speter	result.ypresponse_u.yp_resp_key_valtype.val.valdat_len =
84067834Stegge	result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0;
84167834Stegge
84267834Stegge	if (argp->yp_reqtype != YPREQ_NOKEY) {
84383651Speter		result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS;
84467834Stegge		return(&result);
84567834Stegge	}
84667834Stegge
84767834Stegge	v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype,
84867834Stegge									rqstp);
84925723Stegge	if (v2_result == NULL)
85067834Stegge		return(NULL);
85167834Stegge
85225723Stegge	bcopy((char *)v2_result,
85367834Stegge	      (char *)&result.ypresponse_u.yp_resp_key_valtype,
85471915Stegge	      sizeof(ypresp_key_val));
85571915Stegge
85671915Stegge	return (&result);
85771915Stegge}
85871915Stegge
85971915Stegge/*
86071915Stegge * the 'next' procedure sends a response of type YPRESP_KEY_VAL
86171915Stegge */
86271915Steggeypresponse *
86371915Steggeypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp)
86471915Stegge{
86571915Stegge	static ypresponse  result;
86671915Stegge	ypresp_key_val *v2_result;
86771915Stegge
86871915Stegge	result.yp_resptype = YPRESP_KEY_VAL;
86971915Stegge	result.ypresponse_u.yp_resp_key_valtype.val.valdat_val =
87071915Stegge	result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = "";
87171915Stegge	result.ypresponse_u.yp_resp_key_valtype.val.valdat_len =
87271915Stegge	result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0;
87371915Stegge
87467834Stegge	if (argp->yp_reqtype != YPREQ_KEY) {
87571915Stegge		result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS;
87667834Stegge		return(&result);
87767834Stegge	}
87867834Stegge
87967834Stegge	v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp);
88067834Stegge	if (v2_result == NULL)
88167834Stegge		return(NULL);
88267834Stegge
88367834Stegge	bcopy((char *)v2_result,
88467834Stegge	      (char *)&result.ypresponse_u.yp_resp_key_valtype,
88567834Stegge	      sizeof(ypresp_key_val));
88667834Stegge
88767834Stegge	return (&result);
88867834Stegge}
88967834Stegge
89067834Stegge/*
89167834Stegge * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS
89267834Stegge */
89367834Steggeypresponse *
89467834Steggeypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp)
89567834Stegge{
89667834Stegge	static ypresponse  result;
89767834Stegge	ypresp_master *v2_result1;
89867834Stegge	ypresp_order *v2_result2;
89967834Stegge
90067834Stegge	result.yp_resptype = YPRESP_MAP_PARMS;
90167834Stegge	result.ypresponse_u.yp_resp_map_parmstype.domain =
90267834Stegge		argp->yprequest_u.yp_req_nokeytype.domain;
90367834Stegge	result.ypresponse_u.yp_resp_map_parmstype.map =
90425723Stegge		argp->yprequest_u.yp_req_nokeytype.map;
90567834Stegge	/*
90667834Stegge	 * Hmm... there is no 'status' value in the
90767834Stegge	 * yp_resp_map_parmstype structure, so I have to
90867834Stegge	 * guess at what to do to indicate a failure.
90971915Stegge	 * I hope this is right.
91071915Stegge	 */
91171915Stegge	result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0;
91271915Stegge	result.ypresponse_u.yp_resp_map_parmstype.peer = "";
91371915Stegge
91471915Stegge	if (argp->yp_reqtype != YPREQ_MAP_PARMS) {
91571915Stegge		return(&result);
91671915Stegge	}
91771915Stegge
91871915Stegge	v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype,
91971915Stegge									rqstp);
92083651Speter	if (v2_result1 == NULL)
92171915Stegge		return(NULL);
92271915Stegge
92383651Speter	if (v2_result1->stat != YP_TRUE) {
92467834Stegge		return(&result);
92567834Stegge	}
92667834Stegge
92767834Stegge	v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype,
92867834Stegge									rqstp);
92925723Stegge	if (v2_result2 == NULL)
93083651Speter		return(NULL);
93183651Speter
93267834Stegge	if (v2_result2->stat != YP_TRUE) {
93367834Stegge		return(&result);
93467834Stegge	}
93525723Stegge
93667834Stegge	result.ypresponse_u.yp_resp_map_parmstype.peer =
93771915Stegge		v2_result1->peer;
93871915Stegge	result.ypresponse_u.yp_resp_map_parmstype.ordernum =
93971915Stegge		v2_result2->ordernum;
94071915Stegge
94167834Stegge	return (&result);
94267834Stegge}
94367834Stegge
94467834Steggeypresponse *
94567834Steggeypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp)
94667834Stegge{
94767834Stegge	static ypresponse  result;
94867834Stegge
94967834Stegge	/*
95067834Stegge	 * Not implemented.
95167834Stegge	 */
95267834Stegge
95371915Stegge	return (&result);
95467834Stegge}
95567834Stegge
95667834Steggeypresponse *
95767834Steggeypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp)
95867834Stegge{
95925723Stegge	static ypresponse  result;
96025723Stegge
96183651Speter	/*
96267531Stegge	 * Not implemented.
96367531Stegge	 */
96425723Stegge
96525723Stegge	return (&result);
96625723Stegge}
96725723Stegge
96867531Steggeypresponse *
96967834Steggeypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp)
97083651Speter{
97125723Stegge	static ypresponse  result;
97267531Stegge
97367531Stegge	/*
97467834Stegge	 * Not implemented.
97567834Stegge	 */
97667834Stegge
97767834Stegge	return (&result);
97825723Stegge}
97991406Sjhb