1 /* $OpenBSD: portmap.c,v 1.36 2006/03/18 00:40:14 dhill 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.36 2006/03/18 00:40:14 dhill 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 pw = getpwnam("_portmap"); 247 if (!pw) 248 pw = getpwnam("nobody"); 249 if (chroot("/var/empty") == -1) { 250 syslog(LOG_ERR, "cannot chdir to /var/empty."); 251 exit(1); 252 } 253 chdir("/"); 254 if (pw) { 255 if (setgroups(1, &pw->pw_gid) == -1 || 256 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 || 257 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { 258 syslog(LOG_ERR, "revoke privs: %s", strerror(errno)); 259 exit(1); 260 } 261 } 262 endpwent(); 263 264 if (svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE) == 0) { 265 syslog(LOG_ERR, "svc_register failed."); 266 exit(1); 267 } 268 269 (void)signal(SIGCHLD, reap); 270 svc_run(); 271 syslog(LOG_ERR, "svc_run returned unexpectedly"); 272 abort(); 273 } 274 275 #ifndef lint 276 /* need to override perror calls in rpc library */ 277 void 278 perror(const char *what) 279 { 280 281 syslog(LOG_ERR, "%s: %m", what); 282 } 283 #endif 284 285 struct pmaplist * 286 find_service(u_long prog, u_long vers, u_long prot) 287 { 288 struct pmaplist *hit = NULL; 289 struct pmaplist *pml; 290 291 for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { 292 if ((pml->pml_map.pm_prog != prog) || 293 (pml->pml_map.pm_prot != prot)) 294 continue; 295 hit = pml; 296 if (pml->pml_map.pm_vers == vers) 297 break; 298 } 299 return (hit); 300 } 301 302 /* 303 * 1 OK, 0 not 304 */ 305 void 306 reg_service(struct svc_req *rqstp, SVCXPRT *xprt) 307 { 308 struct pmap reg; 309 struct pmaplist *pml, *prevpml, *fnd; 310 struct sockaddr_in *fromsin; 311 long ans = 0, port; 312 caddr_t t; 313 314 fromsin = svc_getcaller(xprt); 315 316 if (debugging) 317 (void) fprintf(stderr, "server: about to do a switch\n"); 318 switch (rqstp->rq_proc) { 319 320 case PMAPPROC_NULL: 321 /* 322 * Null proc call 323 */ 324 if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) { 325 abort(); 326 } 327 break; 328 329 case PMAPPROC_SET: 330 /* 331 * Set a program,version to port mapping 332 */ 333 if (xprt != ltcpxprt && xprt != ludpxprt) { 334 syslog(LOG_WARNING, 335 "non-local set attempt (might be from %s)", 336 inet_ntoa(fromsin->sin_addr)); 337 svcerr_noproc(xprt); 338 return; 339 } 340 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 341 svcerr_decode(xprt); 342 break; 343 } 344 345 /* 346 * check to see if already used 347 * find_service returns a hit even if 348 * the versions don't match, so check for it 349 */ 350 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 351 if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) { 352 if (fnd->pml_map.pm_port == reg.pm_port) 353 ans = 1; 354 goto done; 355 } 356 357 if (debugging) 358 printf("set: prog %lu vers %lu port %lu\n", 359 reg.pm_prog, reg.pm_vers, reg.pm_port); 360 361 if (reg.pm_port & ~0xffff) 362 goto done; 363 364 /* 365 * only permit localhost root to create 366 * mappings pointing at sensitive ports 367 */ 368 if ((reg.pm_port < IPPORT_RESERVED || 369 reg.pm_port == NFS_PORT) && 370 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 371 syslog(LOG_WARNING, 372 "resvport set attempt by non-root"); 373 goto done; 374 } 375 376 /* 377 * add to END of list 378 */ 379 pml = (struct pmaplist *)malloc(sizeof(struct pmaplist)); 380 if (pml == NULL) { 381 syslog(LOG_ERR, "out of memory"); 382 svcerr_systemerr(xprt); 383 return; 384 } 385 386 pml->pml_map = reg; 387 pml->pml_next = 0; 388 if (pmaplist == 0) { 389 pmaplist = pml; 390 } else { 391 for (fnd = pmaplist; fnd->pml_next != 0; 392 fnd = fnd->pml_next); 393 fnd->pml_next = pml; 394 } 395 ans = 1; 396 done: 397 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 398 debugging) { 399 (void) fprintf(stderr, "svc_sendreply\n"); 400 abort(); 401 } 402 break; 403 404 case PMAPPROC_UNSET: 405 /* 406 * Remove a program,version to port mapping. 407 */ 408 if (xprt != ltcpxprt && xprt != ludpxprt) { 409 syslog(LOG_WARNING, 410 "non-local unset attempt (might be from %s)", 411 inet_ntoa(fromsin->sin_addr)); 412 svcerr_noproc(xprt); 413 return; 414 } 415 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 416 svcerr_decode(xprt); 417 break; 418 } 419 for (prevpml = NULL, pml = pmaplist; pml != NULL; ) { 420 if ((pml->pml_map.pm_prog != reg.pm_prog) || 421 (pml->pml_map.pm_vers != reg.pm_vers)) { 422 /* both pml & prevpml move forwards */ 423 prevpml = pml; 424 pml = pml->pml_next; 425 continue; 426 } 427 if ((pml->pml_map.pm_port < IPPORT_RESERVED || 428 pml->pml_map.pm_port == NFS_PORT) && 429 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 430 syslog(LOG_WARNING, 431 "resvport unset attempt by non-root"); 432 break; 433 } 434 435 /* found it; pml moves forward, prevpml stays */ 436 ans = 1; 437 t = (caddr_t)pml; 438 pml = pml->pml_next; 439 if (prevpml == NULL) 440 pmaplist = pml; 441 else 442 prevpml->pml_next = pml; 443 free(t); 444 } 445 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 446 debugging) { 447 fprintf(stderr, "svc_sendreply\n"); 448 abort(); 449 } 450 break; 451 452 case PMAPPROC_GETPORT: 453 /* 454 * Lookup the mapping for a program,version and return its port 455 */ 456 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 457 svcerr_decode(xprt); 458 break; 459 } 460 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 461 if (fnd) 462 port = fnd->pml_map.pm_port; 463 else 464 port = 0; 465 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) && 466 debugging) { 467 fprintf(stderr, "svc_sendreply\n"); 468 abort(); 469 } 470 break; 471 472 case PMAPPROC_DUMP: 473 /* 474 * Return the current set of mapped program,version 475 */ 476 if (!svc_getargs(xprt, xdr_void, NULL)) { 477 svcerr_decode(xprt); 478 break; 479 } 480 if (!svc_sendreply(xprt, xdr_pmaplist, (caddr_t)&pmaplist) && 481 debugging) { 482 fprintf(stderr, "svc_sendreply\n"); 483 abort(); 484 } 485 break; 486 487 case PMAPPROC_CALLIT: 488 /* 489 * Calls a procedure on the local machine. If the requested 490 * procedure is not registered this procedure does not return 491 * error information!! 492 * This procedure is only supported on rpc/udp and calls via 493 * rpc/udp. It passes null authentication parameters. 494 */ 495 callit(rqstp, xprt); 496 break; 497 498 default: 499 svcerr_noproc(xprt); 500 break; 501 } 502 } 503 504 505 /* 506 * Stuff for the rmtcall service 507 */ 508 #define ARGSIZE 9000 509 510 struct encap_parms { 511 u_int arglen; 512 char *args; 513 }; 514 515 static bool_t 516 xdr_encap_parms(XDR *xdrs, struct encap_parms *epp) 517 { 518 519 return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE)); 520 } 521 522 struct rmtcallargs { 523 u_long rmt_prog; 524 u_long rmt_vers; 525 u_long rmt_port; 526 u_long rmt_proc; 527 struct encap_parms rmt_args; 528 }; 529 530 static bool_t 531 xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 532 { 533 534 /* does not get a port number */ 535 if (xdr_u_long(xdrs, &(cap->rmt_prog)) && 536 xdr_u_long(xdrs, &(cap->rmt_vers)) && 537 xdr_u_long(xdrs, &(cap->rmt_proc))) { 538 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 539 } 540 return (FALSE); 541 } 542 543 static bool_t 544 xdr_rmtcall_result(XDR *xdrs, struct rmtcallargs *cap) 545 { 546 if (xdr_u_long(xdrs, &(cap->rmt_port))) 547 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 548 return (FALSE); 549 } 550 551 /* 552 * only worries about the struct encap_parms part of struct rmtcallargs. 553 * The arglen must already be set!! 554 */ 555 static bool_t 556 xdr_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 557 { 558 559 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 560 } 561 562 /* 563 * This routine finds and sets the length of incoming opaque paraters 564 * and then calls xdr_opaque_parms. 565 */ 566 static bool_t 567 xdr_len_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 568 { 569 u_int beginpos, lowpos, highpos, currpos, pos; 570 571 beginpos = lowpos = pos = xdr_getpos(xdrs); 572 highpos = lowpos + ARGSIZE; 573 while ((int)(highpos - lowpos) >= 0) { 574 currpos = (lowpos + highpos) / 2; 575 if (xdr_setpos(xdrs, currpos)) { 576 pos = currpos; 577 lowpos = currpos + 1; 578 } else { 579 highpos = currpos - 1; 580 } 581 } 582 xdr_setpos(xdrs, beginpos); 583 cap->rmt_args.arglen = pos - beginpos; 584 return (xdr_opaque_parms(xdrs, cap)); 585 } 586 587 /* 588 * Call a remote procedure service 589 * This procedure is very quiet when things go wrong. 590 * The proc is written to support broadcast rpc. In the broadcast case, 591 * a machine should shut-up instead of complain, less the requestor be 592 * overrun with complaints at the expense of not hearing a valid reply ... 593 * 594 * This now forks so that the program & process that it calls can call 595 * back to the portmapper. 596 */ 597 void 598 callit(struct svc_req *rqstp, SVCXPRT *xprt) 599 { 600 struct rmtcallargs a; 601 struct pmaplist *pml; 602 u_short port; 603 struct sockaddr_in me; 604 pid_t pid; 605 int so = -1, dontblock = 1; 606 CLIENT *client; 607 struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred; 608 struct timeval timeout; 609 char buf[ARGSIZE]; 610 611 timeout.tv_sec = 5; 612 timeout.tv_usec = 0; 613 a.rmt_args.args = buf; 614 if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a)) 615 return; 616 if (!check_callit(svc_getcaller(xprt), a.rmt_prog, a.rmt_proc)) 617 return; 618 if ((pml = find_service(a.rmt_prog, a.rmt_vers, 619 (u_long)IPPROTO_UDP)) == NULL) 620 return; 621 622 /* 623 * fork a child to do the work. Parent immediately returns. 624 * Child exits upon completion. 625 */ 626 if ((pid = fork()) != 0) { 627 if (pid == -1) 628 syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m", 629 a.rmt_prog); 630 return; 631 } 632 port = pml->pml_map.pm_port; 633 get_myaddress(&me); 634 me.sin_port = htons(port); 635 636 /* Avoid implicit binding to reserved port by clntudp_create() */ 637 so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 638 if (so == -1) 639 exit(1); 640 if (ioctl(so, FIONBIO, &dontblock) == -1) 641 exit(1); 642 643 client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so); 644 if (client != (CLIENT *)NULL) { 645 if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) 646 client->cl_auth = authunix_create(au->aup_machname, 647 au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); 648 a.rmt_port = (u_long)port; 649 if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, 650 xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) 651 svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); 652 AUTH_DESTROY(client->cl_auth); 653 clnt_destroy(client); 654 } 655 (void)close(so); 656 exit(0); 657 } 658 659 /* ARGSUSED */ 660 void 661 reap(int signo) 662 { 663 int save_errno = errno; 664 665 while (wait3(NULL, WNOHANG, NULL) > 0) 666 ; 667 errno = save_errno; 668 } 669 670 #define NFSPROG ((u_long) 100003) 671 #define MOUNTPROG ((u_long) 100005) 672 #define YPXPROG ((u_long) 100069) 673 #define YPPROG ((u_long) 100004) 674 #define YPPROC_DOMAIN_NONACK ((u_long) 2) 675 #define MOUNTPROC_MNT ((u_long) 1) 676 #define XXXPROC_NOP ((u_long) 0) 677 678 int 679 check_callit(struct sockaddr_in *addr, u_long prog, u_long aproc) 680 { 681 if ((prog == PMAPPROG && aproc != XXXPROC_NOP) || 682 (prog == NFSPROG && aproc != XXXPROC_NOP) || 683 (prog == YPXPROG && aproc != XXXPROC_NOP) || 684 (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) || 685 (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) { 686 syslog(LOG_WARNING, 687 "callit prog %d aproc %d (might be from %s)", 688 (int)prog, (int)aproc, inet_ntoa(addr->sin_addr)); 689 return (FALSE); 690 } 691 return (TRUE); 692 } 693