1df930be7Sderaadt /*- 277baebbfSderaadt * Copyright (c) 1996 Theo de Raadt (OpenBSD). All rights reserved. 3df930be7Sderaadt * Copyright (c) 1990 The Regents of the University of California. 4df930be7Sderaadt * All rights reserved. 5df930be7Sderaadt * 6df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 7df930be7Sderaadt * modification, are permitted provided that the following conditions 8df930be7Sderaadt * are met: 9df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 10df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 11df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 12df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 13df930be7Sderaadt * documentation and/or other materials provided with the distribution. 14df930be7Sderaadt * 3. All advertising materials mentioning features or use of this software 15df930be7Sderaadt * must display the following acknowledgement: 16df930be7Sderaadt * This product includes software developed by the University of 17df930be7Sderaadt * California, Berkeley and its contributors. 18df930be7Sderaadt * 4. Neither the name of the University nor the names of its contributors 19df930be7Sderaadt * may be used to endorse or promote products derived from this software 20df930be7Sderaadt * without specific prior written permission. 21df930be7Sderaadt * 22df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32df930be7Sderaadt * SUCH DAMAGE. 33df930be7Sderaadt */ 34df930be7Sderaadt 35df930be7Sderaadt #ifndef lint 36df930be7Sderaadt char copyright[] = 37df930be7Sderaadt "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 38df930be7Sderaadt All rights reserved.\n"; 39df930be7Sderaadt #endif /* not lint */ 40df930be7Sderaadt 41df930be7Sderaadt #ifndef lint 42df930be7Sderaadt /*static char sccsid[] = "from: @(#)portmap.c 5.4 (Berkeley) 4/19/91";*/ 43*72799b18Smillert static char rcsid[] = "$Id: portmap.c,v 1.12 1997/01/15 23:44:12 millert Exp $"; 44df930be7Sderaadt #endif /* not lint */ 45df930be7Sderaadt 46df930be7Sderaadt /* 47df930be7Sderaadt @(#)portmap.c 2.3 88/08/11 4.0 RPCSRC 48df930be7Sderaadt static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro"; 49df930be7Sderaadt */ 50df930be7Sderaadt 51df930be7Sderaadt /* 52df930be7Sderaadt * portmap.c, Implements the program,version to port number mapping for 53df930be7Sderaadt * rpc. 54df930be7Sderaadt */ 55df930be7Sderaadt 56df930be7Sderaadt /* 57df930be7Sderaadt * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 58df930be7Sderaadt * unrestricted use provided that this legend is included on all tape 59df930be7Sderaadt * media and as a part of the software program in whole or part. Users 60df930be7Sderaadt * may copy or modify Sun RPC without charge, but are not authorized 61df930be7Sderaadt * to license or distribute it to anyone else except as part of a product or 62df930be7Sderaadt * program developed by the user. 63df930be7Sderaadt * 64df930be7Sderaadt * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 65df930be7Sderaadt * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 66df930be7Sderaadt * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 67df930be7Sderaadt * 68df930be7Sderaadt * Sun RPC is provided with no support and without any obligation on the 69df930be7Sderaadt * part of Sun Microsystems, Inc. to assist in its use, correction, 70df930be7Sderaadt * modification or enhancement. 71df930be7Sderaadt * 72df930be7Sderaadt * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 73df930be7Sderaadt * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 74df930be7Sderaadt * OR ANY PART THEREOF. 75df930be7Sderaadt * 76df930be7Sderaadt * In no event will Sun Microsystems, Inc. be liable for any lost revenue 77df930be7Sderaadt * or profits or other special, indirect and consequential damages, even if 78df930be7Sderaadt * Sun has been advised of the possibility of such damages. 79df930be7Sderaadt * 80df930be7Sderaadt * Sun Microsystems, Inc. 81df930be7Sderaadt * 2550 Garcia Avenue 82df930be7Sderaadt * Mountain View, California 94043 83df930be7Sderaadt */ 84df930be7Sderaadt 85df930be7Sderaadt #include <rpc/rpc.h> 86df930be7Sderaadt #include <rpc/pmap_prot.h> 87df930be7Sderaadt #include <stdio.h> 88df930be7Sderaadt #include <stdlib.h> 89df930be7Sderaadt #include <string.h> 90df930be7Sderaadt #include <syslog.h> 91df930be7Sderaadt #include <unistd.h> 92df930be7Sderaadt #include <netdb.h> 93df930be7Sderaadt #include <sys/socket.h> 94df930be7Sderaadt #include <sys/ioctl.h> 95df930be7Sderaadt #include <sys/wait.h> 96df930be7Sderaadt #include <sys/signal.h> 97df930be7Sderaadt #include <sys/resource.h> 9877baebbfSderaadt #include <rpcsvc/nfs_prot.h> 99d91d7659Sderaadt #include <arpa/inet.h> 100df930be7Sderaadt 101df930be7Sderaadt void reg_service __P((struct svc_req *, SVCXPRT *)); 102d91d7659Sderaadt void reap __P((void)); 103d91d7659Sderaadt void callit __P((struct svc_req *, SVCXPRT *)); 104d91d7659Sderaadt int check_callit __P((struct sockaddr_in *, u_long, u_long, u_long)); 105df930be7Sderaadt 106df930be7Sderaadt struct pmaplist *pmaplist; 107df930be7Sderaadt int debugging = 0; 108df930be7Sderaadt extern int errno; 109df930be7Sderaadt 11077baebbfSderaadt SVCXPRT *ludpxprt, *ltcpxprt; 11177baebbfSderaadt 112d91d7659Sderaadt int 113df930be7Sderaadt main(argc, argv) 114df930be7Sderaadt int argc; 115df930be7Sderaadt char **argv; 116df930be7Sderaadt { 117df930be7Sderaadt SVCXPRT *xprt; 11877baebbfSderaadt int sock, lsock, c; 11977baebbfSderaadt struct sockaddr_in addr, laddr; 12077baebbfSderaadt int on = 1; 121df930be7Sderaadt int len = sizeof(struct sockaddr_in); 122df930be7Sderaadt register struct pmaplist *pml; 123df930be7Sderaadt 124*72799b18Smillert while ((c = getopt(argc, argv, "d")) != -1) { 125df930be7Sderaadt switch (c) { 126df930be7Sderaadt 127df930be7Sderaadt case 'd': 128df930be7Sderaadt debugging = 1; 129df930be7Sderaadt break; 130df930be7Sderaadt 131df930be7Sderaadt default: 132df930be7Sderaadt (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]); 133df930be7Sderaadt exit(1); 134df930be7Sderaadt } 135df930be7Sderaadt } 136df930be7Sderaadt 137df930be7Sderaadt if (!debugging && daemon(0, 0)) { 138df930be7Sderaadt (void) fprintf(stderr, "portmap: fork: %s", strerror(errno)); 139df930be7Sderaadt exit(1); 140df930be7Sderaadt } 141df930be7Sderaadt 142df930be7Sderaadt openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID, 143df930be7Sderaadt LOG_DAEMON); 144df930be7Sderaadt 14577baebbfSderaadt bzero((char *)&addr, sizeof addr); 14677baebbfSderaadt addr.sin_addr.s_addr = 0; 14777baebbfSderaadt addr.sin_family = AF_INET; 14877baebbfSderaadt addr.sin_addr.s_addr = htonl(INADDR_ANY); 14977baebbfSderaadt addr.sin_port = htons(PMAPPORT); 15077baebbfSderaadt 15177baebbfSderaadt bzero((char *)&laddr, sizeof laddr); 15277baebbfSderaadt laddr.sin_addr.s_addr = 0; 15377baebbfSderaadt laddr.sin_family = AF_INET; 15477baebbfSderaadt laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 15577baebbfSderaadt laddr.sin_port = htons(PMAPPORT); 15677baebbfSderaadt 157df930be7Sderaadt if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 158df930be7Sderaadt syslog(LOG_ERR, "cannot create udp socket: %m"); 159df930be7Sderaadt exit(1); 160df930be7Sderaadt } 161afeed3b4Sderaadt setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 162df930be7Sderaadt if (bind(sock, (struct sockaddr *)&addr, len) != 0) { 163df930be7Sderaadt syslog(LOG_ERR, "cannot bind udp: %m"); 164df930be7Sderaadt exit(1); 165df930be7Sderaadt } 166df930be7Sderaadt 167df930be7Sderaadt if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { 168df930be7Sderaadt syslog(LOG_ERR, "couldn't do udp_create"); 169df930be7Sderaadt exit(1); 170df930be7Sderaadt } 17177baebbfSderaadt 17277baebbfSderaadt if ((lsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 17377baebbfSderaadt syslog(LOG_ERR, "cannot create udp socket: %m"); 17477baebbfSderaadt exit(1); 17577baebbfSderaadt } 17677baebbfSderaadt setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 17777baebbfSderaadt if (bind(lsock, (struct sockaddr *)&laddr, len) != 0) { 17877baebbfSderaadt syslog(LOG_ERR, "cannot bind udp: %m"); 17977baebbfSderaadt exit(1); 18077baebbfSderaadt } 18177baebbfSderaadt 18277baebbfSderaadt if ((ludpxprt = svcudp_create(lsock)) == (SVCXPRT *)NULL) { 18377baebbfSderaadt syslog(LOG_ERR, "couldn't do udp_create"); 18477baebbfSderaadt exit(1); 18577baebbfSderaadt } 18677baebbfSderaadt 187df930be7Sderaadt /* make an entry for ourself */ 188df930be7Sderaadt pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); 189df930be7Sderaadt pml->pml_next = 0; 190df930be7Sderaadt pml->pml_map.pm_prog = PMAPPROG; 191df930be7Sderaadt pml->pml_map.pm_vers = PMAPVERS; 192df930be7Sderaadt pml->pml_map.pm_prot = IPPROTO_UDP; 193df930be7Sderaadt pml->pml_map.pm_port = PMAPPORT; 194df930be7Sderaadt pmaplist = pml; 195df930be7Sderaadt 196df930be7Sderaadt if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 197df930be7Sderaadt syslog(LOG_ERR, "cannot create tcp socket: %m"); 198df930be7Sderaadt exit(1); 199df930be7Sderaadt } 200afeed3b4Sderaadt setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 201df930be7Sderaadt if (bind(sock, (struct sockaddr *)&addr, len) != 0) { 202da52f073Sderaadt syslog(LOG_ERR, "cannot bind tcp: %m"); 203df930be7Sderaadt exit(1); 204df930be7Sderaadt } 205df930be7Sderaadt if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) 206df930be7Sderaadt == (SVCXPRT *)NULL) { 207df930be7Sderaadt syslog(LOG_ERR, "couldn't do tcp_create"); 208df930be7Sderaadt exit(1); 209df930be7Sderaadt } 21077baebbfSderaadt 21177baebbfSderaadt if ((lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 21277baebbfSderaadt syslog(LOG_ERR, "cannot create tcp socket: %m"); 21377baebbfSderaadt exit(1); 21477baebbfSderaadt } 21577baebbfSderaadt setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 21677baebbfSderaadt if (bind(lsock, (struct sockaddr *)&laddr, len) != 0) { 217da52f073Sderaadt syslog(LOG_ERR, "cannot bind tcp: %m"); 21877baebbfSderaadt exit(1); 21977baebbfSderaadt } 22077baebbfSderaadt if ((ltcpxprt = svctcp_create(lsock, RPCSMALLMSGSIZE, 22177baebbfSderaadt RPCSMALLMSGSIZE)) == (SVCXPRT *)NULL) { 22277baebbfSderaadt syslog(LOG_ERR, "couldn't do tcp_create"); 22377baebbfSderaadt exit(1); 22477baebbfSderaadt } 22577baebbfSderaadt 226df930be7Sderaadt /* make an entry for ourself */ 227df930be7Sderaadt pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); 228df930be7Sderaadt pml->pml_map.pm_prog = PMAPPROG; 229df930be7Sderaadt pml->pml_map.pm_vers = PMAPVERS; 230df930be7Sderaadt pml->pml_map.pm_prot = IPPROTO_TCP; 231df930be7Sderaadt pml->pml_map.pm_port = PMAPPORT; 232df930be7Sderaadt pml->pml_next = pmaplist; 233df930be7Sderaadt pmaplist = pml; 234df930be7Sderaadt 235df930be7Sderaadt (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE); 236df930be7Sderaadt 237d91d7659Sderaadt (void)signal(SIGCHLD, (void (*)())reap); 238df930be7Sderaadt svc_run(); 239da52f073Sderaadt syslog(LOG_ERR, "svc_run returned unexpectedly"); 240df930be7Sderaadt abort(); 241df930be7Sderaadt } 242df930be7Sderaadt 243df930be7Sderaadt #ifndef lint 244df930be7Sderaadt /* need to override perror calls in rpc library */ 245df930be7Sderaadt void 246df930be7Sderaadt perror(what) 247df930be7Sderaadt const char *what; 248df930be7Sderaadt { 249df930be7Sderaadt 250df930be7Sderaadt syslog(LOG_ERR, "%s: %m", what); 251df930be7Sderaadt } 252df930be7Sderaadt #endif 253df930be7Sderaadt 254df930be7Sderaadt static struct pmaplist * 255df930be7Sderaadt find_service(prog, vers, prot) 256df930be7Sderaadt u_long prog, vers, prot; 257df930be7Sderaadt { 258df930be7Sderaadt register struct pmaplist *hit = NULL; 259df930be7Sderaadt register struct pmaplist *pml; 260df930be7Sderaadt 261df930be7Sderaadt for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { 262df930be7Sderaadt if ((pml->pml_map.pm_prog != prog) || 263df930be7Sderaadt (pml->pml_map.pm_prot != prot)) 264df930be7Sderaadt continue; 265df930be7Sderaadt hit = pml; 266df930be7Sderaadt if (pml->pml_map.pm_vers == vers) 267df930be7Sderaadt break; 268df930be7Sderaadt } 269df930be7Sderaadt return (hit); 270df930be7Sderaadt } 271df930be7Sderaadt 272df930be7Sderaadt /* 273df930be7Sderaadt * 1 OK, 0 not 274df930be7Sderaadt */ 275df930be7Sderaadt void 276df930be7Sderaadt reg_service(rqstp, xprt) 277df930be7Sderaadt struct svc_req *rqstp; 278df930be7Sderaadt SVCXPRT *xprt; 279df930be7Sderaadt { 280df930be7Sderaadt struct pmap reg; 281df930be7Sderaadt struct pmaplist *pml, *prevpml, *fnd; 28277baebbfSderaadt struct sockaddr_in *fromsin; 28377baebbfSderaadt long ans = 0, port; 284df930be7Sderaadt caddr_t t; 285df930be7Sderaadt 28677baebbfSderaadt fromsin = svc_getcaller(xprt); 28777baebbfSderaadt 288df930be7Sderaadt if (debugging) 289df930be7Sderaadt (void) fprintf(stderr, "server: about to do a switch\n"); 290df930be7Sderaadt switch (rqstp->rq_proc) { 291df930be7Sderaadt 292df930be7Sderaadt case PMAPPROC_NULL: 293df930be7Sderaadt /* 294df930be7Sderaadt * Null proc call 295df930be7Sderaadt */ 296df930be7Sderaadt if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) { 297df930be7Sderaadt abort(); 298df930be7Sderaadt } 299df930be7Sderaadt break; 300df930be7Sderaadt 301df930be7Sderaadt case PMAPPROC_SET: 302df930be7Sderaadt /* 303df930be7Sderaadt * Set a program,version to port mapping 304df930be7Sderaadt */ 30577baebbfSderaadt if (xprt != ltcpxprt && xprt != ludpxprt) { 30677baebbfSderaadt syslog(LOG_WARNING, 30777baebbfSderaadt "non-local set attempt (might be from %s)", 3089430a6aeSderaadt inet_ntoa(fromsin->sin_addr)); 30977baebbfSderaadt svcerr_noproc(xprt); 31077baebbfSderaadt return; 31177baebbfSderaadt } 31260cef36bSderaadt if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 313df930be7Sderaadt svcerr_decode(xprt); 31460cef36bSderaadt break; 31560cef36bSderaadt } 316df930be7Sderaadt /* 317df930be7Sderaadt * check to see if already used 318df930be7Sderaadt * find_service returns a hit even if 319df930be7Sderaadt * the versions don't match, so check for it 320df930be7Sderaadt */ 321df930be7Sderaadt fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 322df930be7Sderaadt if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) { 32377baebbfSderaadt if (fnd->pml_map.pm_port == reg.pm_port) 324df930be7Sderaadt ans = 1; 325df930be7Sderaadt goto done; 326df930be7Sderaadt } 32777baebbfSderaadt 32877baebbfSderaadt /* check if secure */ 3292afbd927Sderaadt if (fnd && (fnd->pml_map.pm_port < IPPORT_RESERVED || 3302afbd927Sderaadt fnd->pml_map.pm_port == NFS_PORT) && 33177baebbfSderaadt htons(fromsin->sin_port) >= IPPORT_RESERVED) { 33260cef36bSderaadt syslog(LOG_WARNING, "resvport set attempt by non-root"); 333df930be7Sderaadt goto done; 334df930be7Sderaadt } 33577baebbfSderaadt 336df930be7Sderaadt /* 337df930be7Sderaadt * add to END of list 338df930be7Sderaadt */ 33960cef36bSderaadt pml = (struct pmaplist *)malloc(sizeof(struct pmaplist)); 340df930be7Sderaadt pml->pml_map = reg; 341df930be7Sderaadt pml->pml_next = 0; 342df930be7Sderaadt if (pmaplist == 0) { 343df930be7Sderaadt pmaplist = pml; 344df930be7Sderaadt } else { 345df930be7Sderaadt for (fnd = pmaplist; fnd->pml_next != 0; 346df930be7Sderaadt fnd = fnd->pml_next); 347df930be7Sderaadt fnd->pml_next = pml; 348df930be7Sderaadt } 349df930be7Sderaadt ans = 1; 350df930be7Sderaadt done: 351df930be7Sderaadt if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 352df930be7Sderaadt debugging) { 353df930be7Sderaadt (void) fprintf(stderr, "svc_sendreply\n"); 354df930be7Sderaadt abort(); 355df930be7Sderaadt } 356df930be7Sderaadt break; 357df930be7Sderaadt 358df930be7Sderaadt case PMAPPROC_UNSET: 359df930be7Sderaadt /* 360df930be7Sderaadt * Remove a program,version to port mapping. 361df930be7Sderaadt */ 36277baebbfSderaadt if (xprt != ltcpxprt && xprt != ludpxprt) { 36377baebbfSderaadt syslog(LOG_WARNING, 36477baebbfSderaadt "non-local unset attempt (might be from %s)", 3659430a6aeSderaadt inet_ntoa(fromsin->sin_addr)); 36677baebbfSderaadt svcerr_noproc(xprt); 36777baebbfSderaadt return; 36877baebbfSderaadt } 36977baebbfSderaadt if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 370df930be7Sderaadt svcerr_decode(xprt); 37177baebbfSderaadt break; 37277baebbfSderaadt } 373df930be7Sderaadt for (prevpml = NULL, pml = pmaplist; pml != NULL; ) { 374df930be7Sderaadt if ((pml->pml_map.pm_prog != reg.pm_prog) || 375df930be7Sderaadt (pml->pml_map.pm_vers != reg.pm_vers)) { 376df930be7Sderaadt /* both pml & prevpml move forwards */ 377df930be7Sderaadt prevpml = pml; 378df930be7Sderaadt pml = pml->pml_next; 379df930be7Sderaadt continue; 380df930be7Sderaadt } 38177baebbfSderaadt if ((pml->pml_map.pm_port < IPPORT_RESERVED || 38277baebbfSderaadt pml->pml_map.pm_port == NFS_PORT) && 38377baebbfSderaadt htons(fromsin->sin_port) >= IPPORT_RESERVED) { 38477baebbfSderaadt syslog(LOG_WARNING, 38577baebbfSderaadt "resvport unset attempt by non-root"); 38677baebbfSderaadt break; 38777baebbfSderaadt } 38877baebbfSderaadt 389df930be7Sderaadt /* found it; pml moves forward, prevpml stays */ 390df930be7Sderaadt ans = 1; 391df930be7Sderaadt t = (caddr_t)pml; 392df930be7Sderaadt pml = pml->pml_next; 393df930be7Sderaadt if (prevpml == NULL) 394df930be7Sderaadt pmaplist = pml; 395df930be7Sderaadt else 396df930be7Sderaadt prevpml->pml_next = pml; 397df930be7Sderaadt free(t); 398df930be7Sderaadt } 399df930be7Sderaadt if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 400df930be7Sderaadt debugging) { 40160cef36bSderaadt fprintf(stderr, "svc_sendreply\n"); 402df930be7Sderaadt abort(); 403df930be7Sderaadt } 404df930be7Sderaadt break; 405df930be7Sderaadt 406df930be7Sderaadt case PMAPPROC_GETPORT: 407df930be7Sderaadt /* 408df930be7Sderaadt * Lookup the mapping for a program,version and return its port 409df930be7Sderaadt */ 41060cef36bSderaadt if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 411df930be7Sderaadt svcerr_decode(xprt); 41260cef36bSderaadt break; 41360cef36bSderaadt } 414df930be7Sderaadt fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 415df930be7Sderaadt if (fnd) 416df930be7Sderaadt port = fnd->pml_map.pm_port; 417df930be7Sderaadt else 418df930be7Sderaadt port = 0; 419df930be7Sderaadt if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) && 420df930be7Sderaadt debugging) { 42160cef36bSderaadt fprintf(stderr, "svc_sendreply\n"); 422df930be7Sderaadt abort(); 423df930be7Sderaadt } 424df930be7Sderaadt break; 425df930be7Sderaadt 426df930be7Sderaadt case PMAPPROC_DUMP: 427df930be7Sderaadt /* 428df930be7Sderaadt * Return the current set of mapped program,version 429df930be7Sderaadt */ 43060cef36bSderaadt if (!svc_getargs(xprt, xdr_void, NULL)) { 431df930be7Sderaadt svcerr_decode(xprt); 43260cef36bSderaadt break; 43360cef36bSderaadt } 43460cef36bSderaadt if (!svc_sendreply(xprt, xdr_pmaplist, (caddr_t)&pmaplist) && 43560cef36bSderaadt debugging) { 43660cef36bSderaadt fprintf(stderr, "svc_sendreply\n"); 437df930be7Sderaadt abort(); 438df930be7Sderaadt } 439df930be7Sderaadt break; 440df930be7Sderaadt 441df930be7Sderaadt case PMAPPROC_CALLIT: 442df930be7Sderaadt /* 443df930be7Sderaadt * Calls a procedure on the local machine. If the requested 444df930be7Sderaadt * procedure is not registered this procedure does not return 445df930be7Sderaadt * error information!! 446df930be7Sderaadt * This procedure is only supported on rpc/udp and calls via 447df930be7Sderaadt * rpc/udp. It passes null authentication parameters. 448df930be7Sderaadt */ 449df930be7Sderaadt callit(rqstp, xprt); 450df930be7Sderaadt break; 451df930be7Sderaadt 452df930be7Sderaadt default: 453df930be7Sderaadt svcerr_noproc(xprt); 454df930be7Sderaadt break; 455df930be7Sderaadt } 456df930be7Sderaadt } 457df930be7Sderaadt 458df930be7Sderaadt 459df930be7Sderaadt /* 460df930be7Sderaadt * Stuff for the rmtcall service 461df930be7Sderaadt */ 462df930be7Sderaadt #define ARGSIZE 9000 463df930be7Sderaadt 464df930be7Sderaadt struct encap_parms { 465df930be7Sderaadt u_int arglen; 466df930be7Sderaadt char *args; 467df930be7Sderaadt }; 468df930be7Sderaadt 469df930be7Sderaadt static bool_t 470df930be7Sderaadt xdr_encap_parms(xdrs, epp) 471df930be7Sderaadt XDR *xdrs; 472df930be7Sderaadt struct encap_parms *epp; 473df930be7Sderaadt { 474df930be7Sderaadt 475df930be7Sderaadt return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE)); 476df930be7Sderaadt } 477df930be7Sderaadt 478df930be7Sderaadt struct rmtcallargs { 479df930be7Sderaadt u_long rmt_prog; 480df930be7Sderaadt u_long rmt_vers; 481df930be7Sderaadt u_long rmt_port; 482df930be7Sderaadt u_long rmt_proc; 483df930be7Sderaadt struct encap_parms rmt_args; 484df930be7Sderaadt }; 485df930be7Sderaadt 486df930be7Sderaadt static bool_t 487df930be7Sderaadt xdr_rmtcall_args(xdrs, cap) 488df930be7Sderaadt register XDR *xdrs; 489df930be7Sderaadt register struct rmtcallargs *cap; 490df930be7Sderaadt { 491df930be7Sderaadt 492df930be7Sderaadt /* does not get a port number */ 493df930be7Sderaadt if (xdr_u_long(xdrs, &(cap->rmt_prog)) && 494df930be7Sderaadt xdr_u_long(xdrs, &(cap->rmt_vers)) && 495df930be7Sderaadt xdr_u_long(xdrs, &(cap->rmt_proc))) { 496df930be7Sderaadt return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 497df930be7Sderaadt } 498df930be7Sderaadt return (FALSE); 499df930be7Sderaadt } 500df930be7Sderaadt 501df930be7Sderaadt static bool_t 502df930be7Sderaadt xdr_rmtcall_result(xdrs, cap) 503df930be7Sderaadt register XDR *xdrs; 504df930be7Sderaadt register struct rmtcallargs *cap; 505df930be7Sderaadt { 506df930be7Sderaadt if (xdr_u_long(xdrs, &(cap->rmt_port))) 507df930be7Sderaadt return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 508df930be7Sderaadt return (FALSE); 509df930be7Sderaadt } 510df930be7Sderaadt 511df930be7Sderaadt /* 512df930be7Sderaadt * only worries about the struct encap_parms part of struct rmtcallargs. 513df930be7Sderaadt * The arglen must already be set!! 514df930be7Sderaadt */ 515df930be7Sderaadt static bool_t 516df930be7Sderaadt xdr_opaque_parms(xdrs, cap) 517df930be7Sderaadt XDR *xdrs; 518df930be7Sderaadt struct rmtcallargs *cap; 519df930be7Sderaadt { 520df930be7Sderaadt 521df930be7Sderaadt return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 522df930be7Sderaadt } 523df930be7Sderaadt 524df930be7Sderaadt /* 525df930be7Sderaadt * This routine finds and sets the length of incoming opaque paraters 526df930be7Sderaadt * and then calls xdr_opaque_parms. 527df930be7Sderaadt */ 528df930be7Sderaadt static bool_t 529df930be7Sderaadt xdr_len_opaque_parms(xdrs, cap) 530df930be7Sderaadt register XDR *xdrs; 531df930be7Sderaadt struct rmtcallargs *cap; 532df930be7Sderaadt { 533df930be7Sderaadt register u_int beginpos, lowpos, highpos, currpos, pos; 534df930be7Sderaadt 535df930be7Sderaadt beginpos = lowpos = pos = xdr_getpos(xdrs); 536df930be7Sderaadt highpos = lowpos + ARGSIZE; 537df930be7Sderaadt while ((int)(highpos - lowpos) >= 0) { 538df930be7Sderaadt currpos = (lowpos + highpos) / 2; 539df930be7Sderaadt if (xdr_setpos(xdrs, currpos)) { 540df930be7Sderaadt pos = currpos; 541df930be7Sderaadt lowpos = currpos + 1; 542df930be7Sderaadt } else { 543df930be7Sderaadt highpos = currpos - 1; 544df930be7Sderaadt } 545df930be7Sderaadt } 546df930be7Sderaadt xdr_setpos(xdrs, beginpos); 547df930be7Sderaadt cap->rmt_args.arglen = pos - beginpos; 548df930be7Sderaadt return (xdr_opaque_parms(xdrs, cap)); 549df930be7Sderaadt } 550df930be7Sderaadt 551df930be7Sderaadt /* 552df930be7Sderaadt * Call a remote procedure service 553df930be7Sderaadt * This procedure is very quiet when things go wrong. 554df930be7Sderaadt * The proc is written to support broadcast rpc. In the broadcast case, 555df930be7Sderaadt * a machine should shut-up instead of complain, less the requestor be 556df930be7Sderaadt * overrun with complaints at the expense of not hearing a valid reply ... 557df930be7Sderaadt * 558df930be7Sderaadt * This now forks so that the program & process that it calls can call 559df930be7Sderaadt * back to the portmapper. 560df930be7Sderaadt */ 561d91d7659Sderaadt void 562df930be7Sderaadt callit(rqstp, xprt) 563df930be7Sderaadt struct svc_req *rqstp; 564df930be7Sderaadt SVCXPRT *xprt; 565df930be7Sderaadt { 566df930be7Sderaadt struct rmtcallargs a; 567df930be7Sderaadt struct pmaplist *pml; 568df930be7Sderaadt u_short port; 569df930be7Sderaadt struct sockaddr_in me; 570df930be7Sderaadt int pid, so = -1, dontblock = 1; 571df930be7Sderaadt CLIENT *client; 572df930be7Sderaadt struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred; 573df930be7Sderaadt struct timeval timeout; 574df930be7Sderaadt char buf[ARGSIZE]; 575df930be7Sderaadt 576df930be7Sderaadt timeout.tv_sec = 5; 577df930be7Sderaadt timeout.tv_usec = 0; 578df930be7Sderaadt a.rmt_args.args = buf; 579df930be7Sderaadt if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a)) 580df930be7Sderaadt return; 581f94670b8Sderaadt if (!check_callit(svc_getcaller(xprt), rqstp->rq_proc, 582f94670b8Sderaadt a.rmt_prog, a.rmt_proc)) 583f94670b8Sderaadt return; 584df930be7Sderaadt if ((pml = find_service(a.rmt_prog, a.rmt_vers, 585df930be7Sderaadt (u_long)IPPROTO_UDP)) == NULL) 586df930be7Sderaadt return; 58777baebbfSderaadt 588df930be7Sderaadt /* 589df930be7Sderaadt * fork a child to do the work. Parent immediately returns. 590df930be7Sderaadt * Child exits upon completion. 591df930be7Sderaadt */ 592df930be7Sderaadt if ((pid = fork()) != 0) { 593df930be7Sderaadt if (pid == -1) 594df930be7Sderaadt syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m", 595df930be7Sderaadt a.rmt_prog); 596df930be7Sderaadt return; 597df930be7Sderaadt } 598df930be7Sderaadt port = pml->pml_map.pm_port; 599df930be7Sderaadt get_myaddress(&me); 600df930be7Sderaadt me.sin_port = htons(port); 601df930be7Sderaadt 602df930be7Sderaadt /* Avoid implicit binding to reserved port by clntudp_create() */ 603df930be7Sderaadt so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 604df930be7Sderaadt if (so == -1) 605df930be7Sderaadt exit(1); 606df930be7Sderaadt if (ioctl(so, FIONBIO, &dontblock) == -1) 607df930be7Sderaadt exit(1); 608df930be7Sderaadt 609df930be7Sderaadt client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so); 610df930be7Sderaadt if (client != (CLIENT *)NULL) { 61177baebbfSderaadt if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) 612df930be7Sderaadt client->cl_auth = authunix_create(au->aup_machname, 613df930be7Sderaadt au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); 614df930be7Sderaadt a.rmt_port = (u_long)port; 615df930be7Sderaadt if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, 61677baebbfSderaadt xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) 617df930be7Sderaadt svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); 618df930be7Sderaadt AUTH_DESTROY(client->cl_auth); 619df930be7Sderaadt clnt_destroy(client); 620df930be7Sderaadt } 621df930be7Sderaadt (void)close(so); 622df930be7Sderaadt exit(0); 623df930be7Sderaadt } 624df930be7Sderaadt 625df930be7Sderaadt void 626df930be7Sderaadt reap() 627df930be7Sderaadt { 628df930be7Sderaadt int save_errno = errno; 629df930be7Sderaadt 6307af3e1e5Sderaadt while (wait3(NULL, WNOHANG, NULL) > 0) 631df930be7Sderaadt ; 632df930be7Sderaadt errno = save_errno; 633df930be7Sderaadt } 634f94670b8Sderaadt 635f94670b8Sderaadt #define NFSPROG ((u_long) 100003) 636f94670b8Sderaadt #define MOUNTPROG ((u_long) 100005) 637f94670b8Sderaadt #define YPXPROG ((u_long) 100069) 638f94670b8Sderaadt #define YPPROG ((u_long) 100004) 639f94670b8Sderaadt #define YPPROC_DOMAIN_NONACK ((u_long) 2) 640f94670b8Sderaadt #define MOUNTPROC_MNT ((u_long) 1) 641f94670b8Sderaadt 642f94670b8Sderaadt int 643f94670b8Sderaadt check_callit(addr, proc, prog, aproc) 644f94670b8Sderaadt struct sockaddr_in *addr; 645f94670b8Sderaadt u_long proc; 646f94670b8Sderaadt u_long prog; 647f94670b8Sderaadt u_long aproc; 648f94670b8Sderaadt { 649f94670b8Sderaadt if (prog == PMAPPROG || 650f94670b8Sderaadt prog == NFSPROG || 651f94670b8Sderaadt prog == YPXPROG || 652f94670b8Sderaadt (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) || 653f94670b8Sderaadt (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) { 654f94670b8Sderaadt syslog(LOG_WARNING, 655f94670b8Sderaadt "callit prog %d aproc %d (might be from %s)", 656d91d7659Sderaadt (int)prog, (int)aproc, inet_ntoa(addr->sin_addr)); 657f94670b8Sderaadt return (FALSE); 658f94670b8Sderaadt } 659f94670b8Sderaadt return (TRUE); 660f94670b8Sderaadt } 661