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 *)®)) { 184147196Smarkus svcerr_decode(xprt); 185237493Siwasaki return (FALSE); 186237493Siwasaki } 187147196Smarkus 188147196Smarkus if (!check_access(xprt, op, ®, 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 *)®)) { 273148710Smarkus svcerr_decode(xprt); 274147196Smarkus return (FALSE); 275147196Smarkus } 276147196Smarkus 277147196Smarkus if (!check_access(xprt, PMAPPROC_GETPORT, ®, 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