1 /* $OpenBSD: portmap.c,v 1.29 2003/06/26 19:47:09 deraadt 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.29 2003/06/26 19:47:09 deraadt 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 <rpc/rpc.h> 87 #include <rpc/pmap_prot.h> 88 #include <stdio.h> 89 #include <stdlib.h> 90 #include <string.h> 91 #include <syslog.h> 92 #include <unistd.h> 93 #include <netdb.h> 94 #include <pwd.h> 95 #include <sys/socket.h> 96 #include <sys/ioctl.h> 97 #include <sys/wait.h> 98 #include <sys/signal.h> 99 #include <sys/resource.h> 100 #include <rpcsvc/nfs_prot.h> 101 #include <arpa/inet.h> 102 103 void reg_service(struct svc_req *, SVCXPRT *); 104 void reap(void); 105 void callit(struct svc_req *, SVCXPRT *); 106 int check_callit(struct sockaddr_in *, u_long, u_long, u_long); 107 108 struct pmaplist *pmaplist; 109 int debugging = 0; 110 extern int errno; 111 112 SVCXPRT *ludpxprt, *ltcpxprt; 113 114 int 115 main(int argc, char *argv[]) 116 { 117 int sock, lsock, c, on = 1, len = sizeof(struct sockaddr_in); 118 struct sockaddr_in addr, laddr; 119 struct pmaplist *pml; 120 struct passwd *pw; 121 SVCXPRT *xprt; 122 123 while ((c = getopt(argc, argv, "d")) != -1) { 124 switch (c) { 125 126 case 'd': 127 debugging = 1; 128 break; 129 130 default: 131 (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]); 132 exit(1); 133 } 134 } 135 136 if (!debugging && daemon(0, 0)) { 137 (void) fprintf(stderr, "portmap: fork: %s", strerror(errno)); 138 exit(1); 139 } 140 141 openlog("portmap", LOG_NDELAY | (debugging ? LOG_PID | LOG_PERROR : LOG_PID), 142 LOG_DAEMON); 143 144 bzero((char *)&addr, sizeof addr); 145 addr.sin_addr.s_addr = 0; 146 addr.sin_family = AF_INET; 147 addr.sin_addr.s_addr = htonl(INADDR_ANY); 148 addr.sin_port = htons(PMAPPORT); 149 150 bzero((char *)&laddr, sizeof laddr); 151 laddr.sin_addr.s_addr = 0; 152 laddr.sin_family = AF_INET; 153 laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 154 laddr.sin_port = htons(PMAPPORT); 155 156 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 157 syslog(LOG_ERR, "cannot create udp socket: %m"); 158 exit(1); 159 } 160 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 161 if (bind(sock, (struct sockaddr *)&addr, len) != 0) { 162 syslog(LOG_ERR, "cannot bind udp: %m"); 163 exit(1); 164 } 165 166 if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { 167 syslog(LOG_ERR, "couldn't do udp_create"); 168 exit(1); 169 } 170 171 if ((lsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 172 syslog(LOG_ERR, "cannot create udp socket: %m"); 173 exit(1); 174 } 175 setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 176 if (bind(lsock, (struct sockaddr *)&laddr, len) != 0) { 177 syslog(LOG_ERR, "cannot bind local udp: %m"); 178 exit(1); 179 } 180 181 if ((ludpxprt = svcudp_create(lsock)) == (SVCXPRT *)NULL) { 182 syslog(LOG_ERR, "couldn't do udp_create"); 183 exit(1); 184 } 185 186 /* make an entry for ourself */ 187 pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); 188 if (pml == NULL) { 189 syslog(LOG_ERR, "out of memory"); 190 exit(1); 191 } 192 pml->pml_next = 0; 193 pml->pml_map.pm_prog = PMAPPROG; 194 pml->pml_map.pm_vers = PMAPVERS; 195 pml->pml_map.pm_prot = IPPROTO_UDP; 196 pml->pml_map.pm_port = PMAPPORT; 197 pmaplist = pml; 198 199 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 200 syslog(LOG_ERR, "cannot create tcp socket: %m"); 201 exit(1); 202 } 203 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 204 if (bind(sock, (struct sockaddr *)&addr, len) != 0) { 205 syslog(LOG_ERR, "cannot bind tcp: %m"); 206 exit(1); 207 } 208 if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) 209 == (SVCXPRT *)NULL) { 210 syslog(LOG_ERR, "couldn't do tcp_create"); 211 exit(1); 212 } 213 214 if ((lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 215 syslog(LOG_ERR, "cannot create tcp socket: %m"); 216 exit(1); 217 } 218 setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on); 219 if (bind(lsock, (struct sockaddr *)&laddr, len) != 0) { 220 syslog(LOG_ERR, "cannot bind tcp: %m"); 221 exit(1); 222 } 223 if ((ltcpxprt = svctcp_create(lsock, RPCSMALLMSGSIZE, 224 RPCSMALLMSGSIZE)) == (SVCXPRT *)NULL) { 225 syslog(LOG_ERR, "couldn't do tcp_create"); 226 exit(1); 227 } 228 229 /* make an entry for ourself */ 230 pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); 231 if (pml == NULL) { 232 syslog(LOG_ERR, "out of memory"); 233 exit(1); 234 } 235 pml->pml_map.pm_prog = PMAPPROG; 236 pml->pml_map.pm_vers = PMAPVERS; 237 pml->pml_map.pm_prot = IPPROTO_TCP; 238 pml->pml_map.pm_port = PMAPPORT; 239 pml->pml_next = pmaplist; 240 pmaplist = pml; 241 242 pw = getpwnam("_portmap"); 243 if (!pw) 244 pw = getpwnam("nobody"); 245 if (chroot("/var/empty") == -1) { 246 syslog(LOG_ERR, "cannot chdir to /var/empty."); 247 exit(1); 248 } 249 chdir("/"); 250 if (pw) { 251 setgroups(1, &pw->pw_gid); 252 setegid(pw->pw_gid); 253 setgid(pw->pw_gid); 254 seteuid(pw->pw_uid); 255 setuid(pw->pw_uid); 256 } 257 258 if (svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE) == 0) { 259 syslog(LOG_ERR, "svc_register failed."); 260 exit(1); 261 } 262 263 (void)signal(SIGCHLD, (void (*)(int))reap); 264 svc_run(); 265 syslog(LOG_ERR, "svc_run returned unexpectedly"); 266 abort(); 267 } 268 269 #ifndef lint 270 /* need to override perror calls in rpc library */ 271 void 272 perror(const char *what) 273 { 274 275 syslog(LOG_ERR, "%s: %m", what); 276 } 277 #endif 278 279 struct pmaplist * 280 find_service(u_long prog, u_long vers, u_long prot) 281 { 282 struct pmaplist *hit = NULL; 283 struct pmaplist *pml; 284 285 for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { 286 if ((pml->pml_map.pm_prog != prog) || 287 (pml->pml_map.pm_prot != prot)) 288 continue; 289 hit = pml; 290 if (pml->pml_map.pm_vers == vers) 291 break; 292 } 293 return (hit); 294 } 295 296 /* 297 * 1 OK, 0 not 298 */ 299 void 300 reg_service(struct svc_req *rqstp, SVCXPRT *xprt) 301 { 302 struct pmap reg; 303 struct pmaplist *pml, *prevpml, *fnd; 304 struct sockaddr_in *fromsin; 305 long ans = 0, port; 306 caddr_t t; 307 308 fromsin = svc_getcaller(xprt); 309 310 if (debugging) 311 (void) fprintf(stderr, "server: about to do a switch\n"); 312 switch (rqstp->rq_proc) { 313 314 case PMAPPROC_NULL: 315 /* 316 * Null proc call 317 */ 318 if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) { 319 abort(); 320 } 321 break; 322 323 case PMAPPROC_SET: 324 /* 325 * Set a program,version to port mapping 326 */ 327 if (xprt != ltcpxprt && xprt != ludpxprt) { 328 syslog(LOG_WARNING, 329 "non-local set attempt (might be from %s)", 330 inet_ntoa(fromsin->sin_addr)); 331 svcerr_noproc(xprt); 332 return; 333 } 334 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 335 svcerr_decode(xprt); 336 break; 337 } 338 339 /* 340 * check to see if already used 341 * find_service returns a hit even if 342 * the versions don't match, so check for it 343 */ 344 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 345 if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) { 346 if (fnd->pml_map.pm_port == reg.pm_port) 347 ans = 1; 348 goto done; 349 } 350 351 if (debugging) 352 printf("set: prog %lu vers %lu port %lu\n", 353 reg.pm_prog, reg.pm_vers, reg.pm_port); 354 355 if (reg.pm_port & ~0xffff) 356 goto done; 357 358 /* 359 * only permit localhost root to create 360 * mappings pointing at sensitive ports 361 */ 362 if ((reg.pm_port < IPPORT_RESERVED || 363 reg.pm_port == NFS_PORT) && 364 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 365 syslog(LOG_WARNING, 366 "resvport set attempt by non-root"); 367 goto done; 368 } 369 370 /* 371 * add to END of list 372 */ 373 pml = (struct pmaplist *)malloc(sizeof(struct pmaplist)); 374 if (pml == NULL) { 375 syslog(LOG_ERR, "out of memory"); 376 svcerr_systemerr(xprt); 377 return; 378 } 379 380 pml->pml_map = reg; 381 pml->pml_next = 0; 382 if (pmaplist == 0) { 383 pmaplist = pml; 384 } else { 385 for (fnd = pmaplist; fnd->pml_next != 0; 386 fnd = fnd->pml_next); 387 fnd->pml_next = pml; 388 } 389 ans = 1; 390 done: 391 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 392 debugging) { 393 (void) fprintf(stderr, "svc_sendreply\n"); 394 abort(); 395 } 396 break; 397 398 case PMAPPROC_UNSET: 399 /* 400 * Remove a program,version to port mapping. 401 */ 402 if (xprt != ltcpxprt && xprt != ludpxprt) { 403 syslog(LOG_WARNING, 404 "non-local unset attempt (might be from %s)", 405 inet_ntoa(fromsin->sin_addr)); 406 svcerr_noproc(xprt); 407 return; 408 } 409 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 410 svcerr_decode(xprt); 411 break; 412 } 413 for (prevpml = NULL, pml = pmaplist; pml != NULL; ) { 414 if ((pml->pml_map.pm_prog != reg.pm_prog) || 415 (pml->pml_map.pm_vers != reg.pm_vers)) { 416 /* both pml & prevpml move forwards */ 417 prevpml = pml; 418 pml = pml->pml_next; 419 continue; 420 } 421 if ((pml->pml_map.pm_port < IPPORT_RESERVED || 422 pml->pml_map.pm_port == NFS_PORT) && 423 htons(fromsin->sin_port) >= IPPORT_RESERVED) { 424 syslog(LOG_WARNING, 425 "resvport unset attempt by non-root"); 426 break; 427 } 428 429 /* found it; pml moves forward, prevpml stays */ 430 ans = 1; 431 t = (caddr_t)pml; 432 pml = pml->pml_next; 433 if (prevpml == NULL) 434 pmaplist = pml; 435 else 436 prevpml->pml_next = pml; 437 free(t); 438 } 439 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && 440 debugging) { 441 fprintf(stderr, "svc_sendreply\n"); 442 abort(); 443 } 444 break; 445 446 case PMAPPROC_GETPORT: 447 /* 448 * Lookup the mapping for a program,version and return its port 449 */ 450 if (!svc_getargs(xprt, xdr_pmap, (caddr_t)®)) { 451 svcerr_decode(xprt); 452 break; 453 } 454 fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); 455 if (fnd) 456 port = fnd->pml_map.pm_port; 457 else 458 port = 0; 459 if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) && 460 debugging) { 461 fprintf(stderr, "svc_sendreply\n"); 462 abort(); 463 } 464 break; 465 466 case PMAPPROC_DUMP: 467 /* 468 * Return the current set of mapped program,version 469 */ 470 if (!svc_getargs(xprt, xdr_void, NULL)) { 471 svcerr_decode(xprt); 472 break; 473 } 474 if (!svc_sendreply(xprt, xdr_pmaplist, (caddr_t)&pmaplist) && 475 debugging) { 476 fprintf(stderr, "svc_sendreply\n"); 477 abort(); 478 } 479 break; 480 481 case PMAPPROC_CALLIT: 482 /* 483 * Calls a procedure on the local machine. If the requested 484 * procedure is not registered this procedure does not return 485 * error information!! 486 * This procedure is only supported on rpc/udp and calls via 487 * rpc/udp. It passes null authentication parameters. 488 */ 489 callit(rqstp, xprt); 490 break; 491 492 default: 493 svcerr_noproc(xprt); 494 break; 495 } 496 } 497 498 499 /* 500 * Stuff for the rmtcall service 501 */ 502 #define ARGSIZE 9000 503 504 struct encap_parms { 505 u_int arglen; 506 char *args; 507 }; 508 509 static bool_t 510 xdr_encap_parms(XDR *xdrs, struct encap_parms *epp) 511 { 512 513 return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE)); 514 } 515 516 struct rmtcallargs { 517 u_long rmt_prog; 518 u_long rmt_vers; 519 u_long rmt_port; 520 u_long rmt_proc; 521 struct encap_parms rmt_args; 522 }; 523 524 static bool_t 525 xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) 526 { 527 528 /* does not get a port number */ 529 if (xdr_u_long(xdrs, &(cap->rmt_prog)) && 530 xdr_u_long(xdrs, &(cap->rmt_vers)) && 531 xdr_u_long(xdrs, &(cap->rmt_proc))) { 532 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 533 } 534 return (FALSE); 535 } 536 537 static bool_t 538 xdr_rmtcall_result(XDR *xdrs, struct rmtcallargs *cap) 539 { 540 if (xdr_u_long(xdrs, &(cap->rmt_port))) 541 return (xdr_encap_parms(xdrs, &(cap->rmt_args))); 542 return (FALSE); 543 } 544 545 /* 546 * only worries about the struct encap_parms part of struct rmtcallargs. 547 * The arglen must already be set!! 548 */ 549 static bool_t 550 xdr_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 551 { 552 553 return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); 554 } 555 556 /* 557 * This routine finds and sets the length of incoming opaque paraters 558 * and then calls xdr_opaque_parms. 559 */ 560 static bool_t 561 xdr_len_opaque_parms(XDR *xdrs, struct rmtcallargs *cap) 562 { 563 u_int beginpos, lowpos, highpos, currpos, pos; 564 565 beginpos = lowpos = pos = xdr_getpos(xdrs); 566 highpos = lowpos + ARGSIZE; 567 while ((int)(highpos - lowpos) >= 0) { 568 currpos = (lowpos + highpos) / 2; 569 if (xdr_setpos(xdrs, currpos)) { 570 pos = currpos; 571 lowpos = currpos + 1; 572 } else { 573 highpos = currpos - 1; 574 } 575 } 576 xdr_setpos(xdrs, beginpos); 577 cap->rmt_args.arglen = pos - beginpos; 578 return (xdr_opaque_parms(xdrs, cap)); 579 } 580 581 /* 582 * Call a remote procedure service 583 * This procedure is very quiet when things go wrong. 584 * The proc is written to support broadcast rpc. In the broadcast case, 585 * a machine should shut-up instead of complain, less the requestor be 586 * overrun with complaints at the expense of not hearing a valid reply ... 587 * 588 * This now forks so that the program & process that it calls can call 589 * back to the portmapper. 590 */ 591 void 592 callit(struct svc_req *rqstp, SVCXPRT *xprt) 593 { 594 struct rmtcallargs a; 595 struct pmaplist *pml; 596 u_short port; 597 struct sockaddr_in me; 598 pid_t pid; 599 int so = -1, dontblock = 1; 600 CLIENT *client; 601 struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred; 602 struct timeval timeout; 603 char buf[ARGSIZE]; 604 605 timeout.tv_sec = 5; 606 timeout.tv_usec = 0; 607 a.rmt_args.args = buf; 608 if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a)) 609 return; 610 if (!check_callit(svc_getcaller(xprt), rqstp->rq_proc, 611 a.rmt_prog, a.rmt_proc)) 612 return; 613 if ((pml = find_service(a.rmt_prog, a.rmt_vers, 614 (u_long)IPPROTO_UDP)) == NULL) 615 return; 616 617 /* 618 * fork a child to do the work. Parent immediately returns. 619 * Child exits upon completion. 620 */ 621 if ((pid = fork()) != 0) { 622 if (pid == -1) 623 syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m", 624 a.rmt_prog); 625 return; 626 } 627 port = pml->pml_map.pm_port; 628 get_myaddress(&me); 629 me.sin_port = htons(port); 630 631 /* Avoid implicit binding to reserved port by clntudp_create() */ 632 so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 633 if (so == -1) 634 exit(1); 635 if (ioctl(so, FIONBIO, &dontblock) == -1) 636 exit(1); 637 638 client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so); 639 if (client != (CLIENT *)NULL) { 640 if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) 641 client->cl_auth = authunix_create(au->aup_machname, 642 au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); 643 a.rmt_port = (u_long)port; 644 if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, 645 xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) 646 svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); 647 AUTH_DESTROY(client->cl_auth); 648 clnt_destroy(client); 649 } 650 (void)close(so); 651 exit(0); 652 } 653 654 void 655 reap() 656 { 657 int save_errno = errno; 658 659 while (wait3(NULL, WNOHANG, NULL) > 0) 660 ; 661 errno = save_errno; 662 } 663 664 #define NFSPROG ((u_long) 100003) 665 #define MOUNTPROG ((u_long) 100005) 666 #define YPXPROG ((u_long) 100069) 667 #define YPPROG ((u_long) 100004) 668 #define YPPROC_DOMAIN_NONACK ((u_long) 2) 669 #define MOUNTPROC_MNT ((u_long) 1) 670 #define XXXPROC_NOP ((u_long) 0) 671 672 int 673 check_callit(struct sockaddr_in *addr, u_long proc, u_long prog, 674 u_long aproc) 675 { 676 if ((prog == PMAPPROG && aproc != XXXPROC_NOP) || 677 (prog == NFSPROG && aproc != XXXPROC_NOP) || 678 (prog == YPXPROG && aproc != XXXPROC_NOP) || 679 (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) || 680 (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) { 681 syslog(LOG_WARNING, 682 "callit prog %d aproc %d (might be from %s)", 683 (int)prog, (int)aproc, inet_ntoa(addr->sin_addr)); 684 return (FALSE); 685 } 686 return (TRUE); 687 } 688