1 /* $OpenBSD: portmap.c,v 1.37 2009/05/20 20:37:43 thib Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997 Theo de Raadt (OpenBSD). All rights reserved. 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 char copyright[] = 35 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 36 All rights reserved.\n"; 37 #endif /* not lint */ 38 39 #ifndef lint 40 #if 0 41 static char sccsid[] = "from: @(#)portmap.c 5.4 (Berkeley) 4/19/91"; 42 #else 43 static char rcsid[] = "$OpenBSD: portmap.c,v 1.37 2009/05/20 20:37:43 thib Exp $"; 44 #endif 45 #endif /* not lint */ 46 47 /* 48 @(#)portmap.c 2.3 88/08/11 4.0 RPCSRC 49 static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro"; 50 */ 51 52 /* 53 * portmap.c, Implements the program,version to port number mapping for 54 * rpc. 55 */ 56 57 /* 58 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 59 * unrestricted use provided that this legend is included on all tape 60 * media and as a part of the software program in whole or part. Users 61 * may copy or modify Sun RPC without charge, but are not authorized 62 * to license or distribute it to anyone else except as part of a product or 63 * program developed by the user. 64 * 65 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 66 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 67 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 68 * 69 * Sun RPC is provided with no support and without any obligation on the 70 * part of Sun Microsystems, Inc. to assist in its use, correction, 71 * modification or enhancement. 72 * 73 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 74 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 75 * OR ANY PART THEREOF. 76 * 77 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 78 * or profits or other special, indirect and consequential damages, even if 79 * Sun has been advised of the possibility of such damages. 80 * 81 * Sun Microsystems, Inc. 82 * 2550 Garcia Avenue 83 * Mountain View, California 94043 84 */ 85 86 #include <sys/types.h> 87 #include <sys/socket.h> 88 #include <sys/ioctl.h> 89 #include <sys/wait.h> 90 #include <sys/resource.h> 91 92 #include <rpcsvc/nfs_prot.h> 93 #include <arpa/inet.h> 94 #include <rpc/rpc.h> 95 #include <rpc/pmap_prot.h> 96 97 #include <signal.h> 98 #include <stdio.h> 99 #include <stdlib.h> 100 #include <string.h> 101 #include <syslog.h> 102 #include <unistd.h> 103 #include <netdb.h> 104 #include <pwd.h> 105 #include <errno.h> 106 107 void reg_service(struct svc_req *, SVCXPRT *); 108 void reap(int); 109 void callit(struct svc_req *, SVCXPRT *); 110 int check_callit(struct sockaddr_in *, u_long, u_long); 111 struct pmaplist *find_service(u_long, u_long, u_long); 112 113 struct pmaplist *pmaplist; 114 int debugging = 0; 115 116 SVCXPRT *ludpxprt, *ltcpxprt; 117 118 int 119 main(int argc, char *argv[]) 120 { 121 int sock, lsock, c, on = 1, len = sizeof(struct sockaddr_in); 122 struct sockaddr_in addr, laddr; 123 struct pmaplist *pml; 124 struct passwd *pw; 125 SVCXPRT *xprt; 126 127 while ((c = getopt(argc, argv, "d")) != -1) { 128 switch (c) { 129 130 case 'd': 131 debugging = 1; 132 break; 133 134 default: 135 (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]); 136 exit(1); 137 } 138 } 139 140 if (!debugging && daemon(0, 0)) { 141 (void) fprintf(stderr, "portmap: fork: %s", strerror(errno)); 142 exit(1); 143 } 144 145 openlog("portmap", LOG_NDELAY | (debugging ? LOG_PID | LOG_PERROR : LOG_PID), 146 LOG_DAEMON); 147 148 bzero((char *)&addr, sizeof addr); 149 addr.sin_addr.s_addr = 0; 150 addr.sin_family = AF_INET; 151 addr.sin_addr.s_addr = htonl(INADDR_ANY); 152 addr.sin_port = htons(PMAPPORT); 153 154 bzero((char *)&laddr, sizeof laddr); 155 laddr.sin_addr.s_addr = 0; 156 laddr.sin_family = AF_INET; 157 laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 158 laddr.sin_port = htons(PMAPPORT); 159 160 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 161 syslog(LOG_ERR, "cannot create udp socket: %m"); 162 exit(1); 163 } 164 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 165 if (bind(sock, (struct sockaddr *)&addr, len) != 0) { 166 syslog(LOG_ERR, "cannot bind udp: %m"); 167 exit(1); 168 } 169 170 if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { 171 syslog(LOG_ERR, "couldn't do udp_create"); 172 exit(1); 173 } 174 175 if ((lsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 176 syslog(LOG_ERR, "cannot create udp socket: %m"); 177 exit(1); 178 } 179 setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 180 if (bind(lsock, (struct sockaddr *)&laddr, len) != 0) { 181 syslog(LOG_ERR, "cannot bind local udp: %m"); 182 exit(1); 183 } 184 185 if ((ludpxprt = svcudp_create(lsock)) == (SVCXPRT *)NULL) { 186 syslog(LOG_ERR, "couldn't do udp_create"); 187 exit(1); 188 } 189 190 /* make an entry for ourself */ 191 pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); 192 if (pml == NULL) { 193 syslog(LOG_ERR, "out of memory"); 194 exit(1); 195 } 196 pml->pml_next = 0; 197 pml->pml_map.pm_prog = PMAPPROG; 198 pml->pml_map.pm_vers = PMAPVERS; 199 pml->pml_map.pm_prot = IPPROTO_UDP; 200 pml->pml_map.pm_port = PMAPPORT; 201 pmaplist = pml; 202 203 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 204 syslog(LOG_ERR, "cannot create tcp socket: %m"); 205 exit(1); 206 } 207 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 208 if (bind(sock, (struct sockaddr *)&addr, len) != 0) { 209 syslog(LOG_ERR, "cannot bind tcp: %m"); 210 exit(1); 211 } 212 if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) 213 == (SVCXPRT *)NULL) { 214 syslog(LOG_ERR, "couldn't do tcp_create"); 215 exit(1); 216 } 217 218 if ((lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 219 syslog(LOG_ERR, "cannot create tcp socket: %m"); 220 exit(1); 221 } 222 setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 223 if (bind(lsock, (struct sockaddr *)&laddr, len) != 0) { 224 syslog(LOG_ERR, "cannot bind tcp: %m"); 225 exit(1); 226 } 227 if ((ltcpxprt = svctcp_create(lsock, RPCSMALLMSGSIZE, 228 RPCSMALLMSGSIZE)) == (SVCXPRT *)NULL) { 229 syslog(LOG_ERR, "couldn't do tcp_create"); 230 exit(1); 231 } 232 233 /* make an entry for ourself */ 234 pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); 235 if (pml == NULL) { 236 syslog(LOG_ERR, "out of memory"); 237 exit(1); 238 } 239 pml->pml_map.pm_prog = PMAPPROG; 240 pml->pml_map.pm_vers = PMAPVERS; 241 pml->pml_map.pm_prot = IPPROTO_TCP; 242 pml->pml_map.pm_port = PMAPPORT; 243 pml->pml_next = pmaplist; 244 pmaplist = pml; 245 246 247 if ((pw = getpwnam("_portmap")) == NULL) { 248 syslog(LOG_ERR, "no such user _portmap"); 249 exit(1); 250 } 251 if (chroot("/var/empty") == -1) { 252 syslog(LOG_ERR, "cannot chdir to /var/empty."); 253 exit(1); 254 } 255 256 chdir("/"); 257 if (pw) { 258 if (setgroups(1, &pw->pw_gid) == -1 || 259 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 || 260 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { 261 syslog(LOG_ERR, "revoke privs: %s", strerror(errno)); 262 exit(1); 263 } 264 } 265 endpwent(); 266 267 if (svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE) == 0) { 268 syslog(LOG_ERR, "svc_register failed."); 269 exit(1); 270 } 271 272 (void)signal(SIGCHLD, reap); 273 svc_run(); 274 syslog(LOG_ERR, "svc_run returned unexpectedly"); 275 abort(); 276 } 277 278 #ifndef lint 279 /* need to override perror calls in rpc library */ 280 void 281 perror(const char *what) 282 { 283 284 syslog(LOG_ERR, "%s: %m", what); 285 } 286 #endif 287 288 struct pmaplist * 289 find_service(u_long prog, u_long vers, u_long prot) 290 { 291 struct pmaplist *hit = NULL; 292 struct pmaplist *pml; 293 294 for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { 295 if ((pml->pml_map.pm_prog != prog) || 296 (pml->pml_map.pm_prot != prot)) 297 continue; 298 hit = pml; 299 if (pml->pml_map.pm_vers == vers) 300 break; 301 } 302 return (hit); 303 } 304 305 /* 306 * 1 OK, 0 not 307 */ 308 void 309 reg_service(struct svc_req *rqstp, SVCXPRT *xprt) 310 { 311 struct pmap reg; 312 struct pmaplist *pml, *prevpml, *fnd; 313 struct sockaddr_in *fromsin; 314 long ans = 0, port; 315 caddr_t t; 316 317 fromsin = svc_getcaller(xprt); 318 319 if (debugging) 320 (void) fprintf(stderr, "server: about to do a switch\n"); 321 switch (rqstp->rq_proc) { 322 323 case PMAPPROC_NULL: 324 /* 325 * Null proc call 326 */ 327 if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) { 328 abort(); 329 } 330 break; 331 332 case PMAPPROC_SET: 333 /* 334 * Set a program,version to port mapping 335 */ 336 if (xprt != ltcpxprt && xprt != ludpxprt) { 337 syslog(LOG_WARNING, 338 "non-local set attempt (might be from %s)", 339 inet_ntoa(fromsin->sin_addr)); 340 svcerr_noproc(xprt); 341 return; 342 } 343 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 344 svcerr_decode(xprt); 345 break; 346 } 347 348 /* 349 * check to see if already used 350 * find_service returns a hit even if 351 * the versions don't match, so check for it 352 */ 353 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 354 if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) { 355 if (fnd->pml_map.pm_port == reg.pm_port) 356 ans = 1; 357 goto done; 358 } 359 360 if (debugging) 361 printf("set: prog %lu vers %lu port %lu\n", 362 reg.pm_prog, reg.pm_vers, reg.pm_port); 363 364 if (reg.pm_port & ~0xffff) 365 goto done; 366 367 /* 368 * only permit localhost root to create 369 * mappings pointing at sensitive ports 370 */ 371 if ((reg.pm_port < IPPORT_RESERVED || 372 reg.pm_port == NFS_PORT) && 373 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 374 syslog(LOG_WARNING, 375 "resvport set attempt by non-root"); 376 goto done; 377 } 378 379 /* 380 * add to END of list 381 */ 382 pml = (struct pmaplist *)malloc(sizeof(struct pmaplist)); 383 if (pml == NULL) { 384 syslog(LOG_ERR, "out of memory"); 385 svcerr_systemerr(xprt); 386 return; 387 } 388 389 pml->pml_map = reg; 390 pml->pml_next = 0; 391 if (pmaplist == 0) { 392 pmaplist = pml; 393 } else { 394 for (fnd = pmaplist; fnd->pml_next != 0; 395 fnd = fnd->pml_next); 396 fnd->pml_next = pml; 397 } 398 ans = 1; 399 done: 400 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 401 debugging) { 402 (void) fprintf(stderr, "svc_sendreply\n"); 403 abort(); 404 } 405 break; 406 407 case PMAPPROC_UNSET: 408 /* 409 * Remove a program,version to port mapping. 410 */ 411 if (xprt != ltcpxprt && xprt != ludpxprt) { 412 syslog(LOG_WARNING, 413 "non-local unset attempt (might be from %s)", 414 inet_ntoa(fromsin->sin_addr)); 415 svcerr_noproc(xprt); 416 return; 417 } 418 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 419 svcerr_decode(xprt); 420 break; 421 } 422 for (prevpml = NULL, pml = pmaplist; pml != NULL; ) { 423 if ((pml->pml_map.pm_prog != reg.pm_prog) || 424 (pml->pml_map.pm_vers != reg.pm_vers)) { 425 /* both pml & prevpml move forwards */ 426 prevpml = pml; 427 pml = pml->pml_next; 428 continue; 429 } 430 if ((pml->pml_map.pm_port < IPPORT_RESERVED || 431 pml->pml_map.pm_port == NFS_PORT) && 432 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 433 syslog(LOG_WARNING, 434 "resvport unset attempt by non-root"); 435 break; 436 } 437 438 /* found it; pml moves forward, prevpml stays */ 439 ans = 1; 440 t = (caddr_t)pml; 441 pml = pml->pml_next; 442 if (prevpml == NULL) 443 pmaplist = pml; 444 else 445 prevpml->pml_next = pml; 446 free(t); 447 } 448 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 449 debugging) { 450 fprintf(stderr, "svc_sendreply\n"); 451 abort(); 452 } 453 break; 454 455 case PMAPPROC_GETPORT: 456 /* 457 * Lookup the mapping for a program,version and return its port 458 */ 459 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 460 svcerr_decode(xprt); 461 break; 462 } 463 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 464 if (fnd) 465 port = fnd->pml_map.pm_port; 466 else 467 port = 0; 468 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) && 469 debugging) { 470 fprintf(stderr, "svc_sendreply\n"); 471 abort(); 472 } 473 break; 474 475 case PMAPPROC_DUMP: 476 /* 477 * Return the current set of mapped program,version 478 */ 479 if (!svc_getargs(xprt, xdr_void, NULL)) { 480 svcerr_decode(xprt); 481 break; 482 } 483 if (!svc_sendreply(xprt, xdr_pmaplist, (caddr_t)&pmaplist) && 484 debugging) { 485 fprintf(stderr, "svc_sendreply\n"); 486 abort(); 487 } 488 break; 489 490 case PMAPPROC_CALLIT: 491 /* 492 * Calls a procedure on the local machine. If the requested 493 * procedure is not registered this procedure does not return 494 * error information!! 495 * This procedure is only supported on rpc/udp and calls via 496 * rpc/udp. It passes null authentication parameters. 497 */ 498 callit(rqstp, xprt); 499 break; 500 501 default: 502 svcerr_noproc(xprt); 503 break; 504 } 505 } 506 507 508 /* 509 * Stuff for the rmtcall service 510 */ 511 #define ARGSIZE 9000 512 513 struct encap_parms { 514 u_int arglen; 515 char *args; 516 }; 517 518 static bool_t 519 xdr_encap_parms(XDR *xdrs, struct encap_parms *epp) 520 { 521 522 return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE)); 523 } 524 525 struct rmtcallargs { 526 u_long rmt_prog; 527 u_long rmt_vers; 528 u_long rmt_port; 529 u_long rmt_proc; 530 struct encap_parms rmt_args; 531 }; 532 533 static bool_t 534 xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 535 { 536 537 /* does not get a port number */ 538 if (xdr_u_long(xdrs, &(cap->rmt_prog)) && 539 xdr_u_long(xdrs, &(cap->rmt_vers)) && 540 xdr_u_long(xdrs, &(cap->rmt_proc))) { 541 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 542 } 543 return (FALSE); 544 } 545 546 static bool_t 547 xdr_rmtcall_result(XDR *xdrs, struct rmtcallargs *cap) 548 { 549 if (xdr_u_long(xdrs, &(cap->rmt_port))) 550 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 551 return (FALSE); 552 } 553 554 /* 555 * only worries about the struct encap_parms part of struct rmtcallargs. 556 * The arglen must already be set!! 557 */ 558 static bool_t 559 xdr_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 560 { 561 562 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 563 } 564 565 /* 566 * This routine finds and sets the length of incoming opaque paraters 567 * and then calls xdr_opaque_parms. 568 */ 569 static bool_t 570 xdr_len_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 571 { 572 u_int beginpos, lowpos, highpos, currpos, pos; 573 574 beginpos = lowpos = pos = xdr_getpos(xdrs); 575 highpos = lowpos + ARGSIZE; 576 while ((int)(highpos - lowpos) >= 0) { 577 currpos = (lowpos + highpos) / 2; 578 if (xdr_setpos(xdrs, currpos)) { 579 pos = currpos; 580 lowpos = currpos + 1; 581 } else { 582 highpos = currpos - 1; 583 } 584 } 585 xdr_setpos(xdrs, beginpos); 586 cap->rmt_args.arglen = pos - beginpos; 587 return (xdr_opaque_parms(xdrs, cap)); 588 } 589 590 /* 591 * Call a remote procedure service 592 * This procedure is very quiet when things go wrong. 593 * The proc is written to support broadcast rpc. In the broadcast case, 594 * a machine should shut-up instead of complain, less the requestor be 595 * overrun with complaints at the expense of not hearing a valid reply ... 596 * 597 * This now forks so that the program & process that it calls can call 598 * back to the portmapper. 599 */ 600 void 601 callit(struct svc_req *rqstp, SVCXPRT *xprt) 602 { 603 struct rmtcallargs a; 604 struct pmaplist *pml; 605 u_short port; 606 struct sockaddr_in me; 607 pid_t pid; 608 int so = -1, dontblock = 1; 609 CLIENT *client; 610 struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred; 611 struct timeval timeout; 612 char buf[ARGSIZE]; 613 614 timeout.tv_sec = 5; 615 timeout.tv_usec = 0; 616 a.rmt_args.args = buf; 617 if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a)) 618 return; 619 if (!check_callit(svc_getcaller(xprt), a.rmt_prog, a.rmt_proc)) 620 return; 621 if ((pml = find_service(a.rmt_prog, a.rmt_vers, 622 (u_long)IPPROTO_UDP)) == NULL) 623 return; 624 625 /* 626 * fork a child to do the work. Parent immediately returns. 627 * Child exits upon completion. 628 */ 629 if ((pid = fork()) != 0) { 630 if (pid == -1) 631 syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m", 632 a.rmt_prog); 633 return; 634 } 635 port = pml->pml_map.pm_port; 636 get_myaddress(&me); 637 me.sin_port = htons(port); 638 639 /* Avoid implicit binding to reserved port by clntudp_create() */ 640 so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 641 if (so == -1) 642 exit(1); 643 if (ioctl(so, FIONBIO, &dontblock) == -1) 644 exit(1); 645 646 client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so); 647 if (client != (CLIENT *)NULL) { 648 if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) 649 client->cl_auth = authunix_create(au->aup_machname, 650 au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); 651 a.rmt_port = (u_long)port; 652 if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, 653 xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) 654 svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); 655 AUTH_DESTROY(client->cl_auth); 656 clnt_destroy(client); 657 } 658 (void)close(so); 659 exit(0); 660 } 661 662 /* ARGSUSED */ 663 void 664 reap(int signo) 665 { 666 int save_errno = errno; 667 668 while (wait3(NULL, WNOHANG, NULL) > 0) 669 ; 670 errno = save_errno; 671 } 672 673 #define NFSPROG ((u_long) 100003) 674 #define MOUNTPROG ((u_long) 100005) 675 #define YPXPROG ((u_long) 100069) 676 #define YPPROG ((u_long) 100004) 677 #define YPPROC_DOMAIN_NONACK ((u_long) 2) 678 #define MOUNTPROC_MNT ((u_long) 1) 679 #define XXXPROC_NOP ((u_long) 0) 680 681 int 682 check_callit(struct sockaddr_in *addr, u_long prog, u_long aproc) 683 { 684 if ((prog == PMAPPROG && aproc != XXXPROC_NOP) || 685 (prog == NFSPROG && aproc != XXXPROC_NOP) || 686 (prog == YPXPROG && aproc != XXXPROC_NOP) || 687 (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) || 688 (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) { 689 syslog(LOG_WARNING, 690 "callit prog %d aproc %d (might be from %s)", 691 (int)prog, (int)aproc, inet_ntoa(addr->sin_addr)); 692 return (FALSE); 693 } 694 return (TRUE); 695 } 696