174462Salfred/* $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ */ 274462Salfred/* $FreeBSD$ */ 374462Salfred 474462Salfred/* 574462Salfred * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 674462Salfred * unrestricted use provided that this legend is included on all tape 774462Salfred * media and as a part of the software program in whole or part. Users 874462Salfred * may copy or modify Sun RPC without charge, but are not authorized 974462Salfred * to license or distribute it to anyone else except as part of a product or 1074462Salfred * program developed by the user. 1174462Salfred * 1274462Salfred * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1374462Salfred * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1474462Salfred * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1574462Salfred * 1674462Salfred * Sun RPC is provided with no support and without any obligation on the 1774462Salfred * part of Sun Microsystems, Inc. to assist in its use, correction, 1874462Salfred * modification or enhancement. 1974462Salfred * 2074462Salfred * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2174462Salfred * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2274462Salfred * OR ANY PART THEREOF. 2374462Salfred * 2474462Salfred * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2574462Salfred * or profits or other special, indirect and consequential damages, even if 2674462Salfred * Sun has been advised of the possibility of such damages. 2774462Salfred * 2874462Salfred * Sun Microsystems, Inc. 2974462Salfred * 2550 Garcia Avenue 3074462Salfred * Mountain View, California 94043 3174462Salfred */ 3274462Salfred/* 3374462Salfred * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. 3474462Salfred */ 3574462Salfred 3674462Salfred/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */ 3774462Salfred 3874462Salfred#if 0 3974462Salfred#ifndef lint 4074462Salfredstatic char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro"; 4174462Salfred#endif 4274462Salfred#endif 4374462Salfred 4474462Salfred/* 4574462Salfred * pmap_svc.c 4674462Salfred * The server procedure for the version 2 portmaper. 4774462Salfred * All the portmapper related interface from the portmap side. 4874462Salfred */ 4974462Salfred 5074462Salfred#ifdef PORTMAP 5174462Salfred#include <sys/types.h> 5274462Salfred#include <sys/socket.h> 5374462Salfred#include <stdio.h> 5474462Salfred#include <rpc/rpc.h> 5574462Salfred#include <rpc/pmap_prot.h> 5674462Salfred#include <rpc/rpcb_prot.h> 5774462Salfred#ifdef RPCBIND_DEBUG 5874462Salfred#include <stdlib.h> 5974462Salfred#endif 6074462Salfred#include "rpcbind.h" 6174462Salfred 62173412Skevlostatic struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, 63173412Skevlo rpcprot_t); 64173412Skevlostatic bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long); 65173412Skevlostatic bool_t pmapproc_getport(struct svc_req *, SVCXPRT *); 66173412Skevlostatic bool_t pmapproc_dump(struct svc_req *, SVCXPRT *); 6774462Salfred 6874462Salfred/* 6974462Salfred * Called for all the version 2 inquiries. 7074462Salfred */ 7174462Salfredvoid 7274462Salfredpmap_service(struct svc_req *rqstp, SVCXPRT *xprt) 7374462Salfred{ 7474462Salfred rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc); 7574462Salfred switch (rqstp->rq_proc) { 7674462Salfred case PMAPPROC_NULL: 7774462Salfred /* 7874462Salfred * Null proc call 7974462Salfred */ 8074462Salfred#ifdef RPCBIND_DEBUG 8174462Salfred if (debugging) 8274462Salfred fprintf(stderr, "PMAPPROC_NULL\n"); 8374462Salfred#endif 8474462Salfred check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS); 8574462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) && 8674462Salfred debugging) { 8774462Salfred if (doabort) { 8874462Salfred rpcbind_abort(); 8974462Salfred } 9074462Salfred } 9174462Salfred break; 9274462Salfred 9374462Salfred case PMAPPROC_SET: 9474462Salfred /* 9574462Salfred * Set a program, version to port mapping 9674462Salfred */ 9774462Salfred pmapproc_change(rqstp, xprt, rqstp->rq_proc); 9874462Salfred break; 9974462Salfred 10074462Salfred case PMAPPROC_UNSET: 10174462Salfred /* 10274462Salfred * Remove a program, version to port mapping. 10374462Salfred */ 10474462Salfred pmapproc_change(rqstp, xprt, rqstp->rq_proc); 10574462Salfred break; 10674462Salfred 10774462Salfred case PMAPPROC_GETPORT: 10874462Salfred /* 10974462Salfred * Lookup the mapping for a program, version and return its 11074462Salfred * port number. 11174462Salfred */ 11274462Salfred pmapproc_getport(rqstp, xprt); 11374462Salfred break; 11474462Salfred 11574462Salfred case PMAPPROC_DUMP: 11674462Salfred /* 11774462Salfred * Return the current set of mapped program, version 11874462Salfred */ 11974462Salfred#ifdef RPCBIND_DEBUG 12074462Salfred if (debugging) 12174462Salfred fprintf(stderr, "PMAPPROC_DUMP\n"); 12274462Salfred#endif 12374462Salfred pmapproc_dump(rqstp, xprt); 12474462Salfred break; 12574462Salfred 12674462Salfred case PMAPPROC_CALLIT: 12774462Salfred /* 12874462Salfred * Calls a procedure on the local machine. If the requested 12974462Salfred * procedure is not registered this procedure does not return 13074462Salfred * error information!! 13174462Salfred * This procedure is only supported on rpc/udp and calls via 13274462Salfred * rpc/udp. It passes null authentication parameters. 13374462Salfred */ 13474462Salfred rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS); 13574462Salfred break; 13674462Salfred 13774462Salfred default: 13874462Salfred svcerr_noproc(xprt); 13974462Salfred break; 14074462Salfred } 14174462Salfred} 14274462Salfred 14374462Salfred/* 14474462Salfred * returns the item with the given program, version number. If that version 14574462Salfred * number is not found, it returns the item with that program number, so that 14674462Salfred * the port number is now returned to the caller. The caller when makes a 14774462Salfred * call to this program, version number, the call will fail and it will 14874462Salfred * return with PROGVERS_MISMATCH. The user can then determine the highest 14974462Salfred * and the lowest version number for this program using clnt_geterr() and 15074462Salfred * use those program version numbers. 15174462Salfred */ 15274462Salfredstatic struct pmaplist * 15374462Salfredfind_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot) 15474462Salfred{ 15574462Salfred register struct pmaplist *hit = NULL; 15674462Salfred register struct pmaplist *pml; 15774462Salfred 15874462Salfred for (pml = list_pml; pml != NULL; pml = pml->pml_next) { 15974462Salfred if ((pml->pml_map.pm_prog != prog) || 16074462Salfred (pml->pml_map.pm_prot != prot)) 16174462Salfred continue; 16274462Salfred hit = pml; 16374462Salfred if (pml->pml_map.pm_vers == vers) 16474462Salfred break; 16574462Salfred } 16674462Salfred return (hit); 16774462Salfred} 16874462Salfred 16974462Salfredstatic bool_t 170104592Salfredpmapproc_change(struct svc_req *rqstp __unused, SVCXPRT *xprt, unsigned long op) 17174462Salfred{ 17274462Salfred struct pmap reg; 17374462Salfred RPCB rpcbreg; 17474462Salfred long ans; 17574462Salfred struct sockaddr_in *who; 17674627Salfred uid_t uid; 17774462Salfred char uidbuf[32]; 17874462Salfred 17974462Salfred#ifdef RPCBIND_DEBUG 18074462Salfred if (debugging) 18174462Salfred fprintf(stderr, "%s request for (%lu, %lu) : ", 18274462Salfred op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET", 18374462Salfred reg.pm_prog, reg.pm_vers); 18474462Salfred#endif 18574462Salfred 18674462Salfred if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 18774462Salfred svcerr_decode(xprt); 18874462Salfred return (FALSE); 18974462Salfred } 19074462Salfred 19174462Salfred if (!check_access(xprt, op, ®, PMAPVERS)) { 19274462Salfred svcerr_weakauth(xprt); 19374462Salfred return FALSE; 19474462Salfred } 19574462Salfred 19674462Salfred who = svc_getcaller(xprt); 19774462Salfred 19874462Salfred /* 19974462Salfred * Can't use getpwnam here. We might end up calling ourselves 20074462Salfred * and looping. 20174462Salfred */ 20274627Salfred if (__rpc_get_local_uid(xprt, &uid) < 0) 20374462Salfred rpcbreg.r_owner = "unknown"; 20474627Salfred else if (uid == 0) 20574462Salfred rpcbreg.r_owner = "superuser"; 20674462Salfred else { 20774462Salfred /* r_owner will be strdup-ed later */ 20874627Salfred snprintf(uidbuf, sizeof uidbuf, "%d", uid); 20974462Salfred rpcbreg.r_owner = uidbuf; 21074462Salfred } 21174462Salfred 21274462Salfred rpcbreg.r_prog = reg.pm_prog; 21374462Salfred rpcbreg.r_vers = reg.pm_vers; 21474462Salfred 21574462Salfred if (op == PMAPPROC_SET) { 21674462Salfred char buf[32]; 21774462Salfred 21879719Siedowse snprintf(buf, sizeof buf, "0.0.0.0.%d.%d", 21979719Siedowse (int)((reg.pm_port >> 8) & 0xff), 22079719Siedowse (int)(reg.pm_port & 0xff)); 22174462Salfred rpcbreg.r_addr = buf; 22274462Salfred if (reg.pm_prot == IPPROTO_UDP) { 22374462Salfred rpcbreg.r_netid = udptrans; 22474462Salfred } else if (reg.pm_prot == IPPROTO_TCP) { 22574462Salfred rpcbreg.r_netid = tcptrans; 22674462Salfred } else { 22774462Salfred ans = FALSE; 22874462Salfred goto done_change; 22974462Salfred } 23074462Salfred ans = map_set(&rpcbreg, rpcbreg.r_owner); 23174462Salfred } else if (op == PMAPPROC_UNSET) { 23274462Salfred bool_t ans1, ans2; 23374462Salfred 23474462Salfred rpcbreg.r_addr = NULL; 23574462Salfred rpcbreg.r_netid = tcptrans; 23674462Salfred ans1 = map_unset(&rpcbreg, rpcbreg.r_owner); 23774462Salfred rpcbreg.r_netid = udptrans; 23874462Salfred ans2 = map_unset(&rpcbreg, rpcbreg.r_owner); 23974462Salfred ans = ans1 || ans2; 24074462Salfred } else { 24174462Salfred ans = FALSE; 24274462Salfred } 24374462Salfreddone_change: 24474462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) && 24574462Salfred debugging) { 24674462Salfred fprintf(stderr, "portmap: svc_sendreply\n"); 24774462Salfred if (doabort) { 24874462Salfred rpcbind_abort(); 24974462Salfred } 25074462Salfred } 25174462Salfred#ifdef RPCBIND_DEBUG 25274462Salfred if (debugging) 25374462Salfred fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed"); 25474462Salfred#endif 25574462Salfred if (op == PMAPPROC_SET) 25674462Salfred rpcbs_set(RPCBVERS_2_STAT, ans); 25774462Salfred else 25874462Salfred rpcbs_unset(RPCBVERS_2_STAT, ans); 25974462Salfred return (TRUE); 26074462Salfred} 26174462Salfred 26274462Salfred/* ARGSUSED */ 26374462Salfredstatic bool_t 264104592Salfredpmapproc_getport(struct svc_req *rqstp __unused, SVCXPRT *xprt) 26574462Salfred{ 26674462Salfred struct pmap reg; 26774462Salfred long lport; 26874462Salfred int port = 0; 26974462Salfred struct pmaplist *fnd; 27074462Salfred#ifdef RPCBIND_DEBUG 27174462Salfred char *uaddr; 27274462Salfred#endif 27374462Salfred 27474462Salfred if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) { 27574462Salfred svcerr_decode(xprt); 27674462Salfred return (FALSE); 27774462Salfred } 27874462Salfred 27974462Salfred if (!check_access(xprt, PMAPPROC_GETPORT, ®, PMAPVERS)) { 28074462Salfred svcerr_weakauth(xprt); 28174462Salfred return FALSE; 28274462Salfred } 28374462Salfred 28474462Salfred#ifdef RPCBIND_DEBUG 28574462Salfred if (debugging) { 28674462Salfred uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid), 28774462Salfred svc_getrpccaller(xprt)); 28874462Salfred fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :", 28974462Salfred reg.pm_prog, reg.pm_vers, 29074462Salfred reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr); 29174462Salfred free(uaddr); 29274462Salfred } 29374462Salfred#endif 29474462Salfred fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot); 29574462Salfred if (fnd) { 29674462Salfred char serveuaddr[32], *ua; 29774462Salfred int h1, h2, h3, h4, p1, p2; 29874462Salfred char *netid; 29974462Salfred 30074462Salfred if (reg.pm_prot == IPPROTO_UDP) { 30174462Salfred ua = udp_uaddr; 30274462Salfred netid = udptrans; 30374462Salfred } else { 30474462Salfred ua = tcp_uaddr; /* To get the len */ 30574462Salfred netid = tcptrans; 30674462Salfred } 30774462Salfred if (ua == NULL) { 30874462Salfred goto sendreply; 30974462Salfred } 31074462Salfred if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3, 31174462Salfred &h4, &p1, &p2) == 6) { 31274462Salfred p1 = (fnd->pml_map.pm_port >> 8) & 0xff; 31374462Salfred p2 = (fnd->pml_map.pm_port) & 0xff; 31479719Siedowse snprintf(serveuaddr, sizeof serveuaddr, 31579719Siedowse "%d.%d.%d.%d.%d.%d", h1, h2, h3, h4, p1, p2); 31674462Salfred if (is_bound(netid, serveuaddr)) { 31774462Salfred port = fnd->pml_map.pm_port; 31874462Salfred } else { /* this service is dead; delete it */ 31974462Salfred delete_prog(reg.pm_prog); 32074462Salfred } 32174462Salfred } 32274462Salfred } 32374462Salfredsendreply: 32474462Salfred lport = port; 32574462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) && 32674462Salfred debugging) { 32774462Salfred (void) fprintf(stderr, "portmap: svc_sendreply\n"); 32874462Salfred if (doabort) { 32974462Salfred rpcbind_abort(); 33074462Salfred } 33174462Salfred } 33274462Salfred#ifdef RPCBIND_DEBUG 33374462Salfred if (debugging) 33474462Salfred fprintf(stderr, "port = %d\n", port); 33574462Salfred#endif 33674462Salfred rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers, 33774462Salfred reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans, 33874462Salfred port ? udptrans : ""); 33974462Salfred 34074462Salfred return (TRUE); 34174462Salfred} 34274462Salfred 34374462Salfred/* ARGSUSED */ 34474462Salfredstatic bool_t 345104592Salfredpmapproc_dump(struct svc_req *rqstp __unused, SVCXPRT *xprt) 34674462Salfred{ 34774462Salfred if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) { 34874462Salfred svcerr_decode(xprt); 34974462Salfred return (FALSE); 35074462Salfred } 35174462Salfred 35274462Salfred if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) { 35374462Salfred svcerr_weakauth(xprt); 35474462Salfred return FALSE; 35574462Salfred } 35674462Salfred 35774462Salfred if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr, 35874462Salfred (caddr_t)&list_pml)) && debugging) { 35974462Salfred if (debugging) 36074462Salfred (void) fprintf(stderr, "portmap: svc_sendreply\n"); 36174462Salfred if (doabort) { 36274462Salfred rpcbind_abort(); 36374462Salfred } 36474462Salfred } 36574462Salfred return (TRUE); 36674462Salfred} 36774462Salfred 36874462Salfred#endif /* PORTMAP */ 369