174462Salfred/*
274462Salfred * $NetBSD: rpcb_svc_4.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $
374462Salfred * $FreeBSD$
474462Salfred */
574462Salfred
674462Salfred/*
774462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
874462Salfred * unrestricted use provided that this legend is included on all tape
974462Salfred * media and as a part of the software program in whole or part.  Users
1074462Salfred * may copy or modify Sun RPC without charge, but are not authorized
1174462Salfred * to license or distribute it to anyone else except as part of a product or
1274462Salfred * program developed by the user.
1374462Salfred *
1474462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1574462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1674462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1774462Salfred *
1874462Salfred * Sun RPC is provided with no support and without any obligation on the
1974462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction,
2074462Salfred * modification or enhancement.
2174462Salfred *
2274462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2374462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2474462Salfred * OR ANY PART THEREOF.
2574462Salfred *
2674462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2774462Salfred * or profits or other special, indirect and consequential damages, even if
2874462Salfred * Sun has been advised of the possibility of such damages.
2974462Salfred *
3074462Salfred * Sun Microsystems, Inc.
3174462Salfred * 2550 Garcia Avenue
3274462Salfred * Mountain View, California  94043
3374462Salfred */
3474462Salfred/*
3574462Salfred * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
3674462Salfred */
3774462Salfred
3874462Salfred/* #ident	"@(#)rpcb_svc_4.c	1.8	93/07/05 SMI" */
3974462Salfred
4074462Salfred/*
4174462Salfred * rpcb_svc_4.c
4274462Salfred * The server procedure for the version 4 rpcbind.
4374462Salfred *
4474462Salfred */
4574462Salfred
4674462Salfred#include <sys/types.h>
4774462Salfred#include <sys/stat.h>
4874462Salfred#include <rpc/rpc.h>
4974462Salfred#include <stdio.h>
5074462Salfred#include <unistd.h>
5174462Salfred#include <netconfig.h>
5274462Salfred#include <syslog.h>
5374462Salfred#include <string.h>
5474462Salfred#include <stdlib.h>
5574462Salfred#include "rpcbind.h"
5674462Salfred
57173412Skevlostatic void *rpcbproc_getaddr_4_local(void *, struct svc_req *, SVCXPRT *,
58173412Skevlo				      rpcvers_t);
59173412Skevlostatic void *rpcbproc_getversaddr_4_local(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
6074462Salfredstatic void *rpcbproc_getaddrlist_4_local
61173412Skevlo	(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
62173412Skevlostatic void free_rpcb_entry_list(rpcb_entry_list_ptr *);
63173412Skevlostatic void *rpcbproc_dump_4_local(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
6474462Salfred
6574462Salfred/*
6674462Salfred * Called by svc_getreqset. There is a separate server handle for
6774462Salfred * every transport that it waits on.
6874462Salfred */
6974462Salfredvoid
7074462Salfredrpcb_service_4(struct svc_req *rqstp, SVCXPRT *transp)
7174462Salfred{
7274462Salfred	union {
7374462Salfred		rpcb rpcbproc_set_4_arg;
7474462Salfred		rpcb rpcbproc_unset_4_arg;
7574462Salfred		rpcb rpcbproc_getaddr_4_local_arg;
7674462Salfred		char *rpcbproc_uaddr2taddr_4_arg;
7774462Salfred		struct netbuf rpcbproc_taddr2uaddr_4_arg;
7874462Salfred	} argument;
7974462Salfred	char *result;
8074462Salfred	xdrproc_t xdr_argument, xdr_result;
81173412Skevlo	void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
8274462Salfred
8374462Salfred	rpcbs_procinfo(RPCBVERS_4_STAT, rqstp->rq_proc);
8474462Salfred
8574462Salfred	switch (rqstp->rq_proc) {
8674462Salfred	case NULLPROC:
8774462Salfred		/*
8874462Salfred		 * Null proc call
8974462Salfred		 */
9074462Salfred#ifdef RPCBIND_DEBUG
9174462Salfred		if (debugging)
9274462Salfred			fprintf(stderr, "RPCBPROC_NULL\n");
9374462Salfred#endif
9474462Salfred		check_access(transp, rqstp->rq_proc, NULL, RPCBVERS4);
9574462Salfred		(void) svc_sendreply(transp, (xdrproc_t) xdr_void,
9674462Salfred					(char *)NULL);
9774462Salfred		return;
9874462Salfred
9974462Salfred	case RPCBPROC_SET:
10074462Salfred		/*
10174462Salfred		 * Check to see whether the message came from
10274462Salfred		 * loopback transports (for security reasons)
10374462Salfred		 */
10474462Salfred		xdr_argument = (xdrproc_t)xdr_rpcb;
10574462Salfred		xdr_result = (xdrproc_t)xdr_bool;
10674462Salfred		local = rpcbproc_set_com;
10774462Salfred		break;
10874462Salfred
10974462Salfred	case RPCBPROC_UNSET:
11074462Salfred		/*
11174462Salfred		 * Check to see whether the message came from
11274462Salfred		 * loopback transports (for security reasons)
11374462Salfred		 */
11474462Salfred		xdr_argument = (xdrproc_t)xdr_rpcb;
11574462Salfred		xdr_result = (xdrproc_t)xdr_bool;
11674462Salfred		local = rpcbproc_unset_com;
11774462Salfred		break;
11874462Salfred
11974462Salfred	case RPCBPROC_GETADDR:
12074462Salfred		xdr_argument = (xdrproc_t)xdr_rpcb;
12174462Salfred		xdr_result = (xdrproc_t)xdr_wrapstring;
12274462Salfred		local = rpcbproc_getaddr_4_local;
12374462Salfred		break;
12474462Salfred
12574462Salfred	case RPCBPROC_GETVERSADDR:
12674462Salfred#ifdef RPCBIND_DEBUG
12774462Salfred		if (debugging)
12874462Salfred			fprintf(stderr, "RPCBPROC_GETVERSADDR\n");
12974462Salfred#endif
13074462Salfred		xdr_argument = (xdrproc_t)xdr_rpcb;
13174462Salfred		xdr_result = (xdrproc_t)xdr_wrapstring;
13274462Salfred		local = rpcbproc_getversaddr_4_local;
13374462Salfred		break;
13474462Salfred
13574462Salfred	case RPCBPROC_DUMP:
13674462Salfred#ifdef RPCBIND_DEBUG
13774462Salfred		if (debugging)
13874462Salfred			fprintf(stderr, "RPCBPROC_DUMP\n");
13974462Salfred#endif
14074462Salfred		xdr_argument = (xdrproc_t)xdr_void;
14174462Salfred		xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
14274462Salfred		local = rpcbproc_dump_4_local;
14374462Salfred		break;
14474462Salfred
14574462Salfred	case RPCBPROC_INDIRECT:
14674462Salfred#ifdef RPCBIND_DEBUG
14774462Salfred		if (debugging)
14874462Salfred			fprintf(stderr, "RPCBPROC_INDIRECT\n");
14974462Salfred#endif
15074462Salfred		rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
15174462Salfred		return;
15274462Salfred
15374462Salfred/*	case RPCBPROC_CALLIT: */
15474462Salfred	case RPCBPROC_BCAST:
15574462Salfred#ifdef RPCBIND_DEBUG
15674462Salfred		if (debugging)
15774462Salfred			fprintf(stderr, "RPCBPROC_BCAST\n");
15874462Salfred#endif
15974462Salfred		rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
16074462Salfred		return;
16174462Salfred
16274462Salfred	case RPCBPROC_GETTIME:
16374462Salfred#ifdef RPCBIND_DEBUG
16474462Salfred		if (debugging)
16574462Salfred			fprintf(stderr, "RPCBPROC_GETTIME\n");
16674462Salfred#endif
16774462Salfred		xdr_argument = (xdrproc_t)xdr_void;
16874462Salfred		xdr_result = (xdrproc_t)xdr_u_long;
16974462Salfred		local = rpcbproc_gettime_com;
17074462Salfred		break;
17174462Salfred
17274462Salfred	case RPCBPROC_UADDR2TADDR:
17374462Salfred#ifdef RPCBIND_DEBUG
17474462Salfred		if (debugging)
17574462Salfred			fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
17674462Salfred#endif
17774462Salfred		xdr_argument = (xdrproc_t)xdr_wrapstring;
17874462Salfred		xdr_result = (xdrproc_t)xdr_netbuf;
17974462Salfred		local = rpcbproc_uaddr2taddr_com;
18074462Salfred		break;
18174462Salfred
18274462Salfred	case RPCBPROC_TADDR2UADDR:
18374462Salfred#ifdef RPCBIND_DEBUG
18474462Salfred		if (debugging)
18574462Salfred			fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
18674462Salfred#endif
18774462Salfred		xdr_argument = (xdrproc_t)xdr_netbuf;
18874462Salfred		xdr_result = (xdrproc_t)xdr_wrapstring;
18974462Salfred		local = rpcbproc_taddr2uaddr_com;
19074462Salfred		break;
19174462Salfred
19274462Salfred	case RPCBPROC_GETADDRLIST:
19374462Salfred#ifdef RPCBIND_DEBUG
19474462Salfred		if (debugging)
19574462Salfred			fprintf(stderr, "RPCBPROC_GETADDRLIST\n");
19674462Salfred#endif
19774462Salfred		xdr_argument = (xdrproc_t)xdr_rpcb;
19874462Salfred		xdr_result = (xdrproc_t)xdr_rpcb_entry_list_ptr;
19974462Salfred		local = rpcbproc_getaddrlist_4_local;
20074462Salfred		break;
20174462Salfred
20274462Salfred	case RPCBPROC_GETSTAT:
20374462Salfred#ifdef RPCBIND_DEBUG
20474462Salfred		if (debugging)
20574462Salfred			fprintf(stderr, "RPCBPROC_GETSTAT\n");
20674462Salfred#endif
20774462Salfred		xdr_argument = (xdrproc_t)xdr_void;
20874462Salfred		xdr_result = (xdrproc_t)xdr_rpcb_stat_byvers;
20974462Salfred		local = rpcbproc_getstat;
21074462Salfred		break;
21174462Salfred
21274462Salfred	default:
21374462Salfred		svcerr_noproc(transp);
21474462Salfred		return;
21574462Salfred	}
21674462Salfred	memset((char *)&argument, 0, sizeof (argument));
21774462Salfred	if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
21874462Salfred		(char *)&argument)) {
21974462Salfred		svcerr_decode(transp);
22074462Salfred		if (debugging)
22174462Salfred			(void) fprintf(stderr, "rpcbind: could not decode\n");
22274462Salfred		return;
22374462Salfred	}
22474462Salfred	if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS4)) {
22574462Salfred		svcerr_weakauth(transp);
22674462Salfred		goto done;
22774462Salfred	}
22874462Salfred	result = (*local)(&argument, rqstp, transp, RPCBVERS4);
22974462Salfred	if (result != NULL && !svc_sendreply(transp, (xdrproc_t) xdr_result,
23074462Salfred						result)) {
23174462Salfred		svcerr_systemerr(transp);
23274462Salfred		if (debugging) {
23374462Salfred			(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
23474462Salfred			if (doabort) {
23574462Salfred				rpcbind_abort();
23674462Salfred			}
23774462Salfred		}
23874462Salfred	}
23974462Salfreddone:
24074462Salfred	if (!svc_freeargs(transp, (xdrproc_t) xdr_argument,
24174462Salfred				(char *)&argument)) {
24274462Salfred		if (debugging) {
24374462Salfred			(void) fprintf(stderr, "unable to free arguments\n");
24474462Salfred			if (doabort) {
24574462Salfred				rpcbind_abort();
24674462Salfred			}
24774462Salfred		}
24874462Salfred	}
24974462Salfred	return;
25074462Salfred}
25174462Salfred
25274462Salfred/*
25374462Salfred * Lookup the mapping for a program, version and return its
25474462Salfred * address. Assuming that the caller wants the address of the
25574462Salfred * server running on the transport on which the request came.
25674462Salfred * Even if a service with a different version number is available,
25774462Salfred * it will return that address.  The client should check with an
25874462Salfred * clnt_call to verify whether the service is the one that is desired.
25974462Salfred * We also try to resolve the universal address in terms of
26074462Salfred * address of the caller.
26174462Salfred */
26274462Salfred/* ARGSUSED */
26374462Salfredstatic void *
26474462Salfredrpcbproc_getaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
265104592Salfred			 rpcvers_t rpcbversnum __unused)
26674462Salfred{
26774462Salfred	RPCB *regp = (RPCB *)arg;
26874462Salfred#ifdef RPCBIND_DEBUG
26974462Salfred	if (debugging) {
27074462Salfred		char *uaddr;
27174462Salfred
27274462Salfred		uaddr =	taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
27374462Salfred			    svc_getrpccaller(transp));
27474462Salfred		fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
27574462Salfred		    (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
27674462Salfred		    regp->r_netid, uaddr);
27774462Salfred		free(uaddr);
27874462Salfred	}
27974462Salfred#endif
28074462Salfred	return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
28174462Salfred					RPCB_ALLVERS));
28274462Salfred}
28374462Salfred
28474462Salfred/*
28574462Salfred * Lookup the mapping for a program, version and return its
28674462Salfred * address. Assuming that the caller wants the address of the
28774462Salfred * server running on the transport on which the request came.
28874462Salfred *
28974462Salfred * We also try to resolve the universal address in terms of
29074462Salfred * address of the caller.
29174462Salfred */
29274462Salfred/* ARGSUSED */
29374462Salfredstatic void *
29474462Salfredrpcbproc_getversaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
295104592Salfred			     rpcvers_t versnum __unused)
29674462Salfred{
29774462Salfred	RPCB *regp = (RPCB *)arg;
29874462Salfred#ifdef RPCBIND_DEBUG
29974462Salfred	if (debugging) {
30074462Salfred		char *uaddr;
30174462Salfred
30274462Salfred		uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
30374462Salfred			    svc_getrpccaller(transp));
30474462Salfred		fprintf(stderr, "RPCB_GETVERSADDR rqst for (%lu, %lu, %s)"
30574462Salfred				" from %s : ",
30674462Salfred		    (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
30774462Salfred		    regp->r_netid, uaddr);
30874462Salfred		free(uaddr);
30974462Salfred	}
31074462Salfred#endif
31174462Salfred	return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
31274462Salfred					RPCB_ONEVERS));
31374462Salfred}
31474462Salfred
31574462Salfred/*
31674462Salfred * Lookup the mapping for a program, version and return the
31774462Salfred * addresses for all transports in the current transport family.
31874462Salfred * We return a merged address.
31974462Salfred */
32074462Salfred/* ARGSUSED */
32174462Salfredstatic void *
322104592Salfredrpcbproc_getaddrlist_4_local(void *arg, struct svc_req *rqstp __unused,
323104592Salfred			     SVCXPRT *transp, rpcvers_t versnum __unused)
32474462Salfred{
32574462Salfred	RPCB *regp = (RPCB *)arg;
32674462Salfred	static rpcb_entry_list_ptr rlist;
32774462Salfred	register rpcblist_ptr rbl;
32874462Salfred	rpcb_entry_list_ptr rp, tail;
32974462Salfred	rpcprog_t prog;
33074462Salfred	rpcvers_t vers;
33174462Salfred	rpcb_entry *a;
33274462Salfred	struct netconfig *nconf;
33374462Salfred	struct netconfig *reg_nconf;
33474462Salfred	char *saddr, *maddr = NULL;
33574462Salfred
33674462Salfred	free_rpcb_entry_list(&rlist);
33779718Siedowse	tail = NULL;
33874462Salfred	prog = regp->r_prog;
33974462Salfred	vers = regp->r_vers;
34074462Salfred	reg_nconf = rpcbind_get_conf(transp->xp_netid);
34174462Salfred	if (reg_nconf == NULL)
34274462Salfred		return (NULL);
34374462Salfred	if (*(regp->r_addr) != '\0') {
34474462Salfred		saddr = regp->r_addr;
34574462Salfred	} else {
34674462Salfred		saddr = NULL;
34774462Salfred	}
34874462Salfred#ifdef RPCBIND_DEBUG
34974462Salfred	if (debugging) {
35074462Salfred		fprintf(stderr, "r_addr: %s r_netid: %s nc_protofmly: %s\n",
35174462Salfred		    regp->r_addr, regp->r_netid, reg_nconf->nc_protofmly);
35274462Salfred	}
35374462Salfred#endif
35474462Salfred	for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
35574462Salfred	    if ((rbl->rpcb_map.r_prog == prog) &&
35674462Salfred		(rbl->rpcb_map.r_vers == vers)) {
35774462Salfred		nconf = rpcbind_get_conf(rbl->rpcb_map.r_netid);
35874462Salfred		if (nconf == NULL)
35974462Salfred			goto fail;
36074462Salfred		if (strcmp(nconf->nc_protofmly, reg_nconf->nc_protofmly)
36174462Salfred				!= 0) {
36274462Salfred			continue;	/* not same proto family */
36374462Salfred		}
36474462Salfred#ifdef RPCBIND_DEBUG
36574462Salfred		if (debugging)
36679718Siedowse			fprintf(stderr, "\tmerge with: %s\n",
36779718Siedowse			    rbl->rpcb_map.r_addr);
36874462Salfred#endif
36974462Salfred		if ((maddr = mergeaddr(transp, rbl->rpcb_map.r_netid,
37074462Salfred				rbl->rpcb_map.r_addr, saddr)) == NULL) {
37174462Salfred#ifdef RPCBIND_DEBUG
37274462Salfred		if (debugging)
37374462Salfred			fprintf(stderr, " FAILED\n");
37474462Salfred#endif
37574462Salfred			continue;
37674462Salfred		} else if (!maddr[0]) {
37774462Salfred#ifdef RPCBIND_DEBUG
37874462Salfred	if (debugging)
37974462Salfred		fprintf(stderr, " SUCCEEDED, but port died -  maddr: nullstring\n");
38074462Salfred#endif
38174462Salfred			/* The server died. Unset this combination */
38274462Salfred			delete_prog(regp->r_prog);
38374462Salfred			continue;
38474462Salfred		}
38574462Salfred#ifdef RPCBIND_DEBUG
38674462Salfred		if (debugging)
38774462Salfred			fprintf(stderr, " SUCCEEDED maddr: %s\n", maddr);
38874462Salfred#endif
38974462Salfred		/*
39074462Salfred		 * Add it to rlist.
39174462Salfred		 */
39296788Sjmallett		rp = malloc(sizeof (rpcb_entry_list));
39374462Salfred		if (rp == NULL)
39474462Salfred			goto fail;
39574462Salfred		a = &rp->rpcb_entry_map;
39674462Salfred		a->r_maddr = maddr;
39774462Salfred		a->r_nc_netid = nconf->nc_netid;
39874462Salfred		a->r_nc_semantics = nconf->nc_semantics;
39974462Salfred		a->r_nc_protofmly = nconf->nc_protofmly;
40074462Salfred		a->r_nc_proto = nconf->nc_proto;
40174462Salfred		rp->rpcb_entry_next = NULL;
40274462Salfred		if (rlist == NULL) {
40374462Salfred			rlist = rp;
40474462Salfred			tail = rp;
40574462Salfred		} else {
40674462Salfred			tail->rpcb_entry_next = rp;
40774462Salfred			tail = rp;
40874462Salfred		}
40974462Salfred		rp = NULL;
41074462Salfred	    }
41174462Salfred	}
41274462Salfred#ifdef RPCBIND_DEBUG
41374462Salfred	if (debugging) {
41474462Salfred		for (rp = rlist; rp; rp = rp->rpcb_entry_next) {
41574462Salfred			fprintf(stderr, "\t%s %s\n", rp->rpcb_entry_map.r_maddr,
41674462Salfred				rp->rpcb_entry_map.r_nc_proto);
41774462Salfred		}
41874462Salfred	}
41974462Salfred#endif
42074462Salfred	/*
42174462Salfred	 * XXX: getaddrlist info is also being stuffed into getaddr.
42274462Salfred	 * Perhaps wrong, but better than it not getting counted at all.
42374462Salfred	 */
42474462Salfred	rpcbs_getaddr(RPCBVERS4 - 2, prog, vers, transp->xp_netid, maddr);
42574462Salfred	return (void *)&rlist;
42674462Salfred
42774462Salfredfail:	free_rpcb_entry_list(&rlist);
42874462Salfred	return (NULL);
42974462Salfred}
43074462Salfred
43174462Salfred/*
43274462Salfred * Free only the allocated structure, rest is all a pointer to some
43374462Salfred * other data somewhere else.
43474462Salfred */
43574462Salfredstatic void
43674462Salfredfree_rpcb_entry_list(rpcb_entry_list_ptr *rlistp)
43774462Salfred{
43874462Salfred	register rpcb_entry_list_ptr rbl, tmp;
43974462Salfred
44074462Salfred	for (rbl = *rlistp; rbl != NULL; ) {
44174462Salfred		tmp = rbl;
44274462Salfred		rbl = rbl->rpcb_entry_next;
44374462Salfred		free((char *)tmp->rpcb_entry_map.r_maddr);
44474462Salfred		free((char *)tmp);
44574462Salfred	}
44674462Salfred	*rlistp = NULL;
44774462Salfred}
44874462Salfred
44974462Salfred/* ARGSUSED */
45074462Salfredstatic void *
451104592Salfredrpcbproc_dump_4_local(void *arg __unused, struct svc_req *req __unused,
452104592Salfred    		      SVCXPRT *xprt __unused, rpcvers_t versnum __unused)
45374462Salfred{
45474462Salfred	return ((void *)&list_rbl);
45574462Salfred}
456