1138627Stakawata/*	$NetBSD: pmap_svc.c,v 1.2 2013/10/19 17:45:00 christos Exp $	*/
2138627Stakawata
3147196Smarkus/*
4138627Stakawata * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5138627Stakawata * unrestricted use provided that this legend is included on all tape
6138627Stakawata * media and as a part of the software program in whole or part.  Users
7138627Stakawata * may copy or modify Sun RPC without charge, but are not authorized
8138627Stakawata * to license or distribute it to anyone else except as part of a product or
9138627Stakawata * program developed by the user.
10138627Stakawata *
11138627Stakawata * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12138627Stakawata * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13138627Stakawata * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14138627Stakawata *
15138627Stakawata * Sun RPC is provided with no support and without any obligation on the
16138627Stakawata * part of Sun Microsystems, Inc. to assist in its use, correction,
17138627Stakawata * modification or enhancement.
18138627Stakawata *
19138627Stakawata * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20138627Stakawata * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21138627Stakawata * OR ANY PART THEREOF.
22138627Stakawata *
23138627Stakawata * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24138627Stakawata * or profits or other special, indirect and consequential damages, even if
25138627Stakawata * Sun has been advised of the possibility of such damages.
26138627Stakawata *
27138627Stakawata * Sun Microsystems, Inc.
28143002Sobrien * 2550 Garcia Avenue
29143002Sobrien * Mountain View, California  94043
30143002Sobrien */
31147196Smarkus/*
32147196Smarkus * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
33147196Smarkus */
34147196Smarkus
35147196Smarkus/* #ident	"@(#)pmap_svc.c	1.14	93/07/05 SMI" */
36147196Smarkus
37147196Smarkus#if 0
38147196Smarkus#ifndef lint
39147196Smarkusstatic	char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro";
40138627Stakawata#endif
41138627Stakawata#endif
42138627Stakawata
43138627Stakawata/*
44138627Stakawata * pmap_svc.c
45193530Sjkim * The server procedure for the version 2 portmapper.
46193530Sjkim * All the portmapper related interface from the portmap side.
47193530Sjkim */
48193530Sjkim
49138627Stakawata#ifdef PORTMAP
50138627Stakawata#include <sys/types.h>
51138627Stakawata#include <sys/socket.h>
52147196Smarkus#include <stdio.h>
53237493Siwasaki#include <rpc/rpc.h>
54237493Siwasaki#include <rpc/pmap_prot.h>
55138627Stakawata#include <rpc/rpcb_prot.h>
56178193Sphk#ifdef RPCBIND_DEBUG
57138627Stakawata#include <stdlib.h>
58138825Snjl#endif
59138774Sscottl#include "rpcbind.h"
60138774Sscottl
61147196Smarkusstatic struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, rpcprot_t);
62147196Smarkusstatic bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long);
63147196Smarkusstatic bool_t pmapproc_getport(struct svc_req *, SVCXPRT *);
64147196Smarkusstatic bool_t pmapproc_dump(struct svc_req *, SVCXPRT *);
65147196Smarkus
66147196Smarkus/*
67147196Smarkus * Called for all the version 2 inquiries.
68147196Smarkus */
69147196Smarkusvoid
70147196Smarkuspmap_service(struct svc_req *rqstp, SVCXPRT *xprt)
71147196Smarkus{
72154326Smarkus	rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc);
73154326Smarkus	switch (rqstp->rq_proc) {
74154326Smarkus	case PMAPPROC_NULL:
75237493Siwasaki		/*
76138627Stakawata		 * Null proc call
77147196Smarkus		 */
78147196Smarkus#ifdef RPCBIND_DEBUG
79147196Smarkus		if (debugging)
80147196Smarkus			fprintf(stderr, "PMAPPROC_NULL\n");
81147196Smarkus#endif
82147196Smarkus		check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS);
83147196Smarkus		if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) &&
84147196Smarkus			debugging) {
85147196Smarkus			if (doabort) {
86147196Smarkus				rpcbind_abort();
87147196Smarkus			}
88147196Smarkus		}
89147196Smarkus		break;
90147196Smarkus
91147196Smarkus	case PMAPPROC_SET:
92147196Smarkus		/*
93147196Smarkus		 * Set a program, version to port mapping
94147196Smarkus		 */
95147196Smarkus		pmapproc_change(rqstp, xprt, rqstp->rq_proc);
96138627Stakawata		break;
97147196Smarkus
98147196Smarkus	case PMAPPROC_UNSET:
99147196Smarkus		/*
100147196Smarkus		 * Remove a program, version to port mapping.
101147196Smarkus		 */
102147196Smarkus		pmapproc_change(rqstp, xprt, rqstp->rq_proc);
103147196Smarkus		break;
104154326Smarkus
105154326Smarkus	case PMAPPROC_GETPORT:
106147196Smarkus		/*
107147196Smarkus		 * Lookup the mapping for a program, version and return its
108147196Smarkus		 * port number.
109147196Smarkus		 */
110147196Smarkus		pmapproc_getport(rqstp, xprt);
111147196Smarkus		break;
112147196Smarkus
113147196Smarkus	case PMAPPROC_DUMP:
114147196Smarkus		/*
115147196Smarkus		 * Return the current set of mapped program, version
116147196Smarkus		 */
117147196Smarkus#ifdef RPCBIND_DEBUG
118147196Smarkus		if (debugging)
119147196Smarkus			fprintf(stderr, "PMAPPROC_DUMP\n");
120147196Smarkus#endif
121147196Smarkus		pmapproc_dump(rqstp, xprt);
122147196Smarkus		break;
123147196Smarkus
124147196Smarkus	case PMAPPROC_CALLIT:
125147196Smarkus		/*
126147196Smarkus		 * Calls a procedure on the local machine. If the requested
127147196Smarkus		 * procedure is not registered this procedure does not return
128147196Smarkus		 * error information!!
129147196Smarkus		 * This procedure is only supported on rpc/udp and calls via
130147196Smarkus		 * rpc/udp. It passes null authentication parameters.
131147196Smarkus		 */
132237493Siwasaki		rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS);
133237493Siwasaki		break;
134237493Siwasaki
135237493Siwasaki	default:
136237493Siwasaki		svcerr_noproc(xprt);
137237493Siwasaki		break;
138237493Siwasaki	}
139237493Siwasaki}
140237493Siwasaki
141237493Siwasaki/*
142237493Siwasaki * returns the item with the given program, version number. If that version
143237493Siwasaki * number is not found, it returns the item with that program number, so that
144237493Siwasaki * the port number is now returned to the caller. The caller when makes a
145237493Siwasaki * call to this program, version number, the call will fail and it will
146237493Siwasaki * return with PROGVERS_MISMATCH. The user can then determine the highest
147147196Smarkus * and the lowest version number for this program using clnt_geterr() and
148147196Smarkus * use those program version numbers.
149138627Stakawata */
150147196Smarkusstatic struct pmaplist *
151147196Smarkusfind_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
152147196Smarkus{
153147196Smarkus	register struct pmaplist *hit = NULL;
154147196Smarkus	register struct pmaplist *pml;
155147196Smarkus
156147196Smarkus	for (pml = list_pml; pml != NULL; pml = pml->pml_next) {
157147196Smarkus		if ((pml->pml_map.pm_prog != prog) ||
158147196Smarkus			(pml->pml_map.pm_prot != prot))
159147196Smarkus			continue;
160147196Smarkus		hit = pml;
161147196Smarkus		if (pml->pml_map.pm_vers == vers)
162147196Smarkus			break;
163147196Smarkus	}
164147196Smarkus	return (hit);
165147196Smarkus}
166147196Smarkus
167147196Smarkusstatic bool_t
168147196Smarkuspmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op)
169147196Smarkus{
170147196Smarkus	struct pmap reg;
171148710Smarkus	RPCB rpcbreg;
172148710Smarkus	long ans;
173147196Smarkus	struct sockcred *sc;
174148710Smarkus	char uidbuf[32];
175148710Smarkus
176147196Smarkus#ifdef RPCBIND_DEBUG
177147196Smarkus	if (debugging)
178147196Smarkus		fprintf(stderr, "%s request for (%lu, %lu) : ",
179147196Smarkus		    op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET",
180147196Smarkus		    reg.pm_prog, reg.pm_vers);
181147196Smarkus#endif
182147196Smarkus
183147196Smarkus	if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)&reg)) {
184147196Smarkus		svcerr_decode(xprt);
185237493Siwasaki		return (FALSE);
186237493Siwasaki	}
187147196Smarkus
188147196Smarkus	if (!check_access(xprt, op, &reg, PMAPVERS)) {
189138627Stakawata		svcerr_weakauth(xprt);
190138627Stakawata		return FALSE;
191147196Smarkus	}
192147196Smarkus
193147196Smarkus	(void)svc_getcaller(xprt);
194147196Smarkus	sc = __svc_getcallercreds(xprt);
195273377Shselasky
196147196Smarkus	/*
197147196Smarkus	 * Can't use getpwnam here. We might end up calling ourselves
198147196Smarkus	 * and looping.
199147196Smarkus	 */
200147196Smarkus	if (sc == NULL)
201147196Smarkus		rpcbreg.r_owner = __UNCONST(rpcbind_unknown);
202147196Smarkus	else if (sc->sc_uid == 0)
203147196Smarkus		rpcbreg.r_owner = __UNCONST(rpcbind_superuser);
204147196Smarkus	else {
205147196Smarkus		/* r_owner will be strdup-ed later */
206147196Smarkus		snprintf(uidbuf, sizeof uidbuf, "%d", sc->sc_uid);
207147196Smarkus		rpcbreg.r_owner = uidbuf;
208147196Smarkus	}
209147196Smarkus
210147196Smarkus	rpcbreg.r_prog = reg.pm_prog;
211273377Shselasky	rpcbreg.r_vers = reg.pm_vers;
212147196Smarkus
213147196Smarkus	if (op == PMAPPROC_SET) {
214147196Smarkus		char buf[32];
215147196Smarkus
216147196Smarkus		snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d",
217147196Smarkus		    (int)((reg.pm_port >> 8) & 0xff),
218147196Smarkus		    (int)(reg.pm_port & 0xff));
219147196Smarkus		rpcbreg.r_addr = buf;
220147196Smarkus		if (reg.pm_prot == IPPROTO_UDP) {
221147196Smarkus			rpcbreg.r_netid = __UNCONST(udptrans);
222147196Smarkus		} else if (reg.pm_prot == IPPROTO_TCP) {
223147196Smarkus			rpcbreg.r_netid = __UNCONST(tcptrans);
224147196Smarkus		} else {
225147196Smarkus			ans = FALSE;
226147196Smarkus			goto done_change;
227147196Smarkus		}
228147196Smarkus		ans = map_set(&rpcbreg, rpcbreg.r_owner);
229147196Smarkus	} else if (op == PMAPPROC_UNSET) {
230147196Smarkus		bool_t ans1, ans2;
231147196Smarkus
232147196Smarkus		rpcbreg.r_addr = NULL;
233147196Smarkus		rpcbreg.r_netid = __UNCONST(tcptrans);
234147196Smarkus		ans1 = map_unset(&rpcbreg, rpcbreg.r_owner);
235147196Smarkus		rpcbreg.r_netid = __UNCONST(udptrans);
236147196Smarkus		ans2 = map_unset(&rpcbreg, rpcbreg.r_owner);
237147196Smarkus		ans = ans1 || ans2;
238147196Smarkus	} else {
239147196Smarkus		ans = FALSE;
240147196Smarkus	}
241147196Smarkusdone_change:
242273377Shselasky	if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) &&
243147196Smarkus	    debugging) {
244147196Smarkus		fprintf(stderr, "portmap: svc_sendreply\n");
245147196Smarkus		if (doabort) {
246147196Smarkus			rpcbind_abort();
247147196Smarkus		}
248273377Shselasky	}
249147196Smarkus#ifdef RPCBIND_DEBUG
250147196Smarkus	if (debugging)
251154326Smarkus		fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
252154326Smarkus#endif
253154326Smarkus	if (op == PMAPPROC_SET)
254154326Smarkus		rpcbs_set(RPCBVERS_2_STAT, ans);
255154326Smarkus	else
256147196Smarkus		rpcbs_unset(RPCBVERS_2_STAT, ans);
257147196Smarkus	return (TRUE);
258147196Smarkus}
259147196Smarkus
260147196Smarkus/* ARGSUSED */
261147196Smarkusstatic bool_t
262147196Smarkuspmapproc_getport(struct svc_req *rqstp, SVCXPRT *xprt)
263147196Smarkus{
264147196Smarkus	struct pmap reg;
265147196Smarkus	long lport;
266138627Stakawata	int port = 0;
267138627Stakawata	struct pmaplist *fnd;
268138627Stakawata#ifdef RPCBIND_DEBUG
269201605Siwasaki	char *uaddr;
270138627Stakawata#endif
271148710Smarkus
272148710Smarkus	if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)&reg)) {
273148710Smarkus		svcerr_decode(xprt);
274147196Smarkus		return (FALSE);
275147196Smarkus	}
276147196Smarkus
277147196Smarkus	if (!check_access(xprt, PMAPPROC_GETPORT, &reg, PMAPVERS)) {
278147196Smarkus		svcerr_weakauth(xprt);
279147196Smarkus		return FALSE;
280147196Smarkus	}
281237493Siwasaki
282147196Smarkus#ifdef RPCBIND_DEBUG
283147196Smarkus	if (debugging) {
284237493Siwasaki		uaddr =  taddr2uaddr(rpcbind_get_conf(xprt->xp_netid),
285237493Siwasaki			    svc_getrpccaller(xprt));
286237493Siwasaki		fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :",
287237493Siwasaki			reg.pm_prog, reg.pm_vers,
288237493Siwasaki			reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr);
289237493Siwasaki		free(uaddr);
290138627Stakawata	}
291138627Stakawata#endif
292138627Stakawata	fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot);
293138627Stakawata	if (fnd) {
294138627Stakawata		char serveuaddr[32];
295201605Siwasaki		int h1, h2, h3, h4, p1, p2;
296138627Stakawata		const char *netid, *ua;
297246128Ssbz
298138627Stakawata		if (reg.pm_prot == IPPROTO_UDP) {
299138627Stakawata			ua = udp_uaddr;
300138627Stakawata			netid = udptrans;
301138627Stakawata		} else {
302138627Stakawata			ua = tcp_uaddr; /* To get the len */
303138627Stakawata			netid = tcptrans;
304138627Stakawata		}
305138627Stakawata		if (ua == NULL) {
306138627Stakawata			goto sendreply;
307138627Stakawata		}
308138627Stakawata		if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3,
309138627Stakawata				&h4, &p1, &p2) == 6) {
310138627Stakawata			p1 = (fnd->pml_map.pm_port >> 8) & 0xff;
311242305Sbapt			p2 = (fnd->pml_map.pm_port) & 0xff;
312138627Stakawata			snprintf(serveuaddr, sizeof(serveuaddr),
313147196Smarkus			    "%d.%d.%d.%d.%d.%d", h1, h2, h3, h4, p1, p2);
314147196Smarkus			if (is_bound(netid, serveuaddr)) {
315147196Smarkus				port = fnd->pml_map.pm_port;
316148710Smarkus			} else { /* this service is dead; delete it */
317148710Smarkus				delete_prog(reg.pm_prog);
318148710Smarkus			}
319148710Smarkus		}
320148710Smarkus	}
321148710Smarkussendreply:
322148710Smarkus	lport = port;
323148710Smarkus	if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) &&
324148710Smarkus			debugging) {
325148710Smarkus		(void) fprintf(stderr, "portmap: svc_sendreply\n");
326167814Sjkim		if (doabort) {
327148710Smarkus			rpcbind_abort();
328148710Smarkus		}
329148710Smarkus	}
330148710Smarkus#ifdef RPCBIND_DEBUG
331148710Smarkus	if (debugging)
332148710Smarkus		fprintf(stderr, "port = %d\n", port);
333148710Smarkus#endif
334147196Smarkus	rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers,
335148710Smarkus		reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans,
336147196Smarkus		port ? udptrans : "");
337148710Smarkus
338148710Smarkus	return (TRUE);
339147196Smarkus}
340147196Smarkus
341138627Stakawata/* ARGSUSED */
342138627Stakawatastatic bool_t
343138627Stakawatapmapproc_dump(struct svc_req *rqstp, SVCXPRT *xprt)
344147196Smarkus{
345147196Smarkus	if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) {
346147196Smarkus		svcerr_decode(xprt);
347147196Smarkus		return (FALSE);
348138627Stakawata	}
349147196Smarkus
350138627Stakawata	if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) {
351147196Smarkus		svcerr_weakauth(xprt);
352138627Stakawata		return FALSE;
353138627Stakawata	}
354138627Stakawata
355147196Smarkus	if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr,
356138627Stakawata			(caddr_t)&list_pml)) && debugging) {
357147196Smarkus		if (debugging)
358147196Smarkus			(void) fprintf(stderr, "portmap: svc_sendreply\n");
359138627Stakawata		if (doabort) {
360138627Stakawata			rpcbind_abort();
361138627Stakawata		}
362138627Stakawata	}
363147196Smarkus	return (TRUE);
364147196Smarkus}
365147196Smarkus
366147196Smarkus#endif /* PORTMAP */
367147196Smarkus