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